home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / read.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  8.5 KB  |  383 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/read.c,v 2.1 90/10/04 18:25:43 melissa Exp $";
  10. #endif
  11.  
  12. /*
  13.  * read.c - support for the mm read command
  14.  */ 
  15. #include "mm.h"
  16. #include "cmds.h"
  17. #include "parse.h"
  18.  
  19. static int mark;            /* shall we mark message as seen? */
  20.  
  21. int
  22. cmd_read (n)
  23. int n;
  24. {
  25.     if (!check_cf (O_RDWR))        /* want writable, settle for read */
  26.     return;
  27.  
  28.     if (mode != MM_TOP_LEVEL)
  29.     cmerr ("Previous READ command still active; type QUIT first");
  30.  
  31.     parse_sequence ((n == CMD_REVIEW) ? "" : "unseen",NULL,NULL);
  32.     copy_sequence (cf->read_sequence, cf->sequence); /* XXX */
  33.     check_mark();            /* can we mark things? */
  34.  
  35.     if (sequence_start (cf->read_sequence)) {
  36.     mode |= MM_READ;
  37.     mode &= ~MM_SEND;        /* quit from send mode */
  38.     show_message (cf->current);
  39.     }
  40.     return true;
  41. }
  42.  
  43. static int ltype;
  44. static FILE *type_pipe = NULL;
  45.  
  46. static int
  47. do_type (n)
  48. int n;
  49. {
  50.     if (n > 0)
  51.     if (!ignore (n)) {
  52.         display_message (type_pipe, &cf->msgs[n], false,
  53.                  (ltype ? nil : only_type_headers), 
  54.                  (ltype ? nil : dont_type_headers));
  55.         if (!(cf->msgs[n].flags & M_SEEN) && mark) {
  56.         cf->flags |= MF_MODIFIED; /* file (msg flags) must be saved */
  57.         cf->msgs[n].flags |= M_SEEN|M_MODIFIED;
  58.         }
  59.     }
  60.     return true;
  61. }
  62.  
  63. /*
  64.  * cmd_type:
  65.  * TYPE command.  Parse a sequence and hand everything off to real_type.
  66.  */
  67.  
  68.  
  69. int
  70. cmd_type (n)
  71. int n;
  72. {
  73.     int real_seq;
  74.  
  75.     if (!check_cf (O_RDONLY))
  76.     return;
  77.     real_seq = parse_sequence ("current",NULL,NULL);
  78.     check_mark();            /* can we mark things? */
  79.     real_type (n, real_seq);        /* this is the real function */
  80. }
  81.  
  82.  
  83. /*
  84.  * real_type:
  85.  * the real type command is here.  cmd_type (above) only parses a
  86.  * sequence.  It will call this function.  The LITERAL command which
  87.  * defaults to LITERAL TYPE will also call this after IT does a 
  88.  * sequence parse.
  89.  */
  90.  
  91. int
  92. real_type (n, real_seq)
  93. int n;
  94. int real_seq;
  95. {
  96.     int m;
  97.     char *msg, *fmt_message();
  98.     int len;
  99.     FILE *out, *more_pipe_open();
  100.     extern int use_crt_filter_always;
  101.  
  102.     ltype = (n == CMD_LITERAL);
  103.  
  104.     if (real_seq) {
  105.     out = cmcsb._cmoj ? cmcsb._cmoj : stdout;
  106.     if (!use_crt_filter_always)    /* have to check the total length */
  107.         for (len = 0, m = sequence_start (cf->sequence);
  108.          m && (len < cmcsb._cmrmx);
  109.          m = sequence_next (cf->sequence)) {
  110.         if (cf->msgs[m].flags & M_DELETED) /* deleted message? */
  111.             len++;        /* one line error */
  112.         else {
  113.             msg = fmt_message (&(cf->msgs[m]), 
  114.                        (ltype ? nil : only_type_headers), 
  115.                        (ltype ? nil : dont_type_headers));
  116.             if (msg != NULL) {
  117.             len += logical_lines (msg, cmcsb._cmrmx) +1;
  118.             free (msg);
  119.             }
  120.         }
  121.         }
  122.  
  123.     if (use_crt_filter_always ||
  124.         (len >= cmcsb._cmrmx))
  125.         type_pipe = more_pipe_open(out);
  126.     else
  127.         type_pipe = out;
  128.     sequence_loop (do_type);
  129.     if (type_pipe == out)        /* not a pipe */
  130.         fflush (type_pipe);
  131.     else
  132.         more_pipe_close(type_pipe);    /* really a pipe */
  133.     type_pipe = NULL;        /* set back to NULL so other modules */
  134.     }                    /* can use ignore() too */
  135.     else {
  136.     /*
  137.      * Can't use do_type since do_type checks for message deleted.
  138.      */
  139.     if (cf->current) {
  140.         display_message (stdout, &cf->msgs[cf->current], false,
  141.                  (ltype ? nil : only_type_headers),
  142.                  (ltype ? nil : dont_type_headers));
  143.         if (!(cf->msgs[cf->current].flags & M_SEEN) && mark) {
  144.         cf->flags |= MF_MODIFIED; /* file (msg flags) must be saved */
  145.         cf->msgs[cf->current].flags |= M_MODIFIED|M_SEEN;
  146.         }
  147.     }
  148.     }
  149.     return true;
  150. }
  151.  
  152.  
  153. int
  154. cmd_next (cmd)
  155. int cmd;
  156. {
  157.     confirm ();
  158.     if (!check_cf (O_RDONLY))        /* no mod's needed */
  159.     return;
  160.     if (cmd == CMD_KILL) {
  161.     if (!mark)
  162.         fprintf (stderr, 
  163.              "File %s \"examine\"d, not deleting message.\n",
  164.              cf->filename);
  165.     else {
  166.         if (!(cf->msgs[cf->current].flags & M_DELETED)) {
  167.         cf->msgs[cf->current].flags |= (M_DELETED|M_MODIFIED);
  168.         cf->flags |= MF_MODIFIED; /* file (msg flags) must be saved */
  169.         }
  170.         if (!(mode & MM_READ))
  171.         printf (" %d\n", cf->current);
  172.     }
  173.     }
  174.     if (mode & MM_READ)
  175.     if (sequence_next (cf->read_sequence))
  176.         show_message (cf->current);
  177.     else
  178.         mode &= ~MM_READ;
  179.     else
  180.     if (cf->current < cf->count)
  181.         show_message (++cf->current);
  182.     else
  183.         printf (" Currently at end, message %d\n", cf->current);
  184.     return true;
  185. }
  186.  
  187. int
  188. cmd_previous (n)
  189. int n;
  190. {
  191.     confirm ();
  192.     if (!check_cf (O_RDONLY))        /* no modifying intended */
  193.     return;
  194.  
  195.     if (mode & MM_READ)
  196.     if (sequence_prev (cf->read_sequence))
  197.         show_message (cf->current);
  198.     else
  199.         cmerr ("Already at start of sequence");
  200.     else
  201.     /*
  202.      * just step through the file
  203.      */
  204.     if (cf->current > 1)
  205.         show_message (--cf->current);
  206.     else
  207.         printf (" Currently at beginning, message %d\n", cf->current);
  208.     
  209.     return true;
  210. }
  211.  
  212. int
  213. cmd_count (cmd)
  214. int cmd;
  215. {
  216.     if (!check_cf(O_RDONLY))        /* not wanting to modify */
  217.     return;
  218.  
  219.     if (parse_sequence ("all",NULL,NULL)) {
  220.     int count,n;
  221.     for (count = 0, n = sequence_start (cf->sequence); n;
  222.          n = sequence_next (cf->sequence))
  223.         ++count;
  224.     seq_print (false);
  225.     printf ("%s %d message%s\n", count > 0 ? " =" : "",
  226.         count, count != 1 ? "s" : "");
  227.     } else 
  228.     cmerr ("Command not valid in this context");
  229. }
  230.  
  231. int
  232. cmd_mark (cmd)
  233. int cmd;
  234. {
  235.     int real_seq;
  236.  
  237.     if (!check_cf (O_RDONLY))        /* find out for ourselves */
  238.     return;
  239.     real_seq = parse_sequence ("current",NULL,NULL);
  240.     check_mark();
  241.     if (!mark)                /* can't do anything */
  242.     return;
  243.  
  244.     if (!real_seq)
  245.     change_flag (cf->current, cmd);
  246.     else {
  247.     int n;
  248.     for (n = sequence_start (cf->sequence); n;
  249.          n = sequence_next (cf->sequence))
  250.         change_flag (n, cmd);
  251.     seq_print (true);
  252.     }
  253. }
  254.  
  255. change_flag (n, what)
  256. int n, what;
  257. {
  258.     message *m = & cf->msgs[n];
  259.  
  260.     switch (what) {
  261.       case CMD_DELETE:
  262.     if (!(m->flags& M_DELETED)) {
  263.         m->flags |= (M_DELETED|M_MODIFIED);
  264.         cf->flags |= MF_MODIFIED;
  265.     }
  266.     break;
  267.       case CMD_UNDELETE:
  268.     if (m->flags & M_DELETED) {
  269.         m->flags &= ~M_DELETED;
  270.         m->flags |= M_MODIFIED;
  271.         cf->flags |= MF_MODIFIED;
  272.     }
  273.     break;
  274.       case CMD_UNMARK:
  275.     if (m->flags & M_SEEN) {
  276.         m->flags |= M_MODIFIED;
  277.         m->flags &= ~M_SEEN;
  278.         cf->flags |= MF_MODIFIED;
  279.     }
  280.     break;
  281.       case CMD_MARK:
  282.     if (!(m->flags & M_SEEN)) {
  283.         m->flags |= (M_SEEN|M_MODIFIED);
  284.         cf->flags |= MF_MODIFIED;
  285.     }
  286.     break;
  287.       case CMD_FLAG:
  288.     if (!(m->flags & M_FLAGGED)) {
  289.         m->flags |= (M_FLAGGED|M_MODIFIED);
  290.         cf->flags |= MF_MODIFIED;
  291.     }
  292.     break;
  293.       case CMD_UNFLAG:
  294.     if (m->flags & M_FLAGGED) {
  295.         m->flags &= ~M_FLAGGED;
  296.         m->flags |= M_MODIFIED;
  297.         cf->flags |= MF_MODIFIED;
  298.     }
  299.     break;
  300.       case CMD_UNANSWER:
  301.     if (m->flags & M_ANSWERED) {
  302.         m->flags &= ~M_ANSWERED;
  303.         m->flags |= M_MODIFIED;
  304.         cf->flags |= MF_MODIFIED;
  305.     }
  306.     break;
  307.     }
  308. }
  309.  
  310. int
  311. cmd_jump (n)
  312. int n;
  313. {
  314.     if (!check_cf(O_RDONLY))
  315.     return;
  316.     noise ("to message number");
  317.     n = parse_number (10, "message number", nil);
  318.     if (n < 1 || n > cf->count)
  319.     cmerr("Number out of range");
  320.     confirm();
  321.     if (mode & MM_READ)
  322.     if (!in_sequence(cf->sequence, n))
  323.         cmerr ("Number not in current message sequence");
  324.     cf->current = n;
  325. }
  326.  
  327. /*
  328.  * decide whether to ignore a message, and tell the user why.
  329.  */
  330. ignore (n)
  331. int n;                    /* message number in current file */
  332. {
  333.     if ((mode == MM_TOP_LEVEL) && (cf->msgs[n].flags & M_DELETED)) {
  334.     fprintf (type_pipe ? type_pipe : stdout, 
  335.          " Message %d deleted, ignored.\n", n);
  336.     return true;
  337.     }
  338.     return false;
  339. }
  340.  
  341. /*
  342.  * show_message is used by read, next, previous.
  343.  */
  344.  
  345. static
  346. show_message (n)
  347. int n;
  348. {
  349.     message *m = &cf->msgs[n];
  350.  
  351.     if (m->flags & M_DELETED)
  352.     printf (" Message %d deleted, ignored.\n", n);
  353.     else {
  354.     display_message (stdout, m, true,
  355.              only_type_headers, dont_type_headers);
  356.     if (!(m->flags & M_SEEN) && mark) {
  357.         cf->flags |= MF_MODIFIED;    /* file (msg flags) must be saved */
  358.         m->flags |= (M_SEEN|M_MODIFIED);
  359.     }
  360.     }
  361. }
  362.  
  363. /*
  364.  * check_mark:
  365.  * find out if we can mark the messages in the sequence, and set "mark"
  366.  */
  367. check_mark()
  368. {
  369.     if (!(cf->flags & MF_RDONLY))
  370.     mark = TRUE;            /* go ahead! */
  371.     else {                /* read-only */
  372.     if (modify_read_only == SET_NEVER) {
  373.         fprintf (stderr,
  374.        "Warning: cannot mark messages in file visited with \"examine\"\n");
  375.         mark = FALSE;        /* don't bother trying */
  376.     }
  377.     else if (modify_read_only == SET_ASK)
  378.         mark=yesno("File is read-only, mark messages anyway? ", "no");
  379.     else            /* SET_ALWAYS */
  380.         mark = TRUE;
  381.     }
  382. }
  383.