dtmail: resolve coverity warnings related to uninitialised members in C++ classes
[oweals/cde.git] / cde / programs / dtmail / dtmail / AttachArea.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *+SNOTICE
25  *
26  *      $TOG: AttachArea.C /main/18 1999/03/25 14:16:24 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 Sun Microsystems, Inc.  All rights reserved.
39  *
40  *+ENOTICE
41  */
42
43 #ifndef I_HAVE_NO_IDENT
44 #endif
45
46 #include <EUSCompat.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <sys/stat.h>
50 #if defined(USL) || defined(__uxp__)
51 #define S_ISSOCK(mode) ((mode & S_IFMT) == S_IFSOCK)
52 #endif
53 #include <stdio.h>
54 #include <Dt/Editor.h>
55 #include <Xm/ColorObjP.h>
56
57 #include "EUSDebug.hh"
58
59 #if defined(NEED_MMAP_WRAPPER)
60 extern "C" {
61 #endif
62
63 #include <sys/mman.h>
64
65 #if defined(NEED_MMAP_WRAPPER)
66 }
67 #endif
68
69
70 extern "C" {
71 extern XtPointer _XmStringUngenerate (
72                                 XmString string,
73                                 XmStringTag tag,
74                                 XmTextType tag_type,
75                                 XmTextType output_type);
76 }
77
78
79 #include <stdio.h>
80 #include <ctype.h>
81 #include <sys/stat.h>
82 #include <sys/types.h>
83
84
85 #include <Xm/BulletinB.h>
86 #include <Xm/Form.h>
87 #include <Xm/RowColumn.h>
88 #include <Xm/ScrolledW.h>
89 #include <Xm/DrawingA.h>
90 #include <Xm/ScrollBar.h>
91 #include <Xm/PushBG.h>
92 #include <Xm/FileSB.h>
93 #include <Xm/SelectioB.h>
94 #include <Xm/Label.h>
95 #include <Xm/LabelG.h>
96 #include <Xm/AtomMgr.h>
97 #include <Xm/Xm.h>
98 #include <Xm/Screen.h>
99 #include <Xm/ToggleB.h>
100 #include <X11/IntrinsicP.h>
101 #include <X11/Xatom.h>
102
103 #include "Attachment.h"
104 #include "AttachArea.h"
105 #include "Icon.h"
106 #include "MenuBar.h"
107 #include "RoamApp.h"
108 #include "RoamMenuWindow.h"
109
110 #include "MsgScrollingList.hh"
111 #include "ViewMsgDialog.h"
112 #include "SendMsgDialog.h"
113 #include "MailMsg.h"            // DT_catd defined here
114 #include <DtMail/DtMail.hh>    // time_t defined here
115 #include <DtMail/IO.hh>                    // SafeAccess...
116
117 #include "Help.hh"
118 #include "DtMailHelp.hh"
119
120 extern nl_catd  DtMailMsgCat;
121
122 #define equal(a, b) (!strcmp(a,b))
123 #define HSPACE 10
124 #define VSPACE 10
125 #define MAXATOM 2048    // ?????
126
127 // This is the new one
128 AttachArea::AttachArea ( 
129         Widget parent, 
130         DtMailEditor *owner,
131         char *name
132 ) : UIComponent (name)
133 {
134     // Unique stuff
135
136     _myOwner = owner;
137     _parent  = parent;
138
139     _attachmentList=NULL;
140
141     _w = NULL;
142     _iconCount = 0;
143     _iconSelectedCount = 0;
144     _deleteCount = 0;
145
146     _fsDialog = NULL;
147     _fsState = NOTSET;
148     _lastRow = 0;
149     _currentRow = 0;
150     _attachmentsSize = 0;
151     _selectedAttachmentsSize = 0;
152     _clientData = NULL;
153     _renameDialog = NULL;
154
155     _myRMW = NULL;
156     _myVMD = NULL;
157     _mySMD = NULL;
158     
159     _pendingAction = FALSE;
160     _numPendingActions = 0;
161
162     _attach_area_selection_state = AA_SEL_NONE;
163     _cache_single_attachment = NULL;
164
165     _no_selected_label = NULL;
166     _selected_label = NULL;
167     rowOfAttachmentsStatus = NULL;
168     _attachments_status = NULL;
169     _attachments_summary = NULL;
170     _mailbox = NULL;
171     _attachAreaWidth = 0;
172     _attachAreaHeight = 0;
173     _rc = NULL;
174     _sw = NULL;
175     _vsb = NULL;
176     _message = NULL;
177     _clipWindow = NULL;
178     _open = NULL;
179     _saveas = NULL;
180     _selectall = NULL;
181     _unselectall = NULL;
182     _menuBar = NULL;
183     _background = 0;
184     _foreground = 0;
185     _appBackground = 0;
186     _appForeground = 0;
187     _fileCmdList = NULL;
188     _editCmdList = NULL;
189     _size_selected_label = NULL;
190     _format_button = NULL;
191     
192     
193 }
194
195 void
196 AttachArea::initialize()
197 {
198
199     // We're making the assumption here that this widget's parent`
200     // is also a form
201
202     XtWidgetGeometry size;
203     Dimension parWid, parHeight;
204     Dimension txt_w, txt_h;
205     XmFontList fl;
206     XmString xms;
207
208     int         colorUse;
209     short       act, inact, prim, second, text;
210     XmPixelSet  pixels[XmCO_NUM_COLORS];
211
212
213     _w = XtVaCreateManagedWidget (
214                         "AttachPane",
215                         xmFormWidgetClass, _parent, 
216                         NULL);
217
218     // Get pixel data.
219     XmeGetColorObjData(XtScreen(_parent), &colorUse, pixels, XmCO_NUM_COLORS,
220                        &act, &inact, &prim, &second, &text);
221     _foreground = pixels[text].fg;
222     _background = pixels[text].sc;
223
224     parWid = _myOwner->textEditor()->get_text_width();
225
226     fl = _myOwner->textEditor()->get_text_fontList();
227     xms = XmStringCreateLocalized("Xyb");
228     XmStringExtent(fl, xms, &txt_w, &txt_h);
229     parHeight = txt_h + Icon::maxIconHeight() + (2*VSPACE);
230
231     _appBackground = _background;
232     _appForeground = _foreground;
233
234     _sw = XtVaCreateManagedWidget ( 
235                                     "AttachPane_ScrolledWindow", 
236                                     xmScrolledWindowWidgetClass, _w, 
237                                     XmNscrollingPolicy,  XmAPPLICATION_DEFINED,
238                                     XmNrightAttachment,  XmATTACH_FORM,
239                                     XmNleftAttachment,   XmATTACH_FORM,
240                                     XmNtopAttachment,    XmATTACH_FORM,
241                                     XmNshadowThickness, (Dimension)1,
242                                     XmNspacing, 2,
243                                     XmNwidth,        parWid,
244                                     XmNheight,       parHeight,
245                                     NULL);
246
247     rowOfAttachmentsStatus = XtCreateManagedWidget("Attachments_Status",
248                                 xmFormWidgetClass,
249                                 _w, NULL, 0);
250
251      XtVaSetValues(rowOfAttachmentsStatus,
252         XmNrightAttachment,     XmATTACH_FORM, 
253         XmNleftAttachment,      XmATTACH_FORM, 
254         XmNtopAttachment,       XmATTACH_WIDGET,
255         XmNtopWidget,           _sw,
256         XmNtopOffset,           5,
257         XmNbottomOffset,        5,
258         NULL );
259
260     this->addToRowOfAttachmentsStatus();
261
262     size.request_mode = CWHeight;
263     XtQueryGeometry(rowOfAttachmentsStatus, NULL, &size);
264
265     XtVaSetValues(
266         rowOfAttachmentsStatus,
267         XmNpaneMaximum, size.height,
268         XmNpaneMinimum, size.height,
269         NULL
270     );
271
272     _vsb = XtVaCreateManagedWidget("vsb", xmScrollBarWidgetClass, _sw,
273                     XmNorientation, XmVERTICAL,
274                     XmNsliderSize, 1,
275                     XmNmaximum, 1,
276                     XmNpageIncrement, 1,
277                     NULL);
278
279     XtAddCallback(
280         _vsb, 
281         XmNvalueChangedCallback,&AttachArea::valueChangedCallback,
282         (XtPointer) this 
283     );
284
285     XtAddCallback(
286         _vsb, 
287         XmNdragCallback, &AttachArea::dragCallback,
288         (XtPointer) this 
289     );
290
291     _clipWindow = XtVaCreateManagedWidget("AttachArea_clipWindow", 
292                     xmDrawingAreaWidgetClass, _sw,
293                     XmNresizePolicy, XmRESIZE_NONE,
294                     XmNbackground, _background,
295                     XmNwidth,        parWid,
296                     XmNheight,       parHeight,
297                     NULL);
298     XmScrolledWindowSetAreas(_sw, NULL, _vsb, _clipWindow);
299
300     XtManageChild(_clipWindow);
301     XtManageChild(_vsb);
302     XtManageChild(_sw);
303
304     
305     // Set RowCol to NULL here.
306     // It gets set in the expose_all_attachments.
307
308     _rc = NULL;
309
310     CalcSizeOfAttachPane();
311
312     installDestroyHandler();
313 }
314
315 AttachArea::~AttachArea()
316 {
317 }
318
319 void AttachArea::addToList( Attachment *attachment )
320 {
321     Attachment **newList;
322     int i;
323
324     newList = new Attachment*[ _iconCount + 1 ];
325     for(i=0; i < _iconCount; i++)
326         newList[i] = _attachmentList[i];
327  
328     if (_attachmentList)
329         delete []_attachmentList;
330
331     _attachmentList = newList;
332
333     _attachmentList[ _iconCount ] = attachment;
334
335     _iconCount++;
336     
337 //    setAttachmentsLabel();
338 }
339
340 #ifdef DEAD_WOOD
341 void AttachArea::setAttachmentsLabel( )
342 {
343     char *c = new char[256];
344     XmString xmstr;
345     String str;
346     unsigned int last_displayCount, last_selectedCount;
347     unsigned int displayCount = _iconCount - _deleteCount;
348     unsigned int attachmentsSize;
349
350     if((displayCount) == 0) {
351         XtUnmanageChild(_no_attachments_label);
352         XtUnmanageChild(_attachments_label);
353         XtUnmanageChild(_size_attachments_label);
354         XtUnmanageChild(_no_selected_label);
355         XtUnmanageChild(_selected_label);
356         XtUnmanageChild(_size_selected_label);
357     } else {
358         CalcAttachmentsSize();
359         attachmentsSize = getAttachmentsSize();
360
361         // Number of Attachments
362         XtVaGetValues(_no_attachments_label,
363                 XmNlabelString, &xmstr,
364                 NULL);
365         str = NULL;
366         str = (char *) _XmStringUngenerate(
367                                         xmstr, NULL,
368                                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
369         if (NULL == str) return; // internal error
370         last_displayCount = (unsigned int)strtol(str, NULL, 10);
371         XtFree(str);
372
373         // Number of Attachments Selected
374         XtVaGetValues(_no_selected_label,
375                 XmNlabelString, &xmstr,
376                 NULL);
377         str = NULL;
378         str = (char *) _XmStringUngenerate(
379                                         xmstr, NULL,
380                                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
381         if (NULL == str) return; // internal error
382         last_selectedCount = (unsigned int)strtol(str, NULL, 10);
383         XtFree(str);
384
385         if((last_displayCount == 0 && displayCount == 1) ||
386            (last_displayCount == 2 && displayCount == 1)) {
387             sprintf(c, GETMSG(DT_catd, 12, 1, "Attachment"));
388             XtVaSetValues(_attachments_label,
389                 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
390                 NULL);
391         } else if(last_displayCount == 1 && displayCount == 2) {
392             sprintf(c, GETMSG(DT_catd, 12, 2, "Attachments"));
393             XtVaSetValues(_attachments_label,
394                 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
395                 NULL);
396         }
397         if(last_displayCount != displayCount) {
398             sprintf(c, GETMSG(DT_catd, 12, 3, "displayCount"));
399             XtVaSetValues(_no_attachments_label,
400                 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
401                 NULL);
402         }
403         sprintf(c, "(%s),", calcKbytes(attachmentsSize));
404         XtVaSetValues(_size_attachments_label,
405             XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
406             NULL);
407
408         if(last_selectedCount != _iconSelectedCount) {
409             sprintf(c, "%d", _iconSelectedCount); 
410             XtVaSetValues(_no_selected_label,
411                 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
412                 NULL);
413             sprintf(c, "(%s)", calcKbytes(getSelectedAttachmentsSize())); 
414             XtVaSetValues(_size_selected_label,
415                 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
416                 NULL);
417         }
418         if(!XtIsManaged(_no_attachments_label)) {
419             XtManageChild(_no_attachments_label);
420             XtManageChild(_attachments_label);
421             XtManageChild(_size_attachments_label);
422             XtManageChild(_no_selected_label);
423             XtManageChild(_selected_label);
424             XtManageChild(_size_selected_label);
425         }
426     }
427     delete [] c;
428 }
429 #endif /* DEAD_WOOD */
430
431 int AttachArea::getSelectedIconCount()
432 {
433     Attachment **list = getList();
434     int num_selected = 0;
435
436     for (int i = 0; i < getIconCount(); i++) {
437         if (!list[i]->isDeleted() && list[i]->isSelected())
438             num_selected++;
439     }
440     return (num_selected);
441 }
442
443 #ifdef DEAD_WOOD
444 void AttachArea::CalcAttachmentsSize( )
445 {
446      Attachment **list = getList();
447      unsigned int total = 0;
448      int i;
449
450      int num_icons = getIconCount();
451
452  
453      for(i=0;i<num_icons;i++)
454         if(!list[i]->isDeleted())
455             total += (unsigned int)list[i]->getContentsSize();
456      
457      setAttachmentsSize(total);
458 }
459 #endif /* DEAD_WOOD */
460
461 Attachment *
462 AttachArea::getSelectedAttachment()
463 {
464     return _cache_single_attachment;
465 }
466
467
468 void
469 AttachArea::MenuButtonHandler(
470     Widget ,
471     XtPointer cd,
472     XEvent *event,
473     Boolean *)
474 {
475         AttachArea *obj = (AttachArea *)cd;
476
477         if(event->xany.type != ButtonPress)
478                 return;
479
480         XButtonEvent *be = (XButtonEvent *)event;
481
482         if(be->button == theApplication->bMenuButton())
483                 obj->_myOwner->owner()->postAttachmentPopup(event);
484 }
485
486 void 
487 AttachArea::inputCallback(Widget, XtPointer client_data, XtPointer call_data)
488 {
489     AttachArea *obj = (AttachArea *) client_data;
490     XmDrawingAreaCallbackStruct *cb = (XmDrawingAreaCallbackStruct *)call_data;
491
492     if(cb->reason != XmCR_INPUT         ||
493         cb->event->xany.type != ButtonPress)
494         return;
495
496     if(((XButtonEvent *)cb->event)->button == Button1)
497         obj->unselectOtherSelectedAttachments(NULL);
498 }
499
500 void AttachArea::resizeCallback ( 
501                                   Widget w, 
502                                   XtPointer clientData, 
503                                   XtPointer //callData
504                                   )
505 {
506     XtArgVal wid;
507
508     AttachArea *obj = (AttachArea *) clientData;
509     XtVaGetValues(
510         w,
511         XmNwidth, &wid,
512         NULL
513     );
514
515     obj->resize((Dimension)wid);
516 }
517
518 void AttachArea::resize(
519     Dimension wid
520 )
521 {
522     int i;
523     Attachment **list = getList();
524
525     _attachAreaWidth = wid;
526     XtVaSetValues(_clipWindow, XmNwidth, _attachAreaWidth, NULL);
527
528     for (i=0; i<getIconCount(); i++)
529       list[i]->unmanageIconWidget();
530
531     CalcAllAttachmentPositions();
532     CalcLastRow();
533     AdjustCurrentRow();
534     SetScrollBarSize(getLastRow()+1);
535     DisplayAttachmentsInRow(_currentRow);
536 }
537
538 void AttachArea::CalcSizeOfAttachPane( )
539 {
540     _attachAreaWidth = _myOwner->textEditor()->get_text_width();
541     XtVaSetValues(_clipWindow, XmNwidth, _attachAreaWidth, NULL);
542 }
543
544 void AttachArea::activateDeactivate()
545 {
546     //
547     // If exactly one icon is selected then activate the open command 
548     //
549
550     if(getIconSelectedCount() == 1) {
551         openCmd()->activate();
552     } else {
553         openCmd()->deactivate();
554     }
555
556     // If no icons are selected then deactivate the OK button on the FS Dialog
557
558     if(getIconSelectedCount() > 0) {
559         if(getFsDialog())
560             XtSetSensitive(
561                 XmSelectionBoxGetChild( 
562                     getFsDialog(), XmDIALOG_OK_BUTTON), TRUE
563                 );
564     } else {
565         if(getFsDialog())
566             XtSetSensitive(
567                 XmSelectionBoxGetChild( 
568                     getFsDialog(), XmDIALOG_OK_BUTTON
569                 ), 
570                 (getFsState() == SAVEAS) ? FALSE : TRUE
571             );
572     }
573 }
574
575 // Used by Compose window (SMD)
576 // Given a filename, add it to message and to attachArea.
577
578 Attachment*
579 AttachArea::addAttachment(
580                           DtMail::Message* msg,
581                           DtMail::BodyPart *lastAttBP,
582                           char *filename,
583                           char *name
584                           )
585 {
586     int fd;
587     struct stat s;
588     Boolean validtype = TRUE;
589     DtMail::BodyPart * bp = NULL;
590     DtMailEnv mail_error;
591     int answer;
592     char *helpId = NULL;
593
594     mail_error.clear();
595
596     char *errormsg = new char[512];
597     char *buf = new char[2048];
598     char *buffer = NULL, *lbl;
599     char *fname_start;
600
601     for (fname_start = filename + strlen(filename) - 1;
602          fname_start >= filename && *fname_start != '/'; fname_start--) {
603         continue;
604     }
605     if (*fname_start == '/') {
606         fname_start += 1;
607     }
608
609     bp = msg->newBodyPart(mail_error, lastAttBP);       
610
611     if (SafeAccess(filename, F_OK) != 0) {
612         sprintf(buf, GETMSG(DT_catd, 3, 34, "%s does not exist."),
613                 filename);
614         answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 81, "Mailer"), 
615                                          buf);
616         delete [] buf;
617         delete [] errormsg;
618         return(NULL);
619     }
620
621     SafeStat(filename, &s);
622
623     if(S_ISFIFO(s.st_mode)) {
624         sprintf(errormsg,
625                 GETMSG(DT_catd, 12, 4, "Cannot attach FIFO files: %s"), filename);
626         validtype = FALSE;
627     } else if(S_ISCHR(s.st_mode)) {
628         sprintf(
629             errormsg,
630             GETMSG(DT_catd, 12, 5, "Cannot attach character special files: %s"), filename
631         );
632         validtype = FALSE;
633     } else if(S_ISDIR(s.st_mode)) {
634         sprintf(
635             errormsg,
636             GETMSG(DT_catd, 12, 6, "Cannot attach directories: %s"), filename
637         );
638         validtype = FALSE;
639     } else if(S_ISBLK(s.st_mode)) {
640         sprintf(errormsg,
641                 GETMSG(DT_catd, 12, 7, "Cannot attach block special files: %s"), filename
642         );
643         validtype = FALSE;
644     } else if(S_ISSOCK(s.st_mode)) {
645         sprintf(errormsg,
646                 GETMSG(DT_catd, 12, 8, "Cannot attach socket files: %s"), filename
647         );
648         validtype = FALSE;
649     }
650     if(validtype == FALSE) {
651         answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 81, "Mailer"), 
652                                          errormsg,
653                                          NULL);
654         delete [] buf;
655         delete [] errormsg;
656         return(NULL);
657     }
658
659     fd = SafeOpen(filename, O_RDONLY);
660         
661     if (fd < 0) {
662         sprintf(buf, GETMSG(DT_catd, 3, 35, "Unable to open %s."), filename);
663         helpId = DTMAILHELPNOOPEN;
664         answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 82, "Mailer"), 
665                                          buf,
666                                          helpId);
667         delete [] buf;
668         delete [] errormsg;
669         return(NULL);
670     }
671
672     int page_size = (int)sysconf(_SC_PAGESIZE);
673     size_t map_size = (size_t) (s.st_size + 
674                                     (page_size - (s.st_size % page_size)));
675     char * map;
676
677 #if defined(__osf__)
678     // This version of mmap does NOT allow requested length to be
679     // greater than the file size ...  in contradiction to the
680     // documentation (don't round up).
681     map = (char *) mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
682 #else
683     map = (char *) mmap(0, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
684 #endif
685
686     if (map == (char *)-1) {
687         // We could not map it for some reason. Let's just read it into
688         // buffer and pass it to XmText.
689         //
690
691         buffer = new char[s.st_size + 1];
692
693         if (!buffer) {
694             sprintf(buf, "%s",
695                     GETMSG(DT_catd, 3, 36, "Unable to allocate memory."));
696             helpId = DTMAILHELPNOALLOCMEM;
697             answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 83, "Mailer"), 
698                                              buf,
699                                              helpId);
700             return(NULL);
701         }
702
703         if (read(fd, buffer, (unsigned int) s.st_size) < 0) {
704             SafeClose(fd);
705             return(NULL);
706         }
707         buffer[s.st_size] = 0;
708         bp->setContents(
709                 mail_error, buffer, s.st_size, NULL, fname_start, 0, NULL
710                 );
711     }
712     else {
713         // We now have a mapped file. XmText wants a zero terminated
714         // buffer. We get luck with mmap because unless the file is
715         // an even page size, we will have some zero fill bytes that
716         // are legal to access.
717         //
718         // Of course in the case of an even page size file we must
719         // copy the buffer, terminate it and then give it to XmText.
720         //
721         bp->setContents(
722             mail_error, map, s.st_size, NULL, fname_start, 0, NULL
723         );
724         munmap(map, map_size);
725     }
726     SafeClose(fd);
727
728
729     // _iconCount + 1 because iconCount starts at 0 and we want 
730     // attachmentCount to begin at 1.  attachmentCount is set to be
731     // in the widget's userData.  
732
733
734     if(name)
735         lbl = strdup(name);
736     else {
737         if(strchr(filename, '/') == NULL) // The name does not include a slash
738             lbl = strdup(filename);
739         else                       // The name does include a slash
740             lbl = strdup(strrchr(filename, '/')+1);
741     }    
742     Attachment *attachment = new Attachment(this, lbl, bp, _iconCount + 1);
743     attachment->setAttachArea(this);
744     attachment->initialize();
745     addToList( attachment );
746
747     // Update the display.  The Compose Window needs immediate update.
748
749     this->manageList();
750
751     delete [] buf;
752     delete [] errormsg;
753     return(attachment);
754 }
755
756 Attachment*
757 AttachArea::addAttachment(
758     DtMail::Message *msg,
759     DtMail::BodyPart *lastAttBP,
760     String name,
761     DtMailBuffer buf
762 )
763 {
764     DtMailEnv mail_error;
765     DtMail::BodyPart * bp = NULL;
766
767     if (!name)
768         name = "noname";
769
770     mail_error.clear();
771
772     bp = msg->newBodyPart(mail_error, lastAttBP);
773     bp->setContents(mail_error, buf.buffer, buf.size, NULL, name, 0, NULL);
774
775     Attachment *attachment = new Attachment(this,
776                                             name,
777                                             bp,
778                                             _iconCount + 1);
779     attachment->setAttachArea(this);
780     attachment->initialize();
781     addToList(attachment);
782
783     // Update the display.  The Compose Window needs immediate update.
784
785     this->manageList();
786
787     return(attachment);
788 }
789
790 Attachment* 
791 AttachArea::addAttachment( 
792     String name,
793     DtMail::BodyPart *body_part
794 )
795 {
796     // _iconCount + 1 because iconCount starts at 0 and we want 
797     //  attachmentCount to begin at 1.  attachmentCount is set to be
798     // in the widget's userData.  
799
800     Attachment *attachment = new Attachment(
801                                         this, 
802                                         name, 
803                                         body_part, 
804                                         _iconCount + 1
805                                 );
806     attachment->setAttachArea(this);
807     attachment->initialize();
808     addToList( attachment );
809
810     return(attachment);
811 }
812
813 #ifdef DEAD_WOOD
814 void
815 AttachArea::add_attachment(
816     Attachment *attachment
817 )
818 {
819     
820      attachment->setAttachArea(this);
821      attachment->initialize();
822      addToList( attachment );
823 }
824
825 //
826 // This function truly deletes all the attachments in the AttachArea
827 // The widgets are unmanaged and the attachment classes are deleted.
828 //
829
830 void AttachArea::deleteAttachments( )
831 {
832     int i;
833     WidgetList deleteList;
834     int count;
835
836     Attachment **list = getList();
837  
838      // First, unmanaged all the attachment at once so there is no
839      // flickering when we delete them
840
841      deleteList = (WidgetList)XtMalloc(sizeof(Widget) * getIconCount());
842
843      for(i=0;i<getIconCount();i++)
844         deleteList[i] = list[i]->baseWidget();
845      XtUnmanageChildren(deleteList, i);
846
847      delete deleteList;
848      XtFree((char *)deleteList);
849  
850     // Delete each attachment in the list
851     count = getIconCount();
852     for(i=count-1;i>=0;i--) {
853         delete list[i];
854         decIconCount();
855     }
856
857      _iconCount = 0;
858      _iconSelectedCount = 0;
859      _deleteCount = 0;
860      CalcLastRow();
861      AdjustCurrentRow();
862      SetScrollBarSize(getLastRow()+1);
863      activateDeactivate();
864      _attachmentList=NULL;
865      _attachmentsSize = 0;
866      _selectedAttachmentsSize = 0;
867 }
868 #endif /* DEAD_WOOD */
869
870 void AttachArea::manageList( )
871 {
872     int i;
873     Attachment **list = getList();
874
875     for (i=0; i<getIconCount(); i++)
876       list[i]->unmanageIconWidget();
877
878     CalcAllAttachmentPositions();
879     CalcLastRow();
880     AdjustCurrentRow();
881     SetScrollBarSize(getLastRow()+1);
882     DisplayAttachmentsInRow(_currentRow);
883 }
884
885 #ifdef DEAD_WOOD
886 //
887 // Find the x and y position for a newly created attachment
888 //
889
890 void AttachArea::CalcAttachmentPosition(Attachment *item)
891 {
892     int i, j;
893     Boolean found_managed = FALSE;
894
895      Attachment **list = getList();
896      for(i=0, j=0;i<getIconCount();i++)
897         if(!list[i]->isDeleted()) {
898             j = i;
899             found_managed = TRUE;
900         }
901     calculate_attachment_position(
902        found_managed ? list[j] : (Attachment *)NULL, item
903        );
904
905 }      
906 #endif /* DEAD_WOOD */
907
908 //
909 // Display the attachments in row X
910 //
911
912 void AttachArea::DisplayAttachmentsInRow(unsigned int X)
913 {
914     int i;
915     int managecount, unmanagecount;
916
917     Attachment **list = getList();
918     WidgetList manageIconList, unmanageIconList;
919
920     if (getIconCount())
921     {
922         manageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
923         unmanageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
924      
925         managecount = unmanagecount = 0;
926         for(i=0;i<getIconCount();i++) {
927             if(!list[i]->isDeleted()) {
928                 if(list[i]->getRow() == X) {
929                     if(!list[i]->isManaged()) {
930                         manageIconList[managecount] = list[i]->baseWidget();
931                         managecount++;
932                     } 
933                 }
934                 else { // if deleted
935                     if(list[i]->isManaged()) {
936                         unmanageIconList[unmanagecount] = list[i]->baseWidget();
937                         unmanagecount++;
938                     }
939                 }
940             }
941         }
942
943         XtUnmanageChildren(unmanageIconList, unmanagecount);
944         XtManageChildren(manageIconList, managecount);
945
946
947         XtFree((char *)manageIconList);
948         XtFree((char *)unmanageIconList);
949     }
950
951     this->attachment_summary(_iconCount - _deleteCount, _deleteCount);
952 }
953
954 //
955 // Calculate the position of every non-deleted Attachment
956 //
957
958 void AttachArea::CalcAllAttachmentPositions()
959 {
960     int i, j;
961     Attachment **list = getList();
962  
963     j = -1;
964     for(i=0;i<getIconCount();i++) {
965         if(!list[i]->isDeleted()) {
966             calculate_attachment_position(
967                         (j == -1) ? (Attachment *)NULL : list[j],
968                         list[i]);
969             j = i;
970         }
971     }
972 }
973
974 //
975 // Determine the position of attachment "item" given reference
976 // attachment "ref"
977 //
978
979 void AttachArea::calculate_attachment_position(
980     Attachment *ref,
981     Attachment *item
982 )
983 {
984     if(ref == NULL) {
985         item->setX(HSPACE);
986         item->setY(VSPACE);
987         item->setRow(0);
988         return;
989     }
990     if(((Dimension)(ref->getX() + 
991                     ref->getWidth() + 
992                     HSPACE + 
993                     item->getWidth()))  > getAAWidth() ) {
994         item->setX(HSPACE);
995         item->setY(VSPACE);
996         item->setRow(ref->getRow() + 1);
997     } else {
998         item->setX(ref->getX() + ref->getWidth() + HSPACE);
999         item->setRow(ref->getRow());
1000         item->setY(VSPACE);
1001     }
1002 }
1003
1004 //
1005 // Invoked when the user moves the slider by any method
1006 // If the user is dragging the slider then this callback
1007 // is only invoked when the user releases the mouse button
1008 //
1009
1010 void AttachArea::valueChangedCallback ( 
1011     Widget, 
1012     XtPointer clientData, 
1013     XtPointer callData 
1014 )
1015 {
1016     AttachArea *obj = (AttachArea *) clientData;
1017
1018     obj->valueChanged( callData );
1019 }
1020
1021 void AttachArea::valueChanged( XtPointer callData )
1022 {
1023     XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
1024
1025     _currentRow = cbs->value;
1026     DisplayAttachmentsInRow(_currentRow);
1027 }
1028
1029 //
1030 // Invoked when the user drags the slider
1031 //
1032
1033 void AttachArea::dragCallback ( 
1034     Widget, 
1035     XtPointer clientData, 
1036     XtPointer callData 
1037 )
1038 {
1039     AttachArea *obj = (AttachArea *) clientData;
1040
1041     obj->dragSlider( callData );
1042 }
1043
1044 void AttachArea::dragSlider( XtPointer callData )
1045 {
1046     XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
1047
1048     if(cbs->value == _currentRow)
1049         return;
1050     _currentRow = cbs->value;
1051     DisplayAttachmentsInRow(_currentRow);
1052 }
1053
1054 //
1055 // Calculate the number of rows
1056 //
1057
1058 void AttachArea::CalcLastRow()
1059 {
1060     int i;
1061     unsigned row = 0;
1062      Attachment **list = getList();
1063  
1064      for(i=0;i<getIconCount();i++) {
1065         if(!list[i]->isDeleted()) {
1066             row = list[i]->getRow();
1067         }
1068      }
1069     _lastRow = row;
1070 }
1071
1072 //
1073 // Set the XmmNmaximum resource to size
1074 //
1075
1076 void AttachArea::SetScrollBarSize(unsigned int size)
1077 {
1078     XtVaSetValues(_vsb, 
1079         XmNmaximum, size,
1080         NULL);
1081 }
1082
1083 //
1084 // If the current row is greater than the last row, adjust the
1085 // current row to be equal to the last row.
1086 //
1087
1088 void AttachArea::AdjustCurrentRow()
1089 {
1090     if(_currentRow > _lastRow) {
1091         _currentRow = _lastRow;
1092         XtVaSetValues(_vsb, XmNvalue, _currentRow, NULL);
1093     }
1094 }
1095
1096 XmString
1097 AttachArea::getSelectedAttachName()
1098 {
1099     XmString str = (XmString)NULL;
1100
1101     if(_cache_single_attachment)
1102         str = _cache_single_attachment->getLabel();
1103
1104     return(str);
1105 }
1106
1107 void
1108 AttachArea::setSelectedAttachName(
1109     XmString new_name
1110 )
1111 {
1112     int i;
1113     Boolean set = FALSE;
1114     Attachment **list = this->getList();
1115
1116     XmString nn = XmStringCopy(new_name);
1117
1118     // Set name of first selected attachment to new_name
1119     for(i=0;i<this->getIconCount() && !set;i++)
1120         if(list[i]->isSelected()) {
1121             list[i]->rename(nn);
1122             set = TRUE;
1123         }
1124     this->manageList();
1125 }
1126
1127
1128 void
1129 AttachArea::attachmentSelected(
1130     Attachment *attachment
1131
1132 {
1133     // First deselect other selected attachments
1134     this->unselectOtherSelectedAttachments(attachment);
1135     
1136     // Enable the menu item at the toplevel shell's menubar.
1137     if(_cache_single_attachment == NULL)
1138         _myOwner->owner()->attachment_selected();
1139
1140     // Cache the single selected attachment
1141     _cache_single_attachment = attachment;
1142     _attach_area_selection_state = AA_SEL_SINGLE;
1143 }
1144
1145 void
1146 AttachArea::attachmentFeedback(
1147     Boolean value
1148 )
1149 {
1150     _myOwner->owner()->attachmentFeedback(value);
1151 }
1152     
1153 char *
1154 AttachArea::calcKbytes(unsigned int bytes)
1155 {
1156     static char kstring[64];
1157
1158     if(bytes < 103)
1159         sprintf(kstring, "%d bytes",bytes);
1160     else if(bytes < 1024)
1161         sprintf(kstring, " .%dk", bytes/103);
1162     else
1163         sprintf(kstring, "%dk", bytes/1024);
1164
1165     return kstring;
1166 }
1167
1168 void
1169 AttachArea::addToRowOfAttachmentsStatus()
1170 {
1171     XmString labelStr2;
1172
1173     // Size of first label
1174     
1175     labelStr2 = XmStringCreateLocalized(
1176                         GETMSG(DT_catd, 3, 37, "Summary of attachments"));
1177
1178
1179     _attachments_summary = XtCreateManagedWidget("Attachments_Summary", 
1180                                                  xmLabelWidgetClass,
1181                                                  rowOfAttachmentsStatus, NULL, 0);
1182
1183     XtVaSetValues(_attachments_summary,
1184                   XmNalignment, XmALIGNMENT_END,
1185                   XmNlabelString, labelStr2,
1186                   XmNrightAttachment, XmATTACH_FORM,
1187                   NULL );
1188
1189      XmStringFree(labelStr2);
1190 }
1191
1192 void
1193 AttachArea::parseAttachments(
1194     DtMailEnv &mail_error,
1195     DtMail::Message* msg,
1196     Boolean empty,
1197     int startBP
1198 )
1199 {
1200     DtMail::BodyPart * tmpBP;
1201     int index = 1;
1202     int num_attachments = 0;
1203     char * name;
1204
1205
1206     // First unmanage and empty out the current contents.
1207
1208     // SMD sets this boolean to FALSE so that previous message's attachments
1209     // are not cleared.  E.g. Including/forwarding multiple messages each
1210     // with attachments.
1211     // RMW sets this boolean to TRUE so that all attachments are cleared in
1212     // the attachment pane everytime a new message is displayed.
1213
1214     if ( empty ) {
1215
1216         // First unmanage the clipWindow.
1217         // Unmanaging the attachment pane is visually ugly
1218
1219         XtUnmanageChild(_clipWindow);
1220         this->clearAttachArea();
1221     }
1222
1223     _deleteCount = 0;
1224
1225     // Now fill list with new attachments.
1226
1227     tmpBP = msg->getFirstBodyPart(mail_error);
1228     if (mail_error.isSet()) {
1229         // do something
1230     }
1231
1232     // Sync up the index with the bodyPart from which to begin
1233     // adding attachments into attachPane.
1234     // 
1235     while (startBP > index) {
1236         tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1237         index++;
1238     }
1239     
1240     while (tmpBP != NULL) {
1241         num_attachments++;
1242         tmpBP->getContents(
1243                         mail_error,
1244                         NULL,
1245                         NULL,
1246                         NULL,
1247                         &name,
1248                         NULL,
1249                         NULL);
1250         
1251         if (mail_error.isSet()) {
1252             // do something
1253         }
1254
1255         // It is possible for an attachment to not have a name.
1256         if (!name) {
1257             name = "NoName";
1258         }
1259
1260         this->addAttachment(name, tmpBP);
1261         tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1262         if (mail_error.isSet()) {
1263             // do something
1264         }
1265
1266         free(name);
1267     }
1268 }
1269
1270 void
1271 AttachArea::attachment_summary(
1272     int live,
1273     int dead
1274 )
1275 {
1276
1277     char *buf = NULL;
1278     char * tmp1;
1279     char * tmp2;
1280
1281     if ((live == 1) && (dead == 0)) {
1282         tmp1 = GETMSG(DT_catd, 3, 38, "attachment");
1283         buf = new char[strlen(tmp1) + 64];
1284         sprintf(buf, "%d %s", live, tmp1);
1285     }
1286     else if ((live >= 0) && (dead == 0)) {
1287         /* NL_COMMENT
1288          * "attachments" is the plural form of "attachment".
1289          */
1290         tmp1 = GETMSG(DT_catd, 3, 39, "attachments");
1291         buf = new char[strlen(tmp1) + 64];
1292         sprintf(buf, "%d %s", live, tmp1);
1293     }
1294     else if ((live >= 0) && (dead > 0)) {
1295         tmp1 = GETMSG(DT_catd, 3, 40, "attachments");
1296         tmp2 = GETMSG(DT_catd, 3, 41, "deleted");
1297         buf = new char[strlen(tmp1) + strlen(tmp2) + 64];
1298         sprintf(buf, "%d %s, %d %s", live, tmp1, dead, tmp2);
1299     }
1300     
1301     if (buf) {
1302         XmString buf_str = XmStringCreateLocalized(buf);
1303         XtVaSetValues(_attachments_summary,
1304             XmNlabelString, buf_str,
1305             NULL );
1306     
1307         delete [] buf;
1308         XmStringFree(buf_str);
1309     }
1310 }
1311
1312 void
1313 AttachArea::manage()
1314 {
1315     XtArgVal /* Dimension */ ht;
1316     XtArgVal /* Dimension */ pht;
1317     Widget sww;
1318
1319     // Update the display
1320     sww = getSWWindow();
1321     this->manageList();
1322
1323     XtAddCallback(
1324                 _clipWindow, 
1325                 XmNresizeCallback, &AttachArea::resizeCallback,
1326                 (XtPointer) this );
1327
1328     XtAddCallback(
1329                 _clipWindow, 
1330                 XmNinputCallback, &AttachArea::inputCallback,
1331                 (XtPointer) this);
1332
1333     XtAddEventHandler(
1334                 _clipWindow, ButtonPressMask,
1335                 FALSE, MenuButtonHandler,
1336                 (XtPointer) this);
1337
1338     // hack
1339     XtVaGetValues(sww, XmNheight, &ht, NULL);
1340     XtVaGetValues(_w, XmNheight, &pht, NULL);
1341     // Manage the clipWindow back
1342     if (!XtIsManaged(_clipWindow)) XtManageChild(_clipWindow);
1343
1344     // hack
1345     XtVaSetValues(sww, XmNheight, ht, NULL);
1346     UIComponent::manage();
1347     XtVaSetValues(_w, XmNheight, pht, NULL);
1348 }
1349
1350 void
1351 AttachArea::unmanage()
1352 {
1353     int i;
1354     Attachment **list = getList();
1355
1356     // Unmanage the widgets it currently has
1357     for (i=0; i<getIconCount(); i++)
1358       list[i]->unmanageIconWidget();
1359
1360     XtRemoveCallback(
1361         _clipWindow, 
1362         XmNresizeCallback, &AttachArea::resizeCallback,
1363         (XtPointer) this );
1364
1365     XtRemoveCallback(
1366         _clipWindow, 
1367         XmNinputCallback, &AttachArea::inputCallback,
1368         (XtPointer) this );
1369
1370     XtRemoveEventHandler(
1371         _clipWindow, ButtonPressMask,
1372         FALSE, MenuButtonHandler,
1373         (XtPointer) this);
1374
1375     UIComponent::unmanage();
1376 }
1377
1378 void
1379 AttachArea::removeCurrentAttachments()
1380 {
1381
1382     Attachment **list = getList();
1383     int i;
1384
1385     // Unmanage the widgets it currently has
1386
1387     for (i=0; i<getIconCount(); i++) {
1388
1389         list[i]->unmanageIconWidget();
1390         list[i]->deleteIt();
1391     }
1392
1393     // Reset
1394     if (_attachmentList)
1395         delete []_attachmentList;
1396     _attachmentList = NULL;
1397     _iconCount = 0;
1398     _deleteCount = 0;
1399     _attach_area_selection_state = AA_SEL_NONE;
1400     _cache_single_attachment = NULL;
1401
1402     this->attachment_summary(_iconCount, _deleteCount);
1403 }
1404
1405 // Similar to removeCurrentAttachments().
1406 // Except we don't display a summary that there are no attachments.
1407 // Plus has potential for other (different) usage.
1408
1409 void
1410 AttachArea::clearAttachArea()
1411 {
1412
1413     Attachment **list = getList();
1414     int i;
1415
1416     // Unmanage the widgets it currently has
1417
1418     for (i=0; i<getIconCount(); i++) {
1419
1420         list[i]->unmanageIconWidget();
1421         delete list[i];
1422     }
1423
1424     // Reset
1425     if (_attachmentList)
1426         delete []_attachmentList;
1427     _attachmentList = NULL;
1428     _iconCount = 0;
1429     _deleteCount = 0;
1430     _attach_area_selection_state = AA_SEL_NONE;
1431     _cache_single_attachment = NULL;
1432 }
1433
1434 #ifdef DEAD_WOOD
1435 void
1436 AttachArea::saveAttachmentToFile(
1437     DtMailEnv &mail_error,
1438     char *save_path
1439 )
1440 {
1441
1442     Attachment *attachment = this->getSelectedAttachment();
1443
1444     if(attachment != NULL)
1445         attachment->saveToFile(mail_error, save_path);
1446
1447 }
1448 #endif /* DEAD_WOOD */
1449
1450 void
1451 AttachArea::deleteSelectedAttachments(
1452     DtMailEnv &         //mail_error
1453 )
1454 {
1455     Attachment **list = getList();
1456     int i;
1457     
1458     for (i = 0; i<getIconCount(); i++) {
1459         if (list[i]->isSelected() && !list[i]->isDeleted()) {
1460
1461             // unselect it first.  Else, when undeleted it comes
1462             // off selected
1463             
1464             list[i]->unselect();
1465             list[i]->deleteIt();
1466             _deleteCount++;
1467         }
1468     }
1469     
1470     // Unmanage all.
1471     // Their positions need to get recomputed and the undeleted
1472     // ones get remanaged in manageList().
1473
1474     for (i=0; i<getIconCount(); i++) {
1475         list[i]->unmanageIconWidget();
1476     }
1477
1478     _cache_single_attachment = NULL;
1479     _attach_area_selection_state = AA_SEL_NONE;
1480
1481     this->manageList();
1482 }
1483
1484
1485 #ifdef DEAD_WOOD
1486 void
1487 AttachArea::undeleteAllDeletedAttachments(
1488     DtMailEnv &         //mail_error
1489 )
1490 {
1491 }
1492 #endif /* DEAD_WOOD */
1493
1494 void
1495 AttachArea::undeleteLastDeletedAttachment(
1496     DtMailEnv &mail_error
1497 )
1498 {
1499
1500     Attachment *tmpAttachment;
1501     Attachment **list;
1502     time_t time_deleted = 0, tmpTime = 0;
1503     int i;
1504
1505     if (_deleteCount == 0) {
1506         return;
1507     }
1508
1509     list = getList();
1510
1511     tmpAttachment = list[0];
1512     time_deleted = tmpAttachment->getBodyPart()->getDeleteTime(mail_error);
1513     if (mail_error.isSet()) {
1514         // do something
1515     }
1516
1517     for (i=1; i<getIconCount(); i++) {
1518         if (list[i]->isDeleted()) {
1519             tmpTime = list[i]->getBodyPart()->getDeleteTime(mail_error);
1520             if (mail_error.isSet()) {
1521                 // do something
1522             }
1523             if ( tmpTime > time_deleted) {
1524                 time_deleted = tmpTime;
1525                 tmpAttachment = list[i];
1526             }
1527         }
1528     }
1529
1530     tmpAttachment->undeleteIt();
1531     _deleteCount--;
1532
1533     // Unmanage all.
1534     // Their positions need to get recomputed and the deleted
1535     // ones get remanaged in manageList().
1536
1537     for (i=0; i<getIconCount(); i++) {
1538         list[i]->unmanageIconWidget();
1539     }
1540
1541
1542     this->manageList();
1543
1544 }
1545
1546     
1547 void
1548 AttachArea::unselectOtherSelectedAttachments(
1549     Attachment *attachment
1550 )
1551 {
1552     if(_attach_area_selection_state == AA_SEL_NONE)
1553         return;
1554
1555     if(_attach_area_selection_state == AA_SEL_ALL) {
1556         int i;
1557         Attachment **list;
1558
1559         list = getList(); 
1560
1561         for (i=0; i < getIconCount(); i++) 
1562             if (list[i]->isSelected() && list[i] != attachment) 
1563                 list[i]->unselect();
1564     } 
1565     else if (_cache_single_attachment && 
1566             (attachment != _cache_single_attachment)) {
1567         _cache_single_attachment->unselect();
1568         _cache_single_attachment = NULL;
1569     }
1570
1571    if(attachment == NULL) {
1572         // Grey out the appropriate menu items in the RMW...
1573         _myOwner->owner()->all_attachments_deselected();
1574         _attach_area_selection_state = AA_SEL_NONE;
1575         _cache_single_attachment = NULL;
1576    }
1577 }
1578
1579 void
1580 AttachArea::addAttachmentActions(
1581     char **actions,
1582     int indx
1583 )
1584 {
1585
1586     _myOwner->owner()->addAttachmentActions(
1587                                 actions,
1588                                 indx
1589                         );
1590
1591 }
1592
1593 void
1594 AttachArea::setOwnerShell(
1595     RoamMenuWindow *rmw
1596 )
1597 {
1598     _myRMW = rmw;
1599 }
1600
1601 void
1602 AttachArea::setOwnerShell(
1603     ViewMsgDialog *vmd
1604 )
1605 {
1606     _myVMD = vmd;
1607 }
1608
1609 void
1610 AttachArea::setOwnerShell(
1611     SendMsgDialog *smd
1612 )
1613 {
1614     _mySMD = smd;
1615 }
1616
1617 Widget
1618 AttachArea::ownerShellWidget()
1619 {
1620     if (_myRMW) {
1621         return(_myRMW->baseWidget());
1622     }
1623     else if (_myVMD) {
1624         return(_myVMD->baseWidget());
1625     }
1626     else if (_mySMD) {
1627         return(_mySMD->baseWidget());
1628     }
1629     else {
1630         // Error out
1631     }
1632     return((Widget) NULL);
1633 }
1634
1635 Boolean
1636 AttachArea::isOwnerShellEditable()
1637 {
1638     // only SMD is editable
1639     if (_mySMD != NULL) {
1640         return TRUE;
1641     }
1642     else {
1643         return FALSE;
1644     }
1645 }
1646
1647 void
1648 AttachArea::setPendingAction(
1649     Boolean bval
1650 )
1651 {
1652     _pendingAction = bval;
1653     if (bval) {
1654         _numPendingActions++;
1655     }
1656     else {
1657         if (_numPendingActions > 0) {
1658             _numPendingActions--;
1659         }
1660     }
1661 }
1662
1663 void
1664 AttachArea::resetPendingAction()
1665 {
1666
1667     _numPendingActions = 0;
1668 }
1669
1670 int
1671 AttachArea::getNumPendingActions()
1672 {
1673     return(_numPendingActions);
1674 }
1675
1676 void
1677 AttachArea::selectAllAttachments()
1678 {
1679     
1680     Attachment **list;
1681     int numAttachments = getIconCount();
1682
1683     list = getList(); 
1684     
1685     if(list == NULL)
1686         return;
1687
1688     // if there's only 1 attachment, select it and
1689     // add its actions to the menu bar...
1690
1691     if (numAttachments == 1) {
1692         list[0]->primitive_select();
1693         list[0]->set_selected();
1694     }
1695     else {
1696         // More than 1 attachment.
1697         // Select them all. Don't enable their actions however.
1698
1699         for (int i=0; i < numAttachments; i++) 
1700             list[i]->primitive_select();
1701
1702         // Grey out the appropriate menu items in the RMW...
1703         _myOwner->owner()->all_attachments_selected();
1704         _cache_single_attachment = NULL;
1705         _attach_area_selection_state = AA_SEL_ALL;
1706     }
1707 }
1708
1709 int
1710 AttachArea::handleQuestionDialog(
1711     char *title,
1712     char *buf,
1713     char * helpId
1714 )
1715 {
1716     DtMailGenDialog *dialog;
1717     int answer;
1718
1719     if (_myRMW) {
1720         dialog = _myRMW->genDialog();
1721     }
1722     else if (_myVMD) {
1723         dialog = _myVMD->genDialog();
1724     }
1725     else if ( _mySMD) {
1726         dialog = _mySMD->genDialog();
1727     }
1728     else return(-1);
1729
1730     if (!dialog) return(-1);
1731
1732     dialog->setToQuestionDialog(
1733                         title,
1734                         buf);
1735     answer = dialog->post_and_return(helpId);
1736     return(answer);
1737 }
1738
1739 int
1740 AttachArea::handleErrorDialog(
1741     char *title,
1742     char *buf,
1743     char *helpId
1744 )
1745 {
1746     DtMailGenDialog *dialog;
1747     int answer;
1748
1749     if (_myRMW) {
1750         dialog = _myRMW->genDialog();
1751     }
1752     else if (_myVMD) {
1753         dialog = _myVMD->genDialog();
1754     }
1755     else if ( _mySMD) {
1756         dialog = _mySMD->genDialog();
1757     }
1758     else return(-1);
1759
1760     if (!dialog) return(-1);
1761
1762     dialog->setToErrorDialog(title, buf);
1763     answer = dialog->post_and_return(helpId);
1764     return(answer);
1765 }