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