2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
26 * $TOG: AttachArea.C /main/18 1999/03/25 14:16:24 mgreess $
28 * RESTRICTED CONFIDENTIAL INFORMATION:
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
38 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
43 #ifndef I_HAVE_NO_IDENT
46 #include <EUSCompat.h>
51 #define S_ISSOCK(mode) ((mode & S_IFMT) == S_IFSOCK)
54 #include <Dt/Editor.h>
55 #include <Xm/ColorObjP.h>
57 #include "EUSDebug.hh"
59 #if defined(NEED_MMAP_WRAPPER)
65 #if defined(NEED_MMAP_WRAPPER)
71 extern XtPointer _XmStringUngenerate (
75 XmTextType output_type);
82 #include <sys/types.h>
85 #include <Xm/BulletinB.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>
95 #include <Xm/LabelG.h>
96 #include <Xm/AtomMgr.h>
98 #include <Xm/Screen.h>
99 #include <Xm/ToggleB.h>
100 #include <X11/IntrinsicP.h>
101 #include <X11/Xatom.h>
103 #include "Attachment.h"
104 #include "AttachArea.h"
108 #include "RoamMenuWindow.h"
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...
118 #include "DtMailHelp.hh"
120 extern nl_catd DtMailMsgCat;
122 #define equal(a, b) (!strcmp(a,b))
125 #define MAXATOM 2048 // ?????
127 // This is the new one
128 AttachArea::AttachArea (
132 ) : UIComponent (name)
139 _attachmentList=NULL;
143 _iconSelectedCount = 0;
150 _attachmentsSize = 0;
151 _selectedAttachmentsSize = 0;
153 _renameDialog = NULL;
159 _pendingAction = FALSE;
160 _numPendingActions = 0;
162 _attach_area_selection_state = AA_SEL_NONE;
163 _cache_single_attachment = NULL;
165 _no_selected_label = NULL;
166 _selected_label = NULL;
167 rowOfAttachmentsStatus = NULL;
168 _attachments_status = NULL;
169 _attachments_summary = NULL;
171 _attachAreaWidth = 0;
172 _attachAreaHeight = 0;
189 _size_selected_label = NULL;
190 _format_button = NULL;
191 _descriptionDialog = NULL;
192 _no_attachments_label = NULL;
193 _attachments_label = NULL;
194 _size_attachments_label = NULL;
200 AttachArea::initialize()
203 // We're making the assumption here that this widget's parent`
206 XtWidgetGeometry size;
207 Dimension parWid, parHeight;
208 Dimension txt_w, txt_h;
213 short act, inact, prim, second, text;
214 XmPixelSet pixels[XmCO_NUM_COLORS];
217 _w = XtVaCreateManagedWidget (
219 xmFormWidgetClass, _parent,
223 XmeGetColorObjData(XtScreen(_parent), &colorUse, pixels, XmCO_NUM_COLORS,
224 &act, &inact, &prim, &second, &text);
225 _foreground = pixels[text].fg;
226 _background = pixels[text].sc;
228 parWid = _myOwner->textEditor()->get_text_width();
230 fl = _myOwner->textEditor()->get_text_fontList();
231 xms = XmStringCreateLocalized("Xyb");
232 XmStringExtent(fl, xms, &txt_w, &txt_h);
233 parHeight = txt_h + Icon::maxIconHeight() + (2*VSPACE);
235 _appBackground = _background;
236 _appForeground = _foreground;
238 _sw = XtVaCreateManagedWidget (
239 "AttachPane_ScrolledWindow",
240 xmScrolledWindowWidgetClass, _w,
241 XmNscrollingPolicy, XmAPPLICATION_DEFINED,
242 XmNrightAttachment, XmATTACH_FORM,
243 XmNleftAttachment, XmATTACH_FORM,
244 XmNtopAttachment, XmATTACH_FORM,
245 XmNshadowThickness, (Dimension)1,
248 XmNheight, parHeight,
251 rowOfAttachmentsStatus = XtCreateManagedWidget("Attachments_Status",
255 XtVaSetValues(rowOfAttachmentsStatus,
256 XmNrightAttachment, XmATTACH_FORM,
257 XmNleftAttachment, XmATTACH_FORM,
258 XmNtopAttachment, XmATTACH_WIDGET,
264 this->addToRowOfAttachmentsStatus();
266 size.request_mode = CWHeight;
267 XtQueryGeometry(rowOfAttachmentsStatus, NULL, &size);
270 rowOfAttachmentsStatus,
271 XmNpaneMaximum, size.height,
272 XmNpaneMinimum, size.height,
276 _vsb = XtVaCreateManagedWidget("vsb", xmScrollBarWidgetClass, _sw,
277 XmNorientation, XmVERTICAL,
285 XmNvalueChangedCallback,&AttachArea::valueChangedCallback,
291 XmNdragCallback, &AttachArea::dragCallback,
295 _clipWindow = XtVaCreateManagedWidget("AttachArea_clipWindow",
296 xmDrawingAreaWidgetClass, _sw,
297 XmNresizePolicy, XmRESIZE_NONE,
298 XmNbackground, _background,
300 XmNheight, parHeight,
302 XmScrolledWindowSetAreas(_sw, NULL, _vsb, _clipWindow);
304 XtManageChild(_clipWindow);
309 // Set RowCol to NULL here.
310 // It gets set in the expose_all_attachments.
314 CalcSizeOfAttachPane();
316 installDestroyHandler();
319 AttachArea::~AttachArea()
323 void AttachArea::addToList( Attachment *attachment )
325 Attachment **newList;
328 newList = new Attachment*[ _iconCount + 1 ];
329 for(i=0; i < _iconCount; i++)
330 newList[i] = _attachmentList[i];
333 delete []_attachmentList;
335 _attachmentList = newList;
337 _attachmentList[ _iconCount ] = attachment;
341 // setAttachmentsLabel();
345 void AttachArea::setAttachmentsLabel( )
347 char *c = new char[256];
350 unsigned int last_displayCount, last_selectedCount;
351 unsigned int displayCount = _iconCount - _deleteCount;
352 unsigned int attachmentsSize;
354 if((displayCount) == 0) {
355 XtUnmanageChild(_no_attachments_label);
356 XtUnmanageChild(_attachments_label);
357 XtUnmanageChild(_size_attachments_label);
358 XtUnmanageChild(_no_selected_label);
359 XtUnmanageChild(_selected_label);
360 XtUnmanageChild(_size_selected_label);
362 CalcAttachmentsSize();
363 attachmentsSize = getAttachmentsSize();
365 // Number of Attachments
366 XtVaGetValues(_no_attachments_label,
367 XmNlabelString, &xmstr,
370 str = (char *) _XmStringUngenerate(
372 XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
373 if (NULL == str) return; // internal error
374 last_displayCount = (unsigned int)strtol(str, NULL, 10);
377 // Number of Attachments Selected
378 XtVaGetValues(_no_selected_label,
379 XmNlabelString, &xmstr,
382 str = (char *) _XmStringUngenerate(
384 XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
385 if (NULL == str) return; // internal error
386 last_selectedCount = (unsigned int)strtol(str, NULL, 10);
389 if((last_displayCount == 0 && displayCount == 1) ||
390 (last_displayCount == 2 && displayCount == 1)) {
391 sprintf(c, GETMSG(DT_catd, 12, 1, "Attachment"));
392 XtVaSetValues(_attachments_label,
393 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
395 } else if(last_displayCount == 1 && displayCount == 2) {
396 sprintf(c, GETMSG(DT_catd, 12, 2, "Attachments"));
397 XtVaSetValues(_attachments_label,
398 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
401 if(last_displayCount != displayCount) {
402 sprintf(c, GETMSG(DT_catd, 12, 3, "displayCount"));
403 XtVaSetValues(_no_attachments_label,
404 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
407 sprintf(c, "(%s),", calcKbytes(attachmentsSize));
408 XtVaSetValues(_size_attachments_label,
409 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
412 if(last_selectedCount != _iconSelectedCount) {
413 sprintf(c, "%d", _iconSelectedCount);
414 XtVaSetValues(_no_selected_label,
415 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
417 sprintf(c, "(%s)", calcKbytes(getSelectedAttachmentsSize()));
418 XtVaSetValues(_size_selected_label,
419 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
422 if(!XtIsManaged(_no_attachments_label)) {
423 XtManageChild(_no_attachments_label);
424 XtManageChild(_attachments_label);
425 XtManageChild(_size_attachments_label);
426 XtManageChild(_no_selected_label);
427 XtManageChild(_selected_label);
428 XtManageChild(_size_selected_label);
433 #endif /* DEAD_WOOD */
435 int AttachArea::getSelectedIconCount()
437 Attachment **list = getList();
438 int num_selected = 0;
440 for (int i = 0; i < getIconCount(); i++) {
441 if (!list[i]->isDeleted() && list[i]->isSelected())
444 return (num_selected);
448 void AttachArea::CalcAttachmentsSize( )
450 Attachment **list = getList();
451 unsigned int total = 0;
454 int num_icons = getIconCount();
457 for(i=0;i<num_icons;i++)
458 if(!list[i]->isDeleted())
459 total += (unsigned int)list[i]->getContentsSize();
461 setAttachmentsSize(total);
463 #endif /* DEAD_WOOD */
466 AttachArea::getSelectedAttachment()
468 return _cache_single_attachment;
473 AttachArea::MenuButtonHandler(
479 AttachArea *obj = (AttachArea *)cd;
481 if(event->xany.type != ButtonPress)
484 XButtonEvent *be = (XButtonEvent *)event;
486 if(be->button == theApplication->bMenuButton())
487 obj->_myOwner->owner()->postAttachmentPopup(event);
491 AttachArea::inputCallback(Widget, XtPointer client_data, XtPointer call_data)
493 AttachArea *obj = (AttachArea *) client_data;
494 XmDrawingAreaCallbackStruct *cb = (XmDrawingAreaCallbackStruct *)call_data;
496 if(cb->reason != XmCR_INPUT ||
497 cb->event->xany.type != ButtonPress)
500 if(((XButtonEvent *)cb->event)->button == Button1)
501 obj->unselectOtherSelectedAttachments(NULL);
504 void AttachArea::resizeCallback (
506 XtPointer clientData,
512 AttachArea *obj = (AttachArea *) clientData;
519 obj->resize((Dimension)wid);
522 void AttachArea::resize(
527 Attachment **list = getList();
529 _attachAreaWidth = wid;
530 XtVaSetValues(_clipWindow, XmNwidth, _attachAreaWidth, NULL);
532 for (i=0; i<getIconCount(); i++)
533 list[i]->unmanageIconWidget();
535 CalcAllAttachmentPositions();
538 SetScrollBarSize(getLastRow()+1);
539 DisplayAttachmentsInRow(_currentRow);
542 void AttachArea::CalcSizeOfAttachPane( )
544 _attachAreaWidth = _myOwner->textEditor()->get_text_width();
545 XtVaSetValues(_clipWindow, XmNwidth, _attachAreaWidth, NULL);
548 void AttachArea::activateDeactivate()
551 // If exactly one icon is selected then activate the open command
554 if(getIconSelectedCount() == 1) {
555 openCmd()->activate();
557 openCmd()->deactivate();
560 // If no icons are selected then deactivate the OK button on the FS Dialog
562 if(getIconSelectedCount() > 0) {
565 XmSelectionBoxGetChild(
566 getFsDialog(), XmDIALOG_OK_BUTTON), TRUE
571 XmSelectionBoxGetChild(
572 getFsDialog(), XmDIALOG_OK_BUTTON
574 (getFsState() == SAVEAS) ? FALSE : TRUE
579 // Used by Compose window (SMD)
580 // Given a filename, add it to message and to attachArea.
583 AttachArea::addAttachment(
584 DtMail::Message* msg,
585 DtMail::BodyPart *lastAttBP,
592 Boolean validtype = TRUE;
593 DtMail::BodyPart * bp = NULL;
594 DtMailEnv mail_error;
600 char *errormsg = new char[512];
601 char *buf = new char[2048];
602 char *buffer = NULL, *lbl;
605 for (fname_start = filename + strlen(filename) - 1;
606 fname_start >= filename && *fname_start != '/'; fname_start--) {
609 if (*fname_start == '/') {
613 bp = msg->newBodyPart(mail_error, lastAttBP);
615 if (SafeAccess(filename, F_OK) != 0) {
616 sprintf(buf, GETMSG(DT_catd, 3, 34, "%s does not exist."),
618 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 81, "Mailer"),
625 SafeStat(filename, &s);
627 if(S_ISFIFO(s.st_mode)) {
629 GETMSG(DT_catd, 12, 4, "Cannot attach FIFO files: %s"), filename);
631 } else if(S_ISCHR(s.st_mode)) {
634 GETMSG(DT_catd, 12, 5, "Cannot attach character special files: %s"), filename
637 } else if(S_ISDIR(s.st_mode)) {
640 GETMSG(DT_catd, 12, 6, "Cannot attach directories: %s"), filename
643 } else if(S_ISBLK(s.st_mode)) {
645 GETMSG(DT_catd, 12, 7, "Cannot attach block special files: %s"), filename
648 } else if(S_ISSOCK(s.st_mode)) {
650 GETMSG(DT_catd, 12, 8, "Cannot attach socket files: %s"), filename
654 if(validtype == FALSE) {
655 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 81, "Mailer"),
663 fd = SafeOpen(filename, O_RDONLY);
666 sprintf(buf, GETMSG(DT_catd, 3, 35, "Unable to open %s."), filename);
667 helpId = DTMAILHELPNOOPEN;
668 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 82, "Mailer"),
676 int page_size = (int)sysconf(_SC_PAGESIZE);
677 size_t map_size = (size_t) (s.st_size +
678 (page_size - (s.st_size % page_size)));
682 // This version of mmap does NOT allow requested length to be
683 // greater than the file size ... in contradiction to the
684 // documentation (don't round up).
685 map = (char *) mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
687 map = (char *) mmap(0, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
690 if (map == (char *)-1) {
691 // We could not map it for some reason. Let's just read it into
692 // buffer and pass it to XmText.
695 buffer = new char[s.st_size + 1];
699 GETMSG(DT_catd, 3, 36, "Unable to allocate memory."));
700 helpId = DTMAILHELPNOALLOCMEM;
701 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 83, "Mailer"),
707 if (read(fd, buffer, (unsigned int) s.st_size) < 0) {
714 buffer[s.st_size] = 0;
716 mail_error, buffer, s.st_size, NULL, fname_start, 0, NULL
720 // We now have a mapped file. XmText wants a zero terminated
721 // buffer. We get luck with mmap because unless the file is
722 // an even page size, we will have some zero fill bytes that
723 // are legal to access.
725 // Of course in the case of an even page size file we must
726 // copy the buffer, terminate it and then give it to XmText.
729 mail_error, map, s.st_size, NULL, fname_start, 0, NULL
731 munmap(map, map_size);
736 // _iconCount + 1 because iconCount starts at 0 and we want
737 // attachmentCount to begin at 1. attachmentCount is set to be
738 // in the widget's userData.
744 if(strchr(filename, '/') == NULL) // The name does not include a slash
745 lbl = strdup(filename);
746 else // The name does include a slash
747 lbl = strdup(strrchr(filename, '/')+1);
749 Attachment *attachment = new Attachment(this, lbl, bp, _iconCount + 1);
750 attachment->setAttachArea(this);
751 attachment->initialize();
752 addToList( attachment );
754 // Update the display. The Compose Window needs immediate update.
764 AttachArea::addAttachment(
765 DtMail::Message *msg,
766 DtMail::BodyPart *lastAttBP,
771 DtMailEnv mail_error;
772 DtMail::BodyPart * bp = NULL;
779 bp = msg->newBodyPart(mail_error, lastAttBP);
780 bp->setContents(mail_error, buf.buffer, buf.size, NULL, name, 0, NULL);
782 Attachment *attachment = new Attachment(this,
786 attachment->setAttachArea(this);
787 attachment->initialize();
788 addToList(attachment);
790 // Update the display. The Compose Window needs immediate update.
798 AttachArea::addAttachment(
800 DtMail::BodyPart *body_part
803 // _iconCount + 1 because iconCount starts at 0 and we want
804 // attachmentCount to begin at 1. attachmentCount is set to be
805 // in the widget's userData.
807 Attachment *attachment = new Attachment(
813 attachment->setAttachArea(this);
814 attachment->initialize();
815 addToList( attachment );
822 AttachArea::add_attachment(
823 Attachment *attachment
827 attachment->setAttachArea(this);
828 attachment->initialize();
829 addToList( attachment );
833 // This function truly deletes all the attachments in the AttachArea
834 // The widgets are unmanaged and the attachment classes are deleted.
837 void AttachArea::deleteAttachments( )
840 WidgetList deleteList;
843 Attachment **list = getList();
845 // First, unmanaged all the attachment at once so there is no
846 // flickering when we delete them
848 deleteList = (WidgetList)XtMalloc(sizeof(Widget) * getIconCount());
850 for(i=0;i<getIconCount();i++)
851 deleteList[i] = list[i]->baseWidget();
852 XtUnmanageChildren(deleteList, i);
855 XtFree((char *)deleteList);
857 // Delete each attachment in the list
858 count = getIconCount();
859 for(i=count-1;i>=0;i--) {
865 _iconSelectedCount = 0;
869 SetScrollBarSize(getLastRow()+1);
870 activateDeactivate();
871 _attachmentList=NULL;
872 _attachmentsSize = 0;
873 _selectedAttachmentsSize = 0;
875 #endif /* DEAD_WOOD */
877 void AttachArea::manageList( )
880 Attachment **list = getList();
882 for (i=0; i<getIconCount(); i++)
883 list[i]->unmanageIconWidget();
885 CalcAllAttachmentPositions();
888 SetScrollBarSize(getLastRow()+1);
889 DisplayAttachmentsInRow(_currentRow);
894 // Find the x and y position for a newly created attachment
897 void AttachArea::CalcAttachmentPosition(Attachment *item)
900 Boolean found_managed = FALSE;
902 Attachment **list = getList();
903 for(i=0, j=0;i<getIconCount();i++)
904 if(!list[i]->isDeleted()) {
906 found_managed = TRUE;
908 calculate_attachment_position(
909 found_managed ? list[j] : (Attachment *)NULL, item
913 #endif /* DEAD_WOOD */
916 // Display the attachments in row X
919 void AttachArea::DisplayAttachmentsInRow(unsigned int X)
922 int managecount, unmanagecount;
924 Attachment **list = getList();
925 WidgetList manageIconList, unmanageIconList;
929 manageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
930 unmanageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
932 managecount = unmanagecount = 0;
933 for(i=0;i<getIconCount();i++) {
934 if(!list[i]->isDeleted()) {
935 if(list[i]->getRow() == X) {
936 if(!list[i]->isManaged()) {
937 manageIconList[managecount] = list[i]->baseWidget();
942 if(list[i]->isManaged()) {
943 unmanageIconList[unmanagecount] = list[i]->baseWidget();
950 XtUnmanageChildren(unmanageIconList, unmanagecount);
951 XtManageChildren(manageIconList, managecount);
954 XtFree((char *)manageIconList);
955 XtFree((char *)unmanageIconList);
958 this->attachment_summary(_iconCount - _deleteCount, _deleteCount);
962 // Calculate the position of every non-deleted Attachment
965 void AttachArea::CalcAllAttachmentPositions()
968 Attachment **list = getList();
971 for(i=0;i<getIconCount();i++) {
972 if(!list[i]->isDeleted()) {
973 calculate_attachment_position(
974 (j == -1) ? (Attachment *)NULL : list[j],
982 // Determine the position of attachment "item" given reference
986 void AttachArea::calculate_attachment_position(
997 if(((Dimension)(ref->getX() +
1000 item->getWidth())) > getAAWidth() ) {
1003 item->setRow(ref->getRow() + 1);
1005 item->setX(ref->getX() + ref->getWidth() + HSPACE);
1006 item->setRow(ref->getRow());
1012 // Invoked when the user moves the slider by any method
1013 // If the user is dragging the slider then this callback
1014 // is only invoked when the user releases the mouse button
1017 void AttachArea::valueChangedCallback (
1019 XtPointer clientData,
1023 AttachArea *obj = (AttachArea *) clientData;
1025 obj->valueChanged( callData );
1028 void AttachArea::valueChanged( XtPointer callData )
1030 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
1032 _currentRow = cbs->value;
1033 DisplayAttachmentsInRow(_currentRow);
1037 // Invoked when the user drags the slider
1040 void AttachArea::dragCallback (
1042 XtPointer clientData,
1046 AttachArea *obj = (AttachArea *) clientData;
1048 obj->dragSlider( callData );
1051 void AttachArea::dragSlider( XtPointer callData )
1053 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
1055 if(cbs->value == _currentRow)
1057 _currentRow = cbs->value;
1058 DisplayAttachmentsInRow(_currentRow);
1062 // Calculate the number of rows
1065 void AttachArea::CalcLastRow()
1069 Attachment **list = getList();
1071 for(i=0;i<getIconCount();i++) {
1072 if(!list[i]->isDeleted()) {
1073 row = list[i]->getRow();
1080 // Set the XmmNmaximum resource to size
1083 void AttachArea::SetScrollBarSize(unsigned int size)
1091 // If the current row is greater than the last row, adjust the
1092 // current row to be equal to the last row.
1095 void AttachArea::AdjustCurrentRow()
1097 if(_currentRow > _lastRow) {
1098 _currentRow = _lastRow;
1099 XtVaSetValues(_vsb, XmNvalue, _currentRow, NULL);
1104 AttachArea::getSelectedAttachName()
1106 XmString str = (XmString)NULL;
1108 if(_cache_single_attachment)
1109 str = _cache_single_attachment->getLabel();
1115 AttachArea::setSelectedAttachName(
1120 Boolean set = FALSE;
1121 Attachment **list = this->getList();
1123 XmString nn = XmStringCopy(new_name);
1125 // Set name of first selected attachment to new_name
1126 for(i=0;i<this->getIconCount() && !set;i++)
1127 if(list[i]->isSelected()) {
1128 list[i]->rename(nn);
1136 AttachArea::attachmentSelected(
1137 Attachment *attachment
1140 // First deselect other selected attachments
1141 this->unselectOtherSelectedAttachments(attachment);
1143 // Enable the menu item at the toplevel shell's menubar.
1144 if(_cache_single_attachment == NULL)
1145 _myOwner->owner()->attachment_selected();
1147 // Cache the single selected attachment
1148 _cache_single_attachment = attachment;
1149 _attach_area_selection_state = AA_SEL_SINGLE;
1153 AttachArea::attachmentFeedback(
1157 _myOwner->owner()->attachmentFeedback(value);
1161 AttachArea::calcKbytes(unsigned int bytes)
1163 static char kstring[64];
1166 sprintf(kstring, "%d bytes",bytes);
1167 else if(bytes < 1024)
1168 sprintf(kstring, " .%dk", bytes/103);
1170 sprintf(kstring, "%dk", bytes/1024);
1176 AttachArea::addToRowOfAttachmentsStatus()
1180 // Size of first label
1182 labelStr2 = XmStringCreateLocalized(
1183 GETMSG(DT_catd, 3, 37, "Summary of attachments"));
1186 _attachments_summary = XtCreateManagedWidget("Attachments_Summary",
1188 rowOfAttachmentsStatus, NULL, 0);
1190 XtVaSetValues(_attachments_summary,
1191 XmNalignment, XmALIGNMENT_END,
1192 XmNlabelString, labelStr2,
1193 XmNrightAttachment, XmATTACH_FORM,
1196 XmStringFree(labelStr2);
1200 AttachArea::parseAttachments(
1201 DtMailEnv &mail_error,
1202 DtMail::Message* msg,
1207 DtMail::BodyPart * tmpBP;
1209 int num_attachments = 0;
1213 // First unmanage and empty out the current contents.
1215 // SMD sets this boolean to FALSE so that previous message's attachments
1216 // are not cleared. E.g. Including/forwarding multiple messages each
1217 // with attachments.
1218 // RMW sets this boolean to TRUE so that all attachments are cleared in
1219 // the attachment pane everytime a new message is displayed.
1223 // First unmanage the clipWindow.
1224 // Unmanaging the attachment pane is visually ugly
1226 XtUnmanageChild(_clipWindow);
1227 this->clearAttachArea();
1232 // Now fill list with new attachments.
1234 tmpBP = msg->getFirstBodyPart(mail_error);
1235 if (mail_error.isSet()) {
1239 // Sync up the index with the bodyPart from which to begin
1240 // adding attachments into attachPane.
1242 while (startBP > index) {
1243 tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1247 while (tmpBP != NULL) {
1258 if (mail_error.isSet()) {
1262 // It is possible for an attachment to not have a name.
1267 this->addAttachment(name, tmpBP);
1268 tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1269 if (mail_error.isSet()) {
1278 AttachArea::attachment_summary(
1288 if ((live == 1) && (dead == 0)) {
1289 tmp1 = GETMSG(DT_catd, 3, 38, "attachment");
1290 buf = new char[strlen(tmp1) + 64];
1291 sprintf(buf, "%d %s", live, tmp1);
1293 else if ((live >= 0) && (dead == 0)) {
1295 * "attachments" is the plural form of "attachment".
1297 tmp1 = GETMSG(DT_catd, 3, 39, "attachments");
1298 buf = new char[strlen(tmp1) + 64];
1299 sprintf(buf, "%d %s", live, tmp1);
1301 else if ((live >= 0) && (dead > 0)) {
1302 tmp1 = GETMSG(DT_catd, 3, 40, "attachments");
1303 tmp2 = GETMSG(DT_catd, 3, 41, "deleted");
1304 buf = new char[strlen(tmp1) + strlen(tmp2) + 64];
1305 sprintf(buf, "%d %s, %d %s", live, tmp1, dead, tmp2);
1309 XmString buf_str = XmStringCreateLocalized(buf);
1310 XtVaSetValues(_attachments_summary,
1311 XmNlabelString, buf_str,
1315 XmStringFree(buf_str);
1320 AttachArea::manage()
1322 XtArgVal /* Dimension */ ht;
1323 XtArgVal /* Dimension */ pht;
1326 // Update the display
1327 sww = getSWWindow();
1332 XmNresizeCallback, &AttachArea::resizeCallback,
1337 XmNinputCallback, &AttachArea::inputCallback,
1341 _clipWindow, ButtonPressMask,
1342 FALSE, MenuButtonHandler,
1346 XtVaGetValues(sww, XmNheight, &ht, NULL);
1347 XtVaGetValues(_w, XmNheight, &pht, NULL);
1348 // Manage the clipWindow back
1349 if (!XtIsManaged(_clipWindow)) XtManageChild(_clipWindow);
1352 XtVaSetValues(sww, XmNheight, ht, NULL);
1353 UIComponent::manage();
1354 XtVaSetValues(_w, XmNheight, pht, NULL);
1358 AttachArea::unmanage()
1361 Attachment **list = getList();
1363 // Unmanage the widgets it currently has
1364 for (i=0; i<getIconCount(); i++)
1365 list[i]->unmanageIconWidget();
1369 XmNresizeCallback, &AttachArea::resizeCallback,
1374 XmNinputCallback, &AttachArea::inputCallback,
1377 XtRemoveEventHandler(
1378 _clipWindow, ButtonPressMask,
1379 FALSE, MenuButtonHandler,
1382 UIComponent::unmanage();
1386 AttachArea::removeCurrentAttachments()
1389 Attachment **list = getList();
1392 // Unmanage the widgets it currently has
1394 for (i=0; i<getIconCount(); i++) {
1396 list[i]->unmanageIconWidget();
1397 list[i]->deleteIt();
1401 if (_attachmentList)
1402 delete []_attachmentList;
1403 _attachmentList = NULL;
1406 _attach_area_selection_state = AA_SEL_NONE;
1407 _cache_single_attachment = NULL;
1409 this->attachment_summary(_iconCount, _deleteCount);
1412 // Similar to removeCurrentAttachments().
1413 // Except we don't display a summary that there are no attachments.
1414 // Plus has potential for other (different) usage.
1417 AttachArea::clearAttachArea()
1420 Attachment **list = getList();
1423 // Unmanage the widgets it currently has
1425 for (i=0; i<getIconCount(); i++) {
1427 list[i]->unmanageIconWidget();
1432 if (_attachmentList)
1433 delete []_attachmentList;
1434 _attachmentList = NULL;
1437 _attach_area_selection_state = AA_SEL_NONE;
1438 _cache_single_attachment = NULL;
1443 AttachArea::saveAttachmentToFile(
1444 DtMailEnv &mail_error,
1449 Attachment *attachment = this->getSelectedAttachment();
1451 if(attachment != NULL)
1452 attachment->saveToFile(mail_error, save_path);
1455 #endif /* DEAD_WOOD */
1458 AttachArea::deleteSelectedAttachments(
1459 DtMailEnv & //mail_error
1462 Attachment **list = getList();
1465 for (i = 0; i<getIconCount(); i++) {
1466 if (list[i]->isSelected() && !list[i]->isDeleted()) {
1468 // unselect it first. Else, when undeleted it comes
1471 list[i]->unselect();
1472 list[i]->deleteIt();
1478 // Their positions need to get recomputed and the undeleted
1479 // ones get remanaged in manageList().
1481 for (i=0; i<getIconCount(); i++) {
1482 list[i]->unmanageIconWidget();
1485 _cache_single_attachment = NULL;
1486 _attach_area_selection_state = AA_SEL_NONE;
1494 AttachArea::undeleteAllDeletedAttachments(
1495 DtMailEnv & //mail_error
1499 #endif /* DEAD_WOOD */
1502 AttachArea::undeleteLastDeletedAttachment(
1503 DtMailEnv &mail_error
1507 Attachment *tmpAttachment;
1509 time_t time_deleted = 0, tmpTime = 0;
1512 if (_deleteCount == 0) {
1518 tmpAttachment = list[0];
1519 time_deleted = tmpAttachment->getBodyPart()->getDeleteTime(mail_error);
1520 if (mail_error.isSet()) {
1524 for (i=1; i<getIconCount(); i++) {
1525 if (list[i]->isDeleted()) {
1526 tmpTime = list[i]->getBodyPart()->getDeleteTime(mail_error);
1527 if (mail_error.isSet()) {
1530 if ( tmpTime > time_deleted) {
1531 time_deleted = tmpTime;
1532 tmpAttachment = list[i];
1537 tmpAttachment->undeleteIt();
1541 // Their positions need to get recomputed and the deleted
1542 // ones get remanaged in manageList().
1544 for (i=0; i<getIconCount(); i++) {
1545 list[i]->unmanageIconWidget();
1555 AttachArea::unselectOtherSelectedAttachments(
1556 Attachment *attachment
1559 if(_attach_area_selection_state == AA_SEL_NONE)
1562 if(_attach_area_selection_state == AA_SEL_ALL) {
1568 for (i=0; i < getIconCount(); i++)
1569 if (list[i]->isSelected() && list[i] != attachment)
1570 list[i]->unselect();
1572 else if (_cache_single_attachment &&
1573 (attachment != _cache_single_attachment)) {
1574 _cache_single_attachment->unselect();
1575 _cache_single_attachment = NULL;
1578 if(attachment == NULL) {
1579 // Grey out the appropriate menu items in the RMW...
1580 _myOwner->owner()->all_attachments_deselected();
1581 _attach_area_selection_state = AA_SEL_NONE;
1582 _cache_single_attachment = NULL;
1587 AttachArea::addAttachmentActions(
1593 _myOwner->owner()->addAttachmentActions(
1601 AttachArea::setOwnerShell(
1609 AttachArea::setOwnerShell(
1617 AttachArea::setOwnerShell(
1625 AttachArea::ownerShellWidget()
1628 return(_myRMW->baseWidget());
1631 return(_myVMD->baseWidget());
1634 return(_mySMD->baseWidget());
1639 return((Widget) NULL);
1643 AttachArea::isOwnerShellEditable()
1645 // only SMD is editable
1646 if (_mySMD != NULL) {
1655 AttachArea::setPendingAction(
1659 _pendingAction = bval;
1661 _numPendingActions++;
1664 if (_numPendingActions > 0) {
1665 _numPendingActions--;
1671 AttachArea::resetPendingAction()
1674 _numPendingActions = 0;
1678 AttachArea::getNumPendingActions()
1680 return(_numPendingActions);
1684 AttachArea::selectAllAttachments()
1688 int numAttachments = getIconCount();
1695 // if there's only 1 attachment, select it and
1696 // add its actions to the menu bar...
1698 if (numAttachments == 1) {
1699 list[0]->primitive_select();
1700 list[0]->set_selected();
1703 // More than 1 attachment.
1704 // Select them all. Don't enable their actions however.
1706 for (int i=0; i < numAttachments; i++)
1707 list[i]->primitive_select();
1709 // Grey out the appropriate menu items in the RMW...
1710 _myOwner->owner()->all_attachments_selected();
1711 _cache_single_attachment = NULL;
1712 _attach_area_selection_state = AA_SEL_ALL;
1717 AttachArea::handleQuestionDialog(
1723 DtMailGenDialog *dialog;
1727 dialog = _myRMW->genDialog();
1730 dialog = _myVMD->genDialog();
1733 dialog = _mySMD->genDialog();
1737 if (!dialog) return(-1);
1739 dialog->setToQuestionDialog(
1742 answer = dialog->post_and_return(helpId);
1747 AttachArea::handleErrorDialog(
1753 DtMailGenDialog *dialog;
1757 dialog = _myRMW->genDialog();
1760 dialog = _myVMD->genDialog();
1763 dialog = _mySMD->genDialog();
1767 if (!dialog) return(-1);
1769 dialog->setToErrorDialog(title, buf);
1770 answer = dialog->post_and_return(helpId);