#include "HTUtils.h"
#include "tcp.h"
#include "HTAlert.h"
#include "LYCurses.h"
#include "HTAccess.h"
#include "GridText.h"
#include "LYUtils.h"
#include "LYPrint.h"
#include "LYGlobalDefs.h"
#include "LYSignal.h"
#include "LYStrings.h"
#include "LYClean.h"
#include "LYGetFile.h"
#include "LYHistory.h"
#include "LYSystem.h"
#include "LYList.h"
#ifdef VMS
#include "HTVMSUtils.h"
#endif /* VMS */

#include "LYLeaks.h"

#define FREE(x) if (x) {free(x); x = NULL;}

/*
 *  printfile prints out the current file minus the links and targets 
 *  to a veriaty of places
 */

/* it parses an incoming link that looks like
 *
 *  LYNXPRINT://LOCAL_FILE/lines=##
 *  LYNXPRINT://MAIL_FILE/lines=##
 *  LYNXPRINT://TO_SCREEN/lines=##
 *  LYNXPRINT://PRINTER/lines=##/number=#
 */

#define TO_FILE   1
#define TO_SCREEN 2
#define MAIL      3
#define PRINTER   4

#ifdef VMS
PRIVATE int remove_quotes PARAMS((char *string));
#endif /* VMS */

PUBLIC int printfile ARGS1(document *,newdoc) 
{
    static char * tempfile=NULL;
    char buffer[LINESIZE];
    char filename[LINESIZE];
    char user_response[256];
    int lines_in_file=0;
    int printer_number=0;
    int pages=0;
    int type=0, c, len;
    FILE *outfile_fp;
    char *cp;
    lynx_printer_item_type *cur_printer;
    char *sug_filename = NULL;
    char *link_info = NULL;
    DocAddress WWWDoc;
    int pagelen=0;
#ifdef VMS
    extern BOOLEAN HadVMSInterrupt;
#endif /* VMS */

    /* extract useful info from URL */
    StrAllocCopy(link_info,newdoc->address+12);

	/* reload the file we want to print into memory */
    LYpop(newdoc);
    WWWDoc.address = newdoc->address;
    WWWDoc.post_data = newdoc->post_data;
    WWWDoc.post_content_type = newdoc->post_content_type;
    WWWDoc.isHEAD = newdoc->isHEAD;
    if(!HTLoadAbsolute(&WWWDoc))
        return(NOT_FOUND);
  
    StrAllocCopy(sug_filename, newdoc->address); /* must be freed */

    /* get the number of lines in the file */
    if((cp = (char *)strstr(link_info, "lines=")) != NULL) {
	/* terminate prev string here */
	*cp = '\0';
        /* number of charters in lines=  */
	cp += 6;

        lines_in_file = atoi(cp);
	pages = lines_in_file/66;
    }
	

    /* determine the type */
    if(strstr(link_info, "LOCAL_FILE")) {
	type = TO_FILE;
    } else if(strstr(link_info, "TO_SCREEN")) {
	type = TO_SCREEN;
    } else if(strstr(link_info, "MAIL_FILE")) {
	type = MAIL;
    } else if(strstr(link_info, "PRINTER")) {
	type = PRINTER;

        if((cp = (char *)strstr(link_info, "number=")) != NULL) {
            /* number of charters in number=  */
            cp += 7;
            printer_number = atoi(cp);
        }
        if((cp = (char *)strstr(link_info, "pagelen=")) != NULL) {
            /* page length */
            cp += 8;
	    pagelen = atoi(cp);
        } else {
            /* default to 66 lines */
            pagelen = 66;
        }
    }


    switch(type) {
	case TO_FILE:
		_statusline("Please enter a file name: ");
	retry:	strcpy(filename, sug_filename);  /* add suggestion info */
		/* make the sug_filename conform to system specs */
		change_sug_filename(filename);
		if ((len = strlen(filename)) > 4) {
		    len -= 5;
		    if (!strcasecomp((filename + len), ".html")) {
		        filename[len] = '\0';
			strcat(filename, ".txt");
		    }
		}
		if (lynx_save_space && *lynx_save_space) {
		    strcpy(buffer, lynx_save_space);
		    strcat(buffer, filename);
		    strcpy(filename, buffer);
		}
		if (LYgetstr(filename, VISIBLE,
			     sizeof(filename), NORECALL) < 0 ||
		    *filename == '\0') {
                     _statusline("Save request cancelled!!!");
                     sleep(InfoSecs);
		     break;
                }

		if (no_dotfiles || !show_dotfiles) {
		    char *cp;

		    if (*filename == '.' ||
#ifdef VMS
			((cp = strrchr(filename, ':')) && *(cp+1) == '.') ||
			((cp = strrchr(filename, ']')) && *(cp+1) == '.') ||
#endif /* VMS */
			((cp = strrchr(filename, '/')) && *(cp+1) == '.')) {
			_statusline("File name may not begin with dot. Enter a new file name: ");
			goto retry;
		    }
		}
		if ((cp = strchr(filename, '~'))) {
		    *(cp++) = '\0';
		    strcpy(buffer, filename);
		    if ((len=strlen(buffer)) > 0 && buffer[len-1] == '/')
		        buffer[len-1] = '\0';
#ifdef VMS
		    strcat(buffer, HTVMS_wwwName((char *)Home_Dir()));
#else
		    strcat(buffer, Home_Dir());
#endif /* VMS */
		    strcat(buffer, cp);
		    strcpy(filename, buffer);
		}
#ifdef VMS
        	if (strchr(filename, '/') != NULL) {
		    strcpy(buffer, HTVMS_name("", filename));
		    strcpy(filename, buffer);
		}
                strcpy(buffer, filename);
#else
                if (*filename != '/')
		    cp = getenv("PWD");
		else
		    cp = NULL;
		if (cp)
                    sprintf(buffer,"%s/%s", cp, filename);
		else
		    strcpy(buffer, filename);
#endif /* VMS */

		/* see if it already exists */
		if ((outfile_fp = fopen(buffer,"r")) != NULL) {
		    fclose(outfile_fp);
#ifdef VMS
		    _statusline("File exists. Create higher version? (y/n)");
#else
		    _statusline("File exists. Overwrite? (y/n)");
#endif /* VMS */
		    c = 0;
		    while (TOUPPER(c)!='Y' && TOUPPER(c)!='N' &&
		    	   c != 7 && c != 3)
		        c = LYgetch();
#ifdef VMS
		    if (HadVMSInterrupt) {
			HadVMSInterrupt = FALSE;
			_statusline("Save request cancelled!!!");
			sleep(InfoSecs);
			break;
		    }
#endif /* VMS */
		    if (c == 7 || c == 3) { /* Control-G or Control-C */
			_statusline("Save request cancelled!!!");
			sleep(InfoSecs);
			break;
		    }
		    if(TOUPPER(c) == 'N') {
		        _statusline("Enter a new filename: ");
			goto retry;
		    }
		}

                if ((outfile_fp = fopen(buffer,"w")) == NULL) {
		    HTAlert("Cannot write to file.");
		    _statusline("Enter a new filename: ");
		    goto retry;
                }

		print_wwwfile_to_fd(outfile_fp,0);
		if (keypad_mode)
		    printlist(outfile_fp,FALSE);

		fclose(outfile_fp);
		break;

	case MAIL: 
		_statusline("Please enter a valid internet mail address: ");
		strcpy(user_response, (personal_mail_address ?
						personal_mail_address : ""));
		if (LYgetstr(user_response, VISIBLE,
			     sizeof(user_response), NORECALL) < 0 ||
		    *user_response == '\0') {
		    _statusline("Mail request cancelled!!!");
		    sleep(InfoSecs);
		    break;
		}

		change_sug_filename(sug_filename);
#ifndef VMS
#ifdef MMDF
		sprintf(buffer,"%s -mlruxto,cc*", SYSTEM_MAIL);
#else
		sprintf(buffer,"%s -t -oi", SYSTEM_MAIL);
#endif /* MMDF */

		if ((outfile_fp = popen(buffer, "w")) == NULL) {
			_statusline("ERROR - Unable to mail file");
			sleep(AlertSecs);
			break;
		}
		
		fprintf(outfile_fp,"X-within-URL:%s\n",newdoc->address);
		fprintf(outfile_fp,"To:%s\nSubject:%s\n\n",user_response,
								sug_filename);

		print_wwwfile_to_fd(outfile_fp,0);
		if (keypad_mode)
		    printlist(outfile_fp,FALSE);

		pclose(outfile_fp);
#else  /* VMS stuff */
		if (strchr(user_response,'@') && !strchr(user_response,':') &&
		   !strchr(user_response,'%') && !strchr(user_response,'"')) {
		    sprintf(filename, MAIL_ADRS, user_response);
		    strcpy(user_response, filename);
		}

		if(tempfile == NULL) {
		    tempfile = (char *) malloc(128);
		    if (!tempfile)
		        outofmem(__FILE__, "printfile");
		    tempname(tempfile,NEW_FILE);
		} else {
		    remove(tempfile);   /* remove duplicates */
		}
		if((outfile_fp = fopen(tempfile,"w")) == NULL) {
		    HTAlert("Unable to open tempfile");
		    break;
		}

		/* write the contents to a temp file */
		print_wwwfile_to_fd(outfile_fp,0);
		if (keypad_mode)
		    printlist(outfile_fp,FALSE);
		fclose(outfile_fp);

		remove_quotes(sug_filename);
		sprintf(buffer,"%s/subject=\"%s\" %s %s", 
			SYSTEM_MAIL, sug_filename, tempfile, user_response);

        	stop_curses();
		printf("Mailing file.  Please wait...");
        	system(buffer);
		sleep(MessageSecs);
        	start_curses();
#endif /* !VMS */
		break;
	
	case TO_SCREEN:
		pages = lines_in_file/(LYlines+1);
		/* count fractional pages ! */
		if ((lines_in_file % (LYlines+1)) >0)  pages++; 
		if(pages > 4) {
		    sprintf(filename,"File is %d screens long.  Are you sure you want to print? [y]",pages);
 		    _statusline(filename);
		    c=LYgetch();
#ifdef VMS
		    if (HadVMSInterrupt) {
			HadVMSInterrupt = FALSE;
			_statusline("Print request cancelled!!!");
			sleep(InfoSecs);
			break;
		    }
#endif /* VMS */
    		    if (c == RTARROW || c == 'y' || c== 'Y'
                         || c == '\n' || c == '\r') {
                        addstr("   Ok...");
		    } else {
			_statusline("Print request cancelled!!!");
			sleep(InfoSecs);
		        break;
		    }
		}

		_statusline("Press RETURN to begin: ");
		*filename = '\0';
		if (LYgetstr(filename, VISIBLE,
			     sizeof(filename), NORECALL) < 0) {
		      _statusline("Print request cancelled!!!");
	              sleep(InfoSecs);
		      break;
                }

		outfile_fp = stdout;

		stop_curses();

		print_wwwfile_to_fd(outfile_fp,0);
		if (keypad_mode)
		    printlist(outfile_fp,FALSE);

#ifdef VMS
		if (HadVMSInterrupt) {
		     HadVMSInterrupt = FALSE;
		     start_curses();
		     break;
		}
#endif /* VMS */
		fprintf(outfile_fp,"\n\nPress RETURN to finish");

		fflush(stdout);  /* refresh to screen */
		LYgetch();  /* grab some user input to pause */
#ifdef VMS
		HadVMSInterrupt = FALSE;
#endif /* VMS */
		start_curses();
		break;
	
	case PRINTER:
		pages = lines_in_file/pagelen;
		/* count fractional pages ! */
		if ((lines_in_file % pagelen) >0)  pages++; 
		if(pages > 4) {
		    sprintf(filename,"File is %d pages long.  Are you sure you want to print? [y]",pages);
 		    _statusline(filename);
		    c=LYgetch();
#ifdef VMS
		    if (HadVMSInterrupt) {
			HadVMSInterrupt = FALSE;
			_statusline("Print request cancelled!!!");
			sleep(InfoSecs);
			break;
		    }
#endif /* VMS */
    		    if (c == RTARROW || c == 'y' || c== 'Y'
                         || c == '\n' || c == '\r') {
                        addstr("   Ok...");
		    } else  {
			_statusline("Print request cancelled!!!");
			sleep(InfoSecs);
		        break;
		    }
		}

		if(tempfile == NULL) {
		    tempfile = (char *) malloc(128);
		    if (!tempfile)
		        outofmem(__FILE__, "printfile");
		    tempname(tempfile,NEW_FILE);
#if defined(VMS) || defined(NeXT)
		} else {
		    remove(tempfile);   /* remove duplicates */
#endif /* VMS || Next */
		}
#ifdef NeXT
		if ((cp=strrchr(tempfile, '.')) != NULL) {
		    if (HTisDocumentSource() &&
			strcasecomp(cp, ".html")) {
			*cp = '\0';
			strcat(tempfile, ".html");
		    } else if (!HTisDocumentSource() &&
			       strcasecomp(cp, ".txt")) {
			*cp = '\0';
			strcat(tempfile, ".txt");
		    }
		}
#endif /* NeXT */
                if((outfile_fp = fopen(tempfile,"w")) == NULL) {
	            _statusline("ERROR - Unable to allocate file space!!!");
	            sleep(AlertSecs);
		    break;
                }

		print_wwwfile_to_fd(outfile_fp,0);
		if (keypad_mode)
		    printlist(outfile_fp,FALSE);

		fclose(outfile_fp);

		/* find the right printer number */
		{
		    int count=0;
		    for(cur_printer = printers; count < printer_number;
				    count++, cur_printer = cur_printer->next)
			; /* null body */
		}

		/* commands have the form "command %s [%s] [etc]"
		 * where %s is the filename and the second optional
		 * %s is the suggested filename
		 */
		if(cur_printer->command != NULL) {

		    /* check for two '%s' and ask for the second filename
		     * argument if there is
		     */
		    char *first_s = strstr(cur_printer->command, "%s");
		    if(first_s && strstr(first_s+1, "%s")) {
			_statusline("Enter a filename: ");
		again:	strcpy(user_response, sug_filename);
			if (LYgetstr(user_response, VISIBLE,
				     sizeof(user_response), NORECALL) < 0 ||
			    *user_response == '\0') {
			    _statusline("Print request cancelled!!!");
			    sleep(InfoSecs);
			    break;
			}
		        if (no_dotfiles || !show_dotfiles) {
			    if (*user_response == '.' ||
#ifdef VMS
			       ((cp = strrchr(user_response, ':')) &&
			       			*(cp+1) == '.') ||
			       ((cp = strrchr(user_response, ']')) &&
			       			*(cp+1) == '.') ||
#endif /* VMS */
			       ((cp = strrchr(user_response, '/')) &&
			       			*(cp+1) == '.')) {
			        statusline("File name may not begin with dot. Enter a new filename: ");
			        goto again;
			    }
		        }
		    }
#ifdef VMS
		    sprintf(buffer,cur_printer->command,tempfile,user_response);
#else
		    cp = quote_pathname(user_response); /* to prevent spoofing of the shell */
		    sprintf(buffer,cur_printer->command,tempfile,cp);
		    FREE(cp);
#endif /* VMS */

		} else {
		    _statusline("ERROR! - printer is misconfigured");
		    sleep(AlertSecs);
		    break;
		}

		/* move the cursor to the top of the screen so that
		 * output from system'd commands don't scroll up 
                 * the screen
		 */
		move(1,1);

		stop_curses();
#ifndef VMS
		signal(SIGINT, SIG_IGN);
#endif /* !VMS */

		if(TRACE)
		    fprintf(stderr,"command: %s\n",buffer);
		printf("Printing file.  Please wait...");
		system(buffer);
		fflush(stdout);
#ifndef VMS
		signal(SIGINT, cleanup_sig);
#endif /* !VMS */
		sleep(MessageSecs);
		start_curses();
		/* don't remove(tempfile); */
	} /* end switch */

     FREE(link_info);
     FREE(sug_filename);
     return(NORMAL);
}	

#ifdef VMS
PRIVATE int remove_quotes ARGS1(char *,string)
{
   int i;

   for(i=0;string[i]!='\0';i++)
	if(string[i]=='"')
	   string[i]=' ';
	else if(string[i]=='&')
	   string[i]=' ';
	else if(string[i]=='|')
	   string[i]=' ';

   return(0);
}
#endif /* VMS */

/*
 * print_options writes out the current printer choices to a file
 * so that the user can select printers in the same way that
 * they select all other links 
 * printer links look like
 *  LYNXPRINT://LOCAL_FILE/lines=#  	     print to a local file
 *  LYNXPRINT://TO_SCREEN/lines=#   	     print to the screen
 *  LYNXPRINT://MAIL_FILE/lines=#   	     mail the file
 *  LYNXPRINT://PRINTER/lines=#/number=#   print to printer number #
 */

PUBLIC int print_options ARGS2(char **,newfile, int,lines_in_file)
{
    static char * tempfile=NULL;
    char * print_filename=NULL;
    char buffer[LINESIZE];
    int count;
    int pages;
    FILE *fp0;
    lynx_printer_item_type *cur_printer;

    pages = lines_in_file/66 + 1;

    if(tempfile == NULL) {
	tempfile = (char *) malloc(128);
	if (!tempfile)
	    outofmem(__FILE__, "print_options");
        tempname(tempfile,NEW_FILE);
        /* make the file a URL now */
#ifndef VMS
    }
#else
    } else {
        remove(tempfile);   /* put VMS code to remove duplicates here */
    }
#endif /* !VMS */

#ifdef VMS
	StrAllocCopy(print_filename,"file://localhost/");
#else
	StrAllocCopy(print_filename,"file://localhost");
#endif /* VMS */
	StrAllocCat(print_filename,tempfile);

    if((fp0 = fopen(tempfile,"w")) == NULL) {
        HTAlert("Unable to open print options file");
	return(0);
    }

    StrAllocCopy(*newfile, print_filename);
    LYforce_no_cache = TRUE;

    fprintf(fp0, "<head>\n<title>%s</title>\n</head>\n<body>\n",
    		 PRINT_OPTIONS_TITLE);

    fprintf(fp0,"<h1>Printing Options (%s Version %s)</h1>\n",
    				       LYNX_NAME, LYNX_VERSION);

    pages = (lines_in_file+65)/66;
    sprintf(buffer,
    	    "There are %d lines, or approximately %d page%s, to print.<br>\n",
    	    lines_in_file, pages, (pages > 1 ? "s" : ""));
    fputs(buffer,fp0);

    if(no_print || child_lynx || no_mail)
	fputs("Some print functions have been disabled!!!<br>\n", fp0);

    fputs("You have the following print choices.<br>\n", fp0);
    fputs("Please select one:<br>\n<pre>\n", fp0);

    if(child_lynx==FALSE && no_print==FALSE)
         fprintf(fp0, "   <a href=\"LYNXPRINT://LOCAL_FILE/lines=%d\">Save to a local file</a>\n",
	 	      lines_in_file);
    if(child_lynx==FALSE && no_mail==FALSE)
         fprintf(fp0, "   <a href=\"LYNXPRINT://MAIL_FILE/lines=%d\">Mail the file</a>\n",
		      lines_in_file);
    fprintf(fp0, "   <a href=\"LYNXPRINT://TO_SCREEN/lines=%d\">Print to the screen</a>\n",
	 	      lines_in_file);

    for(count=0, cur_printer=printers; cur_printer != NULL; 
        cur_printer = cur_printer->next, count++)
    if(no_print==FALSE || cur_printer->always_enabled) {
        fprintf(fp0,
                "   <a href=\"LYNXPRINT://PRINTER/number=%d/pagelen=%d/lines=%d\">",
                count,cur_printer->pagelen,lines_in_file);
	fprintf(fp0, (cur_printer->name ? 
				cur_printer->name : "No Name Given"));
	fprintf(fp0, "</a>\n");
    }
    fprintf(fp0, "</pre>\n</body>\n");
    fclose(fp0);

    LYforce_no_cache=TRUE;
    return(0);
}
