%!% variable that controls the location of the mailbox for new mail
variable Rmail_Spool_Dir = "/usr/spool/mail";
$1 = getenv("MAIL"); if (strlen($1)) Rmail_Spool_Dir = $1;

%!% where the JED mail reader should put the mail
variable Rmail_Directory = dircat(getenv("HOME"), "Mail");

%!% temporary mailbox where newmail is moved to before parsed and converted.
variable Rmail_Tmp_Mbox = dircat(Rmail_Directory, "#NewMail#");

%!% name to use to indicate that this directory is locked.  This way
%!% another jed rmail reader cannot read this now.
variable Rmail_Lock_File_Name = "___LOCKED___";

variable Rmail_Master_Index_File = dircat(Rmail_Directory, "_Root_Index.index");
variable Rmail_Folder_Buffer = Null_String;
variable Rmail_Folder_Name;
variable Rmail_Newmail_Folder = "New-Mail";
variable Rmail_Root_Buffer = "Rmail: Folder List";
variable Rmail_Mail_Buffer_Name = Null_String;

!if (is_defined("Rmail_Dont_Reply_To"))
{
   variable Rmail_Dont_Reply_To = Null_String;
   $1 = getenv("USER");
   $2 = getenv("HOST");
   if (strlen($1) and strlen ($2))
     {
	Rmail_Dont_Reply_To = strcat ($1, strcat ("@", $2));
     }
}

Rmail_Dont_Reply_To = strlow (Rmail_Dont_Reply_To);

variable Rmail_Message_Number = Null_String;   %/* this is a string!! */


% check for existence of Rmail directory.  Create it if it does not exist.
!if (file_status(Rmail_Directory)) 
{
   !if (mkdir(Rmail_Directory)) error(strcat ("Unable to create ", Rmail_Directory));
   if (chmod(Rmail_Directory, 0700)) error ("chmod failed!");
}

define rmail_buffer_name(folder)
{
   strcat ("Rmail: ", folder);
}


define rmail_folder_file(folder)
{
   strcat (dircat (Rmail_Directory, folder), ".index");
}
   
% set buffer flags so that autosave is off but save anyway is on.
% This way it gets saved in case of a power failure or something.

define rmail_set_buffer_flags()
{
   variable flags = getbuf_info();
   flags = (flags | 0x80) & ~(0x2);    % turn off autosave, turn on save
   flags = flags & ~(0x20);            % turn off undo
   flags = flags | 0x100;              % No backup file.
   setbuf_info(flags);
}

define rmail_save_buffer_secure()
{
   variable dir, file, flags;
   flags = getbuf_info(); pop(); =dir; =file;
   
   !if ((flags & 1) and strlen(file)) return;
   file = dircat(dir, file);
   write_buffer(file); pop();
   chmod(file, 0600); pop();
}

   
define rmail_update_master_index (folder, n, total, n_unread)
{
   variable cbuf = whatbuf(), f, fline;
   
   fline = Sprintf("Folder:\t%20s\t(%d/%d) messages. %d unread.\n", 
		   folder, n, total, n_unread, 4);
   
   variable flags;
   read_file(Rmail_Master_Index_File); pop();
   rmail_set_buffer_flags();
   push_spot();
   bob();
   % only save if necessary.
   !if (bol_fsearch(fline))
     {
	!if (bol_fsearch(Sprintf("Folder:\t%20s\t(", folder, 1))) eob();
	set_readonly(0);
	delete_line();
	insert(fline);
	set_readonly(1);
     }
   rmail_save_buffer_secure();  % only if modified.
   pop_spot();
   setbuf(cbuf);
}


define rmail_save_folder (folder, delit)
{
   !if (bufferp(Rmail_Folder_Buffer)) return;
   
   variable file = rmail_folder_file(folder), n;
   variable total, n_ok, n_unread;
   
   setbuf(Rmail_Folder_Buffer);
   set_readonly(0);
   n = string(whatline());
   
   % This is a good place to update the master index.
   % calculate total messages and number of deleted ones.
   eob(); bskip_chars(" \t\n");
   total = whatline();
   
   bob();
   n_ok = total;
   n_unread = 0;
   forever 
     {
	if (looking_at("D")) n_ok--; else if (looking_at("-")) n_unread++;
	!if (down(1)) break;
	bol();
     }
   
   rmail_update_master_index(folder, n_ok, total, n_unread);

   widen();
   bob();
   go_down(1);
   bol(); push_mark(); eol(); 
   if (strcmp(bufsubstr(), n))
     {
	delete_line();
	insert(n);
	newline();
     }
   rmail_save_buffer_secure();
   
   if (delit) 
     {
	delbuf(whatbuf());
	return;
     }
   % 
   % narrow it back
   % 
   bob();
   bol_fsearch("\x1F\xC\n"); pop(); go_down(1);
   push_mark(); eob(); narrow();
}

define rmail_find_folder (folder)
{
   variable file = rmail_folder_file(folder);
   rmail_save_folder(Rmail_Folder_Name, 1);
   Rmail_Folder_Buffer = rmail_buffer_name(folder);
   find_file(file); pop();
   rmail_set_buffer_flags();

   rename_buffer(Rmail_Folder_Buffer);
   Rmail_Folder_Name = folder;

   % make sure buffer is properly formatted.  Routines expect this to be
   % widened.
   
   widen();
   bob();
   if (eobp())
     {
	% new, format it
	insert("0\n1\n\x1F\xC\n")
     }   
}


define rmail_get_header(h)
{
   bob();
   !if (strcmp(h, "Date: "))
     {
	% special treatment for date.  It always looks like:
	% Wed, 11 jun 1993  
	% The day and , are somtimes missing and 1993 may be just 93.
	!if (re_fsearch("^Date:[ \t]+[a-zA-Z,]* *0?\\([1-3]?[0-9]\\) +\\([a-zA-Z]+\\) +")) return Null_String;
	return Sprintf("%s-%s", regexp_nth_match(1), regexp_nth_match(2), 2);
     }

   !if (bol_fsearch(h)) return Null_String;
   go_right(strlen(h));
   skip_white();
   push_mark(); eol(); trim(); bufsubstr();
}

   
define rmail_extract_headers()
{
   variable from = Null_String, date = Null_String, subject = Null_String;
   
   push_spot();
   bob(); push_mark();
   push_mark();  skip_chars("\n \t");  del_region(); newline();
   
   !if (bol_fsearch("\n")) eob();
   narrow();
   
   from = rmail_get_header("From ");
   !if (strlen(from)) from = rmail_get_header("From: ");
   
   date = rmail_get_header("Date: ");
   subject = rmail_get_header("Subject: ");
   
   widen();
   pop_spot();
   %                RAFE  (flags, the - means it has not been read.)
   Sprintf(" %6s       %25.25s  %s\n", date, from, subject, 3);
   
}


% This routine assumes that the buffer is narrow. 
define rmail_make_filename()
{
   variable cbuf = whatbuf(), n;
   setbuf(Rmail_Folder_Buffer);
   bob();
   push_mark(); push_mark();
   eol();
   n = bufsubstr();
   del_region();
   if (strlen(n)) n = integer(n); else n = 0;
   ++n;
   n = string(n);
   bob();
   insert(n); 
   if (eobp())
     {
	insert("\n1\n\x1F\xC\n");
     }
   
   setbuf(cbuf);
   return n;
}

   
   

define rmail_create_folder(folder)
{
   variable dir = dircat(Rmail_Directory, folder);
   if (file_status(dir)) return dir;
   !if (mkdir(dir)) error ("Unable to create folder directory.");
   chmod(dir, 0700); pop();
   rmail_update_master_index(folder, 0, 0, 0);
   return (dir);
}


define rmail_output_newmail()
{
   variable headers = rmail_extract_headers();
   variable cbuf = whatbuf();
   variable n = rmail_make_filename(), file;
   
   file = rmail_create_folder (Rmail_Folder_Name);
   file = dircat(file, n);
   bob(); push_mark(); skip_chars("\n \t"); del_region();
   push_mark(); eob();
   write_region_to_file(file); pop();
   setbuf(Rmail_Folder_Buffer);
   eob();
   % If this format is changed, change it in xpunge as well.
   insert(Sprintf("-%3s", n, 1)); insert(headers);
   setbuf(cbuf);
}




define rmail_process_newmail()
{
   variable n = 0, from = "^\\cFrom ";
   
   rmail_find_folder(Rmail_Newmail_Folder);
   eob(); push_spot();
   setbuf(" *rmail-newmail*");
   erase_buffer();

   if (insert_file(Rmail_Tmp_Mbox) <= 0) error ("File not inserted.");
   

   bob(); push_mark();
   !if (re_fsearch(from)) error ("New mail with no messages!");
   del_region();
   forever
     {
	push_mark();
	eol();
	if (re_fsearch(from)) go_up(1); else eob();
	narrow();
	++n;
	rmail_output_newmail();
	erase_buffer();
	widen();
	if (eobp()) break;
	del();
     }
   
   % pop back to beginning of the newest messages in the folder.
   % in addition, save_folder expects the buffer to be narrowed.
   whatbuf();   
   setbuf(Rmail_Folder_Buffer);
   bob();
   bol_fsearch("\x1F\xC\n"); pop();
   go_down(1); push_mark(); eob(); narrow();
   pop_spot();
   
   setbuf(());
   
   rmail_save_folder(Rmail_Newmail_Folder, 1);
   return n;
}
   

define rmail_get_newmail()
{
   variable file, n;
   variable nomail, cmd;
   variable exec_file;
   
   nomail = "No new mail.";
   
   file = getenv("MAIL");
   
   !if (strlen(file)) file = dircat(Rmail_Spool_Dir, getenv("USER"));
   
   if (stat_file(file)) 
     {
	message(nomail);
	return (0);
     }
   
   !if (stat_struct("size"))
     {
	message(nomail);
	return (0);
     }
   
   flush("Getting new mail...");
   exec_file = dircat(Jed_Bin_Dir, "getmail");
   
   if (file_status(exec_file) != 1)
     {
	error (strcat (exec_file, " not found!"));
     }
   
   cmd = Sprintf("%s %s %s", exec_file, file, Rmail_Tmp_Mbox, 3);
   push_mark(); pipe_region(cmd); pop();
   
   n = rmail_process_newmail();
   % delete_file(Rmail_Tmp_Mbox);
   return n;
}

define rmail_folder_mode()
{
   variable flags;
   find_file(Rmail_Master_Index_File); pop();
   set_readonly(1);
   rmail_set_buffer_flags();
   rename_buffer(Rmail_Root_Buffer);
   
   bob();
   use_keymap("Rmail-Folder");
}

define rmail_exit_folder ()
{
   rmail_save_folder(Rmail_Folder_Name, 1);
   if (bufferp(Rmail_Root_Buffer)) pop2buf(Rmail_Root_Buffer); 
   else rmail_folder_mode();
   
   onewindow();
   if (bufferp(Rmail_Mail_Buffer_Name))
     {
	delbuf(Rmail_Mail_Buffer_Name);
	Rmail_Message_Number = Null_String;
     }
   Rmail_Mail_Buffer_Name = Null_String;
   message(" ");
}

variable Rmail_Headers_Hidden = 0;

define rmail_unhide_headers ()
{
   variable mark = "\x1F\xC\n";

   Rmail_Headers_Hidden = 0;
   set_readonly(0);
   widen();
   bob(); push_mark();
   !if (bol_fsearch("\n")) eob();
   narrow();
   bob();
   
   % make a mark if not found
   if (bol_fsearch(mark))
     {
	go_down(1);  push_spot();
   
	% delete visible headers
	push_mark(); eob(); del_region();

	% restore old ones
	bob(); push_mark(); bol_fsearch(mark); pop();
	bufsubstr(); eob(); insert();
	pop_spot();
     }
   else
     {
	insert(mark);
	push_mark();
	eob();
	bskip_chars("\n");
	bufsubstr();
	bob();
	insert();
	newline();
	go_down(2);
     }
   push_mark(); widen(); eob(); narrow();
   bob(); set_readonly(1);
}



define rmail_hide_headers()
{
   variable ok_headers = "From,Subj,Cc,Organ,In-Reply,Date,Reply-To,To", header;
   variable n;
   
   rmail_unhide_headers();
   Rmail_Headers_Hidden = 1;
   widen(); bob(); push_mark();
   !if (bol_fsearch("\n")) eob();
   narrow();
   bob();
   !if (bol_fsearch("\x1F\xC\n")) error ("Unable to find marker.");
   set_readonly(0);
   push_spot();
   
   n = 0; 
   % mark ok lines
   while (header = extract_element(ok_headers, n, ','), strlen(header))
     {
	n++;
	while (bol_fsearch(header))
	  {
	     insert("\xFF");
	  }
	
	pop_spot();
	push_spot();
     }
   pop_spot();
   eol(); go_right(1);
   % delete unmarked lines
   while(not(eobp()))
     {
	bol();
	if (looking_at("\xFF"))
	  {
	     del();
	     eol(); go_right(1);
	     continue;
	  }
	
	push_mark(); eol(); skip_chars("\n"); del_region();
	eol();
     }
   newline();
   widen();
   bob();
   bol_fsearch("\x1F\xC\n"); pop();
   down(1);
   push_mark();  eob();   narrow();
   bob();
}


% This routines returns the file number of current summary line as a string.
% If the line is invalid, it returns the null string.
define rmail_extract_file_number()
{
   bol();
   go_right(1); skip_white();
   push_mark();
   skip_chars("0-9");
   bufsubstr();
}

define rmail_add_flag(flag)
{
   variable n = 13, flags = "RFE";
   
   flag = char(flag);
   n += is_substr(flags, flag);
   goto_column(n);
   !if (looking_at(flag))
     {
	insert(flag);
	del();
     }
}


% this routine returns 0 if line does not contain a valid message
% 1 if the message is already in the window, 2 if not but it exists, -1
% if it had to be read in.
define rmail_get_message(flag)
{
   variable buf, file, n, n1, pop_buf, ret;
   
   !if (bufferp(Rmail_Folder_Buffer)) return (0);
   pop2buf(Rmail_Folder_Buffer);
   
   file = rmail_extract_file_number();
   !if (strlen(file)) return 0;
   Rmail_Message_Number = file;
   set_readonly(0);
   bol(); if (looking_at("-")) 
     {
	del(); insert_single_space ();
     }
   
   if (flag) rmail_add_flag(flag);
   
   set_readonly(1);
   
   buf = Sprintf("Rmail: %s(%s)", Rmail_Folder_Name, file, 2);
   pop_buf = buf;
   ret = 2;

   if (strcmp(buf, Rmail_Mail_Buffer_Name) or not(bufferp(buf)))
     {
	%
	% we have to read it in.
	%
	ret = -1;
	if (bufferp(Rmail_Mail_Buffer_Name)) 
	  {
	     pop_buf = Rmail_Mail_Buffer_Name;
	  }
     }
   
   if (buffer_visible(pop_buf))
     {
	pop2buf(pop_buf);
	if (ret == 2) ret = 1;
     }
   else
     {
	% I want summary window at top. There is no nice way to do it
	% at present.
	onewindow();
	n = window_info('r');
	pop2buf(pop_buf);
	if (1 == window_info('t')) 
	  {
	     pop2buf(Rmail_Folder_Buffer);
	     sw2buf(pop_buf);
	  }
	n1 = window_info('r');	
	%  we want n to be 4 lines
	%  now it is:
	n -= n1 + 1;
	loop (n - 4) enlargewin();
	pop2buf(Rmail_Folder_Buffer);
	pop2buf(pop_buf);
     }
   
   if (ret != -1) return ret;

   set_readonly(0);
   widen();
   erase_buffer();
   Rmail_Mail_Buffer_Name = buf;
   file = dircat(dircat(Rmail_Directory, Rmail_Folder_Name), file);
   insert_file(file); pop();
   bob();
   rename_buffer(buf);
   rmail_hide_headers();
   set_readonly(1);
   set_buffer_modified_flag(0);
   return (ret);
}

  
define rmail_toggle_headers()
{
   !if (rmail_get_message(0)) return;

   if (Rmail_Headers_Hidden)
     {
	rmail_unhide_headers();
     }
   else rmail_hide_headers();
   set_buffer_modified_flag(0);
   set_readonly(1);
   pop2buf(Rmail_Folder_Buffer);
}

define rmail_scroll_forward()
{
   ERROR_BLOCK 
     {
	pop2buf(Rmail_Folder_Buffer);
     }
   if (rmail_get_message(0) == 1) 
     {
	update(0);
	call("page_down");
     }

   EXECUTE_ERROR_BLOCK;
}

define rmail_scroll_backward()
{
   ERROR_BLOCK 
     {
	   pop2buf(Rmail_Folder_Buffer);
     }
   if (rmail_get_message(0) == 1) 
     {
	update(0);
	call("page_up");
     }

   EXECUTE_ERROR_BLOCK;
}

define rmail_forward_message()
{
   variable cbuf;
   !if (rmail_get_message('F'))
     {
	beep();
	return;
     }
   
   cbuf = whatbuf();
   mail();
   eob();
   insbuf(cbuf);
   bob(); eol();
}

define rmail_complex_get_from (from)
{
   variable ignore = extract_element(Rmail_Dont_Reply_To, 0, '.');
   variable f;
   f = strtrim(str_uncomment_string (regexp_nth_match (1), "\"'(", "\"')"));
   
   !if (strlen(f)) return from;
   
   % add to list 
   if (strlen(from))
     {
	if (strcmp(f, ignore) and strcmp (f, Rmail_Dont_Reply_To))
	  from = strcat (strcat (from, ","),  f);
	f = from;
     }
   f;
}

define rmail_reply()
{
   !if (rmail_get_message('R'))
     {
	beep();
	return;
     }
   
   variable subj = Null_String, from = Null_String, cbuf = whatbuf();
   variable cc = Null_String;
   

   push_spot();
   bob();  push_mark();
   !if (bol_fsearch("\n")) eob();
   narrow();

   
   if (orelse 
	 {re_bsearch("^\\CFrom:.*<\\(.+\\)>");}
	 {re_bsearch("^\\CReply-To: *\\([^ ]+\\) *");}
	 {re_bsearch("^\\CFrom:.*<\\(.+\\)>");}
	 {re_bsearch("^\\CFrom: *\\([^ ]+\\) *");}
	 {re_bsearch("^\\cFrom +\\([^ ]+\\) *");}
       )
     {
	from = rmail_complex_get_from(from);
     }
   
   eob();
   
   if (re_bsearch("^Subject: *\\(.*\\)$"))
     {
	subj = regexp_nth_match(1);
     }
   bob();
   
   if (orelse
	 {re_fsearch("^\\CCC:.*<\\(.+\\)>");}
	 {re_fsearch("^\\CCC: *\\(.*\\)$");}
       )
     {
	cc = rmail_complex_get_from(cc);
     }

   bob();
   
   if (orelse 
	 {re_fsearch("^\\CTo:.*<\\(.+\\)>");}
	 {re_fsearch("^\\CTo: *\\(.*\\)$");}
       )
     {
	from = rmail_complex_get_from(from);
     }
   
   widen();
   pop_spot();
   mail();
   onewindow();
   
   if (buffer_modified ())
     {
	!if (get_yes_no("Mail already being composed.  Erase it")) return;
     }

   mail_format_buffer ();
   bob();
   do
     {
	if (looking_at("To:")) 
	  {
	     eol ();
	     insert(from);
	  }
	else if (looking_at("Cc:")) 
	  {
	     eol (); 
	     insert (cc);
	  }
	else if (looking_at("Subject:"))
	  {
	     eol ();
	     insert (subj);
	     bol ();
	     ffind(":"); pop(); go_right(1);  skip_white();
	     !if (looking_at("RE:")) insert ("RE: ");
	  }
     }
   while ((down(1), bol()) and not (looking_at("-")));
   
   eob();
   push_mark();
   narrow();
   % This trick allows a single undo to remove the later insertion:
   erase_buffer();
   
   insbuf(cbuf);
   bob();
   do
     {
	bol();
	insert(">");
     }
   while (down(1));
   newline();
   bob();
   widen();
   
   !if (strlen(from)) 
     {
	bob(); eol();
     }
}


define rmail_find_next_message()
{
   push_mark();
   while (down(1), bol(), () and looking_at("D"));
   if (eobp())
     {
	pop_mark(1);
	message("No more undeleted messages.");
	return(0);
     }
   pop_mark(0);
   1;
}

define rmail_find_prev_message()
{
   variable d = "D";
   push_mark();
   while (up(1), bol(), () and looking_at(d));
   if (bobp() and looking_at(d))
     {
	pop_mark(1);
	message("No more undeleted messages.");
	return(0);
     }
   pop_mark(0);
   1;
}

define rmail_delete_forward()
{
   bol();
   if (eolp()) return beep();
   !if (looking_at("D"))
     {
	set_readonly(0);
	del(); insert("D");
	set_readonly(1);
     }
   rmail_find_next_message(); pop();
}

define rmail_undelete ()
{
   push_mark();
   eol();
   if (bol_bsearch("D"))
     {
	set_readonly(0);
	del(); insert_single_space ();
	set_readonly(1);
	pop_mark(0);
	return;
     }
   pop_mark(1);
   beep();
}

define rmail_next_message()
{
   if (rmail_find_next_message())
     {
	rmail_scroll_forward();
     }
}

define rmail_prev_message()
{
   if (rmail_find_prev_message())
     {
	rmail_scroll_forward();
     }
}

define rmail_select_folder (folder)
{
   variable n;
   rmail_find_folder(folder);
   bob();
   go_down(1);
   bol(); push_mark(); eol(); n = integer(bufsubstr());
   bol_fsearch("\x1F\xC\n"); pop;
   go_down (1);
   push_mark();
   eob();
   narrow();
   pop2buf(whatbuf());
   goto_line(n); bol();
   use_keymap("Rmail-Read");
   set_status_line("Jed %b Folder.      (%p)  %t", 0);
   set_readonly(1);
}

define rmail_folder_newmail()
{
   variable n = rmail_get_newmail();
   if (n)
     {
	flush(Sprintf("%d new messages.", n, 1));
	rmail_select_folder(Rmail_Newmail_Folder);
     }
   else flush("No new mail.");
}

variable Rmail_Last_Folder = Null_String;


% This routine deletes buffer containing message n if it exists
% it returns 1 if is exists and is visible otherwise it returns 0.
define rmail_validate_message ()
{
   variable vis = 0;
   variable buf = Sprintf("Rmail: %s(%s)", Rmail_Folder_Name, Rmail_Message_Number, 2);
   
   if (bufferp(buf))
     {
	vis = buffer_visible(buf);
	delbuf(buf);
     }
   return vis;
}



define rmail_resequence_folder ()
{
   variable n, file, new_file, dir, new_n;
   variable update_message = 0;

   push_spot();
   set_readonly(0);
   flush("Resequencing folder...");
   dir = dircat(Rmail_Directory, Rmail_Folder_Name);

   n = 0;
   bob();   
   while (file = rmail_extract_file_number (), strlen(file))
     {
	n++;
	new_n = string(n); 
	if (strcmp(file, new_n))
	  {
	     file = dircat(dir, file);
	     new_file = dircat(dir, new_n);
	     if (file_status (new_file)) error (strcat("Error renaming ", file));
	     if (rename_file(file, new_file)) error (strcat("Error renaming ", file));
	     bol();
	     go_right(1);
	     push_mark();
	     skip_white();
	     skip_chars("0-9");
	     del_region();
	     insert(Sprintf("%3s", new_n, 1));
	     !if (strcmp(new_n, Rmail_Message_Number))
	       {
		 update_message = rmail_validate_message ();
	       }
	  }

	!if (down(1)) break;
     }

   % update the last file number
   widen(); 
   bob(); push_mark(); eol(); 
   if (strcmp(bufsubstr(), new_n))
     {
	delete_line();
	insert(new_n);
	newline();
     }
   bol_fsearch("\x1F\xC\n"); pop();
   go_down(1); push_mark(); eob(); narrow();
   
   pop_mark(1);
   rmail_save_folder(Rmail_Folder_Name, 0);
   pop_spot();
   eol (); bskip_chars("\n"); bol ();
   set_readonly(1);
   if (update_message or (integer(new_n) < integer(Rmail_Message_Number)))
     {
	Rmail_Message_Number = Null_String;
	rmail_scroll_forward ();
     }
   
   message("done.");
}

define rmail_output_to_folder()
{
   variable folder, header, old_n, new_n, new_file, old_file;
   variable old_folder = Rmail_Folder_Name;
   variable buf, vis;
   variable new_dir, old_dir = dircat(Rmail_Directory, Rmail_Folder_Name);
   
   old_n = rmail_extract_file_number ();
   !if (strlen(old_n)) return;
   
   folder = read_mini("Move to folder:", Rmail_Last_Folder, Null_String);
   !if (strlen(folder)) return;
   !if (strcmp(folder, Rmail_Folder_Name)) return;
   
   new_dir = dircat(Rmail_Directory, folder);
   if (file_status(new_dir) != 2)
     {
	if (1 != get_yes_no(Sprintf("Folder %s does not exist, create it", folder, 1)))
	  {
	     return;
	  }
	rmail_create_folder(folder); pop();
     }
   
   % lets get this header
   bol(); push_mark(); eol(); header = bufsubstr();
   
   rmail_find_folder (folder);

   %
   % generate a new filename
   %
   new_n = rmail_make_filename();
   new_file = dircat(new_dir, new_n);
   old_file = dircat(old_dir, old_n);
   
   if (rename_file(old_file, new_file))
     {
	rmail_select_folder(old_folder);
	error("Unable to rename file.");
     }
   eob();
   insert(header);
   bol();
   go_right(1);
   push_mark();
   skip_white();
   skip_chars("0-9");
   del_region();
   insert(Sprintf("%3s", new_n, 1));
   Rmail_Last_Folder = folder;
   
   % Now narrow it so next routine can process it
   bob();
   bol_fsearch("\x1F\xC\n"); pop;
   go_down (1);
   push_mark();
   eob();
   narrow();

   rmail_select_folder(old_folder);
   set_readonly(0);
   bob(); 
   bol_fsearch(header); pop();
   delete_line();
   rmail_resequence_folder();
}


% This function is assumed to be called from within a folder.  It REALLY
% deletes files marked with the D.

define rmail_xpunge_deletions ()
{
   variable file, dir, n, new_file;
   % variable old_n = Null_String;
   flush("Expunging messages...");
   push_mark();
   ERROR_BLOCK
     {
	pop_mark(0);
	set_readonly(1);
     }
   set_readonly(0);
   dir = dircat(Rmail_Directory, Rmail_Folder_Name);
   bob();
   while (bol_fsearch("D"))
     {
	file = rmail_extract_file_number();
	!if (strlen(file)) continue;
	% !if (strcmp(file, Rmail_Message_Number))
	%  {
	%     old_n = file;
	%  }
	
	file = dircat(dir, file);
	if (file_status(file) == 1)
	  {
	     !if (delete_file(file))
	       {
		  error (strcat("Unable to delete ", file));
	       }
	     delete_line();
	  }
	else 
	  {
	     error(strcat("Unable to access ", file));
	  }
     }
   pop_mark(1);
   rmail_resequence_folder ();
}


$1 = "Rmail-Read";
!if (keymap_p($1))
{
   make_keymap($1);
   _for (' ', 127, 1) 
     {
	$2 = char(());
	undefinekey($2, $1);
     }
   definekey("rmail_delete_forward", "D", $1);
   definekey("rmail_delete_forward", "d", $1);
   definekey("rmail_exit_folder", "q", $1);
   definekey("rmail_exit_folder", "Q", $1);
   definekey("rmail_folder_newmail", "g", $1);
   definekey("rmail_folder_newmail", "G", $1);
   definekey("rmail_next_message", "n", $1);
   definekey("rmail_next_message", "N", $1);
   definekey("rmail_prev_message", "p", $1);
   definekey("rmail_prev_message", "P", $1);
   definekey("rmail_toggle_headers", "t", $1);
   definekey("rmail_toggle_headers", "T", $1);
   definekey("rmail_scroll_forward", " ", $1);
   definekey("rmail_scroll_backward", "^?", $1);
   definekey("rmail_xpunge_deletions", "x", $1);
   definekey("rmail_xpunge_deletions", "X", $1);
   definekey("rmail_reply", "r", $1);
   definekey("rmail_reply", "R", $1);
   definekey("rmail_forward_message", "f", $1);
   definekey("rmail_forward_message", "F", $1);
   definekey("rmail_output_to_folder", "o", $1);
   definekey("rmail_undelete", "u", $1);
   definekey("rmail_undelete", "U", $1);
   definekey("mail", "m", $1);
   definekey("mail", "M", $1);
}
   



define rmail_select_this_folder ()
{
   bol();
   !if (looking_at("Folder:\t")) return beep();
   ffind("\t"); pop();
   skip_white();
   push_mark(); 
   !if (ffind("\t("))
     {
	pop_mark();
	beep();
	return;
     }
   
   rmail_select_folder (bufsubstr());
}

	




$1 = "Rmail-Folder";
!if (keymap_p($1))
{
   make_keymap($1);
   _for (' ', 127, 1) 
     {
	$2 = char(());
	undefinekey($2, $1);
     }
   definekey("rmail_folder_newmail", "g", $1);
   definekey("rmail_folder_newmail", "G", $1);
   definekey("rmail_quit_rmail", "q", $1);
   definekey("rmail_quit_rmail", "Q", $1);
   definekey("rmail_select_this_folder", " ", $1);
   definekey("rmail_select_this_folder", "\r", $1);
   definekey("mail", "m", $1);
   definekey("mail", "M", $1);
}

% if parameter is 0, unlock it if it is ours.  Otherwise, lock or steal it.
% it returns 1 if the lock was made, 0 if not.
define rmail_check_lock_file(lck)
{
   variable lpid, this_pid = string(getpid()), do_del;
   variable lock_file = dircat (Rmail_Directory, Rmail_Lock_File_Name);
   variable ret = 0, write_it = 0, lbuf;
   variable errbuf;
   
   read_file(lock_file); pop();  message (" ");
   lbuf = whatbuf();
   
   ERROR_BLOCK
     {
	set_buffer_modified_flag(0);
	delbuf(lbuf);
     }
   
   % extract the pid, it will be null if file was created
   bob(); push_mark(); eol(); lpid = bufsubstr();
   delete_line();
   insert(this_pid);
   
   if (lck)
     {
	% check existence of pid
	if (unix_kill(integer (lpid), 0)) lpid = Null_String;
   
	if (orelse 
	      {not (strlen(lpid)) or not(strcmp(lpid, this_pid))}
	      {get_yes_no(Sprintf("Pid %s is locking mail directory, steal", lpid, 1));}
	    )
	  {
	     ret = 1;
	     write_it = 1;
	  }
     }
   else !if (strcmp(lpid, this_pid))
     {
	delete_file(lock_file); pop();
     }
   
   % get_yes_no WILL change the buffer.  This is because read_file was used 
   % which is effectively a setbuf.  get_yes_no calls update which restores
   % top level buffer.
   
   setbuf(lbuf);
   if (write_it) save_buffer();
   EXECUTE_ERROR_BLOCK;
   return (ret);
}

define rmail_quit_rmail()
{
   rmail_exit_folder();
   % This puts us at the root again so save and get out.
   rmail_save_buffer_secure();
   delbuf(Rmail_Root_Buffer);
   rmail_check_lock_file(0); pop();   % deletes the lock file.
}
	

define rmail ()
{
   variable n;
   !if (rmail_check_lock_file(1)) return;

   rmail_save_folder(Rmail_Folder_Name, 1);
   Rmail_Folder_Buffer = Null_String;
   
   rmail_folder_mode();
	
   n = rmail_get_newmail();
   if (n)
     {
	flush(Sprintf("%d new messages.", n, 1));
	rmail_select_folder(Rmail_Newmail_Folder);
     }
   else
     {
	message("No new mail.");
     }
}

   
  
