home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / JED / JED097-1.TAR / jed / lib / rmail.sl < prev    next >
Encoding:
Text File  |  1994-12-12  |  27.6 KB  |  1,363 lines

  1. %!% variable that controls the location of the mailbox for new mail
  2. variable Rmail_Spool_Dir = "/usr/spool/mail";
  3. $1 = getenv("MAIL"); if (strlen($1)) Rmail_Spool_Dir = $1;
  4.  
  5. %!% where the JED mail reader should put the mail
  6. !if (is_defined("Rmail_Directory"))
  7. {
  8.    variable Rmail_Directory = dircat(getenv("HOME"), "Mail");
  9. }
  10.  
  11. %!% temporary mailbox where newmail is moved to before parsed and converted.
  12. variable Rmail_Tmp_Mbox = dircat(Rmail_Directory, "#NewMail#");
  13.  
  14. %!% name to use to indicate that this directory is locked.  This way
  15. %!% another jed rmail reader cannot read this now.
  16. variable Rmail_Lock_File_Name = "___LOCKED___";
  17.  
  18. variable Rmail_Master_Index_File = dircat(Rmail_Directory, "_Root_Index.index");
  19. variable Rmail_Folder_Buffer = Null_String;
  20. variable Rmail_Folder_Name = Null_String;
  21. variable Rmail_Newmail_Folder = "New-Mail";
  22. variable Rmail_Root_Buffer = "Rmail: Folder List";
  23. variable Rmail_Mail_Buffer_Name = Null_String;
  24.  
  25. !if (is_defined("Rmail_Dont_Reply_To"))
  26. {
  27.    % comma separated list of name to not reply to.   
  28.    variable Rmail_Dont_Reply_To;
  29.    $1 = getenv("USER");
  30.    $2 = getenv("HOST");
  31.    variable Rmail_Dont_Reply_To = $1;
  32.    if (strlen($1) and strlen ($2))
  33.      {
  34.     Rmail_Dont_Reply_To = Sprintf("%s,%s@%s", $1, $1, $2, 3);
  35.      }
  36. }
  37.  
  38. Rmail_Dont_Reply_To = strlow (Rmail_Dont_Reply_To);
  39.  
  40. variable Rmail_Message_Number = Null_String;   %/* this is a string!! */
  41.  
  42.  
  43. % check for existence of Rmail directory.  Create it if it does not exist.
  44. !if (file_status(Rmail_Directory)) 
  45. {
  46.    !if (mkdir(Rmail_Directory)) error(strcat ("Unable to create ", Rmail_Directory));
  47.    if (chmod(Rmail_Directory, 0700)) error ("chmod failed!");
  48. }
  49.  
  50. define rmail_buffer_name(folder)
  51. {
  52.    strcat ("Rmail: ", folder);
  53. }
  54.  
  55.  
  56. define rmail_folder_file(folder)
  57. {
  58.    strcat (dircat (Rmail_Directory, folder), ".index");
  59. }
  60.    
  61. % set buffer flags so that autosave is off but save anyway is on.
  62. % This way it gets saved in case of a power failure or something.
  63.  
  64. define rmail_set_buffer_flags()
  65. {
  66.    variable flags = getbuf_info();
  67.    flags = (flags | 0x80) & ~(0x2);    % turn off autosave, turn on save
  68.    flags = flags & ~(0x20);            % turn off undo
  69.    flags = flags | 0x100;              % No backup file.
  70.    setbuf_info(flags);
  71. }
  72.  
  73. define rmail_save_buffer_secure()
  74. {
  75.    variable dir, file, flags;
  76.    flags = getbuf_info(); pop(); =dir; =file;
  77.    
  78.    !if ((flags & 1) and strlen(file)) return;
  79.    file = dircat(dir, file);
  80.    write_buffer(file); pop();
  81.    chmod(file, 0600); pop();
  82. }
  83.  
  84.    
  85. define rmail_update_master_index (folder, n, total, n_unread)
  86. {
  87.    variable cbuf = whatbuf(), f, fline;
  88.    
  89.    fline = Sprintf("Folder:\t%20s\t(%d/%d) messages. %d unread.\n", 
  90.            folder, n, total, n_unread, 4);
  91.    
  92.    variable flags;
  93.    read_file(Rmail_Master_Index_File); pop();
  94.    rmail_set_buffer_flags();
  95.    push_spot();
  96.    bob();
  97.    % only save if necessary.
  98.    !if (bol_fsearch(fline))
  99.      {
  100.     !if (bol_fsearch(Sprintf("Folder:\t%20s\t(", folder, 1))) eob();
  101.     set_readonly(0);
  102.     delete_line();
  103.     insert(fline);
  104.     set_readonly(1);
  105.      }
  106.    rmail_save_buffer_secure();  % only if modified.
  107.    pop_spot();
  108.    setbuf(cbuf);
  109. }
  110.  
  111.  
  112. define rmail_save_folder (folder, delit)
  113. {
  114.    !if (bufferp(Rmail_Folder_Buffer)) return;
  115.    
  116.    variable file = rmail_folder_file(folder), n;
  117.    variable total, n_ok, n_unread;
  118.    
  119.    setbuf(Rmail_Folder_Buffer);
  120.    set_readonly(0);
  121.    n = string(whatline());
  122.    
  123.    % This is a good place to update the master index.
  124.    % calculate total messages and number of deleted ones.
  125.    eob(); bskip_chars(" \t\n");
  126.    total = whatline();
  127.    
  128.    if (bobp ())
  129.      {
  130.     total = 0; n = "0";
  131.      }
  132.    
  133.    bob();
  134.    n_ok = total;
  135.    n_unread = 0;
  136.    forever 
  137.      {
  138.     if (looking_at("D")) n_ok--; else if (looking_at("-")) n_unread++;
  139.     !if (down(1)) break;
  140.     bol();
  141.      }
  142.    
  143.    rmail_update_master_index(folder, n_ok, total, n_unread);
  144.  
  145.    widen();
  146.    bob();
  147.    go_down(1);
  148.    bol(); push_mark(); eol(); 
  149.    if (strcmp(bufsubstr(), n))
  150.      {
  151.     delete_line();
  152.     insert(n);
  153.     newline();
  154.      }
  155.    rmail_save_buffer_secure();
  156.    
  157.    if (delit) 
  158.      {
  159.     delbuf(whatbuf());
  160.     return;
  161.      }
  162.    % 
  163.    % narrow it back
  164.    % 
  165.    bob();
  166.    bol_fsearch("\x1F\xC\n"); pop(); go_down(1);
  167.    push_mark(); eob(); narrow();
  168. }
  169.  
  170. define rmail_find_folder (folder)
  171. {
  172.    variable file = rmail_folder_file(folder);
  173.    rmail_save_folder(Rmail_Folder_Name, 1);
  174.    Rmail_Folder_Buffer = rmail_buffer_name(folder);
  175.    find_file(file); pop();
  176.    rmail_set_buffer_flags();
  177.  
  178.    rename_buffer(Rmail_Folder_Buffer);
  179.    Rmail_Folder_Name = folder;
  180.  
  181.    % make sure buffer is properly formatted.  Routines expect this to be
  182.    % widened.
  183.    
  184.    widen();
  185.    bob();
  186.    if (eobp())
  187.      {
  188.     % new, format it
  189.     insert("0\n1\n\x1F\xC\n")
  190.      }   
  191. }
  192.  
  193.  
  194. define rmail_get_header(h)
  195. {
  196.    bob();
  197.    !if (strcmp(h, "Date: "))
  198.      {
  199.     % special treatment for date.  It always looks like:
  200.     % Wed, 11 jun 1993
  201.     % or: Sun Dec 04, 1994 11:05:52 GMT
  202.     % The day and , are somtimes missing and 1993 may be just 93.
  203.     if (re_fsearch("^Date:[ \t]+[a-zA-Z,]* *0?\\([1-3]?[0-9]\\) +\\([a-zA-Z]+\\) +"))
  204.       return Sprintf("%s-%s", regexp_nth_match(1), regexp_nth_match(2), 2);
  205.     if (re_fsearch("^Date:[ \t]+[a-zA-Z]+ \\([a-zA-Z]+\\) +0?\\([1-3]?[0-9]\\)[ ,]+"))
  206.       return Sprintf("%s-%s", regexp_nth_match(2), regexp_nth_match(1), 2);
  207.     return Null_String;
  208.      }
  209.  
  210.    !if (bol_fsearch(h)) return Null_String;
  211.    go_right(strlen(h));
  212.    skip_white();
  213.    push_mark(); eol(); trim(); bufsubstr();
  214. }
  215.  
  216.    
  217. define rmail_extract_headers()
  218. {
  219.    variable from = Null_String, date = Null_String, subject = Null_String;
  220.    
  221.    push_spot();
  222.    bob(); push_mark();
  223.    push_mark();  skip_chars("\n \t");  del_region(); newline();
  224.    
  225.    !if (bol_fsearch("\n")) eob();
  226.    narrow();
  227.    
  228.    from = rmail_get_header("From ");
  229.    !if (strlen(from)) from = rmail_get_header("From: ");
  230.    
  231.    date = rmail_get_header("Date: ");
  232.    subject = rmail_get_header("Subject: ");
  233.    
  234.    widen();
  235.    pop_spot();
  236.    %                RAFE  (flags, the - means it has not been read.)
  237.    Sprintf(" %6s       %25.25s  %s\n", date, from, subject, 3);
  238.    
  239. }
  240.  
  241.  
  242. % This routine assumes that the buffer is narrow. 
  243. define rmail_make_filename()
  244. {
  245.    variable cbuf = whatbuf(), n;
  246.    setbuf(Rmail_Folder_Buffer);
  247.    bob();
  248.    push_mark(); push_mark();
  249.    eol();
  250.    n = bufsubstr();
  251.    del_region();
  252.    if (strlen(n)) n = integer(n); else n = 0;
  253.    ++n;
  254.    n = string(n);
  255.    bob();
  256.    insert(n); 
  257.    if (eobp())
  258.      {
  259.     insert("\n1\n\x1F\xC\n");
  260.      }
  261.    
  262.    setbuf(cbuf);
  263.    return n;
  264. }
  265.  
  266.    
  267.    
  268.  
  269. define rmail_create_folder(folder)
  270. {
  271.    variable dir = dircat(Rmail_Directory, folder);
  272.    if (file_status(dir)) return dir;
  273.    !if (mkdir(dir)) error ("Unable to create folder directory.");
  274.    chmod(dir, 0700); pop();
  275.    rmail_update_master_index(folder, 0, 0, 0);
  276.    return (dir);
  277. }
  278.  
  279.  
  280. define rmail_output_newmail()
  281. {
  282.    variable headers = rmail_extract_headers();
  283.    variable cbuf = whatbuf();
  284.    variable n = rmail_make_filename(), file;
  285.    
  286.    file = rmail_create_folder (Rmail_Folder_Name);
  287.    file = dircat(file, n);
  288.    bob(); push_mark(); skip_chars("\n \t"); del_region();
  289.    push_mark(); eob();
  290.    write_region_to_file(file); pop();
  291.    setbuf(Rmail_Folder_Buffer);
  292.    eob();
  293.    % If this format is changed, change it in xpunge as well.
  294.    insert(Sprintf("-%3s", n, 1)); insert(headers);
  295.    setbuf(cbuf);
  296. }
  297.  
  298.  
  299.  
  300.  
  301. define rmail_process_newmail (mbox)
  302. {
  303.    variable n = 0, from = "^\\cFrom ";
  304.    
  305.    rmail_find_folder(Rmail_Newmail_Folder);
  306.    eob(); push_spot();
  307.    setbuf(" *rmail-newmail*");
  308.    erase_buffer();
  309.  
  310.    if (insert_file(mbox) <= 0) error ("File not inserted.");
  311.    
  312.  
  313.    bob(); push_mark();
  314.    !if (re_fsearch(from)) error ("New mail with no messages!");
  315.    del_region();
  316.    forever
  317.      {
  318.     push_mark();
  319.     eol();
  320.     if (re_fsearch(from)) go_up(1); else eob();
  321.     narrow();
  322.     ++n;
  323.     rmail_output_newmail();
  324.     erase_buffer();
  325.     widen();
  326.     if (eobp()) break;
  327.     del();
  328.      }
  329.    
  330.    % pop back to beginning of the newest messages in the folder.
  331.    % in addition, save_folder expects the buffer to be narrowed.
  332.    whatbuf();   
  333.    setbuf(Rmail_Folder_Buffer);
  334.    bob();
  335.    bol_fsearch("\x1F\xC\n"); pop();
  336.    go_down(1); push_mark(); eob(); narrow();
  337.    pop_spot();
  338.    
  339.    setbuf(());
  340.    
  341.    rmail_save_folder(Rmail_Newmail_Folder, 1);
  342.    return n;
  343. }
  344.    
  345.  
  346. define rmail_get_newmail()
  347. {
  348.    variable file, n;
  349.    variable nomail, cmd;
  350.    variable exec_file;
  351.    
  352.    nomail = "No new mail.";
  353.    
  354.    file = getenv("MAIL");
  355.    
  356.    !if (strlen(file)) file = dircat(Rmail_Spool_Dir, getenv("USER"));
  357.    
  358.    if (stat_file(file)) 
  359.      {
  360.     message(nomail);
  361.     return (0);
  362.      }
  363.    
  364.    !if (stat_struct("size"))
  365.      {
  366.     message(nomail);
  367.     return (0);
  368.      }
  369.    
  370.    flush("Getting new mail...");
  371.    exec_file = dircat(Jed_Bin_Dir, "getmail");
  372.    
  373.    if (file_status(exec_file) != 1)
  374.      {
  375.     error (strcat (exec_file, " not found!"));
  376.      }
  377.    
  378.    cmd = Sprintf("%s %s %s", exec_file, file, Rmail_Tmp_Mbox, 3);
  379.    push_mark(); pipe_region(cmd); pop();
  380.    
  381.    n = rmail_process_newmail (Rmail_Tmp_Mbox);
  382.    % delete_file(Rmail_Tmp_Mbox);
  383.    return n;
  384. }
  385.  
  386. define rmail_folder_mode()
  387. {
  388.    variable flags;
  389.    find_file(Rmail_Master_Index_File); pop();
  390.    set_readonly(1);
  391.    rmail_set_buffer_flags();
  392.    rename_buffer(Rmail_Root_Buffer);
  393.    
  394.    bob();
  395.    use_keymap("Rmail-Folder");
  396. }
  397.  
  398. define rmail_exit_folder ()
  399. {
  400.    rmail_save_folder(Rmail_Folder_Name, 1);
  401.    if (bufferp(Rmail_Root_Buffer)) pop2buf(Rmail_Root_Buffer); 
  402.    else rmail_folder_mode();
  403.    
  404.    onewindow();
  405.    if (bufferp(Rmail_Mail_Buffer_Name))
  406.      {
  407.     delbuf(Rmail_Mail_Buffer_Name);
  408.     Rmail_Message_Number = Null_String;
  409.      }
  410.    Rmail_Mail_Buffer_Name = Null_String;
  411.    message(Null_String);
  412. }
  413.  
  414. variable Rmail_Headers_Hidden = 0;
  415.  
  416. define rmail_unhide_headers ()
  417. {
  418.    variable mark = "\x1F\xC\n";
  419.  
  420.    Rmail_Headers_Hidden = 0;
  421.    set_readonly(0);
  422.    widen();
  423.    bob(); push_mark();
  424.    !if (bol_fsearch("\n")) eob();
  425.    narrow();
  426.    bob();
  427.    
  428.    % make a mark if not found
  429.    if (bol_fsearch(mark))
  430.      {
  431.     go_down(1);  push_spot();
  432.    
  433.     % delete visible headers
  434.     push_mark(); eob(); del_region();
  435.  
  436.     % restore old ones
  437.     bob(); push_mark(); bol_fsearch(mark); pop();
  438.     bufsubstr(); eob(); insert();
  439.     pop_spot();
  440.      }
  441.    else
  442.      {
  443.     insert(mark);
  444.     push_mark();
  445.     eob();
  446.     bskip_chars("\n");
  447.     bufsubstr();
  448.     bob();
  449.     insert();
  450.     newline();
  451.     go_down(2);
  452.      }
  453.    push_mark(); widen(); eob(); narrow();
  454.    bob(); set_readonly(1);
  455. }
  456.  
  457.  
  458.  
  459. define rmail_hide_headers()
  460. {
  461.    variable ok_headers = "From,Subj,Cc,Organ,In-Reply,Date,Reply-To,To", header;
  462.    variable n;
  463.    
  464.    rmail_unhide_headers();
  465.    Rmail_Headers_Hidden = 1;
  466.    widen(); bob(); push_mark();
  467.    !if (bol_fsearch("\n")) eob();
  468.    narrow();
  469.    bob();
  470.    !if (bol_fsearch("\x1F\xC\n")) error ("Unable to find marker.");
  471.    set_readonly(0);
  472.    push_spot();
  473.    
  474.    n = 0; 
  475.    % mark ok lines
  476.    while (header = extract_element(ok_headers, n, ','), strlen(header))
  477.      {
  478.     n++;
  479.     while (bol_fsearch(header))
  480.       {
  481.          insert("\xFF");
  482.       }
  483.     
  484.     pop_spot();
  485.     push_spot();
  486.      }
  487.    pop_spot();
  488.    eol(); go_right(1);
  489.    % delete unmarked lines
  490.    while(not(eobp()))
  491.      {
  492.     bol();
  493.     if (looking_at("\xFF"))
  494.       {
  495.          del();
  496.          eol(); go_right(1);
  497.          continue;
  498.       }
  499.     
  500.     push_mark(); eol(); skip_chars("\n"); del_region();
  501.     eol();
  502.      }
  503.    %newline();
  504.    widen();
  505.    bob();
  506.    bol_fsearch("\x1F\xC\n"); pop();
  507.    go_down(1);
  508.    push_mark();  eob();   narrow();
  509.    bob();
  510. }
  511.  
  512.  
  513. % This routines returns the file number of current summary line as a string.
  514. % If the line is invalid, it returns the null string.
  515. define rmail_extract_file_number()
  516. {
  517.    bol();
  518.    go_right(1); skip_white();
  519.    push_mark();
  520.    skip_chars("0-9");
  521.    bufsubstr();
  522. }
  523.  
  524. define rmail_add_flag(flag)
  525. {
  526.    variable n = 13, flags = "RFE";
  527.    
  528.    flag = char(flag);
  529.    n += is_substr(flags, flag);
  530.    goto_column(n);
  531.    !if (looking_at(flag))
  532.      {
  533.     insert(flag);
  534.     del();
  535.      }
  536. }
  537.  
  538.  
  539. % this routine returns 0 if line does not contain a valid message
  540. % 1 if the message is already in the window, 2 if not but it exists, -1
  541. % if it had to be read in.
  542. define rmail_get_message(flag)
  543. {
  544.    variable buf, file, n, n1, pop_buf, ret;
  545.    
  546.    !if (bufferp(Rmail_Folder_Buffer)) return (0);
  547.    pop2buf(Rmail_Folder_Buffer);
  548.    
  549.    file = rmail_extract_file_number();
  550.    !if (strlen(file)) return 0;
  551.    Rmail_Message_Number = file;
  552.    set_readonly(0);
  553.    bol(); if (looking_at("-")) 
  554.      {
  555.     del(); insert_single_space ();
  556.      }
  557.    
  558.    if (flag) rmail_add_flag(flag);
  559.    
  560.    set_readonly(1);
  561.    
  562.    buf = Sprintf("Rmail: %s(%s)", Rmail_Folder_Name, file, 2);
  563.    pop_buf = buf;
  564.    ret = 2;
  565.  
  566.    if (strcmp(buf, Rmail_Mail_Buffer_Name) or not(bufferp(buf)))
  567.      {
  568.     %
  569.     % we have to read it in.
  570.     %
  571.     ret = -1;
  572.     if (bufferp(Rmail_Mail_Buffer_Name)) 
  573.       {
  574.          pop_buf = Rmail_Mail_Buffer_Name;
  575.       }
  576.      }
  577.    
  578.    if (buffer_visible(pop_buf))
  579.      {
  580.     pop2buf(pop_buf);
  581.     if (ret == 2) ret = 1;
  582.      }
  583.    else
  584.      {
  585.     % I want summary window at top. There is no nice way to do it
  586.     % at present.
  587.     onewindow();
  588.     n = window_info('r');
  589.     pop2buf(pop_buf);
  590.     if (TOP_WINDOW_ROW == window_info('t')) 
  591.       {
  592.          pop2buf(Rmail_Folder_Buffer);
  593.          sw2buf(pop_buf);
  594.       }
  595.     n1 = window_info('r');    
  596.     %  we want n to be 4 lines
  597.     %  now it is:
  598.     n -= n1 + 1;
  599.     loop (n - 4) enlargewin();
  600.     pop2buf(Rmail_Folder_Buffer);
  601.     pop2buf(pop_buf);
  602.      }
  603.    
  604.    if (ret != -1) return ret;
  605.  
  606.    set_readonly(0);
  607.    widen();
  608.    erase_buffer();
  609.    Rmail_Mail_Buffer_Name = buf;
  610.    file = dircat(dircat(Rmail_Directory, Rmail_Folder_Name), file);
  611.    n = insert_file(file);
  612.    
  613.    ERROR_BLOCK
  614.      {
  615.     set_readonly(1);
  616.     set_buffer_modified_flag(0);
  617.      }
  618.    
  619.    if (n < 0)
  620.      {
  621.     bob ();
  622.     push_mark ();
  623.     eob ();
  624.     write_region_to_file (file); pop ();
  625.     error ("File not found!");
  626.      }
  627.    
  628.  
  629.    bob();
  630.    rename_buffer(buf);
  631.    rmail_hide_headers();
  632.    
  633.    EXECUTE_ERROR_BLOCK;
  634.    
  635.    return (ret);
  636. }
  637.  
  638.   
  639. define rmail_toggle_headers()
  640. {
  641.    !if (rmail_get_message(0)) return;
  642.  
  643.    if (Rmail_Headers_Hidden)
  644.      {
  645.     rmail_unhide_headers();
  646.      }
  647.    else rmail_hide_headers();
  648.    set_buffer_modified_flag(0);
  649.    set_readonly(1);
  650.    pop2buf(Rmail_Folder_Buffer);
  651. }
  652.  
  653. define rmail_scroll_forward()
  654. {
  655.    ERROR_BLOCK 
  656.      {
  657.     pop2buf(Rmail_Folder_Buffer);
  658.      }
  659.    if (rmail_get_message(0) == 1) 
  660.      {
  661.     update(0);
  662.     call("page_down");
  663.      }
  664.  
  665.    EXECUTE_ERROR_BLOCK;
  666. }
  667.  
  668. define rmail_scroll_backward()
  669. {
  670.    ERROR_BLOCK 
  671.      {
  672.        pop2buf(Rmail_Folder_Buffer);
  673.      }
  674.    if (rmail_get_message(0) == 1) 
  675.      {
  676.     update(0);
  677.     call("page_up");
  678.      }
  679.  
  680.    EXECUTE_ERROR_BLOCK;
  681. }
  682.  
  683. define rmail_forward_message()
  684. {
  685.    variable cbuf;
  686.    !if (rmail_get_message('F'))
  687.      {
  688.     beep();
  689.     return;
  690.      }
  691.    
  692.    cbuf = whatbuf();
  693.    mail();
  694.    if (buffer_modified ())
  695.      {
  696.     !if (get_yes_no("Mail already being composed.  Erase it")) return;
  697.      }
  698.  
  699.    eob();
  700.    insbuf(cbuf);
  701.    bob(); eol();
  702. }
  703.  
  704. define rmail_complex_get_from (from)
  705. {
  706.    variable f;
  707.    f = strtrim(str_uncomment_string (regexp_nth_match (1), "\"'(", "\"')"));
  708.    
  709.    !if (strlen(f)) return from;
  710.    
  711.    % add to list 
  712.    if (strlen(from))
  713.      {
  714.     !if (is_list_element(Rmail_Dont_Reply_To, f, ','))
  715.       from = strcat (strcat (from, ","),  f);
  716.     f = from;
  717.      }
  718.    f;
  719. }
  720.  
  721. define rmail_reply()
  722. {
  723.    !if (rmail_get_message('R'))
  724.      {
  725.     beep();
  726.     return;
  727.      }
  728.    
  729.    variable subj = Null_String, from = Null_String, cbuf = whatbuf();
  730.    variable cc = Null_String;
  731.    
  732.  
  733.    push_spot();
  734.    bob();  push_mark();
  735.    !if (bol_fsearch("\n")) eob();
  736.    narrow();
  737.  
  738.    
  739.    if (orelse 
  740.      {re_bsearch("^\\CFrom:.*<\\(.+\\)>");}
  741.      {re_bsearch("^\\CReply-To: *\\([^ ]+\\) *");}
  742.      {re_bsearch("^\\CFrom:.*<\\(.+\\)>");}
  743.      {re_bsearch("^\\CFrom: *\\([^ ]+\\) *");}
  744.      {re_bsearch("^\\cFrom +\\([^ ]+\\) *");}
  745.        )
  746.      {
  747.     from = rmail_complex_get_from(from);
  748.      }
  749.    
  750.    eob();
  751.    
  752.    if (re_bsearch("^Subject: *\\(.*\\)$"))
  753.      {
  754.     subj = regexp_nth_match(1);
  755.      }
  756.    bob();
  757.    
  758.    if (orelse
  759.      {re_fsearch("^\\CCC:.*<\\(.+\\)>");}
  760.      {re_fsearch("^\\CCC: *\\(.*\\)$");}
  761.        )
  762.      {
  763.     cc = rmail_complex_get_from(cc);
  764.      }
  765.  
  766.    bob();
  767.    
  768.    if (orelse 
  769.      {re_fsearch("^\\CTo:.*<\\(.+\\)>");}
  770.      {re_fsearch("^\\CTo: *\\(.*\\)$");}
  771.        )
  772.      {
  773.     from = rmail_complex_get_from(from);
  774.      }
  775.    
  776.    widen();
  777.    pop_spot();
  778.    mail();
  779.    onewindow();
  780.    
  781.    if (buffer_modified ())
  782.      {
  783.     !if (get_yes_no("Mail already being composed.  Erase it")) return;
  784.      }
  785.  
  786.    mail_format_buffer ();
  787.    bob();
  788.    do
  789.      {
  790.     if (looking_at("To:")) 
  791.       {
  792.          eol ();
  793.          insert(from);
  794.       }
  795.     else if (looking_at("Cc:")) 
  796.       {
  797.          eol (); 
  798.          insert (cc);
  799.       }
  800.     else if (looking_at("Subject:"))
  801.       {
  802.          eol ();
  803.          insert (subj);
  804.          bol ();
  805.          ffind(":"); pop(); go_right(1);  skip_white();
  806.          !if (looking_at("RE:")) insert ("RE: ");
  807.       }
  808.      }
  809.    while ((down(1), bol()) and not (looking_at("-")));
  810.    
  811.    eob();
  812.    push_mark();
  813.    narrow();
  814.    % This trick allows a single undo to remove the later insertion:
  815.    erase_buffer();
  816.    
  817.    insbuf(cbuf);
  818.    bob();
  819.    do
  820.      {
  821.     bol();
  822.     insert(">");
  823.      }
  824.    while (down(1));
  825.    newline();
  826.    bob();
  827.    widen();
  828.    
  829.    !if (strlen(from)) 
  830.      {
  831.     bob(); eol();
  832.      }
  833. }
  834.  
  835.  
  836. define rmail_find_next_message()
  837. {
  838.    push_mark();
  839.    while (down(1), bol(), () and looking_at("D"));
  840.    if (eobp())
  841.      {
  842.     pop_mark(1);
  843.     message("No more undeleted messages.");
  844.     return(0);
  845.      }
  846.    pop_mark(0);
  847.    1;
  848. }
  849.  
  850. define rmail_find_prev_message()
  851. {
  852.    variable d = "D";
  853.    push_mark();
  854.    while (up(1), bol(), () and looking_at(d));
  855.    if (bobp() and looking_at(d))
  856.      {
  857.     pop_mark(1);
  858.     message("No more undeleted messages.");
  859.     return(0);
  860.      }
  861.    pop_mark(0);
  862.    1;
  863. }
  864.  
  865. define rmail_delete_forward()
  866. {
  867.    bol();
  868.    if (eolp()) return beep();
  869.    !if (looking_at("D"))
  870.      {
  871.     set_readonly(0);
  872.     del(); insert("D");
  873.     set_readonly(1);
  874.      }
  875.    rmail_find_next_message(); pop();
  876. }
  877.  
  878. define rmail_undelete ()
  879. {
  880.    push_mark();
  881.    eol();
  882.    if (bol_bsearch("D"))
  883.      {
  884.     set_readonly(0);
  885.     del(); insert_single_space ();
  886.     set_readonly(1);
  887.     pop_mark(0);
  888.     return;
  889.      }
  890.    pop_mark(1);
  891.    beep();
  892. }
  893.  
  894. define rmail_next_message()
  895. {
  896.    if (rmail_find_next_message())
  897.      {
  898.     rmail_scroll_forward();
  899.      }
  900. }
  901.  
  902. define rmail_prev_message()
  903. {
  904.    if (rmail_find_prev_message())
  905.      {
  906.     rmail_scroll_forward();
  907.      }
  908. }
  909.  
  910. define rmail_select_folder (folder)
  911. {
  912.    variable n;
  913.    rmail_find_folder(folder);
  914.    bob();
  915.    go_down(1);
  916.    bol(); push_mark(); eol(); n = integer(bufsubstr());
  917.    bol_fsearch("\x1F\xC\n"); pop;
  918.    go_down (1);
  919.    push_mark();
  920.    eob();
  921.    narrow();
  922.    pop2buf(whatbuf());
  923.    goto_line(n); bol();
  924.    use_keymap("Rmail-Read");
  925.    set_status_line("Jed %b Folder.      (%p)  %t", 0);
  926.    set_readonly(1);
  927.    runhooks ("rmail_folder_hook");
  928. }
  929.  
  930. define rmail_folder_newmail()
  931. {
  932.    variable n;
  933.    
  934.    if (-1 != prefix_argument (-1))
  935.      {
  936.     variable file = read_file_from_mini ("Mailbox:");
  937.     !if (strlen (file)) return;
  938.    
  939.     n = rmail_process_newmail (file);
  940.      }
  941.    else 
  942.      {
  943.     n = rmail_get_newmail();
  944.      }
  945.    
  946.    if (n)
  947.      {
  948.     flush(Sprintf("%d new messages.", n, 1));
  949.     rmail_select_folder(Rmail_Newmail_Folder);
  950.      }
  951.    else flush("No new mail.");
  952. }
  953.  
  954.  
  955. variable Rmail_Last_Folder = Null_String;
  956.  
  957.  
  958. % This routine deletes buffer containing message n if it exists
  959. % it returns 1 if is exists and is visible otherwise it returns 0.
  960. define rmail_validate_message ()
  961. {
  962.    variable vis = 0;
  963.    variable buf = Sprintf("Rmail: %s(%s)", Rmail_Folder_Name, Rmail_Message_Number, 2);
  964.    
  965.    if (bufferp(buf))
  966.      {
  967.     vis = buffer_visible(buf);
  968.     delbuf(buf);
  969.      }
  970.    return vis;
  971. }
  972.  
  973. define rmail_update_folder_and_save ()
  974. {
  975.    variable new_n;
  976.    
  977.    eob ();
  978.    bskip_chars ("\n \t");
  979.    bol ();
  980.    new_n = rmail_extract_file_number ();
  981.    !if (strlen(new_n)) new_n = "0";
  982.    widen(); 
  983.    
  984.    bob(); push_mark(); eol(); 
  985.    if (strcmp(bufsubstr(), new_n))
  986.      {
  987.     delete_line();
  988.     insert(new_n);
  989.     newline();
  990.      }
  991.    bol_fsearch("\x1F\xC\n"); pop();
  992.    go_down(1); push_mark(); eob(); narrow();
  993.    
  994.    pop_mark(1);
  995.    rmail_save_folder(Rmail_Folder_Name, 0);
  996. }
  997.  
  998.  
  999. define rmail_resequence_folder ()
  1000. {
  1001.    variable n, file, new_file, dir, new_n = "0";
  1002.    variable update_message = 0;
  1003.  
  1004.    ERROR_BLOCK
  1005.      {
  1006.     rmail_update_folder_and_save ();
  1007.     pop_spot ();
  1008.      }
  1009.  
  1010.    push_spot();
  1011.    set_readonly(0);
  1012.    flush("Resequencing folder...");
  1013.    dir = dircat(Rmail_Directory, Rmail_Folder_Name);
  1014.  
  1015.    n = 0;
  1016.    bob();   
  1017.    while (file = rmail_extract_file_number (), strlen(file))
  1018.      {
  1019.     n++;
  1020.     new_n = string(n); 
  1021.     if (strcmp(file, new_n))
  1022.       {
  1023.          file = dircat(dir, file);
  1024.          new_file = dircat(dir, new_n);
  1025.          if (file_status (new_file)) error (strcat("Error renaming ", file));
  1026.          if (rename_file(file, new_file)) error (strcat("Error renaming ", file));
  1027.          bol();
  1028.          go_right(1);
  1029.          push_mark();
  1030.          skip_white();
  1031.          skip_chars("0-9");
  1032.          del_region();
  1033.          insert(Sprintf("%3s", new_n, 1));
  1034.          !if (strcmp(new_n, Rmail_Message_Number))
  1035.            {
  1036.          update_message = rmail_validate_message ();
  1037.            }
  1038.       }
  1039.  
  1040.     !if (down(1)) break;
  1041.      }
  1042.  
  1043.    % update the last file number
  1044.    rmail_update_folder_and_save ();
  1045.    
  1046.    pop_spot();
  1047.    eol (); bskip_chars("\n"); bol ();
  1048.    set_readonly(1);
  1049.    if (update_message or (integer(new_n) < integer(Rmail_Message_Number)))
  1050.      {
  1051.     Rmail_Message_Number = Null_String;
  1052.     rmail_scroll_forward ();
  1053.      }
  1054.    
  1055.    message("done.");
  1056. }
  1057.  
  1058. define rmail_build_folder_list ()
  1059. {
  1060.    variable slist = Null_String;
  1061.    variable cbuf = whatbuf ();
  1062.    
  1063.    setbuf (Rmail_Root_Buffer);
  1064.    push_spot ();
  1065.    bob ();
  1066.    while (bol_fsearch("Folder:\t"))
  1067.      {
  1068.     go_right (8);
  1069.     skip_white ();
  1070.     push_mark ();
  1071.     ffind ("\t"); pop ();
  1072.     slist = strncat (slist, ",", bufsubstr (), 3);
  1073.      }
  1074.    pop_spot ();
  1075.    setbuf (cbuf);
  1076.    slist;
  1077. }
  1078.  
  1079. define rmail_output_to_folder()
  1080. {
  1081.    variable folder, header, old_n, new_n, new_file, old_file;
  1082.    variable old_folder = Rmail_Folder_Name;
  1083.    variable buf, vis;
  1084.    variable new_dir, old_dir = dircat(Rmail_Directory, Rmail_Folder_Name);
  1085.    
  1086.    old_n = rmail_extract_file_number ();
  1087.    !if (strlen(old_n)) return;
  1088.  
  1089.    folder = read_string_with_completion ("Move to folder:", 
  1090.                      Rmail_Last_Folder, 
  1091.                      rmail_build_folder_list ());
  1092.    !if (strlen(folder)) return;
  1093.    !if (strcmp(folder, Rmail_Folder_Name)) return;
  1094.    
  1095.    new_dir = dircat(Rmail_Directory, folder);
  1096.    if (file_status(new_dir) != 2)
  1097.      {
  1098.     if (1 != get_yes_no(Sprintf("Folder %s does not exist, create it", folder, 1)))
  1099.       {
  1100.          return;
  1101.       }
  1102.     rmail_create_folder(folder); pop();
  1103.      }
  1104.    
  1105.    % lets get this header
  1106.    bol(); push_mark(); eol(); header = bufsubstr();
  1107.    
  1108.    rmail_find_folder (folder);
  1109.  
  1110.    %
  1111.    % generate a new filename
  1112.    %
  1113.    new_n = rmail_make_filename();
  1114.    new_file = dircat(new_dir, new_n);
  1115.    old_file = dircat(old_dir, old_n);
  1116.    
  1117.    if (rename_file(old_file, new_file))
  1118.      {
  1119.     rmail_select_folder(old_folder);
  1120.     error("Unable to rename file.");
  1121.      }
  1122.    eob();
  1123.    insert(header);
  1124.    bol();
  1125.    go_right(1);
  1126.    push_mark();
  1127.    skip_white();
  1128.    skip_chars("0-9");
  1129.    del_region();
  1130.    insert(Sprintf("%3s", new_n, 1));
  1131.    Rmail_Last_Folder = folder;
  1132.    
  1133.    % Now narrow it so next routine can process it
  1134.    bob();
  1135.    bol_fsearch("\x1F\xC\n"); pop;
  1136.    go_down (1);
  1137.    push_mark();
  1138.    eob();
  1139.    narrow();
  1140.  
  1141.    rmail_select_folder(old_folder);
  1142.    set_readonly(0);
  1143.    bob(); 
  1144.    bol_fsearch(header); pop();
  1145.    delete_line();
  1146.    rmail_resequence_folder();
  1147. }
  1148.  
  1149.  
  1150. % This function is assumed to be called from within a folder.  It REALLY
  1151. % deletes files marked with the D.
  1152.  
  1153. define rmail_xpunge_deletions ()
  1154. {
  1155.    variable file, dir, n, new_file;
  1156.    % variable old_n = Null_String;
  1157.    flush("Expunging messages...");
  1158.    push_mark();
  1159.    ERROR_BLOCK
  1160.      {
  1161.     rmail_resequence_folder ();
  1162.     pop_mark(0);
  1163.     set_readonly(1);
  1164.      }
  1165.    set_readonly(0);
  1166.    dir = dircat(Rmail_Directory, Rmail_Folder_Name);
  1167.    bob();
  1168.    while (bol_fsearch("D"))
  1169.      {
  1170.     file = rmail_extract_file_number();
  1171.     !if (strlen(file)) continue;
  1172.     % !if (strcmp(file, Rmail_Message_Number))
  1173.     %  {
  1174.     %     old_n = file;
  1175.     %  }
  1176.     
  1177.     file = dircat(dir, file);
  1178.     if (file_status(file) == 1)
  1179.       {
  1180.          !if (delete_file(file))
  1181.            {
  1182.           error (strcat("Unable to delete ", file));
  1183.            }
  1184.          delete_line();
  1185.       }
  1186.     else 
  1187.       {
  1188.          error(strcat("Unable to access ", file));
  1189.       }
  1190.      }
  1191.    pop_mark(1);
  1192.    rmail_resequence_folder ();
  1193. }
  1194.  
  1195.  
  1196. $1 = "Rmail-Read";
  1197. !if (keymap_p($1))
  1198. {
  1199.    make_keymap($1);
  1200.    _for (' ', 127, 1) 
  1201.      {
  1202.     $2 = char(());
  1203.     undefinekey($2, $1);
  1204.      }
  1205.    definekey("rmail_delete_forward", "D", $1);
  1206.    definekey("rmail_delete_forward", "d", $1);
  1207.    definekey("rmail_exit_folder", "q", $1);
  1208.    definekey("rmail_exit_folder", "Q", $1);
  1209.    definekey("rmail_folder_newmail", "g", $1);
  1210.    definekey("rmail_folder_newmail", "G", $1);
  1211.    definekey("rmail_next_message", "n", $1);
  1212.    definekey("rmail_next_message", "N", $1);
  1213.    definekey("rmail_prev_message", "p", $1);
  1214.    definekey("rmail_prev_message", "P", $1);
  1215.    definekey("rmail_toggle_headers", "t", $1);
  1216.    definekey("rmail_toggle_headers", "T", $1);
  1217.    definekey("rmail_scroll_forward", " ", $1);
  1218.    definekey("rmail_scroll_forward", "\r", $1);
  1219.    definekey("rmail_scroll_backward", "^?", $1);
  1220.    definekey("rmail_xpunge_deletions", "x", $1);
  1221.    definekey("rmail_xpunge_deletions", "X", $1);
  1222.    definekey("rmail_reply", "r", $1);
  1223.    definekey("rmail_reply", "R", $1);
  1224.    definekey("rmail_forward_message", "f", $1);
  1225.    definekey("rmail_forward_message", "F", $1);
  1226.    definekey("rmail_output_to_folder", "o", $1);
  1227.    definekey("rmail_undelete", "u", $1);
  1228.    definekey("rmail_undelete", "U", $1);
  1229.    definekey("mail", "m", $1);
  1230.    definekey("mail", "M", $1);
  1231. }
  1232.    
  1233.  
  1234.  
  1235.  
  1236. define rmail_select_this_folder ()
  1237. {
  1238.    bol();
  1239.    !if (looking_at("Folder:\t")) return beep();
  1240.    ffind("\t"); pop();
  1241.    skip_white();
  1242.    push_mark(); 
  1243.    !if (ffind("\t("))
  1244.      {
  1245.     pop_mark();
  1246.     beep();
  1247.     return;
  1248.      }
  1249.    
  1250.    rmail_select_folder (bufsubstr());
  1251. }
  1252.  
  1253.     
  1254.  
  1255.  
  1256.  
  1257.  
  1258. $1 = "Rmail-Folder";
  1259. !if (keymap_p($1))
  1260. {
  1261.    make_keymap($1);
  1262.    _for (' ', 127, 1) 
  1263.      {
  1264.     $2 = char(());
  1265.     undefinekey($2, $1);
  1266.      }
  1267.    definekey("rmail_folder_newmail", "g", $1);
  1268.    definekey("rmail_folder_newmail", "G", $1);
  1269.    definekey("rmail_quit_rmail", "q", $1);
  1270.    definekey("rmail_quit_rmail", "Q", $1);
  1271.    definekey("rmail_select_this_folder", " ", $1);
  1272.    definekey("rmail_select_this_folder", "\r", $1);
  1273.    definekey("mail", "m", $1);
  1274.    definekey("mail", "M", $1);
  1275. }
  1276.  
  1277. % if parameter is 0, unlock it if it is ours.  Otherwise, lock or steal it.
  1278. % it returns 1 if the lock was made, 0 if not.
  1279. define rmail_check_lock_file(lck)
  1280. {
  1281.    variable lpid, this_pid = string(getpid()), do_del;
  1282.    variable lock_file = dircat (Rmail_Directory, Rmail_Lock_File_Name);
  1283.    variable ret = 0, write_it = 0, lbuf;
  1284.    variable errbuf;
  1285.    
  1286.    read_file(lock_file); pop();  message (Null_String);
  1287.    lbuf = whatbuf();
  1288.    
  1289.    ERROR_BLOCK
  1290.      {
  1291.     set_buffer_modified_flag(0);
  1292.     delbuf(lbuf);
  1293.      }
  1294.    
  1295.    % extract the pid, it will be null if file was created
  1296.    bob(); push_mark(); eol(); lpid = bufsubstr();
  1297.    delete_line();
  1298.    insert(this_pid);
  1299.    
  1300.    if (lck)
  1301.      {
  1302.     % check existence of pid
  1303.     if (unix_kill(integer (lpid), 0)) lpid = Null_String;
  1304.    
  1305.     if (orelse 
  1306.           {not (strlen(lpid)) or not(strcmp(lpid, this_pid))}
  1307.           {error (Sprintf("Pid %s is locking mail directory.  Sorry.", lpid, 1));}
  1308.         )
  1309.       {
  1310.          ret = 1;
  1311.          write_it = 1;
  1312.       }
  1313.      }
  1314.    else !if (strcmp(lpid, this_pid))
  1315.      {
  1316.     delete_file(lock_file); pop();
  1317.      }
  1318.    
  1319.    % get_yes_no WILL change the buffer.  This is because read_file was used 
  1320.    % which is effectively a setbuf.  get_yes_no calls update which restores
  1321.    % top level buffer.
  1322.    
  1323.    setbuf(lbuf);
  1324.    if (write_it) save_buffer();
  1325.    EXECUTE_ERROR_BLOCK;
  1326.    return (ret);
  1327. }
  1328.  
  1329. define rmail_quit_rmail()
  1330. {
  1331.    rmail_exit_folder();
  1332.    % This puts us at the root again so save and get out.
  1333.    rmail_save_buffer_secure();
  1334.    delbuf(Rmail_Root_Buffer);
  1335.    rmail_check_lock_file(0); pop();   % deletes the lock file.
  1336. }
  1337.     
  1338.  
  1339. define rmail ()
  1340. {
  1341.    variable n;
  1342.    !if (rmail_check_lock_file(1)) return;
  1343.  
  1344.    rmail_save_folder(Rmail_Folder_Name, 1);
  1345.    Rmail_Folder_Buffer = Null_String;
  1346.    
  1347.    rmail_folder_mode();
  1348.     
  1349.    n = rmail_get_newmail();
  1350.    if (n)
  1351.      {
  1352.     flush(Sprintf("%d new messages.", n, 1));
  1353.     rmail_select_folder(Rmail_Newmail_Folder);
  1354.      }
  1355.    else
  1356.      {
  1357.     message("No new mail.");
  1358.      }
  1359. }
  1360.  
  1361.    
  1362.   
  1363.