4 * $TOG: AttachArea.C /main/18 1999/03/25 14:16:24 mgreess $
6 * RESTRICTED CONFIDENTIAL INFORMATION:
8 * The information in this document is subject to special
9 * restrictions in a confidential disclosure agreement between
10 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
11 * document outside HP, IBM, Sun, USL, SCO, or Univel without
12 * Sun's specific written approval. This document and all copies
13 * and derivative works thereof must be returned or destroyed at
16 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
21 #ifndef I_HAVE_NO_IDENT
24 #include <EUSCompat.h>
28 #if defined(USL) || defined(__uxp__)
29 #define S_ISSOCK(mode) ((mode & S_IFMT) == S_IFSOCK)
32 #include <Dt/Editor.h>
33 #include <Xm/ColorObjP.h>
35 #include "EUSDebug.hh"
37 #if defined(NEED_MMAP_WRAPPER)
43 #if defined(NEED_MMAP_WRAPPER)
49 extern XtPointer _XmStringUngenerate (
53 XmTextType output_type);
60 #include <sys/types.h>
63 #include <Xm/BulletinB.h>
65 #include <Xm/RowColumn.h>
66 #include <Xm/ScrolledW.h>
67 #include <Xm/DrawingA.h>
68 #include <Xm/ScrollBar.h>
69 #include <Xm/PushBG.h>
70 #include <Xm/FileSB.h>
71 #include <Xm/SelectioB.h>
73 #include <Xm/LabelG.h>
74 #include <Xm/AtomMgr.h>
76 #include <Xm/Screen.h>
77 #include <Xm/ToggleB.h>
78 #include <X11/IntrinsicP.h>
79 #include <X11/Xatom.h>
81 #include "Attachment.h"
82 #include "AttachArea.h"
86 #include "RoamMenuWindow.h"
88 #include "MsgScrollingList.hh"
89 #include "ViewMsgDialog.h"
90 #include "SendMsgDialog.h"
91 #include "MailMsg.h" // DT_catd defined here
92 #include <DtMail/DtMail.hh> // time_t defined here
93 #include <DtMail/IO.hh> // SafeAccess...
96 #include "DtMailHelp.hh"
98 extern nl_catd DtMailMsgCat;
100 #define equal(a, b) (!strcmp(a,b))
103 #define MAXATOM 2048 // ?????
105 // This is the new one
106 AttachArea::AttachArea (
110 ) : UIComponent (name)
117 _attachmentList=NULL;
121 _iconSelectedCount = 0;
128 _attachmentsSize = 0;
129 _selectedAttachmentsSize = 0;
131 _renameDialog = NULL;
137 _pendingAction = FALSE;
138 _numPendingActions = 0;
140 _attach_area_selection_state = AA_SEL_NONE;
141 _cache_single_attachment = NULL;
146 AttachArea::initialize()
149 // We're making the assumption here that this widget's parent`
152 XtWidgetGeometry size;
153 Dimension parWid, parHeight;
154 Dimension txt_w, txt_h;
159 short act, inact, prim, second, text;
160 XmPixelSet pixels[XmCO_NUM_COLORS];
163 _w = XtVaCreateManagedWidget (
165 xmFormWidgetClass, _parent,
169 XmeGetColorObjData(XtScreen(_parent), &colorUse, pixels, XmCO_NUM_COLORS,
170 &act, &inact, &prim, &second, &text);
171 _foreground = pixels[text].fg;
172 _background = pixels[text].sc;
174 parWid = _myOwner->textEditor()->get_text_width();
176 fl = _myOwner->textEditor()->get_text_fontList();
177 xms = XmStringCreateLocalized("Xyb");
178 XmStringExtent(fl, xms, &txt_w, &txt_h);
179 parHeight = txt_h + Icon::maxIconHeight() + (2*VSPACE);
181 _appBackground = _background;
182 _appForeground = _foreground;
184 _sw = XtVaCreateManagedWidget (
185 "AttachPane_ScrolledWindow",
186 xmScrolledWindowWidgetClass, _w,
187 XmNscrollingPolicy, XmAPPLICATION_DEFINED,
188 XmNrightAttachment, XmATTACH_FORM,
189 XmNleftAttachment, XmATTACH_FORM,
190 XmNtopAttachment, XmATTACH_FORM,
191 XmNshadowThickness, (Dimension)1,
194 XmNheight, parHeight,
197 rowOfAttachmentsStatus = XtCreateManagedWidget("Attachments_Status",
201 XtVaSetValues(rowOfAttachmentsStatus,
202 XmNrightAttachment, XmATTACH_FORM,
203 XmNleftAttachment, XmATTACH_FORM,
204 XmNtopAttachment, XmATTACH_WIDGET,
210 this->addToRowOfAttachmentsStatus();
212 size.request_mode = CWHeight;
213 XtQueryGeometry(rowOfAttachmentsStatus, NULL, &size);
216 rowOfAttachmentsStatus,
217 XmNpaneMaximum, size.height,
218 XmNpaneMinimum, size.height,
222 _vsb = XtVaCreateManagedWidget("vsb", xmScrollBarWidgetClass, _sw,
223 XmNorientation, XmVERTICAL,
231 XmNvalueChangedCallback,&AttachArea::valueChangedCallback,
237 XmNdragCallback, &AttachArea::dragCallback,
241 _clipWindow = XtVaCreateManagedWidget("AttachArea_clipWindow",
242 xmDrawingAreaWidgetClass, _sw,
243 XmNresizePolicy, XmRESIZE_NONE,
244 XmNbackground, _background,
246 XmNheight, parHeight,
248 XmScrolledWindowSetAreas(_sw, NULL, _vsb, _clipWindow);
250 XtManageChild(_clipWindow);
255 // Set RowCol to NULL here.
256 // It gets set in the expose_all_attachments.
260 CalcSizeOfAttachPane();
262 installDestroyHandler();
265 AttachArea::~AttachArea()
269 void AttachArea::addToList( Attachment *attachment )
271 Attachment **newList;
274 newList = new Attachment*[ _iconCount + 1 ];
275 for(i=0; i < _iconCount; i++)
276 newList[i] = _attachmentList[i];
279 delete []_attachmentList;
281 _attachmentList = newList;
283 _attachmentList[ _iconCount ] = attachment;
287 // setAttachmentsLabel();
291 void AttachArea::setAttachmentsLabel( )
293 char *c = new char[256];
296 unsigned int last_displayCount, last_selectedCount;
297 unsigned int displayCount = _iconCount - _deleteCount;
298 unsigned int attachmentsSize;
300 if((displayCount) == 0) {
301 XtUnmanageChild(_no_attachments_label);
302 XtUnmanageChild(_attachments_label);
303 XtUnmanageChild(_size_attachments_label);
304 XtUnmanageChild(_no_selected_label);
305 XtUnmanageChild(_selected_label);
306 XtUnmanageChild(_size_selected_label);
308 CalcAttachmentsSize();
309 attachmentsSize = getAttachmentsSize();
311 // Number of Attachments
312 XtVaGetValues(_no_attachments_label,
313 XmNlabelString, &xmstr,
316 str = (char *) _XmStringUngenerate(
318 XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
319 if (NULL == str) return; // internal error
320 last_displayCount = (unsigned int)strtol(str, NULL, 10);
323 // Number of Attachments Selected
324 XtVaGetValues(_no_selected_label,
325 XmNlabelString, &xmstr,
328 str = (char *) _XmStringUngenerate(
330 XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
331 if (NULL == str) return; // internal error
332 last_selectedCount = (unsigned int)strtol(str, NULL, 10);
335 if((last_displayCount == 0 && displayCount == 1) ||
336 (last_displayCount == 2 && displayCount == 1)) {
337 sprintf(c, GETMSG(DT_catd, 12, 1, "Attachment"));
338 XtVaSetValues(_attachments_label,
339 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
341 } else if(last_displayCount == 1 && displayCount == 2) {
342 sprintf(c, GETMSG(DT_catd, 12, 2, "Attachments"));
343 XtVaSetValues(_attachments_label,
344 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
347 if(last_displayCount != displayCount) {
348 sprintf(c, GETMSG(DT_catd, 12, 3, "displayCount"));
349 XtVaSetValues(_no_attachments_label,
350 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
353 sprintf(c, "(%s),", calcKbytes(attachmentsSize));
354 XtVaSetValues(_size_attachments_label,
355 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
358 if(last_selectedCount != _iconSelectedCount) {
359 sprintf(c, "%d", _iconSelectedCount);
360 XtVaSetValues(_no_selected_label,
361 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
363 sprintf(c, "(%s)", calcKbytes(getSelectedAttachmentsSize()));
364 XtVaSetValues(_size_selected_label,
365 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
368 if(!XtIsManaged(_no_attachments_label)) {
369 XtManageChild(_no_attachments_label);
370 XtManageChild(_attachments_label);
371 XtManageChild(_size_attachments_label);
372 XtManageChild(_no_selected_label);
373 XtManageChild(_selected_label);
374 XtManageChild(_size_selected_label);
379 #endif /* DEAD_WOOD */
381 int AttachArea::getSelectedIconCount()
383 Attachment **list = getList();
384 int num_selected = 0;
386 for (int i = 0; i < getIconCount(); i++) {
387 if (!list[i]->isDeleted() && list[i]->isSelected())
390 return (num_selected);
394 void AttachArea::CalcAttachmentsSize( )
396 Attachment **list = getList();
397 unsigned int total = 0;
400 int num_icons = getIconCount();
403 for(i=0;i<num_icons;i++)
404 if(!list[i]->isDeleted())
405 total += (unsigned int)list[i]->getContentsSize();
407 setAttachmentsSize(total);
409 #endif /* DEAD_WOOD */
412 AttachArea::getSelectedAttachment()
414 return _cache_single_attachment;
419 AttachArea::MenuButtonHandler(
425 AttachArea *obj = (AttachArea *)cd;
427 if(event->xany.type != ButtonPress)
430 XButtonEvent *be = (XButtonEvent *)event;
432 if(be->button == theApplication->bMenuButton())
433 obj->_myOwner->owner()->postAttachmentPopup(event);
437 AttachArea::inputCallback(Widget, XtPointer client_data, XtPointer call_data)
439 AttachArea *obj = (AttachArea *) client_data;
440 XmDrawingAreaCallbackStruct *cb = (XmDrawingAreaCallbackStruct *)call_data;
442 if(cb->reason != XmCR_INPUT ||
443 cb->event->xany.type != ButtonPress)
446 if(((XButtonEvent *)cb->event)->button == Button1)
447 obj->unselectOtherSelectedAttachments(NULL);
450 void AttachArea::resizeCallback (
452 XtPointer clientData,
458 AttachArea *obj = (AttachArea *) clientData;
468 void AttachArea::resize(
473 Attachment **list = getList();
475 _attachAreaWidth = wid;
476 XtVaSetValues(_clipWindow, XmNwidth, _attachAreaWidth, NULL);
478 for (i=0; i<getIconCount(); i++)
479 list[i]->unmanageIconWidget();
481 CalcAllAttachmentPositions();
484 SetScrollBarSize(getLastRow()+1);
485 DisplayAttachmentsInRow(_currentRow);
488 void AttachArea::CalcSizeOfAttachPane( )
490 _attachAreaWidth = _myOwner->textEditor()->get_text_width();
491 XtVaSetValues(_clipWindow, XmNwidth, _attachAreaWidth, NULL);
494 void AttachArea::activateDeactivate()
497 // If exactly one icon is selected then activate the open command
500 if(getIconSelectedCount() == 1) {
501 openCmd()->activate();
503 openCmd()->deactivate();
506 // If no icons are selected then deactivate the OK button on the FS Dialog
508 if(getIconSelectedCount() > 0) {
511 XmSelectionBoxGetChild(
512 getFsDialog(), XmDIALOG_OK_BUTTON), TRUE
517 XmSelectionBoxGetChild(
518 getFsDialog(), XmDIALOG_OK_BUTTON
520 (getFsState() == SAVEAS) ? FALSE : TRUE
525 // Used by Compose window (SMD)
526 // Given a filename, add it to message and to attachArea.
529 AttachArea::addAttachment(
530 DtMail::Message* msg,
531 DtMail::BodyPart *lastAttBP,
538 Boolean validtype = TRUE;
539 DtMail::BodyPart * bp = NULL;
540 DtMailEnv mail_error;
546 char *errormsg = new char[512];
547 char *buf = new char[2048];
548 char *buffer = NULL, *lbl;
551 for (fname_start = filename + strlen(filename) - 1;
552 fname_start >= filename && *fname_start != '/'; fname_start--) {
555 if (*fname_start == '/') {
559 bp = msg->newBodyPart(mail_error, lastAttBP);
561 if (SafeAccess(filename, F_OK) != 0) {
562 sprintf(buf, GETMSG(DT_catd, 3, 34, "%s does not exist."),
564 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 81, "Mailer"),
571 SafeStat(filename, &s);
573 if(S_ISFIFO(s.st_mode)) {
575 GETMSG(DT_catd, 12, 4, "Cannot attach FIFO files: %s"), filename);
577 } else if(S_ISCHR(s.st_mode)) {
580 GETMSG(DT_catd, 12, 5, "Cannot attach character special files: %s"), filename
583 } else if(S_ISDIR(s.st_mode)) {
586 GETMSG(DT_catd, 12, 6, "Cannot attach directories: %s"), filename
589 } else if(S_ISBLK(s.st_mode)) {
591 GETMSG(DT_catd, 12, 7, "Cannot attach block special files: %s"), filename
594 } else if(S_ISSOCK(s.st_mode)) {
596 GETMSG(DT_catd, 12, 8, "Cannot attach socket files: %s"), filename
600 if(validtype == FALSE) {
601 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 81, "Mailer"),
609 fd = SafeOpen(filename, O_RDONLY);
612 sprintf(buf, GETMSG(DT_catd, 3, 35, "Unable to open %s."), filename);
613 helpId = DTMAILHELPNOOPEN;
614 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 82, "Mailer"),
622 int page_size = (int)sysconf(_SC_PAGESIZE);
623 size_t map_size = (size_t) (s.st_size +
624 (page_size - (s.st_size % page_size)));
628 // This version of mmap does NOT allow requested length to be
629 // greater than the file size ... in contradiction to the
630 // documentation (don't round up).
631 map = (char *) mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
633 map = (char *) mmap(0, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
636 if (map == (char *)-1) {
637 // We could not map it for some reason. Let's just read it into
638 // buffer and pass it to XmText.
641 buffer = new char[s.st_size + 1];
645 GETMSG(DT_catd, 3, 36, "Unable to allocate memory."));
646 helpId = DTMAILHELPNOALLOCMEM;
647 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 83, "Mailer"),
653 if (read(fd, buffer, (unsigned int) s.st_size) < 0) {
657 buffer[s.st_size] = 0;
659 mail_error, buffer, s.st_size, NULL, fname_start, 0, NULL
663 // We now have a mapped file. XmText wants a zero terminated
664 // buffer. We get luck with mmap because unless the file is
665 // an even page size, we will have some zero fill bytes that
666 // are legal to access.
668 // Of course in the case of an even page size file we must
669 // copy the buffer, terminate it and then give it to XmText.
672 mail_error, map, s.st_size, NULL, fname_start, 0, NULL
674 munmap(map, map_size);
679 // _iconCount + 1 because iconCount starts at 0 and we want
680 // attachmentCount to begin at 1. attachmentCount is set to be
681 // in the widget's userData.
687 if(strchr(filename, '/') == NULL) // The name does not include a slash
688 lbl = strdup(filename);
689 else // The name does include a slash
690 lbl = strdup(strrchr(filename, '/')+1);
692 Attachment *attachment = new Attachment(this, lbl, bp, _iconCount + 1);
693 attachment->setAttachArea(this);
694 attachment->initialize();
695 addToList( attachment );
697 // Update the display. The Compose Window needs immediate update.
707 AttachArea::addAttachment(
708 DtMail::Message *msg,
709 DtMail::BodyPart *lastAttBP,
714 DtMailEnv mail_error;
715 DtMail::BodyPart * bp = NULL;
722 bp = msg->newBodyPart(mail_error, lastAttBP);
723 bp->setContents(mail_error, buf.buffer, buf.size, NULL, name, 0, NULL);
725 Attachment *attachment = new Attachment(this,
729 attachment->setAttachArea(this);
730 attachment->initialize();
731 addToList(attachment);
733 // Update the display. The Compose Window needs immediate update.
741 AttachArea::addAttachment(
743 DtMail::BodyPart *body_part
746 // _iconCount + 1 because iconCount starts at 0 and we want
747 // attachmentCount to begin at 1. attachmentCount is set to be
748 // in the widget's userData.
750 Attachment *attachment = new Attachment(
756 attachment->setAttachArea(this);
757 attachment->initialize();
758 addToList( attachment );
765 AttachArea::add_attachment(
766 Attachment *attachment
770 attachment->setAttachArea(this);
771 attachment->initialize();
772 addToList( attachment );
776 // This function truly deletes all the attachments in the AttachArea
777 // The widgets are unmanaged and the attachment classes are deleted.
780 void AttachArea::deleteAttachments( )
783 WidgetList deleteList;
786 Attachment **list = getList();
788 // First, unmanaged all the attachment at once so there is no
789 // flickering when we delete them
791 deleteList = (WidgetList)XtMalloc(sizeof(Widget) * getIconCount());
793 for(i=0;i<getIconCount();i++)
794 deleteList[i] = list[i]->baseWidget();
795 XtUnmanageChildren(deleteList, i);
798 XtFree((char *)deleteList);
800 // Delete each attachment in the list
801 count = getIconCount();
802 for(i=count-1;i>=0;i--) {
808 _iconSelectedCount = 0;
812 SetScrollBarSize(getLastRow()+1);
813 activateDeactivate();
814 _attachmentList=NULL;
815 _attachmentsSize = 0;
816 _selectedAttachmentsSize = 0;
818 #endif /* DEAD_WOOD */
820 void AttachArea::manageList( )
823 Attachment **list = getList();
825 for (i=0; i<getIconCount(); i++)
826 list[i]->unmanageIconWidget();
828 CalcAllAttachmentPositions();
831 SetScrollBarSize(getLastRow()+1);
832 DisplayAttachmentsInRow(_currentRow);
837 // Find the x and y position for a newly created attachment
840 void AttachArea::CalcAttachmentPosition(Attachment *item)
843 Boolean found_managed = FALSE;
845 Attachment **list = getList();
846 for(i=0, j=0;i<getIconCount();i++)
847 if(!list[i]->isDeleted()) {
849 found_managed = TRUE;
851 calculate_attachment_position(
852 found_managed ? list[j] : (Attachment *)NULL, item
856 #endif /* DEAD_WOOD */
859 // Display the attachments in row X
862 void AttachArea::DisplayAttachmentsInRow(unsigned int X)
865 int managecount, unmanagecount;
867 Attachment **list = getList();
868 WidgetList manageIconList, unmanageIconList;
872 manageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
873 unmanageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
875 managecount = unmanagecount = 0;
876 for(i=0;i<getIconCount();i++) {
877 if(!list[i]->isDeleted()) {
878 if(list[i]->getRow() == X) {
879 if(!list[i]->isManaged()) {
880 manageIconList[managecount] = list[i]->baseWidget();
885 if(list[i]->isManaged()) {
886 unmanageIconList[unmanagecount] = list[i]->baseWidget();
893 XtUnmanageChildren(unmanageIconList, unmanagecount);
894 XtManageChildren(manageIconList, managecount);
897 XtFree((char *)manageIconList);
898 XtFree((char *)unmanageIconList);
901 this->attachment_summary(_iconCount - _deleteCount, _deleteCount);
905 // Calculate the position of every non-deleted Attachment
908 void AttachArea::CalcAllAttachmentPositions()
911 Attachment **list = getList();
914 for(i=0;i<getIconCount();i++) {
915 if(!list[i]->isDeleted()) {
916 calculate_attachment_position(
917 (j == -1) ? (Attachment *)NULL : list[j],
925 // Determine the position of attachment "item" given reference
929 void AttachArea::calculate_attachment_position(
940 if(((Dimension)(ref->getX() +
943 item->getWidth())) > getAAWidth() ) {
946 item->setRow(ref->getRow() + 1);
948 item->setX(ref->getX() + ref->getWidth() + HSPACE);
949 item->setRow(ref->getRow());
955 // Invoked when the user moves the slider by any method
956 // If the user is dragging the slider then this callback
957 // is only invoked when the user releases the mouse button
960 void AttachArea::valueChangedCallback (
962 XtPointer clientData,
966 AttachArea *obj = (AttachArea *) clientData;
968 obj->valueChanged( callData );
971 void AttachArea::valueChanged( XtPointer callData )
973 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
975 _currentRow = cbs->value;
976 DisplayAttachmentsInRow(_currentRow);
980 // Invoked when the user drags the slider
983 void AttachArea::dragCallback (
985 XtPointer clientData,
989 AttachArea *obj = (AttachArea *) clientData;
991 obj->dragSlider( callData );
994 void AttachArea::dragSlider( XtPointer callData )
996 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
998 if(cbs->value == _currentRow)
1000 _currentRow = cbs->value;
1001 DisplayAttachmentsInRow(_currentRow);
1005 // Calculate the number of rows
1008 void AttachArea::CalcLastRow()
1012 Attachment **list = getList();
1014 for(i=0;i<getIconCount();i++) {
1015 if(!list[i]->isDeleted()) {
1016 row = list[i]->getRow();
1023 // Set the XmmNmaximum resource to size
1026 void AttachArea::SetScrollBarSize(unsigned int size)
1034 // If the current row is greater than the last row, adjust the
1035 // current row to be equal to the last row.
1038 void AttachArea::AdjustCurrentRow()
1040 if(_currentRow > _lastRow) {
1041 _currentRow = _lastRow;
1042 XtVaSetValues(_vsb, XmNvalue, _currentRow, NULL);
1047 AttachArea::getSelectedAttachName()
1049 XmString str = (XmString)NULL;
1051 if(_cache_single_attachment)
1052 str = _cache_single_attachment->getLabel();
1058 AttachArea::setSelectedAttachName(
1063 Boolean set = FALSE;
1064 Attachment **list = this->getList();
1066 XmString nn = XmStringCopy(new_name);
1068 // Set name of first selected attachment to new_name
1069 for(i=0;i<this->getIconCount() && !set;i++)
1070 if(list[i]->isSelected()) {
1071 list[i]->rename(nn);
1079 AttachArea::attachmentSelected(
1080 Attachment *attachment
1083 // First deselect other selected attachments
1084 this->unselectOtherSelectedAttachments(attachment);
1086 // Enable the menu item at the toplevel shell's menubar.
1087 if(_cache_single_attachment == NULL)
1088 _myOwner->owner()->attachment_selected();
1090 // Cache the single selected attachment
1091 _cache_single_attachment = attachment;
1092 _attach_area_selection_state = AA_SEL_SINGLE;
1096 AttachArea::attachmentFeedback(
1100 _myOwner->owner()->attachmentFeedback(value);
1104 AttachArea::calcKbytes(unsigned int bytes)
1106 static char kstring[64];
1109 sprintf(kstring, "%d bytes",bytes);
1110 else if(bytes < 1024)
1111 sprintf(kstring, " .%dk", bytes/103);
1113 sprintf(kstring, "%dk", bytes/1024);
1119 AttachArea::addToRowOfAttachmentsStatus()
1123 // Size of first label
1125 labelStr2 = XmStringCreateLocalized(
1126 GETMSG(DT_catd, 3, 37, "Summary of attachments"));
1129 _attachments_summary = XtCreateManagedWidget("Attachments_Summary",
1131 rowOfAttachmentsStatus, NULL, 0);
1133 XtVaSetValues(_attachments_summary,
1134 XmNalignment, XmALIGNMENT_END,
1135 XmNlabelString, labelStr2,
1136 XmNrightAttachment, XmATTACH_FORM,
1139 XmStringFree(labelStr2);
1143 AttachArea::parseAttachments(
1144 DtMailEnv &mail_error,
1145 DtMail::Message* msg,
1150 DtMail::BodyPart * tmpBP;
1152 int num_attachments = 0;
1156 // First unmanage and empty out the current contents.
1158 // SMD sets this boolean to FALSE so that previous message's attachments
1159 // are not cleared. E.g. Including/forwarding multiple messages each
1160 // with attachments.
1161 // RMW sets this boolean to TRUE so that all attachments are cleared in
1162 // the attachment pane everytime a new message is displayed.
1166 // First unmanage the clipWindow.
1167 // Unmanaging the attachment pane is visually ugly
1169 XtUnmanageChild(_clipWindow);
1170 this->clearAttachArea();
1175 // Now fill list with new attachments.
1177 tmpBP = msg->getFirstBodyPart(mail_error);
1178 if (mail_error.isSet()) {
1182 // Sync up the index with the bodyPart from which to begin
1183 // adding attachments into attachPane.
1185 while (startBP > index) {
1186 tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1190 while (tmpBP != NULL) {
1201 if (mail_error.isSet()) {
1205 // It is possible for an attachment to not have a name.
1210 this->addAttachment(name, tmpBP);
1211 tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1212 if (mail_error.isSet()) {
1221 AttachArea::attachment_summary(
1231 if ((live == 1) && (dead == 0)) {
1232 tmp1 = GETMSG(DT_catd, 3, 38, "attachment");
1233 buf = new char[strlen(tmp1) + 64];
1234 sprintf(buf, "%d %s", live, tmp1);
1236 else if ((live >= 0) && (dead == 0)) {
1238 * "attachments" is the plural form of "attachment".
1240 tmp1 = GETMSG(DT_catd, 3, 39, "attachments");
1241 buf = new char[strlen(tmp1) + 64];
1242 sprintf(buf, "%d %s", live, tmp1);
1244 else if ((live >= 0) && (dead > 0)) {
1245 tmp1 = GETMSG(DT_catd, 3, 40, "attachments");
1246 tmp2 = GETMSG(DT_catd, 3, 41, "deleted");
1247 buf = new char[strlen(tmp1) + strlen(tmp2) + 64];
1248 sprintf(buf, "%d %s, %d %s", live, tmp1, dead, tmp2);
1252 XmString buf_str = XmStringCreateLocalized(buf);
1253 XtVaSetValues(_attachments_summary,
1254 XmNlabelString, buf_str,
1258 XmStringFree(buf_str);
1263 AttachArea::manage()
1270 // Update the display
1271 XtVaGetValues(this->baseWidget(), XmNwidth, &wid, NULL);
1272 sww = getSWWindow();
1277 XmNresizeCallback, &AttachArea::resizeCallback,
1282 XmNinputCallback, &AttachArea::inputCallback,
1286 _clipWindow, ButtonPressMask,
1287 FALSE, MenuButtonHandler,
1291 XtVaGetValues(sww, XmNheight, &ht, NULL);
1292 XtVaGetValues(_w, XmNheight, &pht, NULL);
1293 // Manage the clipWindow back
1294 if (!XtIsManaged(_clipWindow)) XtManageChild(_clipWindow);
1297 XtVaSetValues(sww, XmNheight, ht, NULL);
1298 UIComponent::manage();
1299 XtVaSetValues(_w, XmNheight, pht, NULL);
1303 AttachArea::unmanage()
1306 Attachment **list = getList();
1308 // Unmanage the widgets it currently has
1309 for (i=0; i<getIconCount(); i++)
1310 list[i]->unmanageIconWidget();
1314 XmNresizeCallback, &AttachArea::resizeCallback,
1319 XmNinputCallback, &AttachArea::inputCallback,
1322 XtRemoveEventHandler(
1323 _clipWindow, ButtonPressMask,
1324 FALSE, MenuButtonHandler,
1327 UIComponent::unmanage();
1331 AttachArea::removeCurrentAttachments()
1334 Attachment **list = getList();
1337 // Unmanage the widgets it currently has
1339 for (i=0; i<getIconCount(); i++) {
1341 list[i]->unmanageIconWidget();
1342 list[i]->deleteIt();
1346 if (_attachmentList)
1347 delete []_attachmentList;
1348 _attachmentList = NULL;
1351 _attach_area_selection_state = AA_SEL_NONE;
1352 _cache_single_attachment = NULL;
1354 this->attachment_summary(_iconCount, _deleteCount);
1357 // Similar to removeCurrentAttachments().
1358 // Except we don't display a summary that there are no attachments.
1359 // Plus has potential for other (different) usage.
1362 AttachArea::clearAttachArea()
1365 Attachment **list = getList();
1368 // Unmanage the widgets it currently has
1370 for (i=0; i<getIconCount(); i++) {
1372 list[i]->unmanageIconWidget();
1377 if (_attachmentList)
1378 delete []_attachmentList;
1379 _attachmentList = NULL;
1382 _attach_area_selection_state = AA_SEL_NONE;
1383 _cache_single_attachment = NULL;
1388 AttachArea::saveAttachmentToFile(
1389 DtMailEnv &mail_error,
1394 Attachment *attachment = this->getSelectedAttachment();
1396 if(attachment != NULL)
1397 attachment->saveToFile(mail_error, save_path);
1400 #endif /* DEAD_WOOD */
1403 AttachArea::deleteSelectedAttachments(
1404 DtMailEnv & //mail_error
1407 Attachment **list = getList();
1410 for (i = 0; i<getIconCount(); i++) {
1411 if (list[i]->isSelected() && !list[i]->isDeleted()) {
1413 // unselect it first. Else, when undeleted it comes
1416 list[i]->unselect();
1417 list[i]->deleteIt();
1423 // Their positions need to get recomputed and the undeleted
1424 // ones get remanaged in manageList().
1426 for (i=0; i<getIconCount(); i++) {
1427 list[i]->unmanageIconWidget();
1430 _cache_single_attachment = NULL;
1431 _attach_area_selection_state = AA_SEL_NONE;
1439 AttachArea::undeleteAllDeletedAttachments(
1440 DtMailEnv & //mail_error
1444 #endif /* DEAD_WOOD */
1447 AttachArea::undeleteLastDeletedAttachment(
1448 DtMailEnv &mail_error
1452 Attachment *tmpAttachment;
1454 time_t time_deleted = NULL, tmpTime = NULL;
1457 if (_deleteCount == 0) {
1463 tmpAttachment = list[0];
1464 time_deleted = tmpAttachment->getBodyPart()->getDeleteTime(mail_error);
1465 if (mail_error.isSet()) {
1469 for (i=1; i<getIconCount(); i++) {
1470 if (list[i]->isDeleted()) {
1471 tmpTime = list[i]->getBodyPart()->getDeleteTime(mail_error);
1472 if (mail_error.isSet()) {
1475 if ( tmpTime > time_deleted) {
1476 time_deleted = tmpTime;
1477 tmpAttachment = list[i];
1482 tmpAttachment->undeleteIt();
1486 // Their positions need to get recomputed and the deleted
1487 // ones get remanaged in manageList().
1489 for (i=0; i<getIconCount(); i++) {
1490 list[i]->unmanageIconWidget();
1500 AttachArea::unselectOtherSelectedAttachments(
1501 Attachment *attachment
1504 if(_attach_area_selection_state == AA_SEL_NONE)
1507 if(_attach_area_selection_state == AA_SEL_ALL) {
1513 for (i=0; i < getIconCount(); i++)
1514 if (list[i]->isSelected() && list[i] != attachment)
1515 list[i]->unselect();
1517 else if (_cache_single_attachment &&
1518 (attachment != _cache_single_attachment)) {
1519 _cache_single_attachment->unselect();
1520 _cache_single_attachment = NULL;
1523 if(attachment == NULL) {
1524 // Grey out the appropriate menu items in the RMW...
1525 _myOwner->owner()->all_attachments_deselected();
1526 _attach_area_selection_state = AA_SEL_NONE;
1527 _cache_single_attachment = NULL;
1532 AttachArea::addAttachmentActions(
1538 _myOwner->owner()->addAttachmentActions(
1546 AttachArea::setOwnerShell(
1554 AttachArea::setOwnerShell(
1562 AttachArea::setOwnerShell(
1570 AttachArea::ownerShellWidget()
1573 return(_myRMW->baseWidget());
1576 return(_myVMD->baseWidget());
1579 return(_mySMD->baseWidget());
1584 return((Widget) NULL);
1588 AttachArea::isOwnerShellEditable()
1590 // only SMD is editable
1591 if (_mySMD != NULL) {
1600 AttachArea::setPendingAction(
1604 _pendingAction = bval;
1606 _numPendingActions++;
1609 if (_numPendingActions > 0) {
1610 _numPendingActions--;
1616 AttachArea::resetPendingAction()
1619 _numPendingActions = 0;
1623 AttachArea::getNumPendingActions()
1625 return(_numPendingActions);
1629 AttachArea::selectAllAttachments()
1633 int numAttachments = getIconCount();
1640 // if there's only 1 attachment, select it and
1641 // add its actions to the menu bar...
1643 if (numAttachments == 1) {
1644 list[0]->primitive_select();
1645 list[0]->set_selected();
1648 // More than 1 attachment.
1649 // Select them all. Don't enable their actions however.
1651 for (int i=0; i < numAttachments; i++)
1652 list[i]->primitive_select();
1654 // Grey out the appropriate menu items in the RMW...
1655 _myOwner->owner()->all_attachments_selected();
1656 _cache_single_attachment = NULL;
1657 _attach_area_selection_state = AA_SEL_ALL;
1662 AttachArea::handleQuestionDialog(
1668 DtMailGenDialog *dialog;
1672 dialog = _myRMW->genDialog();
1675 dialog = _myVMD->genDialog();
1678 dialog = _mySMD->genDialog();
1682 if (!dialog) return(-1);
1684 dialog->setToQuestionDialog(
1687 answer = dialog->post_and_return(helpId);
1692 AttachArea::handleErrorDialog(
1698 DtMailGenDialog *dialog;
1702 dialog = _myRMW->genDialog();
1705 dialog = _myVMD->genDialog();
1708 dialog = _mySMD->genDialog();
1712 if (!dialog) return(-1);
1714 dialog->setToErrorDialog(title, buf);
1715 answer = dialog->post_and_return(helpId);