-fpermissive to allow GCC to compile old C++
[oweals/cde.git] / cde / programs / dtmail / dtmail / RoamMenuWindow.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23  /*
24  *+SNOTICE
25  *
26  *      $TOG: RoamMenuWindow.C /main/80 1999/07/07 14:23:51 mgreess $
27  *
28  *      RESTRICTED CONFIDENTIAL INFORMATION:
29  *      
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
36  *      Sun's request.
37  *
38  *      Copyright 1993, 1994, 1995 Sun Microsystems, Inc.  All rights reserved.
39  *
40  *+ENOTICE
41  */
42 /*
43  *                   Common Desktop Environment
44  *
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.
52  *                                                                   
53  *
54  *                     RESTRICTED RIGHTS LEGEND                              
55  *
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).
61
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
69  */
70
71 #include <stdio.h>
72 #include <unistd.h>
73 #include <sys/param.h>
74
75 #ifdef __uxp__
76 #include <string.h>
77 #endif
78
79 #if !defined(USL) && !defined(__uxp__)
80 #include <strings.h>
81 #endif
82 #include <errno.h>
83 #include <unistd.h>
84 #include <sys/utsname.h>
85 #ifdef SunOS
86 #include <sys/systeminfo.h>
87 #endif
88 #include <X11/Xlib.h>
89 #include <X11/Intrinsic.h>
90 #include <X11/cursorfont.h>
91 #include <Xm/TextF.h>
92 #include <Xm/Text.h>
93 #include <Xm/Form.h>
94 #include <Xm/RepType.h>
95 #include <Xm/PanedW.h>
96 #include <Xm/PushB.h>
97 #include <Xm/RowColumn.h>
98 #include <Xm/Label.h>
99 #include <Xm/LabelG.h>
100 #include <Xm/List.h>
101 #include <Xm/Xm.h>
102 #include <Dt/Dnd.h>
103 #include <DtMail/DtMailTypes.h>
104 #include <DtMail/IO.hh>
105 #include "SelectFileCmd.h"
106 #include "RoamMenuWindow.h"
107 #include "RoamApp.h"
108 #include "ButtonInterface.h"
109 #include "WorkingDialogManager.h"
110 #ifdef DEAD_WOOD
111 #include "QuestionDialogManager.h"
112 #endif /* DEAD_WOOD */
113 #include "MemUtils.hh"
114 #include "Help.hh"
115 #include "DtMailHelp.hh"
116 #include "MailMsg.h"
117 #include "SendMsgDialog.h"
118 #include "AttachArea.h"
119 #include "Attachment.h"
120
121 #include <DtMail/OptCmd.h>
122 #include "ComposeCmds.hh"
123 #include "EUSDebug.hh"
124
125 #include "SortCmd.hh"
126
127 extern force( Widget );
128
129  static const char * NormalIcon = "DtMail";
130  static const char * EmptyIcon = "DtMnone";
131  static const char * NewMailIcon = "DtMnew";
132  static const char * MailDragIcon = "DtMmsg";
133
134 extern nl_catd  DtMailMsgCat;
135 #define MAXIMUM_PATH_LENGTH     2048
136
137 #define         RMW_CONCAT_MAILRC_KEY(buf, pfx, key) \
138 { if (NULL==(pfx)) (void) sprintf((buf), "%s", (key)); \
139   else (void) sprintf((buf), "%s_%s", (pfx), (key)); }
140
141 char *
142 RoamMenuWindow:: _supported[] =
143 {
144   "TARGETS", "MESSAGES", "STRING", "DELETE"
145 };
146 enum {TARGETS,MESSAGES, STR, DEL};
147
148 XtResource
149 RoamMenuWindow::_resources[] =
150 {
151   {
152     "fullheader",
153     "FullHeader",
154     XtRBoolean,
155     sizeof( Boolean ),
156     XtOffset ( RoamMenuWindow *, _full_header_resource ),
157     XtRBoolean,
158     ( XtPointer ) 0,
159   },
160
161   {
162     "mailbox",
163     "MailBox",
164     XtRString,
165     sizeof( XtRString ),
166     XtOffset ( RoamMenuWindow *, _mailbox_name_resource ),
167     XtRString,
168     ( XtPointer ) NULL,
169   },
170
171   {
172     "mailfiles",
173     "MailFiles",
174     XtRString,
175     sizeof( XtRString ),
176     XtOffset ( RoamMenuWindow *, _mail_files_resource ),
177     XtRString,
178     ( XtPointer ) NULL,
179   },
180
181 };
182
183
184 // We need to maintain a constant WM_CLASS_NAME for SQE test
185 // suites to run consistently for all RMWs.  We do that by
186 // maintaining a constant "name", as in WM_CLASS_NAME, for all
187 // RMWs by passing "dtmail" to a RMW's parent
188 // at creation time.  We distinguish individual RMWs via the
189 // title which indicates what mail container they are currently
190 // looking at.  The title is passed here as name; its dynamic
191 // (i.e., each RMW has its own "name", as in WM_NAME).
192 // If you are going to change the name, talk to SQE
193 // and get their consent for whatever change you are making.
194 //
195 // Note also that the name chosen must match whatever is specified
196 // in dtwm.fp (front panel configuration file) as the CLIENT_NAME
197 // for the Mail CONTROL. This is so PUSH_RECALL works.
198 // Typically this is the executable name.
199
200 RoamMenuWindow::RoamMenuWindow (char *name) : MenuWindow ("dtmail", True)
201 {
202     DtMailEnv mail_error;
203     
204     // Initialize mail_error.
205     mail_error.clear();
206     
207     // Get a handle to the Inbox.
208     char                *mail_file = NULL;
209     DtMailObjectSpace   space;
210     DtMail::Session     *d_session = theRoamApp.session()->session();
211     DtMail::MailRc      *mailrc = d_session->mailRc(mail_error);
212     const char          *value = NULL;
213     char                *buffer = NULL;
214
215     _forward_filename = NULL;
216     // Set the _mailbox_name here.  
217     // In the absence of the RMW's title being set via title(),
218     // the _mailbox_name is what will be used in initialize().
219     _mailbox_name = NULL;
220     if (name)
221       mailboxName(name);
222     else
223       mailboxName("");
224     _mailbox_fullpath = NULL;
225
226     _mailbox_name_resource = NULL;
227     _mail_files_resource = NULL;
228     _full_header_resource = FALSE;
229
230     _required_conversion = FALSE;
231     _checkformail_when_mapped = FALSE;
232     _delete_on_quit = FALSE;
233     _we_called_newmail = FALSE;
234
235     _dialogs = NULL;
236     _numDialogs = 0;
237     _findDialog = NULL;
238
239     //
240     // ContainerList
241     //
242     _display_cached_list = FALSE;
243     _max_cached_list_size = 0;
244     _first_cached_item = 0;
245     _user_containerlist = NULL;
246     _cached_containerlist = NULL;
247     _filemenu2 = NULL;
248
249     //
250     // File Menu
251     //
252     _file_cmdlist = NULL;
253     _file_separator = NULL;
254     _file_check_new_mail = NULL;
255     _file_open_inbox    = NULL;
256     _file_new_container = NULL;
257     _file_open  = NULL;
258     _file_destroy_deleted_msgs = NULL;
259     _file_quit  = NULL;
260
261     _file_cascade = NULL;
262
263     //
264     // OpenContainer Cascade Menu
265     //
266     _open_container_cmdlist = NULL;
267     _open_container_separator = NULL;
268     _open_container_inbox = NULL;
269     _open_container_other = NULL;
270
271     _open_container_containerlist = NULL;
272     _open_container_containerlist_cached = NULL;
273     _opencontainerMenu = NULL;
274
275     //
276     // Message Menu
277     //
278     _msg_cmdlist = NULL;
279     _msg_separator = NULL;
280     _msg_open = NULL;
281     _msg_save_as = NULL;
282     _msg_print = NULL;
283     _msg_find = NULL;
284     _msg_select_all = NULL;
285     _msg_delete = NULL;
286     _msg_undelete_last = NULL;
287     _msg_undelete_from_list = NULL;
288     
289
290     //
291     // CopyTo Cascade Menu
292     //
293     _copyto_cmdlist = NULL;
294     _copyto_separator = NULL;
295     _copyto_inbox = NULL;
296     _copyto_other = NULL;
297
298     _copyto_containerlist = NULL;
299     _copyto_containerlist_cached = NULL;
300     _copytoMenu = NULL;
301     _message_cascade = NULL;
302     
303
304     //
305     // Edit Menu
306     //
307     _edit_cmdlist = NULL;
308     _edit_copy = NULL;
309     _edit_select_all = NULL;
310
311
312     //
313     // Attachment menu
314     //
315     _att_cmdlist = NULL;
316     _att_save = NULL;
317     _att_select_all = NULL;
318
319     //
320     // View Menu
321     //
322     _view_cmdlist = NULL;
323     _view_separator = NULL;
324     _view_next = NULL;
325     _view_previous = NULL;
326     _view_abbrev_headers = NULL;
327     _view_sortTD = NULL;
328     _view_sortSender = NULL;    
329     _view_sortSubject = NULL;   
330     _view_sortSize = NULL;      
331     _view_sortStatus = NULL;
332     
333     //
334     // Compose Menu
335     //
336     _comp_cmdlist = NULL;
337     _comp_separator = NULL;
338     _comp_new = NULL;
339     _comp_new_include = NULL;
340     _comp_forward = NULL;
341     _comp_replySender = NULL;
342     _comp_replyAll = NULL;
343     _comp_replySinclude = NULL;
344     _comp_replyAinclude = NULL;
345     
346     
347     //
348     // Move Menu
349     //
350     _move_cmdlist = NULL;
351     _move_separator = NULL;
352     _move_inbox = NULL;
353     _move_other = NULL;
354
355     _move_containerlist = NULL;
356     _move_containerlist_cached = NULL;
357     _moveMenu = NULL;
358     _move_cascade = NULL;
359
360
361     // Help Menu
362     _help_cmdlist = NULL;
363     _help_separator = NULL;
364     _help_overview = NULL;
365     _help_tasks = NULL;
366     _help_reference = NULL;
367     _help_on_item = NULL;
368     _help_using_help = NULL;
369     _help_about_mailer = NULL;
370     
371     //
372     // Message Popup
373     //
374     _msgsPopup_cmdlist = NULL;
375     _msgsPopup_separator = NULL;
376
377     _menuPopupMsgs = NULL;
378     _msgsPopupMenu = NULL;
379     _msgsPopupMoveMenu = NULL;
380     
381     //
382     // Text Popup
383     //
384     _textPopup_cmdlist = NULL;
385     _textPopup_separator = NULL;
386     
387     //
388     // Attachment Popup
389     //
390     _attPopup_cmdlist = NULL;
391     _attPopup_separator = NULL;
392     _attActions_cmdlist = NULL;
393
394     _attachmentMenu = NULL;
395
396     //
397     // ConvertContainerCmd
398     //
399     _convertContainerCmd = NULL;
400     _openContainerCmd = NULL;
401
402     //
403     // Message view pane buttons
404     //
405     _delete_button = NULL;
406     _next_button = NULL;
407     _previous_button = NULL;
408     _replySender_button = NULL;
409     _print_button = NULL;
410     _move_copy_button = NULL;
411
412     
413     _mailbox    = NULL;
414     d_session->queryImpl(mail_error,
415                          d_session->getDefaultImpl(mail_error),
416                          DtMailCapabilityInboxName,
417                          &space,
418                          &mail_file);
419     if (strcmp(mail_file, mailboxName()) == 0)
420       _inbox = TRUE;
421     else
422       _inbox = FALSE;
423
424     if (NULL != mail_file)
425       free((void*)mail_file);
426
427     _list       = NULL;
428     _genDialog  = NULL;
429
430     //
431     // Initialize private variables
432     //
433     _mbox_image = NULL;
434     _mbox_mask  = NULL;
435
436     _my_editor = NULL;
437     _message = NULL;
438     _message_summary = NULL;
439     _rowOfLabels = NULL;
440     _rowOfButtons = NULL;
441     _rowOfMessageStatus = NULL;
442
443     _quitWorkprocID = 0;
444     _clear_message_p = FALSE;
445     _is_loaded = FALSE;
446
447
448     buffer = XtMalloc(BUFSIZ);
449     if (buffer)
450     {
451         if (_inbox)
452         {
453             RMW_CONCAT_MAILRC_KEY(buffer, DTMAS_INBOX, "sortby");
454         }
455         else
456         {
457             RMW_CONCAT_MAILRC_KEY(buffer, mailboxName(), "sortby");
458         }
459     }
460     
461     mail_error.clear();
462     mailrc->getValue(mail_error, buffer, &value);
463     if (mail_error.isSet() || NULL == value)
464       _last_sorted_by = SortTimeDate;
465     else
466       _last_sorted_by = (SortBy) atoi(value);
467
468     if (NULL != value) free((void*) value);
469     if (NULL != buffer) XtFree(buffer);
470
471 }
472
473 RoamMenuWindow::~RoamMenuWindow() 
474 {
475     DtMailEnv   error;
476
477     error.clear();
478     theRoamApp.session()->close(error, _mailbox);
479     if (error.isSet()) {
480         // Cannot return error to caller since there's
481         // no caller.  What do we do?
482         // exit(0)??
483     }
484     
485     if (NULL != _forward_filename)
486       free(_forward_filename);
487     if (_mailbox_name)
488         free((void*) _mailbox_name);
489     if (_mailbox_fullpath)
490         free((void*) _mailbox_fullpath);
491
492     if (NULL != _dialogs)
493         delete []_dialogs;
494     if (NULL != _findDialog)
495       delete _findDialog;
496
497
498     // ContainerLists
499     if (NULL != _user_containerlist)
500       delete _user_containerlist;
501     if (NULL != _cached_containerlist)
502       delete _cached_containerlist;
503     if (NULL != _filemenu2)
504       free((void*) _filemenu2);
505
506     // File Menu
507     delete      _file_cmdlist;
508     delete      _file_separator;
509     delete      _file_check_new_mail;
510     delete      _file_open_inbox;
511     delete      _file_new_container;
512 #if defined(USE_OLD_FILE_OPEN)
513     delete      _file_open;
514 #endif
515     delete      _file_destroy_deleted_msgs;
516     delete      _file_quit;
517
518     // OpenContainer Cascade Menu
519     delete      _open_container_cmdlist;
520     delete      _open_container_separator;
521     delete      _open_container_inbox;
522     delete      _open_container_other;
523
524     if (NULL != _open_container_containerlist)
525       delete _open_container_containerlist;
526     if (NULL != _open_container_containerlist_cached)
527       delete _open_container_containerlist_cached;
528
529
530     // Message Menu
531     delete      _msg_cmdlist;
532     delete      _msg_separator;
533     delete      _msg_open;
534     delete      _msg_save_as;
535     delete      _msg_print;
536     delete      _msg_find;
537     delete      _msg_delete;
538     delete      _msg_undelete_last;
539     delete      _msg_undelete_from_list;
540
541     // CopyTo Cascade Menu
542     delete      _copyto_cmdlist;
543     delete      _copyto_separator;
544     delete      _copyto_inbox;
545     delete      _copyto_other;
546
547     if (NULL != _copyto_containerlist)
548       delete _copyto_containerlist;
549     if (NULL != _copyto_containerlist_cached)
550       delete _copyto_containerlist_cached;
551
552     // Edit Menu
553     delete      _edit_cmdlist;
554     delete      _edit_copy;
555     delete      _edit_select_all;
556
557     // Attachment menu
558     delete      _att_cmdlist;
559     delete      _att_save;
560     delete      _att_select_all;
561
562     // View Menu
563     delete      _view_cmdlist;
564     delete      _view_separator;
565     delete      _view_next;
566     delete      _view_previous;
567     delete      _view_abbrev_headers;
568     delete      _view_sortTD;
569     delete      _view_sortSender;       
570     delete      _view_sortSubject;      
571     delete      _view_sortSize; 
572     delete      _view_sortStatus;
573     
574     // Compose Menu
575     delete      _comp_cmdlist;
576     delete      _comp_separator;
577     delete      _comp_new;
578     delete      _comp_new_include;
579     delete      _comp_forward;
580     delete      _comp_replySender;
581     delete      _comp_replyAll;
582     delete      _comp_replySinclude;
583     delete      _comp_replyAinclude;
584     
585     // Move menu
586     delete      _move_cmdlist;
587     delete      _move_separator;
588     delete      _move_inbox;
589     delete      _move_other;
590
591     if (NULL != _move_containerlist)
592       delete _move_containerlist;
593     if (NULL != _move_containerlist_cached)
594       delete _move_containerlist_cached;
595
596     // Help Menu
597     delete      _help_separator;
598     delete      _help_cmdlist;
599     delete      _help_overview;
600     delete      _help_tasks;
601     delete      _help_reference;
602     delete      _help_on_item;
603     delete      _help_using_help;
604     delete      _help_about_mailer;
605     
606     // Message Popup
607     delete      _msgsPopup_cmdlist;
608     delete      _msgsPopup_separator;
609
610     delete      _menuPopupMsgs;
611
612     // Text Popup
613     delete      _textPopup_cmdlist;
614     delete      _textPopup_separator;
615
616     // Attachment Popup
617     delete      _attPopup_cmdlist;
618     delete      _attPopup_separator;
619     delete      _attActions_cmdlist;
620     
621     // ConvertContainerCmd
622     delete      _convertContainerCmd;
623     delete      _openContainerCmd;
624     
625     // Message view pane buttons
626     delete      _delete_button;
627     delete      _next_button;
628     delete      _previous_button;
629     delete      _replySender_button;
630     delete      _print_button;
631     delete      _move_copy_button;
632     
633     delete      _genDialog;
634
635     if (_list)
636     {
637         _list->shutdown();
638         delete  _list;
639     }
640
641     // Private
642     if (_mbox_image)
643         XmDestroyPixmap(XtScreen(baseWidget()), _mbox_image);
644     if (_mbox_mask)
645         XmDestroyPixmap(XtScreen(baseWidget()), _mbox_mask);
646     delete      _my_editor;
647 }
648
649 void
650 RoamMenuWindow::initialize()
651 {
652     XmRepTypeInstallTearOffModelConverter();
653     MenuWindow::initialize();
654
655     if (!this->baseWidget())
656     {
657         fprintf(
658                 stderr, 
659                 GETMSG(DT_catd, 2, 3,
660                   "Unable to initialize windows. Exiting.\n"));
661         exit(1);
662     }
663
664     busyCursor();
665     setStatus(GETMSG(DT_catd, 3, 2, "Initializing..."));
666
667     // XInternAtom(XtDisplay(this->baseWidget()) ,"STRING", False);
668     // XInternAtom(XtDisplay(this->baseWidget()) ,"MESSAGES", False);
669     getResources(_resources, XtNumber(_resources));
670     if (_mailbox_name_resource) mailboxName(_mailbox_name_resource);
671     
672     // Mailbox image & mask
673     {
674         Screen *screen = XtScreen(baseWidget());
675         char    icon_name[256];
676
677         sprintf(icon_name, "%s.m", MailDragIcon);
678         _mbox_image = XmGetPixmap(screen, icon_name,
679             BlackPixelOfScreen(screen), WhitePixelOfScreen(screen));
680
681         sprintf(icon_name, "%s.m_m.bm", MailDragIcon);
682         _mbox_mask = XmGetPixmapByDepth(screen, icon_name, 1, 0, 1);
683
684         if (_mbox_image == XmUNSPECIFIED_PIXMAP ||
685             _mbox_mask == XmUNSPECIFIED_PIXMAP)
686           _mbox_image = _mbox_mask = NULL;
687     }
688     
689     // Add an event handler for structureNotify.
690     // This EH will handle exposure, configure notifies ...
691     XtAddEventHandler(
692                 this->baseWidget(), StructureNotifyMask, False,
693                 (XtEventHandler) &RoamMenuWindow::structurenotify,
694                 (XtPointer) this);
695
696     _convertContainerCmd = new ConvertContainerCmd(
697                                         "convertContainer", 
698                                         "convertContainer", 
699                                         TRUE, this);
700     _openContainerCmd = new OpenContainerCmd(
701                                         "openContainer", 
702                                         "openContainer",
703                                         TRUE, this);
704     _genDialog = new DtMailGenDialog("Dialog", _main);
705     setIconName(NormalIcon);
706 }
707
708 Boolean
709 RoamMenuWindow::inbox()
710 {
711     return(_inbox);
712 }
713
714 Widget
715 RoamMenuWindow::createWorkArea(Widget parent)
716 {
717     Widget form1, panedW;
718     Widget form2, form3;
719     Dimension x, y, width, height, bwid;
720     VacationCmd *vacation_cmd = theRoamApp.vacation();
721
722     form1 = XmCreateForm(parent, "Work_Area",  NULL, 0);
723     XtVaSetValues(form1, XmNresizePolicy, XmRESIZE_NONE, NULL);
724
725     printHelpId("form1", form1);
726     /* add help callback */
727     // XtAddCallback(form1, XmNhelpCallback, HelpCB, helpId);
728     XtAddCallback(form1, XmNhelpCallback, HelpCB, DTMAILWINDOWID);
729
730     panedW = XtCreateManagedWidget("panedW", xmPanedWindowWidgetClass,
731                                    form1, NULL, 0);
732     printHelpId ("panedW", panedW);
733     /* add help callback */
734     // XtAddCallback(panedW, XmNhelpCallback, HelpCB, helpId);
735
736     XtVaSetValues(panedW,
737         XmNrightAttachment,XmATTACH_FORM, 
738         XmNleftAttachment,XmATTACH_FORM, 
739         XmNtopAttachment,XmATTACH_FORM,
740         XmNbottomAttachment, XmATTACH_FORM,
741         XmNsashIndent, -30,
742         XmNsashWidth, 18,
743         XmNsashHeight, 12,
744         NULL );
745
746
747     form2 = XtCreateManagedWidget("form2", xmFormWidgetClass, panedW, NULL, 0);
748     XtVaSetValues(form2, XmNallowResize, True, NULL);
749     printHelpId ("form2", form2);
750     /* add help callback */
751     // XtAddCallback(form2, XmNhelpCallback, HelpCB, helpId);
752
753     _rowOfLabels =
754       XtCreateManagedWidget("RowOfLabels", xmFormWidgetClass, form2, NULL, 0);
755
756     printHelpId("rowOfLabels", _rowOfLabels);
757     /* add help callback */
758     // XtAddCallback(_rowOfLabels, XmNhelpCallback, HelpCB, helpId);
759     XtAddCallback(
760         _rowOfLabels, XmNhelpCallback, HelpCB, DTMAILWINDOWROWOFLABELSID);
761
762     XtVaSetValues(_rowOfLabels, 
763                   XmNrightAttachment,XmATTACH_FORM, 
764                   XmNleftAttachment,XmATTACH_FORM, 
765                   XmNtopAttachment,XmATTACH_FORM,
766                   XmNtopOffset, 5,
767                   XmNorientation, XmHORIZONTAL,
768                   XmNspacing, 120,
769                   XmNmarginWidth, 10,
770                   XmNentryAlignment, XmALIGNMENT_CENTER,
771                   NULL);
772
773     _list = new MsgScrollingList( this, form2, "Message_List");
774     msgListDragSetup();
775
776     DtMailEnv error;
777     DtMail::Session *d_session = theRoamApp.session()->session();
778     DtMail::MailRc  *mailrc = d_session->mailRc(error);
779     const char      *value = NULL;
780     int             msgnums = False;
781
782     this->addToRowOfLabels(_list);
783
784     // See if the header size has changed.
785     value = NULL;
786     mailrc->getValue(error, "headerlines", &value);
787     if (error.isSet()) value = strdup("15");
788
789     int header_lines = (int) strtol(value, NULL, 10);
790     _list->visibleItems(header_lines);
791     if (NULL != value) free((void*) value);
792
793     XtAddCallback(
794         _list->get_scrolling_list(), XmNhelpCallback, 
795         HelpCB, DTMAILMSGLISTID);
796
797     XtVaSetValues(_list->get_scrolling_list(), XmNuserData, this, NULL);
798     _rowOfButtons =
799       XtCreateManagedWidget("RowColumn", xmFormWidgetClass, form2, NULL, 0);
800     printHelpId ("rowOfButtons", _rowOfButtons);
801     // Add help callback
802     // XtAddCallback(_rowOfButtons, XmNhelpCallback, HelpCB, helpId);
803
804
805     // Place it closer to the scrolling list than to the text widget
806     // that is below.
807     XtVaSetValues(XtParent(_list->get_scrolling_list()),
808                 XmNrightAttachment,XmATTACH_FORM, 
809                 XmNleftAttachment,XmATTACH_FORM, 
810                 XmNtopAttachment,XmATTACH_WIDGET,
811                 XmNtopWidget, _rowOfLabels,
812                 XmNtopOffset, 3,
813                 XmNbottomAttachment, XmATTACH_WIDGET,
814                 XmNbottomWidget, _rowOfButtons,
815                 XmNbottomOffset, 7,
816                 NULL );
817
818     XtVaSetValues(_rowOfButtons,
819                   XmNrightAttachment,XmATTACH_FORM, 
820                   XmNleftAttachment,XmATTACH_FORM, 
821                   XmNbottomAttachment, XmATTACH_FORM,
822                   XmNresizable, FALSE, 
823                   NULL );
824
825     this->addToRowOfButtons();
826
827     form3 = XtCreateManagedWidget("form3", xmFormWidgetClass, panedW, NULL, 0);
828     XtVaSetValues(form3, XmNallowResize, True, NULL);
829     printHelpId ("form3", form3);
830     // Add help callback
831     // XtAddCallback(form3, XmNhelpCallback, HelpCB, helpId);
832
833 #if 0
834     XtVaSetValues(form3,
835         XmNrightAttachment,XmATTACH_FORM, 
836         XmNleftAttachment,XmATTACH_FORM, 
837         XmNtopAttachment,XmATTACH_FORM, 
838         NULL );
839 #endif
840
841     _rowOfMessageStatus =
842       XtCreateManagedWidget("Message_Status", xmFormWidgetClass, form3, NULL,0);
843
844      XtVaSetValues(_rowOfMessageStatus,
845         XmNrightAttachment,XmATTACH_FORM, 
846         XmNleftAttachment,XmATTACH_FORM, 
847         XmNtopAttachment,XmATTACH_FORM,
848         XmNtopOffset, 5,
849         NULL );
850
851     this->addToRowOfMessageStatus();
852
853     _my_editor = new DtMailEditor(form3, this);
854     _my_editor->initialize();
855     _my_editor->attachArea()->setOwnerShell(this);
856
857     // DtMailEditor contains a widget that contains the textEditor and 
858     // attachArea.  Get that widget...
859
860     Widget wid = _my_editor->container();
861
862     printHelpId ("wid", wid);
863     /* add help callback */
864     // XtAddCallback(wid, XmNhelpCallback, HelpCB, helpId);
865
866     XtVaSetValues(wid,
867         XmNrightAttachment,XmATTACH_FORM, 
868         XmNleftAttachment,XmATTACH_FORM, 
869         XmNtopAttachment,XmATTACH_WIDGET, 
870         XmNtopWidget, _rowOfMessageStatus,
871         XmNbottomAttachment, XmATTACH_FORM,
872         NULL );
873
874     DtMailEnv mail_error;
875
876     // Initialize the mail_error.
877     mail_error.clear();
878     mailboxFullpath(mailboxName());
879
880     // Set the appShell's title to be _mailbox_fullpath
881     if (vacation_cmd != NULL && vacation_cmd->priorVacationRunning())
882       setVacationTitle();
883     else
884       setTitle(NULL);
885
886     // Set the icon name to the folder name.  Extract foldername from full path.
887     char *fname = strrchr(_mailbox_fullpath, '/');
888     if (fname == NULL)
889       setIconTitle(_mailbox_fullpath);
890     else
891     {
892         // Extract the filename from it.
893         fname++;
894         setIconTitle(fname);
895     }
896
897     XtManageChild(_list->baseWidget());
898     XtManageChild(form1);
899     
900     value = NULL;
901     mailrc->getValue(error, "retrieveinterval", &value);
902     if (error.isNotSet() && value && *value != '\0')
903     {
904         long ping = (time_t) strtol(value, NULL, 10);
905         if (ping <= 0)
906           _checkformail_when_mapped = FALSE;
907         else
908           _checkformail_when_mapped = TRUE;
909     }
910     error.clear();
911     if (NULL != value) free((void*) value);
912
913     XtVaGetValues(_main,
914                   XmNx, &x,
915                   XmNy, &y,
916                   XmNwidth, &width,
917                   XmNheight, &height,
918                   XmNborderWidth, &bwid,
919                   NULL);
920     _x = x;
921     _y = y;
922     _width = width;
923     _height = height;
924     _border_width = bwid;
925     return form1;
926 }
927
928 // This routine is just a place holder callback to pass when creating
929 // a mailbox when we doing want to do anything when the mailbox gets
930 // updated.
931 //
932 static DtMailBoolean
933 openCallback(
934         DtMailCallbackOp,
935         const char *,
936         const char *,
937         void *,
938         ...
939 )
940 {
941     return(DTM_FALSE);
942 }
943
944 // msgListTransferCallback
945 //
946 // Handles the transfer of data that is dragged and dropped to the
947 // MsgScrollingList.  Files and buffers are transferred by inserting 
948 // them as messages into the scrolling list.
949 //
950 void
951 RoamMenuWindow::msgListTransferCallback(
952     Widget      ,
953     XtPointer   clientData,
954     XtPointer   callData)
955 {
956     RoamMenuWindow *rmw = (RoamMenuWindow *) clientData;
957     DtDndTransferCallbackStruct *transferInfo =
958                         (DtDndTransferCallbackStruct *) callData;
959     DtDndContext        *dropData = transferInfo->dropData;
960     char                *filepath;
961     int                 ii, numItems;
962     DtMail::MailBox     *mbox, *tmpmbox;
963     DtMailEnv mail_error;
964     MailSession *session = theRoamApp.session();
965
966     DebugPrintf(3, "In RoamMenuWindow::msgListTransferCallback\n");
967
968     // Initialize the mail_error.
969     mail_error.clear();
970
971     numItems = dropData->numItems;
972
973     switch (dropData->protocol) {
974         case DtDND_FILENAME_TRANSFER:
975
976             // Loop through the files that were dropped onto the msg list
977
978             for (ii = 0; ii < numItems; ii++) {
979
980                 // Try to open the file as a mail container.
981                 filepath = dropData->data.files[ii];
982                 tmpmbox = session->open(
983                                 mail_error, filepath, 
984                                 &RoamMenuWindow::syncViewAndStoreCallback,
985                                 rmw, DTM_FALSE, DTM_TRUE);
986
987                 // Reject the drop if we weren't able to open the file.
988                 if (!tmpmbox || mail_error.isSet()) {
989                     transferInfo->status = DtDND_FAILURE;
990                     return;
991                 } else {
992                     // We were able to open the container, so now we get the 
993                     // current mailbox and copy all the messages into it.
994                     mbox = rmw->mailbox();
995                     mbox->copyMailBox(mail_error, tmpmbox);
996                     rmw->checkForMail(mail_error);
997                     delete tmpmbox;
998                 }
999             }
1000             break;
1001
1002         case DtDND_BUFFER_TRANSFER:
1003
1004             // Loop through the buffers that were dropped onto the msg list
1005
1006             for (ii = 0; ii < numItems; ii++) {
1007
1008                 // Turn the dropped data into a mail buffer to pass to
1009                 // the mailbox constructor.
1010                 DtMailBuffer buf;
1011                 buf.buffer = (char *) transferInfo->dropData->data.buffers->bp;
1012                 buf.size = transferInfo->dropData->data.buffers->size;
1013
1014                 // Convert the buffer into a mailbox object.
1015                 tmpmbox = session->session()->mailBoxConstruct(mail_error,
1016                                                 DtMailBufferObject, &buf,
1017                                                 openCallback, NULL);
1018
1019                 // Reject the drop if we weren't able to convert it to a mailbox
1020                 if (!tmpmbox || mail_error.isSet()) {
1021                     transferInfo->status = DtDND_FAILURE;
1022                     return;
1023                 } else {
1024                     // Parse the dropped data into the tmpmbox.
1025                     tmpmbox->open(mail_error);
1026                     if (mail_error.isSet()) {
1027                         transferInfo->status = DtDND_FAILURE;
1028                         delete tmpmbox;
1029                         return;
1030                     }
1031                     mbox = rmw->mailbox();
1032                     mbox->copyMailBox(mail_error, tmpmbox);
1033                     rmw->checkForMail(mail_error);
1034                     delete tmpmbox;
1035                 }
1036             }
1037             break;
1038
1039         default:
1040             transferInfo->status = DtDND_FAILURE;
1041             return;
1042     }
1043 }
1044
1045 // msgListDropRegister
1046 //
1047 // Register the message list to accept file & buffer drops
1048 //
1049 void
1050 RoamMenuWindow::msgListDropRegister()
1051 {
1052     static XtCallbackRec transferCBRec[] = { 
1053         {&RoamMenuWindow::msgListTransferCallback, NULL}, {NULL, NULL} };
1054
1055     // Pass the RoamMenuWindow object (this) as clientData.
1056     transferCBRec[0].closure = this;
1057
1058     DtDndVaDropRegister(_list->get_scrolling_list(),
1059             DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
1060             (unsigned char)(XmDROP_MOVE | XmDROP_COPY), transferCBRec,
1061             DtNtextIsBuffer, True,
1062             NULL);
1063 }
1064
1065 // msgListDropEnable
1066 //
1067 // Enable the message list for drops by restoring the operation
1068 //
1069 void
1070 RoamMenuWindow::msgListDropEnable()
1071 {
1072     Arg args[1];
1073
1074     XtSetArg(args[0], XmNdropSiteOperations, XmDROP_MOVE | XmDROP_COPY);
1075     XmDropSiteUpdate(_list->get_scrolling_list(), args, 1);
1076 }
1077
1078 // msgListDropDisable
1079 //
1080 // Disable the message list for drops by setting the operation to noop
1081 //
1082 void
1083 RoamMenuWindow::msgListDropDisable()
1084 {
1085     Arg args[1];
1086
1087     XtSetArg(args[0], XmNdropSiteOperations, XmDROP_NOOP);
1088     XmDropSiteUpdate(_list->get_scrolling_list(), args, 1);
1089 }
1090
1091
1092 // msgListConvertCallback
1093 //
1094 // Provide the msg list as a mailbox for the drag
1095 //
1096 void
1097 RoamMenuWindow::msgListConvertCallback(
1098     Widget      /* dragContext */,
1099     XtPointer   clientData,
1100     XtPointer   callData)
1101 {
1102     DtDndConvertCallbackStruct *convertInfo =
1103                             (DtDndConvertCallbackStruct *) callData;
1104     DtDndBuffer         *buffer = &(convertInfo->dragData->data.buffers[0]);
1105     RoamMenuWindow      *rmw = (RoamMenuWindow *)clientData;
1106     MsgScrollingList    *msgList;
1107     Widget              listW;
1108     DtMail::MailBox     *mbox;
1109     DtMail::Message     *msg;
1110     DtMailMessageHandle msgHandle;
1111     DtMailBuffer        *mbufList;
1112     int                 *pos_list, pos_count, ii;
1113     unsigned long       bufSize = 0;
1114     char                *bufPtr;
1115     DtMailEnv           error;
1116
1117     DebugPrintf(3, "In RoamMenuWindow:msgListConvertCallback\n");
1118
1119     error.clear();
1120
1121     switch (convertInfo->reason) {
1122         case DtCR_DND_CONVERT_DATA:
1123
1124             msgList = rmw->list();
1125             listW = msgList->get_scrolling_list();
1126             mbox = rmw->mailbox();
1127
1128             if (!XmListGetSelectedPos(listW, &pos_list, &pos_count)) {
1129                 convertInfo->status = DtDND_FAILURE;
1130                 return;
1131             }
1132
1133             mbufList = (DtMailBuffer*)XtMalloc(pos_count*sizeof(DtMailBuffer));
1134         
1135             for (ii = 0; ii < pos_count; ii++) {
1136                     msgHandle = msgList->msgno(pos_list[ii]);
1137                     msg = mbox->getMessage(error, msgHandle);
1138                     if (error.isSet()) {
1139                         convertInfo->status = DtDND_FAILURE;
1140                         return;
1141                     }
1142                     msg->toBuffer(error, mbufList[ii]);
1143                     if (error.isSet()) {
1144                         convertInfo->status = DtDND_FAILURE;
1145                         return;
1146                     }
1147                     bufSize += mbufList[ii].size + 1;
1148             }
1149
1150             bufPtr = XtMalloc((unsigned int)bufSize);
1151
1152             buffer->bp = bufPtr;
1153             buffer->size = (int)bufSize;
1154             buffer->name = "Mailbox";
1155
1156             for (ii = 0; ii < pos_count; ii++) {
1157                 strncpy(bufPtr, (char *)mbufList[ii].buffer, 
1158                                 (unsigned int)mbufList[ii].size);
1159                 bufPtr += mbufList[ii].size;
1160                 bufPtr[0] = '\n';
1161                 bufPtr++;
1162                 delete mbufList[ii].buffer;
1163             }
1164
1165             XtFree((char *)mbufList);
1166             XtFree((char *)pos_list);
1167             break;
1168
1169         case DtCR_DND_CONVERT_DELETE:
1170             // The drag and drop succeeded, so we can now delete the messages
1171             // from the scrolling list.
1172             rmw->list()->deleteSelected();
1173             break;
1174     }
1175 }
1176
1177 // msgListDragFinishCallback
1178 //
1179 // Clean up from the convert callback and restore state
1180 //
1181 void
1182 RoamMenuWindow::msgListDragFinishCallback(
1183         Widget          /* widget */,
1184         XtPointer       clientData,
1185         XtPointer       callData)
1186 {
1187     DtDndDragFinishCallbackStruct *finishInfo =
1188                 (DtDndDragFinishCallbackStruct *) callData;
1189     DtDndContext        *dragData = finishInfo->dragData;
1190     RoamMenuWindow      *rmw = (RoamMenuWindow *) clientData;
1191     MsgScrollingList    *msgList = rmw->list();
1192     DtMailEnv           mail_error;
1193     int                 ii;
1194
1195     DebugPrintf(3, "In RoamMenuWindow::msgListDragFinishCallback\n");
1196
1197     mail_error.clear();
1198
1199     // Re-enable drops on this message list
1200     if (rmw->mailbox()->mailBoxWritable(mail_error) == DTM_TRUE) {
1201         rmw->msgListDropEnable();
1202     }
1203
1204     if (finishInfo->sourceIcon)
1205         XtDestroyWidget(finishInfo->sourceIcon);
1206
1207     // Free any memory allocated for the drag.
1208     for (ii = 0; ii < dragData->numItems; ii++) {
1209         XtFree((char *)dragData->data.buffers[ii].bp);
1210     }
1211
1212 }
1213
1214 // getDragIcon
1215 //
1216 // Use the mailbox pixmap to create a drag icon
1217 //
1218 Widget
1219 RoamMenuWindow::getDragIcon(
1220         Widget          widget)
1221 {
1222     if (_mbox_image && _mbox_mask) {
1223         return DtDndCreateSourceIcon(widget, _mbox_image, _mbox_mask);
1224     } else {
1225         return NULL;
1226     }
1227 }
1228
1229 // msgListDragStart
1230 //
1231 // Translation start a drag from the msg list
1232 //
1233 XtActionProc
1234 RoamMenuWindow::msgListDragStart(
1235         Widget          widget,
1236         XEvent          *event,
1237         String          * /* params */,
1238         Cardinal        * /* numParams */)
1239 {
1240     static XtCallbackRec convertCBRec[] = { 
1241         {&RoamMenuWindow::msgListConvertCallback, NULL},{NULL, NULL} };
1242     static XtCallbackRec dragFinishCBRec[] = {
1243         {&RoamMenuWindow::msgListDragFinishCallback, NULL}, {NULL, NULL} };
1244     RoamMenuWindow      *rmw = NULL;
1245     unsigned char       operations;
1246     Widget              drag_icon;
1247     DtMailEnv           mail_error;
1248
1249     DebugPrintf(3, "In RoamMenuWindow::msgListProcessDrag\n");
1250
1251     mail_error.clear();
1252
1253     XtVaGetValues(widget, XmNuserData, &rmw, NULL);
1254
1255     if (rmw == NULL)
1256         return NULL;
1257
1258     drag_icon = rmw->getDragIcon(widget);
1259     //drag_icon = NULL;
1260
1261     rmw->msgListDropDisable();
1262
1263     // Choose the drag operations based on the writeability of the mailbox
1264
1265     if (rmw->mailbox()->mailBoxWritable(mail_error) == DTM_TRUE) {
1266         // RW Folder.  Permit Copy and Move.
1267         operations = (unsigned char)(XmDROP_COPY | XmDROP_MOVE);
1268     } else {
1269         // RO Folder.  Permit only Copy drags.
1270         operations = (unsigned char)XmDROP_COPY;
1271     }
1272
1273     // Start the drag
1274
1275     convertCBRec[0].closure = (XtPointer) rmw;
1276     dragFinishCBRec[0].closure = (XtPointer) rmw;
1277
1278     if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, 1,
1279                         operations, convertCBRec, dragFinishCBRec,
1280                         DtNsourceIcon, drag_icon,
1281                         NULL) == NULL) {
1282         DebugPrintf(3, "DragStart returned NULL.\n");
1283     }
1284
1285     return NULL;
1286 }
1287
1288 /* ARGSUSED */
1289 Bool
1290 RoamMenuWindow::msgListLookForButton (
1291         Display *,
1292         XEvent * event,
1293         XPointer arg)
1294 {
1295
1296 #define DAMPING 5
1297 #define ABS_DELTA(x1, x2) (x1 < x2 ? x2 - x1 : x1 - x2)
1298
1299     if( event->type == MotionNotify)  {
1300         XEvent * press = (XEvent *) arg;
1301
1302         if (ABS_DELTA(press->xbutton.x_root, event->xmotion.x_root) > DAMPING ||
1303             ABS_DELTA(press->xbutton.y_root, event->xmotion.y_root) > DAMPING)
1304             return(True);
1305     }
1306     else if (event->type == ButtonRelease)
1307         return(True);
1308     return(False);
1309 }
1310
1311 // msgListProcessPress
1312 //
1313 // Translation implementing Motif 1.2.5 ProcessPress function
1314 //
1315
1316 #define SELECTION_ACTION        0
1317 #define TRANSFER_ACTION         1
1318
1319 void
1320 RoamMenuWindow::msgListProcessPress(
1321         Widget          w,
1322         XEvent          *event,
1323         String          *params,
1324         Cardinal        *num_params)
1325 {
1326    int i, action, cur_item;
1327    int *selected_positions, nselected_positions;
1328
1329    DebugPrintf(3, "In RoamMenuWindow::msgListProcessPress\n");
1330
1331    //  This action happens when Button1 is pressed and the Selection
1332    //  and Transfer are integrated on Button1.  It is passed two
1333    //  parameters: the action to call when the event is a selection,
1334    //  and the action to call when the event is a transfer.
1335
1336     if (*num_params != 2 || !XmIsList(w))
1337       return;
1338
1339     action = SELECTION_ACTION;
1340     cur_item = XmListYToPos(w, event->xbutton.y);
1341
1342     if (cur_item > 0)
1343     {
1344         XtVaGetValues(w,
1345                 XmNselectedPositions, &selected_positions,
1346                 XmNselectedPositionCount, &nselected_positions,
1347                 NULL);
1348
1349         for (i=0; i<nselected_positions; i++)
1350         {
1351             if (cur_item == selected_positions[i])
1352             {
1353                 // The determination of whether this is a transfer drag
1354                 // cannot be made until a Motion event comes in.  It is
1355                 // not a drag as soon as a ButtonUp event happens.
1356                 XEvent new_event;
1357                 
1358                 XPeekIfEvent(
1359                         XtDisplay(w),
1360                         &new_event,
1361                         &RoamMenuWindow::msgListLookForButton,
1362                         (XPointer) event);
1363                 switch (new_event.type)
1364                 {
1365                     case MotionNotify:
1366                        action = TRANSFER_ACTION;
1367                        break;
1368                     case ButtonRelease:
1369                        action = SELECTION_ACTION;
1370                        break;
1371                 }
1372                 break;
1373             }
1374         }
1375     }
1376
1377     XtCallActionProc(w, params[action], event, params, *num_params);
1378 }
1379
1380 // msgListDragSetup
1381 //
1382 // Override default list translations to start our own drags
1383 //
1384 void
1385 RoamMenuWindow::msgListDragSetup()
1386 {
1387     Widget msgList = _list->get_scrolling_list();
1388     static char translations[] = "\
1389                 ~c ~s ~m ~a <Btn1Down>:\
1390                     dt-process-press(ListBeginSelect,MsgListDragStart)\n\
1391                 c ~s ~m ~a <Btn1Down>:\
1392                     dt-process-press(ListBeginToggle,MsgListDragStart)";
1393     static char btn2_translations[] = "\
1394                 ~c ~s ~m ~a <Btn2Down>:\
1395                     dt-process-press(ListBeginSelect,MsgListDragStart)\n\
1396                 c ~s ~m ~a <Btn2Down>:\
1397                     dt-process-press(ListBeginToggle,MsgListDragStart)\n\
1398                 <Btn2Motion>:ListButtonMotion()\n\
1399                 ~c ~s ~m ~a <Btn2Up>:ListEndSelect()\n\
1400                 c ~s ~m ~a <Btn2Up>:ListEndToggle()";
1401     int         btn1_transfer = 0;
1402     XtTranslations      new_translations;
1403     static XtActionsRec actionTable[] = {
1404         {"MsgListDragStart", 
1405         (XtActionProc) &RoamMenuWindow::msgListDragStart},
1406         {"dt-process-press", 
1407         (XtActionProc) &RoamMenuWindow::msgListProcessPress}
1408     };
1409
1410     DebugPrintf(3, "In RoamMenuWindow::msgListDragSetup\n");
1411
1412     XtAppAddActions(
1413                 theRoamApp.appContext(),
1414                 actionTable,
1415                 sizeof(actionTable)/sizeof(actionTable[0]));
1416     new_translations = XtParseTranslationTable(translations);
1417     XtOverrideTranslations(msgList, new_translations);
1418
1419     XtVaGetValues(
1420         (Widget)XmGetXmDisplay(XtDisplayOfObject(msgList)),
1421         "enableBtn1Transfer", &btn1_transfer,
1422         NULL);
1423     
1424     if (btn1_transfer != True) {
1425         new_translations = XtParseTranslationTable(btn2_translations);
1426         XtOverrideTranslations(msgList, new_translations);
1427     }
1428 }
1429
1430 void
1431 RoamMenuWindow::open_and_load(
1432     DtMailEnv &error,
1433     DtMailBoolean create,
1434     DtMailBoolean lock)
1435 {
1436     _openContainerCmd->set_create_lock_flags(create, lock);
1437     _openContainerCmd->execute();
1438
1439     // if it required conversion, let conversion handle the error
1440     // (its a callback routine and we have "lost control" of what
1441     // it returns anyway.)
1442     // 
1443     // if it did not require conversion, then open() should have succeeded.
1444     // If it did succeed, then its _mailbox should be set by now.
1445     // If its not set, then either open() failed somewhere or it was
1446     // cancelled by the user.  We now have an error condition.
1447     if ((!_required_conversion) && (_mailbox == NULL))
1448     {
1449         error.setError(DTME_NoMailBox);
1450         return;
1451     }
1452
1453     // If it required conversion, then let the conversion process handle
1454     // errors if any occur.
1455     // Reset the DtMailEnv for this method.
1456     if (_required_conversion) error.clear();
1457
1458     // If it required conversion, and conversion succeeded, then the
1459     // mailbox was also loaded and _is_loaded gets set to TRUE.
1460     // If it required no conversion, then it implies that we already
1461     // have a container in hand and we just load it (implicitly
1462     // setting _is_loaded to TRUE)
1463     if ((!_required_conversion) && (_is_loaded == FALSE))
1464     {
1465         this->load_mailbox(error);
1466         _is_loaded = TRUE;
1467     }
1468 }
1469
1470
1471 // Ideally, open() should set the error if the user cancels the open.  
1472 // And we should error after open() returns at the caller's end...
1473
1474 void
1475 RoamMenuWindow::open(
1476     DtMailEnv & error, 
1477     DtMailBoolean create_flag, 
1478     DtMailBoolean lock_flag
1479 )
1480 {
1481     FORCE_SEGV_DECL(char, tmp);
1482     Dimension win_x, win_y, win_wid, win_ht, win_bwid;
1483     MailSession *ses = theRoamApp.session();
1484     int answer = 0;
1485     char *helpId;
1486
1487     char *buf = new char[2*MAXPATHLEN];
1488
1489     _openContainerCmd->set_create_lock_flags(create_flag, lock_flag);
1490
1491     // Obtain the current dimensions of the RMW
1492     XtVaGetValues(_main,
1493                   XmNx, &win_x,
1494                   XmNy, &win_y,
1495                   XmNwidth, &win_wid,
1496                   XmNheight, &win_ht,
1497                   XmNborderWidth, &win_bwid,
1498                   NULL);
1499     _x = win_x;
1500     _y = win_y;
1501     _width = win_wid;
1502     _height = win_ht;
1503     _border_width = win_bwid;
1504
1505     // Check to see if the mbox is already open.  If it is, we will
1506     // simply make sure it's displayed in the current workspace.
1507     if (ses->isMboxOpen(_mailbox_fullpath))
1508     {
1509         RoamMenuWindow *rmw = NULL;
1510         rmw = ses->getRMW(_mailbox_fullpath);
1511         if (NULL != rmw)
1512         {
1513             ses->activateRMW(rmw);
1514             rmw->displayInCurrentWorkspace();
1515         }
1516         return;
1517     }
1518
1519     // Try to open this folder, but don't take the lock and and don't create it.
1520     _mailbox = ses->open(error, _mailbox_fullpath, 
1521                          &RoamMenuWindow::syncViewAndStoreCallback,
1522                          this, create_flag, lock_flag);
1523     if (error.isSet())
1524     {
1525         if((DTMailError_t) error == DTME_OutOfSpace )
1526         {
1527               ShowErrMsg((char *)error.getClient(),FALSE,(void*)this );
1528               error.setClient(NULL);
1529               delete [] buf;
1530               return;
1531         }
1532         
1533         // Did we ask for a non-existent file?
1534         if ((DTMailError_t)error == DTME_NoSuchFile)
1535         {
1536             // if (create_flag == DTM_TRUE)
1537             if (create_flag == DTM_FALSE)
1538             {
1539                 sprintf(buf,
1540                         GETMSG(DT_catd, 
1541                                 3, 3, 
1542                                 "The mailbox %s does not exist.\nCreate a mailbox with this name?"),
1543                         _mailbox_fullpath);
1544                 _genDialog->setToQuestionDialog(GETMSG(DT_catd, 
1545                                                         3, 4, "Mailer"),
1546                                              buf);
1547                 helpId = DTMAILHELPERROR;
1548                 answer = _genDialog->post_and_return(GETMSG(DT_catd, 
1549                                                              3, 5, 
1550                                                              "OK"), 
1551                                                      GETMSG(DT_catd,
1552                                                              1, 5,
1553                                                              "Cancel"),
1554                                                      helpId);
1555
1556                 if (answer == 1) open(error, DTM_TRUE, lock_flag);
1557                 if (answer == 2) {
1558                     delete [] buf;
1559                     return;
1560                 }
1561             }
1562             else {
1563                 // A special case should be taken care
1564                 // The create_flag is TRUE but still can not be created
1565                 //      This is because the path is something like
1566                 //      /valid_path/not_such_dir/file_name.
1567                 //     The full file path is not valid so that we need flag
1568                 //     an error
1569                 sprintf(buf,
1570                         GETMSG(DT_catd,
1571                                 3, 44,
1572                                 "Unable to create %s."),
1573                         _mailbox_fullpath);
1574                 _genDialog->setToQuestionDialog(GETMSG(DT_catd,
1575                                                         3, 4, "Mailer"),
1576                                              buf);
1577                 helpId =  DTMAILHELPNOCREATE;
1578                 answer = _genDialog->post_and_return(GETMSG(DT_catd,
1579                                                              3, 5,
1580                                                              "OK"),
1581                                                      helpId);
1582                delete [] buf;
1583                return;
1584             }
1585         }
1586         else if (((DTMailError_t)error == DTME_OtherOwnsWrite) ||
1587                  ((DTMailError_t)error == DTME_AlreadyLocked))
1588         {
1589             // See if they want to take the lock.
1590 //          sprintf(buf, 
1591 //                  GETMSG(DT_catd, 3, 6, "The mailbox %s is locked.\n\
1592 // You can manually unlock the mailbox and try again\n\
1593 // or contact your System Administrator."),
1594 //                 _mailbox_fullpath);
1595
1596 //          _genDialog->setToErrorDialog(
1597 //                              GETMSG(DT_catd, 3, 7, "Mailer"),
1598 //                              buf);
1599 //          helpId = DTMAILHELPTAKELOCK;
1600 //          _genDialog->post_and_return(
1601 //                              GETMSG(DT_catd, 3, 8, "OK"),
1602 //                              helpId);
1603
1604 //          error.setError(DTME_GetLockRefused);
1605             // The above else-if code doesn't make sense.  If ses->open() failed
1606             // because the folder was already locked or not writable then 
1607             // posting the specified error dialog and setting the error to GetLockRefused
1608             // is meaningless.  Especially since the calling function 
1609             // OpenContainerCmd::doit() doesn't even check the error we 
1610             // return.  Lets post a meaningful error dialog and return.
1611             postErrorDialog(error);
1612             delete [] buf;
1613             return;
1614         }
1615         else if ((DTMailError_t)error == DTME_BadRunGroup)
1616         {
1617
1618             sprintf(buf, GETMSG(DT_catd, 2, 4,
1619                    "Mailer has not been properly installed,\n\
1620 and cannot run because the execution group\n\
1621 is incorrectly set."));
1622
1623             _genDialog->setToQuestionDialog(
1624                                 GETMSG(DT_catd, 1, 6, "Mailer"),
1625                                 buf);
1626             
1627             // No choice at this state other than to OK.
1628
1629             helpId = DTMAILHELPBADGROUPID;
1630             answer = _genDialog->post_and_return(
1631                                 GETMSG(DT_catd, 3, 9, "OK"),
1632                                 helpId);
1633             delete [] buf;
1634             return;
1635
1636         }
1637         else if ((DTMailError_t)error == DTME_NoPermission)
1638         {
1639             /* NL_COMMENT
1640              * The %s is the name of the mailbox the user doesn't have
1641              * permission to view.
1642              */
1643             sprintf(buf, GETMSG(DT_catd, 2, 5,
1644                    "You do not have permission to view %s"), _mailbox_fullpath);
1645
1646             _genDialog->setToQuestionDialog(
1647                                 GETMSG(DT_catd, 1, 7, "Mailer"),
1648                                 buf);
1649             
1650             // No choice at this state other than to OK.
1651
1652             helpId = DTMAILHELPNOVIEW;
1653             answer = _genDialog->post_and_return(
1654                                 GETMSG(DT_catd, 3, 10, "OK"),
1655                                 helpId);
1656             delete [] buf;
1657             return;
1658         }
1659         else if ((DTMailError_t)error == DTME_IsDirectory)
1660         {
1661             sprintf(buf, GETMSG(DT_catd, 2, 6,
1662                     "The mailbox %s is a directory and can not be opened."),
1663                     _mailbox_fullpath);
1664
1665             _genDialog->setToQuestionDialog(GETMSG(DT_catd, 1, 8, "Mailer"),
1666                                             buf);
1667
1668             helpId = DTMAILHELPDIRECTORYONLY;
1669             answer = _genDialog->post_and_return(GETMSG(DT_catd, 3, 11, "OK"),
1670                                                  helpId);
1671             delete [] buf;
1672             return;
1673         }
1674         else if ((DTMailError_t)error == DTME_AlreadyOpened)
1675         {
1676            sprintf(buf, GETMSG(DT_catd,20,1,
1677                    "The mailbox %s is already open."), _mailbox_fullpath);
1678  
1679            _genDialog->setToQuestionDialog(GETMSG(DT_catd, 1, 8, "Mailer"),
1680                                            buf);
1681  
1682            // there is no help message for this error
1683            // open a defect and put helpId later
1684            helpId = NULL;
1685            answer = _genDialog->post_and_return(GETMSG(DT_catd, 3, 11, "OK"),
1686                                                 helpId);
1687            delete [] buf;
1688            return;
1689         }
1690         else
1691         {
1692             // This is a real error. Punt!
1693             this->postErrorDialog(error);
1694         }
1695     }
1696
1697     if(_mailbox)
1698     {
1699         if (_mailbox->mailBoxWritable(error) == DTM_TRUE)
1700           msgListDropRegister();
1701         _mailbox->registerErrMsgFunc(ShowErrMsg,this);
1702         if (isIconified())
1703           _mailbox->hideAccessEvents(DTM_TRUE);
1704         else
1705           _mailbox->hideAccessEvents(DTM_FALSE);
1706     }
1707     delete [] buf;
1708     return;
1709 }
1710
1711 void RoamMenuWindow::createMenuPanes()
1712 {
1713     this->createContainerList();
1714
1715     this->construct_file_menu();
1716
1717     this->construct_message_menu();
1718
1719     this->construct_edit_menu();
1720
1721     this->construct_attachment_menu();
1722
1723     this->construct_view_menu();
1724
1725     this->construct_compose_menu();
1726
1727     this->construct_move_menu();
1728
1729     this->construct_help_menu();
1730
1731     this->construct_message_popup();
1732
1733     this->construct_text_popup();
1734
1735     this->construct_attachment_popup();
1736
1737     this->syncCachedContainerList();
1738
1739 }
1740
1741 void
1742 RoamMenuWindow::resetCacheList(int new_size)
1743 {
1744     // Remove the extra items in the list
1745     for (int i = _cached_containerlist->length(); i > new_size; i--) {
1746
1747         _cached_containerlist->remove(i-1);
1748         _open_container_containerlist_cached->remove(i-1);
1749         _copyto_containerlist_cached->remove(i-1);
1750         _move_containerlist_cached->remove(i-1);
1751
1752         _menuBar->removeCommand(_opencontainerMenu, _first_cached_item+i-1);
1753         _menuBar->removeCommand(_copytoMenu, _first_cached_item+i-1);
1754         _menuBar->removeCommand(_moveMenu, _first_cached_item+i-1);
1755         _menuBar->removeCommand(_msgsPopupMoveMenu, _first_cached_item+i-1);
1756     }
1757 }
1758
1759 void
1760 RoamMenuWindow::propsChanged(void)
1761 {
1762     MailSession         *ses = theRoamApp.session();
1763     DtMail::Session     *d_session = ses->session();
1764     DtMail::MailRc      *mailrc = get_mail_rc();
1765     DtMailEnv            error;
1766     const char          *value = NULL;
1767     char                *inbox_path = NULL;
1768     DtMailObjectSpace    space;
1769     Boolean              should_be_inbox;
1770
1771     if (! _is_loaded) return;
1772     enableWorkAreaResize();
1773
1774     d_session->queryImpl(
1775                         error,
1776                         d_session->getDefaultImpl(error),
1777                         DtMailCapabilityInboxName,
1778                         &space,
1779                         &inbox_path);
1780     should_be_inbox = (inbox_path && 0 == strcmp(inbox_path, mailboxName()));
1781
1782     RoamMenuWindow      *rmw = NULL;
1783     char                *password = NULL;
1784     password = MailRetrievalOptions::getPassword(DTMAS_INBOX);
1785
1786     if (_inbox != should_be_inbox)
1787     {
1788
1789         if (_inbox)
1790         {
1791             char buf[2048];
1792             int answer;
1793
1794             //
1795             // Remove inbox attributes
1796             //
1797             displayInCurrentWorkspace();
1798             sprintf(
1799                 buf,
1800                 GETMSG(DT_catd, 99, 99,"The INBOX path has changed.\nReopen?"));
1801             _genDialog->setToQuestionDialog(
1802                                         GETMSG(DT_catd, 3, 22, "Mailer"),
1803                                         buf);
1804             answer = _genDialog->post_and_return(
1805                                         GETMSG(DT_catd, 3, 29, "OK"),
1806                                         GETMSG(DT_catd, 3, 19, "Cancel"),
1807                                         DTMAILHELPERROR);
1808
1809             rmw = ses->getRMW(inbox_path);
1810             if (rmw)
1811             {
1812                 rmw->_inbox = TRUE;
1813                 rmw->_mailbox->createMailRetrievalAgent(password);
1814                 rmw->_open_container_inbox->deactivate();
1815                 rmw->_file_open_inbox->deactivate();
1816             }
1817
1818             if (answer == 1)
1819             {
1820                 if (NULL != rmw)
1821                   rmw->displayInCurrentWorkspace();
1822                 else
1823                   view_mail_file(inbox_path, DTM_FALSE);
1824             }
1825
1826             _inbox = FALSE;
1827             _mailbox->deleteMailRetrievalAgent();
1828             _open_container_inbox->activate();
1829             _file_open_inbox->activate();
1830             
1831         }
1832         else
1833         {
1834             _inbox = TRUE;
1835             _mailbox->createMailRetrievalAgent(password);
1836             _open_container_inbox->deactivate();
1837             _file_open_inbox->deactivate();
1838         }
1839     }
1840     else
1841     {
1842         if (_inbox) _mailbox->createMailRetrievalAgent(password);
1843         else
1844         {
1845             rmw = ses->getRMW(inbox_path);
1846             if (rmw) rmw->_mailbox->createMailRetrievalAgent(password);
1847         }
1848     }
1849
1850     if (password) free(password);
1851
1852
1853     // See if the header size has changed.
1854     //
1855     mailrc->getValue(error, "headerlines", &value);
1856     if (error.isSet())
1857     { 
1858         value = strdup("15");
1859         error.clear();
1860     }
1861
1862     int header_lines = (int) strtol(value, NULL, 10);
1863     if (header_lines != _list->visibleItems())
1864         _list->visibleItems(header_lines);
1865
1866     if (NULL != value)
1867       free((void*) value);
1868
1869     _list->checkDisplayProp();
1870     _my_editor->textEditor()->update_display_from_props();
1871
1872     value = NULL;
1873     mailrc->getValue(error, "dontdisplaycachedfiles", &value);
1874     if (error.isNotSet() && value != NULL)
1875     {
1876         if (_display_cached_list)
1877           // They just turned off the Display Up To prop so
1878           //reset the cache list to zero length.
1879           resetCacheList(0);
1880
1881         _max_cached_list_size = 0;
1882         _display_cached_list = FALSE;
1883         free((void*) value);
1884     }
1885     else
1886     {
1887         error.clear();
1888         value = NULL;
1889         mailrc->getValue(error, "cachedfilemenusize", &value);
1890         if (error.isNotSet() && value != NULL && *value != '\0')
1891         {
1892             int new_size;
1893
1894             new_size = (int) strtol(value, NULL, 10);
1895             if (new_size != _max_cached_list_size && new_size >=0)
1896             {
1897                 // They just changed the display number so chop the 
1898                 // list if it is bigger than the new size just set 
1899                 if (new_size < _max_cached_list_size)
1900                   resetCacheList(new_size);
1901
1902                 _max_cached_list_size = new_size;
1903             }
1904         }
1905         if (NULL != value)
1906           free((void*) value);
1907     }
1908
1909     error.clear(); 
1910     value = NULL;
1911     mailrc->getValue(error, "filemenu2", &value);
1912     if  ( (value == NULL && _filemenu2 != NULL) ||
1913           (value != NULL && _filemenu2 == NULL) ||
1914           (value != NULL && _filemenu2 != NULL &&
1915            strcmp(value, _filemenu2) != 0) )
1916     {
1917         // Recreate the containter list
1918         this->createContainerList();
1919
1920         // Recreate the File menu
1921         this->construct_file_menu();    
1922
1923         // Recreate the Message menu
1924         this->construct_message_menu(); 
1925
1926         // Recreate the Move menu...
1927         this->construct_move_menu();    
1928
1929         // Recreate the Message popup menu
1930         this->construct_message_popup();        
1931     }
1932     if (NULL != value)
1933       free((void*) value);
1934
1935     value = NULL;
1936     mailrc->getValue(error, "retrieveinterval", &value);
1937     if (error.isNotSet() && value && *value != '\0')
1938     {
1939         long ping = (time_t) strtol(value, NULL, 10);
1940         if (ping <= 0)
1941           _checkformail_when_mapped = FALSE;
1942         else
1943           _checkformail_when_mapped = TRUE;
1944     }
1945     error.clear();
1946     if (NULL != value) free((void*) value);
1947
1948     disableWorkAreaResize();
1949 }
1950
1951 void RoamMenuWindow::registerDialog( ViewMsgDialog *dialog )
1952 {
1953     int i;
1954     ViewMsgDialog **newList = (ViewMsgDialog **)-1;
1955   
1956     // Allocate a new list large enough to hold the new
1957     // object, and copy the contents of the current list 
1958     // to the new list
1959   
1960     newList = new ViewMsgDialog*[_numDialogs + 1];
1961   
1962     for ( i = 0; i < _numDialogs; i++ )
1963         newList[i] = _dialogs[i];
1964   
1965     // Install the new list and add the window to the list
1966   
1967     if ( _numDialogs > 0 )
1968         delete []_dialogs;
1969     _dialogs =  newList;
1970     _dialogs[_numDialogs] = dialog;
1971     _numDialogs++;
1972
1973   }
1974 void RoamMenuWindow::unregisterDialog ( ViewMsgDialog *dialog )
1975 {
1976   int i, index;
1977   ViewMsgDialog **newList = (ViewMsgDialog **)-1;
1978   
1979   // Allocate a new, smaller list
1980   
1981   newList = new ViewMsgDialog *[_numDialogs - 1];
1982   
1983   // Copy all objects, except the one to be 
1984   // removed, to the new list
1985   
1986   index = 0;
1987   for ( i = 0; i < _numDialogs; i++ )
1988     if ( _dialogs[i] != dialog )
1989     newList[index++] = _dialogs[i];
1990   
1991   // Install the new list
1992   
1993   delete []_dialogs;
1994   _dialogs =  newList;
1995   
1996   _numDialogs--;
1997 }
1998
1999 void
2000 RoamMenuWindow::forwardFilename( char *file )
2001 {
2002   _forward_filename = (char *)realloc(_forward_filename, strlen(file)+1);
2003   strcpy( _forward_filename, file );
2004 }
2005
2006 char *
2007 RoamMenuWindow::forwardFilename()
2008 {
2009   return _forward_filename;
2010 }
2011
2012
2013
2014 // If it is a configure notify, we are interested in it.
2015 // We need to then capture its new position.
2016 // And if the RMW has not been loaded, we need to load it.
2017
2018 void
2019 RoamMenuWindow::structurenotify(
2020     Widget,             // w
2021     XtPointer clientData,
2022     XEvent *event,
2023     Boolean * )         // continue_to_dispatch
2024 {
2025    RoamMenuWindow *rmw=(RoamMenuWindow *) clientData;
2026
2027    if (event->type == ConfigureNotify)
2028    {
2029        rmw->configurenotify(
2030                         event->xconfigurerequest.x,
2031                         event->xconfigurerequest.y,
2032                         event->xconfigurerequest.width,
2033                         event->xconfigurerequest.height,
2034                         event->xconfigurerequest.border_width);
2035    }
2036    else if ((event->type == MapNotify) || ( event->type == UnmapNotify))
2037    {
2038        if (rmw->_mailbox)
2039          if (event->type == UnmapNotify)
2040          {
2041              rmw->_mailbox->save();
2042              rmw->_mailbox->hideAccessEvents(DTM_TRUE);
2043          }
2044          else
2045          {
2046              rmw->_mailbox->hideAccessEvents(DTM_FALSE);
2047              if (FALSE==rmw->_inbox || TRUE==rmw->_checkformail_when_mapped)
2048              {
2049                  DtMailEnv        error;
2050                  DtMail::Session *m_session = theRoamApp.session()->session(); 
2051                  DtMail::MailRc  *mailrc = m_session->mailRc(error);
2052                  const char      *value = NULL;
2053
2054                  mailrc->getValue(error, "retrievemailonmapnotify", &value);
2055                  if (error.isNotSet()) rmw->checkForMail(error);
2056              }
2057          }
2058
2059        rmw->mapnotify();
2060    }       
2061 }
2062
2063 // Capture its position coordinates.
2064
2065 void 
2066 RoamMenuWindow::configurenotify( 
2067     unsigned int win_x, unsigned int win_y,
2068     unsigned int win_wid, unsigned int win_ht,
2069     unsigned int win_bwid
2070 )
2071 {
2072
2073     _x = win_x;
2074     _y = win_y;
2075     _width = win_wid;
2076     _height = win_ht;
2077     _border_width = win_bwid;
2078
2079 }
2080
2081 // If it is not already loaded, then load it (it might involve
2082 // conversion, etc.; all handled by open_and_load())
2083 // If its been loaded already, then mapnotify gets called when
2084 // the state changes from iconic to open (i.e., the user double-clicks
2085 // on an RMW icon).  If we want to load a folder at that time, this
2086 // is the place to do it.
2087
2088
2089 void
2090 RoamMenuWindow::mapnotify()
2091 {
2092     // If its not been loaded, then open and load it.
2093     if (!_is_loaded)
2094     {
2095         DtMailEnv mail_error;
2096         
2097         mail_error.clear();
2098         
2099         theRoamApp.busyAllWindows();
2100         this->open_and_load(
2101                         mail_error,
2102                         (DtMailBoolean) _create_mailbox_file,
2103                         DTM_TRUE);
2104         theRoamApp.unbusyAllWindows();
2105         
2106         // If there's been an error then we quit the container.
2107         if (mail_error.isSet())
2108         {
2109             // Need to remove the base Widgets destroy callback since
2110             // we end up destroying it twice otherwise...
2111             XtRemoveAllCallbacks(this->baseWidget(), XmNdestroyCallback);
2112             this->quit(TRUE);
2113         }
2114         else {
2115             // We need to disable the editable menu options if the mail
2116             // box is readonly.
2117             //
2118             if (_mailbox->mailBoxWritable(mail_error) == DTM_FALSE)
2119             {
2120                 _msg_delete->deactivate();
2121                 _msg_undelete_last->deactivate();
2122                 _msg_undelete_from_list->deactivate();
2123                 _delete_button->deactivate();
2124                 _file_destroy_deleted_msgs->deactivate();
2125                 if (NULL != _move_cascade)
2126                   XtSetSensitive(_move_cascade, FALSE);
2127                 if (NULL != _msgsPopupMoveMenu)
2128                   XtSetSensitive(_msgsPopupMoveMenu, FALSE);
2129                 
2130                 char * readonly = GETMSG(DT_catd, 20, 3, "Read Only");
2131                 setTitle(readonly);
2132             }
2133
2134             if (_list->get_num_messages())
2135               setIconName(NormalIcon);
2136             else
2137               setIconName(EmptyIcon);
2138         }
2139     }
2140     else
2141     {
2142         // If the mailbox has messages, set to normal icon
2143         if (_list->get_num_messages() > 0)
2144           setIconName(NormalIcon);
2145         else
2146           setIconName(EmptyIcon);
2147     }
2148 }
2149
2150 void
2151 RoamMenuWindow::last_sorted_by(SortBy type)
2152 {
2153     char                 id[16];
2154     char                *buffer = NULL;
2155     DtMailEnv            error;
2156     DtMail::Session     *m_session = theRoamApp.session()->session(); 
2157     DtMail::MailRc      *mailrc = m_session->mailRc(error);
2158
2159     _last_sorted_by = type;
2160
2161     ((SortCmd*)_view_sortTD)->setButtonState(FALSE, FALSE);
2162     ((SortCmd*)_view_sortSender)->setButtonState(FALSE, FALSE);
2163     ((SortCmd*)_view_sortSubject)->setButtonState(FALSE, FALSE);
2164     ((SortCmd*)_view_sortSize)->setButtonState(FALSE, FALSE);
2165     ((SortCmd*)_view_sortStatus)->setButtonState(FALSE, FALSE);
2166
2167     XtVaSetValues(_sender_lbl, XmNlabelString, _sender_xms, NULL);
2168     XtVaSetValues(_subject_lbl, XmNlabelString, _subject_xms, NULL);
2169     XtVaSetValues(_date_lbl, XmNlabelString, _date_xms, NULL);
2170     XtVaSetValues(_size_lbl, XmNlabelString, _size_xms, NULL);
2171
2172     buffer = XtMalloc(BUFSIZ);
2173     if (buffer)
2174     {
2175         if (_inbox)
2176         {
2177             RMW_CONCAT_MAILRC_KEY(buffer, DTMAS_INBOX, "sortby");
2178         }
2179         else
2180         {
2181             RMW_CONCAT_MAILRC_KEY(buffer, mailboxName(), "sortby");
2182         }
2183     }
2184     
2185     switch (_last_sorted_by)
2186     {
2187         case SortTimeDate:
2188             XtVaSetValues(_date_lbl, XmNlabelString, _date_key_xms, NULL);
2189             ((SortCmd*)_view_sortTD)->setButtonState(TRUE,FALSE);
2190             if (buffer) mailrc->removeValue(error, buffer);
2191             break;
2192         case SortSender:
2193             XtVaSetValues(_sender_lbl, XmNlabelString, _sender_key_xms, NULL);
2194             ((SortCmd*)_view_sortSender)->setButtonState(TRUE,FALSE);
2195             sprintf(id, "%d", SortSender);
2196             if (buffer) mailrc->setValue(error, buffer, id);
2197             break;
2198         case SortSubject:
2199             XtVaSetValues(_subject_lbl, XmNlabelString, _subject_key_xms, NULL);
2200             ((SortCmd*)_view_sortSubject)->setButtonState(TRUE,FALSE);
2201             sprintf(id, "%d", SortSubject);
2202             if (buffer) mailrc->setValue(error, buffer, id);
2203             break;
2204         case SortSize:  
2205             XtVaSetValues(_size_lbl, XmNlabelString, _size_key_xms, NULL);
2206             ((SortCmd*)_view_sortSize)->setButtonState(TRUE,FALSE);
2207             sprintf(id, "%d", SortSize);
2208             if (buffer) mailrc->setValue(error, buffer, id);
2209             break;
2210         case SortStatus:
2211             ((SortCmd*)_view_sortStatus)->setButtonState(TRUE,FALSE);
2212             sprintf(id, "%d", SortStatus);
2213             if (buffer) mailrc->setValue(error, buffer, id);
2214             break;
2215         default:
2216             XtVaSetValues(_date_lbl, XmNlabelString, _date_key_xms, NULL);
2217             ((SortCmd*)_view_sortTD)->setButtonState(TRUE,FALSE);
2218             if (buffer) mailrc->removeValue(error, buffer);
2219             break;
2220     }
2221     if (buffer) XtFree(buffer);
2222
2223     //_list->layoutLabels();
2224     mailrc->update(error);
2225 }
2226
2227 void
2228 RoamMenuWindow::message( char *text )
2229 {
2230     int text_size = strlen(text);
2231     char *buf, *str;
2232     XmString labelStr;
2233
2234     if (text_size > 0) {
2235         str = GETMSG(DT_catd, 3, 12, "%s");
2236         buf = new char[strlen(str) + text_size + 1];
2237         sprintf(buf, str, text);
2238         labelStr = XmStringCreateLocalized(buf);
2239         _clear_message_p = TRUE;               
2240     }
2241     else {
2242         buf = new char[2];
2243         sprintf(buf, "");
2244         labelStr = XmStringCreateLocalized(buf);
2245         _clear_message_p = FALSE;
2246     }
2247     
2248     XtVaSetValues(_message, XmNlabelString, labelStr, NULL);
2249     XmUpdateDisplay(this->baseWidget());
2250
2251     XmStringFree(labelStr); 
2252     delete [] buf;
2253 }
2254
2255 void
2256 RoamMenuWindow::setStatus(const char * msg)
2257 {
2258     message((char *)msg);
2259 }
2260
2261 void
2262 RoamMenuWindow::clearStatus(void)
2263 {
2264     setStatus("");
2265 }
2266
2267 void
2268 RoamMenuWindow::message_summary()
2269 {
2270     this->message_summary(
2271                 list()->selected_item_position(),
2272                 list()->get_num_messages(), 
2273                 list()->get_num_new_messages(),
2274                 list()->get_num_deleted_messages());
2275 }
2276
2277 void
2278 RoamMenuWindow::message_summary(
2279     int sel_pos,
2280     int num_msgs,
2281     int num_new,
2282     int num_deleted
2283 )
2284 {
2285     char *buf, *str; 
2286     XmString labelStr;
2287     int num_live_msgs = num_msgs - num_deleted;  // Undeleted msgs
2288     DtMail::MailRc * mailrc = get_mail_rc();
2289     DtMailEnv error;
2290     const char * value = NULL;
2291
2292     mailrc->getValue(error, "nerdmode", &value);
2293     if (error.isSet()) {
2294         str = GETMSG(DT_catd, 3, 13, "Message %d of %d, %d new, %d deleted"); 
2295     }
2296     else {
2297         str = "Message 0x%x of 0x%x, ignoring 0x%x, 0x%x forgotten";
2298     }
2299     if (NULL != value)
2300       free((void*) value);
2301
2302     buf = new char[strlen(str) + 100];
2303     sprintf(buf, str, sel_pos, num_msgs, num_new, num_deleted);
2304
2305     labelStr = XmStringCreateLocalized(buf);
2306     
2307     XtVaSetValues(_message_summary, XmNlabelString, labelStr, NULL);
2308     XmUpdateDisplay(this->baseWidget());
2309
2310     XmStringFree(labelStr);
2311     delete [] buf;
2312 }    
2313
2314 void
2315 RoamMenuWindow::message_selected(
2316     int msg_num,
2317     int num_msgs,
2318     int num_new,
2319     int num_deleted
2320 )
2321 {
2322     char *buf, *str;
2323     XmString labelStr;
2324
2325         /* NL_COMMENT
2326          * The user will see the following message display as:
2327          * "Message 3 of 10, 2 new, 6 deleted"
2328          * This means ??? -- Explain to translator.
2329          */
2330     str = GETMSG(DT_catd, 3, 14, "Message %d of %d, %d new, %d deleted"); 
2331     buf = new char[strlen(str) + 20];
2332     sprintf(buf, str, msg_num, num_msgs, num_new, num_deleted);
2333     
2334     labelStr = XmStringCreateLocalized(buf);
2335
2336     XtVaSetValues(_message_summary, XmNlabelString, labelStr, NULL);
2337     XmUpdateDisplay(this->baseWidget());
2338
2339     XmStringFree(labelStr);
2340     delete [] buf;
2341 }
2342     
2343
2344 FindDialog *
2345 RoamMenuWindow::get_find_dialog()
2346 {
2347   
2348   if (!_findDialog) {
2349     theRoamApp.busyAllWindows();
2350     // No find dialog.  Create it
2351     _findDialog = new FindDialog(this);
2352     _findDialog->initialize();
2353     theRoamApp.unbusyAllWindows();
2354   }
2355
2356   // Show it
2357   _findDialog->manage();
2358   _findDialog->popup();
2359   return _findDialog;
2360 }
2361
2362 Boolean 
2363 RoamMenuWindow::quitWorkproc(XtPointer client_data)
2364 {
2365     RoamMenuWindow      *rmw = (RoamMenuWindow *) client_data;
2366     MailSession         *ses = theRoamApp.session();
2367     static int called = 0;
2368
2369     if (rmw->_numPendingTasks > 0)
2370     {
2371         rmw->busyCursor();
2372         return FALSE;
2373     }
2374     
2375     if (rmw->_quitWorkprocID != 0)
2376     {
2377         XtRemoveWorkProc(rmw->_quitWorkprocID);
2378         rmw->_quitWorkprocID = 0;
2379     }
2380
2381     rmw->normalCursor();
2382     rmw->_genDialog->unmanage();
2383     rmw->unmanage();
2384
2385     if (rmw->_delete_on_quit)
2386     {
2387         rmw->_list->shutdown();
2388         delete rmw;
2389     }
2390     else
2391       ses->deactivateRMW(rmw);
2392
2393     theRoamApp.checkForShutdown();
2394     return TRUE;
2395 }
2396
2397 int 
2398 RoamMenuWindow::queryExpunge()
2399 {
2400     int answer = 0;
2401     DtMailEnv error;
2402     int i = 0;
2403
2404     if (NULL != _mailbox && _mailbox->mailBoxWritable(error) == DTM_TRUE)
2405     {
2406       theRoamApp.busyAllWindows(GETMSG(DT_catd, 3, 15, "Saving..."));
2407
2408       if (_list->get_num_deleted_messages())
2409       {
2410         // We need to deal with deleted messages, based on what the
2411         // user wants to do. There are two properties that control
2412         // this. They are:
2413         //
2414         // keepdeleted - Keep deleted messages on close.
2415         // quietdelete - Delete without asking.
2416         //
2417         // If the user wants to keep the deleted messages, then we
2418         // can just blow by the second. If not, then we have to
2419         // clear the deleted messages, asking first based on the
2420         // second option.
2421         //
2422         DtMail::MailRc * mailrc = get_mail_rc();
2423         const char * value = NULL;
2424
2425         error.clear();
2426         mailrc->getValue(error, "keepdeleted", &value);
2427         if (error.isSet())
2428         {
2429             if (NULL != value)
2430               free((void*) value);
2431
2432             // The user wants to expunge on close. See if they want
2433             // to be asked first.
2434             //
2435             value = NULL;
2436             error.clear();
2437             mailrc->getValue(error, "quietdelete", &value);
2438             if (error.isSet() && !theRoamApp.quitSilently())
2439             {
2440                 if (isIconified())
2441                   manage();
2442
2443                 /* NL_COMMENT
2444                  * This dialog comes up when the user tries to quit the
2445                  * mailbox and the user is asked if he wants to destroy
2446                  * the messages marked for deletion.
2447                  */
2448                 /* NL_COMMENT
2449                  * Messages 16 and 17 are no longer being used.  They are
2450                  * being replaced by message 86 and 87.
2451                  */
2452                 _genDialog->setToQuestionDialog(
2453 #ifdef undef
2454                     GETMSG(DT_catd, 3, 16, "Mailer"),
2455                     GETMSG(DT_catd, 3, 17, "Destroy the messages you have marked\nfor deletion in this mailbox?"));
2456 #endif // undef
2457                 /* NL_COMMENT
2458                  * This dialog comes up when the user tries to quit the
2459                  * mailbox.  The user is asked if they want to destroy
2460                  * the deleted messages.
2461                  */
2462                     GETMSG(DT_catd, 3, 87, "Mailer - Close"),
2463                     GETMSG(DT_catd, 3, 88, "Destroy the deleted messages and close this mailbox?"));
2464                 char * helpId = DTMAILHELPDESTROYMARKMSG;
2465                 int answer = _genDialog->post_and_return(
2466                                 GETMSG(DT_catd, 3, 89, "Destroy and Close"),
2467                                 GETMSG(DT_catd, 3, 73, "Cancel"),
2468                                 GETMSG(DT_catd, 3, 90, "Retain and Close"),
2469                                 helpId);
2470                 if (answer == 1)
2471                 {
2472                     error.clear();
2473                     _mailbox->expunge(error);
2474                     if ((DTMailError_t) error == DTME_OutOfSpace)
2475                     {
2476                         ShowErrMsg(
2477                                 (char *)error.getClient(),
2478                                 FALSE,
2479                                 (void*)this);
2480                         error.setClient(NULL);
2481                     }
2482
2483                     if (_msg_undelete_from_list->dialog())
2484                       _msg_undelete_from_list->dialog()->expunge();
2485                     _list->expunge();
2486
2487                     if (error.isSet())
2488                       postErrorDialog(error);
2489                 }
2490                 else if (answer == 2)
2491                 {
2492                     // This is a very bad way to code selection of the 
2493                     // cancel button.  If someone changes its position
2494                     // in the dialog, this code will break!
2495                     theRoamApp.unbusyAllWindows();
2496                     return 0;
2497                 }
2498             }
2499             else
2500             {
2501                 // If killed by a signal, don't post a dialog.
2502                 error.clear();
2503                 _mailbox->expunge(error);
2504                 if ((DTMailError_t) error == DTME_OutOfSpace)
2505                 {
2506                    ShowErrMsg((char *)error.getClient(),FALSE,(void*)this );
2507                    error.setClient(NULL);
2508                 }
2509
2510                 if (_msg_undelete_from_list->dialog())
2511                   _msg_undelete_from_list->dialog()->expunge();
2512                 _list->expunge();
2513
2514                 if (error.isSet())
2515                   if (! theRoamApp.quitSilently())
2516                     postErrorDialog(error);
2517             }
2518         }
2519         if (NULL != value)
2520           free((void*) value);
2521       }
2522     }
2523     return 1;
2524 }
2525
2526
2527 void 
2528 RoamMenuWindow::quit(Boolean delete_win)
2529 {
2530     DtMailEnv error;
2531     int i = 0;
2532
2533     if (! queryExpunge())
2534       return;
2535
2536     for (i = 0; i < _numDialogs; i++)
2537       _dialogs[i]->unmanage();
2538
2539     XmUpdateDisplay(baseWidget());
2540
2541     for (i = 0; i < _numDialogs; i++)
2542       _dialogs[i]->quit();
2543
2544     theRoamApp.unbusyAllWindows();
2545
2546     this->_delete_on_quit = delete_win;
2547     if (_numPendingTasks > 0)
2548     {
2549         char    *msg;
2550
2551         busyCursor();
2552         msg = GETMSG(
2553                 DT_catd,
2554                 21, 22, "Close pending:  waiting for task to terminate ...");
2555         setStatus(msg);
2556
2557         if (_quitWorkprocID == 0)
2558           _quitWorkprocID = XtAppAddWorkProc(
2559                                         XtWidgetToApplicationContext(_w),
2560                                         &RoamMenuWindow::quitWorkproc,
2561                                         (XtPointer) this);
2562
2563         unmanage();
2564     }
2565     else
2566       quitWorkproc((XtPointer) this);
2567 }
2568
2569 void 
2570 RoamMenuWindow::panicQuit()
2571 {
2572     if (_mailbox != NULL)
2573         _mailbox->unlock();
2574 }
2575
2576 void 
2577 RoamMenuWindow::quit_silently()
2578 {
2579     DtMailEnv error;
2580     int i = 0;
2581
2582     if (_mailbox->mailBoxWritable(error) == DTM_TRUE) {
2583
2584       theRoamApp.busyAllWindows(GETMSG(DT_catd, 3, 15, "Saving..."));
2585
2586       if (_list->get_num_deleted_messages()) {
2587         // We need to deal with deleted messages, based on what the
2588         // user wants to do. There are two properties that control
2589         // this. They are:
2590         //
2591         // keepdeleted - Keep deleted messages on close.
2592         // quietdelete - Delete without asking.
2593         //
2594         // If the user wants to keep the deleted messages, then we
2595         // can just blow by the second. If not, then we have to
2596         // clear the deleted messages, asking first based on the
2597         // second option.
2598         //
2599         DtMail::MailRc * mailrc = get_mail_rc();
2600         const char * value = NULL;
2601
2602         error.clear();
2603         mailrc->getValue(error, "keepdeleted", &value);
2604         if (error.isSet()) {
2605             error.clear();
2606             _mailbox->expunge(error);
2607             if (error.isSet()) {
2608                 this->postErrorDialog(error);
2609             }
2610         }
2611         if (NULL != value)
2612           free((void*) value);
2613
2614       }
2615     }
2616
2617     for (i = 0; i < _numDialogs; i++) {
2618         _dialogs[i]->unmanage();
2619     }
2620
2621     XmUpdateDisplay(this->baseWidget());
2622
2623     for (i = 0; i < _numDialogs; i++) {
2624         _dialogs[i]->quit();
2625     }
2626
2627     this->_delete_on_quit = FALSE;
2628     if (_numPendingTasks > 0)
2629     {
2630         char    *msg;
2631
2632         busyCursor();
2633         msg = GETMSG(
2634                 DT_catd,
2635                 21, 22, "Close pending:  waiting for task to terminate ...");
2636         setStatus(msg);
2637
2638         if (_quitWorkprocID == 0)
2639           _quitWorkprocID = XtAppAddWorkProc(
2640                                         XtWidgetToApplicationContext(_w),
2641                                         &RoamMenuWindow::quitWorkproc,
2642                                         (XtPointer) this);
2643
2644         unmanage();
2645     }
2646     else
2647       quitWorkproc((XtPointer) this);
2648 }
2649
2650 // Callback to open a new mail container.
2651
2652 void
2653 RoamMenuWindow::file_selection_callback(void *client_data, char *selection)
2654 {
2655     if (NULL == selection || 0 == strlen(selection)) return;
2656
2657     RoamMenuWindow *obj=(RoamMenuWindow *) client_data;
2658     obj->view_mail_file(selection, DTM_FALSE);
2659     XtFree(selection);
2660 }
2661
2662
2663 void RoamMenuWindow::reopen_mail_file()
2664 {
2665     char *filename;
2666
2667     theApplication->disableShutdown();
2668
2669     filename = strdup(this->_mailbox_fullpath);
2670     this->unmanage();
2671     this->quit(TRUE);
2672     view_mail_file(filename, DTM_FALSE);
2673     free(filename);
2674
2675     theApplication->enableShutdown();
2676 }
2677
2678 // Given the name of a container, create a new RoamMenuWindow
2679 // and open the container into it.
2680
2681 void RoamMenuWindow::view_mail_file(char *filename, DtMailBoolean create)
2682 {
2683     DtMailEnv           mail_error;
2684     MailSession         *ses = theRoamApp.session();
2685     DtMail::Session     *d_session = ses->session();
2686     RoamMenuWindow      *roamwin = NULL;
2687     char                *expanded_filename = NULL;
2688     char                *plus_filename = NULL;
2689     char                *relative_filename = NULL;
2690
2691     theRoamApp.busyAllWindows(GETMSG(DT_catd, 3, 20, "Opening mailbox..."));
2692
2693     // If the first character of destname is alphanumeric, we can
2694     // safely assume that it is relative to the root folder directory.
2695     // Prepend a '+' and call 'expandPath' to get the actual path.
2696     if (isalnum(filename[0]))
2697     {
2698         plus_filename = (char *) malloc(strlen(filename)+2);
2699         sprintf(plus_filename, "+%s", filename);
2700         expanded_filename = d_session->expandPath(mail_error, plus_filename);
2701         free(plus_filename);
2702     }
2703     else
2704       expanded_filename = d_session->expandPath(mail_error, filename);
2705
2706     // Check to see if the mbox is already open.  If it is, we will
2707     // simply make sure it's displayed in the current workspace.
2708     if (ses->isMboxOpen(expanded_filename))
2709     {
2710         roamwin = ses->getRMW(expanded_filename);
2711         ses->activateRMW(roamwin);
2712         if (NULL != roamwin) roamwin->displayInCurrentWorkspace();
2713     }
2714     else
2715     {
2716         if (DTM_FALSE == create &&
2717             -1 == SafeAccess(expanded_filename, F_OK) &&
2718             ENOENT == errno)
2719         {
2720             char *buf = new char[2048];
2721             int answer;
2722             DtMailGenDialog *dialog = genDialog();
2723
2724             sprintf(
2725                 buf,
2726                 GETMSG(DT_catd, 3, 3, "The mailbox %s does not exist.\nCreate a mailbox with this name?"),
2727                 filename);
2728             dialog->setToQuestionDialog(GETMSG(DT_catd, 3, 22, "Mailer"), buf);
2729             answer = dialog->post_and_return(DTMAILHELPERROR);
2730             delete [] buf;
2731             if (2 == answer) goto do_unbusy;
2732             create = DTM_TRUE;
2733         }
2734     
2735         roamwin = new RoamMenuWindow(expanded_filename);
2736         roamwin->_create_mailbox_file = DTM_TRUE;
2737         roamwin->initialize();
2738         roamwin->mailboxFullpath(expanded_filename);
2739         roamwin->mailboxName(filename);
2740         roamwin->manage();
2741     }
2742
2743     free(expanded_filename);
2744     relative_filename = d_session->getRelativePath(mail_error, filename);
2745     theRoamApp.globalAddToCachedContainerList(relative_filename);
2746     free(relative_filename);
2747
2748 do_unbusy:
2749     theRoamApp.unbusyAllWindows();
2750 }
2751
2752 void
2753 RoamMenuWindow::move_callback(void *client_data, char *selection)
2754 {
2755     DtMailEnv mail_error;
2756
2757     mail_error.clear();
2758     RoamMenuWindow *obj = (RoamMenuWindow *) client_data;
2759
2760     theRoamApp.busyAllWindows(GETMSG(DT_catd, 3, 15, "Saving..."));
2761     obj->_mailbox->save();
2762     theRoamApp.unbusyAllWindows();
2763
2764     obj->_list->copySelected(mail_error, selection, TRUE, FALSE);
2765     if (mail_error.isSet()) obj->postErrorDialog(mail_error);
2766
2767 }
2768
2769 void
2770 RoamMenuWindow::copy_callback(void *client_data, char *selection)
2771 {
2772     DtMailEnv mail_error;
2773
2774     mail_error.clear();
2775     RoamMenuWindow *obj = (RoamMenuWindow *) client_data;
2776
2777     theRoamApp.busyAllWindows(GETMSG(DT_catd, 3, 15, "Saving..."));
2778     obj->_mailbox->save();
2779     theRoamApp.unbusyAllWindows();
2780
2781     obj->_list->copySelected(mail_error, selection, FALSE, FALSE);
2782     if (mail_error.isSet()) obj->postErrorDialog(mail_error);   
2783 }
2784
2785
2786 void
2787 RoamMenuWindow::create_container_callback(void *client_data, char *selection)
2788 {
2789     RoamMenuWindow *obj = (RoamMenuWindow*) client_data;
2790     obj->create_new_container(selection);
2791     if (NULL != selection) XtFree(selection);
2792 }
2793
2794 void
2795 RoamMenuWindow::create_new_container(char *filename)
2796 {
2797     int answer;
2798
2799     if (SafeAccess(filename, F_OK) == 0)
2800     {
2801         char *buf = new char[2048];
2802         sprintf(
2803                 buf,
2804                 GETMSG(DT_catd, 3, 21, "%s already exists.\nOverwrite?"),
2805                 filename);
2806         _genDialog->setToQuestionDialog(GETMSG(DT_catd, 3, 22, "Mailer"), buf);
2807         answer = _genDialog->post_and_return(DTMAILHELPERROR);
2808         if (answer == 2) {
2809             delete [] buf;
2810             return;
2811         }
2812
2813         if (unlink(filename) < 0)
2814         {
2815             sprintf(buf, 
2816                 GETMSG(DT_catd, 3, 23,
2817                   "Unable to overwrite %s.\nCheck file permissions and retry."),
2818                 filename);
2819
2820             _genDialog->setToErrorDialog(GETMSG(DT_catd, 3, 24, "Mailer"), buf);
2821             (void) _genDialog->post_and_return(DTMAILHELPERROR);
2822             delete [] buf;
2823             return;
2824         }
2825         delete [] buf;
2826     }
2827     
2828     // Path filename is ok -- now follow the same route as for Open
2829     this->view_mail_file(filename, DTM_TRUE);
2830 }
2831
2832
2833
2834 // SR - added methods below
2835
2836 ViewMsgDialog*
2837 RoamMenuWindow::ifViewExists(DtMailMessageHandle msg_num)
2838 {
2839
2840     int i;
2841     FORCE_SEGV_DECL(ViewMsgDialog, a_view);
2842
2843     for (i = 0; i < _numDialogs; i++) {
2844         a_view = _dialogs[i];
2845         if (a_view->msgno() == msg_num) {
2846             return(a_view);
2847         }
2848     }
2849     return(NULL);
2850 }
2851
2852         
2853 void
2854 RoamMenuWindow::addToRowOfButtons()
2855 {
2856     FORCE_SEGV_DECL(CmdInterface, ci);
2857     Widget w, prev_widget;
2858     int offset = 10;
2859
2860     _delete_button = new DeleteCmd ( 
2861                                 "Delete",
2862                                 GETMSG(DT_catd, 1, 9, "Delete"), 
2863                                 TRUE, this );
2864     ci  = new ButtonInterface (_rowOfButtons, _delete_button);
2865     w = ci->baseWidget();
2866     XtAddCallback(w, XmNhelpCallback, HelpCB, DTMAILDELBTNID);
2867     XtVaSetValues(w,
2868         XmNleftAttachment, XmATTACH_FORM,
2869         XmNtopAttachment, XmATTACH_FORM,
2870         XmNbottomAttachment, XmATTACH_FORM,
2871         XmNmarginLeft, offset,
2872         XmNmarginRight, offset,
2873         NULL );
2874     ci->manage();
2875     prev_widget = w;
2876
2877     _next_button  = new NextCmd ( 
2878                         "Next",
2879                         GETMSG(DT_catd, 1, 10, "Next"), 
2880                         TRUE, this );
2881     ci  = new ButtonInterface (_rowOfButtons, _next_button);
2882     w = ci->baseWidget();
2883     XtAddCallback(w, XmNhelpCallback, HelpCB, DTMAILNEXTBTNID);
2884     XtVaSetValues(w,
2885         XmNleftAttachment, XmATTACH_WIDGET,
2886         XmNleftWidget, prev_widget,
2887         XmNleftOffset, 10,
2888         XmNtopAttachment, XmATTACH_FORM,
2889         XmNbottomAttachment, XmATTACH_FORM,
2890         XmNmarginLeft, offset,
2891         XmNmarginRight, offset,
2892         NULL );
2893     ci->manage();
2894     prev_widget = w;
2895
2896     _previous_button = new PrevCmd ( 
2897                                 "Previous",
2898                                 GETMSG(DT_catd, 1, 11, "Previous"), 
2899                                 TRUE, this );
2900     ci  = new ButtonInterface (_rowOfButtons, _previous_button);
2901     w = ci->baseWidget();
2902     XtAddCallback(w, XmNhelpCallback, HelpCB, DTMAILPREVBTNID);
2903     XtVaSetValues(w,
2904         XmNleftAttachment, XmATTACH_WIDGET,
2905         XmNleftWidget, prev_widget,
2906         XmNleftOffset, 10,
2907         XmNtopAttachment, XmATTACH_FORM,
2908         XmNbottomAttachment, XmATTACH_FORM,
2909         XmNmarginLeft, offset,
2910         XmNmarginRight, offset,
2911         NULL );
2912     ci->manage();
2913     prev_widget = w;
2914
2915     _replySender_button = new ReplyCmd (
2916                                 "Reply to Sender",
2917                                 GETMSG(DT_catd, 1, 12, "Reply to Sender"), 
2918                                 TRUE, 
2919                                 this, 
2920                                 FALSE );
2921     ci  = new ButtonInterface (_rowOfButtons, _replySender_button);
2922     w = ci->baseWidget();
2923     XtAddCallback(w, XmNhelpCallback, HelpCB, DTMAILREPLYBTNID);
2924     XtVaSetValues(w,
2925         XmNleftAttachment, XmATTACH_WIDGET,
2926         XmNleftWidget, prev_widget,
2927         XmNleftOffset, 10,
2928         XmNtopAttachment, XmATTACH_FORM,
2929         XmNbottomAttachment, XmATTACH_FORM,
2930         XmNmarginLeft, offset,
2931         XmNmarginRight, offset,
2932         NULL );
2933     ci->manage();
2934     prev_widget = w;
2935
2936
2937     _print_button  = new PrintCmd ( "Print", GETMSG(DT_catd, 1, 13, "Print"),
2938                                 TRUE, TRUE, this);
2939     ci  = new ButtonInterface (_rowOfButtons, _print_button);
2940     w = ci->baseWidget();
2941     XtAddCallback(w, XmNhelpCallback, HelpCB, DTMAILPRINTBTNID);
2942     XtVaSetValues(w,
2943         XmNleftAttachment, XmATTACH_WIDGET,
2944         XmNleftWidget, prev_widget,
2945         XmNleftOffset, 10,
2946         XmNtopAttachment, XmATTACH_FORM,
2947         XmNbottomAttachment, XmATTACH_FORM,
2948         XmNmarginLeft, offset,
2949         XmNmarginRight, offset,
2950         NULL );
2951     ci->manage();
2952     prev_widget = w;
2953 }
2954
2955 void
2956 RoamMenuWindow::addToRowOfLabels(MsgScrollingList *msglist)
2957 {
2958
2959     XmString             arrow, basexms, spaces, spaces_arrow;
2960     char                 arrow_symbol[2];
2961     char                *glyph_font;
2962
2963     glyph_font = theRoamApp.glyphName();
2964
2965 #if 0
2966     XFontStruct         *xfs;
2967     XmFontListEntry     xmfle;
2968     XmFontList          xmfl, xmfl_old;
2969     Widget               lbl;
2970     
2971     xfs = XLoadQueryFont(XtDisplay(_rowOfLabels), glyph_font);
2972     xmfle = XmFontListEntryCreate("arrow", XmFONT_IS_FONT, (XtPointer) xfs);
2973
2974     lbl = XtVaCreateManagedWidget("t", xmLabelGadgetClass, _rowOfLabels, NULL);
2975     XtVaGetValues(lbl, XmNfontList, &xmfl_old, NULL);
2976     xmfl = XmFontListAppendEntry(xmfl_old, xmfle);
2977 #else
2978 //  Pixel               foreground, background;
2979     XmRenderTable       rt, rt_old;
2980     XmRendition         rend;
2981     Arg                 args[25];
2982     int                 nargs = 0;
2983
2984 //  lbl = XtVaCreateManagedWidget("t", xmLabelGadgetClass, _rowOfLabels, NULL);
2985 //  XtVaGetValues(
2986 //      lbl,
2987 //      XmNrenderTable, &rt_old,
2988 //      XmNforeground, &foreground,
2989 //      XmNbackground, &background,
2990 //      NULL);
2991
2992 //  XtSetArg(args[nargs], XmNrenditionBackground, background); nargs++;
2993 //  XtSetArg(args[nargs], XmNrenditionForeground, foreground); nargs++;
2994 //  XtSetArg(args[nargs], XmNloadModel, XmLOAD_IMMEDIATE); nargs++;
2995
2996     XtSetArg(args[nargs], XmNfontName, glyph_font); nargs++;
2997     XtSetArg(args[nargs], XmNfontType, XmFONT_IS_FONT); nargs++;
2998     rend = XmRenditionCreate(_rowOfLabels, "arrow", args, nargs);
2999 #endif
3000
3001     arrow_symbol[0] = (char) 209;
3002     arrow_symbol[1] = '\0';
3003
3004     spaces = XmStringCreateLocalized("  ");
3005     arrow = XmStringCreate((char*) arrow_symbol, "arrow");
3006     spaces_arrow = XmStringConcat(spaces, arrow);
3007
3008     XmStringFree(spaces);
3009     spaces = XmStringCreateLocalized("    ");
3010
3011     basexms = XmStringCreateLocalized(GETMSG(DT_catd, 1, 14, "Sender"));
3012     _sender_xms = XmStringConcat(basexms, spaces);
3013     _sender_key_xms = XmStringConcat(basexms, spaces_arrow);
3014     XmStringFree(basexms);
3015
3016     _sender_lbl = XtVaCreateManagedWidget(
3017                                 "Sender", xmLabelGadgetClass, 
3018                                 _rowOfLabels,
3019 #if 0
3020                                 XmNfontList, xmfl,
3021                                 XmNrenderTable, rt,
3022 #endif
3023                                 XmNlabelString, _sender_xms,
3024                                 XmNalignment, XmALIGNMENT_BEGINNING,
3025                                 NULL);
3026
3027     XtSetArg(args[nargs], XmNfontName, glyph_font); nargs++;
3028     XtSetArg(args[nargs], XmNfontType, XmFONT_IS_FONT); nargs++;
3029     rend = XmRenditionCreate(_rowOfLabels, "arrow", args, nargs);
3030
3031     XtVaGetValues(_sender_lbl, XmNrenderTable, &rt_old, NULL);
3032     rt = XmRenderTableCopy(rt_old, NULL, 0);
3033     rt = XmRenderTableAddRenditions(rt, &rend, 1, XmMERGE_REPLACE);
3034     XtVaSetValues(_sender_lbl, XmNrenderTable, rt, NULL);
3035
3036     // Add help callback
3037     // printHelpId("Sender", _sender_lbl);
3038     // XtAddCallback(_sender_lbl, XmNhelpCallback, HelpCB, helpId);
3039
3040     basexms = XmStringCreateLocalized(GETMSG(DT_catd, 1, 15, "Subject"));
3041     _subject_xms = XmStringConcat(basexms, spaces);
3042     _subject_key_xms = XmStringConcat(basexms, spaces_arrow);
3043     XmStringFree(basexms);
3044
3045     _subject_lbl = XtVaCreateManagedWidget(
3046                                 "Subject", xmLabelGadgetClass, 
3047                                 _rowOfLabels,
3048 #if 0
3049                                 XmNfontList, xmfl,
3050                                 XmNrenderTable, rt,
3051 #endif
3052                                 XmNlabelString, _subject_xms,
3053                                 XmNalignment, XmALIGNMENT_BEGINNING,
3054                                 NULL);
3055
3056     XtSetArg(args[nargs], XmNfontName, glyph_font); nargs++;
3057     XtSetArg(args[nargs], XmNfontType, XmFONT_IS_FONT); nargs++;
3058     rend = XmRenditionCreate(_rowOfLabels, "arrow", args, nargs);
3059
3060     XtVaGetValues(_subject_lbl, XmNrenderTable, &rt_old, NULL);
3061     rt = XmRenderTableCopy(rt_old, NULL, 0);
3062     rt = XmRenderTableAddRenditions(rt, &rend, 1, XmMERGE_REPLACE);
3063     XtVaSetValues(_subject_lbl, XmNrenderTable, rt, NULL);
3064
3065     // Add help callback
3066     // printHelpId("Subject", _subject_lbl);
3067     // XtAddCallback(_subject_lbl, XmNhelpCallback, HelpCB, helpId);
3068
3069     basexms = XmStringCreateLocalized(GETMSG(DT_catd, 1, 16,"Date and Time"));
3070     _date_xms = XmStringConcat(basexms, spaces);
3071     _date_key_xms = XmStringConcat(basexms, spaces_arrow);
3072     XmStringFree(basexms);
3073
3074     _date_lbl = XtVaCreateManagedWidget(
3075                                 "DateTime", xmLabelGadgetClass, 
3076                                 _rowOfLabels,
3077 #if 0
3078                                 XmNfontList, xmfl,
3079                                 XmNrenderTable, rt,
3080 #endif
3081                                 XmNlabelString, _date_xms,
3082                                 XmNalignment, XmALIGNMENT_BEGINNING,
3083                                 NULL);
3084
3085     XtSetArg(args[nargs], XmNfontName, glyph_font); nargs++;
3086     XtSetArg(args[nargs], XmNfontType, XmFONT_IS_FONT); nargs++;
3087     rend = XmRenditionCreate(_rowOfLabels, "arrow", args, nargs);
3088
3089     XtVaGetValues(_date_lbl, XmNrenderTable, &rt_old, NULL);
3090     rt = XmRenderTableCopy(rt_old, NULL, 0);
3091     rt = XmRenderTableAddRenditions(rt, &rend, 1, XmMERGE_REPLACE);
3092     XtVaSetValues(_date_lbl, XmNrenderTable, rt, NULL);
3093
3094     // Add help callback
3095     // printHelpId("DateTime", _subject_lbl);
3096     // XtAddCallback(_date_lbl, XmNhelpCallback, HelpCB, helpId);
3097
3098     basexms = XmStringCreateLocalized(GETMSG(DT_catd, 1, 17, "Size"));
3099     _size_xms = XmStringConcat(basexms, spaces);
3100     _size_key_xms = XmStringConcat(basexms, spaces_arrow);
3101     XmStringFree(basexms);
3102
3103     _size_lbl = XtVaCreateManagedWidget(
3104                                 "Size", xmLabelGadgetClass, 
3105                                 _rowOfLabels,
3106 #if 0
3107                                 XmNfontList, xmfl,
3108                                 XmNrenderTable, rt,
3109 #endif
3110                                 XmNlabelString, _size_xms,
3111                                 XmNalignment, XmALIGNMENT_BEGINNING,
3112                                 NULL);
3113
3114     XtSetArg(args[nargs], XmNfontName, glyph_font); nargs++;
3115     XtSetArg(args[nargs], XmNfontType, XmFONT_IS_FONT); nargs++;
3116     rend = XmRenditionCreate(_rowOfLabels, "arrow", args, nargs);
3117
3118     XtVaGetValues(_size_lbl, XmNrenderTable, &rt_old, NULL);
3119     rt = XmRenderTableCopy(rt_old, NULL, 0);
3120     rt = XmRenderTableAddRenditions(rt, &rend, 1, XmMERGE_REPLACE);
3121     XtVaSetValues(_size_lbl, XmNrenderTable, rt, NULL);
3122
3123     // Add help callback
3124     // printHelpId("Size", _size_lbl);
3125     // XtAddCallback(_size_lbl, XmNhelpCallback, HelpCB, helpId);
3126
3127     // Adjust labels so the align on the columns
3128     msglist->layoutLabels(_sender_lbl, _subject_lbl, _date_lbl, _size_lbl);
3129
3130     XmStringFree(arrow);
3131     XmStringFree(spaces);
3132     XmStringFree(spaces_arrow);
3133     return;
3134 }
3135
3136 void
3137 RoamMenuWindow::addToRowOfMessageStatus()
3138 {
3139     XmString labelStr1, labelStr2;
3140
3141     // Size of first label
3142     
3143     labelStr1 = XmStringCreateLocalized(GETMSG(DT_catd, 3, 25,
3144            "Loading container..."));
3145
3146     labelStr2 = XmStringCreateLocalized(
3147                         GETMSG(DT_catd, 3, 26, "Folder Summary Information"));
3148
3149     _message = XtCreateManagedWidget(
3150                         "Message_Status_Text", xmLabelWidgetClass,
3151                         _rowOfMessageStatus, NULL, 0);
3152     printHelpId("_message", _message);
3153     /* add help callback */
3154     // XtAddCallback(_message, XmNhelpCallback, HelpCB, helpId);
3155
3156
3157      XtVaSetValues(_message,
3158         XmNalignment, XmALIGNMENT_BEGINNING,
3159         XmNleftAttachment, XmATTACH_FORM,
3160         XmNtopAttachment, XmATTACH_FORM,
3161         XmNbottomAttachment, XmATTACH_FORM,
3162         XmNlabelString, labelStr1,
3163         NULL );
3164     
3165     _message_summary = XtCreateManagedWidget("Message_Summary", 
3166                                         xmLabelWidgetClass,
3167                                         _rowOfMessageStatus, NULL, 0);
3168      XtVaSetValues(_message_summary,
3169         XmNalignment, XmALIGNMENT_END,
3170         XmNlabelString, labelStr2,
3171         XmNrightAttachment, XmATTACH_FORM,
3172         NULL );
3173
3174      XtVaSetValues(_message,
3175          XmNrightAttachment, XmATTACH_WIDGET,
3176          XmNrightWidget, _message_summary,
3177          XmNrightOffset, 10,
3178          NULL);
3179
3180      XmStringFree(labelStr1);
3181      XmStringFree(labelStr2);
3182  
3183 }
3184
3185 void
3186 RoamMenuWindow::createContainerList()
3187 {
3188     FORCE_SEGV_DECL(DtMail::Session, m_session);
3189     DtMailEnv           error;
3190     const char          *val = NULL;
3191     const char          *cached_containerlist_size = NULL;
3192     const char          *display_cfs = NULL;
3193     DtMailBoolean       user_list = DTM_FALSE;
3194
3195     //
3196     // Get names for permanent containers from .mailrc.
3197     // We get the items from the "filemenu2" variable.
3198     if (_filemenu2 != NULL) free (_filemenu2);
3199
3200     m_session = theRoamApp.session()->session();
3201     m_session->mailRc(error)->getValue(error, "filemenu2", &val);
3202     if (error.isNotSet() && val != NULL && *val != '\0')
3203     {
3204         user_list = DTM_TRUE;
3205         _filemenu2 = strdup(val);
3206     }
3207     else _filemenu2 = NULL;
3208
3209     if (NULL != val)
3210       free((void*) val);
3211
3212     // We will use _user_containerlist to keep track of the static set of
3213     // containers coming from the "filemenu2" value. 
3214     // We will use _cached_containerlist to keep track of containers
3215     // which get cached from "Other Mailboxes... operations from the
3216     // Open, CopyTo, and Move menus.
3217
3218     if (_user_containerlist != NULL)
3219         delete (_user_containerlist);
3220     _user_containerlist = new DtVirtArray<ContainerMenuCmd*> (3);
3221
3222     m_session->mailRc(error)->getValue(
3223                                 error,
3224                                 "dontdisplaycachedfiles",
3225                                 &display_cfs);
3226
3227     if (error.isNotSet() && display_cfs != NULL) 
3228       _max_cached_list_size = 0;
3229     else
3230     {
3231         error.clear();
3232         m_session->mailRc(error)->getValue(
3233                                         error, 
3234                                         "cachedfilemenusize",
3235                                         &cached_containerlist_size);
3236         if (error.isNotSet() &&
3237             cached_containerlist_size && 
3238             *cached_containerlist_size)
3239           _max_cached_list_size = 
3240             (int) strtol(cached_containerlist_size, NULL, 10);
3241         else 
3242           _max_cached_list_size = 10;
3243     }
3244
3245     if (NULL != display_cfs)
3246       free((void*) display_cfs);
3247     if (NULL != cached_containerlist_size)
3248       free((void*) cached_containerlist_size);
3249
3250     int size = (_max_cached_list_size ? _max_cached_list_size : 1);
3251     _cached_containerlist = new DtVirtArray<ContainerMenuCmd*> (size);
3252
3253     if (user_list == DTM_TRUE) {
3254         char *expanded_list = m_session->expandPath(error, _filemenu2);
3255         char *token = NULL;
3256
3257         //
3258         // Create arrays to hold the user defined container list and the
3259         // recently visited (cached) container list.
3260         //
3261         if ((token = (char *) strtok(expanded_list, " ")))
3262         {
3263             ContainerMenuCmd *null_container;
3264             
3265             null_container= new ContainerMenuCmd(
3266                                                 strdup(token),
3267                                                 token,
3268                                                 TRUE,
3269                                                 this,
3270                                                 DTM_NONE);
3271             _user_containerlist->append(null_container);
3272             while (token = (char *) strtok(NULL, " "))
3273             {
3274                 null_container= new ContainerMenuCmd(
3275                                                 strdup(token),
3276                                                 token,
3277                                                 TRUE,
3278                                                 this,
3279                                                 DTM_NONE);
3280                 _user_containerlist->append(null_container);
3281             }
3282         }
3283         free(expanded_list);
3284     }
3285
3286     if (_user_containerlist->length() > 0)
3287       _first_cached_item = _user_containerlist->length() +4;
3288     else
3289       _first_cached_item = 3;
3290 }
3291
3292 void
3293 RoamMenuWindow::createOpenContainerList(CmdList * open_container)
3294 {
3295     int                 ncontainers;
3296     char                *container_name;
3297     ContainerMenuCmd    *container_cmd;
3298
3299     _open_container_separator = new SeparatorCmd("Separator","Separator", TRUE);
3300
3301     _open_container_inbox = new OpenInboxCmd(
3302                                         "Inbox",
3303                                         GETMSG(DT_catd, 1, 221, "Inbox"),
3304                                         (FALSE == this->inbox()),
3305                                         this);
3306
3307     _open_container_other = new UnifiedSelectMailboxCmd(
3308                                 "Open",
3309                                 GETMSG(DT_catd, 1, 246, "Other Mailboxes..."), 
3310                                 GETMSG(DT_catd, 1, 26, "Mailer - Open"),
3311                                 GETMSG(DT_catd, 1, 27, "Open"),
3312                                 TRUE,
3313                                 RoamMenuWindow::file_selection_callback,
3314                                 this,
3315                                 this->baseWidget(),
3316                                 DTM_TRUE);
3317
3318     //
3319     // We will use _open_container_containerlist to keep track of the
3320     // static set of OpenContainer commands coming from the "filemenu2"
3321     // value.
3322     //
3323     ncontainers = _user_containerlist->length();
3324
3325     if (_open_container_containerlist != NULL)
3326       delete (_open_container_containerlist);
3327     _open_container_containerlist =
3328       new DtVirtArray<ContainerMenuCmd*>(ncontainers);
3329
3330     for (int i=0; i<ncontainers; i++)
3331     {
3332         container_name = (*_user_containerlist)[i]->containerName();
3333         if (NULL != container_name)
3334         {
3335             container_cmd = new ContainerMenuCmd(
3336                                                 strdup(container_name),
3337                                                 container_name,
3338                                                 TRUE,
3339                                                 this,
3340                                                 DTM_OPEN);
3341             open_container->add(container_cmd);
3342             _open_container_containerlist->append(container_cmd);
3343         }
3344     }
3345
3346     if (0 < ncontainers)
3347       open_container->add(_open_container_separator);
3348     open_container->add(_open_container_inbox);
3349     open_container->add(_open_container_other);
3350     open_container->add(_open_container_separator);
3351
3352     //
3353     // We will use _open_container_containerlist_cached
3354     // to keep track of OpenContainer which get cached from
3355     // "Other Mailboxes..." operations from the Open, CopyTo, and Move menus.
3356     //
3357
3358     ncontainers =  (_max_cached_list_size ? _max_cached_list_size : 1);
3359
3360     if (_open_container_containerlist_cached != NULL)
3361       delete (_open_container_containerlist_cached);
3362     _open_container_containerlist_cached =
3363       new DtVirtArray<ContainerMenuCmd*> (ncontainers);
3364  
3365     ncontainers = (_display_cached_list ? _cached_containerlist->length() : 0);
3366     for (i=0; i<ncontainers; i++)
3367     {
3368         container_name = (*_cached_containerlist)[i]->containerName();
3369         if (NULL != container_name)
3370         {
3371             container_cmd = new ContainerMenuCmd(
3372                                                 strdup(container_name),
3373                                                 container_name,
3374                                                 TRUE,
3375                                                 this,
3376                                                 DTM_OPEN);
3377             open_container->add(container_cmd);
3378             _open_container_containerlist_cached->append(container_cmd);
3379         }
3380     }
3381 }
3382
3383
3384 void
3385 RoamMenuWindow::construct_file_menu()
3386 {
3387     FORCE_SEGV_DECL(CmdList, cmdList);
3388
3389     _file_separator = new SeparatorCmd( "Separator","Separator", TRUE );
3390     
3391     // Create the "Container" item in the menubar.  And fill 
3392     // with items below the "Container" item in the menubar.
3393     
3394     cmdList = new CmdList( "Mailbox", GETMSG(DT_catd, 1, 18, "Mailbox") );
3395     _file_cmdlist = cmdList;
3396
3397     _file_check_new_mail        = new CheckForNewMailCmd(
3398                                 "Check for New Mail",
3399                                 GETMSG(DT_catd, 1, 19, "Check for New Mail"), 
3400                                 TRUE, 
3401                                 this);
3402     if (this->inbox()) { // Deactivate the Open Inbox item 
3403         _file_open_inbox               = new OpenInboxCmd(
3404                                         "Open Inbox",
3405                                         GETMSG(DT_catd, 1, 20, "Open Inbox"),
3406                                         FALSE,
3407                                         this);
3408     }
3409     else { // Activate the Open Inbox item.
3410         _file_open_inbox               = new OpenInboxCmd(
3411                                         "Open Inbox",
3412                                         GETMSG(DT_catd, 1, 21, "Open Inbox"),
3413                                         TRUE,
3414                                         this);
3415     }
3416
3417     _file_new_container     = new UnifiedSelectMailboxCmd( 
3418                                 "New...",
3419                                 GETMSG(DT_catd, 1, 22, "New..."),
3420                                 GETMSG(DT_catd, 1, 23, "Mailer - New"),
3421                                 GETMSG(DT_catd, 1, 24, "New"),
3422                                 TRUE,
3423                                 RoamMenuWindow::create_container_callback,
3424                                 this,
3425                                 this->baseWidget(),
3426                                 DTM_TRUE);
3427 #if defined(USE_OLD_FILE_OPEN)
3428     _file_open              = new UnifiedSelectMailboxCmd(
3429                                 "Open...",
3430                                 GETMSG(DT_catd, 1, 25, "Open..."), 
3431                                 GETMSG(DT_catd, 1, 26, "Mailer - Open"),
3432                                 GETMSG(DT_catd, 1, 27, "Open"),
3433                                 TRUE,
3434                                 RoamMenuWindow::file_selection_callback,
3435                                 this,
3436                                 this->baseWidget());
3437 #endif
3438
3439     _open_container_cmdlist = new CmdList(
3440                                 "Open Container",
3441                                 GETMSG(DT_catd, 1, 245, "Open"));
3442     createOpenContainerList(_open_container_cmdlist);
3443
3444     _file_destroy_deleted_msgs  = new DestroyCmd(
3445                                         "Destroy Deleted Message",
3446                                         GETMSG(DT_catd, 1, 28, 
3447                                                 "Destroy Deleted Messages"), 
3448                                               TRUE,
3449                                               this);
3450
3451
3452     _file_quit              = new QuitCmd (
3453                                 "Close",
3454                                 GETMSG(DT_catd, 1, 29, "Close"), 
3455                                 TRUE, 
3456                                 this);
3457     
3458     cmdList->add(_file_check_new_mail);
3459     cmdList->add(_file_open_inbox);
3460     cmdList->add(_file_separator);
3461     cmdList->add(_file_new_container);
3462 #if defined(USE_OLD_FILE_OPEN)
3463     cmdList->add(_file_open);
3464 #endif
3465     cmdList->add(_open_container_cmdlist);
3466     cmdList->add(_file_separator);
3467     cmdList->add(_file_destroy_deleted_msgs);
3468     cmdList->add(theRoamApp.mailOptions());
3469     cmdList->add(_file_separator);
3470     cmdList->add(_file_quit);
3471     
3472     _menuBar->addCommands(&_file_cascade, cmdList);
3473  
3474     _opencontainerMenu = _open_container_cmdlist->getPaneWidget();
3475  
3476     XtVaSetValues(
3477                 _opencontainerMenu, 
3478                 XmNpacking, XmPACK_COLUMN, 
3479                 XmNorientation, XmVERTICAL,
3480                 NULL);
3481
3482     XtAddCallback(
3483                 _opencontainerMenu,
3484                 XmNmapCallback, &RoamMenuWindow::map_menu,
3485                 NULL);
3486
3487     XtSetSensitive(_opencontainerMenu, TRUE);
3488 }
3489
3490 void
3491 RoamMenuWindow::createCopyList(CmdList * copy_to)
3492 {
3493     int                 ncontainers;
3494     char                *container_name;
3495     ContainerMenuCmd    *container_cmd;
3496
3497     _copyto_separator = new SeparatorCmd("Separator","Separator", TRUE);
3498
3499     _copyto_inbox = new CopyToInboxCmd(
3500                                 "Inbox",
3501                                 GETMSG(DT_catd, 1, 221, "Inbox"), 
3502                                 TRUE, 
3503                                 this);
3504
3505     // This is where we initialize _move_copy_button, so this needs to
3506     // be the first place that we use it.  This routine needs to be
3507     // called before construct_move_menu(), which expects _move_copy_button
3508     // to be intialized.
3509
3510     DtMailEnv error;
3511     DtMail::Session * d_session = theRoamApp.session()->session();
3512     DtMail::MailRc * mailrc = d_session->mailRc(error);
3513     const char *value = NULL;
3514     DtMailBoolean only_show_mailboxes = DTM_FALSE;
3515
3516     mailrc->getValue(error, "movecopytomailboxesonly", &value);
3517     only_show_mailboxes = (error.isSet()) ? DTM_FALSE : DTM_TRUE;
3518     { 
3519         value = strdup("15");
3520         error.clear();
3521     }
3522     if (value)
3523       free((void*) value);
3524
3525     _move_copy_button = new MoveCopyCmd (
3526                                 "Other Mailboxes...",
3527                                 GETMSG(DT_catd, 1, 65, "Other Mailboxes..."),
3528                                 TRUE,
3529                                 RoamMenuWindow::move_callback,
3530                                 RoamMenuWindow::copy_callback,
3531                                 this,
3532                                 this->baseWidget(),
3533                                 only_show_mailboxes);
3534     _copyto_other = new CopyCmd(
3535                                 GETMSG(DT_catd, 1, 237, "Copy"),
3536                                 GETMSG(DT_catd, 1, 65, "Other Mailboxes..."),
3537                                 TRUE,
3538                                 this,
3539                                 (MoveCopyCmd *) _move_copy_button);
3540
3541     //
3542     // We will use _copyto_containerlist to keep track of the
3543     // static set of CopyTo commands coming from the "filemenu2"
3544     // value.
3545     //
3546     ncontainers = _user_containerlist->length();
3547
3548     if (_copyto_containerlist != NULL)
3549       delete (_copyto_containerlist);
3550     _copyto_containerlist =
3551       new DtVirtArray<ContainerMenuCmd *> (ncontainers);
3552
3553     for (int i=0; i<ncontainers; i++)
3554     {
3555         container_name = (*_user_containerlist)[i]->containerName();
3556         if (NULL != container_name)
3557         {
3558             container_cmd = new ContainerMenuCmd(
3559                                                 strdup(container_name),
3560                                                 container_name,
3561                                                 TRUE,
3562                                                 this,
3563                                                 DTM_COPY);
3564             copy_to->add(container_cmd);
3565             _copyto_containerlist->append(container_cmd);
3566         }
3567     }
3568
3569     if (0 < ncontainers)
3570       copy_to->add(_copyto_separator);
3571     copy_to->add(_copyto_inbox);
3572     copy_to->add(_copyto_other);
3573     copy_to->add(_copyto_separator);
3574
3575     //
3576     // We will use _copyto_containerlist_cached
3577     // to keep track of CopyTo commands which get cached from
3578     //"Other Mailboxes..." operations from the Open, CopyTo, and Move menus.
3579     //
3580
3581     ncontainers = (_max_cached_list_size ? _max_cached_list_size : 1);
3582
3583     if (_copyto_containerlist_cached != NULL)
3584       delete (_copyto_containerlist_cached);
3585     _copyto_containerlist_cached =
3586       new DtVirtArray<ContainerMenuCmd *> (ncontainers);
3587
3588     ncontainers = (_display_cached_list ? _cached_containerlist->length() : 0);
3589     for (i=0; i<ncontainers; i++)
3590     {
3591         container_name = (*_cached_containerlist)[i]->containerName();
3592         if (NULL != container_name)
3593         {
3594             container_cmd = new ContainerMenuCmd(
3595                                                 strdup(container_name),
3596                                                 container_name,
3597                                                 TRUE,
3598                                                 this,
3599                                                 DTM_COPY);
3600             copy_to->add(container_cmd);
3601             _copyto_containerlist_cached->append(container_cmd);
3602         }
3603     }
3604 }
3605
3606 void
3607 RoamMenuWindow::construct_message_menu()
3608 {
3609     FORCE_SEGV_DECL(CmdList, cmdList);
3610     // Separator for menu items
3611     
3612     _msg_separator= new SeparatorCmd( "Separator","Separator", TRUE );
3613     
3614     _msg_open           = new OpenMsgCmd(
3615                                 "Open",
3616                                 GETMSG(DT_catd, 1, 30, "Open"), 
3617                                 TRUE, this);
3618
3619     _msg_save_as        = new SaveAsTextCmd (
3620                                 "Save As Text...",
3621                                 GETMSG(DT_catd, 1, 31, "Save As Text..."),
3622                                 GETMSG(DT_catd, 1, 32, "Mailer - Message - Save As Text"),
3623                                 TRUE,
3624                                 get_editor()->textEditor(),
3625                                 this,
3626                                 this->baseWidget());
3627
3628     _copyto_cmdlist = new CmdList("Copy To", GETMSG(DT_catd, 1, 33, "Copy To"));
3629     createCopyList(_copyto_cmdlist);
3630
3631     _msg_print          = new PrintCmd(
3632                                 "Print...",
3633                                 GETMSG(DT_catd, 1, 34, "Print..."), 
3634                                 TRUE, FALSE, this);
3635
3636     _msg_find           = new FindCmd (
3637                                 "Find...",
3638                                 GETMSG(DT_catd, 1, 35, "Find..."), 
3639                                 TRUE, this );
3640
3641     _msg_select_all = new SelectAllCmd (
3642                                 "Select All",
3643                                 GETMSG(DT_catd, 1, 36, "Select All"),
3644                                 TRUE, this );
3645
3646     _msg_delete         = new DeleteCmd(
3647                                 "Delete",
3648                                 GETMSG(DT_catd, 1, 37, "Delete"),
3649                                 TRUE, this);
3650
3651     _msg_undelete_last       = new UndeleteCmd ( 
3652                                 "Undelete Last",
3653                                 GETMSG(DT_catd, 1, 38, "Undelete Last"), 
3654                                 TRUE, this, FALSE );
3655
3656     _msg_undelete_from_list   = new UndeleteCmd(
3657                                 "Undelete From List...",
3658                                 GETMSG(DT_catd, 1, 39, 
3659                                         "Undelete From List..."), 
3660                                 TRUE, this, TRUE);
3661
3662     // Message Menu
3663     
3664     cmdList = new CmdList( "Message", GETMSG(DT_catd, 1, 40, "Message") );
3665     _msg_cmdlist = cmdList;
3666
3667     cmdList->add(_msg_open);
3668     cmdList->add(_msg_save_as);
3669     cmdList->add(_copyto_cmdlist);
3670     cmdList->add(_msg_print);
3671     cmdList->add(_msg_find);
3672     cmdList->add(_msg_select_all);
3673
3674     cmdList->add(_msg_separator);
3675
3676     cmdList->add(_msg_delete);
3677     cmdList->add(_msg_undelete_last);
3678     cmdList->add(_msg_undelete_from_list);
3679
3680     _menuBar->addCommands(&_message_cascade, cmdList, FALSE, XmMENU_BAR);
3681  
3682     _copytoMenu = _copyto_cmdlist->getPaneWidget();
3683  
3684     XtVaSetValues(_copytoMenu, 
3685                   XmNpacking, XmPACK_COLUMN, 
3686                   XmNorientation, XmVERTICAL,
3687                   NULL);
3688
3689     XtAddCallback(_copytoMenu, XmNmapCallback, &RoamMenuWindow::map_menu, NULL);
3690
3691     XtSetSensitive(_copytoMenu, TRUE);
3692 }
3693
3694 void
3695 RoamMenuWindow::construct_message_popup(void)
3696 {
3697    _msgsPopup_cmdlist = new CmdList( "MsgsPopup", "MsgsPopup");
3698
3699    LabelCmd *title     = new LabelCmd (
3700                         "Mailer - Messages",
3701                         GETMSG(DT_catd, 1, 42, "Mailer - Messages"), TRUE);
3702    _msgsPopup_separator = new SeparatorCmd( "Separator","Separator", TRUE );
3703    _msgsPopup_cmdlist->add(title);
3704    _msgsPopup_cmdlist->add(_msgsPopup_separator);
3705    _msgsPopup_cmdlist->add(_msg_delete);
3706    _msgsPopup_cmdlist->add(_msg_undelete_last);
3707    _msgsPopup_cmdlist->add(_msg_print);
3708    _msgsPopup_cmdlist->add(_comp_replySender);
3709    _msgsPopup_cmdlist->add(_move_cmdlist);
3710    _msgsPopup_cmdlist->add(_msg_save_as);
3711    _msgsPopup_cmdlist->add(_file_check_new_mail);
3712
3713    Widget parent = XtParent(_list->get_scrolling_list());
3714    _menuPopupMsgs = new MenuBar(parent, "RoamMsgsPopup", XmMENU_POPUP);
3715    _msgsPopupMenu = _menuPopupMsgs->addCommands(_msgsPopup_cmdlist, 
3716                         FALSE, XmMENU_POPUP);
3717    XtAddEventHandler(parent, ButtonPressMask,
3718                         FALSE, MenuButtonHandler, (XtPointer) this);
3719    
3720    _msgsPopupMoveMenu = _move_cmdlist->getPaneWidget();
3721
3722    XtVaSetValues(_msgsPopupMoveMenu, 
3723                  XmNpacking, XmPACK_COLUMN, 
3724                  XmNorientation, XmVERTICAL,
3725                  NULL);
3726    XtAddCallback(_msgsPopupMoveMenu, XmNmapCallback, &RoamMenuWindow::map_menu, NULL);
3727
3728    XtSetSensitive(_msgsPopupMoveMenu, TRUE);
3729  
3730 }
3731
3732 void
3733 RoamMenuWindow::construct_edit_menu()
3734 {
3735     FORCE_SEGV_DECL(CmdList, cmdList);
3736     // Separator for menu items
3737     
3738     _edit_copy = new EditCopyCmd(
3739                         "Copy",
3740                         GETMSG(DT_catd, 1, 43, "Copy"), 
3741                         TRUE, 
3742                         this
3743                      );
3744
3745     _edit_select_all = new EditSelectAllCmd(
3746                         "Select All",
3747                         GETMSG(DT_catd, 1, 44, "Select All"), 
3748                         TRUE,
3749                         this
3750                     );
3751
3752     cmdList = new CmdList("Edit", GETMSG(DT_catd, 1, 45, "Edit"));
3753     _edit_cmdlist = cmdList;
3754
3755     cmdList->add(_edit_copy);
3756     cmdList->add(_edit_select_all);
3757     
3758     _menuBar->addCommands(cmdList);
3759 }
3760
3761 void
3762 RoamMenuWindow::construct_text_popup(void)
3763 {
3764    if (theApplication->bMenuButton() != Button3)
3765        return;
3766
3767    _textPopup_cmdlist = new CmdList( "TextPopup", "TextPopup");
3768
3769     LabelCmd *title     = new LabelCmd (
3770                         "Mailer - Text",
3771                         GETMSG(DT_catd, 1, 46, "Mailer - Text"), TRUE);
3772     _textPopup_separator = new SeparatorCmd( "Separator","Separator", TRUE );
3773
3774     _textPopup_cmdlist->add(title);
3775     _textPopup_cmdlist->add(_textPopup_separator);
3776     _textPopup_cmdlist->add(_edit_copy);
3777     _textPopup_cmdlist->add(_edit_select_all);
3778
3779     Widget parent = _my_editor->textEditor()->get_editor();
3780     _menuPopupText = new MenuBar(parent, "RoamTextPopup", XmMENU_POPUP);
3781     _textPopupMenu = _menuPopupText->addCommands(_textPopup_cmdlist, 
3782                                 FALSE, XmMENU_POPUP);
3783 }
3784
3785
3786 void RoamMenuWindow::construct_view_menu()
3787 {
3788     FORCE_SEGV_DECL(CmdList, cmdList);
3789     FORCE_SEGV_DECL(CmdList, subCmdList);
3790
3791     _view_separator= new SeparatorCmd("Separator","Separator",TRUE);
3792     
3793     _view_next          = new NextCmd ( 
3794                                 "Next",
3795                                 GETMSG(DT_catd, 1, 47, "Next"), TRUE, this );
3796     _view_previous              = new PrevCmd ( 
3797                                 "Previous",
3798                                 GETMSG(DT_catd, 1, 48, "Previous"), TRUE, this );
3799     
3800     _view_abbrev_headers = new AbbrevHeadersCmd(
3801                                 "Abbreviated Headers",
3802                                 GETMSG(DT_catd, 1, 49, "Abbreviated Headers"), 
3803                                 this);
3804
3805
3806     _view_sortTD = new SortCmd ("By Date/Time", 
3807                                 GETMSG(DT_catd, 1, 50, "By Date/Time"),
3808                                 TRUE,
3809                                 this,
3810                                 SortTimeDate);
3811     _view_sortSender = new SortCmd ("By Sender",
3812                                 GETMSG(DT_catd, 1, 51, "By Sender"),
3813                                 TRUE,
3814                                 this,
3815                                 SortSender);
3816     _view_sortSubject = new SortCmd ("By Subject",
3817                                 GETMSG(DT_catd, 1, 52, "By Subject"),
3818                                 TRUE,
3819                                 this,
3820                                 SortSubject);
3821     _view_sortSize = new SortCmd ("By Size",
3822                                 GETMSG(DT_catd, 1, 53, "By Size"),
3823                                 TRUE,
3824                                 this,
3825                                 SortSize);
3826     _view_sortStatus = new SortCmd ("By Status",
3827                                 GETMSG(DT_catd, 1, 54, "By Status"),
3828                                 TRUE,
3829                                 this,
3830                                 SortStatus);
3831
3832     // View Menu
3833     
3834     cmdList = new CmdList( "View", GETMSG(DT_catd, 1, 55, "View") );
3835     _view_cmdlist = cmdList;
3836     
3837     cmdList->add(_view_next);
3838     cmdList->add(_view_previous);
3839     cmdList->add(_view_separator);
3840     cmdList->add(_view_abbrev_headers);
3841     cmdList->add(_view_separator);
3842     cmdList->add(_view_sortTD);
3843     cmdList->add(_view_sortSender);
3844     cmdList->add(_view_sortSubject);
3845     cmdList->add(_view_sortSize);
3846     cmdList->add(_view_sortStatus);
3847     
3848     _menuBar->addCommands ( cmdList );
3849 }
3850
3851
3852 void
3853 RoamMenuWindow::construct_compose_menu()
3854 {
3855     FORCE_SEGV_DECL(CmdList, cmdList);
3856     FORCE_SEGV_DECL(CmdList, subCmdList);
3857
3858     // Separator for menu items
3859     
3860     _comp_separator= new SeparatorCmd( "Separator","Separator", TRUE );
3861     
3862     _comp_new   = new ComposeCmd ( 
3863                         "New Message",
3864                         GETMSG(DT_catd, 1, 56, "New Message"), 
3865                         TRUE, 
3866                         this );
3867     _comp_new_include = new ForwardCmd ( 
3868                         "New, Include All",
3869                         GETMSG(DT_catd, 1, 57, "New, Include All"), 
3870                         TRUE, 
3871                         this, 
3872                         FALSE );
3873     _comp_forward       = new ForwardCmd ( 
3874                         "Forward Message",
3875                         GETMSG(DT_catd, 1, 58, "Forward Message"), 
3876                         TRUE, 
3877                         this, 
3878                         TRUE );
3879
3880     _comp_replySender = new ReplyCmd ( 
3881                               "Reply to Sender",
3882                               GETMSG(DT_catd, 1, 59, "Reply to Sender"), 
3883                               TRUE, 
3884                               this, 
3885                               FALSE );
3886
3887     _comp_replyAll      = new ReplyAllCmd ( 
3888                         "Reply to All",
3889                         GETMSG(DT_catd, 1, 60, "Reply to All"), 
3890                         TRUE, 
3891                         this, 
3892                         FALSE );
3893
3894     _comp_replySinclude= new ReplyCmd ( 
3895                         "Reply to Sender, Include",
3896                         GETMSG(DT_catd, 1, 61, "Reply to Sender, Include"), 
3897                         TRUE, 
3898                         this, 
3899                         TRUE ); 
3900
3901     _comp_replyAinclude= new ReplyAllCmd ( 
3902                         "Reply to All, Include",
3903                         GETMSG(DT_catd, 1, 62, "Reply to All, Include"), 
3904                         TRUE, 
3905                         this, 
3906                         TRUE ); 
3907
3908     
3909     // Compose Menu
3910     
3911     cmdList = new CmdList( "Compose", GETMSG(DT_catd, 1, 63, "Compose") );
3912     _comp_cmdlist = cmdList;
3913     cmdList->add(_comp_new);
3914     cmdList->add(_comp_new_include);
3915     cmdList->add(_comp_forward);
3916     cmdList->add(_comp_separator);
3917     cmdList->add(_comp_replySender);
3918     cmdList->add(_comp_replyAll);
3919     cmdList->add(_comp_replySinclude);
3920     cmdList->add(_comp_replyAinclude);
3921
3922     _menuBar->addCommands ( cmdList );
3923 }
3924
3925 // construct_move_menu() builds the Move menu on the menu bar.  
3926 // There is a user defined set of items at the top, the Inbox,
3927 // the "Mail Filing..." item, and a dynamic list of most recently
3928 // accessed containers at the bottom.
3929
3930 void
3931 RoamMenuWindow::construct_move_menu()
3932 {
3933     int                 ncontainers;
3934     char                *container_name;
3935     ContainerMenuCmd    *container_cmd;
3936
3937
3938     if (_move_cmdlist != NULL)
3939       delete _move_cmdlist;
3940     _move_cmdlist = new CmdList( "Move", GETMSG(DT_catd, 1, 64, "Move") );
3941
3942     _move_separator = new SeparatorCmd("Separator","Separator", TRUE );
3943
3944     _move_inbox = new MoveToInboxCmd(
3945                                 "Inbox",
3946                                 GETMSG(DT_catd, 1, 221, "Inbox"),
3947                                 TRUE, 
3948                                 this);
3949
3950     // We expect _move_copy_button to have been initialized already when
3951     // we constructed the copy menu.
3952     _move_other = new MoveCmd(
3953                                 GETMSG(DT_catd, 1, 90, "Move"),
3954                                 GETMSG(DT_catd, 1, 65, "Other Mailboxes..."),
3955                                 TRUE,
3956                                 this,
3957                                 (MoveCopyCmd *) _move_copy_button);
3958
3959     //
3960     // We will use _move_containerlist to keep track of the
3961     // static set of Move commands coming from the "filemenu2"
3962     // value.
3963     //
3964     ncontainers = _user_containerlist->length();
3965
3966     if (_move_containerlist != NULL)
3967       delete _move_containerlist;
3968     _move_containerlist = new DtVirtArray<ContainerMenuCmd *> (ncontainers);
3969
3970     for (int i=0; i<ncontainers; i++)
3971     {
3972         container_name = (*_user_containerlist)[i]->containerName();
3973         if (NULL != container_name)
3974         {
3975             container_cmd = new ContainerMenuCmd(
3976                                                 strdup(container_name),
3977                                                 container_name,
3978                                                 TRUE,
3979                                                 this,
3980                                                 DTM_MOVE);
3981             _move_cmdlist->add(container_cmd);
3982             _move_containerlist->append(container_cmd);
3983         }
3984     }
3985
3986     // Move menu
3987     if (0 < ncontainers)
3988       _move_cmdlist->add(_move_separator);
3989     _move_cmdlist->add(_move_inbox);
3990
3991     _move_cmdlist->add(_move_other);
3992     _move_cmdlist->add(_move_separator);
3993
3994     //
3995     // We will use _move_containerlist_cached
3996     // to keep track of Move commands which get cached from
3997     // "Other Mailboxes..." operations from the Open, CopyTo, and Move menus.
3998     //
3999
4000     ncontainers = (_max_cached_list_size ? _max_cached_list_size : 1 );
4001
4002     if (_move_containerlist_cached != NULL)
4003       delete _move_containerlist_cached;
4004     _move_containerlist_cached =
4005       new DtVirtArray<ContainerMenuCmd *> (ncontainers);
4006     
4007     ncontainers = (_display_cached_list ? _cached_containerlist->length() : 0);
4008     for (i=0; i<ncontainers; i++)
4009     {
4010         container_name = (*_cached_containerlist)[i]->containerName();
4011         if (NULL != container_name)
4012         {
4013             container_cmd = new ContainerMenuCmd(
4014                                                 strdup(container_name),
4015                                                 container_name,
4016                                                 TRUE,
4017                                                 this,
4018                                                 DTM_MOVE);
4019             _move_cmdlist->add(container_cmd);
4020             _move_containerlist_cached->append(container_cmd);
4021         }
4022     }
4023
4024
4025     _moveMenu = _menuBar->addCommands(
4026                                 &_move_cascade, _move_cmdlist, 
4027                                 FALSE, XmMENU_BAR);
4028     XtVaSetValues(_moveMenu, 
4029                   XmNpacking, XmPACK_COLUMN, 
4030                   XmNorientation, XmVERTICAL,
4031                   NULL);
4032     XtAddCallback(_moveMenu, XmNmapCallback, &RoamMenuWindow::map_menu, NULL);
4033 }
4034
4035
4036 // Attachment menu
4037 void
4038 RoamMenuWindow::construct_attachment_menu()
4039 {
4040
4041     _att_save   = new SaveAttachCmd (
4042                                 "Save As...",
4043                                 GETMSG(DT_catd, 1, 66, "Save As..."),
4044                                 GETMSG(DT_catd, 1, 67, "Mailer - Attachments - Save As"),
4045                                 FALSE, 
4046                                 RoamMenuWindow::save_attachment_callback,
4047                                 this,
4048                                 this->baseWidget());
4049
4050     _att_select_all = new SelectAllAttachsCmd(
4051                                         "Select All",
4052                                         GETMSG(
4053                                             DT_catd, 1, 68, "Select All"
4054                                         ),
4055                                         this);
4056
4057     _att_cmdlist = new CmdList( 
4058                                         "Attachments",
4059                                         GETMSG(
4060                                                 DT_catd, 1, 69, 
4061                                                 "Attachments"
4062                                         ) 
4063                                 );
4064     _att_cmdlist->add(_att_save);
4065     _att_cmdlist->add(_att_select_all);
4066
4067     // Create a pulldown from the items in the list.  Retain a handle
4068     // to that pulldown since we need to dynamically add/delete entries 
4069     // to this menu based on the selection of attachments.
4070
4071     _attachmentMenu = _menuBar->addCommands(_att_cmdlist);
4072 }
4073
4074 void
4075 RoamMenuWindow::construct_attachment_popup(void)
4076 {
4077    _attPopup_cmdlist = new CmdList( "AttachmentsPopup", "AttachmentsPopup");
4078
4079     LabelCmd *title     = new LabelCmd (
4080                         "Mailer - Attachments",
4081                         GETMSG(DT_catd, 1, 70, "Mailer - Attachments"), TRUE);
4082     _attPopup_separator = new SeparatorCmd( "Separator","Separator", TRUE );
4083
4084     _attPopup_cmdlist->add(title);
4085     _attPopup_cmdlist->add(_attPopup_separator);
4086     _attPopup_cmdlist->add(_att_save);
4087     _attPopup_cmdlist->add(_att_select_all);
4088     _menuPopupAtt = new MenuBar(_my_editor->attachArea()->getClipWindow(), 
4089                                         "RoamAttachmentPopup", XmMENU_POPUP);
4090     _attachmentPopupMenu = _menuPopupAtt->addCommands(_attPopup_cmdlist, 
4091                                 FALSE, XmMENU_POPUP);
4092 }
4093
4094 void
4095 RoamMenuWindow::construct_help_menu()
4096 {
4097     FORCE_SEGV_DECL(CmdList, cmdList);
4098
4099     // Separator for menu items
4100     
4101     _help_separator= new SeparatorCmd( "Separator","Separator", TRUE );
4102     _help_overview = new OnAppCmd("Overview", GETMSG(DT_catd, 1, 71, "Overview"), 
4103                                 TRUE, this);
4104     _help_tasks = new TasksCmd("Tasks", GETMSG(DT_catd, 1, 72, "Tasks"), 
4105                                 TRUE, this);
4106     _help_reference = new ReferenceCmd("Reference",
4107                                 GETMSG(DT_catd, 1, 73, "Reference"), 
4108                                 TRUE, this);
4109     _help_on_item = new OnItemCmd("On Item", GETMSG(DT_catd, 1, 74, "On Item"), 
4110                                 TRUE, this);
4111     _help_using_help = new UsingHelpCmd("Using Help",
4112                                 GETMSG(DT_catd, 1, 75, "Using Help"), 
4113                                 TRUE, this);
4114     cmdList = new CmdList( "Help", GETMSG(DT_catd, 1, 76, "Help") );
4115     _help_cmdlist = cmdList;
4116
4117     cmdList->add ( _help_overview );
4118     cmdList->add ( _help_separator );
4119     cmdList->add ( _help_tasks );
4120     cmdList->add ( _help_reference );
4121     cmdList->add ( _help_separator );
4122     cmdList->add ( _help_on_item );
4123     cmdList->add ( _help_separator );
4124     cmdList->add ( _help_using_help );
4125     cmdList->add ( _help_separator );
4126
4127     _help_about_mailer = new RelNoteCmd("About Mailer...", 
4128                                     GETMSG(DT_catd, 1, 77, "About Mailer..."),
4129                                     TRUE, this);
4130     cmdList->add ( _help_about_mailer );
4131
4132     // Make help menu show up on right side of menubar.
4133     _menuBar->addCommands ( cmdList, TRUE );
4134     
4135 }
4136  
4137 void
4138 RoamMenuWindow::syncCachedContainerList(void)
4139 {
4140     RoamMenuWindow      *rmw = NULL;
4141
4142     rmw = theRoamApp.nextRoamMenuWindow(NULL);
4143     if (NULL == rmw)
4144       return;
4145
4146     // Sync the cached lists to an existing RoamMenuWindow.
4147     for (int i = rmw->_cached_containerlist->length(); i > 0; i--) {
4148         char *name = (*(rmw->_cached_containerlist))[i-1]->containerName();
4149         addToCachedContainerList(name);
4150     }
4151 }
4152
4153 DtMail::MailRc *
4154 RoamMenuWindow::get_mail_rc()
4155 {
4156     DtMailEnv error;
4157
4158     if (NULL == _mailbox) return NULL;
4159     return _mailbox->session()->mailRc(error);
4160 }
4161
4162
4163 void
4164 RoamMenuWindow::load_mailbox(
4165     DtMailEnv & mail_error
4166 )
4167 {
4168     int         count = 0;
4169     
4170     // If there is no mailbox, return.
4171     if (!_mailbox) {
4172         mail_error.clear();
4173         return;
4174     }
4175
4176     // Now load the messages into the scrolling list.
4177     // This will get the DtMailMessageHandles into the _msgs array and
4178     // it will also get their XmStrings into the CharArray of the _list.
4179     theRoamApp.busyAllWindows(GETMSG(DT_catd, 3, 27, "Loading..."));
4180         
4181     // Call load_headers() to get the XmStrings into the XmList!
4182
4183     count = _list->load_headers(mail_error);
4184     
4185     if (mail_error.isSet()) {
4186         // Return whatever error mailbox->get_next_msg() returned.
4187         theRoamApp.unbusyAllWindows();
4188         return;
4189     }
4190
4191     // If no messages
4192
4193     if (count == 0) {
4194         this->message(GETMSG(DT_catd, 3, 28, "Empty container"));
4195         setIconName(EmptyIcon);
4196     }
4197
4198     _list->sort_messages();
4199
4200     theRoamApp.unbusyAllWindows();
4201 }
4202
4203 void
4204 RoamMenuWindow::clear_message()
4205 {
4206     this->message("");
4207 }
4208
4209 void
4210 RoamMenuWindow::text_selected()
4211 {
4212
4213     // turn on sensitivity for Cut/Clear/Copy/Paste/Delete
4214
4215 }
4216
4217 void
4218 RoamMenuWindow::text_unselected()
4219 {
4220
4221     // turn off sensitivity for those items
4222
4223 }
4224
4225     // syncViewAndStore() does the sync-ing of the view of a mail
4226     // container and the storage of that container.
4227     // This method gets invoked every time a message gets expunged
4228     // by the back end based on "timed delete".
4229     // The method needs to then remove the expunged message from the
4230     // deleted messages list, thereby syncing the view to be always
4231     // current with the storage.
4232     // Similarly, the method also gets invoked when the container store
4233     // has received new mail.  The view then needs to be updated....
4234
4235
4236 DtMailBoolean
4237 RoamMenuWindow::syncViewAndStoreCallback(
4238     DtMailCallbackOp op,
4239     const char *path,
4240     const char *,       // prompt_hint
4241     void *client_data,  
4242     ...
4243 )
4244 {
4245
4246     DtMailBoolean bval;
4247     va_list args;
4248
4249     va_start(args, client_data);
4250     RoamMenuWindow * rmw = (RoamMenuWindow *)client_data;
4251
4252     bval = rmw->syncViewAndStore(op, path, args);
4253     return(bval);
4254 }
4255
4256 DtMailBoolean
4257 RoamMenuWindow::syncViewAndStore(
4258     DtMailCallbackOp op,
4259     const char *path,
4260     va_list args
4261 )
4262 {
4263
4264     DtMailEnv error;
4265     DtMailMessageHandle tmpMH;
4266     char *errmsg;
4267     int answer;
4268
4269
4270     this->busyCursor();
4271
4272     switch(op) {
4273       case DTMC_NEWMAIL:
4274
4275         // New mail has come in.  Load it in and update the
4276         // view's list of headers to also display it.
4277
4278         tmpMH = va_arg(args, DtMailMessageHandle);
4279         this->_list->load_headers(error, tmpMH);
4280
4281         newMailIndicators();
4282
4283         break;
4284
4285       case DTMC_DELETEMSG:
4286
4287         // A message has been expunged from the store by the back end.  
4288         // The expunge has been done based on "timed delete". 
4289         // Remove the expunged message from the displayed list of
4290         // message headers. 
4291         break;
4292
4293       case DTMC_BADSTATE:
4294
4295         errmsg = GETMSG(DT_catd, 1, 238, "Mailer is confused about the state of this mailbox.\nIt may be that another process has rewritten this mailbox in an unexpected way.\n\nSelecting OK will cause the Mailer to close and reopen the mailbox.\nNOTE that any changes made to the mailbox since the last save may be lost.");
4296         this->_genDialog->setToErrorDialog(
4297                                 GETMSG(DT_catd, 2, 10, "Mailer"),
4298                                 errmsg);
4299         answer = this->_genDialog->post_and_return(
4300                                 GETMSG(DT_catd, 3, 29, "OK"),
4301                                 DTMAILHELPUNKNOWNSTATE);
4302
4303         this->reopen_mail_file();
4304         if (DTM_TRUE)
4305           return(DTM_TRUE);
4306         break;
4307
4308       case DTMC_ACCESSFAILED:
4309         
4310         errmsg = GETMSG(DT_catd, 1, 239, "Mailer can no longer access this mailbox.\nIt may be that another process has deleted the mailbox file.\n\nSelecting OK will cause the Mailer to close and reopen the mailbox.\nNOTE that any changes made to the mailbox since the last save may be lost.\n\nSelecting CANCEL will leave the mailbox unchanged.");
4311         this->_genDialog->setToErrorDialog(
4312                                 GETMSG(DT_catd, 2, 10, "Mailer"),
4313                                 errmsg);
4314         answer = this->_genDialog->post_and_return(
4315                                 GETMSG(DT_catd, 3, 29, "OK"),
4316                                 GETMSG(DT_catd, 3, 19, "Cancel"),
4317                                 DTMAILHELPUNKNOWNSTATE);
4318         this->normalCursor();
4319         if (answer == 1)
4320         {
4321             this->reopen_mail_file();
4322             return(DTM_TRUE);
4323         }
4324         else
4325           return(DTM_FALSE);
4326         break;
4327
4328       case DTMC_SERVERPASSWORDNEEDED:
4329         
4330         {
4331             char *buffer = new char[2048];
4332             char *errmsgarg =   va_arg(args, char*);
4333
4334             sprintf(buffer, "%s", errmsgarg);
4335             this->_genDialog->setToTextFieldDialog(
4336                                 GETMSG(DT_catd, 2, 10, "Mailer"),
4337                                 buffer, DTM_TRUE);
4338             answer = this->_genDialog->post_and_return(
4339                                 GETMSG(DT_catd, 3, 29, "Ok"),
4340                                 GETMSG(DT_catd, 3, 19, "Cancel"),
4341                                 DTMAILHELPUNKNOWNSTATE);
4342             this->normalCursor();
4343             delete [] buffer;
4344             if (answer == 1)
4345             {
4346                 char            *password = NULL;
4347                 DtMailEnv       mail_error;
4348                 password = _genDialog->getTextFieldValue();
4349                 _mailbox->updateMailRetrievalPassword(password);
4350                 _mailbox->checkForMail(error);
4351                 if (NULL != password) free(password);
4352                 return(DTM_TRUE);
4353             }
4354             else
4355               return(DTM_FALSE);
4356         }
4357         break;
4358
4359       case DTMC_SERVERACCESSFAILED:
4360         
4361         {
4362             char *buffer = new char[2048];
4363             char *errmsgarg =   va_arg(args, char*);
4364
4365             errmsg = GETMSG(DT_catd, 1, 256, "Mail server access failed:\n%s");
4366
4367             sprintf(buffer, errmsg, errmsgarg);
4368             this->_genDialog->setToErrorDialog(
4369                                 GETMSG(DT_catd, 2, 10, "Mailer"),
4370                                 buffer);
4371             answer = this->_genDialog->post_and_return(
4372                                 GETMSG(DT_catd, 1, 257, "Options..."),
4373                                 GETMSG(DT_catd, 3, 19, "Cancel"),
4374                                 DTMAILHELPUNKNOWNSTATE);
4375             this->normalCursor();
4376             delete [] buffer;
4377             if (answer == 1)
4378             {
4379                 OptCmd  *optCmd = (OptCmd *) theRoamApp.mailOptions();
4380                 optCmd->displayMailRetrievalOptionsPane();
4381                 return(DTM_TRUE);
4382             }
4383             else
4384               return(DTM_FALSE);
4385         }
4386         break;
4387
4388       case DTMC_GETMAILCOMMANDFAILED:
4389         
4390         {
4391             char *buffer = new char[2048];
4392             char *errmsgarg =   va_arg(args, char*);
4393
4394             errmsg =
4395               GETMSG(DT_catd, 1, 258, "User Getmail command failed:\n%s");
4396
4397             sprintf(buffer, errmsg, errmsgarg);
4398             this->_genDialog->setToErrorDialog(
4399                                 GETMSG(DT_catd, 2, 10, "Mailer"),
4400                                 buffer);
4401             answer = this->_genDialog->post_and_return(
4402                                 GETMSG(DT_catd, 1, 257, "Options..."),
4403                                 GETMSG(DT_catd, 3, 19, "Cancel"),
4404                                 DTMAILHELPUNKNOWNSTATE);
4405             this->normalCursor();
4406             delete [] buffer;
4407             if (answer == 1)
4408             {
4409                 OptCmd  *optCmd = (OptCmd *) theRoamApp.mailOptions();
4410                 optCmd->displayMailRetrievalOptionsPane();
4411                 return(DTM_TRUE);
4412             }
4413             else
4414               return(DTM_FALSE);
4415         }
4416         break;
4417
4418       case DTMC_SERVERACCESSINFO:
4419         
4420         {
4421             char *infomsg = va_arg(args, char*);
4422             message(infomsg);
4423             return DTM_TRUE ;
4424         }
4425         break;
4426
4427       case DTMC_SERVERACCESSINFOERROR:
4428         
4429         {
4430             char *buffer = new char[2048];
4431             char *errmsgarg =   va_arg(args, char*);
4432
4433             sprintf(buffer, "%s", errmsgarg);
4434             this->_genDialog->setToErrorDialog(
4435                                 GETMSG(DT_catd, 2, 10, "Mailer"),
4436                                 buffer);
4437             answer = this->_genDialog->post_and_return(
4438                                 GETMSG(DT_catd, 1, 257, "Options..."),
4439                                 GETMSG(DT_catd, 3, 19, "Cancel"),
4440                                 DTMAILHELPUNKNOWNSTATE);
4441             this->normalCursor();
4442             delete [] buffer;
4443             if (answer == 1)
4444             {
4445                 OptCmd  *optCmd = (OptCmd *) theRoamApp.mailOptions();
4446                 optCmd->displayMailRetrievalOptionsPane();
4447                 return(DTM_TRUE);
4448             }
4449             else
4450               return(DTM_FALSE);
4451         }
4452         break;
4453
4454       case DTMC_INODECHANGED:
4455         
4456         errmsg = GETMSG(DT_catd, 1, 240, "Mailer can no longer access this mailbox.\nAnother process has rewritten the mailbox file changing the inode.\n\nSelecting OK will cause the Mailer to close and reopen the mailbox.\nNOTE that any changes made to the mailbox since the last save may be lost.\n\nSelecting CANCEL will leave the mailbox unchanged.");
4457
4458         this->_genDialog->setToErrorDialog(
4459                                 GETMSG(DT_catd, 2, 10, "Mailer"),
4460                                 errmsg);
4461         answer = this->_genDialog->post_and_return(
4462                                 GETMSG(DT_catd, 3, 29, "OK"),
4463                                 GETMSG(DT_catd, 3, 19, "Cancel"),
4464                                 DTMAILHELPUNKNOWNSTATE);
4465         this->normalCursor();
4466         if (answer == 1)
4467         {
4468             this->reopen_mail_file();
4469             return(DTM_TRUE);
4470         }
4471         else
4472           return(DTM_FALSE);
4473         break;
4474
4475       case DTMC_UNLOCK:
4476         
4477         // We are asked to save changes and close the file.
4478         // The backend will take care of unlocking the file.
4479         this->quit_silently();
4480         return(DTM_TRUE);
4481
4482       case DTMC_QUERYLOCK:
4483
4484         // The file is lock by another mailer.
4485         // Should we ask for the lock?
4486         _genDialog->setToQuestionDialog(GETMSG(DT_catd, 3, 16, "Mailer"),
4487            GETMSG(DT_catd, 3, 82, "Someone else is using this mailbox.\nWould you like to demand exclusive access?"));
4488         answer = _genDialog->post_and_return(GETMSG(DT_catd, 3, 18, "OK"),
4489            GETMSG(DT_catd, 3, 19, "Cancel"), DTMAILHELPTAKELOCK);
4490
4491         this->normalCursor();
4492         if (answer == 1) {
4493           return(DTM_TRUE);
4494         } else {
4495           return(DTM_FALSE);
4496         }
4497
4498     case DTMC_READONLY:
4499
4500       // We are not able to obtain a TT lock on this folder,
4501       // ask user if he wants to open it as read only.
4502       _genDialog->setToQuestionDialog(GETMSG(DT_catd, 3, 16, "Mailer"),
4503                                       GETMSG(DT_catd, 3, 83, "Mailer is unable to obtain exclusive access to this mailbox.\nWould you like to open this mailbox read-only?"));
4504         answer = _genDialog->post_and_return(GETMSG(DT_catd, 3, 18, "OK"),
4505                                              GETMSG(DT_catd, 3, 19, "Cancel"),
4506                                              DTMAILHELPOPENREADONLY);
4507         this->normalCursor();
4508         if (answer == 1) {
4509           return(DTM_TRUE);
4510         } else {
4511           return(DTM_FALSE);
4512         }
4513
4514     case DTMC_READWRITEOVERRIDE:
4515       // We are not able to obtain a lock on this folder,
4516       // ask user if he wants to open it as read only.
4517       _genDialog->setToQuestionDialog(GETMSG(DT_catd, 3, 16, "Mailer"),
4518                                       GETMSG(DT_catd, 3, 94, "Mailer is unable to obtain exclusive access to this\nmailbox because the system is not responding.\n\nFor this time only, you can choose to open this mailbox\nread-only, or to open it read-write without exclusive\naccess (use only if no one else is using this mailbox)."));
4519         answer = _genDialog->post_and_return(GETMSG(DT_catd, 3, 95, "Read-only"),
4520                                              GETMSG(DT_catd, 3, 19, "Cancel"),
4521                                              GETMSG(DT_catd, 3, 96, "Read-Write"), 
4522                                              DTMAILHELPOPENREADWRITEOVERRIDE);
4523         this->normalCursor();
4524         // Now the tricky part - since this method can only return 
4525         // DTM_TRUE or DTM_FALSE, we must have a way to indicate "readOnly",
4526         // "readWrite" or "cancel" - horrid hack: readOnly is DTM_FALSE, 
4527         // "readWrite" is DTM_TRUE, and "cancel" is (DTM_TRUE+DTM_FALSE)*2
4528         //
4529         switch (answer)
4530           {
4531           case 1:       // Read-only
4532             return(DTM_FALSE);
4533           case 3:       // Read-Write
4534             return(DTM_TRUE);
4535           default:      // cancel
4536             return((DtMailBoolean)((DTM_FALSE+DTM_TRUE)*2));
4537           }
4538
4539     case DTMC_DOTDTMAILLOCKFAILED:
4540
4541       {
4542         char *buffer            = new char[2048];
4543         char *lockpath          = va_arg(args, char*);
4544         char *errormsg          = va_arg(args, char*);
4545         char *cancel            = GETMSG(DT_catd, 3, 19, "Cancel");
4546         char *ok                = GETMSG(DT_catd, 3, 18, "OK");
4547         char *mailer            = GETMSG(DT_catd, 3, 16, "Mailer");
4548         char *msgfmt            = GETMSG(DT_catd, 3, 97, "%s\n\nThis may indicate that another Mailer has opened\n%s\n\nYou may open this mailbox READ ONLY by choosing '%s'.\n\nOtherwise, you may choose '%s',\nmake sure that another Mailer has not opened this mailbox,\ndelete %s,\nand reopen this mailbox.");
4549
4550         // We are not able to obtain a .dtmail lock on this folder,
4551         // ask user if he wants to open it as read only.
4552         sprintf(buffer, msgfmt, errormsg, path, ok, cancel, lockpath);
4553         _genDialog->setToQuestionDialog(mailer, buffer);
4554         answer =_genDialog->post_and_return(ok, cancel, DTMAILHELPOPENREADONLY);
4555         this->normalCursor();
4556         delete [] buffer;
4557         if (answer == 1) {
4558           return(DTM_TRUE);
4559         } else {
4560           return(DTM_FALSE);
4561         }
4562       }
4563
4564       default:
4565         this->normalCursor();
4566         return(DTM_FALSE);
4567     }
4568
4569     this->normalCursor();
4570     return(DTM_TRUE);
4571 }
4572
4573 // Convert the rfc file.
4574 // Commented out for PAR 5.  Needs to be uncommented out for PAR 6
4575 // and above.
4576
4577 void
4578 RoamMenuWindow::convert(
4579     char *,             // src
4580     char *              // dest
4581 )
4582 {
4583     // Obsoleted when Bento went away
4584 }
4585
4586 // The back end uses the return value to either continue conversion or
4587 // to stop converting.
4588
4589 int
4590 RoamMenuWindow::ConvertStatusCB(
4591     int current, 
4592     int total, 
4593     void * client_data
4594 )
4595 {
4596
4597     RoamMenuWindow *rmw = (RoamMenuWindow *)client_data;
4598
4599     // Return 0 if the conversion is still to proceed.
4600     // Return 1 if the conversion is to stop (e.g., if the user
4601     // has interrupted it...)
4602
4603     return(rmw->showConversionStatus(current, total));
4604 }
4605
4606 int
4607 RoamMenuWindow::showConversionStatus(
4608     int current, 
4609     int total
4610 )
4611 {
4612     char *buf, *str;
4613     int num_already_converted;  // num msgs already converted as set prev.
4614     int previously_complete;  // percent of converted msgs as set prev.
4615     int now_complete;  // percent of converted messages based on parameters
4616
4617     // Remember,  the number set may differ from the previous call to
4618     // this method.  We are not doing set_convert_data() for every call
4619     // to this method and so, what's set will differ from the previous
4620     // call to this method...
4621
4622     num_already_converted = _convertContainerCmd->get_num_converted();
4623     previously_complete = num_already_converted * 100 / total;
4624
4625     now_complete = current * 100 / total;
4626
4627     if ((now_complete > (previously_complete + 5)) ||
4628         (now_complete == 100)) {
4629         str = GETMSG(DT_catd, 1, 79, "Converting... %d percent complete"); 
4630         // Estimate 4 characters for numbers and 1 null terminator.
4631         buf = new char[strlen(str) + 5];   
4632         sprintf(buf, str, now_complete);
4633         
4634         _convertContainerCmd->updateDialog(buf);
4635         delete [] buf;
4636
4637         _convertContainerCmd->set_convert_data(current, total);
4638     }
4639     else {
4640         _convertContainerCmd->updateAnimation();
4641     }
4642
4643     // Check and see if the user had interrupted the conversion
4644     // If the user had interrupted, we need to stop the back-end
4645     // convert...
4646
4647     if (_convertContainerCmd->interrupted()) {
4648         return(1);
4649     }
4650     else {
4651         return(0);
4652     }
4653 }
4654
4655     
4656 void
4657 RoamMenuWindow::conversionFinishedCallback( 
4658     RoamInterruptibleCmd *,
4659     Boolean interrupted,
4660     void             *clientData
4661 )
4662 {
4663
4664     // Do something only it the conversion really finished.
4665     // If it was interrupted, just return...
4666
4667     if (!interrupted) {
4668         RoamMenuWindow *rmw = (RoamMenuWindow *) clientData;
4669         rmw->conversionFinished();
4670     }
4671 }
4672
4673 // If the conversion finished successfully, then we try to open() again
4674 // and if no problems, load the headers into the scrolling list...
4675
4676 void
4677 RoamMenuWindow::conversionFinished()
4678 {
4679     DtMailEnv mail_error;
4680
4681     // Initialize the mail_error.
4682     mail_error.clear();
4683
4684     mailboxFullpath(_convertContainerCmd->get_destination_name());
4685
4686     this->open(mail_error, 
4687                _openContainerCmd->_open_create_flag,
4688                _openContainerCmd->_open_lock_flag);
4689     
4690     // if the user had cancelled the open, then the RMW will not have
4691     // its mailbox set. Do not proceed to load the mailbox.  Return.
4692
4693     // Ideally, open() should set the mail_error if the user cancels
4694     // the open.  And we should check the mail_error here...
4695
4696     if (mail_error.isSet()) {
4697         return;
4698     }
4699
4700     this->load_mailbox(mail_error);
4701
4702     if (mail_error.isSet()) {
4703
4704         // Post a dialog indicating problems in loading...
4705     }
4706
4707 }
4708
4709
4710 // Post the dialog displaying the error text.
4711 // Also display the minor_code, if resource/environment variable
4712 // wants it.
4713 // User has no choice but to OK
4714 // postErrorDialog() is the benign uncle of postFatalErrorDialog() --
4715 // it does not quit the RMW.
4716
4717 void
4718 RoamMenuWindow::postErrorDialog(
4719     DtMailEnv &mail_error
4720 )
4721 {
4722     char *helpId;
4723
4724     const char *text_str = (const char *)mail_error;
4725
4726     // Assume that the char *text that comes in has already 
4727     // been processed for i18n.
4728
4729     _genDialog->setToErrorDialog(GETMSG(DT_catd, 2, 13, "Mailer"), 
4730                                  (char *)text_str);
4731     
4732     helpId = DTMAILHELPERROR;
4733     int i = _genDialog->post_and_return(GETMSG(DT_catd, 3, 31, "OK"), helpId);
4734
4735     // Clear the Error
4736     mail_error.clear();
4737
4738 }
4739
4740
4741 void
4742 RoamMenuWindow::manage()
4743 {
4744     Dimension win_x, win_y, win_wid, win_ht, win_bwid;
4745
4746     MainWindow::manage();
4747     XmUpdateDisplay(this->baseWidget());
4748     // Obtain the current dimensions of the RMW
4749
4750     XtVaGetValues(_w,
4751                   XmNx, &win_x,
4752                   XmNy, &win_y,
4753                   XmNwidth, &win_wid,
4754                   XmNheight, &win_ht,
4755                   XmNborderWidth, &win_bwid,
4756                   NULL);
4757
4758     _x = win_x;
4759     _y = win_y;
4760     _width = win_wid;
4761     _height = win_ht;
4762     _border_width = win_bwid;
4763
4764 }
4765
4766 void
4767 RoamMenuWindow::expunge(void)
4768 {
4769     DtMailEnv error;
4770     error.clear();
4771     
4772     // First order of business - busy out active windows
4773     //
4774     theRoamApp.busyAllWindows(
4775         GETMSG(DT_catd, 3, 32, "Destroying deleted messages..."));
4776
4777     // Before changing the state of any deleted/undeleted lists,
4778     // perform the destroy deleted operation and make sure that
4779     // it was successful - if there was an error, notify the user
4780     // and discontinue processing
4781     //
4782     _mailbox->expunge(error);
4783     if((DTMailError_t) error == DTME_OutOfSpace )
4784     {
4785        stopAutoSave();
4786        ShowErrMsg((char *)error.getClient(),FALSE,(void *)this );
4787        error.setClient(NULL);
4788        startAutoSave();
4789        theRoamApp.unbusyAllWindows();
4790        return;
4791     }
4792
4793     if (error.isSet()) {
4794         // An error happened - must inform the user
4795         //
4796         postErrorDialog(error);
4797         error.clear();
4798     }
4799     else {
4800         if (_msg_undelete_from_list->dialog())
4801           _msg_undelete_from_list->dialog()->expunge();
4802         
4803         _list->expunge();
4804     }
4805
4806     // Last order of business - unbusy out active windows
4807     //
4808     theRoamApp.unbusyAllWindows();
4809 }
4810
4811 void
4812 RoamMenuWindow::attachment_selected()
4813 {
4814     _att_save->activate();
4815 }
4816
4817
4818 void
4819 RoamMenuWindow::all_attachments_selected()
4820 {
4821     _att_save->deactivate();
4822
4823     if (_attActions_cmdlist != NULL) {
4824         _menuBar->removeCommands(_attachmentMenu, _attActions_cmdlist);
4825         _menuPopupAtt->removeCommands(_attachmentPopupMenu, 
4826                         _attActions_cmdlist);
4827         delete _attActions_cmdlist;
4828         _attActions_cmdlist = NULL;
4829     }
4830 }
4831
4832 void
4833 RoamMenuWindow::all_attachments_deselected()
4834 {
4835     _att_save->deactivate();
4836
4837     if (_attActions_cmdlist != NULL) {
4838         _menuBar->removeCommands(_attachmentMenu, _attActions_cmdlist);
4839         _menuPopupAtt->removeCommands(_attachmentPopupMenu, 
4840                                 _attActions_cmdlist);
4841         delete _attActions_cmdlist;
4842         _attActions_cmdlist = NULL;
4843     }
4844 }
4845
4846 void
4847 RoamMenuWindow::activate_default_message_menu()
4848 {
4849     
4850     _msg_open->activate();
4851
4852     _msg_save_as->activate();
4853
4854     XtSetSensitive(_copyto_cmdlist->getPaneWidget(), TRUE);
4855
4856     _msg_print->activate();
4857
4858     _msg_delete->activate();
4859
4860 }
4861
4862 void
4863 RoamMenuWindow::deactivate_default_message_menu()
4864 {
4865     
4866     _msg_open->deactivate();
4867
4868     _msg_save_as->deactivate();
4869
4870     XtSetSensitive(_copyto_cmdlist->getPaneWidget(), FALSE);
4871
4872     _msg_print->deactivate();
4873
4874     _msg_delete->deactivate();
4875
4876 }  
4877
4878 void
4879 RoamMenuWindow::activate_default_attach_menu()
4880 {
4881     _att_select_all->activate();
4882 }
4883
4884 void
4885 RoamMenuWindow::deactivate_default_attach_menu()
4886 {
4887     _att_select_all->deactivate();
4888 }
4889
4890 void
4891 RoamMenuWindow::newMailIndicators(void)
4892 {
4893     // Set to new mail icon only if the window is iconified
4894     if (this->isIconified()) {
4895         setIconName(NewMailIcon);
4896     }
4897
4898     if ((_we_called_newmail == FALSE) || (this->isIconified())){
4899
4900         // See if we are supposed to ring the bell.
4901         //
4902         DtMailEnv error;
4903         const char * val = NULL;
4904         DtMail::Session * m_session = theRoamApp.session()->session(); 
4905         m_session->mailRc(error)->getValue(error, "flash", &val);
4906         if (error.isNotSet()) {
4907             int flashes = (int) strtol(val, NULL, 10);
4908             flash(flashes);
4909         }
4910         if (NULL != val)
4911           free((void*) val);
4912
4913         val = NULL;
4914         m_session->mailRc(error)->getValue(error, "bell", &val);
4915         if (error.isNotSet()) {
4916             int beeps = (int) strtol(val, NULL, 10);
4917             while(beeps > 0) {
4918                 XBell(XtDisplay(baseWidget()), 0);
4919                 beeps -= 1;
4920             }
4921         }
4922         else // Default to 1 beep
4923             XBell(XtDisplay(baseWidget()), 0);
4924
4925         if (NULL != val)
4926           free((void*) val);
4927
4928         val = NULL;
4929         m_session->mailRc(error)->getValue(error, "realsound", &val);
4930         if (error.isNotSet()) {
4931             struct stat stat;
4932             if (SafeStat("/usr/bin/audioplay", &stat) == 0) {
4933                 char *play_str = new char[1500];
4934                 sprintf(play_str, "/usr/bin/audioplay %s", val);
4935                 system(play_str);
4936                 delete [] play_str;
4937             }
4938         }
4939
4940         if (NULL != val)
4941           free((void*) val);
4942     }
4943
4944     _we_called_newmail = FALSE;
4945 }
4946
4947 void
4948 RoamMenuWindow::save_attachment_callback(
4949     void *client_data,
4950     char *selection
4951 )
4952 {
4953
4954     RoamMenuWindow *obj = (RoamMenuWindow *) client_data;
4955     obj->save_selected_attachment(selection);
4956 }
4957
4958 void
4959 RoamMenuWindow::save_selected_attachment(
4960     char *selection
4961 )
4962 {
4963     DtMailEnv mail_error;
4964
4965     // Initialize the mail_error.
4966     mail_error.clear();
4967
4968     DtMailEditor *editor = this->get_editor();
4969     AttachArea *attacharea = editor->attachArea();
4970     Attachment *attachment = attacharea->getSelectedAttachment();
4971
4972    // Get selected attachment, if none selected, then return.
4973    if ( attachment == NULL ) {
4974           // Let User know that no attachment has been selected???
4975           int answer = 0;
4976           char *helpId = NULL;
4977
4978
4979           _genDialog->setToErrorDialog(
4980                     GETMSG(DT_catd, 1, 80, "Mailer"),             
4981                     GETMSG(DT_catd, 2, 14, "An attachment needs to be selected before issuing the\n\"Save As\" command to save to a file.") );
4982           helpId = DTMAILHELPSELECTATTACH;
4983           answer = _genDialog->post_and_return(
4984                         GETMSG(DT_catd, 3, 33, "OK"), helpId );
4985           return;
4986       }
4987
4988
4989     attachment->saveToFile(mail_error, selection);
4990
4991     if (mail_error.isSet()) {
4992         // do something
4993     }
4994
4995 }
4996
4997 void
4998 RoamMenuWindow::addAttachmentActions(
4999     char **actions,
5000     int indx
5001 )
5002 {
5003     int i;
5004     char *anAction;
5005     AttachmentActionCmd *attachActionCmd;
5006     
5007     if (_attActions_cmdlist == NULL) { 
5008         _attActions_cmdlist = new CmdList("AttachmentActions", "AttachmentActions");
5009     }
5010     else {
5011         _menuBar->removeCommands(_attachmentMenu, _attActions_cmdlist);
5012         _menuPopupAtt->removeCommands(_attachmentPopupMenu, 
5013                                 _attActions_cmdlist);
5014         delete _attActions_cmdlist;
5015         _attActions_cmdlist = new CmdList("AttachmentActions", "AttachmentActions");
5016     }
5017
5018     char *actionLabel;
5019     for (i = 0; i < indx; i++) {
5020         anAction = actions[i];
5021
5022         // Retrieve the localized action label
5023         actionLabel = DtActionLabel(anAction);
5024         attachActionCmd = new AttachmentActionCmd(
5025                                         anAction, 
5026                                         actionLabel,
5027                                         this,
5028                                         i);
5029         _attActions_cmdlist->add(attachActionCmd);
5030         
5031     }
5032     _attachmentMenu = _menuBar->addCommands(
5033                                 _attachmentMenu, 
5034                                 _attActions_cmdlist
5035                         );
5036     _attachmentPopupMenu = _menuPopupAtt->addCommands(
5037                                 _attachmentPopupMenu, 
5038                                 _attActions_cmdlist
5039                         );
5040 }
5041
5042 void
5043 RoamMenuWindow::removeAttachmentActions()
5044 {
5045
5046     // Stubbed out for now
5047 }
5048
5049 void
5050 RoamMenuWindow::invokeAttachmentAction(
5051     int index
5052 )
5053 {
5054
5055     DtMailEditor *editor = this->get_editor();
5056     AttachArea *attacharea = editor->attachArea();
5057     Attachment *attachment = attacharea->getSelectedAttachment();
5058
5059     attachment->invokeAction(index);
5060
5061 }
5062
5063 void
5064 RoamMenuWindow::selectAllAttachments()
5065 {
5066     
5067     DtMailEditor *editor = this->get_editor();
5068     AttachArea *attachArea = editor->attachArea();
5069     
5070     attachArea->selectAllAttachments();
5071
5072 }
5073
5074 // Returns the index of the match, -1 if there is no match.
5075 int
5076 RoamMenuWindow::inList(char *filename, DtVirtArray<ContainerMenuCmd *> *list)
5077 {
5078     ContainerMenuCmd *cmd;
5079
5080     if (list == NULL) return(-1);
5081
5082     if (filename &&
5083         *filename != '/' &&
5084         *filename != '.' && 
5085         *filename != '$' &&
5086         *filename != '~')
5087     { // relative path
5088         
5089         DtMail::Session * d_session = theRoamApp.session()->session();
5090         DtMailEnv error;
5091         DtMail::MailRc * mailrc = d_session->mailRc(error);
5092         const char *value = NULL;
5093         char *newname;
5094
5095         mailrc->getValue(error, "folder", &value);
5096         if (error.isNotSet())
5097         {
5098             newname = (char*)malloc(strlen(filename) + strlen(value) + 2);
5099             sprintf(newname, "%s/%s", value, filename);
5100             for (int i=0; i < list->length(); i++)
5101             {
5102                 cmd = (*list)[i];
5103                 if (strcmp(newname, cmd->containerName()) == 0) {
5104                     free(newname);
5105                     return(i);
5106                 }
5107             }
5108             free((void*) newname);
5109         }
5110
5111         if (NULL != value)
5112           free((void*) value);
5113     }
5114
5115     for (int i=0; i < list->length(); i++)
5116     {
5117         cmd = (*list)[i];
5118         if (strcmp(filename, cmd->containerName()) == 0)
5119           return(i);
5120     }
5121     return(-1);
5122 }
5123
5124
5125 void
5126 RoamMenuWindow::addToCachedContainerList(char *filename)
5127 {
5128     int                 i, index;
5129     ContainerMenuCmd    *null_container, *open_container;
5130     ContainerMenuCmd    *move_container, *copy_container;
5131     char                *name;
5132
5133     if (filename != NULL &&
5134         *filename != '\0' &&
5135         (_max_cached_list_size > 0))
5136     {
5137         DtMail::Session *d_session = theRoamApp.session()->session();
5138         DtMailObjectSpace space;
5139         DtMailEnv       mail_error;
5140         int             is_inbox;
5141         char            *mail_file = NULL;
5142
5143         // Is the file in the user defined list?
5144         if ((index = inList(filename, _user_containerlist)) != -1)
5145           return;
5146
5147         d_session->queryImpl(
5148                         mail_error,
5149                         d_session->getDefaultImpl(mail_error),
5150                         DtMailCapabilityInboxName,
5151                         &space,
5152                         &mail_file);
5153
5154         is_inbox = (0 == strcmp(mail_file, filename));
5155         if (NULL != mail_file)
5156           free((void*) mail_file);
5157         if (is_inbox)
5158           return;
5159
5160         // Is the file in the recently used list?
5161         if ((index = inList(filename, _cached_containerlist)) != -1)
5162         {
5163             // Move filename to top of list and move everything else down.
5164             if (index == 0) return;
5165
5166             //
5167             // Change the filenames that each of the Cmds points to in both
5168             // the move and copy cached lists.
5169             //
5170             name = (*_cached_containerlist)[index]->containerName();
5171
5172             for (i = index; i > 0; i--) {
5173                 char    *s = (*_cached_containerlist)[i-1]->containerName();
5174
5175                 (*_cached_containerlist)[i]->changeContainer(s);
5176                 (*_open_container_containerlist_cached)[i]->changeContainer(s);
5177                 (*_copyto_containerlist_cached)[i]->changeContainer(s);
5178                 (*_move_containerlist_cached)[i]->changeContainer(s);
5179             }
5180
5181             (*_cached_containerlist)[0]->changeContainer(name);
5182             (*_open_container_containerlist_cached)[0]->changeContainer(name);
5183             (*_copyto_containerlist_cached)[0]->changeContainer(name);
5184             (*_move_containerlist_cached)[0]->changeContainer(name);
5185
5186             //
5187             // Rename the labels in the menu.
5188             //
5189             if (_first_cached_item != _first_cached_item + index)
5190             {
5191                 _menuBar->rotateLabels(
5192                                 _opencontainerMenu,
5193                                 _first_cached_item,
5194                                 _first_cached_item + index);
5195                 _menuBar->rotateLabels(
5196                                 _copytoMenu,
5197                                 _first_cached_item,
5198                                 _first_cached_item + index);
5199                 _menuBar->rotateLabels(
5200                                 _moveMenu,
5201                                 _first_cached_item,
5202                                 _first_cached_item + index);
5203                 _menuBar->rotateLabels(
5204                                 _msgsPopupMoveMenu,
5205                                 _first_cached_item,
5206                                 _first_cached_item + index);
5207             }
5208          }
5209          else
5210          {
5211             // Add filename to Recently Used List.
5212             int cached_list_size = _cached_containerlist->length();
5213
5214             // Is there room for the menu to grow?
5215             if (cached_list_size < _max_cached_list_size)
5216             {
5217                 // Create the new command.
5218                 null_container = new ContainerMenuCmd(strdup(filename),
5219                                                         filename,
5220                                                         TRUE,
5221                                                         this,
5222                                                         DTM_NONE);
5223                 open_container = new ContainerMenuCmd(strdup(filename),
5224                                                         filename,
5225                                                         TRUE,
5226                                                         this,
5227                                                         DTM_OPEN);
5228                 copy_container = new ContainerMenuCmd(strdup(filename),
5229                                                         filename,
5230                                                         TRUE,
5231                                                         this,
5232                                                         DTM_COPY);
5233                 move_container = new ContainerMenuCmd(strdup(filename),
5234                                                         filename,
5235                                                         TRUE,
5236                                                         this,
5237                                                         DTM_MOVE);
5238
5239                 // Add it to the end of the arrays.
5240                 _cached_containerlist->append(null_container);
5241                 _open_container_containerlist_cached->append(open_container);
5242                 _copyto_containerlist_cached->append(copy_container);
5243                 _move_containerlist_cached->append(move_container);
5244
5245                 // Add it to the end of the menus.
5246                 _menuBar->addCommand(_opencontainerMenu, open_container);
5247                 _menuBar->addCommand(_copytoMenu, copy_container);
5248                 _menuBar->addCommand(_moveMenu, move_container);
5249                 _menuBar->addCommand(_msgsPopupMoveMenu, move_container);
5250
5251                 // Recursively call addToCachedContainerList to rotate to top.
5252                 cached_list_size = _cached_containerlist->length();
5253                 if (cached_list_size > 1)
5254                   addToCachedContainerList(filename);
5255             }
5256             else
5257             {
5258                 // Add new entry to the bottom of the cache.
5259                 int     i = cached_list_size-1;
5260                 char    *s = filename;
5261                 
5262                 // Replace the end of the arrays.
5263                 (*_cached_containerlist)[i]->changeContainer(strdup(s));
5264                 (*_open_container_containerlist_cached)[i]->changeContainer(
5265                                                                 strdup(s));
5266                 (*_copyto_containerlist_cached)[i]->changeContainer(strdup(s));
5267                 (*_move_containerlist_cached)[i]->changeContainer(strdup(s));
5268
5269                 // Replace the end of the menus.
5270                 i += _first_cached_item;
5271                 _menuBar->changeLabel(_opencontainerMenu, i, s);
5272                 _menuBar->changeLabel(_copytoMenu, i, s);
5273                 _menuBar->changeLabel(_moveMenu, i, s);
5274                 _menuBar->changeLabel(_msgsPopupMoveMenu, i, s);
5275
5276                 // Recursively call addToCachedContainerList to rotate to top.
5277                 if (_first_cached_item != i)
5278                   addToCachedContainerList(filename);
5279             }
5280         }
5281     }
5282 }
5283
5284 void
5285 RoamMenuWindow::showAttachArea()
5286 {
5287     DtMailEditor *editor = this->get_editor();
5288     editor->showAttachArea();
5289 }
5290
5291 void
5292 RoamMenuWindow::hideAttachArea()
5293 {
5294     DtMailEditor *editor = this->get_editor();
5295     editor->hideAttachArea();
5296 }
5297
5298 void
5299 RoamMenuWindow::fullHeader(
5300     Boolean state
5301 )
5302 {
5303     DtMailMessageHandle msgHandle;
5304     DtMailEnv mail_error;
5305
5306     // Initialize the mail_error.
5307     mail_error.clear();
5308
5309     _full_header_resource = state;
5310     
5311     msgHandle = this->list()->current_msg_handle();
5312     if (msgHandle) {
5313         this->list()->display_message(mail_error, msgHandle);
5314     }
5315
5316 }
5317
5318 void 
5319 RoamMenuWindow::postMsgsPopup(XEvent *event)
5320 {
5321         XmMenuPosition(_msgsPopupMenu, (XButtonEvent *)event);
5322         XtManageChild(_msgsPopupMenu);
5323 }
5324
5325 void
5326 RoamMenuWindow::MenuButtonHandler(
5327     Widget ,
5328     XtPointer cd,
5329     XEvent *event,
5330     Boolean *)
5331 {
5332         RoamMenuWindow *obj = (RoamMenuWindow *)cd;
5333
5334         if(event->xany.type != ButtonPress)
5335                 return;
5336
5337         XButtonEvent *be = (XButtonEvent *)event;
5338
5339         if(be->button == theApplication->bMenuButton())
5340                 obj->postMsgsPopup(event);
5341 }
5342
5343 void
5344 RoamMenuWindow::attachmentFeedback(
5345     Boolean bval
5346 )
5347 {
5348     if (bval) {
5349         this->busyCursor();
5350     }
5351     else {
5352         this->normalCursor();
5353     }
5354 }
5355
5356 // map_menu is used to figure out how many columns to split the menu
5357 // into.  It is a callback that is called when the menu is mapped.
5358 // If the menu is over half the height of the screen, it figures out
5359 // how many columns to make the menu, and sets its XmNnumColumns
5360 // attribute to that value.  It calculates the maximum number of columns
5361 // that would fit and never goes beyond that number.
5362
5363 void
5364 RoamMenuWindow::map_menu(
5365                     Widget menu, 
5366                     XtPointer,
5367                     XtPointer)
5368 {
5369         Position y;
5370         Dimension h, w;
5371         short   maxcols, newcols, columns;
5372         int     screenheight = HeightOfScreen(XtScreen(menu));
5373         int     fudgefact = 20; /* to allow for decorations on menu */
5374  
5375         XtVaGetValues(menu,
5376         XmNheight, &h,
5377         XmNwidth, &w,
5378         XmNy, &y,
5379         XmNnumColumns, &columns,
5380         NULL);
5381  
5382  
5383         if ((int) (h + fudgefact) > ((int) screenheight / 2)) {
5384  
5385         /* the menu is taller than half the screen.  We need to find out how
5386            many more columns to specify for the menu to make it fit. */
5387  
5388                 newcols = (columns * (int) ((int) (h + fudgefact)/(int) (screenheight/2))) + 1;
5389                 maxcols = WidthOfScreen(XtScreen(menu))/(int) ((int)w/(int)columns);
5390  
5391                 if (newcols > maxcols)
5392                         newcols = maxcols;
5393  
5394                 XtVaSetValues(menu, XmNnumColumns, newcols, NULL);
5395
5396         }
5397  
5398
5399 }
5400
5401
5402 void
5403 RoamMenuWindow::setTitle(char *suffix)
5404 {
5405     DtMailEnv           mail_error;
5406     MailSession         *ses = theRoamApp.session();
5407     DtMail::Session     *d_session = ses->session();
5408     char *prefix = GETMSG(DT_catd, 1, 6, "Mailer");
5409     char *path = NULL;
5410     char *new_title;
5411     char *format;
5412     int   len;
5413
5414     if (mailbox_fullpath())
5415       path = d_session->getRelativePath(mail_error, mailbox_fullpath());
5416     else if (mailboxName())
5417       path = d_session->getRelativePath(mail_error, mailboxName());
5418     else path = strdup("UNTITLED");
5419
5420     if (suffix)
5421     {
5422         format = "%s - %s [%s]";
5423         len = strlen(format) + strlen(prefix) + strlen(path) + strlen(suffix);
5424         new_title = new char[len];
5425         sprintf(new_title, format, prefix, path, suffix);
5426     }
5427     else
5428     {
5429         format = "%s - %s";
5430         len = strlen(format) + strlen(prefix) + strlen(path);
5431         new_title = new char[len];
5432         sprintf(new_title, format, prefix, path);
5433     }
5434
5435     title(new_title);
5436     delete [] new_title; 
5437     free(path);
5438 }
5439
5440 void
5441 RoamMenuWindow::setVacationTitle()
5442 {
5443     // Add "[Vacation]" to the title of the roam menu window 
5444     char *vacation = GETMSG(DT_catd, 1, 3, "Vacation");
5445     setTitle(vacation);
5446 }
5447
5448 void
5449 RoamMenuWindow::removeVacationTitle()
5450 {
5451     // Reset the title on the roam menu window; take out "[Vacation]"
5452     setTitle(NULL);
5453 }
5454
5455 void
5456 RoamMenuWindow::ShowErrMsg(char * fsname,Boolean compose,void *client_data)
5457 {
5458 Widget parent=NULL;
5459   assert((NULL != fsname));
5460   if(!compose)
5461   {
5462     RoamMenuWindow * self = (RoamMenuWindow *)client_data;
5463     parent = self->GetMainWin();
5464   }
5465   else
5466   {
5467     SendMsgDialog * self = (SendMsgDialog *)client_data;
5468     parent = self->GetMainWin();
5469   }
5470     if(!parent)
5471             parent = theApplication->baseWidget();
5472             DtMailGenDialog *genDialog = new DtMailGenDialog("Dialog",parent,XmDIALOG_FULL_APPLICATION_MODAL);
5473
5474             char *errMsg = (char *) XtCalloc(1,10240+strlen(fsname));
5475
5476
5477                 // Serious error here -- No Space on Filesystem --
5478                 sprintf(errMsg,"Insufficient space on %s filesystem. Dtmail unable to show any new \n messages, delete messages, or save further changes to the open \n mailbox. Please contact your System Administrator to correct the \n filesystem space problem.",fsname);
5479             free(fsname);
5480             genDialog->setToErrorDialog(
5481                                 GETMSG(DT_catd, 1, 6, "Mailer"),
5482                                 errMsg);
5483             XtFree(errMsg);
5484
5485             genDialog->post_and_return(
5486                                 GETMSG(DT_catd, 3, 9, "OK"),
5487                                 NULL);
5488             delete genDialog;
5489 }
5490 void
5491 RoamMenuWindow::stopAutoSave(void)
5492 {
5493     DtMailEnv error;
5494     _mailbox->startAutoSave(error,DTM_FALSE);
5495 }
5496 void
5497 RoamMenuWindow::startAutoSave(void)
5498 {
5499     DtMailEnv error;
5500     _mailbox->startAutoSave(error,DTM_TRUE);
5501 }
5502
5503 void
5504 RoamMenuWindow::sync_work_area_size(void)
5505 {
5506     Dimension width, height;
5507
5508     XtVaGetValues(_workArea, XmNwidth, &width, XmNheight, &height, NULL);
5509
5510     if (_workarea_width && _workarea_height &&
5511         (_workarea_width!=width || _workarea_height!=height))
5512     {
5513         enableWorkAreaResize();
5514         XtVaSetValues(_workArea, XmNwidth, width, XmNheight, height, NULL);
5515         disableWorkAreaResize();
5516     }
5517     _workarea_width = width;
5518     _workarea_height = height;
5519 }