1 |
|
---|
2 | /*
|
---|
3 | * bltWinPrnt.c --
|
---|
4 | *
|
---|
5 | * This module implements Win32 printer access.
|
---|
6 | *
|
---|
7 | * Copyright 1998 by Bell Labs Innovations for Lucent Technologies.
|
---|
8 | *
|
---|
9 | * Permission to use, copy, modify, and distribute this software and
|
---|
10 | * its documentation for any purpose and without fee is hereby
|
---|
11 | * granted, provided that the above copyright notice appear in all
|
---|
12 | * copies and that both that the copyright notice and warranty
|
---|
13 | * disclaimer appear in supporting documentation, and that the names
|
---|
14 | * of Lucent Technologies any of their entities not be used in
|
---|
15 | * advertising or publicity pertaining to distribution of the software
|
---|
16 | * without specific, written prior permission.
|
---|
17 | *
|
---|
18 | * Lucent Technologies disclaims all warranties with regard to this
|
---|
19 | * software, including all implied warranties of merchantability and
|
---|
20 | * fitness. In no event shall Lucent Technologies be liable for any
|
---|
21 | * special, indirect or consequential damages or any damages
|
---|
22 | * whatsoever resulting from loss of use, data or profits, whether in
|
---|
23 | * an action of contract, negligence or other tortuous action, arising
|
---|
24 | * out of or in connection with the use or performance of this
|
---|
25 | * software.
|
---|
26 | *
|
---|
27 | */
|
---|
28 |
|
---|
29 | #include <bltInt.h>
|
---|
30 | #include <bltHash.h>
|
---|
31 | #ifndef NO_PRINTER
|
---|
32 | #include <X11/Xutil.h>
|
---|
33 | #undef Status
|
---|
34 | #if defined(_MSC_VER) || defined(__BORLANDC__)
|
---|
35 | #include <winspool.h>
|
---|
36 | #endif /* _MSC_VER || __BORLANDC__ */
|
---|
37 |
|
---|
38 | /*
|
---|
39 | set pid [printer open name]
|
---|
40 | printer close $pid
|
---|
41 | printer write $pid $data
|
---|
42 | printer snap $pid .window
|
---|
43 | printer names
|
---|
44 | printer enum things
|
---|
45 | printer getattr $pid
|
---|
46 | printer setattr $pid
|
---|
47 |
|
---|
48 | set pid [open ]
|
---|
49 | blt::printer open {\\alprint\2a211} p1
|
---|
50 | p1 getattr varName
|
---|
51 | p1 setattr varName
|
---|
52 | p1 write $data
|
---|
53 | .graph print p1
|
---|
54 | p1 snap .window
|
---|
55 | p1 close
|
---|
56 | blt::printer names
|
---|
57 | blt::printer emum things
|
---|
58 | */
|
---|
59 |
|
---|
60 | #define PRINTER_THREAD_KEY "BLT Printer Data"
|
---|
61 |
|
---|
62 | typedef struct {
|
---|
63 | Blt_HashTable printerTable; /* Hash table of printer structures keyed by
|
---|
64 | * the name of the printer. */
|
---|
65 | int nextId;
|
---|
66 | } PrinterInterpData;
|
---|
67 |
|
---|
68 | typedef struct {
|
---|
69 | int type;
|
---|
70 | HDC hDC;
|
---|
71 | } PrintDrawable;
|
---|
72 |
|
---|
73 | typedef struct {
|
---|
74 | Tcl_Interp *interp;
|
---|
75 | Tcl_Command cmdToken; /* Token for vector's Tcl command. */
|
---|
76 | char *name;
|
---|
77 | char *fileName;
|
---|
78 | PrintDrawable drawable;
|
---|
79 | HANDLE hPrinter;
|
---|
80 | Blt_HashEntry *hashPtr;
|
---|
81 | Blt_HashTable *tablePtr;
|
---|
82 | char *driverName;
|
---|
83 | char *deviceName;
|
---|
84 | char *printerName;
|
---|
85 | char *docName;
|
---|
86 | char *portName;
|
---|
87 | DEVMODE *dmPtr;
|
---|
88 | int dmSize;
|
---|
89 | } PrintQueue;
|
---|
90 |
|
---|
91 | typedef struct {
|
---|
92 | DWORD token;
|
---|
93 | char *string;
|
---|
94 | } TokenString;
|
---|
95 |
|
---|
96 | static TokenString sizeTable[] =
|
---|
97 | {
|
---|
98 | /* Letter 8 1/2 x 11 in */
|
---|
99 | { DMPAPER_LETTER, "Letter" },
|
---|
100 | /* Letter Small 8 1/2 x 11 in */
|
---|
101 | { DMPAPER_LETTERSMALL, "Letter Small" },
|
---|
102 | /* Tabloid 11 x 17 in */
|
---|
103 | { DMPAPER_TABLOID, "Tabloid" },
|
---|
104 | /* Ledger 17 x 11 in */
|
---|
105 | { DMPAPER_LEDGER, "Ledger" },
|
---|
106 | /* Legal 8 1/2 x 14 in */
|
---|
107 | { DMPAPER_LEGAL, "Legal" },
|
---|
108 | /* Statement 5 1/2 x 8 1/2 in */
|
---|
109 | { DMPAPER_STATEMENT, "Statement" },
|
---|
110 | /* Executive 7 1/4 x 10 1/2 in */
|
---|
111 | { DMPAPER_EXECUTIVE, "Executive" },
|
---|
112 | /* A3 297 x 420 mm */
|
---|
113 | { DMPAPER_A3, "A3" },
|
---|
114 | /* A4 210 x 297 mm */
|
---|
115 | { DMPAPER_A4, "A4" },
|
---|
116 | /* A4 Small 210 x 297 mm */
|
---|
117 | { DMPAPER_A4SMALL, "A4 Small" },
|
---|
118 | /* A5 148 x 210 mm */
|
---|
119 | { DMPAPER_A5, "A5" },
|
---|
120 | /* B4 (JIS) 250 x 354 */
|
---|
121 | { DMPAPER_B4, "B4 (JIS)" },
|
---|
122 | /* B5 (JIS) 182 x 257 mm */
|
---|
123 | { DMPAPER_B5, "B5 (JIS)" },
|
---|
124 | /* Folio 8 1/2 x 13 in */
|
---|
125 | { DMPAPER_FOLIO, "Folio" },
|
---|
126 | /* Quarto 215 x 275 mm */
|
---|
127 | { DMPAPER_QUARTO, "Quarto" },
|
---|
128 | /* 10x14 in */
|
---|
129 | { DMPAPER_10X14, "10x14" },
|
---|
130 | /* 11x17 in */
|
---|
131 | { DMPAPER_11X17, "11x17" },
|
---|
132 | /* Note 8 1/2 x 11 in */
|
---|
133 | { DMPAPER_NOTE, "Note" },
|
---|
134 | /* Envelope #9 3 7/8 x 8 7/8 */
|
---|
135 | { DMPAPER_ENV_9, "Envelope #9" },
|
---|
136 | /* Envelope #10 4 1/8 x 9 1/2 */
|
---|
137 | { DMPAPER_ENV_10, "Envelope #10" },
|
---|
138 | /* Envelope #11 4 1/2 x 10 3/8 */
|
---|
139 | { DMPAPER_ENV_11, "Envelope #11" },
|
---|
140 | /* Envelope #12 4 \276 x 11 */
|
---|
141 | { DMPAPER_ENV_12, "Envelope #12" },
|
---|
142 | /* Envelope #14 5 x 11 1/2 */
|
---|
143 | { DMPAPER_ENV_14, "Envelope #14" },
|
---|
144 | /* C size sheet */
|
---|
145 | { DMPAPER_CSHEET, "C size sheet" },
|
---|
146 | /* D size sheet */
|
---|
147 | { DMPAPER_DSHEET, "D size sheet" },
|
---|
148 | /* E size sheet */
|
---|
149 | { DMPAPER_ESHEET, "E size sheet" },
|
---|
150 | /* Envelope DL 110 x 220mm */
|
---|
151 | { DMPAPER_ENV_DL, "Envelope DL" },
|
---|
152 | /* Envelope C5 162 x 229 mm */
|
---|
153 | { DMPAPER_ENV_C5, "Envelope C5" },
|
---|
154 | /* Envelope C3 324 x 458 mm */
|
---|
155 | { DMPAPER_ENV_C3, "Envelope C3" },
|
---|
156 | /* Envelope C4 229 x 324 mm */
|
---|
157 | { DMPAPER_ENV_C4, "Envelope C4" },
|
---|
158 | /* Envelope C6 114 x 162 mm */
|
---|
159 | { DMPAPER_ENV_C6, "Envelope C6" },
|
---|
160 | /* Envelope C65 114 x 229 mm */
|
---|
161 | { DMPAPER_ENV_C65, "Envelope C65" },
|
---|
162 | /* Envelope B4 250 x 353 mm */
|
---|
163 | { DMPAPER_ENV_B4, "Envelope B4" },
|
---|
164 | /* Envelope B5 176 x 250 mm */
|
---|
165 | { DMPAPER_ENV_B5, "Envelope B5" },
|
---|
166 | /* Envelope B6 176 x 125 mm */
|
---|
167 | { DMPAPER_ENV_B6, "Envelope B6" },
|
---|
168 | /* Envelope 110 x 230 mm */
|
---|
169 | { DMPAPER_ENV_ITALY, "Envelope Italy" },
|
---|
170 | /* Env Monarch 3 7/8 x 7 1/2 in */
|
---|
171 | { DMPAPER_ENV_MONARCH, "Envelope Monarch" },
|
---|
172 | /* 6 3/4 Envelope 3 5/8 x 6 1/2 in */
|
---|
173 | { DMPAPER_ENV_PERSONAL, "6 3/4 Envelope" },
|
---|
174 | /* US Std Fanfold 14 7/8 x 11 in */
|
---|
175 | { DMPAPER_FANFOLD_US, "US Std Fanfold" },
|
---|
176 | /* German Std Fanfold 8 1/2 x 12 in */
|
---|
177 | { DMPAPER_FANFOLD_STD_GERMAN, "German Std Fanfold" },
|
---|
178 | /* German Legal Fanfold 8 1/2 x 13 in */
|
---|
179 | { DMPAPER_FANFOLD_LGL_GERMAN, "German Legal Fanfold" },
|
---|
180 | /* B4 (ISO) 250 x 353 mm */
|
---|
181 | { DMPAPER_ISO_B4, "ISOB4" },
|
---|
182 | /* Japanese Postcard 100 x 148 mm */
|
---|
183 | { DMPAPER_JAPANESE_POSTCARD, "Postcard (JIS)" },
|
---|
184 | /* 9 x 11 in */
|
---|
185 | { DMPAPER_9X11, "9x11" },
|
---|
186 | /* 10 x 11 in */
|
---|
187 | { DMPAPER_10X11, "10x11" },
|
---|
188 | /* 15 x 11 in */
|
---|
189 | { DMPAPER_15X11, "15x11" },
|
---|
190 | /* Envelope Invite 220 x 220 mm */
|
---|
191 | { DMPAPER_ENV_INVITE, "Envelope Invite" },
|
---|
192 | /* Letter Extra 9 \275 x 12 in */
|
---|
193 | { DMPAPER_LETTER_EXTRA, "Letter Extra" },
|
---|
194 | /* Legal Extra 9 \275 x 15 in */
|
---|
195 | { DMPAPER_LEGAL_EXTRA, "Legal Extra" },
|
---|
196 | /* Tabloid Extra 11.69 x 18 in */
|
---|
197 | { DMPAPER_TABLOID_EXTRA, "Tabloid Extra" },
|
---|
198 | /* A4 Extra 9.27 x 12.69 in */
|
---|
199 | { DMPAPER_A4_EXTRA, "A4 Extra" },
|
---|
200 | /* Letter Transverse 8 \275 x 11 in */
|
---|
201 | { DMPAPER_LETTER_TRANSVERSE, "Letter Transverse" },
|
---|
202 | /* A4 Transverse 210 x 297 mm */
|
---|
203 | { DMPAPER_A4_TRANSVERSE, "A4 Transverse" },
|
---|
204 | /* Letter Extra Transverse 9\275 x 12 in */
|
---|
205 | { DMPAPER_LETTER_EXTRA_TRANSVERSE, "Letter Extra Transverse" },
|
---|
206 | /* SuperA/SuperA/A4 227 x 356 mm */
|
---|
207 | { DMPAPER_A_PLUS, "Super A Plus" },
|
---|
208 | /* SuperB/SuperB/A3 305 x 487 mm */
|
---|
209 | { DMPAPER_B_PLUS, "Super B Plus" },
|
---|
210 | /* Letter Plus 8.5 x 12.69 in */
|
---|
211 | { DMPAPER_LETTER_PLUS, "Letter Plus" },
|
---|
212 | /* A4 Plus 210 x 330 mm */
|
---|
213 | { DMPAPER_A4_PLUS, "A4 Plus" },
|
---|
214 | /* A5 Transverse 148 x 210 mm */
|
---|
215 | { DMPAPER_A5_TRANSVERSE, "A5 Transverse" },
|
---|
216 | /* B5 (JIS) Transverse 182 x 257 mm */
|
---|
217 | { DMPAPER_B5_TRANSVERSE, "B5 Transverse" },
|
---|
218 | /* A3 Extra 322 x 445 mm */
|
---|
219 | { DMPAPER_A3_EXTRA, "A3 Extra" },
|
---|
220 | /* A5 Extra 174 x 235 mm */
|
---|
221 | { DMPAPER_A5_EXTRA, "A5 Extra" },
|
---|
222 | /* B5 (ISO) Extra 201 x 276 mm */
|
---|
223 | { DMPAPER_B5_EXTRA, "B5 Extra" },
|
---|
224 | /* A2 420 x 594 mm */
|
---|
225 | { DMPAPER_A2, "A2" },
|
---|
226 | /* A3 Transverse 297 x 420 mm */
|
---|
227 | { DMPAPER_A3_TRANSVERSE, "A3 Transverse" },
|
---|
228 | /* A3 Extra Transverse 322 x 445 mm */
|
---|
229 | { DMPAPER_A3_EXTRA_TRANSVERSE, "A3 Extra Transverse" },
|
---|
230 | { 0, NULL }
|
---|
231 | };
|
---|
232 |
|
---|
233 | static TokenString statusTable[] =
|
---|
234 | {
|
---|
235 | { PRINTER_STATUS_BUSY, "Busy" },
|
---|
236 | { PRINTER_STATUS_DOOR_OPEN, "Door Open" },
|
---|
237 | { PRINTER_STATUS_ERROR, "Error" },
|
---|
238 | { PRINTER_STATUS_INITIALIZING, "Initializing" },
|
---|
239 | { PRINTER_STATUS_IO_ACTIVE, "IO Active" },
|
---|
240 | { PRINTER_STATUS_MANUAL_FEED, "Manual Feed" },
|
---|
241 | { PRINTER_STATUS_NOT_AVAILABLE, "Not Available" },
|
---|
242 | { PRINTER_STATUS_NO_TONER, "No Toner" },
|
---|
243 | { PRINTER_STATUS_OFFLINE, "Offline" },
|
---|
244 | { PRINTER_STATUS_OUTPUT_BIN_FULL, "Bin Full" },
|
---|
245 | { PRINTER_STATUS_OUT_OF_MEMORY, "Out Of Memory" },
|
---|
246 | { PRINTER_STATUS_PAGE_PUNT, "Page Punt" },
|
---|
247 | { PRINTER_STATUS_PAPER_JAM, "Paper Jam" },
|
---|
248 | { PRINTER_STATUS_PAPER_OUT, "Paper Out" },
|
---|
249 | { PRINTER_STATUS_PAPER_PROBLEM, "Paper Problem" },
|
---|
250 | { PRINTER_STATUS_PAUSED, "Paused" },
|
---|
251 | { PRINTER_STATUS_PENDING_DELETION, "Pending Deletion" },
|
---|
252 | { PRINTER_STATUS_POWER_SAVE, "Power Save" },
|
---|
253 | { PRINTER_STATUS_PRINTING, "Printing" },
|
---|
254 | { PRINTER_STATUS_PROCESSING, "Processing" },
|
---|
255 | { PRINTER_STATUS_SERVER_UNKNOWN, "Server Unknown" },
|
---|
256 | { PRINTER_STATUS_TONER_LOW, "Toner Low" },
|
---|
257 | { PRINTER_STATUS_USER_INTERVENTION, "User Intervention" },
|
---|
258 | { PRINTER_STATUS_WAITING, "Waiting" },
|
---|
259 | { PRINTER_STATUS_WARMING_UP, "Warming Up" },
|
---|
260 | { 0, NULL }
|
---|
261 | };
|
---|
262 |
|
---|
263 | static TokenString attributeTable[] =
|
---|
264 | {
|
---|
265 | { PRINTER_ATTRIBUTE_DEFAULT, "Default" },
|
---|
266 | { PRINTER_ATTRIBUTE_DIRECT, "Direct" },
|
---|
267 | { PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST, "Do Complete First" },
|
---|
268 | { PRINTER_ATTRIBUTE_ENABLE_BIDI, "Enable BIDI" },
|
---|
269 | { PRINTER_ATTRIBUTE_ENABLE_DEVQ, "Enable Devq" },
|
---|
270 | { PRINTER_ATTRIBUTE_HIDDEN, "Hidden" },
|
---|
271 | { PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS, "Keep Printed Jobs" },
|
---|
272 | { PRINTER_ATTRIBUTE_LOCAL, "Local" },
|
---|
273 | { PRINTER_ATTRIBUTE_NETWORK, "Network" },
|
---|
274 | { PRINTER_ATTRIBUTE_QUEUED, "Queued" },
|
---|
275 | { PRINTER_ATTRIBUTE_RAW_ONLY, "Raw Only" },
|
---|
276 | { PRINTER_ATTRIBUTE_SHARED, "Shared" },
|
---|
277 | { PRINTER_ATTRIBUTE_WORK_OFFLINE, "Offline" },
|
---|
278 | { 0, NULL }
|
---|
279 | };
|
---|
280 |
|
---|
281 | static TokenString binTable[] =
|
---|
282 | {
|
---|
283 | { DMBIN_UPPER, "Upper" },
|
---|
284 | { DMBIN_LOWER, "Lower" },
|
---|
285 | { DMBIN_MIDDLE, "Middle" },
|
---|
286 | { DMBIN_MANUAL, "Manual" },
|
---|
287 | { DMBIN_ENVELOPE, "Envelope" },
|
---|
288 | { DMBIN_ENVMANUAL, "Envelope Manual" },
|
---|
289 | { DMBIN_AUTO, "Automatic" },
|
---|
290 | { DMBIN_TRACTOR, "Tractor" },
|
---|
291 | { DMBIN_SMALLFMT, "Small Format" },
|
---|
292 | { DMBIN_LARGEFMT, "Large Format" },
|
---|
293 | { DMBIN_LARGECAPACITY, "Large Capacity" },
|
---|
294 | { DMBIN_CASSETTE, "Cassette" },
|
---|
295 | { DMBIN_FORMSOURCE, "Form Source" },
|
---|
296 | { 0, NULL }
|
---|
297 | };
|
---|
298 |
|
---|
299 | static TokenString orientationTable[] =
|
---|
300 | {
|
---|
301 | { DMORIENT_PORTRAIT, "Portrait" },
|
---|
302 | { DMORIENT_LANDSCAPE, "Landscape" },
|
---|
303 | { 0, NULL }
|
---|
304 | };
|
---|
305 |
|
---|
306 | static TokenString qualityTable[] =
|
---|
307 | {
|
---|
308 | { DMRES_HIGH, "High" },
|
---|
309 | { DMRES_MEDIUM, "Medium" },
|
---|
310 | { DMRES_LOW, "Low" },
|
---|
311 | { DMRES_DRAFT, "Draft" },
|
---|
312 | { 0, NULL }
|
---|
313 | };
|
---|
314 |
|
---|
315 | static TokenString colorTable[] =
|
---|
316 | {
|
---|
317 | { DMCOLOR_COLOR, "Color" },
|
---|
318 | { DMCOLOR_MONOCHROME, "Monochrome" },
|
---|
319 | { 0, NULL }
|
---|
320 | };
|
---|
321 |
|
---|
322 | static TokenString duplexTable[] =
|
---|
323 | {
|
---|
324 | { DMDUP_SIMPLEX, "Simplex" },
|
---|
325 | { DMDUP_HORIZONTAL, "Horizontal" },
|
---|
326 | { DMDUP_VERTICAL, "Vertical" },
|
---|
327 | { 0, NULL }
|
---|
328 | };
|
---|
329 |
|
---|
330 | static TokenString ttOptionTable[] =
|
---|
331 | {
|
---|
332 | { DMTT_BITMAP, "Bitmap" },
|
---|
333 | { DMTT_DOWNLOAD, "Download" },
|
---|
334 | { DMTT_SUBDEV, "Substitute Device" },
|
---|
335 | { DMTT_DOWNLOAD_OUTLINE, "Download Outline" },
|
---|
336 | { 0, NULL }
|
---|
337 | };
|
---|
338 |
|
---|
339 | static Tcl_ObjCmdProc PrinterCmd;
|
---|
340 | static Tcl_InterpDeleteProc PrinterInterpDeleteProc;
|
---|
341 |
|
---|
342 | void
|
---|
343 | Blt_GetPrinterScale(HDC printerDC, double *xRatioPtr, double *yRatioPtr)
|
---|
344 | {
|
---|
345 | double xScreen, yScreen;
|
---|
346 | double xPrinter, yPrinter;
|
---|
347 | HDC screenDC;
|
---|
348 |
|
---|
349 | xPrinter = (double)GetDeviceCaps(printerDC, LOGPIXELSX);
|
---|
350 | yPrinter = (double)GetDeviceCaps(printerDC, LOGPIXELSY);
|
---|
351 | screenDC = GetDC(NULL);
|
---|
352 | xScreen = (double)GetDeviceCaps(screenDC, LOGPIXELSX);
|
---|
353 | yScreen = (double)GetDeviceCaps(screenDC, LOGPIXELSY);
|
---|
354 | ReleaseDC(NULL, screenDC);
|
---|
355 | *xRatioPtr = (xPrinter / xScreen);
|
---|
356 | *yRatioPtr = (yPrinter / yScreen);
|
---|
357 | }
|
---|
358 |
|
---|
359 | static PrinterInterpData *
|
---|
360 | GetPrinterInterpData(Tcl_Interp *interp)
|
---|
361 | {
|
---|
362 | PrinterInterpData *dataPtr;
|
---|
363 | Tcl_InterpDeleteProc *proc;
|
---|
364 |
|
---|
365 | dataPtr = (PrinterInterpData *)
|
---|
366 | Tcl_GetAssocData(interp, PRINTER_THREAD_KEY, &proc);
|
---|
367 | if (dataPtr == NULL) {
|
---|
368 | dataPtr = Blt_Malloc(sizeof(PrinterInterpData));
|
---|
369 | dataPtr->nextId = 0;
|
---|
370 | assert(dataPtr);
|
---|
371 | Tcl_SetAssocData(interp, PRINTER_THREAD_KEY, PrinterInterpDeleteProc,
|
---|
372 | dataPtr);
|
---|
373 | Blt_InitHashTable(&dataPtr->printerTable, BLT_STRING_KEYS);
|
---|
374 | }
|
---|
375 | return dataPtr;
|
---|
376 | }
|
---|
377 |
|
---|
378 | static int
|
---|
379 | GetQueue(
|
---|
380 | Tcl_Interp *interp,
|
---|
381 | const char *name,
|
---|
382 | PrintQueue **queuePtrPtr)
|
---|
383 | {
|
---|
384 | Blt_HashEntry *hPtr;
|
---|
385 | PrinterInterpData *dataPtr;
|
---|
386 |
|
---|
387 | dataPtr = GetPrinterInterpData(interp);
|
---|
388 | hPtr = Blt_FindHashEntry(&dataPtr->printerTable, name);
|
---|
389 | if (hPtr == NULL) {
|
---|
390 | Tcl_AppendResult(interp, "can't find printer \"", name, "\"",
|
---|
391 | (char *)NULL);
|
---|
392 | return TCL_ERROR;
|
---|
393 | }
|
---|
394 | *queuePtrPtr = (PrintQueue *)Blt_GetHashValue(hPtr);
|
---|
395 | return TCL_OK;
|
---|
396 | }
|
---|
397 |
|
---|
398 | static int
|
---|
399 | GetQueueFromObj(
|
---|
400 | Tcl_Interp *interp,
|
---|
401 | Tcl_Obj *objPtr,
|
---|
402 | PrintQueue **queuePtrPtr)
|
---|
403 | {
|
---|
404 | return GetQueue(interp, Tcl_GetString(objPtr), queuePtrPtr);
|
---|
405 | }
|
---|
406 |
|
---|
407 | static void
|
---|
408 | CloseQueue(
|
---|
409 | PrintQueue *queuePtr)
|
---|
410 | {
|
---|
411 | ClosePrinter(queuePtr->hPrinter);
|
---|
412 | queuePtr->hPrinter = NULL;
|
---|
413 | }
|
---|
414 |
|
---|
415 | static int
|
---|
416 | OpenQueue(
|
---|
417 | Tcl_Interp *interp,
|
---|
418 | PrintQueue *queuePtr)
|
---|
419 | {
|
---|
420 | PRINTER_DEFAULTS pd;
|
---|
421 | HANDLE hPrinter;
|
---|
422 |
|
---|
423 | ZeroMemory(&pd, sizeof(pd));
|
---|
424 | pd.DesiredAccess = PRINTER_ALL_ACCESS;
|
---|
425 | if (!OpenPrinter(queuePtr->printerName, &hPrinter, &pd)) {
|
---|
426 | Tcl_AppendResult(interp, "can't open printer \"",
|
---|
427 | queuePtr->printerName, "\": ", Blt_LastError(), (char *)NULL);
|
---|
428 | queuePtr->hPrinter = NULL;
|
---|
429 | return TCL_ERROR;
|
---|
430 | }
|
---|
431 | queuePtr->hPrinter = hPrinter;
|
---|
432 | return TCL_OK;
|
---|
433 | }
|
---|
434 |
|
---|
435 | static HGLOBAL
|
---|
436 | GetQueueProperties(
|
---|
437 | PrintQueue *queuePtr,
|
---|
438 | DEVMODE **dmPtrPtr)
|
---|
439 | {
|
---|
440 | HWND hWnd;
|
---|
441 | unsigned int dmSize;
|
---|
442 | HGLOBAL hMem;
|
---|
443 | DEVMODE *dmPtr;
|
---|
444 |
|
---|
445 | hWnd = GetDesktopWindow();
|
---|
446 | dmSize = DocumentProperties(hWnd, queuePtr->hPrinter,
|
---|
447 | queuePtr->printerName, NULL, NULL, 0);
|
---|
448 | if (dmSize == 0) {
|
---|
449 | Tcl_AppendResult(queuePtr->interp,
|
---|
450 | "can't get document properties for \"",
|
---|
451 | queuePtr->printerName,
|
---|
452 | "\": ", Blt_LastError(), (char *)NULL);
|
---|
453 | return NULL;
|
---|
454 | }
|
---|
455 | hMem = GlobalAlloc(GHND, dmSize);
|
---|
456 | dmPtr = (DEVMODE *)GlobalLock(hMem);
|
---|
457 | if (!DocumentProperties(hWnd, queuePtr->hPrinter, queuePtr->printerName,
|
---|
458 | dmPtr, NULL, DM_OUT_BUFFER)) {
|
---|
459 | Tcl_AppendResult(queuePtr->interp,
|
---|
460 | "can't allocate document properties for \"",
|
---|
461 | queuePtr->printerName, "\": ", Blt_LastError(),
|
---|
462 | (char *)NULL);
|
---|
463 | GlobalUnlock(hMem);
|
---|
464 | GlobalFree(hMem);
|
---|
465 | return NULL;
|
---|
466 | }
|
---|
467 | *dmPtrPtr = dmPtr;
|
---|
468 | queuePtr->dmSize = dmSize;
|
---|
469 | return hMem;
|
---|
470 | }
|
---|
471 |
|
---|
472 | static int
|
---|
473 | SetQueueProperties(
|
---|
474 | Tcl_Interp *interp,
|
---|
475 | PrintQueue *queuePtr,
|
---|
476 | DEVMODE *dmPtr)
|
---|
477 | {
|
---|
478 | HWND hWnd;
|
---|
479 | int result;
|
---|
480 |
|
---|
481 | hWnd = GetDesktopWindow();
|
---|
482 | result = DocumentProperties(hWnd, queuePtr->hPrinter,
|
---|
483 | queuePtr->printerName, dmPtr, dmPtr, DM_IN_BUFFER | DM_OUT_BUFFER);
|
---|
484 | if (result == 0) {
|
---|
485 | Tcl_AppendResult(interp, "can't set document properties for \"",
|
---|
486 | queuePtr->printerName, "\": ", Blt_LastError(), (char *)NULL);
|
---|
487 | return TCL_ERROR;
|
---|
488 | }
|
---|
489 | if (queuePtr->dmPtr != NULL) {
|
---|
490 | Blt_Free(queuePtr->dmPtr);
|
---|
491 | }
|
---|
492 | queuePtr->dmPtr = Blt_Malloc(queuePtr->dmSize);
|
---|
493 | *queuePtr->dmPtr = *dmPtr;
|
---|
494 | return TCL_OK;
|
---|
495 | }
|
---|
496 |
|
---|
497 | static void
|
---|
498 | DestroyQueue(PrintQueue *queuePtr)
|
---|
499 | {
|
---|
500 | if (queuePtr->drawable.hDC != NULL) {
|
---|
501 | DeleteDC(queuePtr->drawable.hDC);
|
---|
502 | }
|
---|
503 | if (queuePtr->printerName != NULL) {
|
---|
504 | Blt_Free(queuePtr->printerName);
|
---|
505 | }
|
---|
506 | if (queuePtr->deviceName != NULL) {
|
---|
507 | Blt_Free(queuePtr->deviceName);
|
---|
508 | }
|
---|
509 | if (queuePtr->portName != NULL) {
|
---|
510 | Blt_Free(queuePtr->portName);
|
---|
511 | }
|
---|
512 | if (queuePtr->driverName != NULL) {
|
---|
513 | Blt_Free(queuePtr->driverName);
|
---|
514 | }
|
---|
515 | if (queuePtr->hashPtr != NULL) {
|
---|
516 | Blt_DeleteHashEntry(queuePtr->tablePtr, queuePtr->hashPtr);
|
---|
517 | }
|
---|
518 | if (queuePtr->dmPtr != NULL) {
|
---|
519 | Blt_Free(queuePtr->dmPtr);
|
---|
520 | }
|
---|
521 | Blt_Free(queuePtr);
|
---|
522 | }
|
---|
523 |
|
---|
524 | static char *
|
---|
525 | AttributesToString(DWORD attributes, Tcl_DString * resultPtr)
|
---|
526 | {
|
---|
527 | register TokenString *p;
|
---|
528 |
|
---|
529 | Tcl_DStringInit(resultPtr);
|
---|
530 | for (p = attributeTable; p->string != NULL; p++) {
|
---|
531 | if (attributes & p->token) {
|
---|
532 | Tcl_DStringAppendElement(resultPtr, p->string);
|
---|
533 | }
|
---|
534 | }
|
---|
535 | return Tcl_DStringValue(resultPtr);
|
---|
536 | }
|
---|
537 |
|
---|
538 | static char *
|
---|
539 | StatusToString(DWORD status, Tcl_DString * resultPtr)
|
---|
540 | {
|
---|
541 | register TokenString *p;
|
---|
542 |
|
---|
543 | Tcl_DStringInit(resultPtr);
|
---|
544 | for (p = statusTable; p->string != NULL; p++) {
|
---|
545 | if (status & p->token) {
|
---|
546 | Tcl_DStringAppendElement(resultPtr, p->string);
|
---|
547 | }
|
---|
548 | }
|
---|
549 | return Tcl_DStringValue(resultPtr);
|
---|
550 | }
|
---|
551 |
|
---|
552 | static char *
|
---|
553 | TokenToString(TokenString *table, DWORD token)
|
---|
554 | {
|
---|
555 | register TokenString *p;
|
---|
556 |
|
---|
557 | for (p = table; p->string != NULL; p++) {
|
---|
558 | if (token == p->token) {
|
---|
559 | return p->string;
|
---|
560 | }
|
---|
561 | }
|
---|
562 | return "???";
|
---|
563 | }
|
---|
564 |
|
---|
565 | static DWORD
|
---|
566 | StringToToken(TokenString * table, char *string)
|
---|
567 | {
|
---|
568 | register TokenString *p;
|
---|
569 | char c;
|
---|
570 |
|
---|
571 | c = toupper(string[0]);
|
---|
572 | for (p = table; p->string != NULL; p++) {
|
---|
573 | if ((c == toupper(p->string[0])) &&
|
---|
574 | (strcasecmp(string, p->string) == 0)) {
|
---|
575 | return p->token;
|
---|
576 | }
|
---|
577 | }
|
---|
578 | return 0;
|
---|
579 | }
|
---|
580 |
|
---|
581 | static void
|
---|
582 | GetFormInfo(
|
---|
583 | Tcl_Interp *interp,
|
---|
584 | FORM_INFO_1 * infoArr,
|
---|
585 | int nForms,
|
---|
586 | char *varName)
|
---|
587 | {
|
---|
588 | Tcl_DString dString;
|
---|
589 | register int i;
|
---|
590 |
|
---|
591 | Tcl_DStringInit(&dString);
|
---|
592 | for (i = 0; i < nForms; i++) {
|
---|
593 | Tcl_DStringAppendElement(&dString, infoArr[i].pName);
|
---|
594 | }
|
---|
595 | Tcl_SetVar2(interp, varName, "EnumForms", Tcl_DStringValue(&dString),
|
---|
596 | TCL_LEAVE_ERR_MSG);
|
---|
597 | Tcl_DStringFree(&dString);
|
---|
598 | }
|
---|
599 |
|
---|
600 |
|
---|
601 | static int
|
---|
602 | GetPrinterAttributes(
|
---|
603 | Tcl_Interp *interp, /* Interpreter context. */
|
---|
604 | PrintQueue *queuePtr,
|
---|
605 | Tcl_Obj *objPtr) /* Name of array variable to contain
|
---|
606 | * printer device information. */
|
---|
607 | {
|
---|
608 | char *string;
|
---|
609 | Tcl_DString dString;
|
---|
610 | DEVMODE *dmPtr;
|
---|
611 | DWORD bytesNeeded;
|
---|
612 | HGLOBAL hMem1, hMem2;
|
---|
613 | PRINTER_INFO_2* pi2Ptr;
|
---|
614 | LPVOID buffer;
|
---|
615 | int result = TCL_ERROR;
|
---|
616 | char *varName;
|
---|
617 |
|
---|
618 | if (OpenQueue(interp, queuePtr) != TCL_OK) {
|
---|
619 | return TCL_ERROR;
|
---|
620 | }
|
---|
621 | Tcl_DStringInit(&dString);
|
---|
622 | hMem2 = NULL;
|
---|
623 |
|
---|
624 | GetPrinter(queuePtr->hPrinter, 2, NULL, 0, &bytesNeeded);
|
---|
625 |
|
---|
626 | /* Windows 95/98 seems to only want locked memory. Allocating
|
---|
627 | * unlocked memory will sometimes crash the printer driver and
|
---|
628 | * therefore Windows itself. */
|
---|
629 |
|
---|
630 | hMem1 = GlobalAlloc(GHND, bytesNeeded);
|
---|
631 | if (hMem1 == NULL) {
|
---|
632 | Tcl_AppendResult(interp, "can't allocate memory for printer \"",
|
---|
633 | queuePtr->name, "\": ", Blt_LastError(), (char *)NULL);
|
---|
634 | goto error;
|
---|
635 | }
|
---|
636 | buffer = (LPVOID)GlobalLock(hMem1);
|
---|
637 | if (!GetPrinter(queuePtr->hPrinter, 2, buffer, bytesNeeded,
|
---|
638 | &bytesNeeded)) {
|
---|
639 | Tcl_AppendResult(interp, "can't get printer \"", queuePtr->name, "\": ",
|
---|
640 | Blt_LastError(), (char *)NULL);
|
---|
641 | goto error;
|
---|
642 | }
|
---|
643 | hMem2 = GetQueueProperties(queuePtr, &dmPtr);
|
---|
644 | if (hMem2 == NULL) {
|
---|
645 | Tcl_AppendResult(interp, "can't allocate memory for printer \"",
|
---|
646 | queuePtr->name, "\" properties: ", Blt_LastError(), (char *)NULL);
|
---|
647 | goto error;
|
---|
648 | }
|
---|
649 | pi2Ptr = (PRINTER_INFO_2 *)buffer;
|
---|
650 | varName = Tcl_GetString(objPtr);
|
---|
651 | Tcl_SetVar2(interp, varName, "ServerName", pi2Ptr->pServerName, 0);
|
---|
652 | Tcl_SetVar2(interp, varName, "PrinterName", pi2Ptr->pPrinterName, 0);
|
---|
653 | Tcl_SetVar2(interp, varName, "PortName", pi2Ptr->pPortName, 0);
|
---|
654 | Tcl_SetVar2(interp, varName, "DriverName", pi2Ptr->pDriverName, 0);
|
---|
655 | Tcl_SetVar2(interp, varName, "Comment", pi2Ptr->pComment, 0);
|
---|
656 | Tcl_SetVar2(interp, varName, "Location", pi2Ptr->pLocation, 0);
|
---|
657 | Tcl_SetVar2(interp, varName, "SepFile", pi2Ptr->pSepFile, 0);
|
---|
658 | Tcl_SetVar2(interp, varName, "PrintProcessor", pi2Ptr->pPrintProcessor, 0);
|
---|
659 | Tcl_SetVar2(interp, varName, "Datatype", pi2Ptr->pDatatype, 0);
|
---|
660 | Tcl_SetVar2(interp, varName, "Parameters", pi2Ptr->pParameters, 0);
|
---|
661 | Tcl_SetVar2(interp, varName, "Attributes",
|
---|
662 | AttributesToString(pi2Ptr->Attributes, &dString), 0);
|
---|
663 | Tcl_SetVar2(interp, varName, "Priority", Blt_Itoa(pi2Ptr->Priority), 0);
|
---|
664 | Tcl_SetVar2(interp, varName, "DefaultPriority",
|
---|
665 | Blt_Itoa(pi2Ptr->DefaultPriority), 0);
|
---|
666 | Tcl_SetVar2(interp, varName, "StartTime", Blt_Itoa(pi2Ptr->StartTime), 0);
|
---|
667 | Tcl_SetVar2(interp, varName, "UntilTime", Blt_Itoa(pi2Ptr->UntilTime), 0);
|
---|
668 | Tcl_SetVar2(interp, varName, "Status",
|
---|
669 | StatusToString(pi2Ptr->Status, &dString), 0);
|
---|
670 | Tcl_SetVar2(interp, varName, "Jobs", Blt_Itoa(pi2Ptr->cJobs), 0);
|
---|
671 | Tcl_SetVar2(interp, varName, "AveragePPM", Blt_Itoa(pi2Ptr->AveragePPM), 0);
|
---|
672 |
|
---|
673 | if (dmPtr->dmFields & DM_ORIENTATION) {
|
---|
674 | Tcl_SetVar2(interp, varName, "Orientation",
|
---|
675 | TokenToString(orientationTable, dmPtr->dmOrientation), 0);
|
---|
676 | }
|
---|
677 | if (dmPtr->dmFields & DM_PAPERSIZE) {
|
---|
678 | Tcl_SetVar2(interp, varName, "PaperSize",
|
---|
679 | TokenToString(sizeTable, dmPtr->dmPaperSize), 0);
|
---|
680 | }
|
---|
681 | if (dmPtr->dmFields & DM_PAPERWIDTH) {
|
---|
682 | Tcl_SetVar2(interp, varName, "PaperWidth",
|
---|
683 | Blt_Itoa(dmPtr->dmPaperWidth), 0);
|
---|
684 | }
|
---|
685 | if (dmPtr->dmFields & DM_PAPERLENGTH) {
|
---|
686 | Tcl_SetVar2(interp, varName, "PaperLength",
|
---|
687 | Blt_Itoa(dmPtr->dmPaperLength), 0);
|
---|
688 | }
|
---|
689 | if (dmPtr->dmFields & DM_SCALE) {
|
---|
690 | Tcl_SetVar2(interp, varName, "Scale", Blt_Itoa(dmPtr->dmScale), 0);
|
---|
691 | }
|
---|
692 | if (dmPtr->dmFields & DM_COPIES) {
|
---|
693 | Tcl_SetVar2(interp, varName, "Copies", Blt_Itoa(dmPtr->dmCopies), 0);
|
---|
694 | }
|
---|
695 | if (dmPtr->dmFields & DM_DEFAULTSOURCE) {
|
---|
696 | Tcl_SetVar2(interp, varName, "DefaultSource",
|
---|
697 | TokenToString(binTable, dmPtr->dmDefaultSource), 0);
|
---|
698 | }
|
---|
699 | if (dmPtr->dmFields & DM_PRINTQUALITY) {
|
---|
700 | if (dmPtr->dmPrintQuality < 0) {
|
---|
701 | string = TokenToString(qualityTable, dmPtr->dmPrintQuality);
|
---|
702 | } else {
|
---|
703 | string = Blt_Itoa(dmPtr->dmPrintQuality);
|
---|
704 | }
|
---|
705 | Tcl_SetVar2(interp, varName, "PrintQuality", string, 0);
|
---|
706 | }
|
---|
707 | if (dmPtr->dmFields & DM_COLOR) {
|
---|
708 | Tcl_SetVar2(interp, varName, "Color",
|
---|
709 | TokenToString(colorTable, dmPtr->dmColor), 0);
|
---|
710 | }
|
---|
711 | if (dmPtr->dmFields & DM_DUPLEX) {
|
---|
712 | Tcl_SetVar2(interp, varName, "Duplex",
|
---|
713 | TokenToString(duplexTable, dmPtr->dmDuplex), 0);
|
---|
714 | }
|
---|
715 | if (dmPtr->dmFields & DM_YRESOLUTION) {
|
---|
716 | Tcl_SetVar2(interp, varName, "YResolution",
|
---|
717 | Blt_Itoa(dmPtr->dmYResolution), 0);
|
---|
718 | }
|
---|
719 | if (dmPtr->dmFields & DM_TTOPTION) {
|
---|
720 | Tcl_SetVar2(interp, varName, "TTOption",
|
---|
721 | TokenToString(ttOptionTable, dmPtr->dmTTOption), 0);
|
---|
722 | }
|
---|
723 | if (dmPtr->dmFields & DM_COLLATE) {
|
---|
724 | if (dmPtr->dmCollate == DMCOLLATE_TRUE) {
|
---|
725 | string = "true";
|
---|
726 | } else if (dmPtr->dmCollate == DMCOLLATE_FALSE) {
|
---|
727 | string = "false";
|
---|
728 | } else {
|
---|
729 | string = "???";
|
---|
730 | }
|
---|
731 | Tcl_SetVar2(interp, varName, "Collate", string, 0);
|
---|
732 | }
|
---|
733 | if (dmPtr->dmFields & DM_FORMNAME) {
|
---|
734 | Tcl_SetVar2(interp, varName, "FormName", dmPtr->dmFormName, 0);
|
---|
735 | }
|
---|
736 | Tcl_SetVar2(interp, varName, "OutputFile", dmPtr->dmDeviceName, 0);
|
---|
737 | result = TCL_OK;
|
---|
738 |
|
---|
739 | error:
|
---|
740 | Tcl_DStringFree(&dString);
|
---|
741 | CloseQueue(queuePtr);
|
---|
742 | if (hMem1 != NULL) {
|
---|
743 | GlobalUnlock(hMem1);
|
---|
744 | GlobalFree(hMem1);
|
---|
745 | }
|
---|
746 | if (hMem2 != NULL) {
|
---|
747 | GlobalUnlock(hMem2);
|
---|
748 | GlobalFree(hMem2);
|
---|
749 | }
|
---|
750 | return result;
|
---|
751 | }
|
---|
752 |
|
---|
753 | static int
|
---|
754 | SetQueueAttributes(
|
---|
755 | Tcl_Interp *interp,
|
---|
756 | PrintQueue *queuePtr,
|
---|
757 | Tcl_Obj *objPtr)
|
---|
758 | {
|
---|
759 | char *string;
|
---|
760 | DEVMODE *dmPtr;
|
---|
761 | int value;
|
---|
762 | HGLOBAL hMem;
|
---|
763 | int result;
|
---|
764 | char *varName;
|
---|
765 |
|
---|
766 | if (OpenQueue(interp, queuePtr) != TCL_OK) {
|
---|
767 | return TCL_ERROR;
|
---|
768 | }
|
---|
769 | hMem = GetQueueProperties(queuePtr, &dmPtr);
|
---|
770 | CloseQueue(queuePtr);
|
---|
771 | if (hMem == NULL) {
|
---|
772 | return TCL_ERROR;
|
---|
773 | }
|
---|
774 | dmPtr->dmFields = 0;
|
---|
775 | varName = Tcl_GetString(objPtr);
|
---|
776 | string = (char *)Tcl_GetVar2(interp, varName, "Orientation", 0);
|
---|
777 | if (string != NULL) {
|
---|
778 | value = StringToToken(orientationTable, string);
|
---|
779 | if (value > 0) {
|
---|
780 | dmPtr->dmFields |= DM_ORIENTATION;
|
---|
781 | dmPtr->dmOrientation = value;
|
---|
782 | }
|
---|
783 | }
|
---|
784 | string = (char *)Tcl_GetVar2(interp, varName, "PaperSize", 0);
|
---|
785 | if (string != NULL) {
|
---|
786 | value = StringToToken(sizeTable, string);
|
---|
787 | if (value > 0) {
|
---|
788 | dmPtr->dmFields |= DM_PAPERSIZE;
|
---|
789 | dmPtr->dmPaperSize = value;
|
---|
790 | }
|
---|
791 | }
|
---|
792 | string = (char *)Tcl_GetVar2(interp, varName, "PaperWidth", 0);
|
---|
793 | if (string != NULL) {
|
---|
794 | if (Tcl_GetInt(interp, string, &value) == TCL_OK) {
|
---|
795 | dmPtr->dmFields |= DM_PAPERWIDTH;
|
---|
796 | dmPtr->dmPaperWidth = value;
|
---|
797 | }
|
---|
798 | }
|
---|
799 | string = (char *)Tcl_GetVar2(interp, varName, "PaperLength", 0);
|
---|
800 | if (string != NULL) {
|
---|
801 | if (Tcl_GetInt(interp, string, &value) == TCL_OK) {
|
---|
802 | dmPtr->dmFields |= DM_PAPERLENGTH;
|
---|
803 | dmPtr->dmPaperLength = value;
|
---|
804 | }
|
---|
805 | }
|
---|
806 | string = (char *)Tcl_GetVar2(interp, varName, "Scale", 0);
|
---|
807 | if (string != NULL) {
|
---|
808 | if (Tcl_GetInt(interp, string, &value) == TCL_OK) {
|
---|
809 | dmPtr->dmFields |= DM_SCALE;
|
---|
810 | dmPtr->dmScale = value;
|
---|
811 | }
|
---|
812 | }
|
---|
813 | string = (char *)Tcl_GetVar2(interp, varName, "Copies", 0);
|
---|
814 | if (string != NULL) {
|
---|
815 | if (Tcl_GetInt(interp, string, &value) == TCL_OK) {
|
---|
816 | dmPtr->dmFields |= DM_COPIES;
|
---|
817 | dmPtr->dmCopies = value;
|
---|
818 | }
|
---|
819 | }
|
---|
820 | string = (char *)Tcl_GetVar2(interp, varName, "DefaultSource", 0);
|
---|
821 | if (string != NULL) {
|
---|
822 | value = StringToToken(binTable, string);
|
---|
823 | if (value > 0) {
|
---|
824 | dmPtr->dmFields |= DM_DEFAULTSOURCE;
|
---|
825 | dmPtr->dmDefaultSource = value;
|
---|
826 | }
|
---|
827 | }
|
---|
828 | string = (char *)Tcl_GetVar2(interp, varName, "PrintQuality", 0);
|
---|
829 | if (string != NULL) {
|
---|
830 | value = StringToToken(qualityTable, string);
|
---|
831 | if (value > 0) {
|
---|
832 | dmPtr->dmFields |= DM_PRINTQUALITY;
|
---|
833 | dmPtr->dmPrintQuality = value;
|
---|
834 | }
|
---|
835 | }
|
---|
836 | string = (char *)Tcl_GetVar2(interp, varName, "Color", 0);
|
---|
837 | if (string != NULL) {
|
---|
838 | value = StringToToken(colorTable, string);
|
---|
839 | if (value > 0) {
|
---|
840 | dmPtr->dmFields |= DM_COLOR;
|
---|
841 | dmPtr->dmColor = value;
|
---|
842 | }
|
---|
843 | }
|
---|
844 | string = (char *)Tcl_GetVar2(interp, varName, "Duplex", 0);
|
---|
845 | if (string != NULL) {
|
---|
846 | value = StringToToken(duplexTable, string);
|
---|
847 | if (value > 0) {
|
---|
848 | dmPtr->dmFields |= DM_DUPLEX;
|
---|
849 | dmPtr->dmDuplex = value;
|
---|
850 | }
|
---|
851 | }
|
---|
852 | string = (char *)Tcl_GetVar2(interp, varName, "YResolution", 0);
|
---|
853 | if (string != NULL) {
|
---|
854 | if (Tcl_GetInt(interp, string, &value) == TCL_OK) {
|
---|
855 | dmPtr->dmFields |= DM_YRESOLUTION;
|
---|
856 | dmPtr->dmYResolution = value;
|
---|
857 | }
|
---|
858 | }
|
---|
859 | string = (char *)Tcl_GetVar2(interp, varName, "TTOption", 0);
|
---|
860 | if (string != NULL) {
|
---|
861 | value = StringToToken(ttOptionTable, string);
|
---|
862 | if (value > 0) {
|
---|
863 | dmPtr->dmFields |= DM_TTOPTION;
|
---|
864 | dmPtr->dmTTOption = value;
|
---|
865 | }
|
---|
866 | }
|
---|
867 | string = (char *)Tcl_GetVar2(interp, varName, "Collate", 0);
|
---|
868 | if (string != NULL) {
|
---|
869 | if (Tcl_GetBoolean(interp, string, &value) == TCL_OK) {
|
---|
870 | dmPtr->dmFields |= DM_COLLATE;
|
---|
871 | dmPtr->dmCollate = value;
|
---|
872 | }
|
---|
873 | }
|
---|
874 | string = (char *)Tcl_GetVar2(interp, varName, "OutputFile", 0);
|
---|
875 | if (string != NULL) {
|
---|
876 | if (queuePtr->fileName != NULL) {
|
---|
877 | Blt_Free(queuePtr->fileName);
|
---|
878 | }
|
---|
879 | queuePtr->fileName = Blt_Strdup(string);
|
---|
880 | }
|
---|
881 | if (queuePtr->dmPtr != NULL) {
|
---|
882 | Blt_Free(queuePtr->dmPtr);
|
---|
883 | }
|
---|
884 | string = (char *)Tcl_GetVar2(interp, varName, "DocumentName", 0);
|
---|
885 | if (string != NULL) {
|
---|
886 | if (queuePtr->docName != NULL) {
|
---|
887 | Blt_Free(queuePtr->docName);
|
---|
888 | }
|
---|
889 | queuePtr->docName = Blt_Strdup(string);
|
---|
890 | }
|
---|
891 | result = SetQueueProperties(interp, queuePtr, dmPtr);
|
---|
892 | GlobalUnlock(hMem);
|
---|
893 | GlobalFree(hMem);
|
---|
894 | CloseQueue(queuePtr);
|
---|
895 | return result;
|
---|
896 | }
|
---|
897 |
|
---|
898 | /*ARGSUSED*/
|
---|
899 | static int
|
---|
900 | EnumOp(
|
---|
901 | ClientData clientData, /* Not used. */
|
---|
902 | Tcl_Interp *interp,
|
---|
903 | int objc,
|
---|
904 | Tcl_Obj *CONST *objv)
|
---|
905 | {
|
---|
906 | TokenString *p;
|
---|
907 | char c;
|
---|
908 | unsigned int length;
|
---|
909 | char *attr;
|
---|
910 |
|
---|
911 | attr = Tcl_GetStringFromObj(objv[2], &length);
|
---|
912 | c = attr[0];
|
---|
913 | if ((c == 'p') && (strncmp(attr, "paper", length) == 0)) {
|
---|
914 | p = sizeTable;
|
---|
915 | } else if ((c == 'q') && (strncmp(attr, "quality", length) == 0)) {
|
---|
916 | p = qualityTable;
|
---|
917 | } else if ((c == 'b') && (strncmp(attr, "bin", length) == 0)) {
|
---|
918 | p = binTable;
|
---|
919 | } else if ((c == 'o') && (strncmp(attr, "orientation", length) == 0)) {
|
---|
920 | p = orientationTable;
|
---|
921 | } else if ((c == 'c') && (strncmp(attr, "color", length) == 0)) {
|
---|
922 | p = colorTable;
|
---|
923 | } else if ((c == 'd') && (strncmp(attr, "duplex", length) == 0)) {
|
---|
924 | p = duplexTable;
|
---|
925 | } else if ((c == 't') && (strncmp(attr, "ttoption", length) == 0)) {
|
---|
926 | p = ttOptionTable;
|
---|
927 | } else {
|
---|
928 | Tcl_AppendResult(interp, "bad enumeration field \"", attr,
|
---|
929 | "\": should be \"paper\", \"quality\", \"bin\", \"orientation\", \"color\", \"duplex\", or \"ttoption\"",
|
---|
930 | (char *)NULL);
|
---|
931 | return TCL_ERROR;
|
---|
932 | }
|
---|
933 | for ( /*empty*/ ; p->string != NULL; p++) {
|
---|
934 | Tcl_AppendElement(interp, p->string);
|
---|
935 | }
|
---|
936 | return TCL_OK;
|
---|
937 | }
|
---|
938 |
|
---|
939 | /*ARGSUSED*/
|
---|
940 | static int
|
---|
941 | OpenOp(
|
---|
942 | ClientData clientData, /* Interpreter-specific data. */
|
---|
943 | Tcl_Interp *interp,
|
---|
944 | int objc,
|
---|
945 | Tcl_Obj *CONST *objv)
|
---|
946 | {
|
---|
947 | PrinterInterpData *dataPtr = clientData;
|
---|
948 | PrintQueue *queuePtr;
|
---|
949 | LPVOID buffer;
|
---|
950 | PRINTER_INFO_2* pi2Ptr;
|
---|
951 | DWORD bytesNeeded;
|
---|
952 | int isNew;
|
---|
953 | Blt_HashEntry *hPtr;
|
---|
954 | HANDLE hMem;
|
---|
955 | char *name;
|
---|
956 |
|
---|
957 | name = Tcl_GetString(objv[2]);
|
---|
958 | hPtr = Blt_CreateHashEntry(&dataPtr->printerTable, name, &isNew);
|
---|
959 | if (isNew) {
|
---|
960 | queuePtr = Blt_Calloc(1, sizeof(PrintQueue));
|
---|
961 | queuePtr->name = Blt_GetHashKey(&dataPtr->printerTable, hPtr);
|
---|
962 | queuePtr->interp = interp;
|
---|
963 | Tcl_SetResult(interp, name, TCL_VOLATILE);
|
---|
964 | Blt_SetHashValue(hPtr, queuePtr);
|
---|
965 | queuePtr->hashPtr = hPtr;
|
---|
966 | queuePtr->tablePtr = &dataPtr->printerTable;
|
---|
967 | queuePtr->printerName = Blt_Strdup(name);
|
---|
968 | } else {
|
---|
969 | Tcl_AppendResult(interp, "printer \"", name, "\" is already open",
|
---|
970 | (char *)NULL);
|
---|
971 | return TCL_ERROR;
|
---|
972 | }
|
---|
973 | if (OpenQueue(interp, queuePtr) != TCL_OK) {
|
---|
974 | DestroyQueue(queuePtr);
|
---|
975 | return TCL_ERROR;
|
---|
976 | }
|
---|
977 | /* Call the first time to determine the amount of memory needed. */
|
---|
978 | GetPrinter(queuePtr->hPrinter, 2, NULL, 0, &bytesNeeded);
|
---|
979 | if ((bytesNeeded == 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
|
---|
980 | Tcl_AppendResult(interp, "can't get size of attribute buffer for \"",
|
---|
981 | name, "\": ", Blt_LastError(), (char *)NULL);
|
---|
982 | return TCL_ERROR;
|
---|
983 | }
|
---|
984 | /* Allocate a buffer to contain all printer information. */
|
---|
985 | hMem = GlobalAlloc(GHND, bytesNeeded);
|
---|
986 | if (hMem == NULL) {
|
---|
987 | return TCL_ERROR;
|
---|
988 | }
|
---|
989 | buffer = (LPVOID)GlobalLock(hMem);
|
---|
990 |
|
---|
991 | /* And call the again to actually get the printer. */
|
---|
992 | if (!GetPrinter(queuePtr->hPrinter, 2, buffer, bytesNeeded,
|
---|
993 | &bytesNeeded)) {
|
---|
994 | Tcl_AppendResult(interp, "can't get printer attributes for \"",
|
---|
995 | name, "\": ", Blt_LastError(), (char *)NULL);
|
---|
996 | GlobalUnlock(hMem);
|
---|
997 | GlobalFree(hMem);
|
---|
998 | return TCL_ERROR;
|
---|
999 | }
|
---|
1000 | pi2Ptr = (PRINTER_INFO_2 *)buffer;
|
---|
1001 | if (pi2Ptr->pDevMode != NULL) {
|
---|
1002 | queuePtr->deviceName = Blt_Strdup(pi2Ptr->pDevMode->dmDeviceName);
|
---|
1003 | }
|
---|
1004 | queuePtr->driverName = Blt_Strdup(pi2Ptr->pDriverName);
|
---|
1005 | /*
|
---|
1006 | queuePtr->printerName = Blt_Strdup(pi2Ptr->pPrinterName);
|
---|
1007 | */
|
---|
1008 | queuePtr->portName = Blt_Strdup(pi2Ptr->pPortName);
|
---|
1009 | GlobalUnlock(hMem);
|
---|
1010 | GlobalFree(hMem);
|
---|
1011 | return TCL_OK;
|
---|
1012 | }
|
---|
1013 |
|
---|
1014 | /*ARGSUSED*/
|
---|
1015 | static int
|
---|
1016 | NamesOp(
|
---|
1017 | ClientData clientData, /* Interpreter-specific data. */
|
---|
1018 | Tcl_Interp *interp,
|
---|
1019 | int objc, /* Not used. */
|
---|
1020 | Tcl_Obj *CONST *objv) /* Not used. */
|
---|
1021 | {
|
---|
1022 | DWORD nPrinters, bytesNeeded;
|
---|
1023 | int elemSize, level;
|
---|
1024 | unsigned char *buffer;
|
---|
1025 | int result, flags;
|
---|
1026 | HANDLE hMem;
|
---|
1027 |
|
---|
1028 | if (Blt_GetPlatformId() == VER_PLATFORM_WIN32_NT) {
|
---|
1029 | level = 4;
|
---|
1030 | elemSize = sizeof(PRINTER_INFO_4);
|
---|
1031 | flags = PRINTER_ENUM_NAME;
|
---|
1032 | } else {
|
---|
1033 | level = 5;
|
---|
1034 | elemSize = sizeof(PRINTER_INFO_5);
|
---|
1035 | flags = PRINTER_ENUM_LOCAL;
|
---|
1036 | }
|
---|
1037 | result = EnumPrinters(
|
---|
1038 | flags, /* Flags */
|
---|
1039 | NULL, /* Printer name */
|
---|
1040 | level, /* Information level: 1, 2, 4, or 5 */
|
---|
1041 | NULL, /* Array of returned information */
|
---|
1042 | 0, /* Size of array */
|
---|
1043 | &bytesNeeded, /* Size needed for array */
|
---|
1044 | &nPrinters); /* Number of structures returned */
|
---|
1045 |
|
---|
1046 | if ((!result) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
|
---|
1047 | Tcl_AppendResult(interp, "can't enumerate printers (memory alloc): ",
|
---|
1048 | Blt_LastError(), (char *)NULL);
|
---|
1049 | return TCL_ERROR;
|
---|
1050 | }
|
---|
1051 | hMem = GlobalAlloc(GHND, bytesNeeded);
|
---|
1052 | buffer = (unsigned char *)GlobalLock(hMem);
|
---|
1053 |
|
---|
1054 | result = EnumPrinters(
|
---|
1055 | flags, /* Flags */
|
---|
1056 | NULL, /* Printer name */
|
---|
1057 | level, /* Information level: 1, 2, 4, or 5 */
|
---|
1058 | buffer, /* Array of returned information */
|
---|
1059 | bytesNeeded, /* Size of array */
|
---|
1060 | &bytesNeeded, /* Size needed for array */
|
---|
1061 | &nPrinters); /* Number of structures returned */
|
---|
1062 |
|
---|
1063 | if (!result) {
|
---|
1064 | Tcl_AppendResult(interp, "can't enumerate printers: ",
|
---|
1065 | Blt_LastError(), (char *)NULL);
|
---|
1066 | return TCL_ERROR;
|
---|
1067 | }
|
---|
1068 | if (objc > 2) {
|
---|
1069 | register unsigned int i;
|
---|
1070 | char *pattern;
|
---|
1071 | char *p;
|
---|
1072 |
|
---|
1073 | p = buffer;
|
---|
1074 | pattern = Tcl_GetString(objv[2]);
|
---|
1075 | for (i = 0; i < nPrinters; i++) {
|
---|
1076 | if (Tcl_StringMatch(p, pattern)) {
|
---|
1077 | Tcl_AppendElement(interp, *(char **)p);
|
---|
1078 | }
|
---|
1079 | p += elemSize;
|
---|
1080 | }
|
---|
1081 | } else {
|
---|
1082 | register unsigned int i;
|
---|
1083 | char *p;
|
---|
1084 |
|
---|
1085 | p = buffer;
|
---|
1086 | for (i = 0; i < nPrinters; i++) {
|
---|
1087 | Tcl_AppendElement(interp, *(char **)p);
|
---|
1088 | p += elemSize;
|
---|
1089 | }
|
---|
1090 | }
|
---|
1091 | GlobalUnlock(hMem);
|
---|
1092 | GlobalFree(hMem);
|
---|
1093 | return TCL_OK;
|
---|
1094 | }
|
---|
1095 |
|
---|
1096 | /*ARGSUSED*/
|
---|
1097 | static int
|
---|
1098 | CloseOp(
|
---|
1099 | ClientData clientData, /* Interpreter-specific data. */
|
---|
1100 | Tcl_Interp *interp,
|
---|
1101 | int objc, /* Not used. */
|
---|
1102 | Tcl_Obj *CONST *objv)
|
---|
1103 | {
|
---|
1104 | PrintQueue *queuePtr;
|
---|
1105 |
|
---|
1106 | if (GetQueueFromObj(interp, objv[2], &queuePtr) != TCL_OK) {
|
---|
1107 | return TCL_ERROR;
|
---|
1108 | }
|
---|
1109 | DestroyQueue(queuePtr);
|
---|
1110 | return TCL_OK;
|
---|
1111 | }
|
---|
1112 |
|
---|
1113 | /*ARGSUSED*/
|
---|
1114 | static int
|
---|
1115 | GetAttrOp(
|
---|
1116 | ClientData clientData, /* Interpreter-specific data. */
|
---|
1117 | Tcl_Interp *interp,
|
---|
1118 | int objc, /* Not used. */
|
---|
1119 | Tcl_Obj *CONST *objv)
|
---|
1120 | {
|
---|
1121 | PrintQueue *queuePtr;
|
---|
1122 |
|
---|
1123 | if (GetQueueFromObj(interp, objv[2], &queuePtr) != TCL_OK) {
|
---|
1124 | return TCL_ERROR;
|
---|
1125 | }
|
---|
1126 | return GetPrinterAttributes(interp, queuePtr, objv[3]);
|
---|
1127 | }
|
---|
1128 |
|
---|
1129 | /*ARGSUSED*/
|
---|
1130 | static int
|
---|
1131 | SetAttrOp(
|
---|
1132 | ClientData clientData, /* Interpreter-specific data. */
|
---|
1133 | Tcl_Interp *interp,
|
---|
1134 | int objc, /* Not used. */
|
---|
1135 | Tcl_Obj *CONST *objv)
|
---|
1136 | {
|
---|
1137 | PrintQueue *queuePtr;
|
---|
1138 |
|
---|
1139 | if (GetQueueFromObj(interp, objv[2], &queuePtr) != TCL_OK) {
|
---|
1140 | return TCL_ERROR;
|
---|
1141 | }
|
---|
1142 | return SetQueueAttributes(interp, queuePtr, objv[3]);
|
---|
1143 | }
|
---|
1144 |
|
---|
1145 | /*
|
---|
1146 | * --------------------------------------------------------------------------
|
---|
1147 | *
|
---|
1148 | * SnapOp --
|
---|
1149 | *
|
---|
1150 | * Prints a snapshot of a Tk_Window to the designated printer.
|
---|
1151 | *
|
---|
1152 | * Results:
|
---|
1153 | * Returns a standard Tcl result. If an error occurred
|
---|
1154 | * TCL_ERROR is returned and interp->result will contain an
|
---|
1155 | * error message.
|
---|
1156 | *
|
---|
1157 | * -------------------------------------------------------------------------
|
---|
1158 | */
|
---|
1159 | static int
|
---|
1160 | SnapOp(
|
---|
1161 | ClientData clientData, /* Interpreter-specific data. */
|
---|
1162 | Tcl_Interp *interp,
|
---|
1163 | int objc,
|
---|
1164 | Tcl_Obj *CONST *objv)
|
---|
1165 | {
|
---|
1166 | BITMAPINFO bi;
|
---|
1167 | DIBSECTION ds;
|
---|
1168 | HBITMAP hBitmap;
|
---|
1169 | HPALETTE hPalette;
|
---|
1170 | HDC hDC, printDC, memDC;
|
---|
1171 | void *data;
|
---|
1172 | Tk_Window tkwin;
|
---|
1173 | TkWinDCState state;
|
---|
1174 | int result;
|
---|
1175 | PrintQueue *queuePtr;
|
---|
1176 | DOCINFO di;
|
---|
1177 | double pageWidth, pageHeight;
|
---|
1178 | int jobId;
|
---|
1179 | char *driverName;
|
---|
1180 | DEVMODE *dmPtr;
|
---|
1181 | HGLOBAL hMem;
|
---|
1182 | Tcl_DString dString;
|
---|
1183 | char *path;
|
---|
1184 |
|
---|
1185 | Tcl_DStringInit(&dString);
|
---|
1186 | if (GetQueueFromObj(interp, objv[2], &queuePtr) != TCL_OK) {
|
---|
1187 | return TCL_ERROR;
|
---|
1188 | }
|
---|
1189 | path = Tcl_GetString(objv[3]);
|
---|
1190 | tkwin = Tk_NameToWindow(interp, path, Tk_MainWindow(interp));
|
---|
1191 | if (tkwin == NULL) {
|
---|
1192 | return TCL_ERROR;
|
---|
1193 | }
|
---|
1194 | if (Tk_WindowId(tkwin) == None) {
|
---|
1195 | Tk_MakeWindowExist(tkwin);
|
---|
1196 | }
|
---|
1197 |
|
---|
1198 | result = TCL_ERROR;
|
---|
1199 | hDC = TkWinGetDrawableDC(Tk_Display(tkwin), Tk_WindowId(tkwin), &state);
|
---|
1200 |
|
---|
1201 | ZeroMemory(&bi, sizeof(bi));
|
---|
1202 | bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
---|
1203 | bi.bmiHeader.biWidth = Tk_Width(tkwin);
|
---|
1204 | bi.bmiHeader.biHeight = Tk_Height(tkwin);
|
---|
1205 | bi.bmiHeader.biPlanes = 1;
|
---|
1206 | bi.bmiHeader.biBitCount = 32;
|
---|
1207 | bi.bmiHeader.biCompression = BI_RGB;
|
---|
1208 | hBitmap = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &data, NULL, 0);
|
---|
1209 | memDC = CreateCompatibleDC(hDC);
|
---|
1210 | SelectBitmap(memDC, hBitmap);
|
---|
1211 | hPalette = Blt_GetSystemPalette();
|
---|
1212 | if (hPalette != NULL) {
|
---|
1213 | SelectPalette(hDC, hPalette, FALSE);
|
---|
1214 | RealizePalette(hDC);
|
---|
1215 | SelectPalette(memDC, hPalette, FALSE);
|
---|
1216 | RealizePalette(memDC);
|
---|
1217 | }
|
---|
1218 | /* Copy the window contents to the memory surface. */
|
---|
1219 | if (!BitBlt(memDC, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), hDC, 0, 0,
|
---|
1220 | SRCCOPY)) {
|
---|
1221 | Tcl_AppendResult(interp, "can't blit \"", Tk_PathName(tkwin), "\": ",
|
---|
1222 | Blt_LastError(), (char *)NULL);
|
---|
1223 | goto done;
|
---|
1224 | }
|
---|
1225 | /* Now that the DIB contains the image of the window, get the
|
---|
1226 | * databits and write them to the printer device, stretching the
|
---|
1227 | * image to the fit the printer's resolution. */
|
---|
1228 | if (GetObject(hBitmap, sizeof(DIBSECTION), &ds) == 0) {
|
---|
1229 | Tcl_AppendResult(interp, "can't get DIB object: ", Blt_LastError(),
|
---|
1230 | (char *)NULL);
|
---|
1231 | goto done;
|
---|
1232 | }
|
---|
1233 | driverName = NULL;
|
---|
1234 | if (Blt_GetPlatformId() == VER_PLATFORM_WIN32_NT) {
|
---|
1235 | driverName = queuePtr->driverName;
|
---|
1236 | }
|
---|
1237 | if (OpenQueue(interp, queuePtr) != TCL_OK) {
|
---|
1238 | goto done;
|
---|
1239 | }
|
---|
1240 | hMem = GetQueueProperties(queuePtr, &dmPtr);
|
---|
1241 | if (hMem == NULL) {
|
---|
1242 | goto done;
|
---|
1243 | }
|
---|
1244 | printDC = CreateDC(driverName, queuePtr->deviceName, NULL, dmPtr);
|
---|
1245 | GlobalUnlock(hMem);
|
---|
1246 | GlobalFree(hMem);
|
---|
1247 | if (printDC == NULL) {
|
---|
1248 | Tcl_AppendResult(interp, "can't allocate printer DC for \"",
|
---|
1249 | queuePtr->name, "\": ", Blt_LastError(), (char *)NULL);
|
---|
1250 | goto done;
|
---|
1251 | }
|
---|
1252 | {
|
---|
1253 | double scale, sx, sy;
|
---|
1254 |
|
---|
1255 | /* Get the resolution of the printer device. */
|
---|
1256 | sx = (double)GetDeviceCaps(printDC, HORZRES)/(double)Tk_Width(tkwin);
|
---|
1257 | sy = (double)GetDeviceCaps(printDC, VERTRES)/(double)Tk_Height(tkwin);
|
---|
1258 | scale = MIN(sx, sy);
|
---|
1259 | pageWidth = scale * Tk_Width(tkwin);
|
---|
1260 | pageHeight = scale * Tk_Height(tkwin);
|
---|
1261 | }
|
---|
1262 | ZeroMemory(&di, sizeof(di));
|
---|
1263 | di.cbSize = sizeof(di);
|
---|
1264 | Tcl_DStringAppend(&dString, "Snapshot of \"", -1);
|
---|
1265 | Tcl_DStringAppend(&dString, Tk_PathName(tkwin), -1);
|
---|
1266 | Tcl_DStringAppend(&dString, "\"", -1);
|
---|
1267 | di.lpszDocName = Tcl_DStringValue(&dString);
|
---|
1268 | jobId = StartDoc(printDC, &di);
|
---|
1269 | if (jobId <= 0) {
|
---|
1270 | Tcl_AppendResult(interp, "can't start document: ", Blt_LastError(),
|
---|
1271 | (char *)NULL);
|
---|
1272 | goto done;
|
---|
1273 | }
|
---|
1274 | if (StartPage(printDC) <= 0) {
|
---|
1275 | Tcl_AppendResult(interp, "error starting page: ", Blt_LastError(),
|
---|
1276 | (char *)NULL);
|
---|
1277 | goto done;
|
---|
1278 | }
|
---|
1279 | StretchDIBits(printDC, 0, 0, ROUND(pageWidth), ROUND(pageHeight), 0, 0,
|
---|
1280 | Tk_Width(tkwin), Tk_Height(tkwin), ds.dsBm.bmBits,
|
---|
1281 | (LPBITMAPINFO)&ds.dsBmih, DIB_RGB_COLORS, SRCCOPY);
|
---|
1282 | EndPage(printDC);
|
---|
1283 | EndDoc(printDC);
|
---|
1284 | DeleteDC(printDC);
|
---|
1285 | Tcl_SetResult(interp, Blt_Itoa(jobId), TCL_VOLATILE);
|
---|
1286 | result = TCL_OK;
|
---|
1287 |
|
---|
1288 | done:
|
---|
1289 | Tcl_DStringFree(&dString);
|
---|
1290 | if (queuePtr->hPrinter != NULL) {
|
---|
1291 | CloseQueue(queuePtr);
|
---|
1292 | }
|
---|
1293 | DeleteBitmap(hBitmap);
|
---|
1294 | DeleteDC(memDC);
|
---|
1295 | TkWinReleaseDrawableDC(Tk_WindowId(tkwin), hDC, &state);
|
---|
1296 | if (hPalette != NULL) {
|
---|
1297 | DeletePalette(hPalette);
|
---|
1298 | }
|
---|
1299 | return result;
|
---|
1300 | }
|
---|
1301 |
|
---|
1302 | /*ARGSUSED*/
|
---|
1303 | static int
|
---|
1304 | WriteOp(
|
---|
1305 | ClientData clientData, /* Interpreter-specific data. */
|
---|
1306 | Tcl_Interp *interp,
|
---|
1307 | int objc, /* Not used. */
|
---|
1308 | Tcl_Obj *CONST *objv)
|
---|
1309 | {
|
---|
1310 | DWORD bytesLeft, nBytes;
|
---|
1311 | DOC_INFO_1 di1;
|
---|
1312 | DWORD jobId;
|
---|
1313 | char *title;
|
---|
1314 | register char *data;
|
---|
1315 | static int nextJob = 0;
|
---|
1316 | char string[200];
|
---|
1317 | PrintQueue *queuePtr;
|
---|
1318 | int result;
|
---|
1319 |
|
---|
1320 | if (GetQueueFromObj(interp, objv[2], &queuePtr) != TCL_OK) {
|
---|
1321 | return TCL_ERROR;
|
---|
1322 | }
|
---|
1323 | if (OpenQueue(interp, queuePtr) != TCL_OK) {
|
---|
1324 | return TCL_ERROR;
|
---|
1325 | }
|
---|
1326 | if (objc == 5) {
|
---|
1327 | title = Tcl_GetString(objv[3]);
|
---|
1328 | data = Tcl_GetStringFromObj(objv[4], &bytesLeft);
|
---|
1329 | } else {
|
---|
1330 | sprintf(string, "Print Job #%d", nextJob++);
|
---|
1331 | title = string;
|
---|
1332 | data = Tcl_GetStringFromObj(objv[3], &bytesLeft);
|
---|
1333 | }
|
---|
1334 | ZeroMemory(&di1, sizeof(DOC_INFO_1));
|
---|
1335 | di1.pDocName = title;
|
---|
1336 | if (queuePtr->fileName != NULL) {
|
---|
1337 | di1.pOutputFile = queuePtr->fileName;
|
---|
1338 | } else {
|
---|
1339 | di1.pOutputFile = NULL;
|
---|
1340 | }
|
---|
1341 | di1.pDatatype = "RAW";
|
---|
1342 |
|
---|
1343 | result = TCL_ERROR;
|
---|
1344 | /* Start new document */
|
---|
1345 | jobId = StartDocPrinter(queuePtr->hPrinter, 1, (unsigned char *)&di1);
|
---|
1346 | if (jobId == 0) {
|
---|
1347 | Tcl_AppendResult(interp, "error starting document on \"",
|
---|
1348 | queuePtr->printerName, "\": ", Blt_LastError(), (char *)NULL);
|
---|
1349 | goto error;
|
---|
1350 | }
|
---|
1351 | /* Start new page */
|
---|
1352 | if (!StartPagePrinter(queuePtr->hPrinter)) {
|
---|
1353 | Tcl_AppendResult(interp, "error starting page on \"",
|
---|
1354 | queuePtr->printerName, "\": ", Blt_LastError(), (char *)NULL);
|
---|
1355 | goto error;
|
---|
1356 | }
|
---|
1357 | do {
|
---|
1358 | if (!WritePrinter(queuePtr->hPrinter, data, bytesLeft, &nBytes)) {
|
---|
1359 | Tcl_AppendResult(interp, "can't write data to \"",
|
---|
1360 | queuePtr->printerName, "\": ", Blt_LastError(), (char *)NULL);
|
---|
1361 | EndDocPrinter(queuePtr->hPrinter);
|
---|
1362 | goto error;
|
---|
1363 | }
|
---|
1364 | data += nBytes;
|
---|
1365 | bytesLeft -= nBytes;
|
---|
1366 | } while (bytesLeft > 0);
|
---|
1367 | /* End last page */
|
---|
1368 | if (!EndPagePrinter(queuePtr->hPrinter)) {
|
---|
1369 | Tcl_AppendResult(interp, "error ending page on \"",
|
---|
1370 | queuePtr->printerName, "\": ", Blt_LastError(), (char *)NULL);
|
---|
1371 | goto error;
|
---|
1372 | }
|
---|
1373 | /* End document */
|
---|
1374 | if (!EndDocPrinter(queuePtr->hPrinter)) {
|
---|
1375 | Tcl_AppendResult(interp, "error ending document on \"",
|
---|
1376 | queuePtr->printerName, "\": ", Blt_LastError(), (char *)NULL);
|
---|
1377 | goto error;
|
---|
1378 | }
|
---|
1379 | result = TCL_OK;
|
---|
1380 | error:
|
---|
1381 | CloseQueue(queuePtr);
|
---|
1382 | return result;
|
---|
1383 | }
|
---|
1384 |
|
---|
1385 | static Blt_OpSpec printerOps[] =
|
---|
1386 | {
|
---|
1387 | {"close", 1, (Blt_Op)CloseOp, 3, 3, "pid",},
|
---|
1388 | {"enum", 1, (Blt_Op)EnumOp, 3, 3, "attribute",},
|
---|
1389 | {"getattrs", 1, (Blt_Op)GetAttrOp, 4, 4, "pid varName",},
|
---|
1390 | {"names", 1, (Blt_Op)NamesOp, 2, 3, "?pattern?",},
|
---|
1391 | {"open", 1, (Blt_Op)OpenOp, 3, 3, "printerName",},
|
---|
1392 | {"setattrs", 1, (Blt_Op)SetAttrOp, 4, 4, "pid varName",},
|
---|
1393 | {"snap", 1, (Blt_Op)SnapOp, 4, 4, "pid window",},
|
---|
1394 | {"write", 1, (Blt_Op)WriteOp, 4, 5, "pid ?title? string",},
|
---|
1395 | };
|
---|
1396 | static int nPrinterOps = sizeof(printerOps) / sizeof(Blt_OpSpec);
|
---|
1397 |
|
---|
1398 | /* ARGSUSED */
|
---|
1399 | static int
|
---|
1400 | PrinterCmd(
|
---|
1401 | ClientData clientData, /* Not used. */
|
---|
1402 | Tcl_Interp *interp,
|
---|
1403 | int objc,
|
---|
1404 | Tcl_Obj *CONST *objv)
|
---|
1405 | {
|
---|
1406 | Blt_Op proc;
|
---|
1407 | int result;
|
---|
1408 |
|
---|
1409 | proc = Blt_GetOpFromObj(interp, nPrinterOps, printerOps, BLT_OP_ARG1,
|
---|
1410 | objc, objv, 0);
|
---|
1411 | if (proc == NULL) {
|
---|
1412 | return TCL_ERROR;
|
---|
1413 | }
|
---|
1414 | result = (*proc) (clientData, interp, objc, objv);
|
---|
1415 | return result;
|
---|
1416 | }
|
---|
1417 |
|
---|
1418 | /*
|
---|
1419 | * -----------------------------------------------------------------------
|
---|
1420 | *
|
---|
1421 | * PrinterInterpDeleteProc --
|
---|
1422 | *
|
---|
1423 | * This is called when the interpreter hosting one or more printer
|
---|
1424 | * commands is destroyed.
|
---|
1425 | *
|
---|
1426 | * Results:
|
---|
1427 | * None.
|
---|
1428 | *
|
---|
1429 | * Side effects:
|
---|
1430 | * Closes and removes all open printers.
|
---|
1431 | *
|
---|
1432 | * ------------------------------------------------------------------------
|
---|
1433 | */
|
---|
1434 | /* ARGSUSED */
|
---|
1435 | static void
|
---|
1436 | PrinterInterpDeleteProc(clientData, interp)
|
---|
1437 | ClientData clientData; /* Interpreter-specific data. */
|
---|
1438 | Tcl_Interp *interp;
|
---|
1439 | {
|
---|
1440 | PrinterInterpData *dataPtr = clientData;
|
---|
1441 | Blt_HashEntry *hPtr;
|
---|
1442 | Blt_HashSearch cursor;
|
---|
1443 | PrintQueue *queuePtr;
|
---|
1444 |
|
---|
1445 | for (hPtr = Blt_FirstHashEntry(&dataPtr->printerTable, &cursor);
|
---|
1446 | hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
|
---|
1447 | queuePtr = (PrintQueue *)Blt_GetHashValue(hPtr);
|
---|
1448 | queuePtr->hashPtr = NULL;
|
---|
1449 | DestroyQueue(queuePtr);
|
---|
1450 | }
|
---|
1451 | Blt_DeleteHashTable(&dataPtr->printerTable);
|
---|
1452 | Tcl_DeleteAssocData(interp, PRINTER_THREAD_KEY);
|
---|
1453 | Blt_Free(dataPtr);
|
---|
1454 | }
|
---|
1455 |
|
---|
1456 |
|
---|
1457 | int
|
---|
1458 | Blt_PrinterInit(Tcl_Interp *interp)
|
---|
1459 | {
|
---|
1460 | static Blt_ObjCmdSpec cmdSpec = {
|
---|
1461 | "printer", PrinterCmd
|
---|
1462 | };
|
---|
1463 | PrinterInterpData *dataPtr;
|
---|
1464 |
|
---|
1465 | dataPtr = GetPrinterInterpData(interp);
|
---|
1466 | cmdSpec.clientData = dataPtr;
|
---|
1467 | if (Blt_InitObjCmd(interp, "blt", &cmdSpec) == NULL) {
|
---|
1468 | return TCL_ERROR;
|
---|
1469 | }
|
---|
1470 | return TCL_OK;
|
---|
1471 | }
|
---|
1472 | |
---|
1473 |
|
---|
1474 |
|
---|
1475 | /* Public routines */
|
---|
1476 | int
|
---|
1477 | Blt_GetOpenPrinter(
|
---|
1478 | Tcl_Interp *interp,
|
---|
1479 | const char *name,
|
---|
1480 | Drawable *drawablePtr)
|
---|
1481 | {
|
---|
1482 | PrintQueue *queuePtr;
|
---|
1483 |
|
---|
1484 | if (GetQueue(interp, name, &queuePtr) != TCL_OK) {
|
---|
1485 | return TCL_ERROR;
|
---|
1486 | }
|
---|
1487 | if (queuePtr->drawable.hDC == NULL) {
|
---|
1488 | char *driverName;
|
---|
1489 | HGLOBAL hMem;
|
---|
1490 | DEVMODE *dmPtr;
|
---|
1491 | HDC hDC;
|
---|
1492 |
|
---|
1493 | driverName = NULL;
|
---|
1494 | if (Blt_GetPlatformId() == VER_PLATFORM_WIN32_NT) {
|
---|
1495 | driverName = queuePtr->driverName;
|
---|
1496 | }
|
---|
1497 | if (OpenQueue(interp, queuePtr) != TCL_OK) {
|
---|
1498 | return TCL_ERROR;
|
---|
1499 | }
|
---|
1500 | hMem = GetQueueProperties(queuePtr, &dmPtr);
|
---|
1501 | if (hMem == NULL) {
|
---|
1502 | CloseQueue(queuePtr);
|
---|
1503 | return TCL_ERROR;
|
---|
1504 | }
|
---|
1505 | if (queuePtr->dmPtr != NULL) {
|
---|
1506 | *dmPtr = *queuePtr->dmPtr;
|
---|
1507 | }
|
---|
1508 | hDC = CreateDC(driverName, queuePtr->deviceName, NULL, dmPtr);
|
---|
1509 | GlobalUnlock(hMem);
|
---|
1510 | GlobalFree(hMem);
|
---|
1511 | CloseQueue(queuePtr);
|
---|
1512 | if (hDC == NULL) {
|
---|
1513 | Tcl_AppendResult(interp, "can't allocate printer DC for \"",
|
---|
1514 | queuePtr->name, "\": ", Blt_LastError(), (char *)NULL);
|
---|
1515 | return TCL_ERROR;
|
---|
1516 | }
|
---|
1517 | queuePtr->drawable.hDC = hDC;
|
---|
1518 | queuePtr->drawable.type = TWD_WINDC;
|
---|
1519 | }
|
---|
1520 | *drawablePtr = (Drawable)(&queuePtr->drawable);
|
---|
1521 | return TCL_OK;
|
---|
1522 | }
|
---|
1523 |
|
---|
1524 | #include <commdlg.h>
|
---|
1525 |
|
---|
1526 | int
|
---|
1527 | Blt_PrintDialog(
|
---|
1528 | Tcl_Interp *interp,
|
---|
1529 | Drawable *drawablePtr)
|
---|
1530 | {
|
---|
1531 | PRINTDLG dlg;
|
---|
1532 | static PrintDrawable drawable;
|
---|
1533 | int mode, result;
|
---|
1534 |
|
---|
1535 | ZeroMemory(&dlg, sizeof(PRINTDLG));
|
---|
1536 | dlg.lStructSize = sizeof(PRINTDLG);
|
---|
1537 | dlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION;
|
---|
1538 | mode = Tcl_SetServiceMode(TCL_SERVICE_NONE);
|
---|
1539 | result = PrintDlg(&dlg);
|
---|
1540 | Tcl_SetServiceMode(mode);
|
---|
1541 | if (!result) {
|
---|
1542 | if (!CommDlgExtendedError()) {
|
---|
1543 | return TCL_RETURN; /* User canceled. */
|
---|
1544 | }
|
---|
1545 | Tcl_AppendResult(interp, "can't access printer:", Blt_LastError(),
|
---|
1546 | (char *)NULL);
|
---|
1547 | return TCL_ERROR;
|
---|
1548 | }
|
---|
1549 | *drawablePtr = (Drawable)&drawable;
|
---|
1550 | drawable.type = TWD_WINDC;
|
---|
1551 | drawable.hDC = dlg.hDC;
|
---|
1552 | return TCL_OK;
|
---|
1553 | }
|
---|
1554 |
|
---|
1555 | int
|
---|
1556 | Blt_StartPrintJob(
|
---|
1557 | Tcl_Interp *interp,
|
---|
1558 | Drawable drawable)
|
---|
1559 | {
|
---|
1560 | DOCINFO di;
|
---|
1561 | PrintDrawable *drawPtr = (PrintDrawable *)drawable;
|
---|
1562 | int jobId;
|
---|
1563 |
|
---|
1564 | ZeroMemory((char *)&di, sizeof(DOCINFO));
|
---|
1565 | di.cbSize = sizeof(DOCINFO);
|
---|
1566 | di.lpszDocName = "Unknown";
|
---|
1567 | jobId = StartDoc(drawPtr->hDC, &di);
|
---|
1568 | if (jobId == 0) {
|
---|
1569 | Tcl_AppendResult(interp, "error starting document: ",
|
---|
1570 | Blt_LastError(), (char *)NULL);
|
---|
1571 | return TCL_ERROR;
|
---|
1572 | }
|
---|
1573 | return TCL_OK;
|
---|
1574 | }
|
---|
1575 |
|
---|
1576 | int
|
---|
1577 | Blt_EndPrintJob(
|
---|
1578 | Tcl_Interp *interp,
|
---|
1579 | Drawable drawable)
|
---|
1580 | {
|
---|
1581 | PrintDrawable *drawPtr = (PrintDrawable *)drawable;
|
---|
1582 |
|
---|
1583 | EndPage(drawPtr->hDC);
|
---|
1584 | EndDoc(drawPtr->hDC);
|
---|
1585 | return TCL_OK;
|
---|
1586 | }
|
---|
1587 |
|
---|
1588 | #endif /*NO_PRINTER*/
|
---|