#include "xmh.h"
#include "tocutil.h"
#include "actions.h"
#define MAX_SYSTEM_LEN 510
Boolean UserWantsAction(
Widget w,
Scrn scrn)
{
if (XtIsSubclass(w, menuButtonWidgetClass) &&
w != LastMenuButtonPressed)
return False;
if (XtIsSubclass(w, simpleMenuWidgetClass) &&
(! XawSimpleMenuGetActiveEntry(w)) &&
(BBoxIsGrandparent(scrn->folderbuttons, w)))
return False;
return True;
}
static void NextAndPreviousView(
Scrn scrn,
Boolean next)
{
Toc toc = scrn->toc;
MsgList mlist;
FateType fate = Fignore;
Msg msg;
if (toc == NULL) return;
mlist = TocCurMsgList(toc);
if (mlist->nummsgs)
msg = (next ? mlist->msglist[0] : mlist->msglist[mlist->nummsgs - 1]);
else {
msg = TocGetCurMsg(toc);
if (msg && msg == scrn->msg)
msg = (next ? TocMsgAfter(toc, msg) : TocMsgBefore(toc, msg));
if (msg) fate = MsgGetFate(msg, (Toc *)NULL);
while (msg && ((app_resources.skip_deleted && fate == Fdelete)
|| (app_resources.skip_moved && fate == Fmove)
|| (app_resources.skip_copied && fate == Fcopy))) {
msg = (next ? TocMsgAfter(toc, msg) : TocMsgBefore(toc, msg));
if (msg) fate = MsgGetFate(msg, (Toc *)NULL);
}
}
if (msg) {
XtCallbackRec confirms[2];
if (next)
confirms[0].callback = (XtCallbackProc) DoNextView;
else
confirms[0].callback = (XtCallbackProc) DoPrevView;
confirms[0].closure = (XtPointer) scrn;
confirms[1].callback = (XtCallbackProc) NULL;
confirms[1].closure = (XtPointer) NULL;
if (MsgSetScrn(msg, scrn, confirms, (XtCallbackList) NULL) !=
NEEDS_CONFIRMATION) {
TocUnsetSelection(toc);
TocSetCurMsg(toc, msg);
}
}
FreeMsgList(mlist);
}
void DoReverseReadOrder(
Widget widget,
XtPointer client_data,
XtPointer call_data)
{
app_resources.reverse_read_order =
(app_resources.reverse_read_order ? False : True);
ToggleMenuItem(widget, app_resources.reverse_read_order);
}
void DoNextView(
Widget widget,
XtPointer client_data,
XtPointer call_data)
{
NextAndPreviousView((Scrn) client_data,
(app_resources.reverse_read_order ? False : True));
}
void XmhViewNextMessage(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoNextView(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoPrevView(
Widget widget,
XtPointer client_data,
XtPointer call_data)
{
NextAndPreviousView((Scrn) client_data,
(app_resources.reverse_read_order ? True : False));
}
void XmhViewPreviousMessage(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoPrevView(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoViewNew(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = scrn->toc;
Scrn vscrn;
MsgList mlist;
if (toc == NULL) return;
mlist = CurMsgListOrCurMsg(toc);
if (mlist->nummsgs) {
vscrn = NewViewScrn();
(void) MsgSetScrn(mlist->msglist[0], vscrn, (XtCallbackList) NULL,
(XtCallbackList) NULL);
MapScrn(vscrn);
}
FreeMsgList(mlist);
}
void XmhViewInNewWindow(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoViewNew(w, (XtPointer) scrn, (XtPointer) NULL);
}
static void DoForwardMsg(
Scrn scrn,
String *params,
Cardinal num_params)
{
Toc toc = scrn->toc;
MsgList mlist;
if (toc == NULL) return;
mlist = CurMsgListOrCurMsg(toc);
if (mlist->nummsgs)
CreateForward(mlist, params, num_params);
FreeMsgList(mlist);
}
void DoForward(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
DoForwardMsg((Scrn) client_data, (String *)NULL, (Cardinal)0);
}
void XmhForward(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoForwardMsg(scrn, params, *num_params);
}
void DoTocUseAsComp(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = scrn->toc;
Scrn vscrn;
MsgList mlist;
Msg msg;
if (toc == NULL) return;
mlist = CurMsgListOrCurMsg(toc);
if (mlist->nummsgs) {
vscrn = NewCompScrn();
if (DraftsFolder == toc) {
msg = mlist->msglist[0];
} else {
msg = TocMakeNewMsg(DraftsFolder);
MsgLoadCopy(msg, mlist->msglist[0]);
MsgSetTemporary(msg);
}
MsgSetScrnForComp(msg, vscrn);
MapScrn(vscrn);
}
FreeMsgList(mlist);
}
void XmhUseAsComposition(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoTocUseAsComp(w, (XtPointer) scrn, (XtPointer) NULL);
}
static void MarkMessages(Scrn scrn, FateType fate, int skip)
{
Toc toc = scrn->toc;
Toc desttoc;
int i;
MsgList mlist;
Msg msg;
if (toc == NULL) return;
if (fate == Fcopy || fate == Fmove)
desttoc = SelectedToc(scrn);
else
desttoc = NULL;
if (desttoc == toc)
Feep(XkbBI_MinorError,0,None);
else {
mlist = TocCurMsgList(toc);
if (mlist->nummsgs == 0) {
msg = TocGetCurMsg(toc);
if (msg) {
MsgSetFate(msg, fate, desttoc);
if (skip)
DoNextView(scrn->widget, (XtPointer) scrn,
(XtPointer) NULL);
}
} else {
for (i = 0; i < mlist->nummsgs; i++)
MsgSetFate(mlist->msglist[i], fate, desttoc);
}
FreeMsgList(mlist);
}
}
void XmhMarkDelete(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoDelete(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoDelete(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
MarkMessages(scrn, Fdelete, app_resources.skip_deleted);
}
void DoCopy(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
MarkMessages(scrn, Fcopy, app_resources.skip_copied);
}
void XmhMarkCopy(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoCopy(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoMove(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
MarkMessages(scrn, Fmove, app_resources.skip_moved);
}
void XmhMarkMove(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoMove(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoUnmark(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
MarkMessages(scrn, Fignore, FALSE);
}
void XmhUnmark(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoUnmark(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoCommit(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
TocCommitChanges(w, (XtPointer) scrn->toc, (XtPointer) NULL);
}
void XmhCommitChanges(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
TocCommitChanges(w, (XtPointer) scrn->toc, (XtPointer) NULL);
}
void XmhShellCommand(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
int i, len, used;
MsgList mlist;
String *p;
Scrn scrn = ScrnFromWidget(w);
char str[MAX_SYSTEM_LEN];
if (! UserWantsAction(w, scrn) || ! scrn->toc)
return;
if (! *num_params) {
PopupError(scrn->parent, "XmhShellCommand: no command given.");
return;
}
used = 0;
p = params;
for (i = *num_params; --i >= 0; p++) {
len = strlen(*p);
if ((used + len + 1) >= MAX_SYSTEM_LEN) {
PopupError(scrn->parent, "XmhShellCommand: command too long.");
return;
}
strncpy(&str[used], *p, len);
str[(used += len)] = ' ';
used++;
}
str[used] = '\0';
mlist = CurMsgListOrCurMsg(scrn->toc);
if (mlist->nummsgs) {
char *msg;
int prefix = used;
i = 0;
while (i < mlist->nummsgs) {
used = prefix;
while (i < mlist->nummsgs &&
(msg = MsgFileName(mlist->msglist[i])) &&
(used + (len = strlen(msg)) + 1) < MAX_SYSTEM_LEN) {
strncpy(&str[used], msg, len);
str[(used += len)] = ' ';
used++;
i++;
}
if (used != prefix) {
char **argv;
str[used] = '\0';
DEBUG( str );
argv = MakeArgv(3);
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = str;
(void) DoCommand(argv, (char*)NULL, (char*)NULL);
XtFree((char*)argv);
}
}
} else
PopupError(scrn->parent, "XmhShellCommand: no messages selected.");
FreeMsgList(mlist);
}
void XmhPrint(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
if (! num_params || ! *num_params) {
Cardinal argc = 1;
String *argv = MakeArgv(argc);
argv[0] = app_resources.print_command;
XmhShellCommand(w, event, argv, &argc);
XtFree((char *) argv);
} else {
XmhShellCommand(w, event, params, num_params);
}
}
void DoPrint(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Cardinal num_params = 0;
XmhPrint(scrn->parent, (XEvent*)NULL, (String*)NULL, &num_params);
}
void DoPack(
Widget widget,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = scrn->toc;
XtCallbackRec confirms[2];
char **argv;
if (toc == NULL) return;
confirms[0].callback = (XtCallbackProc) DoPack;
confirms[0].closure = (XtPointer) scrn;
confirms[1].callback = (XtCallbackProc) NULL;
confirms[1].closure = (XtPointer) NULL;
if (TocConfirmCataclysm(toc, confirms, (XtCallbackRec *) NULL))
return;
argv = MakeArgv(4);
argv[0] = "folder";
argv[1] = TocMakeFolderName(toc);
argv[2] = "-pack";
argv[3] = "-fast";
if (app_resources.block_events_on_busy) ShowBusyCursor();
DoCommand(argv, (char *) NULL, (char *) NULL);
XtFree(argv[1]);
XtFree((char *) argv);
TocForceRescan(toc);
if (app_resources.block_events_on_busy) UnshowBusyCursor();
}
void XmhPackFolder(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoPack(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoSort(
Widget widget,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = scrn->toc;
char ** argv;
XtCallbackRec confirms[2];
if (toc == NULL) return;
confirms[0].callback = (XtCallbackProc) DoSort;
confirms[0].closure = (XtPointer) scrn;
confirms[1].callback = (XtCallbackProc) NULL;
confirms[1].closure = (XtPointer) NULL;
if (TocConfirmCataclysm(toc, confirms, (XtCallbackRec *) NULL))
return;
argv = MakeArgv(3);
argv[0] = "sortm";
argv[1] = TocMakeFolderName(toc);
argv[2] = "-noverbose";
if (app_resources.block_events_on_busy) ShowBusyCursor();
DoCommand(argv, (char *) NULL, (char *) NULL);
XtFree(argv[1]);
XtFree((char *) argv);
TocForceRescan(toc);
if (app_resources.block_events_on_busy) UnshowBusyCursor();
}
void XmhSortFolder(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoSort(w, (XtPointer) scrn, (XtPointer) NULL);
}
void XmhForceRescan(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoForceRescan(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoForceRescan(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = scrn->toc;
if (toc == NULL) return;
if (app_resources.block_events_on_busy) ShowBusyCursor();
TocForceRescan(toc);
if (app_resources.block_events_on_busy) UnshowBusyCursor();
}
void XmhCheckForNewMail(
Widget w,
XEvent *e,
String *p,
Cardinal *n)
{
TocCheckForNewMail(True);
}
void XmhIncorporateNewMail(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn)) {
if (TocCanIncorporate(scrn->toc))
DoIncorporateNewMail(w, (XtPointer) scrn, (XtPointer) NULL);
}
}
void DoIncorporateNewMail(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = scrn->toc;
int i;
int newmail;
if (! toc) return;
newmail = TocIncorporate(toc);
if (app_resources.show_on_inc && newmail)
DoNextView(w, client_data, call_data);
if (app_resources.new_mail_check)
for (i=0; i < numScrns; i++) {
scrn = scrnList[i];
if (scrn->kind == STtocAndView)
BBoxMailFlag(scrn->folderbuttons, TocName(toc), False);
}
if (app_resources.mail_waiting_flag)
TocCheckForNewMail(False);
}
static void DoReplyMsg(
Scrn scrn,
String *params,
Cardinal num_params)
{
Toc toc = scrn->toc;
Scrn nscrn;
MsgList mlist;
Msg msg;
if (toc == NULL) return;
mlist = CurMsgListOrCurMsg(toc);
if (mlist->nummsgs) {
nscrn = NewCompScrn();
ScreenSetAssocMsg(nscrn, mlist->msglist[0]);
msg = TocMakeNewMsg(DraftsFolder);
MsgSetTemporary(msg);
MsgLoadReply(msg, mlist->msglist[0], params, num_params);
MsgSetScrnForComp(msg, nscrn);
MapScrn(nscrn);
}
FreeMsgList(mlist);
}
void DoReply(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
DoReplyMsg((Scrn) client_data, (String *)NULL, (Cardinal)0);
}
void XmhReply(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoReplyMsg(scrn, params, *num_params);
}
void DoPickMessages(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = scrn->toc;
Scrn nscrn;
char * toseq;
Sequence selectedseq;
Boolean recycled;
if (toc == NULL) return;
if ((selectedseq = TocSelectedSequence(toc)) == NULL)
toseq = "temp";
else {
toseq = selectedseq->name;
if (strcmp(toseq, "all") == 0)
toseq = "temp";
}
nscrn = CreateNewScrn(STpick);
recycled = (nscrn->pick) ? True : False;
AddPick(nscrn, toc, (TocViewedSequence(toc))->name, toseq);
DEBUG("Realizing Pick...")
XtRealizeWidget(nscrn->parent);
DEBUG(" done.\n")
if (! recycled) {
InitBusyCursor(nscrn);
XDefineCursor(XtDisplay(nscrn->parent), XtWindow(nscrn->parent),
app_resources.cursor);
(void) XSetWMProtocols(XtDisplay(toplevel), XtWindow(nscrn->parent),
protocolList, XtNumber(protocolList));
}
MapScrn(nscrn);
}
void XmhPickMessages(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
DoPickMessages(w, (XtPointer) scrn, (XtPointer) NULL);
}
void DoSelectSequence(
Widget widget,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = (Toc) scrn->toc;
Sequence seq;
if ((seq = TocSelectedSequence(toc)) != NULL) {
Widget item, menu;
Button button;
button = BBoxFindButtonNamed
(scrn->mainbuttons, MenuBoxButtons[XMH_SEQUENCE].button_name);
menu = BBoxMenuOfButton(button);
if ((item = XtNameToWidget(menu, seq->name)) != NULL)
ToggleMenuItem(item, False);
}
ToggleMenuItem(widget, True);
TocSetSelectedSequence(toc, TocGetSeqNamed(toc, XtName(widget)));
}
void DoOpenSeq(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
Toc toc = scrn->toc;
if (toc == NULL) return;
TocChangeViewedSeq(toc, TocSelectedSequence(toc));
}
void XmhOpenSequence(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Widget entry_object;
Scrn scrn = ScrnFromWidget(w);
Sequence selected_sequence;
if (! UserWantsAction(w, scrn))
return;
if (! TocHasSequences(scrn->toc))
return;
if (*num_params) {
Toc toc = scrn->toc;
if ((selected_sequence = TocGetSeqNamed(toc, params[0]))) {
TocSetSelectedSequence(toc, selected_sequence);
TocChangeViewedSeq(toc, selected_sequence);
}
return;
}
if ((strcmp(XtName(w), "sequenceMenu") == 0) &&
(event->type == ButtonRelease)) {
if ((entry_object = XawSimpleMenuGetActiveEntry(w)) == NULL)
return;
if ((selected_sequence = TocSelectedSequence(scrn->toc)) &&
(strcmp(XtName(entry_object), selected_sequence->name) == 0))
DoOpenSeq(w, (XtPointer) scrn, (XtPointer) NULL);
return;
}
DoOpenSeq(w, (XtPointer) scrn, (XtPointer) NULL);
}
typedef enum {ADD, REMOVE, DELETE} TwiddleOperation;
static void TwiddleSequence(Scrn scrn, TwiddleOperation op)
{
Toc toc = scrn->toc;
char **argv, str[100];
int i;
MsgList mlist;
Sequence selectedseq;
if (toc == NULL || ((selectedseq = TocSelectedSequence(toc)) == NULL))
return;
if (strcmp(selectedseq->name, "all") == 0) {
Feep(XkbBI_MinorError,0,None);
return;
}
if (op == DELETE)
mlist = MakeNullMsgList();
else {
mlist = CurMsgListOrCurMsg(toc);
if (mlist->nummsgs == 0) {
FreeMsgList(mlist);
Feep(XkbBI_MinorError,0,None);
return;
}
}
argv = MakeArgv(6 + mlist->nummsgs);
argv[0] = "mark";
argv[1] = TocMakeFolderName(toc);
argv[2] = "-sequence";
argv[3] = selectedseq->name;
switch (op) {
case ADD:
argv[4] = "-add";
argv[5] = "-nozero";
break;
case REMOVE:
argv[4] = "-delete";
argv[5] = "-nozero";
break;
case DELETE:
argv[4] = "-delete";
argv[5] = "all";
break;
}
for (i = 0; i < mlist->nummsgs; i++) {
(void) sprintf(str, "%d", MsgGetId(mlist->msglist[i]));
argv[6 + i] = XtNewString(str);
}
DoCommand(argv, (char *) NULL, (char *) NULL);
for (i = 0; i < mlist->nummsgs; i++)
XtFree((char *) argv[6 + i]);
XtFree(argv[1]);
XtFree((char *) argv);
FreeMsgList(mlist);
TocReloadSeqLists(toc);
}
void DoAddToSeq(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
TwiddleSequence(scrn, ADD);
}
void XmhAddToSequence(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (! UserWantsAction(w, scrn))
return;
if ((strcmp(XtName(w), "sequenceMenu") == 0) &&
(event->type == ButtonRelease) &&
(XawSimpleMenuGetActiveEntry(w) == NULL))
return;
if (TocHasSequences(scrn->toc))
TwiddleSequence(scrn, ADD);
}
void DoRemoveFromSeq(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
TwiddleSequence(scrn, REMOVE);
}
void XmhRemoveFromSequence(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (UserWantsAction(w, scrn))
if (TocHasSequences(scrn->toc))
TwiddleSequence(scrn, REMOVE);
}
void DoDeleteSeq(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Scrn scrn = (Scrn) client_data;
TwiddleSequence(scrn, DELETE);
TUCheckSequenceMenu(scrn->toc);
}
void XmhDeleteSequence(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
Scrn scrn = ScrnFromWidget(w);
if (! UserWantsAction(w, scrn))
return;
if ((strcmp(XtName(w), "sequenceMenu") == 0) &&
(event->type == ButtonRelease) &&
(XawSimpleMenuGetActiveEntry(w) == NULL))
return;
if (TocHasSequences(scrn->toc))
DoDeleteSeq(w, (XtPointer) scrn, (XtPointer) NULL);
}