% sendmail.sl	-*- mode: slang; mode: fold -*-
%
% (Thanks to olesen@weber.me.queensu.ca (mj olesen) for this)
%
% Sendmail interface for Unix.
%
%  Functions: 
%   mail_send             : send message
%   mail                  : initiate mail mode
%   mail_insert_signature : append contents of Mail_Signature_File
%   mail_kill_buffer      : Delete mail buffer
%
%  Variables:
%   Mail_Reply_To         : Set this to appropriate Reply-To value
%   Mail_Signature_File   : Filename of signature (~/.signature is default)
%   SendMail_Cmd          : Name of sendmail program including switches
%   Mail_Extra_Headers	  : Misc headers to insert
%   
% You might want something like the following in mail_hook
%
% define mail_hook ()
% {
%    local_setkey ("mail_send", "^C^C");
%    local_setkey ("mailalias_expand", "^C^E");
%    local_setkey ("mail_kill_buffer", "^Xk");
% }

autoload ("mailalias_expand", "mailalias"); % the mail-alias package

% Create a dummy function if set_line_readonly is not defined.
!if (is_defined ("set_line_readonly")) eval (".(pop) set_line_readonly");

%{{{ Public Variables 

$1 = "~/.signature";
!if (is_defined ("Mail_Signature_File"))
{
   variable Mail_Signature_File = expand_filename ($1);
}

!if (is_defined ("Mail_Header_Separator_String"))
  variable Mail_Header_Separator_String = 
"--- Do not modify this line.  Enter your message below ---";

!if (is_defined ("Mail_Extra_Headers"))
{
   variable Mail_Extra_Headers = NULL;
}


% The sendmail program

$1 = _stkdepth ();
NULL;
"/usr/bin/sendmail";		% places to look
"/usr/lib/sendmail";
"/usr/sbin/sendmail";

!if (is_defined ("SendMail_Cmd"))
{
   variable SendMail_Cmd;

   while (SendMail_Cmd = (), SendMail_Cmd != NULL)
     {
	if (1 == file_status (SendMail_Cmd))
	  {
	     SendMail_Cmd = strcat (SendMail_Cmd, " -t -oem -oi -odb");
	     break;
	  }
     }
   
}

_pop_n (_stkdepth () - $1);

!if (strlen (SendMail_Cmd)) error ("`sendmail' program not found!");

%!% always Reply-To: here instead.
!if (is_defined ("Mail_Reply_To"))
{
   variable Mail_Reply_To = Null_String;
}

%}}}

%{{{ Private Variables

static variable Mail_Previous_Buffer = Null_String;
static variable Mail_Previous_Windows = 1;
static variable Mail_This_Buffer = Null_String;
static variable Mail_Filename = dircat (getenv ("HOME"), ".__jed_mail__");

%}}}

%{{{ Private Functions


define mail_sw2_prev_buf ()
{
   if (bufferp (Mail_Previous_Buffer)) sw2buf (Mail_Previous_Buffer);
   if (1 == Mail_Previous_Windows) onewindow ();
   if (bufferp (Mail_This_Buffer) and strcmp (Mail_This_Buffer, Mail_Previous_Buffer))
     pop2buf (Mail_This_Buffer);
}

%}}}

define mail_send () %{{{
{
   variable dir, file, sent, buf = "*mail*";
   variable sep_mark, fcc_mark, fcc_file;

   if (buf != whatbuf ())
     error ("not *mail* buffer");

   flush ("Sending...");

   push_spot ();

   bob ();
   !if (bol_fsearch (Mail_Header_Separator_String))
     {
	!if (bol_fsearch ("\n"))
	  {
	     pop_spot ();
	     verror ("Cannot find %s\n", Mail_Header_Separator_String);
	  }
     }

   set_line_readonly (0);
   del_eol ();
   sep_mark = create_user_mark ();

   bob ();
   fcc_mark = NULL;
   if (bol_fsearch ("Fcc: "))
     {
	push_mark_eol ();
	go_right_1 ();
	fcc_file = strtrim (substr (bufsubstr_delete (), 6, -1));
	fcc_mark = create_user_mark ();
     }
  
  
   mark_buffer ();
   sent = not (pipe_region (SendMail_Cmd));
   
   if (fcc_mark != NULL)
     {
	if (sent and strlen (fcc_file))
	  {
	     variable user = getenv ("USER");
	     if (user == NULL)
	       {
		  user = getenv ("LOGNAME");
		  if (user == NULL)
		    user = "user";
	       }
	     () = append_string_to_file (sprintf ("From %s %s\n", user, time ()), fcc_file);

	     % Make sure the buffer ends with two newline characters
	     eob ();
	     push_mark ();
	     bskip_chars (" \t\n");
	     del_region ();
	     newline (); newline ();
	     
	     mark_buffer ();
	     () = append_region_to_file (fcc_file);
	  }
	goto_user_mark (fcc_mark);
	vinsert ("Fcc: %s\n", fcc_file);

	% If the marks are on top of one another, make sure sep_mark gets
	% updated.  I added the binary operations on User Marks just for
	% this purpose.
	if (fcc_mark == sep_mark)
	  move_user_mark (sep_mark);
     }

   goto_user_mark (sep_mark);
   insert (Mail_Header_Separator_String);

   pop_spot ();

   if (sent)
     {
	set_buffer_modified_flag (0);
	flush ("Sending...done");
	(file, dir,,) = getbuf_info ();
	() = delete_file (make_autosave_filename (dir, file));
	file = dircat (dir, file);
	!if (strcmp (Mail_Filename, file))
	  () = delete_file (Mail_Filename);
	mail_sw2_prev_buf ();
	bury_buffer (buf);
	return;
     }

   flush ("Error sending message");
   beep ();
}
add_completion ("mail_send");

%}}}

define mail_format_buffer (erase) %{{{
{
   variable km = "mail_map";

   text_mode ();

   setbuf_info (getbuf_info () & ~(0x40)); %  turn off buried buffer flag
   
   !if (keymap_p(km)) make_keymap(km);
   use_keymap(km);
   
   if (erase)
     {
	erase_buffer ();

	insert ("To: \nCc: \nBcc: \nSubject: \n");
	if (strlen (Mail_Reply_To))
	  vinsert ("Reply-To: %s\n", Mail_Reply_To);
	
	if (Mail_Extra_Headers != NULL)
	  {
	     insert (Mail_Extra_Headers);
	     newline ();
	  }
	insert (Mail_Header_Separator_String);
	newline ();

	go_up_1 ();
	set_line_readonly (1);

	bob (); eol ();
	set_buffer_modified_flag(0);
   
     }

   push_spot ();
   run_mode_hooks("mail_hook");
   pop_spot ();

   set_buffer_undo(1);
}

%}}}

define mail_kill_buffer () %{{{
{
   call ("kill_buffer");
   mail_sw2_prev_buf ();
}

%}}}

define mail () %{{{
{
   variable status, dir, file, buf = "*mail*";
   variable do_format = 1;
   
   status = bufferp (buf);
   Mail_Previous_Windows = nwindows ();
   Mail_This_Buffer = whatbuf ();
   
   if (BATCH)
     {
	% Mail_Previous_Buffer = whatbuf ();
	sw2buf (buf);
     }
   else
     {
	Mail_Previous_Buffer = pop2buf_whatbuf (buf);
     }

   % if buffer is not old, turn autosave on
   if (status)
     {
	(,,,status) = getbuf_info ();
	if (status & 1) return;
     }
   else
     {
	(dir, file) = parse_filename (Mail_Filename);
	setbuf_info (file, dir, buf, 2);	% autosave
	
	file = make_autosave_filename(dir, file);
	if (1 == file_status (file))
	  {
	     if (get_yes_no ("An autosave file exists.  Use it"))
	       {
		  erase_buffer ();
		  () = insert_file (file);
		  do_format = 0;
	       }
	  }
     }

   () = set_buffer_umask (0077);
   mail_format_buffer (do_format);
}

%}}}

define mail_insert_signature () %{{{
{
   !if (strlen (Mail_Signature_File))
     return;
   
   push_spot ();
   eob ();
   insert ("\n-- \n");
   () = insert_file (Mail_Signature_File);
   pop_spot ();
}

%}}}

