Logo Search packages:      
Sourcecode: af version File versions  Download package

mail_cmd.c

/* Mail_cmd.c - Message sending and handling commands for af.
   Copyright (C) 1991 - 2002 Malc Arnold.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */


#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "af.h"
#include "keyseq.h"
#include "functions.h"
#include "commands.h"
#include "variable.h"
#include "mode.h"
#include "tags.h"
#include "complete.h"
#include "io.h"
#include STRING_HDR

/****************************************************************************/
/* RCS info */

#ifndef lint
static char *RcsId = "$Id: mail_cmd.c,v 2.5 2002/09/08 21:26:22 malc Exp $";
#endif /* ! lint */

/****************************************************************************/
/* Global function declarations */

extern char *xmalloc(), *xstrdup(), *vstrcat(), *getenv();
extern char *expand(), *formtext(), *strdate(), *get_vtext();
extern char *subtract_addresses(), *local_part(), *get_str();
extern char *get_cstr(), *get_dstr(), *get_dcstr(), *utos();
extern char *unique_name();
extern int chk_msg(), send_mail(), send_file(), send_reply();
extern int send_forward(), send_bounce(), send_attached();
extern int page_messages(), msg_status_changed(), msg_touched();
extern int confirm(), get_vval(), tagset(), edit_message();
extern int save_selected(), print_selected(), pipe_selected();
extern unsigned count_messages(), text_lines();
extern void free(), free_texpr(), cmsg(), msgl(), emsg(), emsgl();
extern void show_buffer(), alldisplay(), redisplay();
extern WINDOW *add_window(), *del_window();
extern MAILBUF *add_buffer();
extern MESSAGE *expand_message();
extern REGION *get_region();
extern TAG_EXPR *tagexpr();
extern ARGUMENT *form_or_arg();
extern CLIST *fn_complete();

/* Local function declarations */

static char *sname();
static int do_reply(), do_page(), do_save();
static int do_print(), do_pipe(), do_attach();
static int do_open_body_parts();
static int output_format();

/****************************************************************************/
/* Import the system error number */

extern int errno;

/****************************************************************************/
/* Import the current window and user quit flag from commands.c */

extern WINDOW *cwin;
extern int user_quit;

/****************************************************************************/
/*ARGSUSED*/
FORM *mail(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Send a mail message to a specified user or users */

      char *to;

      /* Convert any second form to an argument */

      arg = (forms != NULL) ? form_or_arg(forms->next, arg) : arg;

      /* Get the destination of the message */

      to = (forms != NULL) ? formtext(forms) : NULL;

      /* And send the mail */

      return((send_mail(to, NULL, NULL, NULL, NULL, arg != NULL))
             ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *mail_file(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Send a file to a specified user or users */

      char *filnam, *to;
      int status;

      /* Convert any third form to an argument */

      if (forms != NULL) {
            arg = form_or_arg(forms->next->next, arg);
      }

      /* Get the name of the file to send */

      if ((filnam = get_cstr(forms, "Send file: ", fn_complete,
                         C_STRICT)) == NULL) {
            return(c_errored());
      }
      forms = (forms != NULL) ? forms->next : NULL;

      /* Expand escape chars in the file name */

      filnam = expand(filnam);

      /* Get the destination of the mail */

      to = (forms != NULL) ? formtext(forms) : NULL;

      /* Send the mail and clean up */

      status = send_file(filnam, to, arg != NULL);
      free(filnam);
      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *reply(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Reply to the current message */

      return((do_reply(FALSE)) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *group_reply(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Group reply to the current message */

      return((do_reply(TRUE)) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *forward(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Forward a mail message to a specified user or users */

      char *to;
      int status;

      /* Check there is a message to forward */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Get the destination of the message */

      to = (forms != NULL) ? formtext(forms) : NULL;

      /* Forward the mail and update status */

      if ((status = send_forward(to, cwin->point))
          && msg_touched(cwin, cwin->point, ST_FORWARDED, FALSE)) {
            alldisplay(cwin->buf);
      }

      /* Now return status */

      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *bounce(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Bounce a mail message to a specified user or users */

      char *to;
      int status;

      /* Check there is a message to bounce */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Get the destination of the mail */

      to = (forms != NULL) ? formtext(forms) : NULL;

      /* Bounce the mail and update status */

      if ((status = send_bounce(to, cwin->point))
          && msg_touched(cwin, cwin->point, ST_FORWARDED, FALSE)) {
            alldisplay(cwin->buf);
      }

      /* Now return status */

      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *attach_msg(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Attach a mail message to an outgoing mail */

      char *to, *subject;
      int status;
      MESSAGE **messages;

      /* Check there is a message to attach */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Convert any second form to an argument */

      if (forms != NULL) {
            arg = form_or_arg(forms->next, arg);
      }

      /* Build the array of messages to attach */

      messages = (MESSAGE **) xmalloc(2 * sizeof(MESSAGE *));
      *messages = cwin->point;
      *(messages + 1) = NULL;

      /* Get the destination and subject of the message */

      to = (forms != NULL) ? formtext(forms) : NULL;
      subject = cwin->point->subject;

      /* Resend the mail and update status */

      status = do_attach(to, subject, messages, arg != NULL);

      /* Clean up and return status */

      free(messages);
      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *attach_region(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Send the messages in the region as an attachment or digest */

      char *to;
      int no_msgs, status;
      MESSAGE **messages, **p, *m;
      REGION *region;

      /* Get the region */

      if ((region = get_region(cwin)) == NULL) {
            return(c_errored());
      }

      /* Convert any second form to an argument */

      if (forms != NULL) {
            arg = form_or_arg(forms->next, arg);
      }

      /* Count the number of messages we're attaching */

      no_msgs = 0;
      for (m = region->start; m->text != NULL && m != region->end;
           m = m->next) {
            /* Count the message if it's visible */

            if (m->visible) {
                  no_msgs++;
            }
      }

      /* Build the array of messages to attach */

      messages = (MESSAGE **) xmalloc((no_msgs + 1) * sizeof(MESSAGE *));
      p = messages;
      for (m = region->start; m->text != NULL && m != region->end;
           m = m->next) {
            /* Add the message if it's visible */

            if (m->visible) {
                  *p++ = m;
            }
      }

      /* Terminate the array with a null pointer */

      *p = NULL;

      /* Get the destination of the message */

      to = (forms != NULL) ? formtext(forms) : NULL;

      /* Send the mail and update status */

      status = do_attach(to, NULL, messages, arg != NULL);

      /* Clean up and return status */

      free(messages);
      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *attach_tagset(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Send the messages in a tagset as an attachment or digest */

      char *tags, *to;
      int no_msgs, status;
      MESSAGE **messages, **p, *m;
      TAG_EXPR *texpr;

      /* Get the tags defining the tagset to make a digest from */

      if ((tags = get_dstr(forms, "Digestify messages tagged: ",
                       DEFAULT_TAG)) == NULL) {
            return(c_errored());
      }
      forms = (forms != NULL) ? forms->next : NULL;

      /* Convert the tags to a tag expression */

      if ((texpr = tagexpr(cwin, tags)) == NULL) {
            return(c_errored());
      }

      /* Convert any third (now second) form to an argument */

      if (forms != NULL) {
            arg = form_or_arg(forms->next, arg);
      }

      /* Count the number of messages we're attaching */

      no_msgs = 0;
      for (m = cwin->buf->messages; m->text != NULL; m = m->next) {
            /* Save the message if it's selected and visible */

            if (m->visible && tagset(m, texpr)) {
                  no_msgs++;
            }
      }

      /* Build the array of messages to attach */

      messages = (MESSAGE **) xmalloc((no_msgs + 1) * sizeof(MESSAGE *));
      p = messages;
      for (m = cwin->buf->messages; m->text != NULL; m = m->next) {
            /* Add the message if it's selected and visible */

            if (m->visible && tagset(m, texpr)) {
                  *p++ = m;
            }
      }

      /* Terminate the array with a null pointer */

      *p = NULL;

      /* Get the destination of the message */

      to = (forms != NULL) ? formtext(forms) : NULL;

      /* Send the mail and update status */

      status = do_attach(to, NULL, messages, arg != NULL);

      /* Clean up and return status */

      free(messages);
      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *open_msg(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* "Open" a message - ie. display it to typeout or to a pager */

      /* Check there is a message to open */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Open the message and return status */

      return((do_page(cwin->point, cwin->point->next,
                  get_vtext(V_PAGER), forms, arg, PG_MESSAGE))
             ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *page_msg(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Send a message to the user's preferred pager */

      /* Check there is a message to page */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Open the message and return status */

      return((do_page(cwin->point, cwin->point->next,
                  getenv(PAGER), forms, arg, PG_MESSAGE))
             ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *open_raw_msg(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* View the raw text of a message via typeout or a pager */

      /* Check there is a message to open */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Open the raw message and return status */

      return((do_page(cwin->point, cwin->point->next,
                  get_vtext(V_PAGER), forms, arg, PG_RAW))
             ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *open_body_parts(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* View the body parts of a message as messages in a new buffer */

      return((do_open_body_parts()) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *owin_open_body_parts(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* View the body parts of a message in the other window */

      int newlines = 0;
      WINDOW *oldwin = cwin;

      /* Make the new window if required */

      if ((cwin = cwin->next) == oldwin) {
            /* How many lines will the window have? */

            newlines = (cwin->bottom - cwin->top + 1) / 2;

            /* Now try to create the other window */

            if ((cwin = add_window(cwin, newlines)) == NULL) {
                  return(c_errored());
            }

            /* Display the current buffer in the new window */

            show_buffer(cwin, oldwin->buf);
      }

      /* Display the body parts in the new window */

      if (!do_open_body_parts()) {
            /* Delete any new window and fail */

            if (newlines > 0) {
                  (void) del_window(cwin);
            }
            cwin = oldwin;
            return(c_errored());
      }

      /* Update the old window and return success */

      redisplay(oldwin);
      return(c_t());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *save_msg(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Save the current message to a file */

      /* Check there is a message to save */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Get a file and save the message */

      return((do_save(MS_MESSAGE, forms, arg, cwin->point,
                  cwin->point->next, NULL)) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *save_region(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Save the messages in the region to a file */

      REGION *region;

      /* Get the region */

      if ((region = get_region(cwin)) == NULL) {
            return(c_errored());
      }

      /* Get a file and save the messages */

      return((do_save(MS_REGION, forms, arg, region->start,
                  region->end, NULL)) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *save_tagset(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
      FORM *forms;
{
      /* Save the messages in a tagset to a file */

      char *prompt, *tags;
      int status;
      TAG_EXPR *texpr;

      /* Set up the prompt for the user */

      prompt = vstrcat("Save ", (arg != NULL) ? "bodies of " : "",
                   "messages tagged: ", NULL);

      /* Get the tags defining the tagset to save */

      if ((tags = get_dstr(forms, prompt, DEFAULT_TAG)) == NULL) {
            free(prompt);
            return(c_errored());
      }
      forms = (forms != NULL) ? forms->next : NULL;
      free(prompt);

      /* Convert the tags to a tag expression */

      if ((texpr = tagexpr(cwin, tags)) == NULL) {
            return(c_errored());
      }

      /* Get a file and save the messages in the tagset */

      status = do_save(MS_TAGSET, forms, arg,
                   cwin->buf->messages, NULL, texpr);
      free_texpr(texpr);
      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *print_msg(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Print the current message */

      /* Check there is a message to print */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Print the message */

      return((do_print(MS_MESSAGE, forms, arg, cwin->point,
                   cwin->point->next, NULL)) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *print_region(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Print the messages in the region */

      REGION *region;

      /* Get the region */

      if ((region = get_region(cwin)) == NULL) {
            return(c_errored());
      }

      /* Print the messages in the region */

      return((do_print(MS_REGION, forms, arg, region->start,
                   region->end, NULL)) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *print_tagset(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Print the messages in a tagset */

      char *prompt, *tags;
      int status;
      TAG_EXPR *texpr;

      /* Set up the prompt for the user */

      prompt = vstrcat("Print ", (arg != NULL) ? (arg->negative)
                   ? "bodies of " : "with all headers " : "",
                   "messages tagged: ", NULL);

      /* Get the tags defining the tagset to print */

      if ((tags = get_dstr(forms, prompt, DEFAULT_TAG)) == NULL) {
            free(prompt);
            return(c_errored());
      }
      forms = (forms != NULL) ? forms->next : NULL;
      free(prompt);

      /* Convert the tags to a tag expression */

      if ((texpr = tagexpr(cwin, tags)) == NULL) {
            return(c_errored());
      }

      /* Print the messages in the tagset */

      status = do_print(MS_TAGSET, forms, arg,
                    cwin->buf->messages, NULL, texpr);
      free_texpr(texpr);
      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *pipe_msg(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Pipe the current message into a command */

      /* Check there is a message to pipe */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Get a command and pipe the message */

      return((do_pipe(MS_MESSAGE, forms, arg, cwin->point,
                  cwin->point->next, NULL)) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *pipe_region(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Pipe the messages in the region into a command */

      REGION *region;

      /* Get the region to pipe */

      if ((region = get_region(cwin)) == NULL) {
            return(c_errored());
      }

      /* Get a command and pipe the messages */

      return((do_pipe(MS_REGION, forms, arg, region->start,
                  region->end, NULL)) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *pipe_tagset(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Pipe the messages in a tagset into a command */

      char *prompt, *tags;
      int status;
      TAG_EXPR *texpr;

      /* Set up the prompt for the user */

      prompt = vstrcat("Pipe ", (arg != NULL) ? (arg->negative)
                   ? "bodies of " : "with all headers " : "",
                   "messages tagged: ", NULL);

      /* Get the tags defining the tagset to pipe */

      if ((tags = get_dstr(forms, prompt, DEFAULT_TAG)) == NULL) {
            free(prompt);
            return(c_errored());
      }
      forms = (forms != NULL) ? forms->next : NULL;
      free(prompt);

      /* Convert the tags to a tag expression */

      if ((texpr = tagexpr(cwin, tags)) == NULL) {
            return(c_errored());
      }

      /* Get a command and pipe the messages in the tagset */

      status = do_pipe(MS_TAGSET, forms, arg,
                   cwin->buf->messages, NULL, texpr);
      free_texpr(texpr);
      return((status) ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *edit_msg(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Store the mail in a buffer, and then call an editor on it */

      /* Check there is a message to edit */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Convert any form to an argument */

      arg = form_or_arg(forms, arg);

      /* Now edit the message and return status */

      return((edit_message(cwin, cwin->point, arg != NULL, TRUE))
             ? c_t() : c_errored());
}
/****************************************************************************/
/*ARGSUSED*/
FORM *msg_info(seq, arg, forms)
KEYSEQ *seq;
ARGUMENT *arg;
FORM *forms;
{
      /* Give miscellaneous info about the current message */

      char *dstr;

      /* Check there is a current message */

      if (!chk_msg(cwin, TRUE)) {
            return(c_errored());
      }

      /* Get the string representing the date the message was sent */

      dstr = strdate(cwin->point->date, get_vval(V_SHOW_LTIME));

      /* Output the basic message info */

      msgl("Sent ", dstr, ", ", utos(text_lines(cwin->point->text)),
           " lines", NULL);

      /* Now append the message status */

      if (cwin->point->new) {
            cmsg(", New");
      }
      if (!cwin->point->read) {
            cmsg(", Unread");
      }
      if (cwin->point->replied) {
            cmsg(", Replied");
      }
      if (cwin->point->forwarded) {
            cmsg(", Forwarded");
      }
      if (cwin->point->saved) {
            cmsg(", Saved");
      }
      if (cwin->point->printed) {
            cmsg(", Printed");
      }

      /* Now return success */

      return(c_t());
}
/****************************************************************************/
static int do_reply(group)
int group;
{
      /* Handle replying to messages */

      char *to, *cc, *ignored;

      /* Check there is a message to reply to */

      if (!chk_msg(cwin, TRUE)) {
            return(FALSE);
      }

      /* Check we know where to reply to */

      if ((to = (group) ? cwin->point->group :
           cwin->point->reply) == NULL) {
            emsgl("Can't reply: No ", (group) ? "group" :
                  "return", " address", NULL);
            return(FALSE);
      }

      /* Check which addresses are to be ignored */

      ignored = (group) ? get_vtext(V_ADDRESSES) : NULL;

      /* Strip any ignored addresses in the list */

      if ((to = subtract_addresses(to, ignored)) == NULL) {
            emsg("Can't reply: All addresses ignored");
            return(FALSE);
      }

      /* Set up any carbon-copies */

      cc = (group && get_vval(V_KEEP_CC)) ?
            subtract_addresses(cwin->point->cc, ignored) : NULL;

      /* The user may want a warning if we've already replied */

      if (get_vval(V_MREP_WARN) && cwin->point->replied) {
            if (!confirm("Already replied; reply again? ", TRUE)) {
                  free(to);
                  return(FALSE);
            }
      }

      /* Do the actual replying and update status */

      if (send_reply(to, cc, cwin->point) &&
          msg_touched(cwin, cwin->point, ST_REPLIED, FALSE)) {
            alldisplay(cwin->buf);
      }
      free(to);

      /* It all went ok */

      return(TRUE);
}
/****************************************************************************/
static int do_page(first, last, pager, forms, arg, how)
MESSAGE *first, *last;
char *pager;
FORM *forms;
ARGUMENT *arg;
int how;
{
      /* Handle displaying messages */

      static char *defcmd = DEFPAGER;
      char *cmd, *hdrlist;
      int fmt;

      /* Convert any form into an argument */

      arg = form_or_arg(forms, arg);

      /* Set or default the command to use as required */

      if ((cmd = pager) == NULL && (cmd = getenv(PAGER)) == NULL) {
            /* No variable or environment, use default */

            cmd = defcmd;
      }

      /* Which output format and headers do we need? */

      fmt = (how == PG_RAW) ? WF_TEXT | WF_SHOW | WF_NOBLANK
            : output_format(arg) | WF_NOBLANK | WF_DECODE | WF_SHOW;
      hdrlist = (WF_FMT(fmt) == WF_SOME) ? get_vtext(V_NOTDISP) : NULL;

      /* Clear the global "message status changed" flag */

      (void) msg_status_changed();

      /* Now page the messages until we're finished */

      (void) page_messages(cwin, first, last, FALSE, FALSE, cmd,
                       fmt, hdrlist, how, FALSE, 0, 0);

      /* Update the display and return success */

      if (msg_status_changed()) {
            alldisplay(cwin->buf);
      }
      return(TRUE);
}
/****************************************************************************/
static int do_save(stype, forms, arg, start, end, texpr)
int stype;
FORM *forms;
ARGUMENT *arg;
MESSAGE *start, *end;
TAG_EXPR *texpr;
{
      /* Handle saving of messages to a file */

      char *prompt, *deflt, *filnam = NULL;
      int fmt;

      /* Convert any second form into an argument */

      if (forms != NULL) {
            arg = form_or_arg(forms->next, arg);
      }

      /* Which format should we save in? */

      fmt = (arg != NULL) ? WF_BODY | WF_DECODE | WF_SHOW : WF_MBOX;

      /* Find the first message to be saved */

      while (!start->visible || texpr != NULL && !tagset(start, texpr)) {
            start = start->next;
      }

      /* Form the prompt for the file name */

      prompt = vstrcat("Save ", sname(stype, fmt), " to file: ", NULL);

      /* Get the file to save the messages to */

      if (WF_FMT(fmt) == WF_BODY && start->filename != NULL) {
            /* Default the file from the message */

            deflt = xstrdup(start->filename);
            filnam = get_dcstr(forms, prompt, deflt, fn_complete,
                           C_PERMISSIVE);
            free(deflt);
      } else if (WF_FMT(fmt) == WF_MBOX && strcmp(start->addr, ERRUSER)) {
            /* Default the file from the first message */

            deflt = vstrcat("+", local_part(start->addr), NULL);
            filnam = get_dcstr(forms, prompt, deflt, fn_complete,
                           C_PERMISSIVE);
            free(deflt);
      } else {
            /* No default file in this case */

            filnam = get_cstr(forms, prompt, fn_complete, C_PERMISSIVE);
      }
      free(prompt);

      /* Check and expand the file name */

      if (filnam == NULL) {
            return(FALSE);
      }
      filnam = expand(filnam);

      /* Now save the messages as required */

      return(save_selected(cwin, start, end, texpr, filnam,
                       sname(stype, fmt), fmt));
}
/****************************************************************************/
static int do_print(stype, forms, arg, start, end, texpr)
int stype;
FORM *forms;
ARGUMENT *arg;
MESSAGE *start, *end;
TAG_EXPR *texpr;
{
      /* Handle printing of messages */

      char *cmd;
      int fmt;

      /* Convert any form into an argument */

      arg = form_or_arg(forms, arg);

      /* Which output format do we need */

      fmt = output_format(arg) | WF_DECODE | WF_SHOW;

      /* Get the commands to print with */

      if ((cmd = get_vtext(V_PRINT_CMD)) == NULL) {
            emsg("Can't print: print-command variable not set");
            return(FALSE);
      }

      /* Check we really mean to do this */

      if (get_vval(V_ASK_PRINT) && !confirm("Confirm print? ", TRUE)) {
            return(FALSE);
      }

      /* Now save the messages as required */

      return(print_selected(cwin, start, end, texpr, cmd,
                        sname(stype, fmt), fmt));
}
/****************************************************************************/
static int do_pipe(stype, forms, arg, start, end, texpr)
int stype;
FORM *forms;
ARGUMENT *arg;
MESSAGE *start, *end;
TAG_EXPR *texpr;
{
      /* Handle piping of messages */

      char *prompt, *cmd;
      int fmt;

      /* Convert any second form into an argument */

      if (forms != NULL) {
            arg = form_or_arg(forms->next, arg);
      }

      /* Which output format do we need? */

      fmt = output_format(arg) | WF_DECODE | WF_SHOW;

      /* Form the prompt for the command */

      prompt = vstrcat("Pipe ", sname(stype, fmt),
                   " into command: ", NULL);

      /* Get the command to pipe into */

      if ((cmd = get_str(forms, prompt)) == NULL) {
            free(prompt);
            return(FALSE);
      }
      free(prompt);

      /* Now pipe the messages as required */

      return(pipe_selected(cwin, start, end, texpr, cmd,
                       sname(stype, fmt), fmt));
}
/****************************************************************************/
static int do_open_body_parts()
{
      /* Open a buffer containing a message's body-parts */
      
      char *name, *unique;
      MAILBUF *buf;
      MESSAGE *body_parts;

      /* Check there is a current message */

      if (!chk_msg(cwin, TRUE)) {
            return(FALSE);
      }

      /* Get the body parts of the message */

      if ((body_parts = expand_message(cwin, cwin->point)) == NULL) {
            /* No submessage and not a valid digest either */

            emsg("Message does not have any body parts");
            return(FALSE);
      }

      /* Set up the buffer name and add the buffer */

      name = vstrcat("Message from ", cwin->point->from, NULL);
      unique = unique_name(cwin->buf, name);
      buf = add_buffer(cwin->buf, unique, NULL, NULL,
                   M_MAIL | M_BODY_PARTS);

      /* Clean up the names */

      free(name);
      free(unique);

      /* Set up the buffer's details */

      buf->point = buf->messages = body_parts;
      buf->no_msgs = count_messages(buf->messages, TRUE);
      buf->st_mod = TRUE;

      /* Now update the display and return success */

      show_buffer(cwin, buf);
      redisplay(cwin);
      return(TRUE);
}     
/****************************************************************************/
static int do_attach(to, subject, messages, all_headers)
char *to, *subject;
MESSAGE **messages;
int all_headers;
{
      /* Handle including one or more messages in an outgoing mail */

      int status, touched = FALSE;
      MESSAGE **m;

      /* Send the mail and check status */

      
      if (status = send_attached(to, subject, messages, all_headers)) {
            /* Update the status of the attached messages */

            for (m = messages; m != NULL && *m != NULL; m++) {
                  touched = msg_touched(cwin, *m, ST_FORWARDED, FALSE)
                        || touched;
            }

            /* Update the display if required */

            if (touched) {
                  alldisplay(cwin->buf);
            }
      }

      /* And return status */

      return(status);
}
/****************************************************************************/
static int output_format(arg)
ARGUMENT *arg;
{
      /* Calculate which output format we need according to arg */

      return((arg != NULL) ? (arg->negative) ? WF_BODY : WF_TEXT : WF_SOME);
}
/****************************************************************************/
static char *sname(stype, fmt)
int stype, fmt;
{
      /* Return text describing a selection of messages */

      static char *msg_types[] = {
            "message", "region", "tagset"
      };
      static char *hdr_types[] = {
            "message with all headers", "region with all headers",
            "tagset with all headers"
      };
      static char *bdy_types[] = {
            "message body", "region bodies", "tagset bodies"
      };

      /* Simply return the correct entry from the arrays */

      return((WF_FMT(fmt) == WF_BODY) ? bdy_types[stype]
             : (WF_FMT(fmt) & WF_TEXT) ? hdr_types[stype]
             : msg_types[stype]);
}
/****************************************************************************/

Generated by  Doxygen 1.6.0   Back to index