~ubuntu-branches/debian/stretch/alpine/stretch

« back to all changes in this revision

Viewing changes to alpine/osdep/print.c

  • Committer: Bazaar Package Importer
  • Author(s): Asheesh Laroia
  • Date: 2007-02-17 13:17:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070217131742-99x5c6cpg1pbkdhw
Tags: upstream-0.82+dfsg
ImportĀ upstreamĀ versionĀ 0.82+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if !defined(lint) && !defined(DOS)
 
2
static char rcsid[] = "$Id: print.c 254 2006-11-21 21:54:24Z hubert@u.washington.edu $";
 
3
#endif
 
4
 
 
5
/*
 
6
 * ========================================================================
 
7
 * Copyright 2006 University of Washington
 
8
 *
 
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
 
12
 *
 
13
 *     http://www.apache.org/licenses/LICENSE-2.0
 
14
 *
 
15
 * ========================================================================
 
16
 */
 
17
#include <system.h>
 
18
#include <general.h>
 
19
 
 
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"
 
26
 
 
27
#include "../../pith/charconv/utf8.h"
 
28
#include "../../pith/charconv/filesys.h"
 
29
 
 
30
#include "../../pith/osdep/color.h"
 
31
#include "../../pith/osdep/temp_nam.h"
 
32
#include "../../pith/osdep/err_desc.h"
 
33
 
 
34
#include "../../pith/debug.h"
 
35
#include "../../pith/conf.h"
 
36
#include "../../pith/store.h"
 
37
 
 
38
#include "../../pico/estruct.h" /* for ctrl() */
 
39
#include "../../pico/keydefs.h" /* for KEY_* */
 
40
 
 
41
#include "../status.h"
 
42
#include "../signal.h"
 
43
#include "../radio.h"
 
44
 
 
45
#ifdef _WINDOWS
 
46
#include "../../pico/osdep/mswin.h"
 
47
#endif
 
48
 
 
49
#include "print.h"
 
50
 
 
51
 
 
52
/*======================================================================
 
53
    print routines
 
54
   
 
55
    Functions having to do with printing on paper and forking of spoolers
 
56
 
 
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.
 
62
 
 
63
 ====*/
 
64
 
 
65
 
 
66
 
 
67
#ifndef _WINDOWS
 
68
static char *trailer;  /* so both open and close_printer can see it */
 
69
static int   ansi_off;
 
70
static unsigned char  cbuf[6];
 
71
static unsigned char *cbufp;
 
72
static unsigned char *cbufend;
 
73
#endif /* !_WINDOWS */
 
74
 
 
75
 
 
76
/*----------------------------------------------------------------------
 
77
       Open the printer
 
78
 
 
79
  Args: desc -- Description of item to print. Should have one trailing blank.
 
80
 
 
81
  Return value: < 0 is a failure.
 
82
                0 a success.
 
83
 
 
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.
 
86
  ----*/
 
87
int
 
88
open_printer(char *desc)
 
89
{
 
90
#ifndef _WINDOWS
 
91
    char command[201], prompt[200];
 
92
    int  cmd, rc, just_one;
 
93
    char *p, *init, *nick;
 
94
    char aname[100], wname[100];
 
95
    char *printer;
 
96
    int  done = 0, i, lastprinter, cur_printer = 0;
 
97
    HelpType help;
 
98
    char   **list;
 
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")},
 
106
        {-2,   0,   NULL, NULL},
 
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}};
 
112
#define PREV_KEY   2
 
113
#define NEXT_KEY   3
 
114
#define CUSTOM_KEY 5
 
115
#define UP_KEY     6
 
116
#define DOWN_KEY   7
 
117
 
 
118
    trailer      = NULL;
 
119
    init         = NULL;
 
120
    nick         = NULL;
 
121
    command[sizeof(command)-1] = '\0';
 
122
 
 
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.");
 
126
        return(-1);
 
127
    }
 
128
 
 
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]));
 
139
 
 
140
    if(F_ON(F_CUSTOM_PRINT, ps_global))
 
141
      ekey[CUSTOM_KEY].ch = 'c'; /* turn this key on */
 
142
    else
 
143
      ekey[CUSTOM_KEY].ch = -2;  /* turn this key off */
 
144
 
 
145
    if(just_one){
 
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;
 
150
    }
 
151
    else{
 
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;
 
156
        /*
 
157
         * count how many printers in list and find the default in the list
 
158
         */
 
159
        if(ps_global->printer_category == 2)
 
160
          list = ps_global->VAR_STANDARD_PRINTER;
 
161
        else
 
162
          list = ps_global->VAR_PERSONAL_PRINT_COMMAND;
 
163
 
 
164
        for(i = 0; list[i]; i++)
 
165
          if(strcmp(ps_global->VAR_PRINTER, list[i]) == 0)
 
166
            cur_printer = i;
 
167
        
 
168
        lastprinter = i - 1;
 
169
    }
 
170
 
 
171
    help = NO_HELP;
 
172
    ps_global->mangled_footer = 1;
 
173
 
 
174
    while(!done){
 
175
        if(init)
 
176
          fs_give((void **)&init);
 
177
 
 
178
        if(trailer)
 
179
          fs_give((void **)&trailer);
 
180
 
 
181
        if(just_one)
 
182
          printer = ps_global->VAR_PRINTER;
 
183
        else
 
184
          printer = list[cur_printer];
 
185
 
 
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\" ? "),
 
193
                desc ? desc : "",
 
194
                *nick ? nick : command);
 
195
        prompt[sizeof(prompt)-1] = '\0';
 
196
 
 
197
        fs_give((void **)&nick);
 
198
        
 
199
        cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global),
 
200
                                 ekey, 'y', 'x', help, RB_NORM);
 
201
        
 
202
        switch(cmd){
 
203
          case 'y':
 
204
            q_status_message1(SM_ORDER, 0, 9,
 
205
                "Printing with command \"%s\"", command);
 
206
            done++;
 
207
            break;
 
208
 
 
209
          case 10:
 
210
            cur_printer = (cur_printer>0)
 
211
                                ? (cur_printer-1)
 
212
                                : lastprinter;
 
213
            break;
 
214
 
 
215
          case 11:
 
216
            cur_printer = (cur_printer<lastprinter)
 
217
                                ? (cur_printer+1)
 
218
                                : 0;
 
219
            break;
 
220
 
 
221
          case 'n':
 
222
          case 'x':
 
223
            done++;
 
224
            break;
 
225
 
 
226
          case 'c':
 
227
            done++;
 
228
            break;
 
229
 
 
230
          default:
 
231
            break;
 
232
        }
 
233
    }
 
234
 
 
235
    if(cmd == 'c'){
 
236
        if(init)
 
237
          fs_give((void **)&init);
 
238
 
 
239
        if(trailer)
 
240
          fs_give((void **)&trailer);
 
241
 
 
242
        snprintf(prompt, sizeof(prompt), "Enter custom command : ");
 
243
        prompt[sizeof(prompt)-1] = '\0';
 
244
        command[0] = '\0';
 
245
        rc = 1;
 
246
        help = NO_HELP;
 
247
        while(rc){
 
248
            int flags = OE_APPEND_CURRENT;
 
249
 
 
250
            rc = optionally_enter(command, -FOOTER_ROWS(ps_global), 0,
 
251
                sizeof(command), prompt, NULL, help, &flags);
 
252
            
 
253
            if(rc == 1){
 
254
                cmd = 'x';
 
255
                rc = 0;
 
256
            }
 
257
            else if(rc == 3)
 
258
              help = (help == NO_HELP) ? h_custom_print : NO_HELP;
 
259
            else if(rc == 0){
 
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);
 
264
            }
 
265
        }
 
266
    }
 
267
 
 
268
    if(cmd == 'x' || cmd == 'n'){
 
269
        q_status_message(SM_ORDER, 0, 2, "Print cancelled");
 
270
        if(init)
 
271
          fs_give((void **)&init);
 
272
 
 
273
        if(trailer)
 
274
          fs_give((void **)&trailer);
 
275
 
 
276
        return(-1);
 
277
    }
 
278
 
 
279
    display_message('x');
 
280
 
 
281
    ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
 
282
    memset(ps_global->print, 0, sizeof(PRINT_S));
 
283
 
 
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);
 
299
            ansi_off = 1;
 
300
        }
 
301
        else{
 
302
            ansi_off = 0;
 
303
            printf("%c", 18); /* aux on for wyse60,
 
304
                                 Chuck Everett <ceverett@odessa.edu> */
 
305
        }
 
306
 
 
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 */
 
311
            if(trailer){
 
312
                int len = strlen(trailer);
 
313
 
 
314
                fs_resize((void **)&trailer, len+2);
 
315
                trailer[len] = '\f';
 
316
                trailer[len+1] = '\0';
 
317
            }
 
318
            else
 
319
              trailer = cpystr("\f");
 
320
        }
 
321
    }
 
322
    else{
 
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;
 
333
        }
 
334
        else{
 
335
            if(ps_global->print->result){
 
336
                our_unlink(ps_global->print->result);
 
337
                fs_give((void **)&ps_global->print->result);
 
338
            }
 
339
 
 
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)));
 
345
            if(init)
 
346
              fs_give((void **)&init);
 
347
 
 
348
            if(trailer)
 
349
              fs_give((void **)&trailer);
 
350
            
 
351
            return(-1);
 
352
        }
 
353
    }
 
354
 
 
355
    ps_global->print->err = 0;
 
356
    if(init){
 
357
        if(*init)
 
358
          fputs(init, ps_global->print->fp);
 
359
 
 
360
        fs_give((void **)&init);
 
361
    }
 
362
 
 
363
    cbuf[0] = '\0';
 
364
    cbufp   = cbuf;
 
365
    cbufend = cbuf;
 
366
#else /* _WINDOWS */
 
367
    int status;
 
368
    LPTSTR desclpt = NULL;
 
369
 
 
370
    if(desc)
 
371
      desclpt = utf8_to_lptstr(desc);
 
372
 
 
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));
 
377
        if(desclpt)
 
378
          fs_give((void **) &desclpt);
 
379
 
 
380
        return(-1);
 
381
    }
 
382
 
 
383
    if(desclpt)
 
384
      fs_give((void **) &desclpt);
 
385
 
 
386
    q_status_message(SM_ORDER, 0, 9, "Printing to windows printer...");
 
387
    display_message('x');
 
388
 
 
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));
 
392
 
 
393
    ps_global->print->err = 0;
 
394
#endif /* _WINDOWS */
 
395
 
 
396
    return(0);
 
397
}
 
398
 
 
399
 
 
400
 
 
401
/*----------------------------------------------------------------------
 
402
     Close printer
 
403
  
 
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
 
407
 ----*/
 
408
void
 
409
close_printer(void)
 
410
{
 
411
#ifndef _WINDOWS
 
412
    if(trailer){
 
413
        if(*trailer)
 
414
          fputs(trailer, ps_global->print->fp);
 
415
 
 
416
        fs_give((void **)&trailer);
 
417
    }
 
418
 
 
419
    if(ps_global->print->fp == stdout) {
 
420
        if(ansi_off)
 
421
          fputs("\033[4i", stdout);
 
422
        else
 
423
          printf("%c", 20); /* aux off for wyse60 */
 
424
 
 
425
        fflush(stdout);
 
426
        if(F_OFF(F_PRESERVE_START_STOP, ps_global))
 
427
          xonxoff_proc(0);                      /* turn off XON/XOFF */
 
428
 
 
429
        crlf_proc(0);                           /* turn off CF->LF xlantion */
 
430
    } else {
 
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);
 
434
    }
 
435
#else /* _WINDOWS */
 
436
    mswin_print_done();
 
437
#endif /* _WINDOWS */
 
438
 
 
439
    fs_give((void **)&ps_global->print);
 
440
 
 
441
    q_status_message(SM_ASYNC, 0, 3, "Print command completed");
 
442
    display_message('x');
 
443
}
 
444
 
 
445
 
 
446
/*----------------------------------------------------------------------
 
447
     Print a single character, translate from UTF-8 to user's locale charset.
 
448
 
 
449
  Args: c -- char to print
 
450
  Returns: 1 on success, 0 on ps_global->print->err
 
451
 ----*/
 
452
int
 
453
print_char(int c)
 
454
{
 
455
#ifndef _WINDOWS
 
456
    int rv = 1;
 
457
    int i, outchars;
 
458
    unsigned char obuf[MAX(MB_LEN_MAX,32)];
 
459
 
 
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;
 
465
    }
 
466
#else /* _WINDOWS */
 
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 */
 
472
 
 
473
    return(!ps_global->print->err);
 
474
}
 
475
 
 
476
 
 
477
/*----------------------------------------------------------------------
 
478
     Send a line of text to the printer
 
479
 
 
480
  Args:  line -- Text to print
 
481
 
 
482
  ----*/
 
483
void
 
484
print_text(char *line)
 
485
{
 
486
#ifndef _WINDOWS
 
487
    int slen = strlen(line);
 
488
 
 
489
    while(!ps_global->print->err && slen--)
 
490
      if(print_char(*line++) == 0)
 
491
        ps_global->print->err = 1;
 
492
#else /* _WINDOWS */
 
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 */
 
498
}
 
499
 
 
500
 
 
501
/*----------------------------------------------------------------------
 
502
      printf style formatting with one arg for printer
 
503
 
 
504
 Args: line -- The printf control string
 
505
       a1   -- The 1st argument for printf
 
506
 ----*/
 
507
void
 
508
print_text1(char *line, char *a1)
 
509
{
 
510
    char buf[64000];
 
511
 
 
512
    if(!ps_global->print->err && snprintf(buf, sizeof(buf), line, a1) < 0)
 
513
      ps_global->print->err = 1;
 
514
    else
 
515
      print_text(buf);
 
516
}