2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
26 * $TOG: RoamApp.C /main/62 1999/09/14 16:52:18 mgreess $
28 * RESTRICTED CONFIDENTIAL INFORMATION:
30 * The information in this document is subject to special
31 * restrictions in a confidential disclosure agreement between
32 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
33 * document outside HP, IBM, Sun, USL, SCO, or Univel without
34 * Sun's specific written approval. This document and all copies
35 * and derivative works thereof must be returned or destroyed at
38 * Copyright 1993,1994,1995 Sun Microsystems, Inc. All rights reserved.
43 * Common Desktop Environment
45 * (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
46 * (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
47 * (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
48 * (c) Copyright 1993, 1994, 1995 Novell, Inc.
49 * (c) Copyright 1995 Digital Equipment Corp.
50 * (c) Copyright 1995 Fujitsu Limited
51 * (c) Copyright 1995 Hitachi, Ltd.
54 * RESTRICTED RIGHTS LEGEND
56 *Use, duplication, or disclosure by the U.S. Government is subject to
57 *restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
58 *Technical Data and Computer Software clause in DFARS 252.227-7013. Rights
59 *for non-DOD U.S. Government Departments and Agencies are as set forth in
60 *FAR 52.227-19(c)(1,2).
62 *Hewlett-Packard Company, 3000 Hanover Street, Palo Alto, CA 94304 U.S.A.
63 *International Business Machines Corp., Route 100, Somers, NY 10589 U.S.A.
64 *Sun Microsystems, Inc., 2550 Garcia Avenue, Mountain View, CA 94043 U.S.A.
65 *Novell, Inc., 190 River Road, Summit, NJ 07901 U.S.A.
66 *Digital Equipment Corp., 111 Powdermill Road, Maynard, MA 01754, U.S.A.
67 *Fujitsu Limited, 1015, Kamikodanaka Nakahara-Ku, Kawasaki 211, Japan
68 *Hitachi, Ltd., 6, Kanda Surugadai 4-Chome, Chiyoda-ku, Tokyo 101, Japan
73 #if defined(linux) || defined(CSRG_BASED)
78 #ifdef DTMAIL_TOOLTALK
81 #include "SendMsgDialog.h"
84 #if defined(POSIX_THREADS)
91 #include <sys/param.h>
95 #include <Xm/MessageB.h>
97 #include <Dt/Action.h>
99 #include <Dt/DtPStrings.h>
101 #include <Dt/EnvControlP.h>
103 #include <DtMail/Common.h>
104 #include <DtMail/DtMailError.hh>
105 #include <DtMail/DtMailSigChld.h>
106 #include <DtMail/IO.hh>
107 #include <DtMail/OptCmd.h>
109 #include "DmxPrintJob.h"
110 #include "DtMailGenDialog.hh"
111 #include "DtMailHelp.hh"
112 #include "EUSDebug.hh"
114 #include "MemUtils.hh"
117 #include "RoamMenuWindow.h"
118 #include "RoamCmds.h"
119 #include "SendMsgDialog.h"
120 #include "WorkingDialogManager.h"
123 int use_XmTextEditor = 0;
127 // Provide interface to the DtSvc function DtSimpleError
128 // When this interface is better defined, this can be removed
129 // and replaced with the appropriate include file
140 extern "C" void _DtSimpleError(
148 extern "C" int _DtPrintDefaultErrorSafe(
154 static int x_error_handler(Display *display, XErrorEvent* error_event)
156 #define _DTMAIL_BUFSIZE 1024
157 char error_msg[_DTMAIL_BUFSIZE];
160 _DtPrintDefaultErrorSafe(display, error_event, error_msg, _DTMAIL_BUFSIZE);
161 _DtSimpleError("dtmail", DtWarning, NULL, error_msg, NULL);
163 // if the error occurred on the print display we're going to set
164 // a variable so that and when the job is done, right before calling
165 // XpEndJob, we call XpCancelJob, and notify the user.
167 if (theRoamApp.isActivePrintDisplay(display) &&
168 error_event->error_code == BadAlloc)
170 theRoamApp.setErrorPrintDisplay(display);
174 theRoamApp._default_x_error_handler(display, error_event);
184 XWindowAttributes xwa;
186 XtAppContext cxt=XtWidgetToApplicationContext( w );
190 dpy=XtDisplay(shell);
191 window=XtWindow( shell );
193 while ( XGetWindowAttributes(dpy,window,&xwa)) {
194 if ( XGetWindowAttributes( dpy, window, &xwa ) &&
195 xwa.map_state != IsViewable )
198 XtAppNextEvent( cxt, &event );
199 XtDispatchEvent( &event );
201 XmUpdateDisplay(shell);
205 forceUpdate( Widget w )
207 Widget diashell, topshell;
208 Window diawindow, topwindow;
209 XtAppContext cxt = XtWidgetToApplicationContext( w );
211 XWindowAttributes xwa;
214 for (diashell=w;!XtIsShell(diashell);diashell=XtParent(diashell));
215 for ( topshell=diashell;XtIsTopLevelShell( topshell );
216 topshell = XtParent( topshell ) );
218 dpy=XtDisplay(diashell);
219 diawindow=XtWindow( diashell );
220 topwindow=XtWindow(topshell);
221 while ( XGetWindowAttributes(dpy,diawindow,&xwa)
222 && XEventsQueued( dpy, QueuedAlready) ) {
224 XtAppNextEvent( cxt, &event );
225 XtDispatchEvent( &event );
227 XmUpdateDisplay(topshell);
231 RoamApp::_resources[] = {
237 XtOffset ( RoamApp *, _print_script ),
246 XtOffset ( RoamApp *, _mailfiles_folder ),
255 XtOffset ( RoamApp *, _default_mailbox ),
266 XtOffset ( RoamApp *, _user_font ),
268 ( XtPointer )"-b&h-lucidatypewriter-medium-r-*-sans-*-120-*-*-*-*-*-*",
271 // Fixed width fontlist
276 sizeof( XmFontList ),
277 XtOffset ( RoamApp *, _user_fontlist ),
279 ( XtPointer )"-b&h-lucidatypewriter-medium-r-*-sans-*-120-*-*-*-*-*-*",
282 // Variable width font
288 XtOffset ( RoamApp *, _system_font ),
290 ( XtPointer )"-b&h-lucida-medium-r-*-sans-*-120-*-*-*-*-*-*"
293 // Variable width fontlist
298 sizeof( XmFontList ),
299 XtOffset ( RoamApp *, _system_fontlist ),
301 ( XtPointer )"-b&h-lucida-medium-r-*-sans-*-120-*-*-*-*-*-*"
304 // Font used for attachment glyph
310 XtOffset ( RoamApp *, _glyph_font ),
318 RoamApp theRoamApp("Dtmail");
319 int just_compose = 0;
324 theRoamApp.quitSilently();
325 theRoamApp.closeAllWindows();
330 panicQuitSignalHandler()
332 panicQuitSignalHandler(int)
335 theRoamApp.setQuitQuickly();
336 theRoamApp.setQuitSilently();
337 theRoamApp.closeAllWindows();
342 RoamApp::closeAllWindows(void)
344 // Remove callbacks to prevent XtPhase2Destroy crashes.
345 XtRemoveAllCallbacks(baseWidget(), XmNdestroyCallback);
347 for (int win = 0; win < _numWindows; win++)
349 _windows[win]->panicQuit();
350 else if (quitSilently())
351 _windows[win]->quit();
353 _windows[win]->quit();
359 RoamApp::statusCallback(DtMailOperationId, DtMailEnv &error, void *)
362 // fprintf(stderr, "DEBUG: statusCallback(): Submission failed error = %d\n", error._major);
364 // fprintf(stderr, "DEBUG: statusCallback(): Submission done.%s\n");
368 #ifdef DTMAIL_TOOLTALK
370 int started_by_tt = 0;
371 // Move this to constructor of RoamMenuWindow???
372 int dtmail_mapped = 0; // For explanation, look in RoamApp.h.
373 static int roam_tt_fd = 0;
374 char *roam_tt_procid = NULL;
375 Tt_pattern *roam_tt_pattern = NULL;
377 // Report ToolTalk error
378 int dieFromTtError(Tt_status errid, char *procname, char *errmsg, char *helpid)
380 /* Do not die on warnings or TT_OK */
381 if ( tt_is_err(errid) )
383 char *title = GETMSG(DT_catd, 2, 1, "Mailer");
384 char *errmsg = tt_status_message(errid);
391 GETMSG(DT_catd, 2, 30, "%s returned ToolTalk error: %s\n"),
392 procname, tt_status_message(errid));
394 DtMailGenDialog *exit_dialog = new DtMailGenDialog(
396 theApplication->baseWidget());
397 exit_dialog->setToErrorDialog(title, errmsg);
398 if (NULL == helpid) helpid = DTMAILHELPERROR;
399 exit_dialog->post_and_return(GETMSG(DT_catd, 1, 1, "OK"), helpid);
401 XtRemoveAllCallbacks(theApplication->baseWidget(), XmNdestroyCallback);
407 Tt_message attachmt_msg_handler(
412 unsigned char *contents,
417 static const char *thisFcn = "attachmt_msg_handler()";
418 Tt_status status = TT_OK;
420 SendMsgDialog *compose;
422 if ( diag != TT_OK ) {
423 // Toolkit detected an error
424 // Let toolkit handle error
428 pattern = ttdt_message_accept(msg, NULL, (Widget)0, client_data, 1, 1);
429 dieFromTtError(tt_ptr_error(pattern),
430 "attachmt_msg_handler.ttdt_message_accept", NULL, NULL);
432 if ( op == TTME_MAIL_EDIT ) {
433 status = tt_message_reply(msg);
434 dieFromTtError(status,
435 "attachmt_msg_handler.tt_message_reply", NULL, NULL);
437 // Put the data that is coming in (via buffer or file) as
438 // the attachment of a message.
439 if ( len > 0 ) { // Pass by content
440 compose = theCompose.getWin();
441 compose->inclAsAttmt(contents, len, docname);
443 compose->setTitle(docname);
444 compose->setIconTitle(docname);
446 } else if ( file != NULL ) { // Pass by filename
447 compose = theCompose.getWin();
448 compose->inclAsAttmt(file, docname);
450 compose->setTitle(docname);
451 compose->setIconTitle(docname);
453 } else { // DO NOTHING.
454 // This is not an entry point to bring up a blank compose window
455 // because ttMediaLoadPatCB() returns with diagnosis =
456 // TT_DESKTOP_ENODATA. For INOUT mode, it expects file or buffer.
459 status = tttk_message_fail( msg, TT_DESKTOP_ENOTSUP, 0, 1 );
460 dieFromTtError(status,
461 "tooltalk_msg_handler.tttk_message_fail", NULL, NULL);
465 // Not sure if these should be freed.
467 // tt_free( (caddr_t)contents );
469 // tt_free( docname );
474 typedef struct _msg_handler_done_cb_struct
478 RoamMenuWindow *roamWin;
480 } MsgHandlerDoneCbData;
483 tooltalk_msg_handler_done_cb( Widget w, XtPointer client_data, XtPointer )
485 MsgHandlerDoneCbData *cbData = (MsgHandlerDoneCbData *) client_data;
486 Tt_status status = TT_OK;
488 status = tt_message_reply(cbData->msg);
489 dieFromTtError(status,
490 "tooltalk_msg_handler_done_cb.tt_message_reply", NULL, NULL);
494 XtNdestroyCallback, tooltalk_msg_handler_done_cb,
497 cbData->roamApp->unregisterPendingTask();
498 if (NULL != cbData->roamWin)
500 cbData->roamWin->quit(TRUE);
501 delete cbData->roamWin;
503 XtFree((char*) cbData);
506 static char *tooltalk_save_buffer_to_file(
507 unsigned char *contents,
511 char *tmpdir = new char[MAXPATHLEN+1];
513 // 1. Get buffer content into file.
514 snprintf(tmpdir, MAXPATHLEN+1, "%s/%s", getenv("HOME"), DtPERSONAL_TMP_DIRECTORY);
515 p = tempnam(tmpdir, "mail");
522 int fd = SafeOpen(p, O_RDWR | O_CREAT);
529 if (SafeWrite(fd, contents, len) != len)
541 tooltalk_msg_handler(
546 unsigned char *contents,
552 static const char *thisFcn = "RoamApp::tooltalk_msg_handler()";
553 Tt_status status = TT_OK;
554 SendMsgDialog *compose;
555 RoamApp *roamapp = (RoamApp *) client_data;
558 if ( diag != TT_OK ) {
559 // toolkit detected an error
560 // Let toolkit handle error
564 // Need to check the return value of this call.
566 pattern = ttdt_message_accept(msg, NULL, (Widget)0, client_data, 1, 1);
567 dieFromTtError(tt_ptr_error(pattern),
568 "tooltalk_msg_handler.ttdt_message_accept", NULL, NULL);
570 if ( op == TTME_MAIL ) {
572 status = tt_message_reply(msg);
573 dieFromTtError(status,
574 "tooltalk_msg_handler.tt_message_reply", NULL, NULL);
576 // Construct message handle
579 mbuf.buffer = (void *)contents;
580 mbuf.size = (unsigned long)len;
581 } else if ( file != NULL ) {
582 // 1. Get file content into buffer.
583 int fd = SafeOpen(file, O_RDONLY);
588 if (SafeFStat(fd, &buf) < 0) {
593 mbuf.buffer = new char[buf.st_size];
599 if (SafeRead(fd, mbuf.buffer,
600 (unsigned int) buf.st_size) != buf.st_size) {
601 delete [] mbuf.buffer;
605 mbuf.size = (unsigned long)buf.st_size;
608 DtMail::Session *d_session = theRoamApp.session()->session();
609 DtMail::Message *msgHandle = d_session->messageConstruct(
616 if ( error.isSet() || !msgHandle ) {
621 theRoamApp.default_transport()->submit(error, msgHandle,
622 (DtMailBoolean)FALSE);
624 } else if ( op == TTME_MAIL_COMPOSE ) {
625 // Bring up blank compose window.
626 status = tt_message_reply(msg);
627 dieFromTtError(status,
628 "tooltalk_msg_handler.tt_message_reply", NULL, NULL);
630 compose = theCompose.getWin();
632 compose->setTitle(docname);
633 compose->setIconTitle(docname);
635 } else if ( op == TTME_MAIL_EDIT ) {
636 // Bring up compose window with given data filled in.
637 status = tt_message_reply(msg);
638 dieFromTtError(status,
639 "tooltalk_msg_handler.tt_message_reply", NULL, NULL);
641 // Parse data (coming in as buffer or file)
642 if ( len > 0 ) { // Pass by content
643 compose = theCompose.getWin();
644 compose->parseNplace((char *)contents, len);
646 compose->setTitle(docname);
647 compose->setIconTitle(docname);
649 } else if ( file != NULL ) { // Pass by filename
650 compose = theCompose.getWin();
651 compose->parseNplace(file);
653 compose->setTitle(docname);
654 compose->setIconTitle(docname);
658 // This is not an entry point to bring up a blank compose window
659 // because ttMediaLoadPatCB() returns with diagnosis =
660 // TT_DESKTOP_ENODATA. For INOUT mode, it expects file or buffer.
662 } else if ( op == TTME_DISPLAY ) {
664 char *opname = tt_message_op(msg);
666 // It is the Display message.
667 // Since the compose window can be started independent of
668 // RoamMenuWindow, a DtMail process may be around
669 // (because of a compose window). Then if a DtMail process
670 // exists (ToolTalk will not start another DtMail process),
671 // that process needs to respond to this DISPLAY message.
672 // If for some reason, the view of the specified mail folder
673 // is unmapped, then need to map it. Otherwise, create the
674 // view for the specified mail folder. Need to remove self
675 // destruct when using an existing DtMail process if that
676 // process was started by compose.
678 // This is the wrong place to reply to this message.
679 // Replying here causes the action layer to think that
680 // it is ok to remove the file it passed in, but we
681 // are not done with it yet. Calling tt_message_reply
682 // at the end of this function doesn't work either. We
683 // are just not going to reply to this tooltalk message
684 // (tooltalk folks say this is ok) for the time being.
685 if (! strcmp("Display", opname)) {
686 MailSession *ses = theRoamApp.session();
687 RoamMenuWindow *roamwin = NULL;
689 if ( theApplication == NULL ) {
691 fprintf(stdout, "%s: theApplication is NULL\n", thisFcn);
697 fprintf(stdout, "%s: TTME_DISPLAY\n", thisFcn);
700 if ( theCompose.getTimeOutId() != 0 )
701 XtRemoveTimeOut(theCompose.getTimeOutId());
706 DtMailEnv mail_error;
707 DtMailObjectSpace space;
708 DtMail::Session *d_session = theRoamApp.session()->session();
710 char *str = (char*) malloc(len + 1);
712 memcpy(str, contents, len);
715 if (0 == strcmp("DTMAIL_INBOX", str))
718 d_session->queryImpl(
720 d_session->getDefaultImpl(mail_error),
721 DtMailCapabilityInboxName,
730 file = tooltalk_save_buffer_to_file(contents, len);
731 if (NULL == file) return msg;
735 // Check to see if the mbox is already open. If it is, we will
736 // simply make sure it's displayed in the current workspace.
737 if (ses->isMboxOpen(file))
740 roamwin = ses->getRMW(file);
741 ses->activateRMW(roamwin);
742 if (NULL != roamwin) roamwin->displayInCurrentWorkspace();
746 roamwin = new RoamMenuWindow(file);
747 roamwin->initialize();
751 MsgHandlerDoneCbData *cbData;
753 cbData = (MsgHandlerDoneCbData*)
754 XtMalloc(sizeof(MsgHandlerDoneCbData));
756 cbData->roamApp = roamapp;
757 cbData->roamWin = NULL;
758 XtAddCallback(roamwin->GetMainWin(),
760 tooltalk_msg_handler_done_cb,
762 roamapp->registerPendingTask();
764 // Set this to True so Self_destruct()
765 // would not be started by Compose.
767 } else if (! strcmp("Print", opname)) {
771 p = tooltalk_save_buffer_to_file(contents, len);
772 if (NULL == p) return msg;
773 } else if (file != NULL) {
780 MsgHandlerDoneCbData *cbData = NULL;
782 DmxPrintJob *pjob = NULL;
783 RoamMenuWindow *roamwin = NULL;
784 MailSession *ses = theRoamApp.session();
787 (MsgHandlerDoneCbData*) XtMalloc(sizeof(MsgHandlerDoneCbData));
788 if (ses->isMboxOpen(file))
791 roamwin = ses->getRMW(file);
792 ses->activateRMW(roamwin);
793 if (NULL != roamwin) roamwin->displayInCurrentWorkspace();
795 cbData->roamWin = NULL;
799 roamwin = new RoamMenuWindow(file);
800 roamwin->initialize();
802 roamwin->list()->select_all_and_display_last(error);
804 cbData->roamWin = roamwin;
807 pjob = new DmxPrintJob(p, DTM_FALSE, (MainWindow*) roamwin);
810 cbData->roamApp = roamapp;
811 XtAddCallback(pjob->baseWidget(),
813 tooltalk_msg_handler_done_cb,
815 roamapp->registerPendingTask();
819 MainWindow *mw = roamapp->defaultStatusWindow();
822 char *buf = new char[1024];
823 sprintf(buf, "Printing %s", p);
828 status = tt_message_reply(msg);
829 dieFromTtError(status,
830 "tooltalk_msg_handler.tt_message_reply", NULL, NULL);
834 status = tttk_message_fail( msg, TT_DESKTOP_ENOTSUP, 0, 1 );
835 dieFromTtError(status,
836 "tooltalk_msg_handler.tttk_message_fail", NULL, NULL);
839 // tt_free( (caddr_t)contents );
841 // tt_free( docname );
846 quit_message_cb(Tt_message m,
850 static const char *thisFcn = "quit_message_cb()";
854 // int mark = tt_mark();
856 char *op = tt_message_op(m);
857 if ( tttk_string_op(op) == TTDT_QUIT ) {
860 status = tt_message_arg_ival(m, 0, &silent);
861 if ( status != TT_OK ) {
862 fprintf(stderr, "DEBUG: %s: tt_message_arg_ival(0): %s\n",
863 thisFcn, tt_status_message(status));
870 status = tt_message_arg_ival(m, 1, &force);
871 if ( status != TT_OK ) {
872 fprintf(stderr, "DEBUG: %s: tt_message_arg_ival(1): %s\n",
873 thisFcn, tt_status_message(status));
880 RoamApp *app = (RoamApp *)client_data;
881 // Need to make the following call; otherwise, will
882 // run into Phase2Destroy
883 XtRemoveAllCallbacks(app->baseWidget(),
897 reload_notify_cb(XtPointer)
899 DebugPrintf(2, "reload_notify_cb: Reloading types database\n");
902 #endif /* DTMAIL_TOOLTALK */
909 int pid = (int) wait(&status);
911 ChildExitNotify(pid, status);
913 #endif /* DEAD_WOOD */
916 void pspace_signal( int )
918 Widget parent=theApplication->baseWidget();
921 DtMailGenDialog *genDialog = new DtMailGenDialog("Dialog",parent);
923 char *errMsg = (char *) XtCalloc(1,10240);
925 // Serious error here -- No Space on Filesystem --
926 sprintf(errMsg,"Insufficient paging space, \n Mailer cannot perform any operations.\n Please contact the System Administrator to \n correct the paging space problem ");
927 genDialog->setToErrorDialog(
928 GETMSG(DT_catd, 1, 6, "Mailer"),
932 genDialog->post_and_return(
933 GETMSG(DT_catd, 3, 9, "OK"),
938 printf("Insufficient paging space, \n Mailer cannot perform any operations.\n Please contact the System Administrator to \n correct the paging space problem ");
945 Usage(char *progname)
947 printf("Usage: %s\n", progname);
948 printf("[-h] Help\n");
949 printf("[-c] A blank compose window comes up.\n");
950 printf("[-a file1 ... fileN] Compose window comes up with file1 through fileN as attachments.\n");
951 printf("[-f mailfile] The specified mail folder is displayed instead of INBOX.\n");
952 printf("[-l] Start the compose window on a dead letter file.\n");
954 // There is also a "-e" option which would run dtmail with the XmTextEditor
955 // instead of DtEditor. Right now it is an undocumented feature.
958 nl_catd DT_catd = (nl_catd) -1; // catgets file descriptor
960 #if defined(reallyoldsun)
961 #define SA_HANDLER_TYPE void (*)(void)
963 #define SA_HANDLER_TYPE void (*)(int)
966 void RoamApp::initialize(int *argcp, char **argv)
969 struct sigaction *action;
970 struct sigaction action_buf;
974 _firstSaveYourselfArrived = FALSE;
976 _optionsHandle = NULL;
977 _quitSilently = FALSE;
978 _quitQuickly = FALSE;
979 _shutdownWorkprocID = 0;
982 char * mail_file = NULL;
983 char * dead_letter = NULL;
984 char *session_file = NULL;
989 signal(SIGUSR1, (void(*)(int ...))SigUsr1);
991 signal(SIGUSR1, SigUsr1);
995 (void)signal( SIGDANGER, pspace_signal );
998 action = &action_buf;
999 memset((void*) action, 0, sizeof(struct sigaction));
1000 action->sa_handler = (SA_HANDLER_TYPE) panicQuitSignalHandler;
1001 action->sa_flags = 0;
1002 sigaction(SIGHUP, action, NULL);
1003 sigaction(SIGINT, action, NULL);
1004 sigaction(SIGQUIT, action, NULL);
1005 sigaction(SIGILL, action, NULL);
1006 sigaction(SIGABRT, action, NULL);
1007 sigaction(SIGBUS, action, NULL);
1008 sigaction(SIGSEGV, action, NULL);
1009 sigaction(SIGTERM, action, NULL);
1011 // Must be called before XtAppInitialize.
1012 XtSetLanguageProc(NULL, NULL, NULL);
1014 // Set up environment variable (including NLSPATH) before calling
1015 // XtAppInitialize() (cmvc 6576).
1016 _DtEnvControl (DT_ENV_SET);
1018 // This will take care of standard arguments such as -display.
1019 Application::initialize(argcp,argv);
1021 // If -session arg is present remove it and return session file name.
1022 session_file = parseSessionArg(argcp, argv);
1024 // export display and locale settings
1026 static char displayenv[256]; /* Needs to be static for putenv */
1027 sprintf(displayenv, "DISPLAY=%s", XDisplayString(_display));
1030 // Process dtmail opt args.
1032 int num_legit_args = 0;
1034 while((opt = getopt(*argcp, argv, "a:cef:hl:t")) != EOF) {
1046 use_XmTextEditor = 1;
1051 mail_file = strdup(optarg);
1058 dead_letter = optarg;
1062 // Started by ToolTalk
1071 // Remove cbs else face Phase2Destroy!
1072 XtRemoveAllCallbacks(baseWidget(), XmNdestroyCallback);
1079 if(!just_compose && !started_by_tt && !mail_file && session_file)
1080 openSessionFile(session_file); // Open the session file
1083 getResources( _resources, XtNumber ( _resources ) );
1085 DtInitialize(XtDisplay(baseWidget()), baseWidget(), argv[0], "Dtmail");
1087 // Must be called after XtSetLanguageProc and DtInitialize because
1088 // DtInitialize sets the environment variable NLSPATH which is used
1089 // in catopen(). That's why we have to take out catopen from
1090 // Application::initialize and put a new mathod open->catalog for
1091 // both Application and RoamApp
1092 this->open_catalog();
1094 // Initialize the mail_error. This also has to be done after DtInitialize
1095 // because the DtMailEnv consturctor calls catopen as well.
1096 DtMailEnv mail_error;
1102 // Some of the scrolling lists contain formatted text and thus
1103 // require a fixed width font to display the text correctly.
1104 // We want to use the fixed width font defined by dt.userFont as
1105 // it will be internationalized correctly. If it is not there
1106 // we fall back to a fixed width lucida font. If that fails
1107 // we let the widget fallback to what ever it thinks is best.
1110 // Default font in case we can't find anything else.
1111 XrmDatabase db = XtScreenDatabase(XtScreen(baseWidget()));
1115 char *buf = new char[1024];
1118 // Need to check fixed width font mailrc variable. Assume
1123 XrmPutStringResource(
1124 &db, "*Work_Area*XmText.fontList", _user_font);
1125 XrmPutStringResource(
1126 &db, "*Work_Area*XmTextField.fontList", _user_font);
1128 XrmPutStringResource(
1129 &db, "*Work_Area*DtEditor.textFontList", _user_font);
1130 XrmPutStringResource(
1131 &db, "*Work_Area*iconGadget.fontList", _user_font);
1132 XrmPutStringResource(
1133 &db, "*XmDialogShell*XmList.FontList", _user_font);
1135 // Convert the user fontlist to a font.
1136 if (!fontlist_to_font(_user_fontlist, &userfont)) {
1137 if (!(userfont.f.cf_font = XLoadQueryFont(
1138 XtDisplay(baseWidget()),
1140 /* Couldn't convert the user fontlist to a font */
1143 "RoamApp::initialize : error loading fixed font\n");
1145 userfont.cf_type = XmFONT_IS_FONT;
1150 FontType systemfont;
1152 XrmPutStringResource(
1153 &db, "*Work_Area*Text*fontList", _system_font);
1154 XrmPutStringResource(
1155 &db, "*Work_Area*iconGadget*fontList", _system_font);
1156 XrmPutStringResource(
1157 &db, "*Work_Area*Text*textFontList", _system_font);
1158 XrmPutStringResource(
1159 &db, "*XmDialogShell*XmList*FontList", _system_font);
1161 if (!fontlist_to_font(_system_fontlist, &systemfont)) {
1162 /* Couldn't convert the system fontlist to a font */
1163 if (!(systemfont.f.cf_font = XLoadQueryFont(
1164 XtDisplay(baseWidget()),
1168 "RoamApp::initialize : error loading variable font\n");
1170 systemfont.cf_type = XmFONT_IS_FONT;
1176 // If the glyph font is specified in a resource file, use it.
1178 _glyph_name = XtNewString(_glyph_font);
1182 // If the glyph font hasn't been specified, try to match it with
1185 // Get the font name that matches the user font pixel size.
1186 load_app_font(baseWidget(), &userfont, &_glyph_name);
1189 // Create a fontlist that contains the glyph and user fonts
1190 strcpy(buf, _user_font);
1192 // Never refer to the "plain" tag so dont add it.
1193 if (strchr(_user_font, '=') == NULL) {
1195 strcat(buf, "=plain, ");
1198 // If the symbol font can't be found, use user font above
1201 strcat(buf, _glyph_name);
1202 strcat(buf, "=attach");
1205 // Loosely bind font to message list. This lets users override
1206 // with a more strongly bound name (ie "Dtmail*Message_List*FontList");
1208 // Matches the MsgScrollingList in the RoamMenuWindows.
1209 XrmPutStringResource(&db, "*Message_List*FontList", buf);
1212 // Matches the UndelMsgScrollingList in the UndelFromListDialog
1213 // and overrides the "*XmDialogShell*XmList*FontList" spec above.
1214 XrmPutStringResource(&db, "*XmDialogShell*Message_List*FontList", buf);
1219 // If we don't have a mail file yet, then we need to retrieve the
1220 // Initialize Tooltalk
1221 // NOTE: For now, must make the FIRST ttdt_open call to be the proc_id
1222 // that will respond to the start message. Therefore, call gui's
1223 // ttdt_open before libDtMail calls its.
1226 sess = (char *)getenv("TT_SESSION");
1227 if (!sess || (*sess == '\0')) {
1228 sess = getenv("_SUN_TT_SESSION");
1230 if (!sess || (*sess == '\0')) {
1231 tt_default_session_set(tt_X_session(XDisplayString(_display)));
1234 roam_tt_procid = ttdt_open( &roam_tt_fd, "DTMAIL", "SunSoft", "%I", 1 );
1235 dieFromTtError(tt_ptr_error(roam_tt_procid),
1236 "initialize.ttdt_open",
1237 GETMSG(DT_catd, 2, 2, "ToolTalk is not initialized. Mailer cannot run without ToolTalk.\nTry starting /usr/dt/bin/dtsession, or contact your System Administrator."),
1238 DTMAILHELPCANTINITTOOLTALK);
1240 // This is for supporting old ptype where RFC_822_Message is
1242 status = ttmedia_ptype_declare( "RFC_822_Message",
1244 tooltalk_msg_handler,
1247 dieFromTtError(status,
1248 "initialize.ttmedia_ptype_declare.RFC_822_Message", NULL, NULL);
1250 status = ttmedia_ptype_declare( "RFC_822_MESSAGE",
1252 tooltalk_msg_handler,
1255 dieFromTtError(status,
1256 "initialize.ttmedia_ptype_declare.RFC_822_MESSAGE", NULL, NULL);
1258 status = ttmedia_ptype_declare( "MAIL_TYPE",
1260 attachmt_msg_handler,
1263 dieFromTtError(status,
1264 "initialize.ttmedia_ptype_declare.MAIL_TYPE", NULL, NULL);
1266 /* Join the default session -- This should have been done by default */
1267 roam_tt_pattern = ttdt_session_join(
1269 (Ttdt_contract_cb)quit_message_cb,
1270 baseWidget(), this, 1);
1271 dieFromTtError(tt_ptr_error(roam_tt_pattern),
1272 "initialize.ttdt_session_join", NULL, NULL);
1274 _mail_session = new MailSession(mail_error, Application::appContext());
1275 if (mail_error.isSet()) {
1276 // what do we do here? there are no windows for dialogs
1277 // should we just register a syslog() and exit? ugggh
1279 fprintf(stderr, "RoamApp::initialize : error creating MailSession\n");
1284 // .mailrc parsing error checking
1286 DtMail::Session * d_session = _mail_session->session();
1287 DtMail::MailRc* mailRc = d_session->mailRc(mail_error);
1288 DTMailError_t pErr = mailRc->getParseError();
1289 if (pErr != DTME_NoError) {
1291 DtMailGenDialog *mailrc_dialog = new DtMailGenDialog(
1293 theApplication->baseWidget());
1294 mailrc_dialog->setToQuestionDialog(
1295 GETMSG(DT_catd, 2, 1, "Mailer"),
1296 GETMSG(DT_catd, 2, 22,
1297 "There were unrecoverable syntax errors found in the ~/.mailrc file.\nCheck for more messages on terminal. Fix the errors and restart dtmail.\nIf you choose to continue you will not be able to save any changes made\nin the options dialog to file.") );
1298 helpId = DTMAILHELPERROR;
1299 answer = mailrc_dialog->post_and_return(
1300 GETMSG(DT_catd, 2, 23, "Continue"),
1301 GETMSG(DT_catd, 2, 24, "Exit"),
1304 XtRemoveAllCallbacks(
1305 theApplication->baseWidget(),
1306 XmNdestroyCallback);
1313 // Check if mailer is installed properly if we are not in debugging mode.
1315 const char *value = NULL;
1317 d_session->mailRc(mail_error)->getValue(mail_error,
1318 "__ignore_group_permissions",
1320 if (mail_error.isSet()) {
1324 theApplication->enableGroupPrivileges();
1325 GetGroupName(grp_name);
1326 theApplication->disableGroupPrivileges();
1327 if (strcmp(grp_name, DTMAIL_DEFAULT_CREATE_MAILGROUP))
1328 mail_error.setError(DTME_BadRunGroup);
1331 if ((DTMailError_t)mail_error == DTME_BadRunGroup) {
1335 DtMailGenDialog *install_errDialog =
1336 new DtMailGenDialog("Dialog", theApplication->baseWidget());
1337 sprintf(buf, "%s", GETMSG(DT_catd, 2, 4,
1338 "Mailer has not been properly installed,\n\
1339 and cannot run because the execution group\n\
1340 is incorrectly set."));
1342 install_errDialog->setToErrorDialog(
1343 GETMSG(DT_catd, 1, 6, "Mailer"),
1346 // No choice at this state other than to OK.
1347 helpId = DTMAILHELPBADGROUPID;
1348 answer = install_errDialog->post_and_return(
1349 GETMSG(DT_catd, 3, 9, "OK"),
1351 XtRemoveAllCallbacks(
1352 theApplication->baseWidget(),
1353 XmNdestroyCallback);
1359 free((void*) value);
1361 _options = new OptCmd("Mail Options...",
1362 GETMSG(DT_catd, 1, 2,"Mail Options..."),
1366 if ( just_compose ) {
1367 // Need to install self destruct
1368 SendMsgDialog *compose = theCompose.getWin();
1371 char *ttl = GETMSG(DT_catd, 1, 262, "Dead Letter Message");
1372 compose->loadDeadLetter(dead_letter);
1373 compose->setTitle(ttl);
1374 compose->setIconTitle(ttl);
1377 if ( *argcp > num_legit_args + 1) { // Have attachment(s)
1378 for ( int k = num_legit_args + 1; k < *argcp; k++ ) {
1379 compose->inclAsAttmt(argv[k], NULL);
1385 // inbox. We do this by querying the current implementation for
1386 // the path to its inbox.
1389 DtMailObjectSpace space;
1391 d_session->queryImpl(mail_error,
1392 d_session->getDefaultImpl(mail_error),
1393 DtMailCapabilityInboxName,
1398 // We need to determine which transport to use. The order of preference
1401 // 1) The value of DEFAULT_TRANSPORT in the .mailrc file.
1403 // 2) The value of DEFAULT_TRANSPORT in the environment.
1405 // 3) The transport, if available for the default implementation.
1407 // 4) The first implementation that provides a transport.
1409 const char * trans_impl = NULL;
1411 d_session->mailRc(mail_error)->getValue(mail_error,
1412 "DEFAULT_TRANSPORT",
1414 if (mail_error.isSet()) {
1420 trans_impl = getenv("DEFAULT_TRANSPORT");
1424 trans_impl = d_session->getDefaultImpl(mail_error);
1426 DtMailBoolean trans;
1428 d_session->queryImpl(mail_error, trans_impl,
1429 DtMailCapabilityTransport, &trans);
1430 if (mail_error.isSet() || trans == DTM_FALSE) {
1436 const char ** impls = d_session->enumerateImpls(mail_error);
1438 for (int impl = 0; impls[impl]; impl++) {
1439 DtMailBoolean trans;
1440 d_session->queryImpl(mail_error, impls[impl],
1441 DtMailCapabilityTransport, &trans);
1442 if (!mail_error.isSet() || trans == DTM_TRUE) {
1443 trans_impl = impls[impl];
1450 _mail_transport = d_session->transportConstruct(mail_error,
1456 _mail_transport = NULL;
1459 // Register all callbacks the backend may have to deal with
1461 d_session->registerLastInteractiveEventTimeCallback(lastInteractiveEventTime, this);
1463 // These callbacks are only needed on systems where sendmail is run as
1464 // 'root', and so has access permissions to any file on the system.
1465 d_session->registerDisableGroupPrivilegesCallback(disableGroupPrivileges, this);
1466 d_session->registerEnableGroupPrivilegesCallback(enableGroupPrivileges, this);
1468 if (d_session->pollRequired(mail_error) == DTM_TRUE) {
1469 d_session->registerBusyCallback(mail_error, setBusyState, this);
1470 _appTimeoutId = XtAppAddTimeOut(
1471 XtWidgetToApplicationContext( _w ),
1473 &RoamApp::applicationTimeout,
1477 // Process the message that started us, if any. Should I pass in
1478 // roam_tt_procid or NULL.
1479 tttk_Xt_input_handler( 0, 0, 0 );
1480 XtAppAddInput( Application::appContext(), roam_tt_fd,
1481 (XtPointer)XtInputReadMask,
1482 tttk_Xt_input_handler, roam_tt_procid );
1484 // Get the vacation handle before the new RoamMenuWindow
1485 // This is for setting the Vacation title stripe on the window
1486 _vacation = new VacationCmd("Vacation", GETMSG(DT_catd, 1, 3, "Vacation"));
1488 // DtMail only supports the "Mail" message.
1489 // If DtMail is started by ToolTalk, then we assume that the
1490 // client wants a Compose window. Therefore, we do not
1491 // bring up a RoamMenuWindow.
1493 if ( !session_fp && !started_by_tt && !just_compose) {
1495 _mailview = new RoamMenuWindow(mail_file);
1496 _mailview->initialize();
1497 _mailview->manage();
1507 _dialog = new DtMailGenDialog("Dialog", _w);
1509 DtDbReloadNotify(reload_notify_cb, (XtPointer) NULL);
1510 _default_x_error_handler = XSetErrorHandler(x_error_handler);
1511 if (NULL != mail_file)
1512 free((void*) mail_file);
1515 RoamApp::RoamApp(char *name) : Application (name), _activePrintDisplays(5)
1517 DebugPrintf(2, "RoamApp::RoamApp(%p \"%s\")\n", name, name);
1522 _errorPrintDisplay = NULL;
1523 _firstSaveYourselfArrived = false;
1525 _optionsHandle = NULL;
1527 _quitSilently = false;
1528 _quitQuickly = false;
1531 _shutdownWorkprocID = 0;
1533 _default_mailbox = NULL;
1536 _mailfiles_folder = NULL;
1537 _mail_session = NULL;
1538 _mail_transport = NULL;
1539 _print_script = NULL;
1540 _system_font = NULL;
1541 _system_fontlist = NULL;
1544 _user_fontlist = NULL;
1545 _default_x_error_handler = NULL;
1548 // Let the destructor of parent Application class handle the
1553 #ifdef DTMAIL_TOOLTALK
1554 if ( roam_tt_procid != NULL ) {
1556 // Temporary workaround to get PrintToFile to work.
1557 // Currently, PrintToFile forks a child which is
1558 // calling ~RoamApp when it exits. This clobbers
1559 // the tooltalk connection causing the parent to hang.
1561 ttdt_close(0, 0, 1);
1562 roam_tt_procid = NULL;
1568 XtRemoveTimeOut(_appTimeoutId);
1572 RoamApp::shutdownWorkproc(XtPointer client_data)
1574 RoamApp *thisApp = (RoamApp*) client_data;
1576 if (thisApp->_numPendingTasks > 0)
1579 if (thisApp->_shutdownWorkprocID != 0)
1581 XtRemoveWorkProc(thisApp->_shutdownWorkprocID);
1582 thisApp->_shutdownWorkprocID = 0;
1585 delete thisApp->_mail_session;
1587 // Delete this and let the parent class's destructor call exit(0)
1596 if (_numPendingTasks > 0)
1598 if (_shutdownWorkprocID == 0)
1599 _shutdownWorkprocID = XtAppAddWorkProc(
1601 &RoamApp::shutdownWorkproc,
1605 shutdownWorkproc((XtPointer) this);
1609 RoamApp::checkForShutdown()
1611 int nappwin, ncompunused, nrmwunused;
1613 if (! theApplication->isEnabledShutdown()) return;
1614 nappwin = theApplication->num_windows();
1615 ncompunused = theCompose.numUnusedWindows();
1616 nrmwunused = theRoamApp.session()->numDeactivatedRMW();
1618 if (nappwin == ncompunused + nrmwunused)
1620 theCompose.~Compose();
1621 while (_numWindows > 0)
1629 RoamApp::applicationTimeout( XtPointer client_data,
1632 RoamApp *app = ( RoamApp * ) client_data;
1637 RoamApp::timeout( XtIntervalId * )
1639 DtMail::Session * d_session = _mail_session->session();
1642 d_session->poll(error);
1644 _appTimeoutId = XtAppAddTimeOut(
1645 XtWidgetToApplicationContext( _w ),
1647 &RoamApp::applicationTimeout,
1652 RoamApp::lastInteractiveEventTime(void * client_data)
1654 RoamApp * self = (RoamApp *)client_data;
1655 return (theApplication->lastInteractiveEventTime());
1659 RoamApp::disableGroupPrivileges(void * client_data)
1661 RoamApp * self = (RoamApp *)client_data;
1662 theApplication->disableGroupPrivileges();
1667 RoamApp::enableGroupPrivileges(void * client_data)
1669 RoamApp * self = (RoamApp *)client_data;
1670 theApplication->enableGroupPrivileges();
1676 RoamApp::setBusyState(
1678 DtMailBusyState busy_state,
1681 static const int MAXBUSYSTATES=20;
1682 static int busyStateStackTop = 0;
1683 static DtMailBusyState busyStateStack[MAXBUSYSTATES] =
1684 {DtMailBusyState_NotBusy};
1685 RoamApp *self = (RoamApp*) client_data;
1689 case DtMailBusyState_AutoSave:
1690 case DtMailBusyState_NewMail:
1692 showBusyState(error, busy_state, client_data);
1693 // if (busyStateStackTop) // Already busy from previous message?
1694 // self->_busy_count--; // Decrement busy count for
1695 // displaying this message
1696 busyStateStack[++busyStateStackTop] = busy_state;
1697 assert(busyStateStackTop < MAXBUSYSTATES);
1700 case DtMailBusyState_NotBusy:
1701 if (busyStateStackTop)
1704 self->_mailview->postErrorDialog(error);
1706 busy_state = busyStateStack[--busyStateStackTop];
1707 showBusyState(error, busy_state, client_data);
1708 // if (busyStateStackTop)
1709 // self->_busy_count--; // Decrement busy count for
1710 // redisplaying this message
1713 showBusyState(error, busy_state, client_data);
1716 assert(busyStateStack[0] == DtMailBusyState_NotBusy);
1720 RoamApp::showBusyState(
1722 DtMailBusyState busy_state,
1726 RoamApp * self = (RoamApp *)client_data;
1730 case DtMailBusyState_AutoSave:
1731 self->busyAllWindows(GETMSG(DT_catd, 3, 1, "Auto-saving..."));
1734 case DtMailBusyState_NewMail:
1735 self->busyAllWindows(GETMSG(DT_catd, 3, 86, "Checking for new mail..."));
1738 case DtMailBusyState_NotBusy:
1740 self->unbusyAllWindows();
1746 RoamApp::busyAllWindows(const char * msg)
1748 for (int win = 0; win < _numWindows; win++) {
1749 // if (_busy_count == 0) {
1750 _windows[win]->busyCursor();
1753 _windows[win]->setStatus(msg);
1760 RoamApp::unbusyAllWindows(void)
1763 // if (_busy_count == 0) {
1764 for (int win = 0; win < _numWindows; win++) {
1765 _windows[win]->normalCursor();
1766 _windows[win]->clearStatus();
1772 RoamApp::globalAddToCachedContainerList(char *destname)
1775 RoamMenuWindow *rmw;
1777 for (int win = 0; win < _numWindows; win++) {
1778 cname = _windows[win]->className();
1779 if (strcmp(cname, "RoamMenuWindow") == 0) {
1780 rmw = (RoamMenuWindow *)_windows[win];
1781 rmw->addToCachedContainerList(destname);
1787 RoamApp::globalPropChange(void)
1789 busyAllWindows(GETMSG(DT_catd, 1, 4, "Updating properties..."));
1791 for (int win = 0; win < _numWindows; win++) {
1792 _windows[win]->propsChanged();
1799 RoamApp::genDialog()
1806 RoamApp::startVacation(
1813 RoamMenuWindow *rmw;
1817 XtVaGetValues(subject_tf,
1821 XtVaGetValues(text_tp,
1825 status = _vacation->startVacation((char *)subj, (char *) text);
1827 for (int win = 0; win < _numWindows; win++) {
1828 cname = _windows[win]->className();
1829 if (strcmp(cname, "RoamMenuWindow") == 0) {
1830 rmw = (RoamMenuWindow *)_windows[win];
1831 rmw->setVacationTitle();
1838 RoamApp::stopVacation()
1841 RoamMenuWindow *rmw;
1843 _vacation->stopVacation();
1845 for (int win = 0; win < _numWindows; win++) {
1846 cname = _windows[win]->className();
1847 if (strcmp(cname, "RoamMenuWindow") == 0) {
1848 rmw = (RoamMenuWindow *)_windows[win];
1849 rmw->removeVacationTitle();
1855 getPropStringValue(DtVirtArray<PropStringPair *> &results, const char *label)
1857 for (int mrc = 0; mrc < results.length(); mrc++) {
1858 PropStringPair * psp = results[mrc];
1859 if (strcmp(label, psp->label) == 0)
1860 return strdup(psp->value);
1866 parsePropString(const char * input, DtVirtArray<PropStringPair *> & results)
1871 // If it's not multibyte, use the regular string function
1872 if (MB_CUR_MAX <= 1) {
1873 const char * start = input;
1878 while (isspace(*start)) {
1882 for (end = start; end && *end; end++)
1883 if (isspace(*end) && *(end-1) != '\\')
1886 PropStringPair * new_pair = new PropStringPair;
1888 int len = end - start;
1889 char * label = new char[len + 5];
1890 strncpy(label, start, len);
1892 for (ptr = label; (ptr = strstr(ptr, "\\ ")); ptr++)
1895 char * file = strchr(label, ':');
1897 new_pair->label = strdup(label);
1898 new_pair->value = NULL;
1902 new_pair->label = strdup(label);
1905 if (strlen(file) == 0) {
1906 new_pair->value = NULL;
1909 new_pair->value = strdup(file);
1913 results.append(new_pair);
1918 while (*start && isspace(*start)) {
1922 } while(*start && *end);
1926 // The string can contain multibyte characters and it must be converted to
1927 // wide character string before parsing
1928 int len = strlen(input);
1929 wchar_t *wc_input= new wchar_t[len+1];
1930 mbstowcs(wc_input, input, len+1);
1931 const wchar_t *start = wc_input;
1936 while (iswspace(*start)) {
1940 for (end = start; end && *end; end++)
1941 if (iswspace(*end) && *(end-1) != (wint_t)'\\')
1943 PropStringPair * new_pair = new PropStringPair;
1945 int wclen = end - start;
1946 wchar_t *wc_label = new wchar_t[wclen+1];
1947 wcsncpy(wc_label, start, wclen);
1948 wc_label[wclen] = (wint_t)'\0';
1950 // Search the string "\ " and take out the back slash
1951 wchar_t esc_space[3];
1952 mbstowcs(esc_space, "\\ ", 3);
1953 for (ptr = wc_label; (ptr = wcswcs(ptr, esc_space)); ptr++)
1956 wchar_t *file = wcschr(wc_label, (wint_t)':');
1958 new_pair->label = new char[(wclen+1)*MB_CUR_MAX];
1959 wcstombs(new_pair->label, wc_label, wclen+1);
1960 new_pair->value = NULL;
1965 *file = (wint_t)'\0';
1966 new_pair->label = new char[(wclen+1)*MB_CUR_MAX];
1967 wcstombs(new_pair->label, wc_label, (wclen+1)*MB_CUR_MAX);
1970 int filelen = wcslen(file);
1972 new_pair->value = NULL;
1975 new_pair->value = new char[(filelen+1)*MB_CUR_MAX];
1976 wcstombs(new_pair->value, file, (filelen+1)*MB_CUR_MAX);
1980 results.append(new_pair);
1984 while (*start && iswspace(*start)) {
1988 } while(*start && *end);
1994 PropStringPair::PropStringPair(void)
2000 PropStringPair::PropStringPair(const PropStringPair & other)
2006 label = strdup(other.label);
2010 value = strdup(other.value);
2014 PropStringPair::~PropStringPair(void)
2026 RoamApp::setSession( MailSession *session )
2028 _mail_session = session;
2038 char *formatPropPair(char * key, const void * data)
2040 char *formatted_str = NULL;
2041 char *white_space = NULL;
2042 int i, num_spaces = 0;
2043 int key_len = strlen(key);
2049 // figure out whitespace for formatting
2050 // assume 13 for normal sized alias name
2052 if(key_len < 13) // need to add spaces
2054 num_spaces = 13 - key_len;
2056 white_space = (char *)malloc(num_spaces + 1);
2057 strcpy(white_space, "\0");
2059 for(i = 0; i < num_spaces; i++)
2060 strcat(white_space, " ");
2062 m_size = key_len + strlen((char *)white_space)
2063 + strlen((char *)data) + strlen(" = ") + 1;
2064 formatted_str = (char *)malloc(m_size);
2066 sprintf(formatted_str, "%s%s = %s",key, white_space, (const char *) data);
2071 /* make an alias string */
2072 formatted_str = (char *)malloc(key_len + strlen((const char *)data) + 2);
2074 m_size = key_len + strlen((const char *)data) + strlen(" = ") + 1;
2075 formatted_str = (char *)malloc(m_size);
2077 sprintf(formatted_str, "%s = %s",key, (const char *) data);
2081 return formatted_str;
2086 RoamApp::inboxWindow()
2088 RoamMenuWindow *rmw;
2091 for (int win = 0; win < _numWindows; win++) {
2092 cname = _windows[win]->className();
2093 if (strcmp(cname, "RoamMenuWindow") == 0) {
2094 rmw = (RoamMenuWindow *)_windows[win];
2104 RoamApp::nextRoamMenuWindow(RoamMenuWindow *last)
2106 RoamMenuWindow *looking_for = last;
2107 RoamMenuWindow *rmw;
2110 for (int win = 0; win < _numWindows; win++) {
2111 cname = _windows[win]->className();
2112 if (strcmp(cname, "RoamMenuWindow") == 0) {
2113 rmw = (RoamMenuWindow *)_windows[win];
2114 if (NULL == looking_for)
2116 if (rmw == looking_for)
2124 RoamApp::closeInactiveRoamMenuWindows(void)
2126 MailSession *ses = theRoamApp.session();
2127 RoamMenuWindow **rmws;
2131 rmws = (RoamMenuWindow**) malloc(_numWindows * sizeof(RoamMenuWindow *));
2132 for (win=0; win<_numWindows; win++)
2134 cname = _windows[win]->className();
2135 if (strcmp(cname, "RoamMenuWindow") == 0)
2136 rmws[nrmws++] = (RoamMenuWindow*) _windows[win];
2139 for (win=0; win<nrmws; win++)
2140 if (! ses->isActiveRMW(rmws[win])) rmws[win]->quit(TRUE);
2146 RoamApp::reopenRoamMenuWindows(void)
2148 RoamMenuWindow *rmw, **rmws;
2152 theApplication->disableShutdown();
2154 rmws = (RoamMenuWindow**) malloc(_numWindows * sizeof(RoamMenuWindow *));
2155 for (win=0; win<_numWindows; win++)
2157 cname = _windows[win]->className();
2158 if (strcmp(cname, "RoamMenuWindow") == 0)
2159 rmws[nrmws++] = (RoamMenuWindow*) _windows[win];
2162 for (win=0; win<nrmws; win++)
2166 name = strdup(rmw->mailboxName());
2169 rmw = new RoamMenuWindow(name);
2176 theApplication->enableShutdown();
2180 RoamApp::defaultStatusWindow()
2182 MainWindow *mw = NULL;
2184 if ((mw = (MainWindow *) _mailview) != NULL)
2186 if ((mw = (MainWindow *) inboxWindow()) != NULL)
2188 if (_numWindows > 0)
2189 mw = (MainWindow *) _windows[0];
2195 RoamApp::open_catalog()
2197 Application::open_catalog(); // Open Motif Application message catalog file
2198 DT_catd = catopen(DTMAIL_CAT, NL_CAT_LOCALE); // Open DtMail message catalog file