/* read.c */

#include "ml.h"

Menu read_save_menu[] = {
  { NULL, "fullhead", NUL_TERM,
      read_savefull, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "parthead", NUL_TERM,
      read_savepart, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "nonehead", NUL_TERM,
      read_savenone, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_pipe_menu[] = {
  { NULL, "fullhead", NUL_TERM,
      read_execfull, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "parthead", NUL_TERM,
      read_execpart, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "nonehead", NUL_TERM,
      read_execnone, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_print_menu[] = {
  { NULL, "fullhead", NUL_TERM,
      read_printfull, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "parthead", NUL_TERM,
      read_printpart, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "nonehead", NUL_TERM,
      read_printnone, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_file_menu[] = {
  { NULL, "view_attachment", NUL_TERM,
      read_view_attach, NULL, 0, NULL, NULL, BTN_NOATTACHSELECT },
  { NULL, "save_attachment", NUL_TERM,
      read_save_attach, NULL, 0, NULL, NULL, BTN_NOATTACHSELECT },
  { NULL, "copy", NUL_TERM,
      read_copy, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "print_menu", NUL_TERM, 
      NULL, read_print_menu, XtNumber(read_print_menu), NULL, NULL, BTN_ON },
  { NULL, "save_menu", NUL_TERM,
      NULL, read_save_menu, XtNumber(read_save_menu), NULL, NULL, BTN_ON },
  { NULL, "pipe_menu", NUL_TERM,
      NULL, read_pipe_menu, XtNumber(read_pipe_menu), NULL, NULL, BTN_ON },
  { NULL, "browse_url", NUL_TERM,
      read_browse_url, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "address_book", NUL_TERM,
      main_address_book, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "note_book", NUL_TERM,
      main_note_book, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "close_window", NUL_TERM,
      read_close_window,   NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_setflags_menu[] = {
  { NULL, "set_deleted", NUL_TERM,
      read_set_deleted, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "set_seen", NUL_TERM,
      read_set_seen, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "set_flagged", NUL_TERM,
      read_set_flagged, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "set_answered", NUL_TERM,
      read_set_answered, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_clearflags_menu[] = {
  { NULL, "clear_deleted", NUL_TERM,
      read_clear_deleted, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "clear_seen", NUL_TERM,
      read_clear_seen, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "clear_flagged", NUL_TERM,
      read_clear_flagged, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "clear_answered", NUL_TERM,
      read_clear_answered, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_edit_menu[] = {
  { NULL, "select_text", NUL_TERM,
      read_select_text, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "copy_text", NUL_TERM,
      read_copy_text, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "kill_current", NUL_TERM,
      read_kill_current, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "trash_current", NUL_TERM,
      read_trash_current, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "setflags_menu", NUL_TERM,
      NULL, read_setflags_menu, XtNumber(read_setflags_menu), 
      NULL, NULL, BTN_ON },
  { NULL, "clearflags_menu", NUL_TERM,
      NULL, read_clearflags_menu, XtNumber(read_clearflags_menu),
      NULL, NULL, BTN_ON },
};




Menu read_option_menu[] = {
  { NULL, "full_header", NUL_TERM,
      read_full_header, NULL, 0, NULL, NULL, BTN_SHORT_HEADER },
  { NULL, "short_header", NUL_TERM,
      read_short_header, NULL, 0, NULL, NULL, BTN_LONG_HEADER },
  { NULL, "takeaddr", NUL_TERM,
      read_address, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_reply_submenu[] = {
  { NULL, "reply_sender", NUL_TERM,
      read_reply_sender, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "reply_all", NUL_TERM,
      read_reply_all, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_forward_submenu[] = {
  { NULL, "forward", NUL_TERM,
      read_forward, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "forward_attach", NUL_TERM,
      read_forward_attach, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_send_menu[] = {
  { NULL, "compose_new", NUL_TERM,
      main_compose, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "reply_menu", NUL_TERM,
      NULL, read_reply_submenu, XtNumber(read_reply_submenu), 
      NULL, NULL, BTN_ON },
  { NULL, "forward_menu", NUL_TERM,
      NULL, read_forward_submenu, XtNumber(read_forward_submenu),
      NULL, NULL, BTN_ON },
  { NULL, "remail", NUL_TERM,
      read_remail, NULL, 0, NULL, NULL, BTN_ON },
};

Menu read_menu[] = {
  { NULL, "file_menu", NUL_TERM,
      NULL, read_file_menu, XtNumber(read_file_menu), 
      NULL, NULL, BTN_ON },
  { NULL, "edit_menu", NUL_TERM,
      NULL, read_edit_menu, XtNumber(read_edit_menu), 
      NULL, NULL, BTN_ON },
  { NULL, "option_menu", NUL_TERM,
      NULL, read_option_menu, XtNumber(read_option_menu), 
      NULL, NULL, BTN_ON },
  { NULL, "send_menu", NUL_TERM,
      NULL, read_send_menu, XtNumber(read_send_menu), 
      NULL, NULL, BTN_ON },
  { NULL, "prevwin", NUL_TERM,
      read_prev, NULL, 0, NULL, NULL, BTN_NOPREV },
  { NULL, "nextwin", NUL_TERM,
      read_next, NULL, 0, NULL, NULL, BTN_NONEXT },
  { NULL, "read_delete", NUL_TERM,
      read_set_deleted, NULL, 0, NULL, NULL, BTN_ON },
  { NULL, "HELP", NUL_TERM,
      read_help, NULL, 0,
      NULL, NULL, BTN_ON },
};


Button_Menu read_secondbuttons[] = {
  { "read_get_next_btn",    read_get_next,      NULL, BTN_ON,          NULL },
  { "read_trash_btn",       read_trash_current, NULL, BTN_ON,          NULL },
  { "read_copy_btn",        read_copy,          NULL, BTN_ON,          NULL },
  { "read_save_btn",        read_savepart,      NULL, BTN_ON,          NULL },
  { "read_reply_btn",       read_reply_sender,  NULL, BTN_ON,          NULL },
  { "read_replyall_btn",    read_reply_all,     NULL, BTN_ON,          NULL },
  { "read_dismiss_btn",     read_close_window,  NULL, BTN_ON,          NULL },
};



#ifdef __STDC__
void read_check_buttons(void)
#else
void read_check_buttons()
#endif
{
  ButtonState state;
  Read *read;

  for(read = session->read; read; read = read->next) {
    state = (read->current) ? read->current->button_state : BTN_ON;
    update_buttons(read->buttonlist, state);
  }
  return;
}






#ifdef __STDC__
Read *new_read(void)
#else
Read *new_read()
#endif
{
  Read *read = (Read *) fs_get(sizeof(Read));
  
  read->current          = NULL;
  read->read_info        = NULL;
  read->is_realized      = FALSE;
  read->buttonlist       = NULL;
  read->next             = NULL;
  read->prev             = NULL;
  return(read);
}


#ifdef __STDC__
Read_Info *new_read_info(void)
#else 
Read_Info *new_read_info() 
#endif
{
  Read_Info *read_info = (Read_Info *) fs_get(sizeof(Read_Info));

  read_info->message_type     = MESSAGE_NORMAL;
  read_info->mailbox_type     = MAILBOX_TYPE_MAIL;
  read_info->message          = NULL;
  read_info->mailstream       = NULL;
  read_info->lview            = NULL;
  read_info->msgno            = 0L;
  read_info->serialno         = 0L;
  read_info->fetched          = FALSE;
  read_info->visible          = FALSE;
  read_info->expunged         = FALSE;
  read_info->selected         = FALSE;
  read_info->amount           = 100;
  read_info->server           = NULL;
  read_info->current_part_str = NULL;
  read_info->base_part_str    = NULL;
  read_info->short_header     = NULL;
  read_info->header           = NULL;
  read_info->current_text     = NULL;
  read_info->alt_text         = NULL;
  read_info->current_part     = NULL;
  read_info->body             = NULL;
  read_info->envelope         = NULL;
  read_info->attachments      = NULL;
  read_info->button_state     = BTN_ON | BTN_LONG_HEADER;
  read_info->number           = 0L;
  read_info->selection        = 0L;
  read_info->show_long_header = FALSE;
  read_info->show_entire      = FALSE;
  read_info->show_alt         = FALSE;
  read_info->rfc_msg_leaf     = FALSE;
  read_info->part_list        = NULL;
  read_info->next             = NULL;
  read_info->prev             = NULL;

  return(read_info);
}


#ifdef __STDC__
void free_read_info(Read_Info *read_info)
#else
void free_read_info(read_info)
     Read_Info *read_info;
#endif
{
  if(read_info == NULL)
    return;
  read_info->msgno = 0L;
  if(read_info->current_part_str)
    fs_give((void **) &read_info->current_part_str);
  if(read_info->base_part_str)
    fs_give((void **) &read_info->base_part_str);
  if(read_info->short_header)
    fs_give((void **) &read_info->short_header);
  if(read_info->header)
    fs_give((void **) &read_info->header);
  if(read_info->current_text)
    fs_give((void **) &read_info->current_text);
  if(read_info->alt_text)
    fs_give((void **) &read_info->alt_text);
  if(read_info->part_list)
    destroy_part_list(read_info->part_list);
  read_info->part_list = NULL;
  fs_give((void **) &read_info);
}

#ifdef __STDC__
void read_messagelist(MainWindow *mwin, Lview *lview, 
		      Message_List *message_list, int amount, Boolean newwin)
#else
void read_messagelist(mwin,lview,message_list, amount, newwin)
     MainWindow *mwin;
     Lview *lview;
     Message_List *message_list;
     int amount;
     Boolean newwin;
#endif
{
  Read *read = NULL;
  Message_List *select_list;
  Read_Info *read_info;
  Read_Info *first_message = NULL;
  Message *message;

  if(newwin == FALSE) {
    for(read = session->read; read; read = read->next) {
      if((read->read_info != NULL) && (read->read_info->lview == lview))
	break;
    }
  }
  if(read == NULL)
    read = create_read_window();
  if(read == NULL)
    return;

  de_iconify(read->shell);

  for(select_list = message_list; select_list;
      select_list = select_list->next) {
    if(select_list->selected == TRUE) {
      message = select_list->message;
      if(message->fetched == FALSE)
	continue;
      read_info = new_read_info();
      read_info->serialno = mwin->serialno;
      if(first_message == NULL)
	first_message = read_info;
      read_info->lview = lview;
      read_info->amount = amount;
      read_info->mailstream = message->mailstream;
      read_info->msgno = message->msgno;
      read_info->message = message;
      read_info->server = cpystr(message->mailbox->host);
      read_info->current_part_str = cpystr(PART_ONE_STR);
      read_info->mailbox_type = message->mailbox->type;

      if(read_info->mailbox_type == MAILBOX_TYPE_NEWS)
	read_info->button_state |= BTN_ISNEWS;

      read_info->button_state |= BTN_NOATTACHSELECT;
      read_info->envelope = message->envelope;
      read_info->body = message->body;

      if((read_info->body) && (read_info->body->type == TYPEMULTIPART))
	read_info->attachments = read_info->body->contents.part;

      read_new_link(read,read_info);
    }
  }

  if(first_message != NULL) {
    if((first_message->body != NULL) 
       && (first_message->body->type == TYPEMESSAGE) 
       && (first_message->body->subtype != NULL)
       && ((strcasecmp(first_message->body->subtype,"rfc822")) == STRMATCH)) {
      read_rfc822(read_info,first_message->current_part_str,
		  first_message->body);
      return;
    }
    read_fetch(first_message, first_message->body);
    read_context_switch(read,NULL,first_message);
  }
  return;
}

#ifdef __STDC__
void read_load_next(Read_Info *info)
#else
void read_load_next(info)
     Read_Info *info;
#endif
{
  Read *read;
  Mailbox *mailbox;
  Message *message = NULL;
  Message_List *ml;
  Read_Info *read_info;

  if((info == NULL) || (info->msgno == 0) || (info->mailstream == NULL) 
     || (info->lview == NULL))
    return;

  read = find_read_window(info);
  mailbox = info->lview->mailbox;

  if((read == NULL) || (mailbox == NULL))
    return;
  


  for(ml = info->lview->message_list; ml; ml = ml->next ) {
    if(ml->message == info->message) {
      message = (ml->next) ? ml->next->message : NULL;
      view_select_from_read(info->lview,message);
      break;
    }
  }
  if(message) {
    if(message->fetched == FALSE)
      return;

    read_info = new_read_info();
    read_info->serialno = info->serialno;
    read_info->amount = info->amount;
    read_info->mailstream = message->mailstream;
    read_info->lview = info->lview;
    read_info->msgno = message->msgno;
    read_info->message = message;
    read_info->server = cpystr(message->mailbox->host);
    read_info->current_part_str = cpystr(PART_ONE_STR);
    read_info->mailbox_type = message->mailbox->type;

    if(read_info->mailbox_type == MAILBOX_TYPE_NEWS)
      read_info->button_state |= BTN_ISNEWS;

    read_info->button_state |= BTN_NOATTACHSELECT;
    read_info->envelope = message->envelope;
    read_info->body = message->body;

    if((read_info->body) && (read_info->body->type == TYPEMULTIPART))
      read_info->attachments = read_info->body->contents.part;

    read_kill_all(NULL, read, NULL);

    read_new_link(read,read_info);

    if((read_info->body != NULL) 
       && (read_info->body->type == TYPEMESSAGE) 
       && (read_info->body->subtype != NULL)
       && ((strcasecmp(read_info->body->subtype,"rfc822")) == STRMATCH)) {
      read_rfc822(read_info,read_info->current_part_str,
		  read_info->body);
      return;
    }

    read_fetch(read_info, read_info->body);
    read_context_switch(read,NULL,read_info);
    read_check_buttons();
  }
  else
    read_kill_all(NULL, read, NULL);
  return;
}

#ifdef __STDC__
void read_lview_detach(Lview *lview)
#else
void read_lview_detach(lview)
     Lview *lview;
#endif
{
  Read *read;
  Read_Info *info;

  for(read = session->read; read; read = read->next ) 
    for(info = read->read_info; info; info = info->prev)
      if(info->lview == lview)
	info->lview = NULL;
  return;
}

#ifdef __STDC__
Read *create_read_window(void)
#else
Read *create_read_window()
#endif
{
  Arg args[ARGLISTSIZE];
  int n = 0;
  XtTranslations translations;
  Read *prev;
  Read *read;


  read = new_read();

  if(session->read == NULL) 
    session->read = read;
  else {
    for(prev = session->read; prev->next; prev = prev->next)
      ;
    prev->next = read;
    read->prev = prev;
  }
  XtSetArg (args[n], XmNdeleteResponse, XmDO_NOTHING); n++;   
  read->shell = XtCreatePopupShell("read", topLevelShellWidgetClass,
				   session->shell, args,n);
  n = 0;
  AddDestroyCallback(read->shell);
  setup_editres(read->shell);

  if(read_icon != (Pixmap) None)
    XtVaSetValues(read->shell,
		  XmNiconPixmap,read_icon,
		  NULL);

  read->form = XmCreateForm(read->shell, "form", args, n);      n = 0;

  XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM);           n ++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM);          n ++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);         n ++;
  read->menubar = XmCreateMenuBar(read->form,"menubar", args, n);     n = 0;
  XtManageChild(read->menubar);

  make_buttons(&read->buttonlist, NULL, read->menubar, 
	       read_menu, XtNumber(read_menu), 
	       BTN_ON, (XtPointer) read, ROOTMENULEVEL);





  XtSetArg(args[n], XmNadjustMargin, FALSE);      n ++;
  XtSetArg(args[n], XmNmarginWidth, 0);           n ++;
  XtSetArg(args[n], XmNborderWidth, 0);           n ++;

  XtSetArg(args[n], XmNtopAttachment,   XmATTACH_WIDGET);       n ++;
  XtSetArg(args[n], XmNtopWidget, read->menubar);                     n ++;
  XtSetArg(args[n], XmNleftAttachment,  XmATTACH_FORM);         n ++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);         n ++;
  XtSetArg(args[n], XmNorientation, XmHORIZONTAL);              n ++;
  XtSetArg(args[n], XmNpacking, XmPACK_COLUMN);                  n ++;
  read->rowcol = XmCreateRowColumn(read->form, "rowcol", args, n);    n = 0;
  XtManageChild(read->rowcol);

  make_secondbuttons(read->buttonlist, read->rowcol, 
		     read_secondbuttons, XtNumber(read_secondbuttons),
		     BTN_ON, (XtPointer) read);



  XtSetArg(args[n], XmNtopAttachment,   XmATTACH_WIDGET);        n ++;
  XtSetArg(args[n], XmNleftAttachment,  XmATTACH_FORM);          n ++;
  XtSetArg(args[n], XmNtopWidget,       read->rowcol);           n ++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);          n ++;
  XtSetArg(args[n], XmNtraversalOn,     FALSE);                  n ++;

  XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n ++;
  XtSetArg(args[n], XmNvalue, 100); n ++;
  read->slider = XmCreateScale(read->form, "slider", args, n);
  n = 0;
  XtManageChild(read->slider);





  XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET );         n ++;
  XtSetArg(args[n], XmNtopWidget, read->slider);                 n ++;
  XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM);           n ++;
  XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);          n ++;
  XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM);         n ++;
  XtSetArg(args[n], XmNsashHeight, 6);                           n ++;
  XtSetArg(args[n], XmNsashWidth, 12);                           n ++;
  XtSetArg(args[n], XmNspacing, 4);                              n ++;

  read->pane = XmCreatePanedWindow(read->form,"pane", args, n);  n = 0;


  XtSetArg(args[n], XmNpaneMinimum, 30);                         n ++;
  XtSetArg(args[n], XmNeditable, FALSE);                         n ++;
  XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT);             n ++;
  XtSetArg(args[n], XmNwordWrap, TRUE);                          n ++;
  XtSetArg(args[n], XmNrows,     4);                             n ++;
  XtSetArg(args[n], XmNcolumns,  80);                            n ++;
  XtSetArg(args[n], XmNscrollVertical, TRUE);                    n ++;
  XtSetArg(args[n], XmNscrollHorizontal, FALSE );                n ++;
  read->read_header = 
    XmCreateScrolledText(read->pane, "header", args, n);         n = 0;
  XtManageChild(read->read_header);

  translations = XtParseTranslationTable(GLOBAL_text_translations);
  XtOverrideTranslations(read->read_header, translations);

  XtSetArg(args[n], XmNpaneMinimum, 45);                         n ++;
  XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC);        n ++;
  XtSetArg(args[n], XmNlistSizePolicy,XmCONSTANT);               n ++;
  XtSetArg(args[n], XmNvisibleItemCount, VISIBLE_ATTACHMENTS );  n ++; 
  XtSetArg(args[n], XmNselectionPolicy,XmSINGLE_SELECT);         n ++;
  read->read_attach = XmCreateScrolledList(read->pane,"list",args,n);  
  n = 0;

  XtAddCallback(read->read_attach,
		XmNsingleSelectionCallback, 
		(XtCallbackProc) read_select_attach, read);
  XtAddCallback(read->read_attach,
		XmNdefaultActionCallback, 
		(XtCallbackProc) read_exec_attach, read);

  XtManageChild(read->read_attach); 

  XtSetArg(args[n], XmNpaneMinimum, 30);                         n ++;
  XtSetArg(args[n], XmNeditable, FALSE);                         n ++;
  XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT);             n ++;
  XtSetArg(args[n], XmNwordWrap, TRUE);                          n ++;
  XtSetArg(args[n], XmNcolumns,  80);                            n ++;
  XtSetArg(args[n], XmNscrollVertical, TRUE);                    n ++;
  XtSetArg(args[n], XmNscrollHorizontal, FALSE );                n ++;
  read->read_text = 
    XmCreateScrolledText(read->pane, "text", args, n);           n = 0;

  XtManageChild(read->read_text);

  translations = XtParseTranslationTable(GLOBAL_text_translations);
  XtOverrideTranslations(read->read_text, translations);

  translations = XtParseTranslationTable(GLOBAL_read_pop_translations);
  XtOverrideTranslations(read->read_text, translations);

  XtAddCallback(read->shell, XmNdestroyCallback, 
		(XtCallbackProc) read_destroy, read);

  XtManageChild(read->pane);
  XtManageChild(read->form);
  XtManageChild(read->shell);
  XtPopup(read->shell,XtGrabNone);
  XmProcessTraversal(read->read_text, XmTRAVERSE_CURRENT);
  read->is_realized = TRUE;
  return(read);
}

#ifdef __STDC__
void read_close_window(Widget w, Read *read, XtPointer xp)
#else
void read_close_window(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  if(read == session->read)
    session->read = read->next;
  if(read->next)
    read->next->prev = read->prev;
  if(read->prev)
    read->prev->next = read->next;

  XtPopdown(read->shell);
  XtDestroyWidget(read->shell);
  return;
}


#ifdef __STDC__
void read_destroy(Widget w, Read *read, XtPointer xp)
#else
void read_destroy(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  Read *dead;

  for(dead = session->read; dead; dead = dead->next)
    if(dead == read) {           /* still linked to session */
      if(read == session->read)
	session->read = read->next;
      if(read->next)
	read->next->prev = read->prev;
      if(read->prev)
	read->prev->next = read->next;
    }
  read_kill_all(w,read,xp);
  free_buttonlist(read->buttonlist);
  fs_give((void **) &read);
  return;
}



#ifdef __STDC__
void read_help(Widget w, Read *read, XtPointer xp)
#else
void read_help(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  help(read->shell, READWINDOWHELPFILE);
  return;
}

#ifdef __STDC__
void read_next(Widget w, Read *read, XtPointer xp)
#else
void read_next(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  if(read->current->next)
    read_context_switch(read,read->current,read->current->next);
  return;
}

#ifdef __STDC__
void read_prev(Widget w, Read *read, XtPointer xp)
#else
void read_prev(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  if(read->current->prev)
    read_context_switch(read,read->current,read->current->prev);
  return;
}



#ifdef __STDC__
void read_address(Widget w, Read *read, XtPointer xp)
#else
void read_address(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  char *from;
  char *name;
  Address_Book_Info *info;

  if((read == NULL) 
     || (read->current == NULL) 
     || (read->current->header == NULL))
    return;

  from = get_header_field_contents("reply-to",read->current->header);
  if(from == NULL)
    from = get_header_field_contents("sender", read->current->header);
  if(from == NULL)
    from = get_header_field_contents("from", read->current->header);
  if(*from == NUL_TERM)
    return;

  name = input_string(read->shell,MLGetLocalized(XtNmsgAddressName,
						 MsgAddressName),
		      NULL,ADDRTAKEHELPFILE);
  if(name == NULL) {
    fs_give((void **) &from);
    return;
  }

  info = new_address_book_info();
  info->name    = (unsigned char *) name;
  info->address = (unsigned char *) from;
  info->groups  = (unsigned char *) cpystr(EMPTYSTR);
  info->comment = (unsigned char *) cpystr(EMPTYSTR);

  if(session->addresses == NULL)
    session->addresses = info;
  else {
    info->prev = session->addresses;
    session->addresses->next = info;
    session->addresses = info;
  }
  if((session->address_book != NULL) 
     && (session->address_book->is_realized == TRUE)) {
    address_sort(session->address_book);
    address_reset(NULL, session->address_book, NULL);
  }
  save_defaults();
  return;

}





#ifdef __STDC__
void read_copy(Widget w, Read *read, XtPointer xp)
#else
void read_copy(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  char *mailboxname;
  Boolean changed;
  char sequence[32];
  int result;
  Boolean move;

  if(read->current && read->current->mailstream && read->current->msgno) {
    mailboxname = 
      get_mailbox_name(read->shell, 
		       (read->current->server) 
		       ? read->current->server 
		       : EMPTYSTR,
		       &changed, &move);
    if(mailboxname == NULL)
      return;
    if(*mailboxname == NUL_TERM) {
      fs_give((void **) &mailboxname);
      return;
    }

    push_cursor(WATCH_CURSOR); 

    if(changed == TRUE) {

      result = copy_message_to_mailbox(read->current->mailstream,
				       read->current->msgno,
				       mailboxname);
      if(move) {
	if(result == SYSCALL_SUCCESS) {
	  update_view_line_stream_msgno(read->current->mailstream,
					read->current->msgno);
	  mm_log(MLGetLocalized(XtNmsgMoveSuccess,MsgMoveSuccess), NIL);
	}
	else
	  mm_log(MLGetLocalized(XtNmsgMoveFail,MsgMoveFail), WARN);
      }
      else {
	if(result == SYSCALL_SUCCESS)
	  mm_log(MLGetLocalized(XtNmsgCopySuccess,MsgCopySuccess), NIL);
	else
	  mm_log(MLGetLocalized(XtNmsgCopyFail,MsgCopyFail), WARN);
      }
    }
    else {
      sprintf(sequence,"%lu",read->current->msgno);
      if(move) {
	result = mail_move(read->current->mailstream, sequence, mailboxname);
	if(result == T) {
	  update_view_line_stream_msgno(read->current->mailstream,
					read->current->msgno);
	  mm_log(MLGetLocalized(XtNmsgMoveSuccess,MsgMoveSuccess), NIL);
	}
	else
	  mm_log(MLGetLocalized(XtNmsgMoveFail,MsgMoveFail), WARN);
      }
      else {
	result = mail_copy(read->current->mailstream, 
			   sequence, mailboxname); 
	if(result == T) 
	  mm_log(MLGetLocalized(XtNmsgCopySuccess,MsgCopySuccess), NIL);
	else
	  mm_log(MLGetLocalized(XtNmsgCopyFail,MsgCopyFail), WARN);
      }
    }
    fs_give((void **) &mailboxname);
    pop_cursor();
  }
  else
    mm_log(MLGetLocalized(XtNmsgCopyFail,MsgCopyFail), WARN);

  return;
}

#ifdef __STDC__
void read_full_header(Widget w, Read *read, XtPointer xp)
#else
void read_full_header(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read->current->show_long_header = TRUE;
  read->current->button_state |=  BTN_SHORT_HEADER;
  read->current->button_state &= ~(BTN_LONG_HEADER);
  read_context_switch(read,NULL, read->current);
  return;
}

#ifdef __STDC__
void read_short_header(Widget w, Read *read, XtPointer xp)
#else
void read_short_header(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read->current->show_long_header = FALSE;
  read->current->button_state |=  BTN_LONG_HEADER;
  read->current->button_state &= ~(BTN_SHORT_HEADER);
  read_context_switch(read,NULL, read->current);
  return;
}

#ifdef __STDC__
void read_savefull(Widget w, Read *read, XtPointer xp)
#else
void read_savefull(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_save_dispatch(read,HEADER_FULL);
  return;
}

#ifdef __STDC__
void read_savepart(Widget w, Read *read, XtPointer xp)
#else
void read_savepart(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_save_dispatch(read,HEADER_PART);
  return;
}

#ifdef __STDC__
void read_savenone(Widget w, Read *read, XtPointer xp)
#else
void read_savenone(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_save_dispatch(read,HEADER_NONE);
  return;
}


#ifdef __STDC__
void read_save_dispatch(Read *read, Header_Mode header_mode)
#else
void read_save_dispatch(read,header_mode)
     Read *read;
     Header_Mode header_mode;
#endif
{
  FILE *fp;
  char *filename;
  int errors = 0;
  char *header_text = NULL;
  char *body_text;
  Boolean append_it;
  filename = file_select(read->shell, NULL, NULL, NULL, TRUE, &append_it);
  if(filename == NULL)
    return;

  push_cursor(WATCH_CURSOR);

  if(header_mode == HEADER_FULL)
    header_text = read->current->header;
  if(header_mode == HEADER_PART)
    header_text = read->current->short_header;

  if(read->current->alt_text)
    body_text = read->current->alt_text;
  else
    body_text = read->current->current_text;

  
  if((fp = fopen(filename,(append_it == TRUE) ? "a" : "w")) != NULL) {
    (void) chmod(filename,S_IRWXU);
    if((header_mode != HEADER_NONE) && (header_text != NULL)) {
      if((fwrite(header_text,strlen(header_text),1,fp)) != 1)
	errors ++;
      if((fwrite(LFSTR,1,1,fp)) != 1)
	errors ++;
    }
    if((fwrite(body_text,strlen(body_text),1,fp)) != 1)
      errors ++;
    if((fclose(fp)) != SYSCALL_SUCCESS)
      errors ++;
  }
  else
    errors ++;

  fs_give((void **) &filename);

  if(errors)
    mm_log(MLGetLocalized(XtNmsgSaveFail,MsgSaveFail),WARN);
  else
    mm_log(MLGetLocalized(XtNmsgSaveSuccess,MsgSaveSuccess), NIL);

  pop_cursor();
}



#ifdef __STDC__
void read_printfull(Widget w, Read *read, XtPointer xp)
#else
void read_printfull(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_print_dispatch(w,read,HEADER_FULL);
  return;
}

#ifdef __STDC__
void read_printpart(Widget w, Read *read, XtPointer xp)
#else
void read_printpart(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_print_dispatch(w,read,HEADER_PART);
  return;
}

#ifdef __STDC__
void read_printnone(Widget w, Read *read, XtPointer xp)
#else
void read_printnone(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_print_dispatch(w,read,HEADER_NONE);
  return;
}

#ifdef __STDC__
void read_print_dispatch(Widget w, Read *read, Header_Mode header_mode)
#else
void read_print_dispatch(w,read,header_mode)
     Widget w;
     Read *read;
     Header_Mode header_mode;
#endif
{
  char *header = NULL;

  if(*preferences.print_command == NUL_TERM) {
    mm_log(MLGetLocalized(XtNmsgNoPrintCommand,MsgNoPrintCommand), WARN);
    return;
  }

  push_cursor(WATCH_CURSOR);
  
  if(header_mode == HEADER_FULL)
    header = read->current->header;
  if(header_mode == HEADER_PART)
    header = read->current->short_header;


  if(write_to_pipe(preferences.print_command, header,
		(read->current->alt_text)
		? read->current->alt_text : read->current->current_text,
		(read->current->alt_text)
		? strlen(read->current->alt_text) 
		: strlen(read->current->current_text)))

    mm_log(MLGetLocalized(XtNmsgPrintFail,MsgPrintFail), WARN);
  else
    mm_log(MLGetLocalized(XtNmsgPrintSuccess,MsgPrintSuccess), NIL);

  pop_cursor();
  return;
}

#ifdef __STDC__
char *find_url(char *s)
#else
char *find_url(s)
     char *s;
#endif
{
  char *ptr;
  char *tmp;
  char *ret;
  int n = 0;

  if((s == NULL) || (ptr = ML_Strstr(s,URL_SIG_STR)) == NULL)
    return(NULL);

  if(ptr > s)
    ptr --;
  while(ptr >= s && isalpha(*ptr))
	   ptr --;
  ptr ++;
  tmp = ptr;

  while((*ptr) && ((!isspace(*ptr)) && (*ptr != '\"') 
	&& (*ptr != '}') && (*ptr != ')') && (*ptr != '>'))) {
    ptr ++;
    n ++;
  }

  ret = (char *) fs_get((unsigned) n + 16);
  strncpy(ret,tmp,n);
  ret[n] = 0;
  return(ret);
}

#ifdef __STDC__
void read_browse_url(Widget w, Read *read, XtPointer xp)
#else
void read_browse_url(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  XmTextPosition left, right;
  char command[FILEBUFFLEN];
  char log[FILEBUFFLEN];
  char *temp_url = NULL;
  char *url = NULL;

  if(*preferences.url_command == NUL_TERM) {
    mm_log(MLGetLocalized(XtNmsgNoWebBrowser,MsgNoWebBrowser), WARN);
    return;
  }

  if((ML_Strstr(preferences.url_command,"%s")) == NULL) {
    mm_log(MLGetLocalized(XtNmsgWebCommand,MsgWebCommand), WARN);
    return;
  }

  XmTextGetSelectionPosition(read->read_text, &left, &right);
  if(left != right) {
    temp_url = XmTextGetSelection(read->read_text);
  }
  else {
    temp_url = find_url((read->current->alt_text) 
		   ? read->current->alt_text : read->current->current_text);
  }

  if(temp_url == NULL)
    return;

  url = input_string(read->shell, MLGetLocalized(XtNmsgShowURL,MsgShowURL), 
		     temp_url, SHOWURLHELPFILE);
  fs_give((void **) &temp_url);

  if(url == NULL)
    return;

  if(*url == NUL_TERM) {
    fs_give((void **) &url);
    return;
  }

  push_cursor(WATCH_CURSOR);
  sprintf(command,preferences.url_command,url);
  sprintf(log,MLGetLocalized(XtNmsgExecuting,MsgExecuting), command);
  mm_log(log,NIL);
  system(command);
  fs_give((void **) &url);
  pop_cursor();
  return;
}

#ifdef __STDC__
void read_execfull(Widget w, Read *read, XtPointer xp)
#else
void read_execfull(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_exec_dispatch(w,read,HEADER_FULL);
  return;
}

#ifdef __STDC__
void read_execpart(Widget w, Read *read, XtPointer xp)
#else
void read_execpart(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_exec_dispatch(w,read,HEADER_PART);
  return;
}

#ifdef __STDC__
void read_execnone(Widget w, Read *read, XtPointer xp)
#else
void read_execnone(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_exec_dispatch(w,read,HEADER_NONE);
  return;
}

#ifdef __STDC__
void read_exec_dispatch(Widget w, Read *read, Header_Mode header_mode)
#else
void read_exec_dispatch(w,read,header_mode)
     Widget w;
     Read *read;
     Header_Mode header_mode;
#endif
{
  char *command;
  char *header = NULL;

  command = input_string(read->shell,MLGetLocalized(XtNmsgInputCommand,
						    MsgInputCommand),
			 session->last_command, SHELLCOMMANDHELPFILE);
  if(command == NULL)
    return;

  if(*command == NUL_TERM) {
    fs_give((void **) &command);
    return;
  }

  push_cursor(WATCH_CURSOR);

  if(header_mode == HEADER_FULL)
    header = read->current->header;
  if(header_mode == HEADER_PART)
    header = read->current->short_header;

  if(write_to_pipe(command, header,
		(read->current->alt_text)
		? read->current->alt_text : read->current->current_text,
		(read->current->alt_text)
		? strlen(read->current->alt_text) 
		: strlen(read->current->current_text)))

    mm_log(MLGetLocalized(XtNmsgPipeFail,MsgPipeFail), WARN);
  if(session->last_command != NULL)
    fs_give((void **) &session->last_command);
  session->last_command = command;

  pop_cursor();
  return;
}


#ifdef __STDC__
void read_select_attach(Widget w, Read *read, XmListCallbackStruct *xp)
#else
void read_select_attach(w,read,xp)
     Widget w;
     Read *read;
     XmListCallbackStruct *xp;
#endif
{
  Part_List *part_list;
  BODY *body = NULL;
  
  if(xp->item_position == read->current->selection) {
    read->current->selection = 0;
    read->current->button_state |= BTN_NOATTACHSELECT;
    read_check_buttons();
    return;
  }

  read->current->selection = xp->item_position;
  read->current->button_state &= (~BTN_NOATTACHSELECT);
  read_check_buttons();


  for(part_list = read->current->part_list;
      ((part_list) && part_list->partnumber != read->current->selection);
      part_list = part_list->next);

  if(part_list) {
    if(part_list->part) 
      body = &(part_list->part->body);

    read_message_part(read->current,part_list->partstr,body);
  }
  return;
}

#ifdef __STDC__
void read_view_attach(Widget w, Read *read, XtPointer xp)
#else
void read_view_attach(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  Part_List *part_list;
  BODY *body = NULL;
  int result;
  char **ptrptr = NULL;

  if(read->current->selection) {
    for(part_list = read->current->part_list;
	((part_list) && part_list->partnumber != read->current->selection);
	part_list = part_list->next);

    if(part_list) {
      if(part_list->part) 
	body = &(part_list->part->body);
      else
	body = read->current->body;

      /* On local connections, the body isn't cached. Grrrr. */
      
      if(body) {
	switch(body->type) {
	  
	case TYPEMULTIPART:
	  break;
	  
	case TYPEMESSAGE:

	  if(body->contents.msg.text == NULL) {
	    body->contents.msg.text =
	      mail_fetchbody(read->current->mailstream,
			     read->current->msgno,
			     (read->current->rfc_msg_leaf == TRUE) 
			     ? read->current->current_part_str
			     : part_list->partstr,
			     &body->size.bytes);
	    ptrptr = &body->contents.msg.text;
	  }
	  break;
	case TYPETEXT:
	case TYPEIMAGE:
	case TYPEAUDIO:
	case TYPEAPPLICATION:
	case TYPEOTHER:
	default:
	  if(body->contents.text == NULL) {
	    body->contents.text = (unsigned char *)
	      mail_fetchbody(read->current->mailstream,
			     read->current->msgno,
			     part_list->partstr, 
			     &body->size.bytes);
	    ptrptr = (char **) &body->contents.text;
	  }
	  break;
	}
	result = show_mime(read->shell,body, FALSE);
      }
    }
  }
  
  if(ptrptr)
    *ptrptr = NULL;
  return;
}

#ifdef __STDC__
void read_save_attach(Widget w, Read *read, XtPointer xp)
#else
void read_save_attach(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  Part_List *part_list;
  BODY *body = NULL;
  int result;
  char **ptrptr = NULL;

  if(read->current->selection) {
    for(part_list = read->current->part_list;
	((part_list) && part_list->partnumber != read->current->selection);
	part_list = part_list->next);

    if(part_list) {
      if(part_list->part) 
	body = &(part_list->part->body);
      else
	body = read->current->body;

      /* On local connections, the body isn't cached. Grrrr. */
      
      if(body) {
	switch(body->type) {
	  
	case TYPEMULTIPART:
	  break;
	  
	case TYPEMESSAGE:

	  if(body->contents.msg.text == NULL) {
	    body->contents.msg.text =
	      mail_fetchbody(read->current->mailstream,
			     read->current->msgno,
			     (read->current->rfc_msg_leaf == TRUE) 
			     ? read->current->current_part_str
			     : part_list->partstr,
			     &body->size.bytes);
	    ptrptr = &body->contents.msg.text;
	  }
	  break;
	case TYPETEXT:
	case TYPEIMAGE:
	case TYPEAUDIO:
	case TYPEAPPLICATION:
	case TYPEOTHER:
	default:
	  if(body->contents.text == NULL) {
	    body->contents.text = (unsigned char *)
	      mail_fetchbody(read->current->mailstream,
			     read->current->msgno,
			     part_list->partstr, 
			     &body->size.bytes);
	    ptrptr = (char **) &body->contents.text;
	  }
	  break;
	}
	result = show_mime(read->shell,body,TRUE);
      }
    }
  }
  
  if(ptrptr)
    *ptrptr = NULL;
  return;
}



#ifdef __STDC__
void read_exec_attach(Widget w, Read *read, XmListCallbackStruct *xp)
#else
void read_exec_attach(w,read,xp)
     Widget w;
     Read *read;
     XmListCallbackStruct *xp;
#endif
{
  Part_List *part_list;
  BODY *body = NULL;
  char **ptrptr = NULL;
  int result;
  

  read->current->selection = xp->item_position;

  if(read->current->selection) {
    for(part_list = read->current->part_list;
	((part_list) && part_list->partnumber != read->current->selection);
	part_list = part_list->next);

    if(part_list) {
      if(part_list->part) 
	body = &(part_list->part->body);
      else
	body = read->current->body;

      /* On local connections, the body isn't cached. Grrrr. */

      if(body) {
	switch(body->type) {

	case TYPEMULTIPART:
	  break;
	  
	case TYPEMESSAGE:
	  if(body->contents.msg.text == NULL) {
	    body->contents.msg.text =
	      mail_fetchbody(read->current->mailstream,
			     read->current->msgno,
			     (read->current->rfc_msg_leaf == TRUE) 
			     ? read->current->current_part_str
			     : part_list->partstr,
			     &body->size.bytes);
	    ptrptr = &body->contents.msg.text;
	  }
	  break;
	case TYPETEXT:
	case TYPEIMAGE:
	case TYPEAUDIO:
	case TYPEAPPLICATION:
	case TYPEOTHER:
	default:
	  if(body->contents.text == NULL) {
	    body->contents.text = (unsigned char *)
	      mail_fetchbody(read->current->mailstream,
			     read->current->msgno,
			     part_list->partstr, 
			     &body->size.bytes);
	    ptrptr = (char **) &body->contents.text;
	  }
	  break;
	}
	result = show_mime(read->shell,body, FALSE);
      }
    }
  }

  if(ptrptr)
    *ptrptr = NULL;

  read->current->button_state &= (~BTN_NOATTACHSELECT);
  read_check_buttons();
  XmListSelectPos(read->read_attach,read->current->selection,FALSE);
  return;
}

#ifdef __STDC__
void read_kill_current(Widget w, Read *read, XtPointer xp)
#else
void read_kill_current(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  Read_Info *this_one = NULL;
  Read_Info *next_one = NULL;;

  if(read == NULL)
    return;

  this_one = read->current;

  if(this_one == NULL)
    return;

  if(this_one->expunged == TRUE) {
    for(next_one = read->read_info; next_one; next_one = next_one->prev)
      if(next_one->expunged == FALSE)
	break;
  }
  else {
    if(this_one->next)
      next_one = this_one->next;
    else
      if(this_one->prev)
	next_one = this_one->prev;
  }

  if(next_one) {
    read_context_switch(read,this_one,next_one);
    kill_read_info(this_one);
  }
  else {
    read_close_window(w,read,xp);
    return;
  }

  return;
}


#ifdef __STDC__
void read_get_next(Widget w, Read *read, XtPointer xp)
#else
void read_get_next(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  Read_Info *this_one = NULL;
  Read_Info *next_one = NULL;;

  if(read == NULL)
    return;

  this_one = read->current;

  if(this_one == NULL)
    return;

  if(this_one->next) {
    next_one = this_one->next;
    while((next_one->next != NULL) && (next_one->next->expunged == TRUE))
	next_one = next_one->next;
  }

  if(next_one) {
    read_context_switch(read,this_one,next_one);
    kill_read_info(this_one);
  }
  else {
    read_load_next(this_one); /* wipe out the current queue as a result */
    if(read->read_info == NULL)
      read_close_window(w,read,xp);
    else
      de_iconify(read->shell);
    return;
  }

  return;
}

/* Wipe out the current read queue */

#ifdef __STDC__
void read_kill_all(Widget w, Read *read, XtPointer xp)
#else
void read_kill_all(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  Read_Info *this_one = NULL;
  Read_Info *next_one = NULL;;

  if(read == NULL)
    return;

  this_one = read->read_info;

  if(this_one == NULL)
    return;

  for(this_one = read->read_info; this_one; this_one = next_one ) {
    next_one = this_one->prev;
    kill_read_info(this_one);
  }

  read->current = NULL;
  read->read_info = NULL;

  return;
}

/* 
 * kill this message, and do a context switch to any message
 * which isn't in this mailbox; which is being closed.
 * If there aren't any, close the window.
 */


#ifdef __STDC__
void read_close_kill_current(Widget w, Read *read, XtPointer xp)
#else
void read_close_kill_current(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  Read_Info *this_one = NULL;
  Read_Info *next_one = NULL;
  Read_Info *current  = NULL;

  if(read == NULL)
    return;

  this_one = read->current;

  if(this_one == NULL)
    return;

  for(current = read->read_info; current ; current = current->prev)
    if(current->mailstream != this_one->mailstream) {
      next_one = current;
      break;
    }
  
  if(next_one) {
    read_context_switch(read,this_one,next_one);
    kill_read_info(this_one);
  }
  else {
    read_close_window(w,read,xp);
    return;
  }
  return;
}

#ifdef __STDC__
void read_trash_current(Widget w, Read *read, XtPointer xp)
#else
void read_trash_current(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  Read_Info *this_one = NULL;
  Read_Info *next_one = NULL;
  char sequence[32];

  if(read == NULL)
    return;

  this_one = read->current;

  if(this_one == NULL)
    return;

  if(read->current->mailstream && read->current->msgno) {
    sprintf(sequence,"%lu",read->current->msgno);
    push_cursor(WATCH_CURSOR);
    mail_setflag(read->current->mailstream, sequence, DELETED_FLAG);
    mm_flags(read->current->mailstream, read->current->msgno);
    pop_cursor();
  }
  read_get_next(w,read,xp);
  return;
}

#ifdef __STDC__
void kill_read_info(Read_Info *read_info)
#else
void kill_read_info(read_info)
     Read_Info *read_info;
#endif
{
  Read *read = find_read_window(read_info);

  if((read == NULL) || (read_info == NULL))
    return;

  if(read->current == read_info)
    read->current = NULL;

  if(read->read_info == read_info)
    read->read_info = read_info->prev;

  if(read_info->prev) {
    read_info->prev->next = read_info->next;
    if(read_info->next == NULL) 
      read_info->prev->button_state |= BTN_NONEXT;
    else
      read_info->prev->button_state &= ~(BTN_NONEXT);
  }
  if(read_info->next) {
    read_info->next->prev = read_info->prev;
    if(read_info->prev == NULL) 
      read_info->next->button_state |= BTN_NOPREV;
    else
      read_info->next->button_state &= ~(BTN_NOPREV);
  }
  free_read_info(read_info);
  read_check_buttons();
  return;
}

#ifdef __STDC__
Read *find_read_window(Read_Info *info)
#else
Read *find_read_window(info)
     Read_Info *info;
#endif
{
  Read *read;
  Read_Info *ri;

  for(read = session->read; read; read = read->next)
    for(ri = read->read_info; ri; ri = ri->prev)
      if(ri == info)
	return(read);
  return(NULL);
}


#ifdef __STDC__
void read_rfc822(Read_Info *parent, char *partstr, BODY *body)
#else
void read_rfc822(parent,partstr,body)
     Read_Info *parent;
     char *partstr;
     BODY *body;
#endif
{
  Read *read = find_read_window(parent);
  Read_Info *read_info;
  char *basetxt = NULL;
  unsigned long length;
  unsigned long newlength;
  char *tmpptr = NULL;
  char *ptr = NULL;
  int foo;

  if(read == NULL)
    return;

  read_info = new_read_info();
  read_info->serialno = parent->serialno;
  parent->selection = 0L;
  read_info->mailstream = parent->mailstream;
  read_info->lview = parent->lview;
  read_info->msgno = parent->msgno;
  read_info->message = parent->message;
  read_info->server = cpystr(parent->server);
  read_info->mailbox_type = parent->mailbox_type;
  read_info->envelope = parent->envelope;
  read_info->base_part_str = cpystr(partstr);
  read_info->message_type = MESSAGE_PART;
  read_info->fetched = TRUE;
  if(read_info->mailbox_type == MAILBOX_TYPE_NEWS)
    read_info->button_state |= BTN_ISNEWS;

  read_info->button_state |= BTN_NOATTACHSELECT;

  basetxt = cpystr(mail_fetchbody(read_info->mailstream,
				  read_info->msgno,
				  partstr, &length));
  if(basetxt == NULL)
    basetxt = cpystr(EMPTYSTR);

  stripcr(basetxt);

  ptr = ML_Strstr(basetxt,"\n\n");

  if(ptr != NULL) {
    ptr ++;
    *ptr = NUL_TERM;
    ptr ++;
    read_info->header = cpystr(basetxt);
  }
  else {
    read_info->header = cpystr(EMPTYSTR);
    ptr = basetxt;
  }

  read_info->short_header = get_short_header(read_info->header);
  if(read_info->short_header == NULL)
    read_info->short_header = cpystr(EMPTYSTR);

  read_new_link(read,read_info);
  
  if(body->contents.msg.body->type == TYPEMULTIPART) {
    read_info->body = body->contents.msg.body;
    read_info->current_part_str = (char *) fs_get(strlen(partstr) + 2);
    sprintf(read_info->current_part_str,"%s.1",partstr);
    read_info->attachments = read_info->body->contents.part;
    read_fetch(read_info,body);
  }
  else {
    read_info->body = body->contents.msg.body;
    read_info->current_part_str = cpystr(partstr);
    read_info->current_text = cpystr(ptr);
    read_info->rfc_msg_leaf = TRUE;

    if((body->type == TYPETEXT) || (body->type == TYPEMESSAGE))
      read_info->visible = TRUE;
    else
      read_info->visible = FALSE;

    length = strlen(ptr);

    if((length != 0L) && (read_info->visible == TRUE)) {
      switch(body->encoding) {
      case ENCBASE64:
	read_info->alt_text = 
	  (char *) rfc822_base64((unsigned char *) ptr,
				 length,&newlength);
	if(read_info->alt_text)
	  read_info->alt_text[newlength] = NUL_TERM;
	break;
      case ENCQUOTEDPRINTABLE:
	read_info->alt_text =
	  (char *) rfc822_qprint((unsigned char *) ptr,
				 length,&newlength);
	if(read_info->alt_text)
	  read_info->alt_text[newlength] = NUL_TERM;
	break;
      case ENCOTHER:
      case ENC7BIT:
      case ENC8BIT:
      case ENCBINARY:
      default:
	break;
      }
    }
    if(read_info->alt_text) {
      if((foo = strlen(read_info->alt_text)) < newlength)
	fs_give((void **) &read_info->alt_text);
      else
	stripcr(read_info->alt_text);
    }

    if((body->subtype) 
       && (((strcasecmp(body->subtype,"html")) == STRMATCH))
       || ((strncasecmp(read_info->current_text,"<HTML>",6)) == STRMATCH)){
	tmpptr = strip_html((read_info->alt_text) 
			    ? read_info->alt_text : read_info->current_text);
	if(read_info->alt_text)
	  fs_give((void **) &read_info->alt_text);
	read_info->alt_text = tmpptr;
    }

  }
  
  fs_give((void **) &basetxt);
  read_context_switch(read,read->current,read_info);
  return;
}

#ifdef __STDC__
void read_message_part(Read_Info *read_info, char *partstr, BODY *body)
#else
void read_message_part(read_info,partstr,body)
     Read_Info *read_info;
     char *partstr;
     BODY *body;
#endif
{
  /* Don't recurse again... */
  Read *read = find_read_window(read_info);

  if((read == NULL) || (read_info->rfc_msg_leaf == TRUE))
    return;

  if(read_info->current_part_str)
    fs_give((void **) &read_info->current_part_str);
  read_info->current_part_str = cpystr(partstr);
  read_info->message_type = MESSAGE_PART;
  read_info->rfc_msg_leaf = FALSE;

  if((body != NULL) && (body->type == TYPEMESSAGE) && (body->subtype != NULL)
     && ((strcasecmp(body->subtype,"rfc822")) == STRMATCH)) {
    read_rfc822(read_info,partstr,body);
    return;
  }
  read_fetch(read_info,body);
  read_context_switch(read,NULL,read_info);
  return;
}

#ifdef __STDC__
void read_new_link(Read *read, Read_Info *read_info)
#else
void read_new_link(read, read_info)
     Read *read;
     Read_Info *read_info;
#endif
{

  if(read->read_info) {
    read->read_info->next = read_info;
    read->read_info->button_state &= ~(BTN_NONEXT);
    read_info->button_state &= ~(BTN_NOPREV);
  }
  else
    read_info->button_state |= BTN_NOPREV;

  read_info->button_state |= BTN_NONEXT;
  read_info->prev = read->read_info;
  read->read_info = read_info;
  return;
}

#ifdef __STDC__
void read_fetch(Read_Info *read_info, BODY *body)
#else
void read_fetch(read_info,body)
     Read_Info *read_info;
     BODY *body;
#endif
{
  Read *read = find_read_window(read_info);
  char sequence[16];
  Arg args[ARGLISTSIZE];
  int n = 0;
  char *tmpptr = NULL;
  char *src_text = NULL;
  unsigned long length = 0L;
  unsigned long newlength = 0L;
  unsigned long foo;
  char *decode_subject;
  char *decode_ptr;
  BODY *local_body = body;
  char buffer[FILEBUFFLEN];
  char *subject = NULL;

  if(read == NULL)
    return;

  XmUpdateDisplay(read->shell);

  if((local_body) && (local_body->type == TYPEMULTIPART))
    local_body = &(body->contents.part->body);

  if(body == NULL) /* should warn */
    return;

  if((local_body->type == TYPETEXT) || (local_body->type == TYPEMESSAGE))
    read_info->visible = TRUE;
  else
    read_info->visible = FALSE;

  push_cursor(WATCH_CURSOR);

  switch(read_info->message_type) {
  case MESSAGE_NORMAL:

    if(read_info->fetched == TRUE)
      break;

    if(read_info->header == NULL) {
      read_info->header = cpystr(mail_fetchheader(read_info->mailstream,
						  read_info->msgno));
      stripcr(read_info->header);
      if(read_info->header[strlen(read_info->header) - 1] == LFCHAR)
	read_info->header[strlen(read_info->header) - 1] = NUL_TERM;
    }

    read_info->short_header = get_short_header(read_info->header);
    if(read_info->short_header == NULL)
      read_info->short_header = cpystr(EMPTYSTR);


    if(read_info->visible) {
      src_text = mail_fetchbody(read_info->mailstream,
				read_info->msgno,
				read_info->current_part_str, &length);
      
      read_info->current_text = cpystr(src_text);
    }

    if(read_info->current_text == NULL)
      read_info->current_text = cpystr(EMPTYSTR);
    
    stripcr(read_info->current_text);
    update_view_line_stream_msgno(read_info->mailstream, read_info->msgno);
    break;

  case MESSAGE_PART:
    if(read_info->current_text)
      fs_give((void **) &read_info->current_text);

    src_text = mail_fetchbody(read_info->mailstream,
			      read_info->msgno,
			      read_info->current_part_str, &length);

    read_info->current_text =  cpystr(src_text);

    if(read_info->current_text == NULL)
      read_info->current_text = cpystr(EMPTYSTR);
    
    stripcr(read_info->current_text);

    break;

  case MESSAGE_RAWPART:
  case MESSAGE_IN_MEMORY:
  case MESSAGE_FROM_FILE:
    
  default:
    break;
  }

  if(local_body) {

    if(read_info->alt_text)
      fs_give((void **) &read_info->alt_text);


    if(read_info->envelope) 
      subject = read_info->envelope->subject;
    if(subject == NULL)
      subject = "No subject";

    decode_subject = (char *) fs_get(strlen(subject) + 1);
    *decode_subject = NUL_TERM;
    while((decode_ptr = iso_decode(&subject, TRUE)) != NULL) {
      strcat(decode_subject,decode_ptr);
      fs_give((void **) &decode_ptr);
    }
      
    sprintf(buffer,"[%d] %-64.64s (Part %s%s)",
	    read_info->serialno,
	    decode_subject,read_info->current_part_str,
	    (read_info->base_part_str) 
	    ? MLGetLocalized(XtNstrRFC822,StrRFC822) 
	    : EMPTYSTR);
    XtSetArg(args[n], XmNtitle, buffer); n ++;
    XtSetValues(read->shell, args, n); n = 0;
    fs_give((void **) &decode_subject);

    if((src_text != NULL) && (read_info->visible == TRUE)) {
      switch(local_body->encoding) {
      case ENCBASE64:
	read_info->alt_text = 
	  (char *) rfc822_base64((unsigned char *) src_text,
				 length,&newlength);
	if(read_info->alt_text)
	  read_info->alt_text[newlength] = NUL_TERM;
	break;
      case ENCQUOTEDPRINTABLE:
	read_info->alt_text =
	  (char *) rfc822_qprint((unsigned char *) src_text,
				 length,&newlength);
	if(read_info->alt_text)
	  read_info->alt_text[newlength] = NUL_TERM;
	break;
      case ENCOTHER:
      case ENC7BIT:
      case ENC8BIT:
      case ENCBINARY:
      default:
	break;
      }
    }
    if(read_info->alt_text) {
      if((foo = strlen(read_info->alt_text)) < newlength)
	fs_give((void **) &read_info->alt_text);
      else
	stripcr(read_info->alt_text);
    }
    if((local_body->subtype) 
       && (((strcasecmp(local_body->subtype,"html")) == STRMATCH))
       || ((strncasecmp(read_info->current_text,"<HTML>",6)) == STRMATCH)){
	tmpptr = strip_html((read_info->alt_text) 
			    ? read_info->alt_text : read_info->current_text);
	if(read_info->alt_text)
	  fs_give((void **) &read_info->alt_text);
	read_info->alt_text = tmpptr;
    }
  }
  if(read_info->mailstream && read_info->msgno) {
    sprintf(sequence,"%lu",read_info->msgno);
    mail_setflag(read_info->mailstream, sequence, SEEN_FLAG);
    mm_flags(read_info->mailstream, read_info->msgno);
  }

  if(read_info->visible == TRUE)
    read_info->fetched = TRUE;
  pop_cursor();
  return;
}

#ifdef __STDC__
void read_context_switch(Read *read, Read_Info *old, Read_Info *new)
#else
void read_context_switch(read,old,new) 
  Read *read;
  Read_Info *old, *new;
#endif
{
  char buffer[FILEBUFFLEN];
  char *subject = NULL;
  Arg args[ARGLISTSIZE];
  int n = 0;
  char *decode_subject = NULL;
  char *decode_ptr = NULL;

  unsigned long selection;

  if((read == NULL) || (read->is_realized == FALSE) || (new == NULL))
    return;

  /*
   * old isn't used here. It is only in the arg list to make
   * this function syntactically compatible with other context
   * switch functions in the program. The difference in the read 
   * window is that you can't type into it, so there's no old 
   * context to save. Instead we use this function whenever we 
   * need to update the contents of the read window, either to change
   * messages, or to navigate a multipart, or just to toggle the
   * header mode.
   */

  read->current = new;
  selection = read->current->selection;

  /* zap! */


  XmTextSetString(read->read_header, EMPTYSTR);
  XmTextSetString(read->read_text,EMPTYSTR);
  XmListDeselectAllItems(read->read_attach);
  XmListDeleteAllItems(read->read_attach); 


  switch(new->message_type) {
  case MESSAGE_NORMAL:
  case MESSAGE_PART:
    if(new->fetched == FALSE)
      read_fetch(new,new->body);

    if((new->show_long_header == TRUE) && (new->header))
      XmTextSetString(read->read_header,new->header);
    if((new->show_long_header == FALSE) && (new->short_header))
      XmTextSetString(read->read_header,new->short_header);

    if(new->visible) {
      if(new->alt_text)
	XmTextSetString(read->read_text,new->alt_text);
      else
	if(new->current_text)
	  XmTextSetString(read->read_text,new->current_text);
    }
    else
      XmTextSetString(read->read_text,MLGetLocalized(XtNmsgBinaryMessage,
						     MsgBinaryMessage));

    XtSetKeyboardFocus(read->shell, read->read_text);

    read_make_attachment_list(read);

    if(selection) {
      read->current->selection = selection;
      XmListSelectPos(read->read_attach,selection,FALSE);
      XmListSetPos(read->read_attach,selection);
      new->button_state &= (~BTN_NOATTACHSELECT);
    }
    else
      new->button_state |= BTN_NOATTACHSELECT;

    break;
  case MESSAGE_RAWPART:
  case MESSAGE_IN_MEMORY:
  case MESSAGE_FROM_FILE:
  default:
    break;
  }

  if(new && new->envelope && new->envelope->subject) {
    subject = new->envelope->subject;
    if(subject == NULL)
      subject = "No subject";
    decode_subject = (char *) fs_get(strlen(subject) + 1);
    *decode_subject = NUL_TERM;
    
    while((decode_ptr = iso_decode(&subject, TRUE)) != NULL) {
      strcat(decode_subject, decode_ptr);
      fs_give((void **) &decode_ptr);
    }
  }  
   
  sprintf(buffer,"[%d] %-64.64s (Part %s%s)",
	  new->serialno,
	  (decode_subject) ? decode_subject : EMPTYSTR,
	  new->current_part_str, 
	  (new->base_part_str) 
	  ? MLGetLocalized(XtNstrRFC822,StrRFC822) : EMPTYSTR);
  XtSetArg(args[n], XmNtitle, buffer); n ++;
  XtSetValues(read->shell, args, n); n = 0;
  if(decode_subject)
    fs_give((void **) &decode_subject);

  read_check_buttons();
  XmProcessTraversal(read->read_text, XmTRAVERSE_CURRENT);
  XmUpdateDisplay(read->shell);
  return;
}

#ifdef __STDC__
void read_make_attachment_list(Read *read)
#else
void read_make_attachment_list(read)
     Read *read;
#endif
{
  /* Erase current list contents and start over */

  XmListDeselectAllItems(read->read_attach);
  XmListDeleteAllItems(read->read_attach); 

  read->current->selection = 0;

  if(read->current->part_list) 
    destroy_part_list(read->current->part_list);

  read->current->part_list = NULL;

  if(read->current->body == NULL) {
    read_check_buttons();
    return;
  }

  if(read->current->body->type != TYPEMULTIPART)
    read_add_this_part(read->read_attach,read);

  read_add_attach_strings(read->read_attach, read, 
			  read->current->attachments,0, 
			  (read->current->base_part_str) 
			  ? read->current->base_part_str : EMPTYSTR);

  read->current->button_state &= ~(BTN_NOATTACH);
  read_check_buttons();
  return;
}

#ifdef __STDC__
void read_add_this_part(Widget w, Read *read)
#else
void read_add_this_part(w,read)
     Widget w;
     Read *read;
#endif
{
  char buffer[FILEBUFFLEN];
  char partbuff[FILEBUFFLEN];
  Part_List *part_list;
  
  XmString xstr;
  int len;
  struct mail_body_parameter *params;

  strcpy(buffer,type_to_name(read->current->body->type));
  strcat(buffer,TYPE_SEPARATOR_STR);
  strcat(buffer,(read->current->body->subtype) 
	 ? read->current->body->subtype : NOSUBTYPE );

  if(read->current->rfc_msg_leaf == TRUE)
    strcpy(partbuff,read->current->base_part_str);
  else {
    if(read->current->base_part_str)
      sprintf(partbuff,"%s.1", read->current->base_part_str);
    else
      sprintf(partbuff,"1");
  }

  strcat(buffer," (Part ");
  strcat(buffer,partbuff);
  strcat(buffer,") ");

  for(len = strlen(buffer); len < (COMPOSEWIDTH/2); len ++)
    strcat(buffer,SPACESTR);
  if((read->current->body->description) && 
     ((int) (strlen(buffer) 
	     + strlen(read->current->body->description)) < FILEBUFFLEN))
    strcat(buffer, read->current->body->description); 
  for(params = read->current->body->parameter; 
      params; params = params->next) {
    if((int) (strlen(buffer) + strlen(params->attribute) 
	+ strlen(params->value) + 2) >= FILEBUFFLEN)
      break;
    strcat(buffer,SPACESTR);
    strcat(buffer,params->attribute);
    strcat(buffer,"=");
    strcat(buffer,params->value);
  }
  
  xstr = XmStringCreateSimple(buffer);
  XmListAddItemUnselected(w,xstr,0);
  XmStringFree(xstr);

  part_list = (Part_List *) fs_get(sizeof(Part_List));

  part_list->partstr = cpystr("1");
  part_list->partnumber = 1;
  part_list->next = NULL;
  part_list->prev = NULL;
  part_list->part = NULL;

  read->current->part_list = part_list;
  return;
}

#ifdef __STDC__
void read_add_attach_strings(Widget w, Read *read, PART *part, 
			     int level, char *partstr)
#else
void read_add_attach_strings(w,read,part,level, partstr)
     Widget w;
     Read *read;
     PART *part;
     int level;
     char *partstr;
#endif
{
  int len;
  PART *curr;
  char buffer[FILEBUFFLEN];
  char partbuff[FILEBUFFLEN];

  struct mail_body_parameter *params;
  XmString xstr;
  Part_List *part_list;
  Part_List *curr_part_list;
  int subpart_cnt = 0;

  if(part == NULL)
    return;

  strcpy(partbuff,EMPTYSTR);

  for(curr = part; curr; curr = curr->next) {
    subpart_cnt ++;

    if(*partstr == NUL_TERM)
      sprintf(partbuff,"%d",subpart_cnt);
    else
      sprintf(partbuff,"%s.%d",partstr,subpart_cnt);

    strcpy(buffer,EMPTYSTR);
    for(len = 0; len < level; len ++)
      strcat(buffer,SPACESTR);
    strcat(buffer,type_to_name(curr->body.type));
    strcat(buffer,TYPE_SEPARATOR_STR);
    strcat(buffer,(curr->body.subtype) ? curr->body.subtype : NOSUBTYPE );

    strcat(buffer," (Part ");
    strcat(buffer,partbuff);
    strcat(buffer,") ");

    for(len = strlen(buffer); len < (COMPOSEWIDTH/2); len ++)
      strcat(buffer,SPACESTR);
    if((curr->body.description) 
       && ((int) (strlen(buffer) 
		  + strlen(curr->body.description)) < FILEBUFFLEN)) {
      strcat(buffer,curr->body.description);
      strcat(buffer,SPACESTR);
    }
    for(params = curr->body.parameter; params; params = params->next) {
      if((int) (strlen(buffer) + strlen(params->attribute) 
	  + strlen(params->value) + 2) >= FILEBUFFLEN)
	break;
      strcat(buffer,params->attribute);
      strcat(buffer,"=");
      strcat(buffer,params->value);
      strcat(buffer,SPACESTR);
    }

    xstr = XmStringCreateSimple(buffer);
    XmListAddItemUnselected(w,xstr,0);
    XmStringFree(xstr);
    
    part_list = (Part_List *) fs_get(sizeof(Part_List));

    part_list->partstr = cpystr(partbuff);
    part_list->next = NULL;
    part_list->part = curr;
    
    if(read->current->part_list == NULL) {
      read->current->part_list = part_list;
      part_list->partnumber = 1;
      part_list->prev = NULL;
    }
    else {
      for(curr_part_list = read->current->part_list; curr_part_list->next;
	curr_part_list = curr_part_list->next);

      curr_part_list->next = part_list;
      part_list->prev = curr_part_list;
      part_list->partnumber = curr_part_list->partnumber + 1;
    }

    if(curr->body.type == TYPEMULTIPART)
      read_add_attach_strings(w, read, curr->body.contents.part,
			      level+1, partbuff);
  }
  return;
}


#ifdef __STDC__
void read_reply_sender(Widget w, Read *read, XtPointer xp)
#else
void read_reply_sender(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  compose_message(COMPOSE_REPLY, FALSE, NULL, NULL, read->current);
  return;
}

#ifdef __STDC__
void read_reply_all(Widget w, Read *read, XtPointer xp)
#else
void read_reply_all(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{

  compose_message(COMPOSE_REPLYALL, FALSE, NULL, NULL, read->current);
  return;
}

#ifdef __STDC__
void read_forward(Widget w, Read *read, XtPointer xp)
#else
void read_forward(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  compose_message(COMPOSE_FORWARD, FALSE, NULL, NULL, read->current);
  return;
}

#ifdef __STDC__
void read_forward_attach(Widget w, Read *read, XtPointer xp)
#else
void read_forward_attach(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  compose_message(COMPOSE_FORWARDATTACH, FALSE, NULL, NULL, read->current);
  return;
}

#ifdef __STDC__
void read_remail(Widget w, Read *read, XtPointer xp)
#else
void read_remail(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  compose_message(COMPOSE_REMAIL, FALSE, NULL, NULL, read->current);
  return;
}



/* called from mm_expunged(). Just mark 'em, we'll clean up later. */

#ifdef __STDC__
void read_expunge(MAILSTREAM *mailstream, unsigned long msgno)
#else
void read_expunge(mailstream,msgno)
     MAILSTREAM *mailstream;
     unsigned long msgno;
#endif
{
  Read *read;
  Read_Info *read_info;

  for(read = session->read; read; read = read->next)
    for(read_info = read->read_info; read_info; read_info = read_info->prev) {
      if(read_info->mailstream != mailstream)
	continue;
      if(read_info->msgno == msgno)
	read_info->expunged = TRUE;
      if(read_info->msgno > msgno)
	read_info->msgno --;
    }
  return;
}

/* 
 * Called after an expunge has returned. This is so we don't 
 * run into a c-client recursion if the next message needs to be 
 * fetched.
 */

#ifdef __STDC__
void read_after_expunge(void)
#else
void read_after_expunge()
#endif
{
  Read *read;
  Read_Info *read_info;
  Boolean found;

  do {
    found = FALSE;
    for(read = session->read; read; read = read->next) {
      for(read_info = read->read_info; read_info; 
	  read_info = read_info->prev) {
	if(read_info->expunged == TRUE) {
	  found = TRUE;
	  if(read_info == read->current) 
	    read_kill_current(read->shell,read,NULL);
	  else
	    kill_read_info(read_info);
	  break;
	}
      }
    }
  } while (found == TRUE);
  return;
}

#ifdef __STDC__
void read_set_deleted(Widget w, Read *read, XtPointer xp)
#else
void read_set_deleted(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_setflag(w,read,DELETED_FLAG);
  return;
}

#ifdef __STDC__
void read_set_seen(Widget w, Read *read, XtPointer xp)
#else
void read_set_seen(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_setflag(w,read,SEEN_FLAG);
  return;
}

#ifdef __STDC__
void read_set_flagged(Widget w, Read *read, XtPointer xp)
#else
void read_set_flagged(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_setflag(w,read,FLAGGED_FLAG);
  return;
}

#ifdef __STDC__
void read_set_answered(Widget w, Read *read, XtPointer xp)
#else
void read_set_answered(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_setflag(w,read,ANSWERED_FLAG);
  return;
}

#ifdef __STDC__
void read_clear_deleted(Widget w, Read *read, XtPointer xp)
#else
void read_clear_deleted(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_clearflag(w,read,DELETED_FLAG);
  return;
}

#ifdef __STDC__
void read_clear_seen(Widget w, Read *read, XtPointer xp)
#else
void read_clear_seen(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_clearflag(w,read,SEEN_FLAG);
  return;
}

#ifdef __STDC__
void read_clear_flagged(Widget w, Read *read, XtPointer xp)
#else
void read_clear_flagged(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_clearflag(w,read,FLAGGED_FLAG);
  return;
}

#ifdef __STDC__
void read_clear_answered(Widget w, Read *read, XtPointer xp)
#else
void read_clear_answered(w,read,xp)
     Widget w;
     Read *read;
     XtPointer xp;
#endif
{
  read_clearflag(w,read,ANSWERED_FLAG);
  return;
}

#ifdef __STDC__
void read_setflag(Widget w, Read *read, char *flag)
#else
void read_setflag(w,read,flag)
     Widget w;
     Read *read;
     char *flag;
#endif
{
  char sequence[32];

  if(read->current->mailstream && read->current->msgno) {
    sprintf(sequence,"%lu",read->current->msgno);
    push_cursor(WATCH_CURSOR);
    mail_setflag(read->current->mailstream, sequence, flag);
    mm_flags(read->current->mailstream, read->current->msgno);

    pop_cursor();
  }
  return;
}

#ifdef __STDC__
void read_clearflag(Widget w, Read *read, char *flag)
#else
void read_clearflag(w,read,flag)
     Widget w;
     Read *read;
     char *flag;
#endif
{
  char sequence[32];

  if(read->current->mailstream && read->current->msgno) {
    sprintf(sequence,"%lu",read->current->msgno);
    push_cursor(WATCH_CURSOR);
    mail_clearflag(read->current->mailstream, sequence, flag);
    mm_flags(read->current->mailstream, read->current->msgno);
    pop_cursor();
  }
  return;
}


#ifdef __STDC__
void read_select_text(Widget w, Read *read, char *flag)
#else
void read_select_text(w,read,flag)
     Widget w;
     Read *read;
     char *flag;
#endif
{
  char *ptr = XmTextGetString(read->read_text);
  if(ptr) {
    XmTextSetSelection(read->read_text,0, strlen(ptr),
		       XtLastTimestampProcessed(display));
    fs_give((void **) &ptr);
  }
  return;
}

#ifdef __STDC__
void read_copy_text(Widget w, Read *read, char *flag)
#else
void read_copy_text(w,read,flag)
     Widget w;
     Read *read;
     char *flag;
#endif
{
  XmTextCopy(read->read_text,
	     XtLastTimestampProcessed(display));
  return;
}

#ifdef __STDC__
void read_pop(Widget w, XtPointer xp)
#else
void read_pop(w,xp)
     Widget w;
     XtPointer xp;
#endif
{
  Read *read;
  for(read = session->read; read; read = read->next) {
    if(read->read_text == w) {
      read_close_window(w,read,NULL);
      break;
    }
  }
  return;
}





syntax highlighted by Code2HTML, v. 0.9.1