/* ml.c */
#include "ml.h"
#include <locale.h>
/* global structures and variables */
XtAppContext context;
Preferences preferences;
Local_Auth local_auth;
Session *session; /* Most everything in the program is found here */
Display *display;
int errfd[2];
Boolean no_prefs = FALSE;
Boolean silent_pipe = FALSE;
char MLSender[FILEBUFFLEN];
char MLMailbox[FILEBUFFLEN];
char **Argv;
int Argc = 0;
XtActionsRec global_actions[] = {
{ "complete-address", (XtActionProc) complete_address },
{ "search-text", (XtActionProc) search_text },
{ "hex-input", (XtActionProc) hex_input },
{ "lview-pop", (XtActionProc) lview_pop },
{ "read-pop", (XtActionProc) read_pop },
{ "compose-pop", (XtActionProc) compose_pop },
{ "filters-pop", (XtActionProc) filters_pop },
{ "mailboxes-pop", (XtActionProc) mailboxes_pop },
{ "mailcopy-pop", (XtActionProc) mailcopy_pop },
{ "addresses-pop", (XtActionProc) addresses_pop },
{ "note-pop", (XtActionProc) note_pop },
{ "help-pop", (XtActionProc) help_pop },
{ "netconf-pop", (XtActionProc) netconf_pop },
{ "messages-pop", (XtActionProc) messages_pop },
};
/* IMAP registered drivers */
extern DRIVER
imapdriver, mboxdriver, bezerkdriver, tenexdriver, nntpdriver,
newsdriver, dummydriver, pop3driver, mtxdriver, mhdriver,
mmdfdriver, philedriver;
/* Begin Program */
#ifdef __STDC__
void main(int argc,char **argv, char **envp)
#else
void main(argc,argv,envp)
int argc;
char ** argv;
char ** envp;
#endif
{
Arg args[ARGLISTSIZE];
MainWindow *mwin;
LogWindow *lwin;
int fd;
int n = 0;
char buffer[FILEBUFFLEN];
char envstring[256];
struct stat st;
char *ptr;
Argv = argv;
Argc = argc;
if(getenv(ML_SETLANG))
#if XtSpecificationRelease > 4
XtSetLanguageProc(NULL, NULL, NULL);
#else
setlocale(LC_ALL, EMPTYSTR);
#endif
session = (Session *) fs_get(sizeof(Session));
mwin = (MainWindow *) fs_get(sizeof(MainWindow));
mwin->next = mwin->prev = NULL;
session->lwin = (LogWindow *) fs_get(sizeof(LogWindow));
session->active = NULL;
session->mwin = mwin;
/***********************************************************************
* Create top level application shell - start X *
***********************************************************************/
session->shell = mwin->shell = XtAppInitialize((XtAppContext*) &context,
PROGRAM,
NULL, 0, &argc,argv,
#ifdef FALLBACK
fallback_resources,
#else /* FALLBACK */
NULL,
#endif /* FALLBACK */
args, n);
n = 0;
setup_editres(mwin->shell);
XtAppAddActions(context, global_actions, XtNumber(global_actions));
if((get_user()) == SYSCALL_FAILURE) {
fprintf(stderr,"Cannot determine user identity. Program terminated.");
exit(0);
}
(void) chdir(local_auth.homedir);
mail_link(&imapdriver); mail_link(&mboxdriver); mail_link(&bezerkdriver);
mail_link(&tenexdriver); mail_link(&nntpdriver); mail_link(&newsdriver);
mail_link(&pop3driver); mail_link(&mtxdriver); mail_link(&mhdriver);
mail_link(&mmdfdriver); mail_link(&philedriver); mail_link(&dummydriver);
session->connected = TRUE; /* optimistic assumption */
session->connections = 0;
session->address_book = NULL;
session->addresses = NULL;
session->edfilter = NULL;
session->filters = NULL;
session->session_filters = NULL;
session->servers = NULL;
session->mime_handlers = NULL;
session->busy = FALSE;
session->buttonstate = BTN_NOMAILBOXESOPEN;
session->authorizations = NULL;
session->netconf = NULL;
session->mailboxwin = NULL;
session->mailcopywin = NULL;
session->compose = NULL;
session->read = NULL;
session->prefst = NULL;
session->pref2st = NULL;
session->gentext = NULL;
session->update_needed = 0;
session->filter_map = NULL;
session->note = NULL;
session->btn = NULL;
session->header_set = NULL;
session->header_str = NULL;
session->last_command = NULL;
session->last_dir = NULL;
session->mailboxes = NULL;
(void) get_resources(session->shell);
/* Honor the NNTPSERVER variable unless told otherwise. */
if((ptr = getenv("NNTPSERVER")) != NULL)
preferences.nntp_server = cpystr(ptr);
/* Fill in all the language specific structures. */
init_representation();
init_flags();
init_action_and_header_list();
init_logical_view_structures();
/*
* Create a cache directory. Maybe there's already one. If we fail,
* or it doesn't have permissions we can use, complain loudly and die
* horribly.
*/
sprintf(buffer,"%s/%s",local_auth.homedir,MLDATADIR);
(void) mkdir(buffer,S_IRWXU);
if((access(buffer,R_OK|W_OK|X_OK)) != SYSCALL_SUCCESS) {
fprintf(stderr,MLGetLocalized(XtNmsgNoDataDir,MsgNoDataDir),buffer);
exit(1);
}
session->cachedir = cpystr(buffer);
if((load_defaults()) == SYSCALL_FAILURE)
no_prefs = TRUE;
(void) sane_defaults();
if(preferences.authLogin == TRUE)
auth_link(&auth_log);
/* Load these after the preferences, so we know where to look. */
(void) load_mime_types();
(void) load_mime_extension_map();
(void) load_mime_handlers();
/* Initialize the c-client's sense of identity. Ignore results. */
(void) myusername_full(NIL);
display = XtDisplay(session->shell);
make_icons();
(void) create_main_window(mwin);
create_log_window(session->lwin);
(void) create_cursors(display);
if(ml_icon != (Pixmap) None)
XtVaSetValues(session->shell, XmNiconPixmap, ml_icon, NULL);
/*
* For the poor folks on X terminals and PC's who start the
* program as "ml -display {something}" and wonder why their
* attachment handlers and other sub-processes don't work.
*/
sprintf(envstring,"DISPLAY=%s",XDisplayString(display));
(void) putenv(envstring);
/* Sorry, but this one's in English. Period. */
sprintf(buffer,"Welcome to %s, Version %s\n",PROGRAM,MLVERSION);
log_error(buffer, MLNOTIFY);
if(preferences.showLog == FALSE) {
/* show the banner for a couple of seconds and then nuke the log window */
sleep(2);
lwin_dismiss(NULL,session->lwin,NULL);
}
trap_stderr();
/* Debug a quirky locale */
if(getenv("MLDEBUG")) {
fprintf(stderr,"Locale: %s\n",setlocale(LC_ALL, NULL));
fflush(stderr);
}
/* Check for obsolete or missing app-defaults. */
if((preferences.local_defs == FALSE)
&& (preferences.defaults_installed == FALSE))
mm_log(MLGetLocalized(XtNmsgNoDefaults,MsgNoDefaults),WARN);
else {
if((strcmp(preferences.defaults_version,DEFAULTS_VERSION)) != STRMATCH)
mm_log(MLGetLocalized(XtNmsgWrongDefaults,MsgWrongDefaults),WARN);
}
if(preferences.auto_open == TRUE)
auto_open(mwin);
/*************************************************************************
* Main application loop - get and process input forever *
*************************************************************************/
main_loop();
/* NOTREACHED */
}
#ifdef __STDC__
MAILSTREAM *server_to_mailstream(char *server)
#else
MAILSTREAM *server_to_mailstream(server)
char *server;
#endif
{
Mailbox *mailbox;
if((server == NULL) || (*server == NUL_TERM))
return(NULL);
for(mailbox = session->mailboxes; mailbox; mailbox = mailbox->next)
if((strcasecmp(mailbox->host,server)) == STRMATCH)
return(mailbox->mailstream);
return(NULL);
}
/*
* auto_open has to initialize a few things in the mailbox structure
* which would have otherwise been initialized by the mailbox select window.
*/
#ifdef __STDC__
void auto_open(MainWindow *mwin)
#else
void auto_open(mwin)
MainWindow *mwin;
#endif
{
Mailbox *mailbox = new_mailbox();
Boolean new_server = FALSE;
Server_Config *config;
if(*preferences.defaultConfig == NUL_TERM) {
fs_give((void **) &mailbox);
return;
}
config = find_configuration(preferences.defaultConfig);
mailbox->host = cpystr((config->hostname) ? config->hostname : EMPTYSTR);
mailbox->mailboxname = fix_mailboxpath((config->mailbox)
? config->mailbox : INBOX);
mailbox->imapname =
format_mailboxname_server(config,mailbox->mailboxname,MAILBOX_TYPE_MAIL);
mailbox->type = MAILBOX_TYPE_MAIL;
if((mailbox->imapname == NULL) || (*mailbox->imapname == NUL_TERM)) {
free_mailbox(mailbox);
return;
}
mailbox->server = config;
session->active = config;
open_mailbox(mwin, mailbox, new_server);
session->active = NULL;
return;
}
#ifdef __STDC__
void open_mailbox(MainWindow *mwin, Mailbox *mailbox, Boolean new_server)
#else
void open_mailbox(mwin, mailbox, new_server)
MainWindow *mwin;
Mailbox *mailbox;
Boolean new_server;
#endif
{
char log[FILEBUFFLEN];
char popname[FILEBUFFLEN];
Lview *lview;
int total = 0;
long openflags = 0L;
struct stat st;
int fd;
if(preferences.developer_debug == TRUE)
openflags |= OP_DEBUG;
push_cursor(WATCH_CURSOR);
if((mailbox->imapname == NULL) || (*mailbox->imapname == NUL_TERM)) {
free_mailbox(mailbox);
mwin_cancel(mwin);
pop_cursor();
return;
}
/*
* Just in case the mailbox is already open, we'll be nice and close it.
*/
close_invalid_mailbox(mailbox->imapname);
if((session->active != NULL) && (session->active->type == SERVICE_POP)) {
sprintf(popname,"%s/%s/%s.inbox",local_auth.homedir,MLDATADIR,
(session->active->name) ? session->active->name : "" );
if((access(popname,R_OK|W_OK)) != SYSCALL_SUCCESS) {
fd = open(popname,O_CREAT|O_RDWR,0700);
if(fd)
close(fd);
}
mailbox->ispop = TRUE;
}
else
mailbox->ispop = FALSE;
sprintf(log,MLGetLocalized(XtNmsgOpeningMailbox,MsgOpeningMailbox),
mailbox->mailboxname);
mm_log(log,NIL);
if(((mailbox->mailstream =
mail_open(mailbox->mailstream,
(mailbox->ispop) ? popname : mailbox->imapname,
openflags)) == NIL)
|| (mailbox->mailstream->halfopen)) {
if(mailbox->mailstream)
mail_close(mailbox->mailstream);
free_mailbox(mailbox);
mwin_cancel(mwin);
mm_log(MLGetLocalized(XtNmsgOpenFailed,MsgOpenFailed),ERROR);
pop_cursor();
return;
}
mailbox->nmsgs = mailbox->mailstream->nmsgs;
if(session->mailboxes)
session->mailboxes->prev = mailbox;
mailbox->next = session->mailboxes;
session->mailboxes = mailbox;
if(preferences.check_interval)
mailbox->timer =
XtAppAddTimeOut(context,
((unsigned long) preferences.check_interval * 1000L),
(XtTimerCallbackProc) timed_check, mailbox);
else
mailbox->timer = (XtIntervalId) 0;
create_all_lview(mwin,mailbox);
session->buttonstate = BTN_ON;
view_check_buttons();
pop_cursor();
return;
}
#ifdef __STDC__
void check_mailbox(Mailbox *mailbox, Boolean startup)
#else
void check_mailbox(mailbox, startup)
Mailbox *mailbox;
Boolean startup;
#endif
{
MAILSTREAM *popstream = NIL;
char msg[FILEBUFFLEN];
char popname[FILEBUFFLEN];
char sequence[16];
unsigned long i;
unsigned long delta = 0;
if((session->busy == TRUE) && (startup == FALSE))
return;
push_cursor(WATCH_CURSOR);
if(mailbox->ispop) {
session->active = mailbox->server;
if(((popstream = mail_open(popstream,mailbox->imapname,OP_SILENT)) == NIL)
|| (popstream->halfopen))
mail_close(popstream);
else {
sprintf(popname,"%s/%s/%s.inbox",local_auth.homedir,MLDATADIR,
(session->active->name) ? session->active->name : "" );
for(i = 1; i <= popstream->nmsgs; i ++) {
if(((copy_message_to_cachemailbox(popstream,i,popname))
!= SYSCALL_SUCCESS))
break;
delta ++;
if(preferences.keepOnServer == FALSE) {
sprintf(sequence,"%lu",i);
mail_setflag(popstream,sequence,DELETED_FLAG);
}
}
if(delta) {
mail_expunge(popstream);
mail_ping(mailbox->mailstream);
}
mail_close(popstream);
}
session->active = NULL;
}
if(startup == TRUE) {
pop_cursor();
return;
}
if(mail_ping(mailbox->mailstream)) {
if(mailbox->has_new_mail == TRUE) {
get_new_message_info(mailbox);
mailbox->has_new_mail = FALSE;
if(preferences.newMailBeep == TRUE)
XBell(display,1000);
}
if(mailbox->flags_changed != 0L) {
mail_check(mailbox->mailstream);
mailbox->flags_changed = 0L;
}
}
else {
sprintf(msg,MLGetLocalized(XtNmsgLostConnection,MsgLostConnection),
mailbox->host);
mm_log(msg,ERROR);
}
pop_cursor();
return;
}
#ifdef __STDC__
void timed_check(Mailbox *mailbox, XtIntervalId *id)
#else
void timed_check(mailbox,id)
Mailbox *mailbox;
XtIntervalId *id;
#endif
{
unsigned long next_timer;
/*
* We've been called by a timer (or user) to check the mailbox.
* Unfortunately, we might be doing something critical.
* If we are, set the timer interval to a short period (15 seconds)
* so we'll keep coming back until things are free again.
* Otherwise, check the mailbox, and reset to the normal timer interval.
*/
if(session->busy == FALSE) {
check_mailbox(mailbox, FALSE);
next_timer = (unsigned long) preferences.check_interval * 1000L;
}
else
next_timer = (unsigned long) 15000L;
mailbox->timer = XtAppAddTimeOut(context,next_timer,
(XtTimerCallbackProc) timed_check,
mailbox);
return;
}
#ifdef __STDC__
void main_close(Widget w,XtPointer data,XtPointer xp)
#else
void main_close(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
Mailbox *mailbox, *next;
mm_log(MLGetLocalized(XtNmsgClosingAll,MsgClosingAll),NIL);
for(mailbox = session->mailboxes; mailbox ; mailbox = next) {
next = mailbox->next;
close_mailbox(mailbox);
}
session->mailboxes = NULL;
return;
}
#ifdef __STDC__
void close_mailbox(Mailbox *mailbox)
#else
void close_mailbox(mailbox)
Mailbox *mailbox;
#endif
{
Lview *lview;
MainWindow *mwin;
Read *read;
Read_Info *read_info;
Boolean found = FALSE;
char log[FILEBUFFLEN];
char sequence[64];
sprintf(log,
MLGetLocalized(XtNmsgClosingMailbox, MsgClosingMailbox),
mailbox->imapname);
mm_log(log,NIL);
if(mailbox->timer)
XtRemoveTimeOut(mailbox->timer);
mailbox->timer = (XtIntervalId) 0;
if(mailbox->bg_timer)
XtRemoveTimeOut(mailbox->bg_timer);
mailbox->bg_timer = (XtIntervalId) 0;
if(mail_ping(mailbox->mailstream)) {
if((mailbox->type == MAILBOX_TYPE_NEWS)
&& (mailbox->nmsgs > 0L)
&& (mailbox->no_update == FALSE)) {
if(mailbox->nmsgs == 1L)
strcpy(sequence,"1");
else
sprintf(sequence,"1:%lu",(unsigned long) mailbox->nmsgs);
mm_log(MLGetLocalized(XtNmsgUpdatingNewsrc,MsgUpdatingNewsrc),NIL);
mail_setflag(mailbox->mailstream,sequence,DELETED_FLAG);
XmUpdateDisplay(session->shell);
}
mail_check(mailbox->mailstream);
mail_close(mailbox->mailstream);
}
compose_mailbox_close(mailbox->mailstream);
mwin_close_mailbox(mailbox);
if(session->read) {
do {
found = FALSE;
for(read = session->read; read; read = read->next) {
for(read_info = read->read_info; read_info;
read_info = read_info->prev) {
if(read_info->mailstream == mailbox->mailstream) {
if(read_info == read->current)
read_close_kill_current(read->shell,read,NULL);
else
kill_read_info(read_info);
found = TRUE;
}
}
}
} while(found == TRUE);
}
if(mailbox == session->mailboxes)
session->mailboxes = mailbox->next;
if(mailbox->prev)
mailbox->prev->next = mailbox->next;
if(mailbox->next)
mailbox->next->prev = mailbox->prev;
free_mailbox(mailbox);
mailbox = NULL;
if(session->mailboxes == NULL) {
if(session->edfilter && session->edfilter->is_realized)
edfilter_dismiss(NULL, session->edfilter, NULL);
session->buttonstate |=
BTN_NOSELECTION|BTN_NOMAILBOXESOPEN|BTN_NOPREV|BTN_NONEXT;
view_check_buttons();
}
XFlush(display);
return;
}
#ifdef __STDC__
void main_compose(Widget w, XtPointer data, XtPointer xp)
#else
void main_compose(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
(void) compose_message(COMPOSE_NEW, FALSE, NULL, NULL, NULL);
return;
}
#ifdef __STDC__
void main_address_book(Widget w, XtPointer data, XtPointer xp)
#else
void main_address_book(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
(void) create_address_book_window(session->shell);
return;
}
#ifdef __STDC__
void main_note_book(Widget w, XtPointer data, XtPointer xp)
#else
void main_note_book(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
(void) create_note_window();
return;
}
#ifdef __STDC__
void main_logwin(Widget w, XtPointer data, XtPointer xp)
#else
void main_logwin(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
(void) lwin_popup(session->shell, session->lwin, NULL);
return;
}
#ifdef __STDC__
void no_op(Widget w, XtPointer data, XtPointer xp)
#else
void no_op(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
/* globally accessible absolutely useless function */
return;
}
#ifdef __STDC__
void main_help(Widget w, XtPointer data, XtPointer xp)
#else
void main_help(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
help(session->shell,MAINHELPFILE);
return;
}
#ifdef __STDC__
void main_keyboard_help(Widget w, XtPointer data, XtPointer xp)
#else
void main_keyboard_help(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
help(session->shell, KEYBOARDHELPFILE);
return;
}
#ifdef __STDC__
void main_config_help(Widget w, XtPointer data, XtPointer xp)
#else
void main_config_help(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
help(session->shell, MIMEINFOHELPFILE);
return;
}
#ifdef __STDC__
void main_resources_help(Widget w, XtPointer data, XtPointer xp)
#else
void main_resources_help(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
help(session->shell, RESOURCESHELPFILE);
return;
}
#ifdef __STDC__
void main_intl_help(Widget w, XtPointer data, XtPointer xp)
#else
void main_intl_help(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
help(session->shell, INTLHELPFILE);
return;
}
#ifdef __STDC__
void main_version_help(Widget w, XtPointer data, XtPointer xp)
#else
void main_version_help(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
help(session->shell, VERSIONHELPFILE);
return;
}
/*
* End the program. Unless you kill it, or it (shudder) dumps core,
* this is the only way out.
*/
#ifdef __STDC__
void bye(Widget w, XtPointer data, XtPointer xp)
#else
void bye(w,data,xp)
Widget w;
XtPointer data;
XtPointer xp;
#endif
{
if(session->mailboxes)
main_close(w,NULL,NULL);
exit(0);
}
/*
* This is called out of our main loop when something changed during
* a callback. refresh_needed means that the current contents of
* the view window changed; we have to do something because the
* change is visible. update_needed means we have to re-evaluate
* our logical view filters. They may or may not be changed as a
* result.
*/
#ifdef __STDC__
void update_views(void)
#else
void update_views()
#endif
{
Mailbox *mailbox;
for(mailbox = session->mailboxes; mailbox; mailbox = mailbox->next) {
if(mailbox->refresh_needed) {
update_current_view(mailbox);
mailbox->refresh_needed = 0;
}
if(mailbox->update_needed) {
update_logical_views(mailbox,FALSE);
mailbox->update_needed = 0;
}
}
return;
}
/*
* Grab a chunk of messages envelopes in the "background".
* We'll keep doing this at a settable interval until the mailbox
* is completely loaded, or a newsgroup has been pruned.
*/
#ifdef __STDC__
void background_fetch(Mailbox *mailbox, XtIntervalId *id)
#else
void background_fetch(mailbox,id)
Mailbox *mailbox;
XtIntervalId *id;
#endif
{
Boolean result;
unsigned long count;
if(session->busy == FALSE) {
if(mailbox->first_fetch <= 1L) { /* no more to fetch */
update_logical_views(mailbox,TRUE);
mailbox->update_needed = 0;
XtRemoveTimeOut(mailbox->bg_timer);
mailbox->bg_timer = (XtIntervalId) 0;
mm_log(MLGetLocalized(XtNmsgBackgroundDone,MsgBackgroundDone),MLNOTIFY);
return;
}
else { /* more to fetch */
push_cursor(WATCH_CURSOR);
if(mailbox->type == MAILBOX_TYPE_MAIL) {
if(mailbox->first_fetch <= preferences.mail_fetch)
mailbox->first_fetch = 1L;
else
mailbox->first_fetch -= preferences.mail_fetch;
}
else { /* MAILBOX_TYPE_NEWS */
if(mailbox->first_fetch <= preferences.news_fetch)
mailbox->first_fetch = 1L;
else
mailbox->first_fetch -= preferences.news_fetch;
}
count = mailbox->first_fetch;
do {
result = background_fetch_message(mailbox,count, FALSE);
count ++;
} while(result == TRUE);
update_current_view(mailbox);
mailbox->refresh_needed = 0;
if(mailbox->first_fetch <= 1L) { /* We've just gotten the last one */
update_logical_views(mailbox,TRUE);
mailbox->update_needed = 0;
XtRemoveTimeOut(mailbox->bg_timer);
mailbox->bg_timer = (XtIntervalId) 0;
mm_log(MLGetLocalized(XtNmsgBackgroundDone,MsgBackgroundDone),
MLNOTIFY);
pop_cursor();
return;
}
pop_cursor();
}
}
/* Adios for now, but we'll be back. */
mailbox->bg_timer = XtAppAddTimeOut(context,
(mailbox->type == MAILBOX_TYPE_NEWS)
? (preferences.news_background * 1000)
: (preferences.mail_background * 1000),
(XtTimerCallbackProc) background_fetch,
mailbox);
return;
}
/*
* This loop is called from our modal pop-ups -- those that wait
* for you to do something before continuing. The loop is exited
* when the condition (usually an int) becomes non-zero. This usually
* happens when a modal widget gets what it needs and relinquishes
* exclusive control of the keyboard and mouse by killing itself.
* In general we set "pirate" cursors for other windows to indicate
* that they are non-functional until the active window is dismissed.
* Yes, it's awful design strategy, but necessary in this program,
* since something you are doing elsewhere (like expunging messages
* or closing mailboxes) could invalidate the entire state of the
* current data structures.
*/
#ifdef __STDC__
void modal_main_loop (int *exit_condition)
#else
void modal_main_loop (exit_condition)
int *exit_condition;
#endif
{
XEvent event;
while(!(*exit_condition)) {
if(XPending(display)) {
XtAppNextEvent(context, &event);
XtDispatchEvent(&event);
}
}
return;
}
/*
* This is the normal event processing loop. We trigger a logical view update
* through external means, so that functions which are making several changes
* don't have to flash the screen for every change. When the functions exit,
* we'll fall back into this loop, and the update will be triggered. This
* way it's only called once.
*/
#ifdef __STDC__
void main_loop(void)
#else
void main_loop ()
#endif
{
XEvent event;
Mailbox *mailbox;
while(1) {
XtAppNextEvent(context, &event);
XtDispatchEvent(&event);
for(mailbox = session->mailboxes; mailbox ; mailbox = mailbox->next) {
if(mailbox->has_new_mail == TRUE) {
get_new_message_info(mailbox);
mailbox->has_new_mail = FALSE;
if(preferences.newMailBeep == TRUE)
XBell(display,1000);
}
if(mailbox->flags_changed != 0L) {
push_cursor(WATCH_CURSOR);
XFlush(display);
mail_check(mailbox->mailstream);
pop_cursor();
mailbox->flags_changed = 0L;
}
}
if(session->update_needed) {
update_views();
session->update_needed = 0;
}
}
/* NOTREACHED */
}
/*
* Functions to capture the stderr stream from sub-processes
* (or X window messages) and send them to the ML log window.
*/
#ifdef __STDC__
void redirect_stderr(XtPointer client_data, int *fd, XtInputId *id)
#else
void redirect_stderr(client_data, fd, id)
XtPointer client_data;
int *fd;
XtInputId *id;
#endif
{
char buf[FILEBUFFLEN];
int nbytes;
if((nbytes = read(*fd,buf,FILEBUFFLEN - 1)) == (EOF))
return;
buf[nbytes] = NUL_TERM;
if(nbytes)
log_error(buf, MLNOTIFY);
return;
}
#ifdef __STDC__
void trap_stderr(void)
#else
void trap_stderr()
#endif
{
(void) signal(SIGPIPE,SIG_IGN);
if(pipe(errfd))
return;
dup2(errfd[1], fileno(stderr));
close(errfd[1]);
XtAppAddInput(context, errfd[0], (caddr_t) XtInputReadMask,
(XtInputCallbackProc) redirect_stderr, NULL);
return;
}
#ifdef __STDC__
void setup_editres(Widget shell)
#else
void setup_editres(shell)
Widget shell;
#endif
{
#ifndef NO_EDITRES
XtAddEventHandler(shell, (EventMask) 0,
True, _XEditResCheckMessages, NULL );
#endif
}
/*
* Pops the window to the front. De-iconifies it if neccessary first.
*/
#ifdef __STDC__
void de_iconify(Widget shell)
#else
void de_iconify(shell)
Widget shell;
#endif
{
XMapWindow(display,XtWindow(shell));
XRaiseWindow(display,XtWindow(shell));
}
#ifdef __STDC__
Mailbox *find_mailbox_from_mailstream(MAILSTREAM *mailstream)
#else
Mailbox *find_mailbox_from_mailstream(mailstream)
MAILSTREAM *mailstream;
#endif
{
Mailbox *mailbox;
for(mailbox = session->mailboxes; mailbox ; mailbox = mailbox->next)
if(mailbox->mailstream == mailstream)
return(mailbox);
return(NULL);
}
#ifdef __STDC__
void MLDestroyCallback (Widget w, XtPointer data, XtPointer cb)
#else
void MLDestroyCallback (w, data, cb)
Widget w;
XtPointer data;
XtPointer cb;
#endif
{
Widget dismissWidget;
if ((dismissWidget = XtNameToWidget (w, "*dismiss")) != NULL) {
XtCallCallbacks (dismissWidget, XmNactivateCallback, NULL);
}
else
if ((dismissWidget = XtNameToWidget (w, "*cancel")) != NULL) {
XtCallCallbacks (dismissWidget, XmNactivateCallback, NULL);
}
else
if ((dismissWidget = XtNameToWidget (w, "*close_window")) != NULL) {
XtCallCallbacks (dismissWidget, XmNactivateCallback, NULL);
}
else
if ((dismissWidget = XtNameToWidget (w, "*exit")) != NULL) {
XtCallCallbacks (dismissWidget, XmNactivateCallback, NULL);
}
return;
}
#ifdef __STDC__
void AddDestroyCallback (Widget w)
#else
void AddDestroyCallback (w)
Widget w;
#endif
{
Atom wmDestroyWindow = (Atom) NULL;
wmDestroyWindow = XmInternAtom (XtDisplay (w), "WM_DELETE_WINDOW", False);
XmAddWMProtocolCallback (w, wmDestroyWindow, MLDestroyCallback, NULL);
return;
}
#ifdef __STDC__
void MLSaveYourselfCallback (Widget w, XtPointer data, XtPointer cb)
#else
void MLSaveYourselfCallback (w, data, cb)
Widget w;
XtPointer data;
XtPointer cb;
#endif
{
XSetCommand(XtDisplay (w), XtWindow (w), Argv, Argc);
return;
}
#ifdef __STDC__
void AddSaveYourselfCallback (Widget w)
#else
void AddSaveYourselfCallback (w)
Widget w;
#endif
{
Atom wmSaveYourself = (Atom) NULL;
wmSaveYourself = XmInternAtom (XtDisplay (w), "WM_SAVE_YOURSELF", False);
XmAddWMProtocolCallback (w, wmSaveYourself, MLSaveYourselfCallback,NULL);
}
#ifdef __STDC__
Boolean CheckConnection(void)
#else
Boolean CheckConnection()
#endif
{
FILE *fp;
int result;
if((preferences.netCheckCommand != NULL)
&& (*preferences.netCheckCommand != NUL_TERM)) {
if((fp = popen(preferences.netCheckCommand,"r")) != NULL) {
result = pclose(fp);
if(result) {
session->connected = FALSE;
return(FALSE);
}
}
}
session->connected = TRUE;
return(TRUE);
}
syntax highlighted by Code2HTML, v. 0.9.1