894 lines
22 KiB
C
894 lines
22 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
*+SNOTICE
|
|
*
|
|
* $TOG: ComposeCmds.C /main/11 1998/10/21 17:23:13 mgreess $
|
|
*
|
|
* RESTRICTED CONFIDENTIAL INFORMATION:
|
|
*
|
|
* The information in this document is subject to special
|
|
* restrictions in a confidential disclosure agreement between
|
|
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
|
|
* document outside HP, IBM, Sun, USL, SCO, or Univel without
|
|
* Sun's specific written approval. This document and all copies
|
|
* and derivative works thereof must be returned or destroyed at
|
|
* Sun's request.
|
|
*
|
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
*+ENOTICE
|
|
*/
|
|
|
|
#include <EUSCompat.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
|
|
#if defined(NEED_MMAP_WRAPPER)
|
|
extern "C" {
|
|
#endif
|
|
#include <sys/mman.h>
|
|
#if defined(NEED_MMAP_WRAPPER)
|
|
}
|
|
#endif
|
|
|
|
#include <pwd.h>
|
|
#include <Xm/Text.h>
|
|
#include <Xm/FileSBP.h>
|
|
#include <Xm/PushB.h>
|
|
#include <Xm/ToggleB.h>
|
|
#include <Xm/PushBG.h>
|
|
#include <Xm/PanedW.h>
|
|
#include <Xm/Form.h>
|
|
#include <Dt/Dts.h>
|
|
#include <Dt/Action.h>
|
|
#include <DtMail/IO.hh>
|
|
#include "RoamMenuWindow.h"
|
|
#include "SendMsgDialog.h"
|
|
#include "Undelete.hh"
|
|
#include "RoamCmds.h"
|
|
#include "ComposeCmds.hh"
|
|
#include "Application.h"
|
|
#include "RoamApp.h"
|
|
#include "DtMailWDM.hh"
|
|
#include "FindDialog.h"
|
|
#include "MsgScrollingList.hh"
|
|
#include "MsgHndArray.hh"
|
|
#include "MemUtils.hh"
|
|
#include "MailMsg.h"
|
|
#include "EUSDebug.hh"
|
|
#include "DtMailGenDialog.hh"
|
|
#include "DtMailHelp.hh"
|
|
#include <DtMail/DtMailError.hh>
|
|
#include "Help.hh"
|
|
#include <Dt/Help.h>
|
|
#include "Attachment.h"
|
|
#include "str_utils.h"
|
|
|
|
ComposeFamily::ComposeFamily(char *name,
|
|
char *label,
|
|
int active,
|
|
RoamMenuWindow *window)
|
|
: RoamCmd(name, label, active, window)
|
|
{
|
|
_parent = window;
|
|
}
|
|
|
|
#ifndef CAN_INLINE_VIRTUALS
|
|
ComposeFamily::~ComposeFamily( void )
|
|
{
|
|
}
|
|
#endif /* ! CAN_INLINE_VIRTUALS */
|
|
|
|
// Append a formatted message to Compose's Text area.
|
|
// This routine is essentially the same as MsgScollingList::display_message()
|
|
// except for two major differences:
|
|
// 1. No RoamMenuWindow reference (so that Compose can be standalone).
|
|
// 2. Indent string can be used for "include" and "forward".
|
|
void
|
|
ComposeFamily::Display_entire_msg(DtMailMessageHandle msgno,
|
|
SendMsgDialog *compose,
|
|
char *format
|
|
)
|
|
{
|
|
DtMailEnv error;
|
|
|
|
int num_bodyParts;
|
|
DtMail::MailBox *mbox = _menuwindow->mailbox();
|
|
DtMail::Message *msg = mbox->getMessage(error, msgno);
|
|
DtMail::Envelope *env = msg->getEnvelope(error);
|
|
DtMail::BodyPart *tmpBP = NULL;
|
|
DtMailBuffer tmpBuffer;
|
|
void *buffer = NULL;
|
|
unsigned long size = 0;
|
|
|
|
Editor::InsertFormat ins_format = Editor::IF_NONE;
|
|
Editor::BracketFormat brackets = Editor::BF_NONE;
|
|
|
|
// Do not need to wrap "include", "forward", and "indent" with
|
|
// catgets().
|
|
if ( strcmp(format, "include") == 0 ) {
|
|
ins_format = Editor::IF_BRACKETED;
|
|
brackets = Editor::BF_INCLUDE;
|
|
} else if ( strcmp(format, "forward") == 0 ) {
|
|
ins_format = Editor::IF_BRACKETED;
|
|
brackets = Editor::BF_FORWARD;
|
|
} else if ( strcmp(format, "indent") == 0 ) {
|
|
ins_format = Editor::IF_INDENTED;
|
|
}
|
|
|
|
// Get the editor to display the body of message with the appropriate
|
|
// insert/bracket formatting.
|
|
// We only include the first body part of the message. Attachments,
|
|
// etc. are "FORWARD"-ed but not "INCLUDE"-ed
|
|
|
|
char * status_string;
|
|
DtMailBoolean firstBPHandled =
|
|
compose->get_editor()->textEditor()->set_message(
|
|
msg,
|
|
&status_string,
|
|
Editor::HF_ABBREV,
|
|
ins_format,
|
|
brackets);
|
|
|
|
// Now need to handle the unhandled body parts of the message.
|
|
|
|
num_bodyParts = msg->getBodyCount(error);
|
|
if (error.isSet()) {
|
|
// do something
|
|
}
|
|
|
|
if (strcmp(format, "forward") == 0) {
|
|
// If the message has attachments, then let the attach pane
|
|
// handle attachments but not the first bodyPart (which has
|
|
// already been handled here).
|
|
|
|
if ((num_bodyParts > 1) || (!firstBPHandled)) {
|
|
|
|
tmpBP = msg->getFirstBodyPart(error);
|
|
if (firstBPHandled) {
|
|
// The first bodyPart has already been handled.
|
|
// The others, beginning from the second, need to be parsed
|
|
// and put into the attachPane.
|
|
|
|
compose->setInclMsgHnd(msg, TRUE);
|
|
tmpBP = msg->getNextBodyPart(error, tmpBP);
|
|
|
|
} else {
|
|
// The first bodyPart was not handled.
|
|
// It may not have been of type text.
|
|
// The attachment pane needs to handle all the bodyParts
|
|
// beginning with the first.
|
|
|
|
compose->setInclMsgHnd(msg, FALSE);
|
|
}
|
|
|
|
char *name;
|
|
while (tmpBP != NULL) {
|
|
tmpBP->getContents(
|
|
error, (const void **) &tmpBuffer.buffer,
|
|
&tmpBuffer.size,
|
|
NULL,
|
|
&name,
|
|
NULL,
|
|
NULL);
|
|
if (error.isSet()) {
|
|
// Do something
|
|
}
|
|
// It's possible for an attachment to not have a name.
|
|
if (!name) {
|
|
name = "NoName";
|
|
}
|
|
|
|
compose->add_att(name, tmpBuffer);
|
|
tmpBP = msg->getNextBodyPart(error, tmpBP);
|
|
if (error.isSet()) {
|
|
// do something
|
|
}
|
|
|
|
if (strcmp(name, "NoName") != 0) {
|
|
free(name);
|
|
}
|
|
}
|
|
if (error.isSet()) {
|
|
|
|
// do something
|
|
}
|
|
|
|
// Need to call this after calling parseAttachments().
|
|
|
|
compose->get_editor()->manageAttachArea();
|
|
|
|
// This message has attachment and is being included/forwarded,
|
|
// so need to fill the Compose Message Handle with attachment
|
|
// BodyParts.
|
|
// See function for further details.
|
|
|
|
// compose->updateMsgHndAtt();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If the message has attachments, then let the attach pane
|
|
// handle attachments but not the first bodyPart (which has
|
|
// already been handled here).
|
|
|
|
if ((num_bodyParts > 1) || (!firstBPHandled))
|
|
{
|
|
char *att;
|
|
Editor *editor = compose->get_editor()->textEditor();
|
|
|
|
att = GETMSG(
|
|
DT_catd, 1, 255,
|
|
"------------------ Attachments ------------------\n");
|
|
|
|
tmpBP = msg->getFirstBodyPart(error);
|
|
if (firstBPHandled)
|
|
tmpBP = msg->getNextBodyPart(error, tmpBP);
|
|
|
|
editor->append_to_contents(att, strlen(att));
|
|
while (tmpBP != NULL)
|
|
{
|
|
editor->set_attachment(tmpBP, ins_format, brackets);
|
|
tmpBP = msg->getNextBodyPart(error, tmpBP);
|
|
if (error.isSet()) {
|
|
// do something
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Leave it up to check point routine for update or do it now???
|
|
compose->updateMsgHnd();
|
|
}
|
|
|
|
void
|
|
ComposeFamily::appendSignature(SendMsgDialog * compose)
|
|
{
|
|
DtMailEnv error;
|
|
DtMail::Session * d_session = theRoamApp.session()->session();
|
|
DtMail::MailRc * mail_rc = d_session->mailRc(error);
|
|
|
|
const char * value = NULL;
|
|
mail_rc->getValue(error, "signature", &value);
|
|
if (error.isSet()) {
|
|
return;
|
|
}
|
|
|
|
char * fullpath = d_session->expandPath(error, value);
|
|
compose->get_editor()->textEditor()->append_to_contents(fullpath);
|
|
if (NULL != fullpath)
|
|
free((void*) fullpath);
|
|
if (NULL != value)
|
|
free((void*) value);
|
|
|
|
compose->get_editor()->textEditor()->set_to_top();
|
|
}
|
|
|
|
char *
|
|
ComposeFamily::valueToAddrString(DtMailValueSeq & value)
|
|
{
|
|
int max_len = 0;
|
|
int count;
|
|
|
|
for (count = 0; count < value.length(); count++) {
|
|
max_len += strlen(*(value[count]));
|
|
}
|
|
|
|
char * str = new char[max_len + count + 1];
|
|
str[0] = 0;
|
|
|
|
DtMailBoolean need_comma = DTM_FALSE;
|
|
|
|
for (int cat = 0; cat < value.length(); cat++)
|
|
{
|
|
DtMailValue * val = value[cat];
|
|
DtMailAddressSeq *addr_seq = val->toAddress();
|
|
|
|
for (int ad = 0; ad < addr_seq->length(); ad++)
|
|
{
|
|
DtMailValueAddress * addr = (*addr_seq)[ad];
|
|
|
|
// Deal with mail address parser shortcomings
|
|
if ( strcmp(addr->dtm_address, ",") == 0 )
|
|
continue ;
|
|
|
|
if (need_comma) {
|
|
strcat(str, ", ");
|
|
}
|
|
|
|
need_comma = DTM_TRUE;
|
|
|
|
strcat(str, addr->dtm_address);
|
|
}
|
|
|
|
delete addr_seq;
|
|
}
|
|
|
|
return(str);
|
|
}
|
|
|
|
|
|
// Container menu "Compose==>New Message"
|
|
ComposeCmd::ComposeCmd(
|
|
char *name,
|
|
char *label,
|
|
int active,
|
|
RoamMenuWindow *window
|
|
) : ComposeFamily( name, label, active, window )
|
|
{
|
|
}
|
|
|
|
// Put up a blank compose window.
|
|
void
|
|
ComposeCmd::doit()
|
|
{
|
|
SendMsgDialog * newsend = theCompose.getWin();
|
|
if (newsend == NULL) {
|
|
DtMailGenDialog * dialog = _parent->genDialog();
|
|
|
|
dialog->setToErrorDialog(GETMSG(DT_catd, 1, 203, "Mailer"),
|
|
GETMSG(DT_catd, 1, 204, "Unable to create a compose window."));
|
|
char * helpId = DTMAILHELPNOCOMPOSE;
|
|
int answer = dialog->post_and_return(helpId);
|
|
}
|
|
|
|
appendSignature(newsend);
|
|
}
|
|
|
|
// Container menu "Compose==>New, Include All" and "Compose==>Forward Message"
|
|
// The last parameter is a switch for "include" or "forward" format.
|
|
ForwardCmd::ForwardCmd(
|
|
char *name,
|
|
char *label,
|
|
int active,
|
|
RoamMenuWindow *window,
|
|
int forward
|
|
) : ComposeFamily(name, label, active, window)
|
|
{
|
|
_forward = forward;
|
|
}
|
|
|
|
// Forward or Include selected messages.
|
|
// For Include message(s), all Compose window header fields are left blank.
|
|
// For Forward message(s), the Compose window "Subject" header field is filled
|
|
// with the subject of the last selected message.
|
|
void
|
|
ForwardCmd::doit()
|
|
{
|
|
FORCE_SEGV_DECL(MsgHndArray, msgList);
|
|
FORCE_SEGV_DECL(MsgStruct, tmpMS);
|
|
DtMailMessageHandle msgno;
|
|
|
|
// Get a Compose window.
|
|
SendMsgDialog *newsend = theCompose.getWin();
|
|
if ( newsend == NULL ) {
|
|
DtMailGenDialog * dialog = _parent->genDialog();
|
|
|
|
dialog->setToErrorDialog(GETMSG(DT_catd, 1, 205, "Mailer"),
|
|
GETMSG(DT_catd, 1, 206, "Unable to create a compose window."));
|
|
char * helpId = DTMAILHELPNOCOMPOSE;
|
|
int answer = dialog->post_and_return(helpId);
|
|
}
|
|
|
|
// Put the signature above the message.
|
|
//
|
|
appendSignature(newsend);
|
|
|
|
// For Forwarding subject
|
|
DtMail::MailBox * mbox = _menuwindow->mailbox();
|
|
DtMail::Message * msg;
|
|
DtMail::Envelope * env;
|
|
DtMailValueSeq value;
|
|
DtMailEnv error;
|
|
|
|
// For each selected message, put it in the Compose window.
|
|
if ( msgList = _menuwindow->list()->selected() ) {
|
|
for ( int k = 0; k < msgList->length(); k++ ) {
|
|
tmpMS = msgList->at(k);
|
|
msgno = tmpMS->message_handle;
|
|
if ( _forward ) {
|
|
msg = mbox->getMessage(error, msgno);
|
|
env = msg->getEnvelope(error);
|
|
value.clear();
|
|
env->getHeader(error, DtMailMessageSubject, DTM_TRUE, value);
|
|
if (!error.isSet()) {
|
|
const char *subject = *(value[0]);
|
|
newsend->setHeader("Subject", subject);
|
|
newsend->setTitle((char*) subject);
|
|
newsend->setIconTitle((char*) subject);
|
|
}
|
|
Display_entire_msg(msgno, newsend, "forward");
|
|
} else {
|
|
Display_entire_msg(msgno, newsend, "indent");
|
|
}
|
|
}
|
|
}
|
|
newsend->get_editor()->textEditor()->set_to_top();
|
|
}
|
|
|
|
// Container menu "Compose==>Reply to Semder" and
|
|
// "Compose==>Reply to Sender, Include"
|
|
// The last parameter is a switch for including the selected message or not.
|
|
ReplyCmd::ReplyCmd (
|
|
char *name,
|
|
char *label,
|
|
int active,
|
|
RoamMenuWindow *window,
|
|
int include
|
|
) : ComposeFamily ( name, label, active, window )
|
|
{
|
|
_include = include;
|
|
}
|
|
|
|
// For each message selected, reply to sender.
|
|
void
|
|
ReplyCmd::doit()
|
|
{
|
|
FORCE_SEGV_DECL(MsgHndArray, msgList);
|
|
FORCE_SEGV_DECL(MsgStruct, tmpMS);
|
|
DtMailMessageHandle msgno;
|
|
FORCE_SEGV_DECL(char, from);
|
|
FORCE_SEGV_DECL(char, subject);
|
|
FORCE_SEGV_DECL(char, cc);
|
|
DtMailEnv error;
|
|
DtMail::MailBox * mbox = _menuwindow->mailbox();
|
|
|
|
// Initialize the error.
|
|
error.clear();
|
|
|
|
if (msgList = _menuwindow->list()->selected())
|
|
{
|
|
for ( int i=0; i < msgList->length(); i++ ) {
|
|
tmpMS = msgList->at(i);
|
|
msgno = tmpMS->message_handle;
|
|
SendMsgDialog *newsend = theCompose.getWin();
|
|
if ( newsend == NULL ) {
|
|
DtMailGenDialog * dialog = _parent->genDialog();
|
|
|
|
dialog->setToErrorDialog(GETMSG(DT_catd, 1, 207, "Mailer"),
|
|
GETMSG(DT_catd, 1, 208, "Unable to create a compose window."));
|
|
char * helpId = DTMAILHELPNOCOMPOSE;
|
|
int answer = dialog->post_and_return(helpId);
|
|
}
|
|
XmUpdateDisplay( newsend->baseWidget() );
|
|
|
|
DtMail::Message * msg = mbox->getMessage(error, msgno);
|
|
DtMail::Envelope * env = msg->getEnvelope(error);
|
|
|
|
DtMailValueSeq value;
|
|
|
|
env->getHeader(error, DtMailMessageSender, DTM_TRUE, value);
|
|
if (error.isSet()) {
|
|
newsend->setHeader("To", "nobody@nowhere");
|
|
}
|
|
else {
|
|
char * addr_str = valueToAddrString(value);
|
|
newsend->setHeader("To", addr_str);
|
|
delete [] addr_str;
|
|
}
|
|
|
|
value.clear();
|
|
env->getHeader(error, DtMailMessageSubject, DTM_TRUE, value);
|
|
if (error.isSet()) {
|
|
subject = new char[200];
|
|
strcpy(subject, "Re: ");
|
|
DtMailValueSeq sent;
|
|
env->getHeader(error,
|
|
DtMailMessageSentTime,
|
|
DTM_TRUE,
|
|
sent);
|
|
if (error.isSet()) {
|
|
strcat(subject, "Your Message");
|
|
}
|
|
else {
|
|
strcat(subject, "Your Message Sent on ");
|
|
strcat(subject, *(sent[0]));
|
|
}
|
|
newsend->setHeader("Subject", subject);
|
|
}
|
|
else {
|
|
// Get the BE store of header. It may contain newlines or
|
|
// tab chars which can munge the scrolling list's display!
|
|
|
|
const char * orig = *(value[0]);
|
|
|
|
int fc;
|
|
int orig_length;
|
|
char *tmp_subj;
|
|
|
|
// Check if BE store contains the funky chars.
|
|
|
|
for (fc = 0, orig_length = strlen(orig),
|
|
tmp_subj = (char *) orig;
|
|
fc < orig_length;
|
|
fc++, tmp_subj++) {
|
|
|
|
char c = *tmp_subj;
|
|
if ((c == '\n')
|
|
|| (c == '\t')
|
|
|| (c == '\r')) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
subject = new char[fc+6];
|
|
|
|
if (strncasecmp(orig, "Re:", 3)) {
|
|
strcpy(subject, "Re: ");
|
|
}
|
|
else {
|
|
*subject = 0;
|
|
}
|
|
|
|
strncat((char *)subject, orig, fc);
|
|
|
|
newsend->setHeader("Subject", subject);
|
|
}
|
|
|
|
newsend->setTitle(subject);
|
|
newsend->setIconTitle(subject);
|
|
delete [] subject;
|
|
|
|
if ( _include ) {
|
|
Display_entire_msg(msgno, newsend, "indent");
|
|
newsend->get_editor()->textEditor()->set_to_top();
|
|
}
|
|
appendSignature(newsend);
|
|
newsend->setInputFocus(1);
|
|
}
|
|
|
|
delete msgList;
|
|
}
|
|
}
|
|
|
|
// Container menu "Compose==>Reply to All" and "Compose==>Reply to All, Include"
|
|
// The last parameter is a switch for including the selected message or not.
|
|
ReplyAllCmd::ReplyAllCmd(
|
|
char *name,
|
|
char *label,
|
|
int active,
|
|
RoamMenuWindow *window,
|
|
int include
|
|
) : ComposeFamily( name, label, active, window )
|
|
{
|
|
_include = include;
|
|
}
|
|
|
|
// For each message selected, reply to everybody.
|
|
void
|
|
ReplyAllCmd::doit()
|
|
{
|
|
FORCE_SEGV_DECL(MsgHndArray, msgList);
|
|
FORCE_SEGV_DECL(MsgStruct, tmpMS);
|
|
FORCE_SEGV_DECL(char, subject);
|
|
FORCE_SEGV_DECL(char, to);
|
|
FORCE_SEGV_DECL(char, buffer);
|
|
DtMailMessageHandle msgno;
|
|
DtMail::MailBox *mbox = _menuwindow->mailbox();
|
|
DtMailEnv error;
|
|
char *currentCcValue;
|
|
SendMsgDialog *newsend;
|
|
DtMailGenDialog * dialog;
|
|
DtMail::Message *msg;
|
|
DtMail::Envelope *env;
|
|
|
|
|
|
// Initialize the mail_error.
|
|
error.clear();
|
|
|
|
|
|
if ( msgList = _menuwindow->list()->selected() )
|
|
for ( int k = 0; k < msgList->length(); k++ ) {
|
|
DtMailValueSeq value ;
|
|
|
|
tmpMS = msgList->at(k);
|
|
msgno = tmpMS->message_handle;
|
|
newsend = theCompose.getWin();
|
|
if ( newsend == NULL ) {
|
|
dialog = _parent->genDialog();
|
|
|
|
dialog->setToErrorDialog(GETMSG(DT_catd, 1, 209, "Mailer"),
|
|
GETMSG(DT_catd, 1, 210, "Unable to create a compose window."));
|
|
char * helpId = DTMAILHELPNOCOMPOSE;
|
|
int answer = dialog->post_and_return(helpId);
|
|
}
|
|
msg = mbox->getMessage(error, msgno);
|
|
env = msg->getEnvelope(error);
|
|
|
|
env->getHeader(
|
|
error,
|
|
DtMailMessageToReply,
|
|
DTM_TRUE,
|
|
value);
|
|
|
|
env->getHeader(
|
|
error,
|
|
DtMailMessageSender,
|
|
DTM_TRUE,
|
|
value);
|
|
|
|
char * addr_str = valueToAddrString(value);
|
|
newsend->setHeader("To", addr_str);
|
|
delete [] addr_str;
|
|
value.clear();
|
|
env->getHeader(
|
|
error,
|
|
DtMailMessageSubject,
|
|
DTM_TRUE,
|
|
value);
|
|
if ( error.isSet() ) {
|
|
subject = new char[200];
|
|
strcpy(subject, "Re: ");
|
|
DtMailValueSeq sent;
|
|
env->getHeader(error,
|
|
DtMailMessageSentTime,
|
|
DTM_TRUE,
|
|
sent);
|
|
if (error.isSet()) {
|
|
strcat(subject, "Your Message");
|
|
}
|
|
else {
|
|
strcat(subject, "Your Message Sent on ");
|
|
strcat(subject, *(sent[0]));
|
|
}
|
|
newsend->setHeader("Subject", subject);
|
|
} else {
|
|
// Get the BE store of header. It may contain newlines or
|
|
// tab chars which can munge the scrolling list's display!
|
|
|
|
const char * orig = *(value[0]);
|
|
|
|
|
|
int fc = 0;
|
|
int orig_length;
|
|
char *tmp_subj;
|
|
|
|
// Check if BE store contains the funky chars.
|
|
|
|
for (fc = 0, orig_length = strlen(orig),
|
|
tmp_subj = (char *)orig;
|
|
fc < orig_length;
|
|
fc++, tmp_subj++) {
|
|
|
|
char c = *tmp_subj;
|
|
if ((c == '\n')
|
|
|| (c == '\t')
|
|
|| (c == '\r')) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
subject = new char[fc+6];
|
|
|
|
if (strncasecmp(orig, "Re:", 3)) {
|
|
strcpy(subject, "Re: ");
|
|
}
|
|
else {
|
|
*subject = 0;
|
|
}
|
|
|
|
strncat((char *)subject, orig, fc);
|
|
|
|
newsend->setHeader("Subject", subject);
|
|
}
|
|
value.clear();
|
|
env->getHeader(
|
|
error,
|
|
DtMailMessageCcReply,
|
|
DTM_TRUE,
|
|
value);
|
|
if (!error.isSet()) {
|
|
// Strip out newlines from the cc line. They *may* be
|
|
// present.
|
|
currentCcValue = valueToAddrString(value);
|
|
|
|
newsend->setHeader("Cc", currentCcValue);
|
|
delete [] currentCcValue ;
|
|
}
|
|
|
|
newsend->setTitle(subject);
|
|
newsend->setIconTitle(subject);
|
|
delete [] subject;
|
|
|
|
if ( _include ) {
|
|
Display_entire_msg(msgno, newsend, "indent");
|
|
newsend->get_editor()->textEditor()->set_to_top();
|
|
}
|
|
appendSignature(newsend);
|
|
newsend->setInputFocus(1);
|
|
}
|
|
}
|
|
|
|
TemplateCmd::TemplateCmd(char *name,
|
|
char *label,
|
|
int active,
|
|
SendMsgDialog * compose,
|
|
const char * file)
|
|
: NoUndoCmd(name, label, active)
|
|
{
|
|
_compose = compose;
|
|
|
|
if (*file != '/' && *file != '~') {
|
|
// Relative path. Should be relative to home directory
|
|
_file = (char *)malloc(strlen(file) + 4);
|
|
if (_file != NULL) {
|
|
strcpy(_file, "~/");
|
|
strcat(_file, file);
|
|
}
|
|
} else {
|
|
_file = strdup(file);
|
|
}
|
|
}
|
|
|
|
TemplateCmd::~TemplateCmd(void)
|
|
{
|
|
free(_file);
|
|
}
|
|
|
|
void
|
|
TemplateCmd::doit()
|
|
{
|
|
DtMailEnv error;
|
|
DtMail::Session * d_session = theRoamApp.session()->session();
|
|
DtMailGenDialog * dialog = _compose->genDialog();
|
|
DtMailBuffer mbuf;
|
|
|
|
char * fullpath = d_session->expandPath(error, _file);
|
|
|
|
// Map the file and try to parse it as a message. If it is a message,
|
|
// then load it with headers. Otherwise, throw everything into the
|
|
// editor.
|
|
//
|
|
int fd = SafeOpen(fullpath, O_RDONLY);
|
|
if (fd < 0) {
|
|
dialog->setToErrorDialog(GETMSG(DT_catd, 1, 211, "Mailer"),
|
|
GETMSG(DT_catd, 1, 212, "The template does not exist."));
|
|
char * helpId = DTMAILHELPNOTEMPLATE;
|
|
int answer = dialog->post_and_return(helpId);
|
|
free(fullpath);
|
|
return;
|
|
}
|
|
|
|
struct stat buf;
|
|
if (SafeFStat(fd, &buf) < 0) {
|
|
dialog->setToErrorDialog(GETMSG(DT_catd, 1, 213, "Mailer"),
|
|
GETMSG(DT_catd, 1, 214, "The template appears to be corrupt."));
|
|
char * helpId = DTMAILHELPCORRUPTTEMPLATE;
|
|
int answer = dialog->post_and_return(helpId);
|
|
SafeClose(fd);
|
|
free(fullpath);
|
|
return;
|
|
}
|
|
|
|
int page_size = (int)sysconf(_SC_PAGESIZE);
|
|
size_t map_size = (size_t) (buf.st_size +
|
|
(page_size - (buf.st_size % page_size)));
|
|
|
|
int free_buf = 0;
|
|
mbuf.size = buf.st_size;
|
|
#ifdef __osf__
|
|
// This version of mmap does NOT allow requested length to be
|
|
// greater than the file size ... in contradiction to the
|
|
// documentation (don't round up).
|
|
mbuf.buffer = mmap(0, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
#else
|
|
mbuf.buffer = mmap(0, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
#endif
|
|
if (mbuf.buffer == (char *)-1) {
|
|
free_buf = 1;
|
|
mbuf.buffer = new char[mbuf.size];
|
|
if (mbuf.buffer == NULL) {
|
|
dialog->setToErrorDialog(GETMSG(DT_catd, 1, 215, "Mailer"),
|
|
GETMSG(DT_catd, 1, 216, "There is not enough memory to load the template."));
|
|
char * helpId = DTMAILHELPNOMEMTEMPLATE;
|
|
int answer = dialog->post_and_return(helpId);
|
|
SafeClose(fd);
|
|
free(fullpath);
|
|
return;
|
|
}
|
|
|
|
if (SafeRead(fd, mbuf.buffer, (unsigned int)mbuf.size) < mbuf.size) {
|
|
dialog->setToErrorDialog(GETMSG(DT_catd, 1, 217, "Mailer"),
|
|
GETMSG(DT_catd, 1, 218, "The template appears to be corrupt."));
|
|
char * helpId = DTMAILHELPERROR;
|
|
int answer = dialog->post_and_return(helpId);
|
|
SafeClose(fd);
|
|
delete [] mbuf.buffer;
|
|
free(fullpath);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Now we ask the library to parse it. If this fails for any reason, this
|
|
// is not a message, so we give up.
|
|
//
|
|
DtMail::Message * msg = d_session->messageConstruct(error,
|
|
DtMailBufferObject,
|
|
&mbuf,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (error.isSet()) {
|
|
_compose->get_editor()->textEditor()->append_to_contents((char *)mbuf.buffer,
|
|
mbuf.size);
|
|
}
|
|
else {
|
|
_compose->loadHeaders(msg, DTM_TRUE);
|
|
|
|
DtMail::BodyPart * bp = msg->getFirstBodyPart(error);
|
|
if (error.isNotSet()) {
|
|
const void * contents;
|
|
unsigned long length;
|
|
|
|
bp->getContents(error,
|
|
&contents,
|
|
&length,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
_compose->get_editor()->textEditor()->append_to_contents(
|
|
(char *)contents, length);
|
|
}
|
|
}
|
|
|
|
free(fullpath);
|
|
|
|
if (free_buf) {
|
|
free(mbuf.buffer);
|
|
}
|
|
else {
|
|
munmap((char *)mbuf.buffer, map_size);
|
|
}
|
|
|
|
SafeClose(fd);
|
|
}
|
|
|
|
HideShowCmd::HideShowCmd(char *name,
|
|
char *widgetlabel,
|
|
int active,
|
|
SendMsgDialog * compose,
|
|
const char * label)
|
|
: NoUndoCmd(name, (char *)widgetlabel, active)
|
|
{
|
|
_compose = compose;
|
|
_header = strdup(label);
|
|
}
|
|
|
|
HideShowCmd::~HideShowCmd(void)
|
|
{
|
|
if (_header) {
|
|
free(_header);
|
|
}
|
|
}
|
|
|
|
void
|
|
HideShowCmd::doit(void)
|
|
{
|
|
_compose->changeHeaderState(_header);
|
|
}
|