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 #define SA_HANDLER_TYPE void (*)(int)
962 void RoamApp::initialize(int *argcp, char **argv)
965 struct sigaction *action;
966 struct sigaction action_buf;
970 _firstSaveYourselfArrived = FALSE;
972 _optionsHandle = NULL;
973 _quitSilently = FALSE;
974 _quitQuickly = FALSE;
975 _shutdownWorkprocID = 0;
978 char * mail_file = NULL;
979 char * dead_letter = NULL;
980 char *session_file = NULL;
985 signal(SIGUSR1, (void(*)(int ...))SigUsr1);
987 signal(SIGUSR1, SigUsr1);
991 (void)signal( SIGDANGER, pspace_signal );
994 action = &action_buf;
995 memset((void*) action, 0, sizeof(struct sigaction));
996 action->sa_handler = (SA_HANDLER_TYPE) panicQuitSignalHandler;
997 action->sa_flags = 0;
998 sigaction(SIGHUP, action, NULL);
999 sigaction(SIGINT, action, NULL);
1000 sigaction(SIGQUIT, action, NULL);
1001 sigaction(SIGILL, action, NULL);
1002 sigaction(SIGABRT, action, NULL);
1003 sigaction(SIGBUS, action, NULL);
1004 sigaction(SIGSEGV, action, NULL);
1005 sigaction(SIGTERM, action, NULL);
1007 // Must be called before XtAppInitialize.
1008 XtSetLanguageProc(NULL, NULL, NULL);
1010 // Set up environment variable (including NLSPATH) before calling
1011 // XtAppInitialize() (cmvc 6576).
1012 _DtEnvControl (DT_ENV_SET);
1014 // This will take care of standard arguments such as -display.
1015 Application::initialize(argcp,argv);
1017 // If -session arg is present remove it and return session file name.
1018 session_file = parseSessionArg(argcp, argv);
1020 // export display and locale settings
1022 static char displayenv[256]; /* Needs to be static for putenv */
1023 sprintf(displayenv, "DISPLAY=%s", XDisplayString(_display));
1026 // Process dtmail opt args.
1028 int num_legit_args = 0;
1030 while((opt = getopt(*argcp, argv, "a:cef:hl:t")) != EOF) {
1042 use_XmTextEditor = 1;
1047 mail_file = strdup(optarg);
1054 dead_letter = optarg;
1058 // Started by ToolTalk
1067 // Remove cbs else face Phase2Destroy!
1068 XtRemoveAllCallbacks(baseWidget(), XmNdestroyCallback);
1075 if(!just_compose && !started_by_tt && !mail_file && session_file)
1076 openSessionFile(session_file); // Open the session file
1079 getResources( _resources, XtNumber ( _resources ) );
1081 DtInitialize(XtDisplay(baseWidget()), baseWidget(), argv[0], "Dtmail");
1083 // Must be called after XtSetLanguageProc and DtInitialize because
1084 // DtInitialize sets the environment variable NLSPATH which is used
1085 // in catopen(). That's why we have to take out catopen from
1086 // Application::initialize and put a new mathod open->catalog for
1087 // both Application and RoamApp
1088 this->open_catalog();
1090 // Initialize the mail_error. This also has to be done after DtInitialize
1091 // because the DtMailEnv consturctor calls catopen as well.
1092 DtMailEnv mail_error;
1098 // Some of the scrolling lists contain formatted text and thus
1099 // require a fixed width font to display the text correctly.
1100 // We want to use the fixed width font defined by dt.userFont as
1101 // it will be internationalized correctly. If it is not there
1102 // we fall back to a fixed width lucida font. If that fails
1103 // we let the widget fallback to what ever it thinks is best.
1106 // Default font in case we can't find anything else.
1107 XrmDatabase db = XtScreenDatabase(XtScreen(baseWidget()));
1111 char *buf = new char[1024];
1114 // Need to check fixed width font mailrc variable. Assume
1119 XrmPutStringResource(
1120 &db, "*Work_Area*XmText.fontList", _user_font);
1121 XrmPutStringResource(
1122 &db, "*Work_Area*XmTextField.fontList", _user_font);
1124 XrmPutStringResource(
1125 &db, "*Work_Area*DtEditor.textFontList", _user_font);
1126 XrmPutStringResource(
1127 &db, "*Work_Area*iconGadget.fontList", _user_font);
1128 XrmPutStringResource(
1129 &db, "*XmDialogShell*XmList.FontList", _user_font);
1131 // Convert the user fontlist to a font.
1132 if (!fontlist_to_font(_user_fontlist, &userfont)) {
1133 if (!(userfont.f.cf_font = XLoadQueryFont(
1134 XtDisplay(baseWidget()),
1136 /* Couldn't convert the user fontlist to a font */
1139 "RoamApp::initialize : error loading fixed font\n");
1141 userfont.cf_type = XmFONT_IS_FONT;
1146 FontType systemfont;
1148 XrmPutStringResource(
1149 &db, "*Work_Area*Text*fontList", _system_font);
1150 XrmPutStringResource(
1151 &db, "*Work_Area*iconGadget*fontList", _system_font);
1152 XrmPutStringResource(
1153 &db, "*Work_Area*Text*textFontList", _system_font);
1154 XrmPutStringResource(
1155 &db, "*XmDialogShell*XmList*FontList", _system_font);
1157 if (!fontlist_to_font(_system_fontlist, &systemfont)) {
1158 /* Couldn't convert the system fontlist to a font */
1159 if (!(systemfont.f.cf_font = XLoadQueryFont(
1160 XtDisplay(baseWidget()),
1164 "RoamApp::initialize : error loading variable font\n");
1166 systemfont.cf_type = XmFONT_IS_FONT;
1172 // If the glyph font is specified in a resource file, use it.
1174 _glyph_name = XtNewString(_glyph_font);
1178 // If the glyph font hasn't been specified, try to match it with
1181 // Get the font name that matches the user font pixel size.
1182 load_app_font(baseWidget(), &userfont, &_glyph_name);
1185 // Create a fontlist that contains the glyph and user fonts
1186 strcpy(buf, _user_font);
1188 // Never refer to the "plain" tag so don't add it.
1189 if (strchr(_user_font, '=') == NULL) {
1191 strcat(buf, "=plain, ");
1194 // If the symbol font can't be found, use user font above
1197 strcat(buf, _glyph_name);
1198 strcat(buf, "=attach");
1201 // Loosely bind font to message list. This lets users override
1202 // with a more strongly bound name (ie "Dtmail*Message_List*FontList");
1204 // Matches the MsgScrollingList in the RoamMenuWindows.
1205 XrmPutStringResource(&db, "*Message_List*FontList", buf);
1208 // Matches the UndelMsgScrollingList in the UndelFromListDialog
1209 // and overrides the "*XmDialogShell*XmList*FontList" spec above.
1210 XrmPutStringResource(&db, "*XmDialogShell*Message_List*FontList", buf);
1215 // If we don't have a mail file yet, then we need to retrieve the
1216 // Initialize Tooltalk
1217 // NOTE: For now, must make the FIRST ttdt_open call to be the proc_id
1218 // that will respond to the start message. Therefore, call gui's
1219 // ttdt_open before libDtMail calls its.
1222 sess = (char *)getenv("TT_SESSION");
1223 if (!sess || (*sess == '\0')) {
1224 sess = getenv("_SUN_TT_SESSION");
1226 if (!sess || (*sess == '\0')) {
1227 tt_default_session_set(tt_X_session(XDisplayString(_display)));
1230 roam_tt_procid = ttdt_open( &roam_tt_fd, "DTMAIL", "SunSoft", "%I", 1 );
1231 dieFromTtError(tt_ptr_error(roam_tt_procid),
1232 "initialize.ttdt_open",
1233 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."),
1234 DTMAILHELPCANTINITTOOLTALK);
1236 // This is for supporting old ptype where RFC_822_Message is
1238 status = ttmedia_ptype_declare( "RFC_822_Message",
1240 tooltalk_msg_handler,
1243 dieFromTtError(status,
1244 "initialize.ttmedia_ptype_declare.RFC_822_Message", NULL, NULL);
1246 status = ttmedia_ptype_declare( "RFC_822_MESSAGE",
1248 tooltalk_msg_handler,
1251 dieFromTtError(status,
1252 "initialize.ttmedia_ptype_declare.RFC_822_MESSAGE", NULL, NULL);
1254 status = ttmedia_ptype_declare( "MAIL_TYPE",
1256 attachmt_msg_handler,
1259 dieFromTtError(status,
1260 "initialize.ttmedia_ptype_declare.MAIL_TYPE", NULL, NULL);
1262 /* Join the default session -- This should have been done by default */
1263 roam_tt_pattern = ttdt_session_join(
1265 (Ttdt_contract_cb)quit_message_cb,
1266 baseWidget(), this, 1);
1267 dieFromTtError(tt_ptr_error(roam_tt_pattern),
1268 "initialize.ttdt_session_join", NULL, NULL);
1270 _mail_session = new MailSession(mail_error, Application::appContext());
1271 if (mail_error.isSet()) {
1272 // what do we do here? there are no windows for dialogs
1273 // should we just register a syslog() and exit? ugggh
1275 fprintf(stderr, "RoamApp::initialize : error creating MailSession\n");
1280 // .mailrc parsing error checking
1282 DtMail::Session * d_session = _mail_session->session();
1283 DtMail::MailRc* mailRc = d_session->mailRc(mail_error);
1284 DTMailError_t pErr = mailRc->getParseError();
1285 if (pErr != DTME_NoError) {
1287 DtMailGenDialog *mailrc_dialog = new DtMailGenDialog(
1289 theApplication->baseWidget());
1290 mailrc_dialog->setToQuestionDialog(
1291 GETMSG(DT_catd, 2, 1, "Mailer"),
1292 GETMSG(DT_catd, 2, 22,
1293 "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.") );
1294 helpId = DTMAILHELPERROR;
1295 answer = mailrc_dialog->post_and_return(
1296 GETMSG(DT_catd, 2, 23, "Continue"),
1297 GETMSG(DT_catd, 2, 24, "Exit"),
1300 XtRemoveAllCallbacks(
1301 theApplication->baseWidget(),
1302 XmNdestroyCallback);
1309 // Check if mailer is installed properly if we are not in debugging mode.
1311 const char *value = NULL;
1313 d_session->mailRc(mail_error)->getValue(mail_error,
1314 "__ignore_group_permissions",
1316 if (mail_error.isSet()) {
1320 theApplication->enableGroupPrivileges();
1321 GetGroupName(grp_name);
1322 theApplication->disableGroupPrivileges();
1323 if (strcmp(grp_name, DTMAIL_DEFAULT_CREATE_MAILGROUP))
1324 mail_error.setError(DTME_BadRunGroup);
1327 if ((DTMailError_t)mail_error == DTME_BadRunGroup) {
1331 DtMailGenDialog *install_errDialog =
1332 new DtMailGenDialog("Dialog", theApplication->baseWidget());
1333 sprintf(buf, "%s", GETMSG(DT_catd, 2, 4,
1334 "Mailer has not been properly installed,\n\
1335 and cannot run because the execution group\n\
1336 is incorrectly set."));
1338 install_errDialog->setToErrorDialog(
1339 GETMSG(DT_catd, 1, 6, "Mailer"),
1342 // No choice at this state other than to OK.
1343 helpId = DTMAILHELPBADGROUPID;
1344 answer = install_errDialog->post_and_return(
1345 GETMSG(DT_catd, 3, 9, "OK"),
1347 XtRemoveAllCallbacks(
1348 theApplication->baseWidget(),
1349 XmNdestroyCallback);
1355 free((void*) value);
1357 _options = new OptCmd("Mail Options...",
1358 GETMSG(DT_catd, 1, 2,"Mail Options..."),
1362 if ( just_compose ) {
1363 // Need to install self destruct
1364 SendMsgDialog *compose = theCompose.getWin();
1367 char *ttl = GETMSG(DT_catd, 1, 262, "Dead Letter Message");
1368 compose->loadDeadLetter(dead_letter);
1369 compose->setTitle(ttl);
1370 compose->setIconTitle(ttl);
1373 if ( *argcp > num_legit_args + 1) { // Have attachment(s)
1374 for ( int k = num_legit_args + 1; k < *argcp; k++ ) {
1375 compose->inclAsAttmt(argv[k], NULL);
1381 // inbox. We do this by querying the current implementation for
1382 // the path to its inbox.
1385 DtMailObjectSpace space;
1387 d_session->queryImpl(mail_error,
1388 d_session->getDefaultImpl(mail_error),
1389 DtMailCapabilityInboxName,
1394 // We need to determine which transport to use. The order of preference
1397 // 1) The value of DEFAULT_TRANSPORT in the .mailrc file.
1399 // 2) The value of DEFAULT_TRANSPORT in the environment.
1401 // 3) The transport, if available for the default implementation.
1403 // 4) The first implementation that provides a transport.
1405 const char * trans_impl = NULL;
1407 d_session->mailRc(mail_error)->getValue(mail_error,
1408 "DEFAULT_TRANSPORT",
1410 if (mail_error.isSet()) {
1416 trans_impl = getenv("DEFAULT_TRANSPORT");
1420 trans_impl = d_session->getDefaultImpl(mail_error);
1422 DtMailBoolean trans;
1424 d_session->queryImpl(mail_error, trans_impl,
1425 DtMailCapabilityTransport, &trans);
1426 if (mail_error.isSet() || trans == DTM_FALSE) {
1432 const char ** impls = d_session->enumerateImpls(mail_error);
1434 for (int impl = 0; impls[impl]; impl++) {
1435 DtMailBoolean trans;
1436 d_session->queryImpl(mail_error, impls[impl],
1437 DtMailCapabilityTransport, &trans);
1438 if (!mail_error.isSet() || trans == DTM_TRUE) {
1439 trans_impl = impls[impl];
1446 _mail_transport = d_session->transportConstruct(mail_error,
1452 _mail_transport = NULL;
1455 // Register all callbacks the backend may have to deal with
1457 d_session->registerLastInteractiveEventTimeCallback(lastInteractiveEventTime, this);
1459 // These callbacks are only needed on systems where sendmail is run as
1460 // 'root', and so has access permissions to any file on the system.
1461 d_session->registerDisableGroupPrivilegesCallback(disableGroupPrivileges, this);
1462 d_session->registerEnableGroupPrivilegesCallback(enableGroupPrivileges, this);
1464 if (d_session->pollRequired(mail_error) == DTM_TRUE) {
1465 d_session->registerBusyCallback(mail_error, setBusyState, this);
1466 _appTimeoutId = XtAppAddTimeOut(
1467 XtWidgetToApplicationContext( _w ),
1469 &RoamApp::applicationTimeout,
1473 // Process the message that started us, if any. Should I pass in
1474 // roam_tt_procid or NULL.
1475 tttk_Xt_input_handler( 0, 0, 0 );
1476 XtAppAddInput( Application::appContext(), roam_tt_fd,
1477 (XtPointer)XtInputReadMask,
1478 tttk_Xt_input_handler, roam_tt_procid );
1480 // Get the vacation handle before the new RoamMenuWindow
1481 // This is for setting the Vacation title stripe on the window
1482 _vacation = new VacationCmd("Vacation", GETMSG(DT_catd, 1, 3, "Vacation"));
1484 // DtMail only supports the "Mail" message.
1485 // If DtMail is started by ToolTalk, then we assume that the
1486 // client wants a Compose window. Therefore, we do not
1487 // bring up a RoamMenuWindow.
1489 if ( !session_fp && !started_by_tt && !just_compose) {
1491 _mailview = new RoamMenuWindow(mail_file);
1492 _mailview->initialize();
1493 _mailview->manage();
1503 _dialog = new DtMailGenDialog("Dialog", _w);
1505 DtDbReloadNotify(reload_notify_cb, (XtPointer) NULL);
1506 _default_x_error_handler = XSetErrorHandler(x_error_handler);
1507 if (NULL != mail_file)
1508 free((void*) mail_file);
1511 RoamApp::RoamApp(char *name) : Application (name), _activePrintDisplays(5)
1513 DebugPrintf(2, "RoamApp::RoamApp(%p \"%s\")\n", name, name);
1518 _errorPrintDisplay = NULL;
1519 _firstSaveYourselfArrived = false;
1521 _optionsHandle = NULL;
1523 _quitSilently = false;
1524 _quitQuickly = false;
1527 _shutdownWorkprocID = 0;
1529 _default_mailbox = NULL;
1532 _mailfiles_folder = NULL;
1533 _mail_session = NULL;
1534 _mail_transport = NULL;
1535 _print_script = NULL;
1536 _system_font = NULL;
1537 _system_fontlist = NULL;
1540 _user_fontlist = NULL;
1541 _default_x_error_handler = NULL;
1544 // Let the destructor of parent Application class handle the
1549 #ifdef DTMAIL_TOOLTALK
1550 if ( roam_tt_procid != NULL ) {
1552 // Temporary workaround to get PrintToFile to work.
1553 // Currently, PrintToFile forks a child which is
1554 // calling ~RoamApp when it exits. This clobbers
1555 // the tooltalk connection causing the parent to hang.
1557 ttdt_close(0, 0, 1);
1558 roam_tt_procid = NULL;
1564 XtRemoveTimeOut(_appTimeoutId);
1568 RoamApp::shutdownWorkproc(XtPointer client_data)
1570 RoamApp *thisApp = (RoamApp*) client_data;
1572 if (thisApp->_numPendingTasks > 0)
1575 if (thisApp->_shutdownWorkprocID != 0)
1577 XtRemoveWorkProc(thisApp->_shutdownWorkprocID);
1578 thisApp->_shutdownWorkprocID = 0;
1581 delete thisApp->_mail_session;
1583 // Delete this and let the parent class's destructor call exit(0)
1592 if (_numPendingTasks > 0)
1594 if (_shutdownWorkprocID == 0)
1595 _shutdownWorkprocID = XtAppAddWorkProc(
1597 &RoamApp::shutdownWorkproc,
1601 shutdownWorkproc((XtPointer) this);
1605 RoamApp::checkForShutdown()
1607 int nappwin, ncompunused, nrmwunused;
1609 if (! theApplication->isEnabledShutdown()) return;
1610 nappwin = theApplication->num_windows();
1611 ncompunused = theCompose.numUnusedWindows();
1612 nrmwunused = theRoamApp.session()->numDeactivatedRMW();
1614 if (nappwin == ncompunused + nrmwunused)
1616 theCompose.~Compose();
1617 while (_numWindows > 0)
1625 RoamApp::applicationTimeout( XtPointer client_data,
1628 RoamApp *app = ( RoamApp * ) client_data;
1633 RoamApp::timeout( XtIntervalId * )
1635 DtMail::Session * d_session = _mail_session->session();
1638 d_session->poll(error);
1640 _appTimeoutId = XtAppAddTimeOut(
1641 XtWidgetToApplicationContext( _w ),
1643 &RoamApp::applicationTimeout,
1648 RoamApp::lastInteractiveEventTime(void * client_data)
1650 RoamApp * self = (RoamApp *)client_data;
1651 return (theApplication->lastInteractiveEventTime());
1655 RoamApp::disableGroupPrivileges(void * client_data)
1657 RoamApp * self = (RoamApp *)client_data;
1658 theApplication->disableGroupPrivileges();
1663 RoamApp::enableGroupPrivileges(void * client_data)
1665 RoamApp * self = (RoamApp *)client_data;
1666 theApplication->enableGroupPrivileges();
1672 RoamApp::setBusyState(
1674 DtMailBusyState busy_state,
1677 static const int MAXBUSYSTATES=20;
1678 static int busyStateStackTop = 0;
1679 static DtMailBusyState busyStateStack[MAXBUSYSTATES] =
1680 {DtMailBusyState_NotBusy};
1681 RoamApp *self = (RoamApp*) client_data;
1685 case DtMailBusyState_AutoSave:
1686 case DtMailBusyState_NewMail:
1688 showBusyState(error, busy_state, client_data);
1689 // if (busyStateStackTop) // Already busy from previous message?
1690 // self->_busy_count--; // Decrement busy count for
1691 // displaying this message
1692 busyStateStack[++busyStateStackTop] = busy_state;
1693 assert(busyStateStackTop < MAXBUSYSTATES);
1696 case DtMailBusyState_NotBusy:
1697 if (busyStateStackTop)
1700 self->_mailview->postErrorDialog(error);
1702 busy_state = busyStateStack[--busyStateStackTop];
1703 showBusyState(error, busy_state, client_data);
1704 // if (busyStateStackTop)
1705 // self->_busy_count--; // Decrement busy count for
1706 // redisplaying this message
1709 showBusyState(error, busy_state, client_data);
1712 assert(busyStateStack[0] == DtMailBusyState_NotBusy);
1716 RoamApp::showBusyState(
1718 DtMailBusyState busy_state,
1722 RoamApp * self = (RoamApp *)client_data;
1726 case DtMailBusyState_AutoSave:
1727 self->busyAllWindows(GETMSG(DT_catd, 3, 1, "Auto-saving..."));
1730 case DtMailBusyState_NewMail:
1731 self->busyAllWindows(GETMSG(DT_catd, 3, 86, "Checking for new mail..."));
1734 case DtMailBusyState_NotBusy:
1736 self->unbusyAllWindows();
1742 RoamApp::busyAllWindows(const char * msg)
1744 for (int win = 0; win < _numWindows; win++) {
1745 // if (_busy_count == 0) {
1746 _windows[win]->busyCursor();
1749 _windows[win]->setStatus(msg);
1756 RoamApp::unbusyAllWindows(void)
1759 // if (_busy_count == 0) {
1760 for (int win = 0; win < _numWindows; win++) {
1761 _windows[win]->normalCursor();
1762 _windows[win]->clearStatus();
1768 RoamApp::globalAddToCachedContainerList(char *destname)
1771 RoamMenuWindow *rmw;
1773 for (int win = 0; win < _numWindows; win++) {
1774 cname = _windows[win]->className();
1775 if (strcmp(cname, "RoamMenuWindow") == 0) {
1776 rmw = (RoamMenuWindow *)_windows[win];
1777 rmw->addToCachedContainerList(destname);
1783 RoamApp::globalPropChange(void)
1785 busyAllWindows(GETMSG(DT_catd, 1, 4, "Updating properties..."));
1787 for (int win = 0; win < _numWindows; win++) {
1788 _windows[win]->propsChanged();
1795 RoamApp::genDialog()
1802 RoamApp::startVacation(
1809 RoamMenuWindow *rmw;
1813 XtVaGetValues(subject_tf,
1817 XtVaGetValues(text_tp,
1821 status = _vacation->startVacation((char *)subj, (char *) text);
1823 for (int win = 0; win < _numWindows; win++) {
1824 cname = _windows[win]->className();
1825 if (strcmp(cname, "RoamMenuWindow") == 0) {
1826 rmw = (RoamMenuWindow *)_windows[win];
1827 rmw->setVacationTitle();
1834 RoamApp::stopVacation()
1837 RoamMenuWindow *rmw;
1839 _vacation->stopVacation();
1841 for (int win = 0; win < _numWindows; win++) {
1842 cname = _windows[win]->className();
1843 if (strcmp(cname, "RoamMenuWindow") == 0) {
1844 rmw = (RoamMenuWindow *)_windows[win];
1845 rmw->removeVacationTitle();
1851 getPropStringValue(DtVirtArray<PropStringPair *> &results, const char *label)
1853 for (int mrc = 0; mrc < results.length(); mrc++) {
1854 PropStringPair * psp = results[mrc];
1855 if (strcmp(label, psp->label) == 0)
1856 return strdup(psp->value);
1862 parsePropString(const char * input, DtVirtArray<PropStringPair *> & results)
1867 // If it's not multibyte, use the regular string function
1868 if (MB_CUR_MAX <= 1) {
1869 const char * start = input;
1874 while (isspace(*start)) {
1878 for (end = start; end && *end; end++)
1879 if (isspace(*end) && *(end-1) != '\\')
1882 PropStringPair * new_pair = new PropStringPair;
1884 int len = end - start;
1885 char * label = new char[len + 5];
1886 strncpy(label, start, len);
1888 for (ptr = label; (ptr = strstr(ptr, "\\ ")); ptr++)
1891 char * file = strchr(label, ':');
1893 new_pair->label = strdup(label);
1894 new_pair->value = NULL;
1898 new_pair->label = strdup(label);
1901 if (strlen(file) == 0) {
1902 new_pair->value = NULL;
1905 new_pair->value = strdup(file);
1909 results.append(new_pair);
1914 while (*start && isspace(*start)) {
1918 } while(*start && *end);
1922 // The string can contain multibyte characters and it must be converted to
1923 // wide character string before parsing
1924 int len = strlen(input);
1925 wchar_t *wc_input= new wchar_t[len+1];
1926 mbstowcs(wc_input, input, len+1);
1927 const wchar_t *start = wc_input;
1932 while (iswspace(*start)) {
1936 for (end = start; end && *end; end++)
1937 if (iswspace(*end) && *(end-1) != (wint_t)'\\')
1939 PropStringPair * new_pair = new PropStringPair;
1941 int wclen = end - start;
1942 wchar_t *wc_label = new wchar_t[wclen+1];
1943 wcsncpy(wc_label, start, wclen);
1944 wc_label[wclen] = (wint_t)'\0';
1946 // Search the string "\ " and take out the back slash
1947 wchar_t esc_space[3];
1948 mbstowcs(esc_space, "\\ ", 3);
1949 for (ptr = wc_label; (ptr = wcswcs(ptr, esc_space)); ptr++)
1952 wchar_t *file = wcschr(wc_label, (wint_t)':');
1954 new_pair->label = new char[(wclen+1)*MB_CUR_MAX];
1955 wcstombs(new_pair->label, wc_label, wclen+1);
1956 new_pair->value = NULL;
1961 *file = (wint_t)'\0';
1962 new_pair->label = new char[(wclen+1)*MB_CUR_MAX];
1963 wcstombs(new_pair->label, wc_label, (wclen+1)*MB_CUR_MAX);
1966 int filelen = wcslen(file);
1968 new_pair->value = NULL;
1971 new_pair->value = new char[(filelen+1)*MB_CUR_MAX];
1972 wcstombs(new_pair->value, file, (filelen+1)*MB_CUR_MAX);
1976 results.append(new_pair);
1980 while (*start && iswspace(*start)) {
1984 } while(*start && *end);
1990 PropStringPair::PropStringPair(void)
1996 PropStringPair::PropStringPair(const PropStringPair & other)
2002 label = strdup(other.label);
2006 value = strdup(other.value);
2010 PropStringPair::~PropStringPair(void)
2022 RoamApp::setSession( MailSession *session )
2024 _mail_session = session;
2034 char *formatPropPair(char * key, const void * data)
2036 char *formatted_str = NULL;
2037 char *white_space = NULL;
2038 int i, num_spaces = 0;
2039 int key_len = strlen(key);
2045 // figure out whitespace for formatting
2046 // assume 13 for normal sized alias name
2048 if(key_len < 13) // need to add spaces
2050 num_spaces = 13 - key_len;
2052 white_space = (char *)malloc(num_spaces + 1);
2053 strcpy(white_space, "\0");
2055 for(i = 0; i < num_spaces; i++)
2056 strcat(white_space, " ");
2058 m_size = key_len + strlen((char *)white_space)
2059 + strlen((char *)data) + strlen(" = ") + 1;
2060 formatted_str = (char *)malloc(m_size);
2062 sprintf(formatted_str, "%s%s = %s",key, white_space, (const char *) data);
2067 /* make an alias string */
2068 formatted_str = (char *)malloc(key_len + strlen((const char *)data) + 2);
2070 m_size = key_len + strlen((const char *)data) + strlen(" = ") + 1;
2071 formatted_str = (char *)malloc(m_size);
2073 sprintf(formatted_str, "%s = %s",key, (const char *) data);
2077 return formatted_str;
2082 RoamApp::inboxWindow()
2084 RoamMenuWindow *rmw;
2087 for (int win = 0; win < _numWindows; win++) {
2088 cname = _windows[win]->className();
2089 if (strcmp(cname, "RoamMenuWindow") == 0) {
2090 rmw = (RoamMenuWindow *)_windows[win];
2100 RoamApp::nextRoamMenuWindow(RoamMenuWindow *last)
2102 RoamMenuWindow *looking_for = last;
2103 RoamMenuWindow *rmw;
2106 for (int win = 0; win < _numWindows; win++) {
2107 cname = _windows[win]->className();
2108 if (strcmp(cname, "RoamMenuWindow") == 0) {
2109 rmw = (RoamMenuWindow *)_windows[win];
2110 if (NULL == looking_for)
2112 if (rmw == looking_for)
2120 RoamApp::closeInactiveRoamMenuWindows(void)
2122 MailSession *ses = theRoamApp.session();
2123 RoamMenuWindow **rmws;
2127 rmws = (RoamMenuWindow**) malloc(_numWindows * sizeof(RoamMenuWindow *));
2128 for (win=0; win<_numWindows; win++)
2130 cname = _windows[win]->className();
2131 if (strcmp(cname, "RoamMenuWindow") == 0)
2132 rmws[nrmws++] = (RoamMenuWindow*) _windows[win];
2135 for (win=0; win<nrmws; win++)
2136 if (! ses->isActiveRMW(rmws[win])) rmws[win]->quit(TRUE);
2142 RoamApp::reopenRoamMenuWindows(void)
2144 RoamMenuWindow *rmw, **rmws;
2148 theApplication->disableShutdown();
2150 rmws = (RoamMenuWindow**) malloc(_numWindows * sizeof(RoamMenuWindow *));
2151 for (win=0; win<_numWindows; win++)
2153 cname = _windows[win]->className();
2154 if (strcmp(cname, "RoamMenuWindow") == 0)
2155 rmws[nrmws++] = (RoamMenuWindow*) _windows[win];
2158 for (win=0; win<nrmws; win++)
2162 name = strdup(rmw->mailboxName());
2165 rmw = new RoamMenuWindow(name);
2172 theApplication->enableShutdown();
2176 RoamApp::defaultStatusWindow()
2178 MainWindow *mw = NULL;
2180 if ((mw = (MainWindow *) _mailview) != NULL)
2182 if ((mw = (MainWindow *) inboxWindow()) != NULL)
2184 if (_numWindows > 0)
2185 mw = (MainWindow *) _windows[0];
2191 RoamApp::open_catalog()
2193 Application::open_catalog(); // Open Motif Application message catalog file
2194 DT_catd = catopen(DTMAIL_CAT, NL_CAT_LOCALE); // Open DtMail message catalog file