#if !defined(lint) && !defined(DOS)
static char rcsid[] = "$Id: print.c,v 4.21 1994/10/05 18:37:55 mikes Exp $";
#endif
/*----------------------------------------------------------------------

            T H E    P I N E    M A I L   S Y S T E M

   Laurence Lundblade and Mike Seibel
   Networks and Distributed Computing
   Computing and Communications
   University of Washington
   Administration Builiding, AG-44
   Seattle, Washington, 98195, USA
   Internet: lgl@CAC.Washington.EDU
             mikes@CAC.Washington.EDU

   Please address all bugs and comments to "pine-bugs@cac.washington.edu"

   Copyright 1989-1994  University of Washington

    Permission to use, copy, modify, and distribute this software and its
   documentation for any purpose and without fee to the University of
   Washington is hereby granted, provided that the above copyright notice
   appears in all copies and that both the above copyright notice and this
   permission notice appear in supporting documentation, and that the name
   of the University of Washington not be used in advertising or publicity
   pertaining to distribution of the software without specific, written
   prior permission.  This software is made available "as is", and
   THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
   WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
   NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
   (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
   WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
   Pine and Pico are trademarks of the University of Washington.
   No commercial use of these trademarks may be made without prior
   written permission of the University of Washington.

   Pine is in part based on The Elm Mail System:
    ***********************************************************************
    *  The Elm Mail System  -  Revision: 2.13                             *
    *                                                                     *
    * 			Copyright (c) 1986, 1987 Dave Taylor              *
    * 			Copyright (c) 1988, 1989 USENET Community Trust   *
    ***********************************************************************
 

  ----------------------------------------------------------------------*/

/*======================================================================
    print.c
   
    Functions having to do with printing on paper and forking of spoolers

    In general one calls open_printer() to start printing. One of
    the little print functions to send a line or string, and then
    call print_end() when complete. This takes care of forking offa spooler
    and piping the stuff down it. No handles or anything here because there's
    only one printer open at a time.

 ====*/

#include "headers.h"
#ifndef	DOS
FILE   *fdopen(); 
FILE   *command_pipe;
char   *outputsave;
PIPE_S *print_pipe = NULL;
#else

#ifdef	ANSI
int	  send_printer(char);				/* Prototypes */
unsigned  short printer_ready();
char     *p_printer_error(unsigned short);
#endif
#endif

static int   write_error;


#define WTR 1
#define RDR 0


/*----------------------------------------------------------------------
       Open the printer

  Args: desc --Description of item to print. Should have on tailing blank.

This does most of the work of popen so we can save the standard output of the
command we execute and send it back to the user.
  ----*/
open_printer(desc)
     char *desc;
{
#ifdef	DOS
    char           prompt[100];
    unsigned short status;
    
#ifndef _WINDOWS

    if(status = printer_ready()){		/* 0 means things are OK */
        q_status_message1(0, 2, 4, "\007Error opening printer: %s",
                              p_printer_error(status));
	write_error = 1;	/* just in case */
        return(-1);
    }

    sprintf(prompt, "Print %sto desktop printer", desc == NULL ? "" : desc);
    if(want_to(prompt, 'y', 'n', NO_HELP, 0, 0) == 'n') {
	q_status_message(0, 0, 2, "Print cancelled");
	return(-1);
    }
    q_status_message(1, 2, 3,"Printing to desktop printer...");
    display_message('x');
    
#else
    /* Windows printing. */
    if (status = mswin_print_ready (desc)) {
        q_status_message1(0, 2, 4, "\007Error starting print job: %s",
                              mswin_print_error(status));
	write_error = 1;	/* just in case */
        return(-1);
    }
    q_status_message(1, 0, 3,"Printing to windows printer...");
    display_message('x');
#endif /* _WINDOWS */

#else
    char command[100], prompt[100];
    int  p[2];

    if(ps_global->VAR_PRINTER == NULL) {
        q_status_message(1, 1, 3,
    "\007No printer has been chosen.  Use SETUP on main menu to make choice.");
        return(-1);
    }
    outputsave = fs_get(40) ;
#ifdef VMS
    sprintf(outputsave, "SYS$SCRATCH:pine-print-output-%d.", getpid());
#else	/* VMS */
    sprintf(outputsave, "/tmp/pine-print-output-%d", getpid());
#endif	/* VMS */

    /*========= Sort out the printer command ==========*/
    if(strucmp(ps_global->VAR_PRINTER, ANSI_PRINTER) == 0) {
        /*---------- Print on an attatched ascii printer --------*/
        command[0] = '\0';
        sprintf(prompt, "Print %susing \"%s\"",desc == NULL ? "" : desc,
                ps_global->VAR_PRINTER);
        if(want_to(prompt, 'y', 'n', (char **)NULL, 0, 0) == 'n') {
            q_status_message(0, 0, 2, "Print cancelled");
            return(-1);
        }
    } else {
        
        /*------- custom configuration ------*/
        sprintf(prompt, "Print %susing command \"%s\"", desc==NULL ? "" : desc,
                ps_global->VAR_PRINTER);
        if(want_to(prompt, 'y', 'n', (char **)NULL, 0, 0) == 'n') {
            q_status_message(0, 0, 2, "Print cancelled");
            return(-1);
        }
        strcpy(command, ps_global->VAR_PRINTER);
        q_status_message1(1, 1, 3, "Printing with command \"%s\"",
                          ps_global->VAR_PRINTER);
    }

    display_message('x');

    if(command[0] == '\0') {
        /*----------- Printer attached to ansi device ---------*/
        q_status_message(1, 2, 3,"Printing to attached desktop printer...");
        display_message('x');
        sleep(1);
        Raw(0);
        fputs("\033[5i", stdout);
        command_pipe = stdout;
    } else {
        /*----------- Print by forking off a UNIX command ------------*/
#ifdef VMS
	print_pipe = (PIPE_S *)fs_get(sizeof(PIPE_S));
	memset(print_pipe, 0, sizeof(PIPE_S));
	if((print_pipe->ifile = fopen(outputsave, "w")) == NULL) {
            q_status_message1(1, 2, 4, "\007Error opening temporary file: %s",
                              error_description(errno));
            dprint(2, (debugfile, "Error opening popening file \"%s\"\n",
                      error_description(errno)));
            return(-1);
        }
	command_pipe = print_pipe->ifile;
#else	/* VMS */
	print_pipe = open_system_pipe(ps_global->VAR_PRINTER, 
				      &outputsave, PIPE_SYS) ;
        dprint(4, (debugfile, "Printing using command \"%s\"\n",
                                              ps_global->VAR_PRINTER));
	if(print_pipe){
	    command_pipe = print_pipe->ifile;
	}
	else{
            q_status_message1(1, 2, 4, "\007Error opening printer: %s",
                              error_description(errno));
            dprint(2, (debugfile, "Error opening popening printer \"%s\"\n",
                      error_description(errno)));
            return(-1);
        }
#endif	/* VMS */
    }
#endif
    write_error = 0;
    return(0);
}



/*----------------------------------------------------------------------
     Close printer
  
  If we're piping to a spooler close down the pipe and wait for the process
to finish. If we're sending to an attached printer send the escape sequence.
Also let the user know the result of the print
 ----*/
void close_printer()
{
#ifdef	DOS
#ifndef _WINDOWS
    print_char(FORMFEED);
#else
    mswin_print_done ();
#endif
#else
    int   status ;
  
    if(command_pipe == stdout) {
        fputs("\f\033[4i", stdout);
        fflush(stdout);
        Raw(1);
    } else {
#ifdef VMS
	char	PrintCommand[512];
	fclose(print_pipe->ifile);
	sprintf(PrintCommand, "%s/DELETE %s", ps_global->VAR_PRINTER, 
		outputsave);
	system(PrintCommand);
#else	/* VMS */
	status = close_system_pipe(&print_pipe, PIPE_SYS);
	display_system_pipe_output(outputsave, "PRINT") ;
#endif	/* VMS */
    }
#endif	/* !DOS */

    q_status_message(0, 0, 3, "Print command completed");
    display_message('x');
}



/*----------------------------------------------------------------------
     Print a single character

  Args: c -- char to print
  Returns: 1 on success, 0 on write_error
 ----*/
int
print_char(c)
     int c;
{
#ifdef	DOS
#ifndef _WINDOWS
    if(!write_error)
	if(write_error = send_printer((char) c)){
            q_status_message1(0, 2, 4, "Print cancelled: %s",
                              p_printer_error((unsigned short)write_error));
	}
#else
    if(!write_error)
	if(write_error = mswin_print_char (c)) {
            q_status_message1(0, 2, 4, "Print cancelled: %s",
                              mswin_print_error((unsigned short)write_error));
	}
#endif /* _WINDOWS */		
#else
    if(write_error)
      return(0);
    if(putc(c, command_pipe) == EOF)
      write_error = 1;
#endif	/* DOS */
    return(!write_error);
}



/*----------------------------------------------------------------------
     Send a line of text to the printer

  Args:  line -- Text to print

  ----*/
    
void print_text(line)
     char *line;
{
#ifdef	DOS
#ifndef _WINDOWS
    register char *c = line;

    while(*c != '\0' && !write_error)
      print_char(*c++);
#else
    if(!write_error)
	if(write_error = mswin_print_text (line)) {
            q_status_message1(0, 2, 4, "Print cancelled: %s",
                              mswin_print_error((unsigned short)write_error));
	}
#endif
#else
    if(write_error)
      return;
    if(fputs(line, command_pipe) == EOF)
      write_error = 1;
#endif	/* DOS */
}


/*----------------------------------------------------------------------
      printf style formatting with one arg for printer

 Args: line -- The printf control string
       a1   -- The 1st argument for printf
 ----*/

void print_text1(line, a1)
     char *line, *a1;
{
#ifdef	DOS
    sprintf(tmp_20k_buf, line, a1);
    print_text(tmp_20k_buf);
#else
    if(write_error)
      return;
    if(fprintf(command_pipe, line, a1) < 0)
      write_error = 1;
#endif
}


/*----------------------------------------------------------------------
      printf style formatting with one arg for printer

 Args: line -- The printf control string
       a1   -- The 1st argument for printf
       a2   -- The 2nd argument for printf
 ----*/

void print_text2(line, a1, a2)
     char *line, *a1, *a2;
{
#ifdef	DOS
    sprintf(tmp_20k_buf, line, a1, a2);
    print_text(tmp_20k_buf);
#else
    if(write_error)
      return;
    if(fprintf(command_pipe, line, a1, a2) < 0)
      write_error = 1;
#endif
}


/*----------------------------------------------------------------------
      printf style formatting with one arg for printer

 Args: line -- The printf control string
       a1   -- The 1st argument for printf
       a2   -- The 2nd argument for printf
       a3   -- The 3rd argument for printf
 ----*/

void print_text3(line, a1, a2, a3)
     char *line, *a1, *a2, *a3;
{
#ifdef	DOS
    sprintf(tmp_20k_buf, line, a1, a2, a3);
    print_text(tmp_20k_buf);
#else
    if(write_error)
      return;
    if(fprintf(command_pipe, line, a1, a2, a3)< 0)
      write_error = 1;
#endif
}
