1
#if !defined(lint) && !defined(DOS)
2
static char rcsid[] = "$Id: print.c 254 2006-11-21 21:54:24Z hubert@u.washington.edu $";
6
* ========================================================================
7
* Copyright 2006 University of Washington
9
* Licensed under the Apache License, Version 2.0 (the "License");
10
* you may not use this file except in compliance with the License.
11
* You may obtain a copy of the License at
13
* http://www.apache.org/licenses/LICENSE-2.0
15
* ========================================================================
20
#include "../c-client/mail.h" /* for MAILSTREAM and friends */
21
#include "../c-client/osdep.h"
22
#include "../c-client/rfc822.h" /* for soutr_t and such */
23
#include "../c-client/misc.h" /* for cpystr proto */
24
#include "../c-client/utf8.h" /* for CHARSET and such*/
25
#include "../c-client/imap4r1.h"
27
#include "../../pith/charconv/utf8.h"
28
#include "../../pith/charconv/filesys.h"
30
#include "../../pith/osdep/color.h"
31
#include "../../pith/osdep/temp_nam.h"
32
#include "../../pith/osdep/err_desc.h"
34
#include "../../pith/debug.h"
35
#include "../../pith/conf.h"
36
#include "../../pith/store.h"
38
#include "../../pico/estruct.h" /* for ctrl() */
39
#include "../../pico/keydefs.h" /* for KEY_* */
41
#include "../status.h"
42
#include "../signal.h"
46
#include "../../pico/osdep/mswin.h"
52
/*======================================================================
55
Functions having to do with printing on paper and forking of spoolers
57
In general one calls open_printer() to start printing. One of
58
the little print functions to send a line or string, and then
59
call print_end() when complete. This takes care of forking off a spooler
60
and piping the stuff down it. No handles or anything here because there's
61
only one printer open at a time.
68
static char *trailer; /* so both open and close_printer can see it */
70
static unsigned char cbuf[6];
71
static unsigned char *cbufp;
72
static unsigned char *cbufend;
73
#endif /* !_WINDOWS */
76
/*----------------------------------------------------------------------
79
Args: desc -- Description of item to print. Should have one trailing blank.
81
Return value: < 0 is a failure.
84
This does most of the work of popen so we can save the standard output of the
85
command we execute and send it back to the user.
88
open_printer(char *desc)
91
char command[201], prompt[200];
92
int cmd, rc, just_one;
93
char *p, *init, *nick;
94
char aname[100], wname[100];
96
int done = 0, i, lastprinter, cur_printer = 0;
99
static ESCKEY_S ekey[] = {
100
/* TRANSLATORS: these are command labels for printing screen */
101
{'y', 'y', "Y", N_("Yes")},
102
{'n', 'n', "N", N_("No")},
103
/* TRANSLATORS: go to Previous Printer in list */
104
{ctrl('P'), 10, "^P", N_("Prev Printer")},
105
{ctrl('N'), 11, "^N", N_("Next Printer")},
107
/* TRANSLATORS: use Custom Print command */
108
{'c', 'c', "C", N_("CustomPrint")},
109
{KEY_UP, 10, "", ""},
110
{KEY_DOWN, 11, "", ""},
111
{-1, 0, NULL, NULL}};
121
command[sizeof(command)-1] = '\0';
123
if(ps_global->VAR_PRINTER == NULL){
124
q_status_message(SM_ORDER | SM_DING, 3, 5,
125
"No printer has been chosen. Use SETUP on main menu to make choice.");
129
/* Is there just one print command available? */
130
just_one = (ps_global->printer_category!=3&&ps_global->printer_category!=2)
131
|| (ps_global->printer_category == 2
132
&& !(ps_global->VAR_STANDARD_PRINTER
133
&& ps_global->VAR_STANDARD_PRINTER[0]
134
&& ps_global->VAR_STANDARD_PRINTER[1]))
135
|| (ps_global->printer_category == 3
136
&& !(ps_global->VAR_PERSONAL_PRINT_COMMAND
137
&& ps_global->VAR_PERSONAL_PRINT_COMMAND[0]
138
&& ps_global->VAR_PERSONAL_PRINT_COMMAND[1]));
140
if(F_ON(F_CUSTOM_PRINT, ps_global))
141
ekey[CUSTOM_KEY].ch = 'c'; /* turn this key on */
143
ekey[CUSTOM_KEY].ch = -2; /* turn this key off */
146
ekey[PREV_KEY].ch = -2; /* turn these keys off */
147
ekey[NEXT_KEY].ch = -2;
148
ekey[UP_KEY].ch = -2;
149
ekey[DOWN_KEY].ch = -2;
152
ekey[PREV_KEY].ch = ctrl('P'); /* turn these keys on */
153
ekey[NEXT_KEY].ch = ctrl('N');
154
ekey[UP_KEY].ch = KEY_UP;
155
ekey[DOWN_KEY].ch = KEY_DOWN;
157
* count how many printers in list and find the default in the list
159
if(ps_global->printer_category == 2)
160
list = ps_global->VAR_STANDARD_PRINTER;
162
list = ps_global->VAR_PERSONAL_PRINT_COMMAND;
164
for(i = 0; list[i]; i++)
165
if(strcmp(ps_global->VAR_PRINTER, list[i]) == 0)
172
ps_global->mangled_footer = 1;
176
fs_give((void **)&init);
179
fs_give((void **)&trailer);
182
printer = ps_global->VAR_PRINTER;
184
printer = list[cur_printer];
186
parse_printer(printer, &nick, &p, &init, &trailer, NULL, NULL);
187
strncpy(command, p, sizeof(command)-1);
188
command[sizeof(command)-1] = '\0';
189
fs_give((void **)&p);
190
/* TRANSLATORS: Print something1 using something2.
191
For example, Print configuration using printer three. */
192
snprintf(prompt, sizeof(prompt), _("Print %s using \"%s\" ? "),
194
*nick ? nick : command);
195
prompt[sizeof(prompt)-1] = '\0';
197
fs_give((void **)&nick);
199
cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global),
200
ekey, 'y', 'x', help, RB_NORM);
204
q_status_message1(SM_ORDER, 0, 9,
205
"Printing with command \"%s\"", command);
210
cur_printer = (cur_printer>0)
216
cur_printer = (cur_printer<lastprinter)
237
fs_give((void **)&init);
240
fs_give((void **)&trailer);
242
snprintf(prompt, sizeof(prompt), "Enter custom command : ");
243
prompt[sizeof(prompt)-1] = '\0';
248
int flags = OE_APPEND_CURRENT;
250
rc = optionally_enter(command, -FOOTER_ROWS(ps_global), 0,
251
sizeof(command), prompt, NULL, help, &flags);
258
help = (help == NO_HELP) ? h_custom_print : NO_HELP;
260
removing_trailing_white_space(command);
261
removing_leading_white_space(command);
262
q_status_message1(SM_ORDER, 0, 9,
263
"Printing with command \"%s\"", command);
268
if(cmd == 'x' || cmd == 'n'){
269
q_status_message(SM_ORDER, 0, 2, "Print cancelled");
271
fs_give((void **)&init);
274
fs_give((void **)&trailer);
279
display_message('x');
281
ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
282
memset(ps_global->print, 0, sizeof(PRINT_S));
284
strncat(strncpy(aname, ANSI_PRINTER, 50), "-no-formfeed", 30);
285
strncat(strncpy(wname, WYSE_PRINTER, 50), "-no-formfeed", 30);
286
if(strucmp(command, ANSI_PRINTER) == 0
287
|| strucmp(command, aname) == 0
288
|| strucmp(command, WYSE_PRINTER) == 0
289
|| strucmp(command, wname) == 0){
290
/*----------- Attached printer ---------*/
291
q_status_message(SM_ORDER, 0, 9,
292
"Printing to attached desktop printer...");
293
display_message('x');
294
xonxoff_proc(1); /* make sure XON/XOFF used */
295
crlf_proc(1); /* AND LF->CR xlation */
296
if(strucmp(command, ANSI_PRINTER) == 0
297
|| strucmp(command, aname) == 0){
298
fputs("\033[5i", stdout);
303
printf("%c", 18); /* aux on for wyse60,
304
Chuck Everett <ceverett@odessa.edu> */
307
ps_global->print->fp = stdout;
308
if(strucmp(command, ANSI_PRINTER) == 0
309
|| strucmp(command, WYSE_PRINTER) == 0){
310
/* put formfeed at the end of the trailer string */
312
int len = strlen(trailer);
314
fs_resize((void **)&trailer, len+2);
316
trailer[len+1] = '\0';
319
trailer = cpystr("\f");
323
/*----------- Print by forking off a UNIX command ------------*/
324
dprint((4, "Printing using command \"%s\"\n",
325
command ? command : "?"));
326
ps_global->print->result = temp_nam(NULL, "pine_prt", 0);
327
if(ps_global->print->result &&
328
(ps_global->print->pipe = open_system_pipe(command,
329
&ps_global->print->result, NULL,
330
PIPE_WRITE | PIPE_STDERR, 0,
331
pipe_callback, NULL))){
332
ps_global->print->fp = ps_global->print->pipe->out.f;
335
if(ps_global->print->result){
336
our_unlink(ps_global->print->result);
337
fs_give((void **)&ps_global->print->result);
340
q_status_message1(SM_ORDER | SM_DING, 3, 4,
341
"Error opening printer: %s",
342
error_description(errno));
343
dprint((2, "Error popening printer \"%s\"\n",
344
error_description(errno)));
346
fs_give((void **)&init);
349
fs_give((void **)&trailer);
355
ps_global->print->err = 0;
358
fputs(init, ps_global->print->fp);
360
fs_give((void **)&init);
368
LPTSTR desclpt = NULL;
371
desclpt = utf8_to_lptstr(desc);
373
if (status = mswin_print_ready (0, desclpt)) {
374
q_status_message1(SM_ORDER | SM_DING, 3, 4,
375
"Error starting print job: %s",
376
mswin_print_error(status));
378
fs_give((void **) &desclpt);
384
fs_give((void **) &desclpt);
386
q_status_message(SM_ORDER, 0, 9, "Printing to windows printer...");
387
display_message('x');
389
/* init print control structure */
390
ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
391
memset(ps_global->print, 0, sizeof(PRINT_S));
393
ps_global->print->err = 0;
394
#endif /* _WINDOWS */
401
/*----------------------------------------------------------------------
404
If we're piping to a spooler close down the pipe and wait for the process
405
to finish. If we're sending to an attached printer send the escape sequence.
406
Also let the user know the result of the print
414
fputs(trailer, ps_global->print->fp);
416
fs_give((void **)&trailer);
419
if(ps_global->print->fp == stdout) {
421
fputs("\033[4i", stdout);
423
printf("%c", 20); /* aux off for wyse60 */
426
if(F_OFF(F_PRESERVE_START_STOP, ps_global))
427
xonxoff_proc(0); /* turn off XON/XOFF */
429
crlf_proc(0); /* turn off CF->LF xlantion */
431
(void) close_system_pipe(&ps_global->print->pipe, NULL, 0);
432
display_output_file(ps_global->print->result, "PRINT", NULL, 1);
433
fs_give((void **)&ps_global->print->result);
437
#endif /* _WINDOWS */
439
fs_give((void **)&ps_global->print);
441
q_status_message(SM_ASYNC, 0, 3, "Print command completed");
442
display_message('x');
446
/*----------------------------------------------------------------------
447
Print a single character, translate from UTF-8 to user's locale charset.
449
Args: c -- char to print
450
Returns: 1 on success, 0 on ps_global->print->err
458
unsigned char obuf[MAX(MB_LEN_MAX,32)];
460
if(!ps_global->print->err
461
&& (outchars = utf8_to_locale(c, cbuf, sizeof(cbuf), &cbufp, obuf, sizeof(obuf)))){
462
for(i = 0; i < outchars && !ps_global->print->err; i++)
463
if(putc(obuf[i], ps_global->print->fp) == EOF)
464
ps_global->print->err = 1;
467
if(!ps_global->print->err
468
&& (ps_global->print->err = mswin_print_char_utf8(c)))
469
q_status_message1(SM_ORDER, 0, 9, "Print cancelled: %s",
470
mswin_print_error((unsigned short)ps_global->print->err));
471
#endif /* _WINDOWS */
473
return(!ps_global->print->err);
477
/*----------------------------------------------------------------------
478
Send a line of text to the printer
480
Args: line -- Text to print
484
print_text(char *line)
487
int slen = strlen(line);
489
while(!ps_global->print->err && slen--)
490
if(print_char(*line++) == 0)
491
ps_global->print->err = 1;
493
if(!ps_global->print->err
494
&& (ps_global->print->err = mswin_print_text_utf8(line)))
495
q_status_message1(SM_ORDER, 0, 9, "Print cancelled: %s",
496
mswin_print_error((unsigned short)ps_global->print->err));
497
#endif /* _WINDOWS */
501
/*----------------------------------------------------------------------
502
printf style formatting with one arg for printer
504
Args: line -- The printf control string
505
a1 -- The 1st argument for printf
508
print_text1(char *line, char *a1)
512
if(!ps_global->print->err && snprintf(buf, sizeof(buf), line, a1) < 0)
513
ps_global->print->err = 1;