/* mlcompose.c */
#include "ml.h"
char compose_address_translations[] = "<Key>Tab: complete-address()\n";
Menu compose_file_menu[] = {
{ NULL, "load_draft", NUL_TERM,
compose_load_draft, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "save_draft", NUL_TERM,
compose_save_draft, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "print", NUL_TERM,
compose_print, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "insert_file", NUL_TERM,
compose_insert_file, 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,
compose_destroy_current, NULL, 0, NULL, NULL, BTN_ON },
};
Menu compose_attach_menu[] = {
{ NULL, "attach_file", NUL_TERM,
compose_attach_file, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "attach_multi", NUL_TERM,
compose_attach_multi, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "createattach", NUL_TERM,
compose_createattach, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "delete_part", NUL_TERM,
compose_delete_part, NULL, 0,
NULL, NULL, BTN_NOATTACH|BTN_NOATTACHSELECT },
};
Menu compose_edit_menu[] = {
{ NULL, "cut_text", NUL_TERM,
compose_cut, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "copy_text", NUL_TERM,
compose_copy, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "paste_text", NUL_TERM,
compose_paste, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "spell", NUL_TERM,
compose_spell, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "attach_menu", NUL_TERM,
NULL, compose_attach_menu, XtNumber(compose_attach_menu),
NULL, NULL, BTN_ON },
};
Menu compose_option_menu[] = {
{ NULL, "configure", NUL_TERM,
compose_options, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "parameters", NUL_TERM,
compose_parameters, NULL, 0, NULL, NULL, BTN_ON },
};
Menu compose_send_menu[] = {
{ NULL, "send_message", NUL_TERM,
send_message, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "send_autograph", BTN_ON,
compose_send_autograph, NULL, 0, NULL, NULL, BTN_ON },
};
Menu compose_menu[] = {
{ NULL, "file_menu", NUL_TERM,
NULL, compose_file_menu, XtNumber(compose_file_menu),
NULL, NULL, BTN_ON },
{ NULL, "edit_menu", NUL_TERM,
NULL, compose_edit_menu, XtNumber(compose_edit_menu),
NULL, NULL, BTN_ON },
{ NULL, "option_menu", NUL_TERM,
NULL, compose_option_menu, XtNumber(compose_option_menu),
NULL, NULL, BTN_ON },
{ NULL, "send_menu", NUL_TERM,
NULL, compose_send_menu, XtNumber(compose_send_menu),
NULL, NULL, BTN_ON },
{ NULL, "HELP", NUL_TERM,
compose_help, NULL, 0,
NULL, NULL, BTN_ON },
};
Button_Menu compose_secondbuttons[] = {
{ "compose_insert_file_btn", compose_insert_file, NULL, BTN_ON, NULL },
{ "compose_attach_file_btn", compose_attach_file, NULL, BTN_ON, NULL },
{ "compose_reply_insert_btn", compose_reply_insert, NULL, BTN_ON, NULL },
{ "compose_send_message_btn", send_message, NULL, BTN_ON, NULL },
{ "compose_cancel_btn", compose_destroy_current, NULL, BTN_ON, NULL },
};
#ifdef __STDC__
void compose_check_buttons(MLCompose *compose)
#else
void compose_check_buttons(compose)
MLCompose *compose;
#endif
{
if(compose && compose->window)
update_buttons(compose->window->buttonlist,
compose->window->buttonstate);
return;
}
#ifdef __STDC__
void free_MLCompose(MLCompose *compose)
#else
void free_MLCompose(compose)
MLCompose *compose;
#endif
{
if(compose != NULL) {
free_buttonlist(compose->window->buttonlist);
fs_give((void **) &compose->window);
free_MLComposeOptions(compose->options);
compose->options = NULL;
if(compose->in_reply_to != NULL)
fs_give((void **) &compose->in_reply_to);
if(compose->reply_text != NULL)
fs_give((void **) &compose->reply_text);
if(compose->remail_header != NULL)
fs_give((void **) &compose->remail_header);
fs_give((void **) &compose);
}
return;
}
#ifdef __STDC__
void free_MLComposeOptions(MLComposeOptions *options)
#else
void free_MLComposeOptions(options)
MLComposeOptions *options;
#endif
{
if(options) {
if(options->window) {
if(options->window->buttonlist)
fs_give((void **) &options->window->buttonlist);
fs_give((void **) &options->window);
}
if(options->mailhost)
fs_give((void **) &options->mailhost);
if(options->nntphost)
fs_give((void **) &options->nntphost);
if(options->domain)
fs_give((void **) &options->domain);
if(options->replyto)
fs_give((void **) &options->replyto);
if(options->charset)
fs_give((void **) &options->charset);
if(options->sigfile)
fs_give((void **) &options->sigfile);
if(options->language)
fs_give((void **) &options->language);
if(options->outlog)
fs_give((void **) &options->outlog);
if(options->defcc)
fs_give((void **) &options->defcc);
if(options->defbcc)
fs_give((void **) &options->defbcc);
if(options->prefix)
fs_give((void **) &options->prefix);
fs_give((void **) &options);
}
return;
}
#ifdef __STDC__
MLComposeWindow *new_MLComposeWindow(void)
#else
MLComposeWindow *new_MLComposeWindow()
#endif
{
MLComposeWindow *composewindow = (MLComposeWindow *)
fs_get(sizeof(MLComposeWindow));
composewindow->buttonlist = NULL;
composewindow->attach_list_selection = 0;
composewindow->toggled_newsgroups = FALSE;
composewindow->toggled_bcc = FALSE;
return(composewindow);
}
#ifdef __STDC__
MLComposeOptions *new_MLComposeOptions(void)
#else
MLComposeOptions *new_MLComposeOptions()
#endif
{
MLComposeOptions *options = (MLComposeOptions *)
fs_get(sizeof(MLComposeOptions));
options->window = NULL;
options->verbose = preferences.smtp_debug;
options->keep_open = preferences.keep_open;
options->send_eight = preferences.send_eight;
options->word_wrap = preferences.word_wrap;
options->message_log = preferences.logit;
options->log_attachments = preferences.log_full;
options->verbose_tmp = preferences.smtp_debug;
options->keep_open_tmp = preferences.keep_open;
options->send_eight_tmp = preferences.send_eight;
options->word_wrap_tmp = preferences.word_wrap;
options->message_log_tmp = preferences.logit;
options->log_attachments_tmp = preferences.log_full;
options->mailhost = cpystr(preferences.smtp_server);
options->nntphost = cpystr(preferences.nntp_server);
options->domain = cpystr(preferences.default_domain);
options->replyto = cpystr(preferences.reply_address);
options->charset = cpystr(preferences.charset);
options->sigfile = cpystr(preferences.signature_file);
options->language = cpystr(preferences.language);
options->outlog = cpystr(preferences.sendlog);
options->defcc = cpystr(preferences.default_cc);
options->defbcc = cpystr(preferences.default_bcc);
options->prefix = cpystr(preferences.reply_prefix);
return(options);
}
#ifdef __STDC__
MLCompose *new_MLCompose(void)
#else
MLCompose *new_MLCompose()
#endif
{
MLCompose *mlcompose = (MLCompose *) fs_get(sizeof(MLCompose));
mlcompose->window = new_MLComposeWindow();
mlcompose->options = new_MLComposeOptions();
mlcompose->spellwindow = NULL;
mlcompose->compose_type = COMPOSE_NEW;
mlcompose->message = NULL;
mlcompose->in_reply_to = NULL;
mlcompose->reply_text = NULL;
mlcompose->remail_header = NULL;
mlcompose->in_ispell = FALSE;
mlcompose->has_newsgroups = FALSE;
mlcompose->parameters = NULL;
mlcompose->attachments = NULL;
mlcompose->part_list = NULL;
mlcompose->next = NULL;
mlcompose->prev = NULL;
return(mlcompose);
}
#ifdef __STDC__
void compose_message(Compose_Type type, Boolean news,
Lview *lview, Message *message,
Read_Info *read_info)
#else
void compose_message(type, news, lview, message, read_info)
Compose_Type type;
Boolean news;
Lview *lview;
Message *message;
Read_Info *read_info;
#endif
{
MLCompose *compose = new_MLCompose();
/* Create Window */
create_compose_window(compose, type, news);
/* Link to session */
if(session->compose) {
compose->next = session->compose;
session->compose->prev = compose;
}
session->compose = compose;
/* Set initial options. */
/* Get|Set known message values. */
if(read_info != NULL)
load_compose_from_read(compose, type, news, read_info);
else
load_compose_info(compose, type, news, lview, message);
if(compose->attachments == NULL) {
compose->window->buttonstate |= BTN_NOATTACH;
compose->window->buttonstate |= BTN_NOATTACHSELECT;
}
else
make_attachment_list(compose, TRUE);
compose_set_window_title(compose,type,news,lview,message,read_info);
compose_check_buttons(compose);
return;
}
#ifdef __STDC__
void create_compose_window(MLCompose *compose, Compose_Type type, Boolean news)
#else
void create_compose_window(compose, type, news)
MLCompose *compose;
Compose_Type type;
Boolean news;
#endif
{
Arg args[ARGLISTSIZE];
int n = 0;
XtTranslations translations;
XtSetArg (args[n], XmNdeleteResponse, XmDO_NOTHING); n++;
compose->window->shell = XtCreatePopupShell("compose",
topLevelShellWidgetClass,
session->shell,
NULL, 0);
AddDestroyCallback (compose->window->shell);
setup_editres(compose->window->shell);
if(compose_icon != (Pixmap) None)
XtVaSetValues(compose->window->shell,
XmNiconPixmap,compose_icon,
NULL);
compose->window->form = XmCreateForm(compose->window->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 ++;
compose->window->menubar = XmCreateMenuBar(compose->window->form,"menubar",
args, n);
n = 0;
XtManageChild(compose->window->menubar);
make_buttons(&compose->window->buttonlist,
NULL, compose->window->menubar,
compose_menu, XtNumber(compose_menu),
BTN_ON, (XtPointer) compose, 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, compose->window->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 ++;
compose->window->rowcol
= XmCreateRowColumn(compose->window->form, "rowcol", args, n); n = 0;
XtManageChild(compose->window->rowcol);
make_secondbuttons(compose->window->buttonlist,
compose->window->rowcol,
compose_secondbuttons, XtNumber(compose_secondbuttons),
BTN_ON, (XtPointer) compose);
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->rowcol); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNborderWidth, 0); n ++;
compose->window->to_button
= XmCreatePushButton(compose->window->form,"to_button", args, n);
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->rowcol); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNleftWidget,compose->window->to_button); n ++;
compose->window->to_text = XmCreateTextField(compose->window->form,
"to_textfld", args, n); n = 0;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->rowcol); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNborderWidth, 0); n ++;
compose->window->newsgroups_button
= XmCreatePushButton(compose->window->form,"newsgroups_button",
args, n);
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->rowcol); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNleftWidget,compose->window->newsgroups_button); n ++;
compose->window->newsgroups_text
= XmCreateTextField(compose->window->form,"newsgroups_textfld",
args, n); n = 0;
translations = XtParseTranslationTable(GLOBAL_text_field_translations);
XtOverrideTranslations(compose->window->to_text,translations);
translations =
XtParseTranslationTable(GLOBAL_nonterminal_text_field_translations);
XtOverrideTranslations(compose->window->to_text,translations);
translations =
XtParseTranslationTable(compose_address_translations);
XtOverrideTranslations(compose->window->to_text,translations);
XtAddCallback(compose->window->to_text, XmNmodifyVerifyCallback,
(XtCallbackProc) text_field_edit, NULL);
translations = XtParseTranslationTable(GLOBAL_text_field_translations);
XtOverrideTranslations(compose->window->newsgroups_text,translations);
translations =
XtParseTranslationTable(GLOBAL_nonterminal_text_field_translations);
XtOverrideTranslations(compose->window->newsgroups_text,translations);
translations =
XtParseTranslationTable(compose_address_translations);
XtOverrideTranslations(compose->window->newsgroups_text,translations);
XtAddCallback(compose->window->newsgroups_text, XmNmodifyVerifyCallback,
(XtCallbackProc) text_field_edit, NULL);
XtAddCallback(compose->window->newsgroups_button, XmNactivateCallback,
(XtCallbackProc) compose_toggle_news, compose );
XtAddCallback(compose->window->to_button, XmNactivateCallback,
(XtCallbackProc) compose_toggle_news, compose );
if(news == TRUE) {
XtManageChild(compose->window->newsgroups_button);
XtManageChild(compose->window->newsgroups_text);
compose->window->toggled_newsgroups = TRUE;
}
else {
XtManageChild(compose->window->to_button);
XtManageChild(compose->window->to_text);
compose->window->toggled_newsgroups = FALSE;
}
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->to_text); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNborderWidth, 0); n ++;
compose->window->subject_button =
XmCreatePushButton(compose->window->form,"subject_button", args, n); n = 0;
XtManageChild(compose->window->subject_button);
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->to_text); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNleftWidget,compose->window->subject_button); n ++;
compose->window->subject_text = XmCreateTextField(compose->window->form,
"subject_textfld",
args, n);
n = 0;
XtManageChild(compose->window->subject_text);
translations = XtParseTranslationTable(GLOBAL_text_field_translations);
XtOverrideTranslations(compose->window->subject_text,translations);
translations =
XtParseTranslationTable(GLOBAL_nonterminal_text_field_translations);
XtOverrideTranslations(compose->window->subject_text,translations);
XtAddCallback(compose->window->subject_text, XmNmodifyVerifyCallback,
(XtCallbackProc) text_field_edit, NULL);
XtAddCallback(compose->window->subject_button, XmNactivateCallback,
(XtCallbackProc) generate_subject, compose );
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->subject_text); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNborderWidth, 0); n ++;
compose->window->cc_button = XmCreatePushButton(compose->window->form,
"cc_button", args, n);
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->subject_text); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNleftWidget,compose->window->cc_button); n ++;
compose->window->cc_text = XmCreateTextField(compose->window->form,
"cc_textfld", args, n); n = 0;
translations = XtParseTranslationTable(GLOBAL_text_field_translations);
XtOverrideTranslations(compose->window->cc_text,translations);
translations =
XtParseTranslationTable(GLOBAL_nonterminal_text_field_translations);
XtOverrideTranslations(compose->window->cc_text,translations);
translations =
XtParseTranslationTable(compose_address_translations);
XtOverrideTranslations(compose->window->cc_text,translations);
XtAddCallback(compose->window->cc_text, XmNmodifyVerifyCallback,
(XtCallbackProc) text_field_edit, NULL);
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->subject_text); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNborderWidth, 0); n ++;
compose->window->bcc_button = XmCreatePushButton(compose->window->form,
"bcc_button", args, n);
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->subject_text); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNleftWidget,compose->window->bcc_button); n ++;
compose->window->bcc_text = XmCreateTextField(compose->window->form,
"bcc_textfld", args, n); n = 0;
translations = XtParseTranslationTable(GLOBAL_text_field_translations);
XtOverrideTranslations(compose->window->bcc_text,translations);
translations =
XtParseTranslationTable(GLOBAL_nonterminal_text_field_translations);
XtOverrideTranslations(compose->window->bcc_text,translations);
translations =
XtParseTranslationTable(compose_address_translations);
XtOverrideTranslations(compose->window->bcc_text,translations);
XtAddCallback(compose->window->bcc_text, XmNmodifyVerifyCallback,
(XtCallbackProc) text_field_edit, NULL);
XtAddCallback(compose->window->cc_button, XmNactivateCallback,
(XtCallbackProc) compose_toggle_cc, compose );
XtAddCallback(compose->window->bcc_button, XmNactivateCallback,
(XtCallbackProc) compose_toggle_cc, compose );
XtManageChild(compose->window->cc_button);
XtManageChild(compose->window->cc_text);
compose->window->toggled_bcc = FALSE;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmSTATIC); n ++;
XtSetArg(args[n], XmNlistSizePolicy,XmCONSTANT); n ++;
XtSetArg(args[n], XmNselectionPolicy,XmSINGLE_SELECT); n ++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->cc_text); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
compose->window->attach_list =
XmCreateScrolledList(compose->window->form,"partlist",args,n); n = 0;
XtManageChild(compose->window->attach_list);
XtAddCallback(compose->window->attach_list,
XmNsingleSelectionCallback,
(XtCallbackProc) select_attach, compose);
XtAddCallback(compose->window->attach_list,
XmNdefaultActionCallback,
(XtCallbackProc) double_click_attach, compose);
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->attach_list); n ++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNeditable, TRUE); n ++;
XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n ++;
XtSetArg(args[n], XmNwordWrap, TRUE); n ++;
XtSetArg(args[n], XmNcolumns, COMPOSEWIDTH - 1); n ++;
XtSetArg(args[n], XmNscrollVertical, TRUE); n ++;
XtSetArg(args[n], XmNscrollHorizontal, FALSE ); n ++;
compose->window->compose_text =
XmCreateScrolledText(compose->window->form, "text", args, n); n = 0;
XtManageChild(compose->window->compose_text);
translations = XtParseTranslationTable(GLOBAL_text_translations);
XtOverrideTranslations(compose->window->compose_text, translations);
translations = XtParseTranslationTable(GLOBAL_compose_pop_translations);
XtOverrideTranslations(compose->window->compose_text, translations);
XtAddCallback(compose->window->compose_text, XmNmodifyVerifyCallback,
(XtCallbackProc) text_hex_edit, NULL);
XtAddCallback(compose->window->shell, XmNdestroyCallback,
(XtCallbackProc) compose_destroy, compose);
XtManageChild(compose->window->form);
XtManageChild(compose->window->shell);
XtPopup(compose->window->shell, XtGrabNone);
return;
}
#ifdef __STDC__
void compose_destroy_current(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_destroy_current(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if(compose->in_ispell == TRUE)
return;
if(preferences.confirmDestroy == TRUE)
if((ml_confirm(compose->window->shell,
MLGetLocalized(XtNmsgDestroyEdit,
MsgDestroyEdit),CONFIRM_YES_NO)) == FALSE)
return;
compose_close_window(w,compose,xp);
return;
}
#ifdef __STDC__
void compose_close_window(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_close_window(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if(compose->in_ispell == TRUE)
return;
if(compose) {
XtPopdown(compose->window->shell);
XtDestroyWidget(compose->window->shell);
}
return;
}
#ifdef __STDC__
void compose_destroy(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_destroy(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if(compose) {
if(compose->next)
compose->next->prev = compose->prev;
if(compose == session->compose)
session->compose = compose->next;
else
compose->prev->next = compose->next;
free_MLCompose(compose);
}
return;
}
#ifdef __STDC__
void compose_wrap_off(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_wrap_off(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
Arg args[ARGLISTSIZE];
int n = 0;
XtTranslations translations;
char *str = NULL;
if((compose != NULL) && (compose->options != NULL)) {
compose->options->word_wrap = FALSE;
str = XmTextGetString(compose->window->compose_text);
XtDestroyWidget(compose->window->compose_text);
XtSetArg(args[n], XmNeditable, TRUE); n ++;
XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n ++;
XtSetArg(args[n], XmNwordWrap, FALSE); n ++;
XtSetArg(args[n], XmNcolumns, COMPOSEWIDTH - 1); n ++;
XtSetArg(args[n], XmNscrollVertical, TRUE); n ++;
XtSetArg(args[n], XmNscrollHorizontal, TRUE ); n ++;
compose->window->compose_text =
XmCreateScrolledText(compose->window->form, "compose_text", args, n);
n = 0;
translations = XtParseTranslationTable(GLOBAL_text_translations);
XtOverrideTranslations(compose->window->compose_text, translations);
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->attach_list); n ++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
XtSetValues(XtParent(compose->window->compose_text), args, n);
n = 0;
XtManageChild(compose->window->compose_text);
XmTextSetString(compose->window->compose_text, str);
fs_give((void **) &str);
}
return;
}
#ifdef __STDC__
void compose_wrap_on(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_wrap_on(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
Arg args[ARGLISTSIZE];
int n = 0;
char *str = NULL;
XtTranslations translations;
if((compose != NULL) && (compose->options != NULL)) {
compose->options->word_wrap = TRUE;
str = XmTextGetString(compose->window->compose_text);
XtDestroyWidget(compose->window->compose_text);
XtSetArg(args[n], XmNeditable, TRUE); n ++;
XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n ++;
XtSetArg(args[n], XmNwordWrap, TRUE); n ++;
XtSetArg(args[n], XmNcolumns, COMPOSEWIDTH - 1); n ++;
XtSetArg(args[n], XmNscrollVertical, TRUE); n ++;
XtSetArg(args[n], XmNscrollHorizontal, FALSE ); n ++;
compose->window->compose_text =
XmCreateScrolledText(compose->window->form,"compose_text", args, n);
n = 0;
translations = XtParseTranslationTable(GLOBAL_text_translations);
XtOverrideTranslations(compose->window->compose_text, translations);
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, compose->window->attach_list); n ++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n ++;
XtSetValues(XtParent(compose->window->compose_text), args, n); n = 0;
XtManageChild(compose->window->compose_text);
XmTextSetString(compose->window->compose_text, str);
fs_give((void **) &str);
XtSetArg(args[n], XmNwordWrap, TRUE); n ++;
XtSetArg(args[n], XmNscrollHorizontal, FALSE ); n ++;
XtSetValues(compose->window->compose_text, args, n); n = 0;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_NONE); n ++;
XtSetValues(XtParent(compose->window->compose_text), args, n); n = 0;
}
return;
}
#ifdef __STDC__
void compose_toggle_cc(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_toggle_cc(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if(compose != NULL) {
if(compose->window->toggled_bcc == TRUE) {
compose->window->toggled_bcc = FALSE;
XtUnmanageChild(compose->window->bcc_button);
XtUnmanageChild(compose->window->bcc_text);
XtManageChild(compose->window->cc_button);
XtManageChild(compose->window->cc_text);
}
else {
compose->window->toggled_bcc = TRUE;
XtUnmanageChild(compose->window->cc_button);
XtUnmanageChild(compose->window->cc_text);
XtManageChild(compose->window->bcc_button);
XtManageChild(compose->window->bcc_text);
}
}
return;
}
#ifdef __STDC__
void compose_toggle_news(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_toggle_news(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if(compose != NULL) {
if(compose->window->toggled_newsgroups == TRUE) {
compose->window->toggled_newsgroups = FALSE;
XtUnmanageChild(compose->window->newsgroups_button);
XtUnmanageChild(compose->window->newsgroups_text);
XtManageChild(compose->window->to_button);
XtManageChild(compose->window->to_text);
}
else {
compose->window->toggled_newsgroups = TRUE;
XtUnmanageChild(compose->window->to_button);
XtUnmanageChild(compose->window->to_text);
XtManageChild(compose->window->newsgroups_button);
XtManageChild(compose->window->newsgroups_text);
}
}
return;
}
#ifdef __STDC__
void compose_set_window_title(MLCompose *compose, Compose_Type type,
Boolean news, Lview *lview,
Message *message, Read_Info *read_info)
#else
void compose_set_window_title(compose, type, news, lview, message, read_info)
MLCompose *compose;
Compose_Type type;
Boolean news;
Lview *lview;
Message *message;
Read_Info *read_info;
#endif
{
char *basestr = NULL;
switch (type) {
case COMPOSE_REPLY:
basestr = MLGetLocalized(XtNmsgReplySender,MsgReplySender);
break;
case COMPOSE_REPLYALL:
basestr = MLGetLocalized(XtNmsgReplyAll,MsgReplyAll);
break;
case COMPOSE_FORWARD:
case COMPOSE_FORWARDATTACH:
basestr = MLGetLocalized(XtNmsgForward,MsgForward);
break;
case COMPOSE_REMAIL:
basestr = MLGetLocalized(XtNmsgRemail,MsgRemail);
break;
case COMPOSE_NEW:
default:
basestr = MLGetLocalized(XtNmsgComposeNew,MsgComposeNew);
break;
}
XtVaSetValues(compose->window->shell, XmNtitle, basestr, NULL);
return;
}
/*
* This is a fat function, and does almost all the dirty work. When it
* comes back, the message should be on its way.
*
* It takes a compose structure which
* points to an open compose window, extracts the stuff from
* the windows (which are presumably more current than the Compose_Info
* structures), connects any attachments, and sends it off. It also
* determines whether it is appropriate to send news, mail or both.
* On success, the current session is killed; the compose window is
* restored to any previous (or next) composings, or otherwise closes
* the window. On failure the message is left intact so the user can
* take some form of action to correct the condition, or perhaps save
* the work, or whatever.
*/
#ifdef __STDC__
void send_message(Widget w, MLCompose *compose, XtPointer xp)
#else
void send_message(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
SMTPSTREAM *smtp_stream = NIL;
SMTPSTREAM *nntp_stream = NIL;
ENVELOPE *envelope = NULL;
ENVELOPE *news_envelope = NULL;
BODY *body = NULL;
BODY *currbody = NULL;
PART *part = NULL;
char **mailhosts = NULL;
char **newshosts = NULL;
Boolean intl = FALSE;
char *chk;
unsigned long len;
char *default_host = NULL;
long openflags = 0L;
struct mail_body_parameter *params;
Boolean sendnews = FALSE;
Boolean sendmail = TRUE;
Boolean retry = FALSE;
Boolean attach_text = FALSE;
char *from = NULL;
char *to = NULL;
char *newsgroups = NULL;
char *subject = NULL;
char *cc = NULL;
char *bcc = NULL;
char *temp_text = NULL;
char *text = NULL;
char *fixed_subject = NULL;
char msgno_string[32];
int errors = 0;
if((CheckConnection()) == FALSE) {
mm_log(MLGetLocalized(XtNmsgNotConnected,MsgNotConnected),WARN);
return;
}
if((compose->options->domain != NULL)
&& (*compose->options->domain != NUL_TERM))
default_host = cpystr(compose->options->domain);
else
default_host = cpystr(compose->options->mailhost);
push_cursor(WATCH_CURSOR);
if(! default_host)
default_host = cpystr(EMPTYSTR);
mailhosts = (char **) fs_get( 2 * sizeof(char *));
mailhosts[0] = cpystr(compose->options->mailhost);
mailhosts[1] = NULL;
newshosts = (char **) fs_get( 2 * sizeof(char *));
newshosts[0] = cpystr(compose->options->nntphost);
newshosts[1] = NULL;
from = cpystr(compose->options->replyto);
/* Collect message information from window. */
newsgroups = GetTextField(compose->window->newsgroups_text);
to = GetTextField(compose->window->to_text);
subject = GetTextField(compose->window->subject_text);
cc = GetTextField(compose->window->cc_text);
bcc = GetTextField(compose->window->bcc_text);
text = XmTextGetString(compose->window->compose_text);
/* See if the text has international chars we might need to encode */
for(chk = text; (*chk != NUL_TERM) ; chk ++ )
if(((unsigned char) *chk) >= (unsigned char) 0x80)
intl = TRUE;
/*
* Do two conversions. First translate paragraphs to LF terminated
* text. Then turn LF to CRLF for sending. The reason for doing this
* in two steps is so we can allocate approximately the right amount
* of space in each function, and not have to overkill the memory
* requirements. It also compartmentalizes the functionality.
*
*/
if(compose->options->word_wrap == TRUE)
temp_text = wrap_text(text, COMPOSEWIDTH - 1);
else
temp_text = cpystr(text);
fs_give((void **) &text);
text = lftocrlf(temp_text);
fs_give((void **) &temp_text);
if((intl == TRUE) && (compose->options->send_eight == FALSE))
temp_text = (char *)
rfc822_8bit((unsigned char *) text, (unsigned long) strlen(text), &len);
else
temp_text = NULL;
if((newsgroups != NULL) && (*(first_nonwhite(newsgroups)) != NUL_TERM))
sendnews = TRUE;
if( (*(first_nonwhite(to)) == NUL_TERM)
&& (*(first_nonwhite(cc)) == NUL_TERM)
&& (*(first_nonwhite(bcc)) == NUL_TERM))
sendmail = FALSE;
/* No recipients. Make sure it fails. */
if((sendnews == FALSE) && (sendmail == FALSE))
retry = TRUE;
if(compose->options->verbose == TRUE)
openflags |= SOP_DEBUG;
if(sendnews == TRUE) {
nntp_stream = nntp_open(newshosts, openflags);
if(nntp_stream == NIL) {
mm_log(MLGetLocalized(XtNmsgOpenNNTPFailed,MsgOpenNNTPFailed),WARN);
retry = TRUE;
}
}
if(compose->options->send_eight == TRUE)
openflags |= SOP_ESMTP;
if(sendmail == TRUE) {
smtp_stream = smtp_open(mailhosts, openflags);
if(smtp_stream == NIL) {
mm_log(MLGetLocalized(XtNmsgOpenSMTPFailed,MsgOpenSMTPFailed),WARN);
retry = TRUE;
}
}
/*
* We've got our neccessary stream(s) open. Now build the message.
*/
body = mail_newbody();
envelope = mail_newenvelope();
/* Don't send any empty multiparts. Won't work */
fix_empty_attachments(compose);
if(compose->attachments) {
body->contents.part = compose->attachments;
body->type = TYPEMULTIPART;
body->encoding = ENC7BIT;
/*
* Our text portion (if there is one)
* will become the first part of the multipart
*/
if(*text != NUL_TERM) {
attach_text = TRUE;
part = mail_newbody_part();
currbody = &(part->body);
part->next = body->contents.part;
body->contents.part = part;
}
else
currbody = NULL;
}
else /* Not a multipart. Just the text message. */
currbody = body;
/*
* Set the parameters for CHARSET and LANGUAGE in the parent
* compose structure. We only want to do this once; and this function
* might be re-entered if options->keep_open is set.
*/
if(intl) {
for(params = compose->parameters; params != NULL; params = params->next)
if((params->attribute != NULL)
&& (strcasecmp(params->attribute,CHARSET_STR) == STRMATCH))
break;
/*
* NULL params means "CHARSET" wasn't found,
* so initialize it (if not US-ASCII).
*/
if(params == NULL) {
if((strcasecmp(compose->options->charset,US_ASCII_STR) != STRMATCH)) {
params = mail_newbody_parameter();
params->attribute = cpystr(CHARSET_STR);
params->value = cpystr(compose->options->charset);
if(compose->parameters)
params->next = compose->parameters;
compose->parameters = params;
}
}
}
/*
* Now do the same (though a bit different logic) for LANGUAGE.
*/
if(*compose->options->language) {
for(params = compose->parameters; params != NULL; params = params->next)
if((params->attribute != NULL)
&& (strcasecmp(params->attribute,"LANGUAGE") == STRMATCH))
break;
if(params == NULL) {
params = mail_newbody_parameter();
params->attribute = cpystr("LANGUAGE");
params->value = cpystr(compose->options->language);
if(compose->parameters)
params->next = compose->parameters;
compose->parameters = params;
}
}
/*
* Attach our text to the body.
* If we have 8-bit chars, we start off with 8bit encoding
* for NNTP. After that's sent we'll have to check and perhaps
* switch to Q-P if desired or the mailstream doesn't support it.
*/
if(currbody) {
currbody->type = TYPETEXT;
currbody->encoding = (intl == TRUE) ? ENC8BIT : ENC7BIT;
currbody->contents.text = (unsigned char *) text;
currbody->size.bytes = (unsigned long) strlen((char *) text);
currbody->parameter = copy_params(compose->parameters, intl);
}
/*
* Now build the appropriate envelope(s).
* Warning: The c-client appears to trash the calling text strings
* in rfc822_parse_addr(), which text_to_address() calls... So, don't
* parse the same string twice to get a duplicate. Use copy_address()
* instead.
*/
envelope->from = text_to_address(from,default_host);
envelope->to = text_to_address(to, default_host);
envelope->cc = text_to_address(cc, default_host);
envelope->bcc = text_to_address(bcc, default_host);
envelope->reply_to = copy_address(envelope->from);
envelope->return_path = mail_newaddr();
if(envelope->from) {
if(envelope->from->mailbox)
envelope->return_path->mailbox = cpystr(envelope->from->mailbox);
if(envelope->from->host)
envelope->return_path->host = cpystr(envelope->from->host);
}
/*
* The sender field is our real bonafide Unix name.
* This is done to thwart forgeries. This address is also used
* for delivery bounces. Making certain that it can be used for
* this purpose is a local system administration issue. That is,
* if incoming SMTP is not allowed on the system, it should be
* MX forwarded to a mail hub which can process the errors.
*/
if(compose->compose_type == COMPOSE_REMAIL) {
envelope->remail = cpystr(compose->remail_header);
body->type = TYPETEXT;
if(body->subtype)
fs_give((void **) &body->subtype);
body->subtype = NULL;
body->encoding = ENC7BIT;
}
else {
envelope->sender = mail_newaddr();
envelope->sender->mailbox = cpystr(local_auth.username);
envelope->sender->host = cpystr(local_auth.hostname);
}
envelope->subject = cpystr(subject);
if(compose->in_reply_to)
envelope->in_reply_to = cpystr(compose->in_reply_to);
/*
* Generate a message-id and date. Note that we also supply the
* real Unix credentials here as the second stage of
* forgery suppression.
*/
envelope->message_id = (char *) fs_get(MESSAGE_ID_LENGTH);
sprintf(envelope->message_id,"<%s-%s.%d.%d.%s@%s>",
PROGRAM, MLVERSION,
time(NULL), rand() % 10000,
local_auth.username, local_auth.hostname);
envelope->date = (char *) fs_get(MESSAGE_ID_LENGTH);
rfc822_date(envelope->date);
/* Allow legitimate schizoids (undocumented) */
compose_smart_reply(envelope, newsgroups);
if((sendnews == TRUE) && (nntp_stream != NIL)) {
/*
* We create a separate envelope for news posts, containing
* newsgroups line, and stripping out to,cc,bcc. We don't need to,
* but partitioning like this will prevent older pine clients
* from reporting "bogus newsgroups". The reasons are amusing if you
* look closely at c-client/rfc822.c.
*/
news_envelope = mail_newenvelope();
news_envelope->from = copy_address(envelope->from);
news_envelope->reply_to = copy_address(envelope->reply_to);
news_envelope->return_path = copy_address(envelope->return_path);
news_envelope->sender = copy_address(envelope->sender);
news_envelope->subject = cpystr(envelope->subject);
news_envelope->message_id = cpystr(envelope->message_id);
news_envelope->date = cpystr(envelope->date);
if(compose->in_reply_to) {
news_envelope->in_reply_to
= (char *) fs_get((2 * strlen(compose->in_reply_to)) + 32);
sprintf(news_envelope->in_reply_to,"%s\r\nReferences: %s",
compose->in_reply_to,
compose->in_reply_to);
}
news_envelope->newsgroups = cpystr(newsgroups);
errors = nntp_mail(nntp_stream, news_envelope, body);
if(errors != T ) {
mm_log(MLGetLocalized(XtNmsgSendNNTPFailed,MsgSendNNTPFailed),WARN);
retry = TRUE;
}
else
mm_log(MLGetLocalized(XtNmsgNewsSent,MsgNewsSent),NIL);
smtp_close(nntp_stream);
}
if((sendmail == TRUE) && (smtp_stream != NIL)) {
/*
* OK. Now we've got to see if 8-bit text is allowed, and otherwise
* do some last minute patching of the message if it's got 8-bit
* text.
*/
if((intl == TRUE) && (compose->options->send_eight == TRUE)) {
if(! smtp_stream->ok_8bitmime) {
mm_log(MLGetLocalized(XtNmsgSendEightFailure,MsgSendEightFailure),
WARN);
compose->options->send_eight = FALSE;
}
}
if(compose->options->send_eight == TRUE)
fs_give((void **) &temp_text); /* Well, we sure don't need you now */
else {
if((intl == TRUE) && (currbody != NULL)) {
if (temp_text == NULL)
temp_text = (char *)
rfc822_8bit((unsigned char *) text,
(unsigned long) strlen(text), &len);
currbody->encoding = ENCQUOTEDPRINTABLE;
fs_give((void **) &text);
currbody->contents.text = (unsigned char *) temp_text;
currbody->size.bytes = (unsigned long) strlen((char *) temp_text);
}
iso_encode_address(envelope->from);
iso_encode_address(envelope->to);
iso_encode_address(envelope->cc);
iso_encode_address(envelope->bcc);
iso_encode_address(envelope->reply_to);
iso_encode_address(envelope->return_path);
if(envelope->subject)
fs_give((void **) &envelope->subject);
envelope->subject = iso_encode_subject(subject);
}
errors = smtp_mail(smtp_stream,"MAIL", envelope, body);
if(errors != T ) {
mm_log(MLGetLocalized(XtNmsgSendSMTPFailed,MsgSendSMTPFailed),WARN);
retry = TRUE;
}
else
mm_log(MLGetLocalized(XtNmsgMailSent,MsgMailSent),NIL);
smtp_close(smtp_stream);
}
if(retry == FALSE) {
if((sendnews == TRUE) && (sendmail == TRUE))
envelope->newsgroups = cpystr(newsgroups);
log_message(compose, body, envelope);
}
if(sendnews == TRUE)
mail_free_envelope(&news_envelope);
if(sendmail == TRUE)
mail_free_envelope(&envelope);
/*
* If the send failed, protect all our attachments. mail_free_body()
* is recursive. If the first part is our text, we'll let it go,
* since it will be rebuilt next time through. This also means we
* don't explicity free it. It will be nuked as a result of
* mail_free_body().
*/
if((retry == TRUE) || (compose->options->keep_open == TRUE)) {
if(attach_text == TRUE)
body->contents.part->next = NIL;
else
body->contents.part = NIL;
}
else {
/* Set answered flag on original message if appropriate */
if(((compose->compose_type == COMPOSE_REPLY) ||
(compose->compose_type == COMPOSE_REPLYALL))
&& ((compose->message != NULL)
&& compose->message->mailstream && compose->message->msgno)) {
sprintf(msgno_string,"%lu",compose->message->msgno);
push_cursor(WATCH_CURSOR);
mail_setflag(compose->message->mailstream,
msgno_string, ANSWERED_FLAG );
mm_flags(compose->message->mailstream,
compose->message->msgno);
pop_cursor();
}
}
/*
* Clean up everything and go home.
*/
mail_free_body(&body); /* and therefore our allocated text */
fs_give((void **) &from);
fs_give((void **) &to);
fs_give((void **) &newsgroups);
fs_give((void **) &subject);
fs_give((void **) &cc);
fs_give((void **) &bcc);
fs_give((void **) &mailhosts[0]);
fs_give((void **) &mailhosts);
fs_give((void **) &newshosts[0]);
fs_give((void **) &newshosts);
fs_give((void **) &default_host);
if((retry == FALSE) && (compose->options->keep_open == FALSE)) {
/*
* Our attachments are already gone. Make sure we don't
* free them a second time.
*/
compose->attachments = NIL;
compose_close_window(w,compose,xp);
}
pop_cursor();
return;
}
/*
* Called externally from mm_expunge() on an expunge event. There is no
* guarantee that a compose structure exists. What we do is locate a
* message structure which matches and zero it out in the compose structure.
* This guarantees we won't be setting any flags on it later. There will
* only be such a message structure on replies. Since these are just
* pointers to messages found in the mailbox, we don't need to manage
* the message numbers for higher numbered messages here. That's done
* in the main window expunge loop. Be careful not to destroy the
* structure before this gets called.
*/
#ifdef __STDC__
void compose_expunge(MAILSTREAM *mailstream, unsigned long msgno)
#else
void compose_expunge(mailstream,msgno)
MAILSTREAM *mailstream;
unsigned long msgno;
#endif
{
MLCompose *compose;
if(session->compose != NULL) {
for(compose = session->compose ; compose; compose = compose->next) {
if((compose->message != NULL)
&& (compose->message->mailstream == mailstream)
&& (compose->message->msgno == msgno))
compose->message = NULL;
}
}
return;
}
#ifdef __STDC__
void load_compose_from_read(MLCompose *compose, Compose_Type type,
Boolean news, Read_Info *read_info)
#else
void load_compose_from_read(compose,type,news,read_info)
MLCompose *compose;
Compose_Type type;
Boolean news;
Read_Info *read_info;
#endif
{
char *to;
char *reply_subject;
char *cc;
char *msgid;
char *ptr1;
char *ptr2;
char *fulltext;
char *fulleverything;
PART *part;
BODY *body;
char *tmp;
if((type == COMPOSE_NEW) || (read_info == NULL))
return;
compose->compose_type = type;
push_cursor(WATCH_CURSOR);
switch(type) {
case COMPOSE_REPLYALL:
ptr1 = get_header_field_contents(HEADER_NEWSGROUPS, read_info->header);
if(ptr1) {
XmTextSetString(compose->window->newsgroups_text, ptr1);
fs_give((void **) &ptr1);
}
ptr1 = get_header_field_contents(HEADER_TO,read_info->header);
if(ptr1 == NULL)
ptr1 = cpystr(EMPTYSTR);
ptr2 = get_header_field_contents(HEADER_CC,read_info->header);
if(ptr2 == NULL)
ptr2 = cpystr(EMPTYSTR);
cc = (char *) fs_get(strlen(ptr1) + strlen(ptr2) + 8 );
*cc = NUL_TERM;
if(*ptr1 != NUL_TERM) {
strcpy(cc,ptr1);
if(*ptr2 != NUL_TERM)
strcat(cc,", ");
}
if(*ptr2 != NUL_TERM)
strcat(cc,ptr2);
fs_give((void **) &ptr1);
fs_give((void **) &ptr2);
XmTextSetString(compose->window->cc_text, cc);
fs_give((void **) &cc);
/* fall through to set other info */
case COMPOSE_REPLY:
to = get_header_field_contents(HEADER_REPLY_TO,read_info->header);
if(to == NULL)
to = get_header_field_contents(HEADER_FROM, read_info->header);
if(to) {
XmTextSetString(compose->window->to_text, to);
fs_give((void **) &to);
}
reply_subject = get_reply_subject(read_info->header);
if(reply_subject != NULL) {
XmTextSetString(compose->window->subject_text, reply_subject);
fs_give((void **) &reply_subject);
}
msgid = get_header_field_contents(HEADER_MESSAGE_ID, read_info->header);
compose->in_reply_to = msgid;
/* References !!! */
if(read_info->alt_text)
compose->reply_text = cpystr(read_info->alt_text);
else
if(read_info->current_text)
compose->reply_text = cpystr(read_info->current_text);
compose->message = read_info->message;
break;
case COMPOSE_FORWARD:
if(read_info->alt_text) {
ptr1 = get_forward_text(read_info->alt_text);
if(ptr1) {
XmTextSetString(compose->window->compose_text, ptr1);
fs_give((void **) &ptr1);
}
}
else {
if(read_info->current_text) {
ptr1 = get_forward_text(read_info->current_text);
if(ptr1) {
XmTextSetString(compose->window->compose_text, ptr1);
fs_give((void **) &ptr1);
}
}
}
ptr1 = get_forward_subject(read_info->header);
if(ptr1) {
XmTextSetString(compose->window->subject_text, ptr1);
fs_give((void **) &ptr1);
}
break;
case COMPOSE_FORWARDATTACH:
if((read_info->mailstream == NULL)
|| (read_info->msgno == 0L)) {
mm_log(MLGetLocalized(XtNmsgForwardExpunged,MsgForwardExpunged),WARN);
break;
}
fulltext = mail_fetchtext(read_info->mailstream,read_info->msgno);
if(fulltext == NULL)
break;
stripcr(fulltext);
fulleverything = (char *) fs_get(((read_info->header)
? strlen(read_info->header) : 1)
+ strlen(fulltext) + 256);
strcpy(fulleverything, (read_info->header) ? read_info->header : EMPTYSTR);
strcat(fulleverything,LFSTR);
strcat(fulleverything,fulltext);
part = mail_newbody_part();
body = &part->body;
body->type = TYPEMESSAGE;
body->subtype = cpystr("RFC822");
body->description = get_forward_subject(read_info->header);
body->encoding = ENC7BIT;
body->contents.msg.text = fulleverything;
compose->attachments = part;
break;
case COMPOSE_REMAIL:
if(read_info->mailstream && read_info->msgno) {
compose->remail_header
= cpystr(mail_fetchheader(read_info->mailstream,read_info->msgno));
ptr1 = cpystr(mail_fetchtext(read_info->mailstream, read_info->msgno));
if(ptr1) {
stripcr(ptr1);
XmTextSetString(compose->window->compose_text, ptr1);
fs_give((void **) &ptr1);
}
}
break;
default:
break;
}
if((compose->options->defcc != NULL)
&& (*compose->options->defcc != NUL_TERM)) {
ptr1 = XmTextGetString(compose->window->cc_text);
if(*ptr1 != NUL_TERM)
AppendText(compose->window->cc_text,", ");
AppendText(compose->window->cc_text,compose->options->defcc);
fs_give((void **) &ptr1);
}
if((compose->options->defbcc != NULL)
&& (*compose->options->defbcc != NUL_TERM)) {
ptr1 = XmTextGetString(compose->window->bcc_text);
if(*ptr1 != NUL_TERM)
AppendText(compose->window->bcc_text,", ");
AppendText(compose->window->bcc_text,compose->options->defbcc);
fs_give((void **) &ptr1);
}
pop_cursor();
return;
}
#ifdef __STDC__
void load_compose_info(MLCompose *compose, Compose_Type type,
Boolean news, Lview *lview, Message *message)
#else
void load_compose_info(compose,type, news, lview, message)
MLCompose *compose;
Compose_Type type;
Boolean news;
Lview *lview;
Message *message;
#endif
{
char *tmp;
char *to;
char *reply_subject;
char *cc;
char *msgid;
char *ptr1;
char *ptr2;
char *fulleverything;
PART *oldpart;
PART *part;
BODY *body;
char *fetched_header = NULL;
char *fetched_text = NULL;
Message_List *message_list;
compose->compose_type = type;
push_cursor(WATCH_CURSOR);
if(message) {
fetched_header = cpystr(mail_fetchheader(message->mailstream,
message->msgno));
stripcr(fetched_header);
if(fetched_header[strlen(fetched_header) - 1] == LFCHAR)
fetched_header[strlen(fetched_header) - 1] = NUL_TERM;
fetched_text = cpystr(mail_fetchtext(message->mailstream,
message->msgno));
stripcr(fetched_text);
}
switch(type) {
case COMPOSE_REPLYALL:
ptr1 = get_header_field_contents(HEADER_NEWSGROUPS, fetched_header);
if(ptr1) {
XmTextSetString(compose->window->newsgroups_text,ptr1);
fs_give((void **) &ptr1);
}
ptr1 = get_header_field_contents(HEADER_TO,fetched_header);
if(ptr1 == NULL)
ptr1 = cpystr(EMPTYSTR);
ptr2 = get_header_field_contents(HEADER_CC,fetched_header);
if(ptr2 == NULL)
ptr2 = cpystr(EMPTYSTR);
cc = (char *) fs_get(strlen(ptr1) + strlen(ptr2) + 8 );
*cc = NUL_TERM;
if(*ptr1 != NUL_TERM) {
strcpy(cc,ptr1);
if(*ptr2 != NUL_TERM)
strcat(cc,", ");
}
if(*ptr2 != NUL_TERM)
strcat(cc,ptr2);
fs_give((void **) &ptr1);
fs_give((void **) &ptr2);
XmTextSetString(compose->window->cc_text,cc);
fs_give((void **) &cc);
/* fall through to set other info */
case COMPOSE_REPLY:
to = get_header_field_contents(HEADER_REPLY_TO,fetched_header);
if(to == NULL)
to = get_header_field_contents(HEADER_FROM, fetched_header);
if(to) {
XmTextSetString(compose->window->to_text, to);
fs_give((void **) &to);
}
reply_subject = get_reply_subject(fetched_header);
if(reply_subject) {
XmTextSetString(compose->window->subject_text, reply_subject);
fs_give((void **) &reply_subject);
}
msgid = get_header_field_contents(HEADER_MESSAGE_ID, fetched_header);
compose->in_reply_to = msgid;
if(fetched_text)
compose->reply_text = cpystr(fetched_text);
compose->message = message;
break;
case COMPOSE_FORWARD:
get_multi_forward_info(lview,compose);
break;
case COMPOSE_FORWARDATTACH:
for(message_list = lview->message_list;
message_list; message_list = message_list->next) {
if(message_list->selected == TRUE) {
if(fetched_header)
fs_give((void **) &fetched_header);
if(fetched_text)
fs_give((void **) &fetched_text);
fetched_header
= cpystr(mail_fetchheader(message_list->message->mailstream,
message_list->message->msgno));
stripcr(fetched_header);
if(fetched_header[strlen(fetched_header) - 1] == LFCHAR)
fetched_header[strlen(fetched_header) - 1] = NUL_TERM;
fetched_text
= cpystr(mail_fetchtext(message_list->message->mailstream,
message_list->message->msgno));
stripcr(fetched_text);
fulleverything = (char *) fs_get(strlen(fetched_header) +
strlen(fetched_text) + 256);
strcpy(fulleverything,fetched_header);
strcat(fulleverything,LFSTR);
strcat(fulleverything,fetched_text);
part = mail_newbody_part();
body = &part->body;
body->type = TYPEMESSAGE;
body->subtype = cpystr("RFC822");
body->description = get_forward_subject(fetched_header);
body->encoding = ENC7BIT;
body->contents.msg.text = fulleverything;
if(compose->attachments == NULL)
compose->attachments = part;
else {
for(oldpart = compose->attachments; oldpart->next;
oldpart = oldpart->next)
;
oldpart->next = part;
}
fs_give((void **) &fetched_header);
fs_give((void **) &fetched_text);
}
}
break;
case COMPOSE_REMAIL:
compose->message = message;
if(fetched_header)
compose->remail_header = cpystr(fetched_header);
if(fetched_text)
XmTextSetString(compose->window->compose_text,fetched_text);
break;
default:
break;
}
if(fetched_header)
fs_give((void **) &fetched_header);
if(fetched_text)
fs_give((void **) &fetched_text);
if((compose->options->defcc != NULL)
&& (*compose->options->defcc != NUL_TERM)) {
ptr1 = XmTextGetString(compose->window->cc_text);
if(*ptr1 != NUL_TERM)
AppendText(compose->window->cc_text,", ");
AppendText(compose->window->cc_text,compose->options->defcc);
fs_give((void **) &ptr1);
}
if((compose->options->defbcc != NULL)
&& (*compose->options->defbcc != NUL_TERM)) {
ptr1 = XmTextGetString(compose->window->bcc_text);
if(*ptr1 != NUL_TERM)
AppendText(compose->window->bcc_text,", ");
AppendText(compose->window->bcc_text,compose->options->defbcc);
fs_give((void **) &ptr1);
}
pop_cursor();
return;
}
#ifdef __STDC__
void get_multi_forward_info(Lview *lview, MLCompose *compose)
#else
void get_multi_forward_info(lview,compose)
Lview *lview;
MLCompose *compose;
#endif
{
Message_List *message_list;
unsigned long count = 0L;
Message *message = NULL;
char *old_header = NULL;
char *old_text = NULL;
char *new_header = NULL;
char *new_text = NULL;
char *tmp_header = NULL;
char *tmp_text = NULL;
char *fetched_header = NULL;
char *fetched_text = NULL;
char *ret = NULL;
char *foo = NULL;
for(message_list = lview->message_list; message_list;
message_list = message_list->next) {
if(message_list->selected) {
message = message_list->message;
count ++;
}
}
if(count == 0)
return;
if((count == 1) && (message)) {
fetched_header = cpystr(mail_fetchheader(message->mailstream,
message->msgno));
stripcr(fetched_header);
if(fetched_header[strlen(fetched_header) - 1] == LFCHAR)
fetched_header[strlen(fetched_header) - 1] = NUL_TERM;
fetched_text = cpystr(mail_fetchtext(message->mailstream,
message->msgno));
stripcr(fetched_text);
foo = get_forward_text(fetched_text);
XmTextSetString(compose->window->compose_text, foo);
fs_give((void **) &foo);
foo = get_forward_subject(fetched_header);
XmTextSetString(compose->window->subject_text,foo);
fs_give((void **) &foo);
fs_give((void **) &fetched_header);
fs_give((void **) &fetched_text);
return;
}
count = 0;
XmTextSetString(compose->window->subject_text,
MLGetLocalized(XtNstrMultiForwardSubject,
StrMultiForwardSubject));
old_header = cpystr(MLGetLocalized(XtNstrMultiForwardHeader,
StrMultiForwardHeader));
old_text = cpystr(EMPTYSTR);
for(message_list = lview->message_list; message_list;
message_list = message_list->next) {
if(message_list->selected) {
message = message_list->message;
count ++;
fetched_header = cpystr(mail_fetchheader(message->mailstream,
message->msgno));
stripcr(fetched_header);
if(fetched_header[strlen(fetched_header) - 1] == LFCHAR)
fetched_header[strlen(fetched_header) - 1] = NUL_TERM;
tmp_header = get_short_forward_line(fetched_header,count);
new_header = (char *)fs_get(strlen(old_header) + strlen(tmp_header) + 1);
strcpy(new_header,old_header);
strcat(new_header,tmp_header);
fs_give((void **) &old_header);
fs_give((void **) &tmp_header);
fs_give((void **) &fetched_header);
old_header = new_header;
fetched_text = cpystr(mail_fetchtext(message->mailstream,
message->msgno));
stripcr(fetched_text);
tmp_text = get_forward_text(fetched_text);
new_text = (char *) fs_get(strlen(old_text) + strlen(tmp_text) + 2);
strcpy(new_text,old_text);
strcat(new_text,LFSTR);
strcat(new_text,tmp_text);
fs_give((void **) &old_text);
fs_give((void **) &tmp_text);
fs_give((void **) &fetched_text);
old_text = new_text;
}
}
ret = (char *) fs_get(strlen(old_header) + strlen(old_text) + 1);
strcpy(ret,old_header);
strcat(ret,old_text);
fs_give((void **) &old_header);
fs_give((void **) &old_text);
XmTextSetString(compose->window->compose_text,ret);
fs_give((void **) &ret);
return;
}
#ifdef __STDC__
void compose_help(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_help(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
help(compose->window->shell, COMPOSEHELPFILE);
return;
}
/* Option setting callbacks. */
#ifdef __STDC__
void compose_keep_open(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_keep_open(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if((compose != NULL) && (compose->options != NULL)) {
compose->options->keep_open = TRUE;
}
return;
}
#ifdef __STDC__
void compose_eight(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_eight(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if((compose != NULL) && (compose->options != NULL)) {
compose->options->send_eight = TRUE;
}
return;
}
#ifdef __STDC__
void compose_seven(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_seven(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if((compose != NULL) && (compose->options != NULL)) {
compose->options->send_eight = FALSE;
}
return;
}
/*
* Turn on the mail debugging flag. We can also do it globally
* from preferences.smtp_debug. This sets it for the current
* message only. There is no way to turn it off again.
*/
#ifdef __STDC__
void compose_watch_delivery(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_watch_delivery(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
if((compose != NULL) && (compose->options != NULL)) {
compose->options->verbose = TRUE;
}
return;
}
#ifdef __STDC__
struct mail_body_parameter *copy_params(struct mail_body_parameter *src,
Boolean intl)
#else
struct mail_body_parameter *copy_params(src, intl)
struct mail_body_parameter *src;
Boolean intl;
#endif
{
struct mail_body_parameter *curr;
struct mail_body_parameter *new;
struct mail_body_parameter *prev = NULL;
struct mail_body_parameter *ret = NULL;
if(src == NULL)
return(NULL);
for(curr = src; curr; curr = curr->next) {
/* No 8-bit characters were found. Remove any charset value
* so as to default to us-ascii. This is called for in the
* MIME specification.
*/
if((intl == FALSE) && (curr != NULL)
&& (curr->attribute != NULL)
&& ((strcasecmp(curr->attribute,"charset")) == STRMATCH))
continue;
new = mail_newbody_parameter();
new->attribute = cpystr(curr->attribute);
new->value = cpystr(curr->value);
if(ret == NULL)
ret = new;
if(prev)
prev->next = new;
prev = new;
}
return(ret);
}
#ifdef __STDC__
void fix_empty_attachments(MLCompose *compose)
#else
void fix_empty_attachments(compose)
MLCompose *compose;
#endif
{
Part_List *part_list;
BODY *body;
PART *part;
BODY *newbody;
Boolean changed = FALSE;
for(part_list = compose->part_list;
part_list; part_list = part_list->next) {
body = &(part_list->part->body);
if((body->type == TYPEMULTIPART) && (body->contents.part == NULL)) {
/*
* Somebody tried to send an empty part. It would be rather
* painful to try and prune it, so we'll gratuitously supply
* a part for them. Otherwise, the c-client will core dump.
*
*/
part = mail_newbody_part();
body->contents.part = part;
newbody = &part->body;
newbody->type = TYPETEXT;
newbody->encoding = ENC7BIT;
newbody->description = cpystr(MLGetLocalized(XtNstrFakePart,
StrFakePart));
newbody->subtype = cpystr("plain");
newbody->contents.text = (unsigned char *) cpystr(EMPTYSTR);
newbody->size.bytes = 0;
changed = TRUE;
}
}
if(changed == TRUE) {
mm_log(MLGetLocalized(XtNmsgEmptyMultipart,MsgEmptyMultipart),WARN);
make_attachment_list(compose, FALSE);
}
return;
}
#ifdef __STDC__
void log_message(MLCompose *compose, BODY *body, ENVELOPE *envelope)
#else
void log_message(compose, body, envelope)
MLCompose *compose;
BODY *body;
ENVELOPE *envelope;
#endif
{
extern STRINGDRIVER mail_string;
STRING bs;
char *mailboxname;
char tmp[16 * FILEBUFFLEN];
char tmpfile[MAXPATHLEN];
char log[FILEBUFFLEN];
Binary_Buffer *binary_buffer;
FILE *fp;
Server_Config *config;
char *host;
Boolean changed = FALSE; /* ignored */
if((compose != NULL) && (compose->options != NULL)) {
if((*compose->options->outlog == NUL_TERM)
|| (compose->options->message_log == FALSE))
return;
mailboxname = fix_netmailboxpath(compose->options->outlog,&changed);
if(compose->options->log_attachments == FALSE) {
log_short_message(compose,mailboxname,body,envelope);
return;
}
tmpnam(tmpfile);
if((fp = fopen(tmpfile,"w")) == NULL) {
sprintf(log,MLGetLocalized(XtNmsgCannotWriteFile,MsgCannotWriteFile),
tmpfile);
mm_log(log,WARN);
fs_give((void **) &mailboxname);
return;
}
chmod(tmpfile,S_IRWXU);
rfc822_output(tmp,envelope, body, ml_file_soutr, fp);
fclose(fp);
binary_buffer = load_binary_file(tmpfile);
unlink(tmpfile);
if(binary_buffer) {
if(binary_buffer->data) {
INIT(&bs,mail_string,binary_buffer->data, binary_buffer->length);
if((mail_append_full(NIL,mailboxname, SEEN_FLAG,
NULL, &bs)) == NIL)
mm_log(MLGetLocalized(XtNmsgAppendFailed,MsgAppendFailed),WARN);
}
free_binary_buffer(binary_buffer);
}
}
return;
}
#ifdef __STDC__
long ml_file_soutr(void *stream, char *s)
#else
long ml_file_soutr(stream,s)
void *stream;
char *s;
#endif
{
FILE *fp = stream;
char c, *t;
if (s[0] == '.') fputs(".",fp);
/* find lines beginning with a "." */
while (t = ML_Strstr (s,"\015\012.")) {
c = *(t += 3); /* remember next character after "." */
*t = '\0'; /* tie off string */
/* output prefix */
if ((fputs(s,fp)) == EOF)
return NIL;
*t = c; /* restore delimiter */
s = t - 1; /* push pointer up to the "." */
}
if(*s) {
if((fputs(s,fp)) == EOF)
return(NIL);
else
return(T);
}
else
return(T);
}
#ifdef __STDC__
void cat4(char *dest, char *s1, char *s2, char *s3, char *s4)
#else
void cat4(dest,s1,s2,s3,s4)
char *dest;
char *s1;
char *s2;
char *s3;
char *s4;
#endif
{
strcat(dest,s1);
strcat(dest,s2);
strcat(dest,s3);
strcat(dest,s4);
return;
}
#ifdef __STDC__
void log_short_message(MLCompose *compose, char *mailboxname,
BODY *body, ENVELOPE *envelope)
#else
void log_short_message(compose, mailboxname, body, envelope)
MLCompose *compose;
char *mailboxname;
BODY *body;
ENVELOPE *envelope;
#endif
{
extern STRINGDRIVER mail_string;
STRING bs;
char *from;
char *newsgroups;
char *to;
char *subject;
char *cc;
char *bcc;
char *text;
char *date;
char *temp_text;
char *bigbuf;
char *ret;
Server_Config *server_config;
char *host;
from = cpystr(compose->options->replyto);
newsgroups = GetTextField(compose->window->newsgroups_text);
to = GetTextField(compose->window->to_text);
subject = GetTextField(compose->window->subject_text);
cc = GetTextField(compose->window->cc_text);
bcc = GetTextField(compose->window->bcc_text);
temp_text = XmTextGetString(compose->window->compose_text);
date = (char *) fs_get(MESSAGE_ID_LENGTH);
rfc822_date(date);
if(compose->options->word_wrap == TRUE)
text = wrap_text(temp_text, COMPOSEWIDTH - 1);
else
text = cpystr(temp_text);
fs_give((void **) &temp_text);
bigbuf = (char *) fs_get( ((from) ? strlen(from) : 0)
+ ((newsgroups) ? strlen(newsgroups) : 0)
+ ((to) ? strlen(to) : 0)
+ ((subject) ? strlen(subject) : 0)
+ ((cc) ? strlen(cc) : 0)
+ ((bcc) ? strlen(bcc) : 0)
+ ((date) ? strlen(date) : 0)
+ ((envelope->in_reply_to) ?
strlen(envelope->in_reply_to) : 0)
+ ((envelope->message_id) ?
strlen(envelope->message_id) : 0)
+ ((text) ? strlen(text) : 0)
+ 512);
*bigbuf = NUL_TERM;
if(from) {
if(*from)
cat4(bigbuf,HEADER_FROM,SPACESTR,from,LFSTR);
fs_give((void **) &from);
}
if(newsgroups) {
if(*newsgroups)
cat4(bigbuf,HEADER_NEWSGROUPS,SPACESTR,newsgroups,LFSTR);
fs_give((void **) &newsgroups);
}
if(to) {
if(*to)
cat4(bigbuf,HEADER_TO,SPACESTR,to,LFSTR);
fs_give((void **) &to);
}
if(subject) {
if(*subject)
cat4(bigbuf,HEADER_SUBJECT,SPACESTR,subject,LFSTR);
fs_give((void **) &subject);
}
if(cc) {
if(*cc)
cat4(bigbuf,HEADER_CC,SPACESTR,cc,LFSTR);
fs_give((void **) &cc);
}
if(bcc) {
if(*bcc)
cat4(bigbuf,HEADER_BCC,SPACESTR,bcc,LFSTR);
fs_give((void **) &bcc);
}
if(date) {
if(*date)
cat4(bigbuf,HEADER_DATE,SPACESTR,date,LFSTR);
fs_give((void **) &date);
}
if(envelope->in_reply_to) {
if(*envelope->in_reply_to)
cat4(bigbuf,HEADER_IN_REPLY_TO,SPACESTR,envelope->in_reply_to,LFSTR);
}
if(envelope->message_id) {
if(*envelope->message_id)
cat4(bigbuf,HEADER_MESSAGE_ID,SPACESTR,envelope->message_id,LFSTR);
}
strcat(bigbuf,LFSTR);
if(text) {
if(*text)
strcat(bigbuf,text);
strcat(bigbuf,LFSTR);
fs_give((void **) &text);
}
ret = lftocrlf(bigbuf);
fs_give((void **) &bigbuf);
if(ret) {
INIT(&bs,mail_string,ret,strlen(ret));
if((mail_append_full(NIL, mailboxname, SEEN_FLAG, NULL, &bs)) == NIL)
mm_log(MLGetLocalized(XtNmsgAppendFailed,MsgAppendFailed),WARN);
fs_give((void **) &ret);
}
if(mailboxname)
fs_give((void **) &mailboxname);
return;
}
#ifdef __STDC__
char *param_to_str(PARAMETER *parameter)
#else
char *param_to_str(parameter)
PARAMETER *parameter;
#endif
{
char buffer[FILEBUFFLEN];
PARAMETER *p;
if(parameter == NULL)
return(cpystr(EMPTYSTR));
strcpy(buffer,EMPTYSTR);
for(p = parameter; p; p = p->next) {
if((p->attribute == NULL) || (p->value == NULL))
continue;
if(*buffer != NUL_TERM)
strcat(buffer,SPACESTR);
strcat(buffer,p->attribute);
strcat(buffer,EQUALSTR);
strcat(buffer,p->value);
}
return(cpystr(buffer));
}
#ifdef __STDC__
PARAMETER *str_to_param(char *str)
#else
PARAMETER *str_to_param(str)
char *str;
#endif
{
char *p;
char *ptr;
char *last = str;
PARAMETER *parameter = NULL;
PARAMETER *first = NULL;
PARAMETER *lastp = NULL;
Boolean reached_end = FALSE;
Boolean bad_input = FALSE;
if((str == NULL) || (*str == NUL_TERM))
return(NULL);
for(ptr = str; *ptr != NUL_TERM ; ptr ++) {
if(reached_end == TRUE)
break;
if(*ptr != EQUALCHAR)
continue;
*ptr = NUL_TERM;
ptr ++;
parameter = mail_newbody_parameter();
parameter->attribute = cpystr(last);
p = ptr;
if(*p == DQUOTECHAR) {
p ++;
while((*p != NUL_TERM) && (*p != DQUOTECHAR))
p ++;
while((*p != NUL_TERM) && (*p != SPACECHAR))
p ++;
}
else {
while ((*p != NUL_TERM) && (*p != SPACECHAR))
p ++;
}
if(*p == NUL_TERM)
reached_end = TRUE;
*p = NUL_TERM;
parameter->value = cpystr(ptr);
if(first == NULL) {
first = parameter;
lastp = parameter;
}
else {
lastp->next = parameter;
lastp = parameter;
}
if(reached_end == TRUE)
break;
else {
last = p + 1;
ptr = p + 1;
while((*last != NUL_TERM) && (isspace(*last)))
last ++;
if(*last == NUL_TERM)
break;
}
}
/* Now check for bad input.... */
for(parameter = first; parameter != NULL; parameter = parameter->next) {
if((parameter->attribute == NULL) || (parameter->value == NULL))
bad_input = TRUE;
}
if(bad_input) {
mm_log(MLGetLocalized(XtNmsgInvalidParams,MsgInvalidParams),ERROR);
mail_free_body_parameter(&first);
}
return(first);
}
#ifdef __STDC__
void compose_delete_part(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_delete_part(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
Part_List *part_list;
BODY *body = NULL;
if((compose->window->attach_list_selection == 0)
|| (compose->part_list == NULL))
return;
/* point to the Part_List of the selected part.*/
for(part_list = compose->part_list;
part_list->partnumber != compose->window->attach_list_selection;
part_list = part_list->next);
/* First see if it's a multipart which still has contents */
body = &(part_list->part->body);
if(body->type == TYPEMULTIPART
&& (body->contents.part != NULL)) {
mm_log(MLGetLocalized(XtNmsgNonEmptyMulti,MsgNonEmptyMulti),WARN);
return;
}
/* first part in our attachment list */
if(part_list->part == compose->attachments) {
compose->attachments = part_list->part->next;
part_list->part->next = NULL;
mail_free_body_part(&part_list->part);
make_attachment_list(compose, FALSE);
return;
}
/* Some other part. See if our previous neighbor points to us. */
if((part_list->prev) && (part_list->prev->part->next == part_list->part)) {
part_list->prev->part->next = part_list->part->next;
part_list->part->next = NULL;
}
else {
/* Hmmm. Heirarchical. Find the parent. */
body = (part_list->prev) ? &(part_list->prev->part->body) : NULL;
if((body) && (body->type == TYPEMULTIPART))
body->contents.part = part_list->part->next;
part_list->part->next = NULL;
}
mail_free_body_part(&part_list->part);
make_attachment_list(compose, FALSE);
return;
}
/*
* Callback when an item in the attachment list is selected.
*/
#ifdef __STDC__
void select_attach(Widget w, MLCompose *compose, XmListCallbackStruct *xp)
#else
void select_attach(w,compose,xp)
Widget w;
MLCompose *compose;
XmListCallbackStruct *xp;
#endif
{
if(xp->item_position == compose->window->attach_list_selection) {
compose->window->attach_list_selection = 0;
compose->window->buttonstate |= BTN_NOATTACHSELECT;
}
else {
compose->window->attach_list_selection = xp->item_position;
compose->window->buttonstate &= ~(BTN_NOATTACHSELECT);
}
compose_check_buttons(compose);
return;
}
#ifdef __STDC__
void double_click_attach(Widget w, MLCompose *compose,
XmListCallbackStruct *xp)
#else
void double_click_attach(w,compose,xp)
Widget w;
MLCompose *compose;
XmListCallbackStruct *xp;
#endif
{
Part_List *part_list;
BODY *body;
if(! xp->item_position)
return;
for(part_list = compose->part_list;
part_list && part_list->partnumber != xp->item_position;
part_list = part_list->next);
if(! part_list)
return;
/* Make sure the window shows it as selected */
XmListDeselectAllItems(compose->window->attach_list);
compose->window->attach_list_selection = xp->item_position;
compose->window->buttonstate &= ~(BTN_NOATTACHSELECT);
XmListSelectPos(compose->window->attach_list,xp->item_position,FALSE);
compose_check_buttons(compose);
body = &(part_list->part->body);
/* invoke message handler */
show_mime(compose->window->shell, body, FALSE);
return;
}
#ifdef __STDC__
void make_attachment_list(MLCompose *compose, Boolean init)
#else
void make_attachment_list(compose, init)
MLCompose *compose;
Boolean init;
#endif
{
if(compose != NULL) {
/* Erase current list contents and start over */
XmListDeselectAllItems(compose->window->attach_list);
XmListDeleteAllItems(compose->window->attach_list);
compose->window->attach_list_selection = 0;
compose->window->buttonstate |= BTN_NOATTACHSELECT;
/* No contents. Check buttons and get outa' here */
if(compose->attachments == NULL) {
compose->window->buttonstate |= BTN_NOATTACH;
compose_check_buttons(compose);
return;
}
if(compose->part_list) {
destroy_part_list(compose->part_list);
}
compose->part_list = NULL;
/*
* Recursively add strings to the attachment list widget
* and add to our part_list structure. We use this to look up
* specific parts from the list management functions without having
* to go through all this recursive hullabaloo all over again.
*/
add_attach_strings(compose->window->attach_list, compose,
compose->attachments,0);
compose->window->buttonstate &= ~(BTN_NOATTACH);
compose_check_buttons(compose);
}
return;
}
#ifdef __STDC__
void destroy_part_list(Part_List *part_list)
#else
void destroy_part_list(part_list)
Part_List *part_list;
#endif
{
if(part_list == NULL)
return;
destroy_part_list(part_list->next);
if(part_list->partstr)
fs_give((void **) &part_list->partstr);
fs_give((void **) &part_list);
part_list = NULL;
return;
}
#ifdef __STDC__
void add_attach_strings(Widget wid, MLCompose *compose, PART *part, int level)
#else
void add_attach_strings(wid,compose,part,level)
Widget wid;
MLCompose *compose;
PART *part;
int level;
#endif
{
int len;
XmString xstr;
PART *curr;
char buffer[FILEBUFFLEN];
Part_List *part_list;
Part_List *curr_part_list;
struct mail_body_parameter *params;
if(part == NULL)
return;
for(curr = part; curr; curr = curr->next) {
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 );
for(len = strlen(buffer); len < (COMPOSEWIDTH/2); len ++)
strcat(buffer,SPACESTR);
strncat(buffer,
(curr->body.description) ? curr->body.description : EMPTYSTR,
COMPOSEWIDTH);
buffer[COMPOSEWIDTH - 2] = NUL_TERM;
for(params = curr->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(wid,xstr,0);
XmStringFree(xstr);
part_list = (Part_List *) fs_get(sizeof(Part_List));
part_list->next = NULL;
part_list->part = curr;
part_list->partstr = NULL;
if(compose->part_list == NULL) {
compose->part_list = part_list;
part_list->partnumber = 1;
part_list->prev = NULL;
}
else {
for(curr_part_list = compose->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)
add_attach_strings(wid,compose,curr->body.contents.part,level+1);
}
return;
}
#ifdef __STDC__
void compose_insert_file(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_insert_file(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
char *filename;
Binary_Buffer *binary_buffer;
filename = file_select(compose->window->shell, NULL,
NULL, NULL, FALSE, NULL);
if(filename == NULL)
return;
push_cursor(WATCH_CURSOR);
binary_buffer = load_binary_file(filename);
if(binary_buffer) {
text_blast(compose->window->compose_text,(char *)binary_buffer->data);
free_binary_buffer(binary_buffer);
}
fs_give((void **) &filename);
pop_cursor();
return;
}
/*
* Append signature file into current text window and call
* send_message(). We throw in an extra linefeed between the two
* just in case the last line of the message doesn't have one.
*/
#ifdef __STDC__
void compose_send_autograph(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_send_autograph(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
FILE *fp;
char *filename;
char buffer[FILEBUFFLEN];
filename = cpystr(compose->options->sigfile);
if((*filename != NUL_TERM) && (fp = fopen(filename,"r")) != NULL) {
AppendText(compose->window->compose_text,LFSTR);
while((fgets(buffer,sizeof(buffer),fp)) != NULL)
AppendText(compose->window->compose_text,buffer);
fclose(fp);
}
fs_give((void **) &filename);
send_message(w,compose,xp);
return;
}
#ifdef __STDC__
void compose_attach_file(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_attach_file(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
char *filename = NULL;
Binary_Buffer *binary_buffer;
PART *part;
BODY *body;
Boolean auto_attach;
Boolean keep_going;
filename = file_select(compose->window->shell, NULL,
NULL, NULL, FALSE, NULL);
if(filename == NULL)
return;
binary_buffer = load_binary_file(filename);
if(binary_buffer) {
part = mail_newbody_part();
body = &part->body;
set_default_attach_type(body,filename);
if((auto_attach = get_type_from_suffix(body,filename)) == FALSE)
keep_going =
create_mime_attach_window(compose->window->shell,body,FALSE);
if(auto_attach || keep_going)
link_attachment(compose,part,body,binary_buffer);
else
mail_free_body_part(&part);
free_binary_buffer(binary_buffer);
}
fs_give((void **) &filename);
return;
}
#ifdef __STDC__
void compose_attach_multi(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_attach_multi(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
PART *part;
BODY *body;
part = mail_newbody_part();
body = &part->body;
body->type = TYPEMULTIPART;
body->subtype = cpystr("mixed");
if(create_mime_attach_window(compose->window->shell,body,TRUE))
link_attachment(compose,part,body,NULL);
else
mail_free_body_part(&part);
return;
}
#ifdef __STDC__
void compose_createattach(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_createattach(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
PART *part;
BODY *body;
Binary_Buffer *binary_buffer;
part = mail_newbody_part();
body = &part->body;
binary_buffer = create_mime_compose_window(compose->window->shell,body);
if(binary_buffer) {
link_attachment(compose,part,body,binary_buffer);
free_binary_buffer(binary_buffer);
}
else
mail_free_body_part(&part);
return;
}
/*
* We've been called by an address text field widget. At least that's the
* assumption, so don't try and change it. All we have is the widget.
* It contains something presumably that we will have to complete from
* the address book. But it might contain other addresses, and the one to be
* completed could be anywhere. We presume that it is under the cursor.
* We then split up the string into three parts. The part before the current
* word (comma delimited), and anything afterward (delimited by comma or a
* space). Any of these parts might be empty. After we extract our pattern,
* we look it up, and replace it with the address book address. More on
* that later. We then combine it with any or all of the other parts, and
* make sure we have comma delimiters (plus a gratuitous space) between
* all the fields. On failure we leave it alone, and advance to the next
* tab group, since the most likely key binding for this will be a tab key.
* Therefore, the tab completes, if possible, and in all other cases moves to
* the next tab group.
*/
#ifdef __STDC__
void complete_address(Widget w, XtPointer xp)
#else
void complete_address(w,xp)
Widget w;
XtPointer xp;
#endif
{
char *text = GetTextField(w);
XmTextPosition pos = XmTextGetInsertionPosition(w);
char *begin = NULL;
char *end = NULL;
char *pattern = NULL;
char *lookup = NULL;
XmTextPosition newpos = 0;
Boolean found = FALSE;
if(*text == NUL_TERM) {
fs_give((void **) &text);
XmProcessTraversal(w,XmTRAVERSE_NEXT_TAB_GROUP);
return;
}
/* point to current position. */
pattern = text + ((pos > 0) ? (pos - 1) : 0 );
/* find the beginning of this address */
while((pattern > text) && (*pattern != ','))
pattern --;
/* We're at the beginning */
if(pattern == text) {
begin = NULL;
}
/*
* Not the beginning, so set the begin pointer to it,
* tie it off, and point pattern just beyond it.
*/
else {
*pattern = NUL_TERM;
pattern = first_nonwhite(pattern + 1);
begin = text;
}
/*
* find any subsequent addresses. If we find one, tie off
* our pattern string, and point end at the next address.
*/
end = strpbrk(pattern,", ");
if(end) {
*end = NUL_TERM;
end = first_nonwhite(end + 1);
}
/*
* Try and match it. If we do, rebuild the visible text. Set the
* cursor at the end of the address we just completed.
*/
if((lookup = lookup_group(pattern)) != NULL) {
XmTextSetString(w,(begin) ? begin : EMPTYSTR);
AppendText(w,(begin) ? ", " : EMPTYSTR );
AppendText(w,lookup);
newpos = XmTextGetInsertionPosition(w);
if(end) {
AppendText(w,", ");
AppendText(w,end);
}
XmTextSetInsertionPosition(w,newpos);
fs_give((void **) &lookup);
found = TRUE;
}
else {
if((lookup = lookup_address(pattern)) != NULL) {
XmTextSetString(w,(begin) ? begin : EMPTYSTR);
AppendText(w,(begin) ? ", " : EMPTYSTR );
AppendText(w,lookup);
newpos = XmTextGetInsertionPosition(w);
if(end) {
AppendText(w,", ");
AppendText(w,end);
}
XmTextSetInsertionPosition(w,newpos);
fs_give((void **) &lookup);
found = TRUE;
}
}
if(found == FALSE)
XmProcessTraversal(w,XmTRAVERSE_NEXT_TAB_GROUP);
fs_give((void **) &text);
return;
}
#ifdef __STDC__
char *lookup_address(char *str)
#else
char *lookup_address(str)
char *str;
#endif
{
int cnt = 0;
Address_Book_Info *address_book_info;
Address_Book_Info *saved = NULL;
for(address_book_info = session->addresses;
address_book_info ; address_book_info = address_book_info->prev) {
if((strcasecmp((char *) address_book_info->name,str)) == STRMATCH) {
/* Exact match. Use it. */
cnt = 1;
saved = address_book_info;
break;
}
else {
if((strncasecmp((char *) address_book_info->name,
str,strlen(str))) == STRMATCH) {
cnt ++;
saved = address_book_info;
}
}
}
if(cnt == 1)
return(cpystr((char *) saved->address));
if(cnt > 1) /* Not completed */
return(address_popup(str));
return(NULL);
}
#ifdef __STDC__
char *lookup_group(char *str)
#else
char *lookup_group(str)
char *str;
#endif
{
char buffer[FILEBUFFLEN];
char *ptr;
char *end;
char *result = NULL;
char *now = NULL;
Address_Book_Info *address_book_info;
for(address_book_info = session->addresses;
address_book_info ; address_book_info = address_book_info->prev) {
if((address_book_info->groups == NULL)
|| (*address_book_info->groups == NUL_TERM))
continue;
strcpy(buffer,(char *) address_book_info->groups);
ptr = end = buffer;
while((*ptr != NUL_TERM) && (end)) {
if((end = strpbrk(ptr,", ")) != NULL) {
*end = NUL_TERM;
end ++;
}
if((strcasecmp(ptr,str)) == STRMATCH) {
if(result) {
now = fs_get(strlen(result)
+ ((address_book_info->address)
? strlen((char *) address_book_info->address)
: 1) + 4);
strcpy(now,result);
strcat(now,", ");
strcat(now,(address_book_info->address)
? (char *) address_book_info->address : EMPTYSTR);
fs_give((void **) &result);
result = now;
}
else
result = cpystr((address_book_info->address)
? (char *) address_book_info->address
: EMPTYSTR);
}
if(end) {
ptr = end;
while((*ptr != NUL_TERM)
&& ((*ptr == SPACECHAR) || (*ptr == ',')))
ptr ++;
}
}
}
return(result);
}
#ifdef __STDC__
char *address_popup(char *str)
#else
char *address_popup(str)
char *str;
#endif
{
XBell(display, 500);
return(NULL);
}
#ifdef __STDC__
void generate_subject(Widget w, MLCompose *compose, XtPointer xp)
#else
void generate_subject(w, compose, xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
Binary_Buffer *binary_buffer;
unsigned char *ptr;
silent_pipe = TRUE;
if((access(PATH_FORTUNE, X_OK)) == SYSCALL_SUCCESS) {
binary_buffer = read_from_pipe(FORTUNE_CMD);
if(binary_buffer) {
if(binary_buffer->data) {
for(ptr = binary_buffer->data; *ptr != NUL_TERM; ptr ++)
if((*ptr == LFCHAR) || (*ptr == TABCHAR))
*ptr = SPACECHAR;
XmTextSetString(compose->window->subject_text, binary_buffer->data);
}
free_binary_buffer(binary_buffer);
}
}
silent_pipe = FALSE;
return;
}
#ifdef __STDC__
void compose_spell(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_spell(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
FILE *fp = NULL;
char *text = NULL;
String_List *string_list = NULL;
String_List *prev = NULL;
String_List *base = NULL;
char *tmp_file = NULL;
char *otext = NULL;
Binary_Buffer *bb = NULL;
char filename[MAXPATHLEN];
char buffer[FILEBUFFLEN];
char command[FILEBUFFLEN];
int count = 0;
Boolean has_stop = FALSE;
if(access(SPELLSTOPFILE,R_OK) == SYSCALL_SUCCESS)
has_stop = TRUE;
if(preferences.useIspell == FALSE) {
if((compose->spellwindow != NULL)
&& (compose->spellwindow->is_realized == TRUE)) {
de_iconify(compose->spellwindow->shell);
return;
}
}
otext = XmTextGetString(compose->window->compose_text);
if(otext == NULL)
return;
if(*otext == NUL_TERM) {
fs_give((void **) &otext);
return;
}
/* Just in case they didn't end the message properly.... */
text = (char *) fs_get(strlen(otext) + 8);
strcpy(text,otext);
strcat(text,LFSTR);
fs_give((void **) &otext);
tmp_file = (char *) tmpnam(filename);
if(preferences.useIspell == TRUE) {
/* run ispell in an xterm */
if((fp = fopen(tmp_file,"w")) != NULL) {
(void) chmod(tmp_file,S_IRWXU);
fwrite(text,strlen(text),1,fp);
fclose(fp);
sprintf(command,ISPELL_COMMAND,tmp_file);
XtVaSetValues(compose->window->compose_text,XmNeditable, FALSE, NULL);
compose->in_ispell = TRUE;
if((write_to_pipe(command,NULL, NULL, 0)) == SYSCALL_SUCCESS) {
bb = load_binary_file(tmp_file);
if(bb != NULL) {
if(bb->data != NULL)
XmTextSetString(compose->window->compose_text,(char *)bb->data);
free_binary_buffer(bb);
}
}
XtVaSetValues(compose->window->compose_text,XmNeditable, TRUE, NULL);
compose->in_ispell = FALSE;
}
else {
fs_give((void **) &text);
fs_give((void **) &tmp_file);
return;
}
unlink(tmp_file);
return;
}
/* otherwise we use /bin/spell */
sprintf(command, SPELL_COMMAND,
(has_stop == TRUE) ? '+' : SPACECHAR,
(has_stop == TRUE) ? SPELLSTOPFILE : EMPTYSTR,
tmp_file);
push_cursor(WATCH_CURSOR);
sprintf(buffer,MLGetLocalized(XtNmsgExecuting,MsgExecuting),command);
mm_log(buffer, NIL);
if((fp = popen(command,"w")) != NULL) {
(void) chmod(tmp_file,S_IRWXU);
fwrite(text,strlen(text),1,fp);
pclose(fp);
}
else {
fs_give((void **) &text);
fs_give((void **) &tmp_file);
pop_cursor();
return;
}
if((fp = fopen(tmp_file,"r")) != NULL) {
while((fgets(buffer,sizeof(buffer),fp)) != NULL) {
buffer[strlen(buffer) - 1] = NUL_TERM;
if(*buffer == NUL_TERM)
continue;
count ++;
string_list = new_string_list();
string_list->string = cpystr(buffer);
if(prev == NULL)
base = string_list;
else
prev->next = string_list;
prev = string_list;
}
fclose(fp);
}
else
mm_log(MLGetLocalized(XtNmsgSpellNoRead,MsgSpellNoRead),NIL);
fs_give((void **) &text);
unlink(tmp_file);
pop_cursor();
sprintf(buffer,MLGetLocalized(XtNmsgNCorrections,MsgNCorrections),count);
mm_log(buffer, NIL);
if(base)
make_text_spell_window(compose->window->compose_text, base);
return;
}
#ifdef __STDC__
void link_attachment(MLCompose *compose, PART *part, BODY *body,
Binary_Buffer *binary_buffer)
#else
void link_attachment(compose,part,body,binary_buffer)
MLCompose *compose;
PART *part;
BODY *body;
Binary_Buffer *binary_buffer;
#endif
{
Part_List *part_list;
PART *current;
BODY *subbody;
Boolean attached = FALSE;
add_attachment_contents_to_body(body,binary_buffer);
/*
* See if there is a selected attachment. Then check to see if
* it is a multipart. If so, then we add to that multipart.
*/
if(compose->window->attach_list_selection && compose->part_list) {
for(part_list = compose->part_list;
part_list->partnumber != compose->window->attach_list_selection;
part_list = part_list->next);
subbody = &(part_list->part->body);
if(subbody && subbody->type == TYPEMULTIPART) {
current = subbody->contents.part;
if(! current)
subbody->contents.part = part;
else {
while(current->next)
current = current->next;
current->next = part;
}
attached = TRUE;
}
}
/*
* Wasn't a subpart, or we couldn't attach it as one. Attach to the
* root part.
*/
if(! attached) {
if(compose->attachments == NULL) {
compose->attachments = part;
}
else {
current = compose->attachments;
while(current->next)
current = current->next;
current->next = part;
}
}
make_attachment_list(compose, TRUE);
return;
}
#ifdef __STDC__
void compose_parameters(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_parameters(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
Part_List *part_list;
PARAMETER **old = NULL;
PARAMETER *new = NULL;
char *oldstr = NULL;
char *newstr = NULL;
/* See if there is a selected attachment. */
if(compose->window->attach_list_selection && compose->part_list) {
for(part_list = compose->part_list;
part_list->partnumber != compose->window->attach_list_selection;
part_list = part_list->next)
;
old = &part_list->part->body.parameter;
}
if(old == NULL)
old = &compose->parameters;
oldstr = param_to_str(*old);
newstr = input_string(compose->window->shell,
MLGetLocalized(XtNmsgPromptParams,MsgPromptParams),
oldstr, PARAMSHELPFILE);
if(newstr == NULL)
return;
if(*newstr == NUL_TERM) {
fs_give((void **) &newstr);
fs_give((void **) &oldstr);
mail_free_body_parameter(old);
}
else {
new = str_to_param(newstr);
if(new != NULL) {
mail_free_body_parameter(old);
*old = new;
}
}
fs_give((void **) &oldstr);
fs_give((void **) &newstr);
return;
}
/*
* This is just to calculate how much space to allocate for storing
* a text field. (Used in the print function). We over-allocate by
* a little bit to make up for psuedo-tabs and line breaks.
*/
#ifdef __STDC__
unsigned long compose_field_approx_size(char *prefix, char *str,
unsigned long len)
#else
unsigned long compose_field_approx_size(prefix, str, len)
char *prefix;
char *str;
unsigned long len;
#endif
{
unsigned long retval = 0L;
if(!str)
return(0L);
if(len == 0L)
return((unsigned long) strlen(str));
if(prefix)
retval = strlen(prefix);
retval += (unsigned long) strlen(str) +
((unsigned long) strlen(str) / len ) + (unsigned long) 16L;
return(retval);
}
/*
* This is an undocumented interface.
* If you need it, you'll figure
* it out.
*/
#ifdef __STDC__
void compose_smart_reply(ENVELOPE *env, char *newsgroups)
#else
void compose_smart_reply(env, newsgroups)
ENVELOPE *env;
char *newsgroups;
#endif
{
FILE *fp;
char *tmp_file;
char mybuf[FILEBUFFLEN];
char filename[MAXPATHLEN];
char command[FILEBUFFLEN];
ADDRESS *curr;
if(!preferences.smart_reply || *preferences.smart_reply == NUL_TERM)
return;
if(!strstr(preferences.smart_reply,"%s"))
return;
tmp_file = (char *) tmpnam(filename);
sprintf(command,preferences.smart_reply,tmp_file);
if((fp = fopen(tmp_file,"w")) != NULL) {
(void) chmod(tmp_file,S_IRWXU);
fprintf(fp,"%s ",HEADER_TO);
for(curr = env->to; curr; curr = curr->next) {
local_make_addr_str(curr,mybuf);
fprintf(fp,"%s ",mybuf);
}
fprintf(fp,LFSTR);
fprintf(fp,"%s ",HEADER_CC);
for(curr = env->cc; curr; curr = curr->next) {
local_make_addr_str(curr,mybuf);
fprintf(fp,"%s ",mybuf);
}
fprintf(fp,LFSTR);
fprintf(fp,"%s ",HEADER_BCC);
for(curr = env->bcc; curr; curr = curr->next) {
local_make_addr_str(curr,mybuf);
fprintf(fp,"%s ",mybuf);
}
fprintf(fp,LFSTR);
fprintf(fp,"%s %s\n", HEADER_NEWSGROUPS,
(newsgroups) ? newsgroups : EMPTYSTR);
fprintf(fp,"%s %s\n", HEADER_SUBJECT,
(env->subject) ? env->subject : EMPTYSTR);
fclose(fp);
}
/*
* External process generates one line (or nothing).
* If something, use it as the reply-to.
*/
*mybuf = NUL_TERM;
if((fp = popen(command,"r")) != NULL) {
fgets(mybuf,sizeof(mybuf),fp);
mybuf[strlen(mybuf) - 1] = NUL_TERM;
if(*mybuf != NUL_TERM) {
mail_free_address(&env->reply_to);
env->reply_to = text_to_address(mybuf,EMPTYSTR);
}
pclose(fp);
}
unlink(tmp_file);
return;
}
#ifdef __STDC__
void compose_print(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_print(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
char *s;
char *wrapped_text;
unsigned long size = 0L;
char *to = NULL;
char *newsgroups = NULL;
char *subject = NULL;
char *cc = NULL;
char *bcc = NULL;
char *message_text = NULL;
if(!preferences.print_command || *preferences.print_command == NUL_TERM) {
mm_log(MLGetLocalized(XtNmsgNoPrintCommand,MsgNoPrintCommand),WARN);
return;
}
push_cursor(WATCH_CURSOR);
to = GetTextField(compose->window->to_text);
newsgroups = GetTextField(compose->window->newsgroups_text);
subject = GetTextField(compose->window->subject_text);
cc = GetTextField(compose->window->cc_text);
bcc = GetTextField(compose->window->bcc_text);
message_text = GetTextField(compose->window->compose_text);
s = fs_get( strlen(to) + strlen(newsgroups) + strlen(subject)
+ strlen(cc) + strlen(bcc) + strlen(message_text)
+ 1024);
*s = NUL_TERM;
#define HEADER_MARGIN (COMPOSEWIDTH - 20)
if(*to != NUL_TERM) {
strcat(s,MLGetLocalized(XtNheaderTo,HeaderTo));
strcat(s,TABSTR);
wrapped_text = wrap_text(to, HEADER_MARGIN);
strcat(s, wrapped_text);
strcat(s, LFSTR);
}
if(*newsgroups != NUL_TERM) {
strcat(s,MLGetLocalized(XtNheaderNewsgroups,HeaderNewsgroups));
strcat(s,TABSTR);
wrapped_text = wrap_text(newsgroups, HEADER_MARGIN);
strcat(s, wrapped_text);
strcat(s, LFSTR);
}
if(*subject != NUL_TERM) {
strcat(s,MLGetLocalized(XtNheaderSubject,HeaderSubject));
strcat(s,TABSTR);
wrapped_text = wrap_text(subject, HEADER_MARGIN);
strcat(s, wrapped_text);
strcat(s, LFSTR);
}
if(*cc != NUL_TERM) {
strcat(s,MLGetLocalized(XtNheaderCc,HeaderCc));
strcat(s,TABSTR);
wrapped_text = wrap_text(cc, HEADER_MARGIN);
strcat(s, wrapped_text);
strcat(s, LFSTR);
}
if(*bcc != NUL_TERM) {
strcat(s,MLGetLocalized(XtNheaderBcc,HeaderBcc));
strcat(s,TABSTR);
wrapped_text = wrap_text(bcc, HEADER_MARGIN);
strcat(s, wrapped_text);
strcat(s, LFSTR);
}
strcat(s, LFSTR);
if(*message_text != NUL_TERM) {
wrapped_text = wrap_text(message_text, COMPOSEWIDTH - 1);
strcat(s, wrapped_text);
strcat(s, LFSTR);
}
if((write_to_pipe(preferences.print_command, NULL,s,strlen(s)))
!= SYSCALL_SUCCESS)
mm_log(MLGetLocalized(XtNmsgPrintFail,MsgPrintFail), WARN);
else
mm_log(MLGetLocalized(XtNmsgPrintSuccess,MsgPrintSuccess), NIL);
fs_give((void **) &s);
fs_give((void **) &to);
fs_give((void **) &newsgroups);
fs_give((void **) &subject);
fs_give((void **) &cc);
fs_give((void **) &bcc);
fs_give((void **) &message_text);
pop_cursor();
return;
}
#ifdef __STDC__
void compose_mailbox_close(MAILSTREAM *mailstream)
#else
void compose_mailbox_close(mailstream)
MAILSTREAM *mailstream;
#endif
{
MLCompose *compose;
if(session->compose == NULL)
return;
/*
* Run through the list of compose sessions searching for our mailstream.
* If it's ours, zero the message structure so it won't be referenced again.
* (The message can still be composed -- we just won't set any flags at
* the end).
*/
for(compose = session->compose ; compose; compose = compose->next) {
if((compose->message != NULL)
&& (compose->message->mailstream == mailstream)) {
compose->message = NULL;
}
}
}
#ifdef __STDC__
void compose_options(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_options(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
compose_preferences(compose);
return;
}
Menu copts_menu[] = {
{ NULL, "accept", NUL_TERM,
cwin_accept, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "save", NUL_TERM,
cwin_save, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "dismiss", NUL_TERM,
cwin_dismiss, NULL, 0, NULL, NULL, BTN_ON },
{ NULL, "HELP", NUL_TERM,
cwin_help, NULL, 0, NULL, NULL, BTN_ON },
};
#ifdef __STDC__
void compose_preferences(MLCompose *compose)
#else
void compose_preferences(compose)
MLCompose *compose;
#endif
{
Arg args[ARGLISTSIZE];
int n = 0;
MLComposeOptions *options;
MLComposeOptionsWindow *win;
if(compose->options->window != NULL) {
win = compose->options->window;
if(win->destroyed == FALSE) {
if(win->is_realized == TRUE)
de_iconify(win->shell);
else
XtPopup(win->shell, XtGrabNone);
return;
}
}
options = compose->options;
options->window = (MLComposeOptionsWindow *)
fs_get(sizeof(MLComposeOptionsWindow));
win = options->window;
win->buttonlist = NULL;
win->destroyed = FALSE;
win->is_realized = FALSE;
if(preferences.autoPlace == TRUE) {
XtSetArg(args[n], XtNx, -1000); n ++;
XtSetArg(args[n], XtNy, -1000); n ++;
}
XtSetArg (args[n], XmNdeleteResponse, XmDO_NOTHING); n++;
win->shell = XtCreatePopupShell("composeOptions",
topLevelShellWidgetClass,
compose->window->shell,
args, n);
AddDestroyCallback (win->shell);
n = 0;
setup_editres(win->shell);
if(ml_icon != (Pixmap) None)
XtVaSetValues(win->shell,
XmNiconPixmap,ml_icon,
NULL);
win->form = XmCreateForm(win->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 ++;
win->menubar = XmCreateMenuBar(win->form, "menubar", args, n); n = 0;
XtManageChild(win->menubar);
make_buttons(&win->buttonlist, NULL,
win->menubar, copts_menu,
XtNumber(copts_menu),
BTN_ON, (XtPointer) compose,
ROOTMENULEVEL);
win->mailhost =
create_text_field(win->form, win->menubar,
"mailhost",
options->mailhost,
0, NULL, NULL);
win->nntphost =
create_text_field(win->form, win->mailhost,
"nntphost",
options->nntphost,
0, NULL, NULL);
win->domain =
create_text_field(win->form, win->nntphost,
"domain",
options->domain,
0, NULL, NULL);
win->replyto =
create_text_field(win->form, win->domain,
"replyto",
options->replyto,
0, NULL, NULL);
win->sigfile =
create_text_field(win->form, win->replyto,
"sigfile",
options->sigfile,
0, NULL, NULL);
win->outlog =
create_text_field(win->form, win->sigfile,
"outlog",
options->outlog,
0, NULL, NULL);
win->defcc =
create_text_field(win->form, win->outlog,
"defcc",
options->defcc,
0, NULL, NULL);
win->defbcc =
create_text_field(win->form, win->defcc,
"defbcc",
options->defbcc,
0, NULL, NULL);
win->charset =
create_text_field(win->form, win->defbcc,
"charset",
options->charset,
0, NULL, NULL);
win->language =
create_text_field(win->form, win->charset,
"language",
options->language,
0, NULL, NULL);
XtSetArg(args[n], XmNadjustMargin, FALSE); n ++;
XtSetArg(args[n], XmNmarginWidth, 0); n ++;
XtSetArg(args[n], XmNborderWidth, 0); n ++;
XtSetArg(args[n], XmNnumColumns, 3); n ++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n ++;
XtSetArg(args[n], XmNtopWidget, win->language); n ++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n ++;
XtSetArg(args[n], XmNorientation, XmVERTICAL); n ++;
XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n ++;
win->rowcol = XtCreateWidget("rowcol",
xmRowColumnWidgetClass,
win->form, args, n );
n = 0;
XtManageChild(win->rowcol);
XtSetArg(args[n], XmNborderWidth, 0); n ++;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
win->verbose = XmCreateToggleButton(win->rowcol, "verbose_toggle",
args, n); n = 0;
XtManageChild(win->verbose);
XtAddCallback(win->verbose, XmNvalueChangedCallback,
(XtCallbackProc) cwin_verbose, compose);
XtSetArg(args[n], XmNborderWidth, 0); n ++;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
win->keep_open = XmCreateToggleButton(win->rowcol, "keep_open_toggle",
args, n); n = 0;
XtManageChild(win->keep_open);
XtAddCallback(win->keep_open, XmNvalueChangedCallback,
(XtCallbackProc) cwin_keep_open, compose);
XtSetArg(args[n], XmNborderWidth, 0); n ++;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
win->send_eight = XmCreateToggleButton(win->rowcol, "send_eight_toggle",
args, n); n = 0;
XtManageChild(win->send_eight);
XtAddCallback(win->send_eight, XmNvalueChangedCallback,
(XtCallbackProc) cwin_send_eight, compose);
XtSetArg(args[n], XmNborderWidth, 0); n ++;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
win->word_wrap = XmCreateToggleButton(win->rowcol, "word_wrap_toggle",
args, n); n = 0;
XtManageChild(win->word_wrap);
XtAddCallback(win->word_wrap, XmNvalueChangedCallback,
(XtCallbackProc) cwin_word_wrap, compose);
XtSetArg(args[n], XmNborderWidth, 0); n ++;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
win->message_log = XmCreateToggleButton(win->rowcol, "message_log_toggle",
args, n); n = 0;
XtManageChild(win->message_log);
XtAddCallback(win->message_log, XmNvalueChangedCallback,
(XtCallbackProc) cwin_message_log, compose);
XtSetArg(args[n], XmNborderWidth, 0); n ++;
XtSetArg(args[n], XmNtraversalOn, FALSE); n ++;
win->log_attachments = XmCreateToggleButton(win->rowcol,
"log_attachments_toggle",
args, n); n = 0;
XtManageChild(win->log_attachments);
XtAddCallback(win->log_attachments, XmNvalueChangedCallback,
(XtCallbackProc) cwin_log_attachments, compose);
XtAddCallback(win->shell, XmNpopdownCallback,
(XtCallbackProc) cwin_popdown, compose);
XtAddCallback(win->shell, XmNdestroyCallback,
(XtCallbackProc) cwin_destroy, compose);
set_initial_buttons(compose);
XtManageChild(win->form);
XtManageChild(win->shell);
XtPopup(win->shell, XtGrabNone);
position_popup_widget(win->shell, FALSE);
win->is_realized = TRUE;
return;
}
#ifdef __STDC__
void cwin_help(Widget w, MLCompose *compose, XtPointer xp)
#else
void cwin_help(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
help(compose->options->window->shell,COPTHELPFILE);
return;
}
#ifdef __STDC__
void set_initial_buttons(MLCompose *compose)
#else
void set_initial_buttons(compose)
MLCompose *compose;
#endif
{
MLComposeOptions *options = compose->options;
MLComposeOptionsWindow *win = compose->options->window;
XmToggleButtonSetState(win->verbose,options->verbose,FALSE);
XmToggleButtonSetState(win->keep_open,options->keep_open,FALSE);
XmToggleButtonSetState(win->send_eight,options->send_eight,FALSE);
XmToggleButtonSetState(win->word_wrap,options->word_wrap,FALSE);
XmToggleButtonSetState(win->message_log,options->message_log,FALSE);
XmToggleButtonSetState(win->log_attachments,options->log_attachments,FALSE);
return;
}
#ifdef __STDC__
void cwin_accept(Widget w, MLCompose *compose, XtPointer xp)
#else
void cwin_accept(w, compose, xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
get_compose_options(compose);
cwin_dismiss(w,compose,xp);
return;
}
#ifdef __STDC__
void cwin_save(Widget w, MLCompose *compose, XtPointer xp)
#else
void cwin_save(w, compose, xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
MLComposeOptions *options = compose->options;
get_compose_options(compose);
fs_give((void **) &preferences.smtp_server);
preferences.smtp_server = cpystr(options->mailhost);
fs_give((void **) &preferences.nntp_server);
preferences.nntp_server = cpystr(options->nntphost);
fs_give((void **) &preferences.default_domain);
preferences.default_domain = cpystr(options->domain);
fs_give((void **) &preferences.reply_address);
preferences.reply_address = cpystr(options->replyto);
fs_give((void **) &preferences.charset);
preferences.charset = cpystr(options->charset);
fs_give((void **) &preferences.signature_file);
preferences.signature_file = cpystr(options->sigfile);
fs_give((void **) &preferences.language);
preferences.language = cpystr(options->language);
fs_give((void **) &preferences.sendlog);
preferences.sendlog = cpystr(options->outlog);
fs_give((void **) &preferences.default_cc);
preferences.default_cc = cpystr(options->defcc);
fs_give((void **) &preferences.default_bcc);
preferences.default_bcc = cpystr(options->defbcc);
preferences.smtp_debug = options->verbose;
preferences.keep_open = options->keep_open;
preferences.send_eight = options->send_eight;
preferences.word_wrap = options->word_wrap;
preferences.logit = options->message_log;
preferences.log_full = options->log_attachments;
save_defaults();
cwin_dismiss(w,compose,xp);
}
#ifdef __STDC__
void cwin_dismiss(Widget w, MLCompose *compose, XtPointer xp)
#else
void cwin_dismiss(w, compose, xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
XtPopdown(compose->options->window->shell);
compose->options->window->is_realized = FALSE;
return;
}
#ifdef __STDC__
void cwin_popdown(Widget w, MLCompose *compose, XtPointer xp)
#else
void cwin_popdown(w, compose, xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
compose->options->window->is_realized = FALSE;
return;
}
#ifdef __STDC__
void cwin_destroy(Widget w, MLCompose *compose, XtPointer xp)
#else
void cwin_destroy(w, compose, xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
compose->options->window->is_realized = FALSE;
compose->options->window->destroyed = TRUE;
fs_give((void **) &compose->options->window->buttonlist);
return;
}
#ifdef __STDC__
void get_compose_options(MLCompose *compose)
#else
void get_compose_options(compose)
MLCompose *compose;
#endif
{
MLComposeOptions *options = compose->options;
fs_give((void **) &options->mailhost);
options->mailhost = GetTextField(options->window->mailhost);
fs_give((void **) &options->nntphost);
options->nntphost = GetTextField(options->window->nntphost);
fs_give((void **) &options->domain);
options->domain = GetTextField(options->window->domain);
fs_give((void **) &options->replyto);
options->replyto = GetTextField(options->window->replyto);
fs_give((void **) &options->sigfile);
options->sigfile = GetTextField(options->window->sigfile);
fs_give((void **) &options->charset);
options->charset = GetTextField(options->window->charset);
fs_give((void **) &options->language);
options->language = GetTextField(options->window->language);
fs_give((void **) &options->outlog);
options->outlog = GetTextField(options->window->outlog);
fs_give((void **) &options->defcc);
options->defcc = GetTextField(options->window->defcc);
fs_give((void **) &options->defbcc);
options->defbcc = GetTextField(options->window->defbcc);
if(options->word_wrap != options->word_wrap_tmp)
if(options->word_wrap_tmp == TRUE)
compose_wrap_on(NULL,compose,NULL);
else
compose_wrap_off(NULL,compose,NULL);
options->verbose = options->verbose_tmp;
options->keep_open = options->keep_open_tmp;
options->send_eight = options->send_eight_tmp;
options->word_wrap = options->word_wrap_tmp;
options->message_log = options->message_log_tmp;
options->log_attachments = options->log_attachments_tmp;
return;
}
#ifdef __STDC__
void cwin_verbose(Widget w,MLCompose *compose,
XmToggleButtonCallbackStruct *xp)
#else
void cwin_verbose(w,compose,xp)
Widget w;
MLCompose *compose;
XmToggleButtonCallbackStruct *xp;
#endif
{
MLComposeOptions *options = compose->options;
if(xp->set == TRUE)
options->verbose_tmp = TRUE;
else
options->verbose_tmp = FALSE;
return;
}
#ifdef __STDC__
void cwin_keep_open(Widget w,MLCompose *compose,
XmToggleButtonCallbackStruct *xp)
#else
void cwin_keep_open(w,compose,xp)
Widget w;
MLCompose *compose;
XmToggleButtonCallbackStruct *xp;
#endif
{
MLComposeOptions *options = compose->options;
if(xp->set == TRUE)
options->keep_open_tmp = TRUE;
else
options->keep_open_tmp = FALSE;
return;
}
#ifdef __STDC__
void cwin_send_eight(Widget w,MLCompose *compose,
XmToggleButtonCallbackStruct *xp)
#else
void cwin_send_eight(w,compose,xp)
Widget w;
MLCompose *compose;
XmToggleButtonCallbackStruct *xp;
#endif
{
MLComposeOptions *options = compose->options;
if(xp->set == TRUE)
options->send_eight_tmp = TRUE;
else
options->send_eight_tmp = FALSE;
return;
}
#ifdef __STDC__
void cwin_word_wrap(Widget w,MLCompose *compose,
XmToggleButtonCallbackStruct *xp)
#else
void cwin_word_wrap(w,compose,xp)
Widget w;
MLCompose *compose;
XmToggleButtonCallbackStruct *xp;
#endif
{
MLComposeOptions *options = compose->options;
if(xp->set == TRUE)
options->word_wrap_tmp = TRUE;
else
options->word_wrap_tmp = FALSE;
return;
}
#ifdef __STDC__
void cwin_message_log(Widget w,MLCompose *compose,
XmToggleButtonCallbackStruct *xp)
#else
void cwin_message_log(w,compose,xp)
Widget w;
MLCompose *compose;
XmToggleButtonCallbackStruct *xp;
#endif
{
MLComposeOptions *options = compose->options;
if(xp->set == TRUE)
options->message_log_tmp = TRUE;
else
options->message_log_tmp = FALSE;
return;
}
#ifdef __STDC__
void cwin_log_attachments(Widget w,MLCompose *compose,
XmToggleButtonCallbackStruct *xp)
#else
void cwin_log_attachments(w,compose,xp)
Widget w;
MLCompose *compose;
XmToggleButtonCallbackStruct *xp;
#endif
{
MLComposeOptions *options = compose->options;
if(xp->set == TRUE)
options->log_attachments_tmp = TRUE;
else
options->log_attachments_tmp = FALSE;
return;
}
#ifdef __STDC__
void compose_reply_insert(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_reply_insert(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
Read *read;
XmTextPosition left, right;
char *the_text = NULL;
char *tmp;
Boolean found = FALSE;
char buffer[FILEBUFFLEN];
push_cursor(WATCH_CURSOR);
for(read = session->read; read != NULL; read = read->next) {
if(read->is_realized == TRUE) {
XmTextGetSelectionPosition(read->read_text,&left,&right);
if(left != right) {
tmp = XmTextGetSelection(read->read_text);
the_text = copywrap(tmp,
(COMPOSEWIDTH - 2)
- strlen(preferences.reply_prefix));
fs_give((void **) &tmp);
found = TRUE;
}
}
}
if(! found) {
if(compose->reply_text) {
/* add the attribution and original message to the reply body */
memset(buffer, 0, FILEBUFFLEN);
make_attribution_line(compose->message,buffer);
if(*buffer) {
strcat(buffer,"\n");
text_blast(compose->window->compose_text,
copywrap(buffer,COMPOSEWIDTH));
}
the_text = copywrap(compose->reply_text, (COMPOSEWIDTH - 2)
- strlen(preferences.reply_prefix));
found ++;
}
}
if((found) && (*the_text != NUL_TERM)) {
tmp = add_prefix(the_text);
left = XmTextGetInsertionPosition(compose->window->compose_text);
right = left + strlen(tmp);
text_blast(compose->window->compose_text,tmp);
fs_give((void **) &tmp);
}
if(the_text)
fs_give((void **) &the_text);
pop_cursor();
return;
}
#ifdef __STDC__
void compose_cut(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_cut(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
XmTextCut(compose->window->compose_text,
XtLastTimestampProcessed(display));
return;
}
#ifdef __STDC__
void compose_copy(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_copy(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
XmTextCopy(compose->window->compose_text,
XtLastTimestampProcessed(display));
return;
}
#ifdef __STDC__
void compose_paste(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_paste(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
XmTextPaste(compose->window->compose_text);
return;
}
#ifdef __STDC__
void compose_save_draft(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_save_draft(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
FILE *fp;
char *filename;
Boolean append_it;
char *tmp;
filename = file_select(compose->window->shell, NULL, DRAFT_FILEPAT,
DRAFT_TEXT,
TRUE, &append_it);
if(filename == NULL)
return;
push_cursor(WATCH_CURSOR);
if((fp = fopen(filename,(append_it == TRUE) ? "a" : "w")) != NULL) {
(void) chmod(filename,S_IRWXU);
fprintf(fp,"%s\n",ML_DRAFT_HEADER);
fprintf(fp,"%s\t%s\n",HEADER_FROM,compose->options->replyto);
tmp = XmTextGetString(compose->window->to_text);
if(*tmp)
fprintf(fp,"%s\t%s\n",HEADER_TO,tmp);
fs_give((void **) &tmp);
tmp = XmTextGetString(compose->window->newsgroups_text);
if(*tmp)
fprintf(fp,"%s\t%s\n",HEADER_NEWSGROUPS,tmp);
fs_give((void **) &tmp);
tmp = XmTextGetString(compose->window->subject_text);
if(*tmp)
fprintf(fp,"%s\t%s\n",HEADER_SUBJECT,tmp);
fs_give((void **) &tmp);
tmp = XmTextGetString(compose->window->cc_text);
if(*tmp)
fprintf(fp,"%s\t%s\n",HEADER_CC,tmp);
fs_give((void **) &tmp);
tmp = XmTextGetString(compose->window->bcc_text);
if(*tmp)
fprintf(fp,"%s\t%s\n",HEADER_BCC,tmp);
fs_give((void **) &tmp);
fprintf(fp,"\n");
tmp = XmTextGetString(compose->window->compose_text);
fprintf(fp,"%s",tmp);
fs_give((void **) &tmp);
fclose(fp);
}
fs_give((void **) &filename);
pop_cursor();
return;
}
#ifdef __STDC__
void compose_load_draft(Widget w, MLCompose *compose, XtPointer xp)
#else
void compose_load_draft(w,compose,xp)
Widget w;
MLCompose *compose;
XtPointer xp;
#endif
{
FILE *fp;
char *filename;
char buffer[2 * FILEBUFFLEN];
struct stat st;
int c;
char *str;
char *dst;
filename = file_select(compose->window->shell, NULL, DRAFT_FILEPAT,
DRAFT_TEXT, FALSE, NULL);
if(filename == NULL)
return;
if(stat(filename,&st) != SYSCALL_SUCCESS) {
fs_give((void **) &filename);
return;
}
if((fp = fopen(filename,"r")) != NULL) {
fgets(buffer,sizeof(buffer),fp);
buffer[strlen(buffer) - 1] = NUL_TERM;
if(strcmp(buffer,ML_DRAFT_HEADER) != STRMATCH) {
fs_give((void **) &filename);
mm_log(MLGetLocalized(XtNmsgNotDraft,MsgNotDraft),ERROR);
return;
}
push_cursor(WATCH_CURSOR);
XtVaSetValues(compose->window->shell,
XmNtitle, MLGetLocalized(XtNstrDraft,StrDraft), NULL);
while(fgets(buffer,sizeof(buffer),fp) != NULL) {
buffer[strlen(buffer) - 1] = NUL_TERM;
if(! strlen(buffer))
break;
if(strncmp(buffer,HEADER_FROM,strlen(HEADER_FROM)) == STRMATCH) {
fs_give((void **) &compose->options->replyto);
compose->options->replyto = cpystr(buffer + strlen(HEADER_FROM) + 1);
}
if(strncmp(buffer,HEADER_TO,strlen(HEADER_TO)) == STRMATCH)
AppendText(compose->window->to_text,buffer + strlen(HEADER_TO) + 1);
if(strncmp(buffer,HEADER_NEWSGROUPS,
strlen(HEADER_NEWSGROUPS)) == STRMATCH)
AppendText(compose->window->newsgroups_text,
buffer + strlen(HEADER_NEWSGROUPS) + 1);
if(strncmp(buffer,HEADER_SUBJECT,strlen(HEADER_SUBJECT)) == STRMATCH)
AppendText(compose->window->subject_text,
buffer + strlen(HEADER_SUBJECT) + 1);
if(strncmp(buffer,HEADER_CC,strlen(HEADER_CC)) == STRMATCH)
AppendText(compose->window->cc_text,buffer + strlen(HEADER_CC) + 1);
if(strncmp(buffer,HEADER_BCC,strlen(HEADER_BCC)) == STRMATCH)
AppendText(compose->window->bcc_text,buffer + strlen(HEADER_BCC) + 1);
}
str = (char *) fs_get(st.st_size + 1);
dst = str;
while((c = fgetc(fp)) != EOF) {
*dst = c;
dst ++;
}
*dst = NUL_TERM;
fclose(fp);
AppendText(compose->window->compose_text,str);
fs_give((void **) &str);
}
fs_give((void **) &filename);
pop_cursor();
return;
}
#ifdef __STDC__
void compose_pop(Widget w, XtPointer xp)
#else
void compose_pop(w,xp)
Widget w;
XtPointer xp;
#endif
{
MLCompose *compose;
for(compose = session->compose; compose; compose = compose->next) {
if(compose->window->compose_text == w) {
compose_destroy_current(w,compose,NULL);
break;
}
}
return;
}
syntax highlighted by Code2HTML, v. 0.9.1