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