text: #if !defined(lint) && !defined(DOS)
  static char rcsid[] = "$Id: print.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
  #endif
  
  /*
   * ========================================================================
   * Copyright 2006-2007 University of Washington
   * Copyright 2013-2020 Eduardo Chappa
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * ========================================================================
   */
  
  #include "headers.h"
  #include "print.h"
  #include "confscroll.h"
  #include "keymenu.h"
  #include "radio.h"
  #include "status.h"
  #include "../pith/state.h"
  #include "../pith/mailcmd.h"
  
  
  /*
   * Internal prototypes
   */
  void	 set_def_printer_value(char *);
  int      print_select_tool(struct pine *, int, CONF_S **, unsigned);
  int      print_edit_tool(struct pine *, int, CONF_S **, unsigned);
  
  
  static char **def_printer_line;
  static char no_ff[] = "-no-formfeed";
  
  
  #ifndef	DOS
  
  /*
   * Information used to paint and maintain a line on the configuration screen
   */
  /*----------------------------------------------------------------------
      The printer selection screen
  
     Draws the screen and prompts for the printer number and the custom
     command if so selected.
  
   ----*/
  void
  select_printer(struct pine *ps, int edit_exceptions)
  {
      struct        variable  *vtmp;
      CONF_S       *ctmpa = NULL, *ctmpb = NULL, *heading = NULL,
  		 *start_line = NULL;
      PINERC_S     *prc = NULL;
      int i, saved_printer_cat, readonly_warning = 0, no_ex;
      SAVED_CONFIG_S *vsave;
      char *saved_printer, **lval;
      OPT_SCREEN_S screen;
      size_t l;
  
      if(edit_exceptions){
  	q_status_message(SM_ORDER, 3, 7,
  			 _("Exception Setup not implemented for printer"));
  	return;
      }
  
      if(fixed_var(&ps_global->vars[V_PRINTER], "change", "printer"))
        return;
  
      ew = edit_exceptions ? ps_global->ew_for_except_vars : Main;
      
      no_ex = (ps_global->ew_for_except_vars == Main);
  
      if(ps->restricted)
        readonly_warning = 1;
      else{
  	switch(ew){
  	  case Main:
  	    prc = ps->prc;
  	    break;
  	  case Post:
  	    prc = ps->post_prc;
  	    break;
  	  default:
  	    break;
  	}
  
  	readonly_warning = prc ? prc->readonly : 1;
  	if(prc && prc->quit_to_edit){
  	    quit_to_edit_msg(prc);
  	    return;
  	}
      }
  
      saved_printer = cpystr(ps->VAR_PRINTER);
      saved_printer_cat = ps->printer_category;
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 2;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("\"Select\" a port or |pipe-command as your default printer.");
  #else
        = cpystr(_("You may \"Select\" a print command as your default printer."));
  #endif
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 2;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("You may also add alternative ports or !pipes to the list in the");
  #else
        = cpystr(_("You may also add custom print commands to the list in the"));
  #endif
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 2;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("\"Personally selected port or |pipe\" section below.");
  #else
        = cpystr(_("\"Personally selected print command\" section below."));
  #endif
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 2;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT | CF_B_LINE;
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 4;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      def_printer_line = &ctmpa->value;
      set_def_printer_value(ps->VAR_PRINTER);
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 2;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT | CF_B_LINE;
  
  #ifndef OS2
      new_confline(&ctmpa);
      heading = ctmpa;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->varname
  	= cpystr(_(" Printer attached to IBM PC or compatible, Macintosh"));
      ctmpa->flags    |= (CF_NOSELECT | CF_STARTITEM);
      ctmpa->value     = cpystr("");
      ctmpa->headingp  = heading;
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
        = cpystr(_("This may not work with all attached printers, and will depend on the"));
      ctmpa->headingp  = heading;
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
        = cpystr(_("terminal emulation/communications software in use. It is known to work"));
      ctmpa->headingp  = heading;
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
        = cpystr("with Kermit and the latest UW version of NCSA telnet on Macs and PCs,");
      ctmpa->headingp  = heading;
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
        = cpystr("Versaterm Pro on Macs, and WRQ Reflections on PCs.");
      ctmpa->headingp  = heading;
  
      new_confline(&ctmpa);
      start_line = ctmpb = ctmpa; /* default start line */
      ctmpa->valoffset = 17;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = h_config_set_att_ansi;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOHILITE;
      ctmpa->varoffset = 8;
      ctmpa->varname   = cpystr("Printer:");
      ctmpa->value     = cpystr(ANSI_PRINTER);
      ctmpa->varnamep  = ctmpb;
      ctmpa->headingp  = heading;
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 17;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = h_config_set_att_ansi2;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOHILITE;
      ctmpa->varoffset = 8;
      l = strlen(ANSI_PRINTER)+strlen(no_ff);
      ctmpa->value     = (char *)fs_get((l+1) * sizeof(char));
      ctmpa->varnamep  = ctmpb;
      ctmpa->headingp  = heading;
      snprintf(ctmpa->value, l+1, "%s%s", ANSI_PRINTER, no_ff);
      ctmpa->value[l] = '\0';
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 17;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = h_config_set_att_wyse;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOHILITE;
      ctmpa->varoffset = 8;
      ctmpa->value     = cpystr(WYSE_PRINTER);
      ctmpa->varnamep  = ctmpb;
      ctmpa->headingp  = heading;
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 17;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = h_config_set_att_wyse2;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOHILITE;
      ctmpa->varoffset = 8;
      l = strlen(WYSE_PRINTER)+strlen(no_ff);
      ctmpa->value     = (char *)fs_get((l+1) * sizeof(char));
      ctmpa->varnamep  = ctmpb;
      ctmpa->headingp  = heading;
      snprintf(ctmpa->value, l+1, "%s%s", WYSE_PRINTER, no_ff);
      ctmpa->value[l] = '\0';
  #endif
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 0;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT | CF_B_LINE;
      ctmpa->var = &ps->vars[V_STANDARD_PRINTER];
  
  
      new_confline(&ctmpa);
      heading = ctmpa;
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->varname
  #ifdef OS2
          = cpystr(" Standard OS/2 printer port");
  #else
  	= cpystr(_(" Standard UNIX print command"));
  #endif
      ctmpa->value = cpystr("");
      ctmpa->flags    |= (CF_NOSELECT | CF_STARTITEM);
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_STANDARD_PRINTER];
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("Using this option may require you to use the OS/2 \"MODE\" command to");
  #else
        = cpystr(_("Using this option may require setting your \"PRINTER\" or \"LPDEST\""));
  #endif
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_STANDARD_PRINTER];
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("direct printer output to the correct port.");
  #else
        = cpystr(_("environment variable using the standard UNIX utilities."));
  #endif
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_STANDARD_PRINTER];
  
      vtmp = &ps->vars[V_STANDARD_PRINTER];
      for(i = 0; vtmp->current_val.l[i]; i++){
  	new_confline(&ctmpa);
  	ctmpa->valoffset = 22;
  	ctmpa->keymenu   = &printer_select_keymenu;
  	ctmpa->help      = NO_HELP;
  	ctmpa->help      = h_config_set_stand_print;
  	ctmpa->tool      = print_select_tool;
  	if(i == 0){
  	    ctmpa->varoffset = 8;
  	    ctmpa->varname   = cpystr(_("Printer List:"));
  	    ctmpa->flags    |= CF_NOHILITE|CF_PRINTER;
  #ifdef OS2
  	    start_line = ctmpb = ctmpa; /* default start line */
  #else
  	    ctmpb = ctmpa;
  #endif
  	}
  
  	ctmpa->varnamep  = ctmpb;
  	ctmpa->headingp  = heading;
  	ctmpa->varmem = i;
  	ctmpa->var = vtmp;
  	ctmpa->value = printer_name(vtmp->current_val.l[i]);
      }
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 0;
      ctmpa->keymenu   = &printer_select_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_select_tool;
      ctmpa->flags    |= CF_NOSELECT | CF_B_LINE;
  
      new_confline(&ctmpa);
      heading = ctmpa;
      ctmpa->valoffset = 0;
      ctmpa->keymenu   = &printer_edit_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_edit_tool;
      ctmpa->varname
  #ifdef OS2
          = cpystr(" Personally selected port or |command");
  #else
  	= cpystr(_(" Personally selected print command"));
  #endif
      ctmpa->flags    |= (CF_NOSELECT | CF_STARTITEM);
      ctmpa->value = cpystr("");
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_PERSONAL_PRINT_COMMAND];
  
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_edit_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_edit_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("The text to be printed will be sent to the printer or command given here.");
  #else
        = cpystr(_("The text to be printed will be piped into the command given here. The"));
  #endif
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_PERSONAL_PRINT_COMMAND];
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_edit_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_edit_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("The printer port or |pipe is in the 2nd column, the printer name is in");
  #else
        = cpystr(_("command is in the 2nd column, the printer name is in the first column. Some"));
  #endif
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_PERSONAL_PRINT_COMMAND];
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_edit_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_edit_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("the first column. Examples: \"LPT1\", \"COM2\", \"|enscript\". A command may");
  #else
        = cpystr(_("examples are: \"prt\", \"lpr\", \"lp\", or \"enscript\". The command may be given"));
  #endif
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_PERSONAL_PRINT_COMMAND];
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_edit_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_edit_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("be given options, for example \"|ascii2ps -p LPT1\" or \"|txt2hplc -2\". Use");
  #else
        = cpystr(_("with options, for example \"enscript -2 -r\" or \"lpr -Plpacc170\". The"));
  #endif
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_PERSONAL_PRINT_COMMAND];
  
      new_confline(&ctmpa);
      ctmpa->valoffset = 6;
      ctmpa->keymenu   = &printer_edit_keymenu;
      ctmpa->help      = NO_HELP;
      ctmpa->tool      = print_edit_tool;
      ctmpa->flags    |= CF_NOSELECT;
      ctmpa->value
  #ifdef OS2
        = cpystr("the |command method for printers that require conversion from ASCII.");
  #else
        = cpystr(_("commands and options on your system may be different from these examples."));
  #endif
      ctmpa->headingp  = heading;
      ctmpa->var = &ps->vars[V_PERSONAL_PRINT_COMMAND];
  
      vtmp = &ps->vars[V_PERSONAL_PRINT_COMMAND];
      lval = no_ex ? vtmp->current_val.l : LVAL(vtmp, ew);
      if(lval){
  	for(i = 0; lval[i]; i++){
  	    new_confline(&ctmpa);
  	    ctmpa->valoffset = 22;
  	    ctmpa->keymenu   = &printer_edit_keymenu;
  	    ctmpa->help      = h_config_set_custom_print;
  	    ctmpa->tool      = print_edit_tool;
  	    if(i == 0){
  		ctmpa->varoffset = 8;
  		ctmpa->varname   = cpystr(_("Printer List:"));
  		ctmpa->flags    |= CF_NOHILITE|CF_PRINTER;
  		ctmpb = ctmpa;
  	    }
  
  	    ctmpa->varnamep  = ctmpb;
  	    ctmpa->headingp  = heading;
  	    ctmpa->varmem = i;
  	    ctmpa->var = vtmp;
  	    ctmpa->value = printer_name(lval[i]);
  	}
      }
      else{
  	new_confline(&ctmpa);
  	ctmpa->valoffset = 22;
  	ctmpa->keymenu   = &printer_edit_keymenu;
  	ctmpa->help      = h_config_set_custom_print;
  	ctmpa->tool      = print_edit_tool;
  	ctmpa->flags    |= CF_NOHILITE;
  	ctmpa->varoffset = 8;
  	ctmpa->varname   = cpystr(_("Printer List:"));
  	ctmpa->varnamep  = ctmpa;
  	ctmpa->headingp  = heading;
  	ctmpa->varmem    = 0;
  	ctmpa->var       = vtmp;
  	ctmpa->value     = cpystr("");
      }
  
      memset(&screen, 0, sizeof(screen));
      screen.ro_warning = readonly_warning;
      vsave = save_config_vars(ps, 0);
      /* TRANSLATORS: SETUP... is a screen title
         Print something1 using something2.
         "printer config" is something1 */
      switch(conf_scroll_screen(ps, &screen, start_line,
  			      edit_exceptions ? _("SETUP PRINTER EXCEPTIONS")
  					      : _("SETUP PRINTER"),
  			      _("printer config"), 0, NULL)){
        case 0:
  	break;
      
        case 1:
  	write_pinerc(ps, ew, WRP_NONE);
  	break;
      
        case 10:
  	revert_to_saved_config(ps, vsave, 0);
  	ps->printer_category = saved_printer_cat;
  	set_variable(V_PRINTER, saved_printer, 1, 0, ew);
  	set_variable(V_PERSONAL_PRINT_CATEGORY, comatose(ps->printer_category),
  		     1, 0, ew);
  	if(prc)
  	  prc->outstanding_pinerc_changes = 0;
  
  	break;
      }
  
      def_printer_line = NULL;
      free_saved_config(ps, &vsave, 0);
      fs_give((void **)&saved_printer);
  }
  
  #endif	/* !DOS */
  
  
  void
  set_def_printer_value(char *printer)
  {
      char *p, *nick, *cmd;
      int set, editing_norm_except_exists;
      size_t l;
  
      if(!def_printer_line)
        return;
      
      editing_norm_except_exists = ((ps_global->ew_for_except_vars != Main) &&
  				  (ew == Main));
  
      parse_printer(printer, &nick, &cmd, NULL, NULL, NULL, NULL);
      p = *nick ? nick : cmd;
      set = *p;
      if(*def_printer_line)
        fs_give((void **)def_printer_line);
  
      l = strlen(p) + 60;
      *def_printer_line = fs_get((l+1) * sizeof(char));
      snprintf(*def_printer_line, l+1, "Default printer %s%s%s%s%s",
  	set ? "set to \"" : "unset", set ? p : "", set ? "\"" : "",
  	(set && editing_norm_except_exists) ? " (in exception config)" : "",
  	set ? "." : ""); 
      (*def_printer_line)[l] = '\0';
  
      fs_give((void **)&nick);
      fs_give((void **)&cmd);
  }
  
  
  int
  print_select_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
  {
      int rc, retval, no_ex, printer_msg = 0;
      char *p, **lval, *printer_was;
      struct variable *vtmp;
  
      no_ex = (ps_global->ew_for_except_vars == Main);
  
      printer_was = ps->VAR_PRINTER ? cpystr(ps->VAR_PRINTER) : NULL;
  
      switch(cmd){
        case MC_EXIT:
          retval = config_exit_cmd(flags);
  	break;
  
        case MC_CHOICE :
  	if(cl && *cl){
  	    char aname[100], wname[100];
  
  	    strncpy(aname, ANSI_PRINTER, sizeof(aname)-1);
  	    aname[sizeof(aname)-1] = '\0';
  	    strncat(aname, no_ff, sizeof(aname)-strlen(aname)-1);
  	    strncpy(wname, WYSE_PRINTER, sizeof(wname)-1);
  	    wname[sizeof(wname)-1] = '\0';
  	    strncat(wname, no_ff, sizeof(wname)-strlen(wname)-1);
  	    if((*cl)->var){
  		vtmp = (*cl)->var;
  		lval = (no_ex || !vtmp->is_user) ? vtmp->current_val.l
  						 : LVAL(vtmp, ew);
  		rc = set_variable(V_PRINTER, lval ? lval[(*cl)->varmem] : NULL,
  				  1, 0, ew);
  		if(rc == 0){
  		    if(vtmp == &ps->vars[V_STANDARD_PRINTER])
  		      ps->printer_category = 2;
  		    else if(vtmp == &ps->vars[V_PERSONAL_PRINT_COMMAND])
  		      ps->printer_category = 3;
  
  		    set_variable(V_PERSONAL_PRINT_CATEGORY, 
  				 comatose(ps->printer_category), 1, 0, ew);
  
  		    printer_msg++;
  		}
  		else
  		  q_status_message(SM_ORDER,3,5, _("Trouble setting default printer"));
  
  		retval = 1;
  	    }
  	    else if(!strcmp((*cl)->value,ANSI_PRINTER)){
  		rc = set_variable(V_PRINTER, ANSI_PRINTER, 1, 0, ew);
  		if(rc == 0){
  		    ps->printer_category = 1;
  		    set_variable(V_PERSONAL_PRINT_CATEGORY, 
  				 comatose(ps->printer_category), 1, 0, ew);
  		    printer_msg++;
  		}
  		else
  		  q_status_message(SM_ORDER,3,5, _("Trouble setting default printer"));
  
  		retval = 1;
  	    }
  	    else if(!strcmp((*cl)->value,aname)){
  		rc = set_variable(V_PRINTER, aname, 1, 0, ew);
  		if(rc == 0){
  		    ps->printer_category = 1;
  		    set_variable(V_PERSONAL_PRINT_CATEGORY, 
  				 comatose(ps->printer_category), 1, 0, ew);
  		    printer_msg++;
  		}
  		else
  		  q_status_message(SM_ORDER,3,5, _("Trouble setting default printer"));
  
  		retval = 1;
  	    }
  	    else if(!strcmp((*cl)->value,WYSE_PRINTER)){
  		rc = set_variable(V_PRINTER, WYSE_PRINTER, 1, 0, ew);
  		if(rc == 0){
  		    ps->printer_category = 1;
  		    set_variable(V_PERSONAL_PRINT_CATEGORY, 
  				 comatose(ps->printer_category), 1, 0, ew);
  		    printer_msg++;
  		}
  		else
  		  q_status_message(SM_ORDER,3,5, _("Trouble setting default printer"));
  
  		retval = 1;
  	    }
  	    else if(!strcmp((*cl)->value,wname)){
  		rc = set_variable(V_PRINTER, wname, 1, 0, ew);
  		if(rc == 0){
  		    ps->printer_category = 1;
  		    set_variable(V_PERSONAL_PRINT_CATEGORY, 
  				 comatose(ps->printer_category), 1, 0, ew);
  		    printer_msg++;
  		}
  		else
  		  q_status_message(SM_ORDER,3,5, _("Trouble setting default printer"));
  
  		retval = 1;
  	    }
  	    else
  	      retval = 0;
  	}
  	else
  	  retval = 0;
  
  	if(retval){
  	    ps->mangled_body = 1;	/* BUG: redraw it all for now? */
  	    set_def_printer_value(ps->VAR_PRINTER);
  	}
  
  	break;
  
        default:
  	retval = -1;
  	break;
      }
  
      if(printer_msg){
  	p = NULL;
  	if(ps->VAR_PRINTER){
  	    char *nick, *q;
  
  	    parse_printer(ps->VAR_PRINTER, &nick, &q,
  			  NULL, NULL, NULL, NULL);
  	    p = cpystr(*nick ? nick : q);
  	    fs_give((void **)&nick);
  	    fs_give((void **)&q);
  	}
  
  	q_status_message4(SM_ORDER, 0, 3,
  			  "Default printer%s %s%s%s",
  			  ((!printer_was && !ps->VAR_PRINTER) ||
  			   (printer_was && ps->VAR_PRINTER &&
  			    !strcmp(printer_was,ps->VAR_PRINTER)))
  			      ? " still" : "",
  			  p ? "set to \"" : "unset",
  			  p ? p : "", p ? "\"" : ""); 
  
  	if(p)
  	  fs_give((void **)&p);
      }
  
      if(printer_was)
        fs_give((void **)&printer_was);
  
      return(retval);
  }
  
  
  int
  print_edit_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned int flags)
  {
      char	     prompt[81], sval[MAXPATH+1], name[MAXPATH+1];
      char            *nick, *p, *tmp, **newval = NULL, **ltmp = NULL;
      char           **lval, **nelval;
      int		     rv = 0, skip_to_next = 0, after = 0, i = 4, j, k = 0;
      int		     oeflags, changing_selected = 0, no_ex;
      HelpType         help;
      ESCKEY_S         ekey[6];
  
      /* need this to preserve old behavior when no exception config file */
      no_ex = (ps_global->ew_for_except_vars == Main);
  
      if(cmd == MC_CHOICE)
        return(print_select_tool(ps, cmd, cl, flags));
  
      if(!(cl && *cl && (*cl)->var))
        return(0);
  
      nelval = no_ex ? (*cl)->var->current_val.l : LVAL((*cl)->var, ew);
      lval = LVAL((*cl)->var, ew);
  
      switch(cmd){
        case MC_ADD:				/* add to list */
  	sval[0] = '\0';
  	if(!fixed_var((*cl)->var, "add to", NULL)){
  
  	    if(lval && (*cl)->value){
  		strncpy(prompt, _("Enter printer name : "), sizeof(prompt));
  		prompt[sizeof(prompt)-1] = '\0';
  	    }
  	    else if(!lval && nelval){
  		/* Add to list which doesn't exist, but default does exist */
  		ekey[0].ch    = 'r';
  		ekey[0].rval  = 'r';
  		ekey[0].name  = "R";
  		ekey[0].label = N_("Replace");
  		ekey[1].ch    = 'a';
  		ekey[1].rval  = 'a';
  		ekey[1].name  = "A";
  		ekey[1].label = N_("Add To");
  		ekey[2].ch    = -1;
  		strncpy(prompt, _("Replace or Add To default value ? "), sizeof(prompt));
  		prompt[sizeof(prompt)-1] = '\0';
  		switch(i = radio_buttons(prompt, -FOOTER_ROWS(ps), ekey, 'a',
  					 'x', h_config_replace_add, RB_NORM)){
  		  case 'a':
  		    /* Make a list of the default commands, leaving room for 
  		       the command we are about to add below. */
  		    for(k = 0; nelval[k]; k++)
  		      ;
  
  		    ltmp = (char **)fs_get((k+2) * sizeof(char *));
  		    
  		    for(j = 0; j < k; j++)
  		      ltmp[j] = cpystr(nelval[j]);
  
  		    ltmp[k + 1] = ltmp[k] = NULL;
  
  add_text:
  		    strncpy(prompt, _("Enter name of printer to be added : "), sizeof(prompt));
  		    prompt[sizeof(prompt)-1] = '\0';
  		    break;
  		    
  		  case 'r':
  replace_text:
  		    strncpy(prompt, _("Enter the name for replacement printer : "), sizeof(prompt));
  		    prompt[sizeof(prompt)-1] = '\0';
  		    break;
  		    
  		  case 'x':
  		    cmd_cancelled("Add");
  		    break;
  		}
  
  		if(i == 'x')
  		  break;
  	    }
  	    else{
  		strncpy(prompt, _("Enter name of printer to be added : "), sizeof(prompt));
  		prompt[sizeof(prompt)-1] = '\0';
  	    }
  
  	    ps->mangled_footer = 1;
  	    help = NO_HELP;
  
  	    name[0] = '\0';
  	    i = 2;
  	    while(i != 0 && i != 1){
  		if(lval && (*cl)->value){
  		    ekey[0].ch    = ctrl('W');
  		    ekey[0].rval  = 5;
  		    ekey[0].name  = "^W";
  		    ekey[0].label = after ? N_("InsertBefore") : N_("InsertAfter");
  		    ekey[1].ch    = -1;
  		}
  		else
  		  ekey[0].ch    = -1;
  
  		oeflags = OE_APPEND_CURRENT;
  		i = optionally_enter(name, -FOOTER_ROWS(ps), 0, sizeof(name),
  				     prompt,
  				     (ekey[0].ch != -1) ? ekey : NULL,
  				     help, &oeflags);
  		if(i == 0){
  		    rv = ps->mangled_body = 1;
  		    removing_leading_and_trailing_white_space(name);
  		}
  		else if(i == 1){
  		    cmd_cancelled("Add");
  		}
  		else if(i == 3){
  		    help = (help == NO_HELP) ? h_config_insert_after : NO_HELP;
  		}
  		else if(i == 4){		/* no redraw, yet */
  		}
  		else if(i == 5){ /* change from/to prepend to/from append */
  		    after = after ? 0 : 1;
  		}
  	    }
  
  	    if(i == 0)
  	      i = 2;
  
  #ifdef OS2
  	    strncpy(prompt, "Enter port or |command : ", sizeof(prompt));
  #else
  	    strncpy(prompt, _("Enter command for printer : "), sizeof(prompt));
  #endif
  	    prompt[sizeof(prompt)-1] = '\0';
  	    while(i != 0 && i != 1){
  		oeflags = OE_APPEND_CURRENT;
  		i = optionally_enter(sval, -FOOTER_ROWS(ps), 0, sizeof(sval),
  				     prompt,
  				     (ekey[0].ch != -1) ? ekey : NULL,
  				     help, &oeflags);
  		if(i == 0){
  		    rv = ps->mangled_body = 1;
  		    removing_leading_and_trailing_white_space(sval);
  		    if(*sval || !lval){
  
  			for(tmp = sval; *tmp; tmp++)
  			  if(*tmp == ',')
  			  i++;	/* conservative count of ,'s */
  
  			if(!i){	/* only one item */
  			  if (!ltmp){
  			    ltmp = (char **)fs_get(2 * sizeof(char *));
  			    ltmp[1] = NULL;
  			    k = 0;
  			  }
  			  if(*name){
  			    size_t l;
  
  			    l = strlen(name) + 4 + strlen(sval);
  			    ltmp[k] = (char *) fs_get((l+1) * sizeof(char));
  			    snprintf(ltmp[k], l+1, "%s [] %s", name, sval);
  			    ltmp[k][l] = '\0';
  			  }
  			  else
  			    ltmp[k] = cpystr(sval);
  			}
  			else{
  			    /*
  			     * Don't allow input of multiple entries at once.
  			     */
  			    q_status_message(SM_ORDER,3,5,
  				_("No commas allowed in command"));
  			    i = 2;
  			    continue;
  			}
  
  			config_add_list(ps, cl, ltmp, &newval, after);
  
  			if(after)
  			  skip_to_next = 1;
  
  			fs_give((void **)&ltmp);
  			k = 0;
  		    }
  		    else
  		      q_status_message1(SM_ORDER, 0, 3,
  					 _("Can't add %s to list"), empty_val);
  		}
  		else if(i == 1){
  		    cmd_cancelled("Add");
  		}
  		else if(i == 3){
  		    help = help == NO_HELP ? h_config_print_cmd : NO_HELP;
  		}
  		else if(i == 4){		/* no redraw, yet */
  		}
  		else if(i == 5){ /* change from/to prepend to/from append */
  		    after = after ? 0 : 1;
  		}
  	    }
  	}
  
  	break;
  
        case MC_DELETE:					/* delete */
  	if((*cl)->var->current_val.l
  	  && (*cl)->var->current_val.l[(*cl)->varmem]
  	  && !strucmp(ps->VAR_PRINTER,(*cl)->var->current_val.l[(*cl)->varmem]))
  	    changing_selected = 1;
  
  	if(!lval && nelval){
  	    char pmt[80];
  
  	    snprintf(pmt, sizeof(pmt), _("Override default with %s"), empty_val2);
  	    pmt[sizeof(pmt)-1] = '\0';
  	    if(want_to(pmt, 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y'){
  		char **ltmp;
  
  		sval[0] = '\0';
  		ltmp    = (char **)fs_get(2 * sizeof(char *));
  		ltmp[0] = cpystr(sval);
  		ltmp[1] = NULL;
  		config_add_list(ps, cl, ltmp, &newval, 0);
  		fs_give((void **)&ltmp);
  		rv = ps->mangled_body = 1;
  	    }
  	}
  	else if(!lval){
  	    q_status_message(SM_ORDER, 0, 3, _("No set value to delete"));
  	}
  	else{
  	    if((*cl)->var->is_fixed){
  		parse_printer(lval[(*cl)->varmem],
  		    &nick, &p, NULL, NULL, NULL, NULL);
  	        snprintf(prompt, sizeof(prompt), _("Delete (unused) printer %s "),
  		    *nick ? nick : (!*p) ? empty_val2 : p);
  		fs_give((void **)&nick);
  		fs_give((void **)&p);
  	    }
  	    else
  	      snprintf(prompt, sizeof(prompt), _("Really delete item %s from printer list "),
  		    int2string((*cl)->varmem + 1));
  
  	    prompt[sizeof(prompt)-1] = '\0';
  
  	    ps->mangled_footer = 1;
  	    if(want_to(prompt,'n','n',h_config_print_del, WT_FLUSH_IN) == 'y'){
  		rv = ps->mangled_body = 1;
  		fs_give((void **)&lval[(*cl)->varmem]);
  		config_del_list_item(cl, &newval);
  	    }
  	    else
  	      q_status_message(SM_ORDER, 0, 3, _("Printer not deleted"));
  	}
  
  	break;
  
        case MC_EDIT:				/* edit/change list option */
  	if((*cl)->var->current_val.l
  	  && (*cl)->var->current_val.l[(*cl)->varmem]
  	  && !strucmp(ps->VAR_PRINTER,(*cl)->var->current_val.l[(*cl)->varmem]))
  	    changing_selected = 1;
  
  	if(fixed_var((*cl)->var, NULL, "printer"))
  	  break;
  	else if(!lval &&  nelval)
  	  goto replace_text;
  	else if(!lval && !nelval)
  	  goto add_text;
  	else{
  	    HelpType help;
  
  	    ekey[0].ch    = 'n';
  	    ekey[0].rval  = 'n';
  	    ekey[0].name  = "N";
  	    ekey[0].label = N_("Name");
  	    ekey[1].ch    = 'c';
  	    ekey[1].rval  = 'c';
  	    ekey[1].name  = "C";
  	    ekey[1].label = N_("Command");
  	    ekey[2].ch    = 'o';
  	    ekey[2].rval  = 'o';
  	    ekey[2].name  = "O";
  	    ekey[2].label = N_("Options");
  	    ekey[3].ch    = -1;
  	    /* TRANSLATORS: this is a question with three choices */
  	    strncpy(prompt, _("Change Name or Command or Options ? "), sizeof(prompt));
  	    prompt[sizeof(prompt)-1] = '\0';
  	    i = radio_buttons(prompt, -FOOTER_ROWS(ps), ekey, 'c', 'x',
  			      h_config_print_name_cmd, RB_NORM);
  
  	    if(i == 'x'){
  		cmd_cancelled("Change");
  		break;
  	    } 
  	    else if(i == 'c'){
  		char *all_but_cmd;
  
  		parse_printer(lval[(*cl)->varmem],
  			      NULL, &p, NULL, NULL, NULL, &all_but_cmd);
  		
  		strncpy(prompt, _("Change command : "), sizeof(prompt));
  		prompt[sizeof(prompt)-1] = '\0';
  		strncpy(sval, p ? p : "", sizeof(sval)-1);
  		sval[sizeof(sval)-1] = '\0';
  		fs_give((void **)&p);
  
  		ps->mangled_footer = 1;
  		help = NO_HELP;
  		while(1){
  		    oeflags = OE_APPEND_CURRENT;
  		    i = optionally_enter(sval, -FOOTER_ROWS(ps), 0,
  				         sizeof(sval), prompt, NULL,
  					 help, &oeflags);
  		    if(i == 0){
  			removing_leading_and_trailing_white_space(sval);
  			rv = ps->mangled_body = 1;
  			if(lval[(*cl)->varmem])
  			  fs_give((void **)&lval[(*cl)->varmem]);
  
  			i = 0;
  			for(tmp = sval; *tmp; tmp++)
  			  if(*tmp == ',')
  			    i++;	/* count of ,'s */
  
  			if(!i){	/* only one item */
  			    size_t l;
  
  			    l = strlen(all_but_cmd) + strlen(sval);
  			    lval[(*cl)->varmem] = (char *)fs_get((l+1) * sizeof(char));
  			    snprintf(lval[(*cl)->varmem], l+1, "%s%s", all_but_cmd, sval);
  			    lval[(*cl)->varmem][l] = '\0';
  			    
  			    newval = &(*cl)->value;
  			}
  			else{
  			    /*
  			     * Don't allow input of multiple entries at once.
  			     */
  			    q_status_message(SM_ORDER,3,5,
  				_("No commas allowed in command"));
  			    continue;
  			}
  		    }
  		    else if(i == 1){
  			cmd_cancelled("Change");
  		    }
  		    else if(i == 3){
  			help = help == NO_HELP ? h_config_change : NO_HELP;
  			continue;
  		    }
  		    else if(i == 4){		/* no redraw, yet */
  			continue;
  		    }
  
  		    break;
  		}
  	    }
  	    else if(i == 'n'){
  		char *all_but_nick;
  
  		parse_printer(lval[(*cl)->varmem],
  			      &p, NULL, NULL, NULL, &all_but_nick, NULL);
  		
  		strncpy(prompt, _("Change name : "), sizeof(prompt));
  		prompt[sizeof(prompt)-1] = '\0';
  		strncpy(name, p ? p : "", sizeof(name));
  		name[sizeof(name)-1] = '\0';
  
  		fs_give((void **)&p);
  
  		ps->mangled_footer = 1;
  		help = NO_HELP;
  		while(1){
  		    oeflags = OE_APPEND_CURRENT;
  		    i = optionally_enter(name, -FOOTER_ROWS(ps), 0,
  					 sizeof(name), prompt, NULL,
  					 help, &oeflags);
  		    if(i == 0){
  			size_t l;
  
  			rv = ps->mangled_body = 1;
  			removing_leading_and_trailing_white_space(name);
  			if(lval[(*cl)->varmem])
  			  fs_give((void **)&lval[(*cl)->varmem]);
  
  			l = strlen(name) + 1 + ((*all_but_nick == '[') ? 0 : 3) + strlen(all_but_nick);
  			lval[(*cl)->varmem] = (char *)fs_get((l+1) * sizeof(char));
  			snprintf(lval[(*cl)->varmem], l+1,
  			    "%s %s%s", name,
  			    (*all_but_nick == '[') ? "" : "[] ",
  			    all_but_nick);
  			lval[(*cl)->varmem][l] = '\0';
  			
  			newval = &(*cl)->value;
  		    }
  		    else if(i == 1){
  			cmd_cancelled("Change");
  		    }
  		    else if(i == 3){
  			help = help == NO_HELP ? h_config_change : NO_HELP;
  			continue;
  		    }
  		    else if(i == 4){		/* no redraw, yet */
  			continue;
  		    }
  
  		    break;
  		}
  		
  		fs_give((void **)&all_but_nick);
  	    }
  	    else if(i == 'o'){
  		HelpType help;
  
  		ekey[0].ch    = 'i';
  		ekey[0].rval  = 'i';
  		ekey[0].name  = "I";
  		ekey[0].label = N_("Init");
  		ekey[1].ch    = 't';
  		ekey[1].rval  = 't';
  		ekey[1].name  = "T";
  		ekey[1].label = N_("Trailer");
  		ekey[2].ch    = -1;
  		strncpy(prompt, _("Change Init string or Trailer string ? "), sizeof(prompt));
  		prompt[sizeof(prompt)-1] = '\0';
  		j = radio_buttons(prompt, -FOOTER_ROWS(ps), ekey, 'i', 'x',
  				  h_config_print_opt_choice, RB_NORM);
  
  		if(j == 'x'){
  		    cmd_cancelled("Change");
  		    break;
  		} 
  		else{
  		    char *init, *trailer;
  
  		    parse_printer(lval[(*cl)->varmem],
  				  &nick, &p, &init, &trailer, NULL, NULL);
  		    
  		    if(j == i)
  		      snprintf(prompt, sizeof(prompt), _("Change INIT string : "));
  		    else
  		      snprintf(prompt, sizeof(prompt), _("Change TRAILER string : "));
  
  		    strncpy(sval, (j == 'i') ? init : trailer, sizeof(sval)-1);
  		    sval[sizeof(sval)-1] = '\0';
  
  		    tmp = string_to_cstring(sval);
  		    strncpy(sval, tmp, sizeof(sval)-1);
  		    sval[sizeof(sval)-1] = '\0';
  		    fs_give((void **)&tmp);
  		    
  		    ps->mangled_footer = 1;
  		    help = NO_HELP;
  		    while(1){
  			oeflags = OE_APPEND_CURRENT;
  			i = optionally_enter(sval, -FOOTER_ROWS(ps), 0,
  			    sizeof(sval), prompt, NULL, help, &oeflags);
  			if(i == 0){
  			    size_t l;
  
  			    removing_leading_and_trailing_white_space(sval);
  			    rv = 1;
  			    if(lval[(*cl)->varmem])
  			      fs_give((void **)&lval[(*cl)->varmem]);
  			    if(j == 'i'){
  				init = cstring_to_hexstring(sval);
  				tmp = cstring_to_hexstring(trailer);
  				fs_give((void **)&trailer);
  				trailer = tmp;
  			    }
  			    else{
  				trailer = cstring_to_hexstring(sval);
  				tmp = cstring_to_hexstring(init);
  				fs_give((void **)&init);
  				init = tmp;
  			    }
  
  			    l = strlen(nick) + 1 + 2 + strlen("INIT=") + strlen(init) + 1 + strlen("TRAILER=") + strlen(trailer)+ 1 + strlen(p);
  			    lval[(*cl)->varmem] = (char *)fs_get((l+1) * sizeof(char));
  			    snprintf(lval[(*cl)->varmem], l+1,
  				"%s%s%s%s%s%s%s%s%s%s%s",
  	    /* nick */	    nick,
  	    /* space */	    *nick ? " " : "",
  	    /* [ */		    (*nick || *init || *trailer) ? "[" : "",
  	    /* INIT= */	    *init ? "INIT=" : "",
  	    /* init */	    init,
  	    /* space */	    (*init && *trailer) ? " " : "",
  	    /* TRAILER= */	    *trailer ? "TRAILER=" : "",
  	    /* trailer */	    trailer,
  	    /* ] */		    (*nick || *init || *trailer) ? "]" : "",
  	    /* space */	    (*nick || *init || *trailer) ? " " : "",
  	    /* command */	    p);
  			    lval[(*cl)->varmem][l] = '\0';
  	    
  			    newval = &(*cl)->value;
  			}
  			else if(i == 1){
  			    cmd_cancelled("Change");
  			}
  			else if(i == 3){
  			    help=(help == NO_HELP)?h_config_print_init:NO_HELP;
  			    continue;
  			}
  			else if(i == 4){		/* no redraw, yet */
  			    continue;
  			}
  
  			break;
  		    }
  
  		    fs_give((void **)&nick);
  		    fs_give((void **)&p);
  		    fs_give((void **)&init);
  		    fs_give((void **)&trailer);
  		}
  	    }
  	}
  
  	break;
  
        case MC_EXIT:				/* exit */
  	rv = config_exit_cmd(flags);
  	break;
  
        default:
  	rv = -1;
  	break;
      }
  
      if(skip_to_next)
        *cl = next_confline(*cl);
  
      /*
       * At this point, if changes occurred, var->user_val.X is set.
       * So, fix the current_val, and handle special cases...
       */
      if(rv == 1){
  	set_current_val((*cl)->var, TRUE, FALSE);
  	fix_side_effects(ps, (*cl)->var, 0);
  
  	if(newval){
  	    if(*newval)
  	      fs_give((void **)newval);
  	    
  	    if((*cl)->var->current_val.l)
  	      *newval = printer_name((*cl)->var->current_val.l[(*cl)->varmem]);
  	    else
  	      *newval = cpystr("");
  	}
  
  	if(changing_selected)
  	  print_select_tool(ps, MC_CHOICE, cl, flags);
      }
  
      return(rv);
  }
  
  
  /*
   * Given a single printer string from the config file, returns an allocated
   * copy of the friendly printer name, which is
   *      "Nickname"  command
   */
  char *
  printer_name(char *input)
  {
      char *nick, *cmd;
      char *ret;
  
      parse_printer(input, &nick, &cmd, NULL, NULL, NULL, NULL);
      ret = (char *)fs_get((2+6*22+1+strlen(cmd)) * sizeof(char));
      utf8_snprintf(ret, 2+6*22+1+strlen(cmd), "\"%.21w\"%*s%s",
  	*nick ? nick : "",
  	22 - MIN(utf8_width(nick), 21),
  	"",
  	cmd);
      fs_give((void **) &nick);
      fs_give((void **) &cmd);
  
      return(ret);
  }
  