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 #include <Dt/Editor.h>
52 #include <Xm/ColorObjP.h>
54 #include "EUSDebug.hh"
56 #if defined(NEED_MMAP_WRAPPER)
62 #if defined(NEED_MMAP_WRAPPER)
68 extern XtPointer _XmStringUngenerate (
72 XmTextType output_type);
79 #include <sys/types.h>
82 #include <Xm/BulletinB.h>
84 #include <Xm/RowColumn.h>
85 #include <Xm/ScrolledW.h>
86 #include <Xm/DrawingA.h>
87 #include <Xm/ScrollBar.h>
88 #include <Xm/PushBG.h>
89 #include <Xm/FileSB.h>
90 #include <Xm/SelectioB.h>
92 #include <Xm/LabelG.h>
93 #include <Xm/AtomMgr.h>
95 #include <Xm/Screen.h>
96 #include <Xm/ToggleB.h>
97 #include <X11/IntrinsicP.h>
98 #include <X11/Xatom.h>
100 #include "Attachment.h"
101 #include "AttachArea.h"
105 #include "RoamMenuWindow.h"
107 #include "MsgScrollingList.hh"
108 #include "ViewMsgDialog.h"
109 #include "SendMsgDialog.h"
110 #include "MailMsg.h" // DT_catd defined here
111 #include <DtMail/DtMail.hh> // time_t defined here
112 #include <DtMail/IO.hh> // SafeAccess...
115 #include "DtMailHelp.hh"
117 extern nl_catd DtMailMsgCat;
119 #define equal(a, b) (!strcmp(a,b))
122 #define MAXATOM 2048 // ?????
124 // This is the new one
125 AttachArea::AttachArea (
129 ) : UIComponent (name)
136 _attachmentList=NULL;
140 _iconSelectedCount = 0;
147 _attachmentsSize = 0;
148 _selectedAttachmentsSize = 0;
150 _renameDialog = NULL;
156 _pendingAction = FALSE;
157 _numPendingActions = 0;
159 _attach_area_selection_state = AA_SEL_NONE;
160 _cache_single_attachment = NULL;
162 _no_selected_label = NULL;
163 _selected_label = NULL;
164 rowOfAttachmentsStatus = NULL;
165 _attachments_status = NULL;
166 _attachments_summary = NULL;
168 _attachAreaWidth = 0;
169 _attachAreaHeight = 0;
186 _size_selected_label = NULL;
187 _format_button = NULL;
188 _descriptionDialog = NULL;
189 _no_attachments_label = NULL;
190 _attachments_label = NULL;
191 _size_attachments_label = NULL;
197 AttachArea::initialize()
200 // We're making the assumption here that this widget's parent`
203 XtWidgetGeometry size;
204 Dimension parWid, parHeight;
205 Dimension txt_w, txt_h;
210 short act, inact, prim, second, text;
211 XmPixelSet pixels[XmCO_NUM_COLORS];
214 _w = XtVaCreateManagedWidget (
216 xmFormWidgetClass, _parent,
220 XmeGetColorObjData(XtScreen(_parent), &colorUse, pixels, XmCO_NUM_COLORS,
221 &act, &inact, &prim, &second, &text);
222 _foreground = pixels[text].fg;
223 _background = pixels[text].sc;
225 parWid = _myOwner->textEditor()->get_text_width();
227 fl = _myOwner->textEditor()->get_text_fontList();
228 xms = XmStringCreateLocalized("Xyb");
229 XmStringExtent(fl, xms, &txt_w, &txt_h);
230 parHeight = txt_h + Icon::maxIconHeight() + (2*VSPACE);
232 _appBackground = _background;
233 _appForeground = _foreground;
235 _sw = XtVaCreateManagedWidget (
236 "AttachPane_ScrolledWindow",
237 xmScrolledWindowWidgetClass, _w,
238 XmNscrollingPolicy, XmAPPLICATION_DEFINED,
239 XmNrightAttachment, XmATTACH_FORM,
240 XmNleftAttachment, XmATTACH_FORM,
241 XmNtopAttachment, XmATTACH_FORM,
242 XmNshadowThickness, (Dimension)1,
245 XmNheight, parHeight,
248 rowOfAttachmentsStatus = XtCreateManagedWidget("Attachments_Status",
252 XtVaSetValues(rowOfAttachmentsStatus,
253 XmNrightAttachment, XmATTACH_FORM,
254 XmNleftAttachment, XmATTACH_FORM,
255 XmNtopAttachment, XmATTACH_WIDGET,
261 this->addToRowOfAttachmentsStatus();
263 size.request_mode = CWHeight;
264 XtQueryGeometry(rowOfAttachmentsStatus, NULL, &size);
267 rowOfAttachmentsStatus,
268 XmNpaneMaximum, size.height,
269 XmNpaneMinimum, size.height,
273 _vsb = XtVaCreateManagedWidget("vsb", xmScrollBarWidgetClass, _sw,
274 XmNorientation, XmVERTICAL,
282 XmNvalueChangedCallback,&AttachArea::valueChangedCallback,
288 XmNdragCallback, &AttachArea::dragCallback,
292 _clipWindow = XtVaCreateManagedWidget("AttachArea_clipWindow",
293 xmDrawingAreaWidgetClass, _sw,
294 XmNresizePolicy, XmRESIZE_NONE,
295 XmNbackground, _background,
297 XmNheight, parHeight,
299 XmScrolledWindowSetAreas(_sw, NULL, _vsb, _clipWindow);
301 XtManageChild(_clipWindow);
306 // Set RowCol to NULL here.
307 // It gets set in the expose_all_attachments.
311 CalcSizeOfAttachPane();
313 installDestroyHandler();
316 AttachArea::~AttachArea()
320 void AttachArea::addToList( Attachment *attachment )
322 Attachment **newList;
325 newList = new Attachment*[ _iconCount + 1 ];
326 for(i=0; i < _iconCount; i++)
327 newList[i] = _attachmentList[i];
330 delete []_attachmentList;
332 _attachmentList = newList;
334 _attachmentList[ _iconCount ] = attachment;
338 // setAttachmentsLabel();
342 void AttachArea::setAttachmentsLabel( )
344 char *c = new char[256];
347 unsigned int last_displayCount, last_selectedCount;
348 unsigned int displayCount = _iconCount - _deleteCount;
349 unsigned int attachmentsSize;
351 if((displayCount) == 0) {
352 XtUnmanageChild(_no_attachments_label);
353 XtUnmanageChild(_attachments_label);
354 XtUnmanageChild(_size_attachments_label);
355 XtUnmanageChild(_no_selected_label);
356 XtUnmanageChild(_selected_label);
357 XtUnmanageChild(_size_selected_label);
359 CalcAttachmentsSize();
360 attachmentsSize = getAttachmentsSize();
362 // Number of Attachments
363 XtVaGetValues(_no_attachments_label,
364 XmNlabelString, &xmstr,
367 str = (char *) _XmStringUngenerate(
369 XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
370 if (NULL == str) return; // internal error
371 last_displayCount = (unsigned int)strtol(str, NULL, 10);
374 // Number of Attachments Selected
375 XtVaGetValues(_no_selected_label,
376 XmNlabelString, &xmstr,
379 str = (char *) _XmStringUngenerate(
381 XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
382 if (NULL == str) return; // internal error
383 last_selectedCount = (unsigned int)strtol(str, NULL, 10);
386 if((last_displayCount == 0 && displayCount == 1) ||
387 (last_displayCount == 2 && displayCount == 1)) {
388 sprintf(c, GETMSG(DT_catd, 12, 1, "Attachment"));
389 XtVaSetValues(_attachments_label,
390 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
392 } else if(last_displayCount == 1 && displayCount == 2) {
393 sprintf(c, GETMSG(DT_catd, 12, 2, "Attachments"));
394 XtVaSetValues(_attachments_label,
395 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
398 if(last_displayCount != displayCount) {
399 sprintf(c, GETMSG(DT_catd, 12, 3, "displayCount"));
400 XtVaSetValues(_no_attachments_label,
401 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
404 sprintf(c, "(%s),", calcKbytes(attachmentsSize));
405 XtVaSetValues(_size_attachments_label,
406 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
409 if(last_selectedCount != _iconSelectedCount) {
410 sprintf(c, "%d", _iconSelectedCount);
411 XtVaSetValues(_no_selected_label,
412 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
414 sprintf(c, "(%s)", calcKbytes(getSelectedAttachmentsSize()));
415 XtVaSetValues(_size_selected_label,
416 XtVaTypedArg, XmNlabelString, XtRString, c, strlen(c)+1,
419 if(!XtIsManaged(_no_attachments_label)) {
420 XtManageChild(_no_attachments_label);
421 XtManageChild(_attachments_label);
422 XtManageChild(_size_attachments_label);
423 XtManageChild(_no_selected_label);
424 XtManageChild(_selected_label);
425 XtManageChild(_size_selected_label);
430 #endif /* DEAD_WOOD */
432 int AttachArea::getSelectedIconCount()
434 Attachment **list = getList();
435 int num_selected = 0;
437 for (int i = 0; i < getIconCount(); i++) {
438 if (!list[i]->isDeleted() && list[i]->isSelected())
441 return (num_selected);
445 void AttachArea::CalcAttachmentsSize( )
447 Attachment **list = getList();
448 unsigned int total = 0;
451 int num_icons = getIconCount();
454 for(i=0;i<num_icons;i++)
455 if(!list[i]->isDeleted())
456 total += (unsigned int)list[i]->getContentsSize();
458 setAttachmentsSize(total);
460 #endif /* DEAD_WOOD */
463 AttachArea::getSelectedAttachment()
465 return _cache_single_attachment;
470 AttachArea::MenuButtonHandler(
476 AttachArea *obj = (AttachArea *)cd;
478 if(event->xany.type != ButtonPress)
481 XButtonEvent *be = (XButtonEvent *)event;
483 if(be->button == theApplication->bMenuButton())
484 obj->_myOwner->owner()->postAttachmentPopup(event);
488 AttachArea::inputCallback(Widget, XtPointer client_data, XtPointer call_data)
490 AttachArea *obj = (AttachArea *) client_data;
491 XmDrawingAreaCallbackStruct *cb = (XmDrawingAreaCallbackStruct *)call_data;
493 if(cb->reason != XmCR_INPUT ||
494 cb->event->xany.type != ButtonPress)
497 if(((XButtonEvent *)cb->event)->button == Button1)
498 obj->unselectOtherSelectedAttachments(NULL);
501 void AttachArea::resizeCallback (
503 XtPointer clientData,
509 AttachArea *obj = (AttachArea *) clientData;
516 obj->resize((Dimension)wid);
519 void AttachArea::resize(
524 Attachment **list = getList();
526 _attachAreaWidth = wid;
527 XtVaSetValues(_clipWindow, XmNwidth, _attachAreaWidth, NULL);
529 for (i=0; i<getIconCount(); i++)
530 list[i]->unmanageIconWidget();
532 CalcAllAttachmentPositions();
535 SetScrollBarSize(getLastRow()+1);
536 DisplayAttachmentsInRow(_currentRow);
539 void AttachArea::CalcSizeOfAttachPane( )
541 _attachAreaWidth = _myOwner->textEditor()->get_text_width();
542 XtVaSetValues(_clipWindow, XmNwidth, _attachAreaWidth, NULL);
545 void AttachArea::activateDeactivate()
548 // If exactly one icon is selected then activate the open command
551 if(getIconSelectedCount() == 1) {
552 openCmd()->activate();
554 openCmd()->deactivate();
557 // If no icons are selected then deactivate the OK button on the FS Dialog
559 if(getIconSelectedCount() > 0) {
562 XmSelectionBoxGetChild(
563 getFsDialog(), XmDIALOG_OK_BUTTON), TRUE
568 XmSelectionBoxGetChild(
569 getFsDialog(), XmDIALOG_OK_BUTTON
571 (getFsState() == SAVEAS) ? FALSE : TRUE
576 // Used by Compose window (SMD)
577 // Given a filename, add it to message and to attachArea.
580 AttachArea::addAttachment(
581 DtMail::Message* msg,
582 DtMail::BodyPart *lastAttBP,
589 Boolean validtype = TRUE;
590 DtMail::BodyPart * bp = NULL;
591 DtMailEnv mail_error;
597 char *errormsg = new char[512];
598 char *buf = new char[2048];
599 char *buffer = NULL, *lbl;
602 for (fname_start = filename + strlen(filename) - 1;
603 fname_start >= filename && *fname_start != '/'; fname_start--) {
606 if (*fname_start == '/') {
610 bp = msg->newBodyPart(mail_error, lastAttBP);
612 if (SafeAccess(filename, F_OK) != 0) {
613 sprintf(buf, GETMSG(DT_catd, 3, 34, "%s does not exist."),
615 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 81, "Mailer"),
622 SafeStat(filename, &s);
624 if(S_ISFIFO(s.st_mode)) {
626 GETMSG(DT_catd, 12, 4, "Cannot attach FIFO files: %s"), filename);
628 } else if(S_ISCHR(s.st_mode)) {
631 GETMSG(DT_catd, 12, 5, "Cannot attach character special files: %s"), filename
634 } else if(S_ISDIR(s.st_mode)) {
637 GETMSG(DT_catd, 12, 6, "Cannot attach directories: %s"), filename
640 } else if(S_ISBLK(s.st_mode)) {
642 GETMSG(DT_catd, 12, 7, "Cannot attach block special files: %s"), filename
645 } else if(S_ISSOCK(s.st_mode)) {
647 GETMSG(DT_catd, 12, 8, "Cannot attach socket files: %s"), filename
651 if(validtype == FALSE) {
652 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 81, "Mailer"),
660 fd = SafeOpen(filename, O_RDONLY);
663 sprintf(buf, GETMSG(DT_catd, 3, 35, "Unable to open %s."), filename);
664 helpId = DTMAILHELPNOOPEN;
665 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 82, "Mailer"),
673 int page_size = (int)sysconf(_SC_PAGESIZE);
674 size_t map_size = (size_t) (s.st_size +
675 (page_size - (s.st_size % page_size)));
679 // This version of mmap does NOT allow requested length to be
680 // greater than the file size ... in contradiction to the
681 // documentation (don't round up).
682 map = (char *) mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
684 map = (char *) mmap(0, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
687 if (map == (char *)-1) {
688 // We could not map it for some reason. Let's just read it into
689 // buffer and pass it to XmText.
692 buffer = new char[s.st_size + 1];
696 GETMSG(DT_catd, 3, 36, "Unable to allocate memory."));
697 helpId = DTMAILHELPNOALLOCMEM;
698 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 83, "Mailer"),
704 if (read(fd, buffer, (unsigned int) s.st_size) < 0) {
711 buffer[s.st_size] = 0;
713 mail_error, buffer, s.st_size, NULL, fname_start, 0, NULL
717 // We now have a mapped file. XmText wants a zero terminated
718 // buffer. We get luck with mmap because unless the file is
719 // an even page size, we will have some zero fill bytes that
720 // are legal to access.
722 // Of course in the case of an even page size file we must
723 // copy the buffer, terminate it and then give it to XmText.
726 mail_error, map, s.st_size, NULL, fname_start, 0, NULL
728 munmap(map, map_size);
733 // _iconCount + 1 because iconCount starts at 0 and we want
734 // attachmentCount to begin at 1. attachmentCount is set to be
735 // in the widget's userData.
741 if(strchr(filename, '/') == NULL) // The name does not include a slash
742 lbl = strdup(filename);
743 else // The name does include a slash
744 lbl = strdup(strrchr(filename, '/')+1);
746 Attachment *attachment = new Attachment(this, lbl, bp, _iconCount + 1);
747 attachment->setAttachArea(this);
748 attachment->initialize();
749 addToList( attachment );
751 // Update the display. The Compose Window needs immediate update.
761 AttachArea::addAttachment(
762 DtMail::Message *msg,
763 DtMail::BodyPart *lastAttBP,
768 DtMailEnv mail_error;
769 DtMail::BodyPart * bp = NULL;
776 bp = msg->newBodyPart(mail_error, lastAttBP);
777 bp->setContents(mail_error, buf.buffer, buf.size, NULL, name, 0, NULL);
779 Attachment *attachment = new Attachment(this,
783 attachment->setAttachArea(this);
784 attachment->initialize();
785 addToList(attachment);
787 // Update the display. The Compose Window needs immediate update.
795 AttachArea::addAttachment(
797 DtMail::BodyPart *body_part
800 // _iconCount + 1 because iconCount starts at 0 and we want
801 // attachmentCount to begin at 1. attachmentCount is set to be
802 // in the widget's userData.
804 Attachment *attachment = new Attachment(
810 attachment->setAttachArea(this);
811 attachment->initialize();
812 addToList( attachment );
819 AttachArea::add_attachment(
820 Attachment *attachment
824 attachment->setAttachArea(this);
825 attachment->initialize();
826 addToList( attachment );
830 // This function truly deletes all the attachments in the AttachArea
831 // The widgets are unmanaged and the attachment classes are deleted.
834 void AttachArea::deleteAttachments( )
837 WidgetList deleteList;
840 Attachment **list = getList();
842 // First, unmanaged all the attachment at once so there is no
843 // flickering when we delete them
845 deleteList = (WidgetList)XtMalloc(sizeof(Widget) * getIconCount());
847 for(i=0;i<getIconCount();i++)
848 deleteList[i] = list[i]->baseWidget();
849 XtUnmanageChildren(deleteList, i);
852 XtFree((char *)deleteList);
854 // Delete each attachment in the list
855 count = getIconCount();
856 for(i=count-1;i>=0;i--) {
862 _iconSelectedCount = 0;
866 SetScrollBarSize(getLastRow()+1);
867 activateDeactivate();
868 _attachmentList=NULL;
869 _attachmentsSize = 0;
870 _selectedAttachmentsSize = 0;
872 #endif /* DEAD_WOOD */
874 void AttachArea::manageList( )
877 Attachment **list = getList();
879 for (i=0; i<getIconCount(); i++)
880 list[i]->unmanageIconWidget();
882 CalcAllAttachmentPositions();
885 SetScrollBarSize(getLastRow()+1);
886 DisplayAttachmentsInRow(_currentRow);
891 // Find the x and y position for a newly created attachment
894 void AttachArea::CalcAttachmentPosition(Attachment *item)
897 Boolean found_managed = FALSE;
899 Attachment **list = getList();
900 for(i=0, j=0;i<getIconCount();i++)
901 if(!list[i]->isDeleted()) {
903 found_managed = TRUE;
905 calculate_attachment_position(
906 found_managed ? list[j] : (Attachment *)NULL, item
910 #endif /* DEAD_WOOD */
913 // Display the attachments in row X
916 void AttachArea::DisplayAttachmentsInRow(unsigned int X)
919 int managecount, unmanagecount;
921 Attachment **list = getList();
922 WidgetList manageIconList, unmanageIconList;
926 manageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
927 unmanageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
929 managecount = unmanagecount = 0;
930 for(i=0;i<getIconCount();i++) {
931 if(!list[i]->isDeleted()) {
932 if(list[i]->getRow() == X) {
933 if(!list[i]->isManaged()) {
934 manageIconList[managecount] = list[i]->baseWidget();
939 if(list[i]->isManaged()) {
940 unmanageIconList[unmanagecount] = list[i]->baseWidget();
947 XtUnmanageChildren(unmanageIconList, unmanagecount);
948 XtManageChildren(manageIconList, managecount);
951 XtFree((char *)manageIconList);
952 XtFree((char *)unmanageIconList);
955 this->attachment_summary(_iconCount - _deleteCount, _deleteCount);
959 // Calculate the position of every non-deleted Attachment
962 void AttachArea::CalcAllAttachmentPositions()
965 Attachment **list = getList();
968 for(i=0;i<getIconCount();i++) {
969 if(!list[i]->isDeleted()) {
970 calculate_attachment_position(
971 (j == -1) ? (Attachment *)NULL : list[j],
979 // Determine the position of attachment "item" given reference
983 void AttachArea::calculate_attachment_position(
994 if(((Dimension)(ref->getX() +
997 item->getWidth())) > getAAWidth() ) {
1000 item->setRow(ref->getRow() + 1);
1002 item->setX(ref->getX() + ref->getWidth() + HSPACE);
1003 item->setRow(ref->getRow());
1009 // Invoked when the user moves the slider by any method
1010 // If the user is dragging the slider then this callback
1011 // is only invoked when the user releases the mouse button
1014 void AttachArea::valueChangedCallback (
1016 XtPointer clientData,
1020 AttachArea *obj = (AttachArea *) clientData;
1022 obj->valueChanged( callData );
1025 void AttachArea::valueChanged( XtPointer callData )
1027 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
1029 _currentRow = cbs->value;
1030 DisplayAttachmentsInRow(_currentRow);
1034 // Invoked when the user drags the slider
1037 void AttachArea::dragCallback (
1039 XtPointer clientData,
1043 AttachArea *obj = (AttachArea *) clientData;
1045 obj->dragSlider( callData );
1048 void AttachArea::dragSlider( XtPointer callData )
1050 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
1052 if(cbs->value == _currentRow)
1054 _currentRow = cbs->value;
1055 DisplayAttachmentsInRow(_currentRow);
1059 // Calculate the number of rows
1062 void AttachArea::CalcLastRow()
1066 Attachment **list = getList();
1068 for(i=0;i<getIconCount();i++) {
1069 if(!list[i]->isDeleted()) {
1070 row = list[i]->getRow();
1077 // Set the XmmNmaximum resource to size
1080 void AttachArea::SetScrollBarSize(unsigned int size)
1088 // If the current row is greater than the last row, adjust the
1089 // current row to be equal to the last row.
1092 void AttachArea::AdjustCurrentRow()
1094 if(_currentRow > _lastRow) {
1095 _currentRow = _lastRow;
1096 XtVaSetValues(_vsb, XmNvalue, _currentRow, NULL);
1101 AttachArea::getSelectedAttachName()
1103 XmString str = (XmString)NULL;
1105 if(_cache_single_attachment)
1106 str = _cache_single_attachment->getLabel();
1112 AttachArea::setSelectedAttachName(
1117 Boolean set = FALSE;
1118 Attachment **list = this->getList();
1120 XmString nn = XmStringCopy(new_name);
1122 // Set name of first selected attachment to new_name
1123 for(i=0;i<this->getIconCount() && !set;i++)
1124 if(list[i]->isSelected()) {
1125 list[i]->rename(nn);
1133 AttachArea::attachmentSelected(
1134 Attachment *attachment
1137 // First deselect other selected attachments
1138 this->unselectOtherSelectedAttachments(attachment);
1140 // Enable the menu item at the toplevel shell's menubar.
1141 if(_cache_single_attachment == NULL)
1142 _myOwner->owner()->attachment_selected();
1144 // Cache the single selected attachment
1145 _cache_single_attachment = attachment;
1146 _attach_area_selection_state = AA_SEL_SINGLE;
1150 AttachArea::attachmentFeedback(
1154 _myOwner->owner()->attachmentFeedback(value);
1158 AttachArea::calcKbytes(unsigned int bytes)
1160 static char kstring[64];
1163 sprintf(kstring, "%d bytes",bytes);
1164 else if(bytes < 1024)
1165 sprintf(kstring, " .%dk", bytes/103);
1167 sprintf(kstring, "%dk", bytes/1024);
1173 AttachArea::addToRowOfAttachmentsStatus()
1177 // Size of first label
1179 labelStr2 = XmStringCreateLocalized(
1180 GETMSG(DT_catd, 3, 37, "Summary of attachments"));
1183 _attachments_summary = XtCreateManagedWidget("Attachments_Summary",
1185 rowOfAttachmentsStatus, NULL, 0);
1187 XtVaSetValues(_attachments_summary,
1188 XmNalignment, XmALIGNMENT_END,
1189 XmNlabelString, labelStr2,
1190 XmNrightAttachment, XmATTACH_FORM,
1193 XmStringFree(labelStr2);
1197 AttachArea::parseAttachments(
1198 DtMailEnv &mail_error,
1199 DtMail::Message* msg,
1204 DtMail::BodyPart * tmpBP;
1206 int num_attachments = 0;
1210 // First unmanage and empty out the current contents.
1212 // SMD sets this boolean to FALSE so that previous message's attachments
1213 // are not cleared. E.g. Including/forwarding multiple messages each
1214 // with attachments.
1215 // RMW sets this boolean to TRUE so that all attachments are cleared in
1216 // the attachment pane everytime a new message is displayed.
1220 // First unmanage the clipWindow.
1221 // Unmanaging the attachment pane is visually ugly
1223 XtUnmanageChild(_clipWindow);
1224 this->clearAttachArea();
1229 // Now fill list with new attachments.
1231 tmpBP = msg->getFirstBodyPart(mail_error);
1232 if (mail_error.isSet()) {
1236 // Sync up the index with the bodyPart from which to begin
1237 // adding attachments into attachPane.
1239 while (startBP > index) {
1240 tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1244 while (tmpBP != NULL) {
1255 if (mail_error.isSet()) {
1259 // It is possible for an attachment to not have a name.
1264 this->addAttachment(name, tmpBP);
1265 tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1266 if (mail_error.isSet()) {
1275 AttachArea::attachment_summary(
1285 if ((live == 1) && (dead == 0)) {
1286 tmp1 = GETMSG(DT_catd, 3, 38, "attachment");
1287 buf = new char[strlen(tmp1) + 64];
1288 sprintf(buf, "%d %s", live, tmp1);
1290 else if ((live >= 0) && (dead == 0)) {
1292 * "attachments" is the plural form of "attachment".
1294 tmp1 = GETMSG(DT_catd, 3, 39, "attachments");
1295 buf = new char[strlen(tmp1) + 64];
1296 sprintf(buf, "%d %s", live, tmp1);
1298 else if ((live >= 0) && (dead > 0)) {
1299 tmp1 = GETMSG(DT_catd, 3, 40, "attachments");
1300 tmp2 = GETMSG(DT_catd, 3, 41, "deleted");
1301 buf = new char[strlen(tmp1) + strlen(tmp2) + 64];
1302 sprintf(buf, "%d %s, %d %s", live, tmp1, dead, tmp2);
1306 XmString buf_str = XmStringCreateLocalized(buf);
1307 XtVaSetValues(_attachments_summary,
1308 XmNlabelString, buf_str,
1312 XmStringFree(buf_str);
1317 AttachArea::manage()
1319 XtArgVal /* Dimension */ ht;
1320 XtArgVal /* Dimension */ pht;
1323 // Update the display
1324 sww = getSWWindow();
1329 XmNresizeCallback, &AttachArea::resizeCallback,
1334 XmNinputCallback, &AttachArea::inputCallback,
1338 _clipWindow, ButtonPressMask,
1339 FALSE, MenuButtonHandler,
1343 XtVaGetValues(sww, XmNheight, &ht, NULL);
1344 XtVaGetValues(_w, XmNheight, &pht, NULL);
1345 // Manage the clipWindow back
1346 if (!XtIsManaged(_clipWindow)) XtManageChild(_clipWindow);
1349 XtVaSetValues(sww, XmNheight, ht, NULL);
1350 UIComponent::manage();
1351 XtVaSetValues(_w, XmNheight, pht, NULL);
1355 AttachArea::unmanage()
1358 Attachment **list = getList();
1360 // Unmanage the widgets it currently has
1361 for (i=0; i<getIconCount(); i++)
1362 list[i]->unmanageIconWidget();
1366 XmNresizeCallback, &AttachArea::resizeCallback,
1371 XmNinputCallback, &AttachArea::inputCallback,
1374 XtRemoveEventHandler(
1375 _clipWindow, ButtonPressMask,
1376 FALSE, MenuButtonHandler,
1379 UIComponent::unmanage();
1383 AttachArea::removeCurrentAttachments()
1386 Attachment **list = getList();
1389 // Unmanage the widgets it currently has
1391 for (i=0; i<getIconCount(); i++) {
1393 list[i]->unmanageIconWidget();
1394 list[i]->deleteIt();
1398 if (_attachmentList)
1399 delete []_attachmentList;
1400 _attachmentList = NULL;
1403 _attach_area_selection_state = AA_SEL_NONE;
1404 _cache_single_attachment = NULL;
1406 this->attachment_summary(_iconCount, _deleteCount);
1409 // Similar to removeCurrentAttachments().
1410 // Except we don't display a summary that there are no attachments.
1411 // Plus has potential for other (different) usage.
1414 AttachArea::clearAttachArea()
1417 Attachment **list = getList();
1420 // Unmanage the widgets it currently has
1422 for (i=0; i<getIconCount(); i++) {
1424 list[i]->unmanageIconWidget();
1429 if (_attachmentList)
1430 delete []_attachmentList;
1431 _attachmentList = NULL;
1434 _attach_area_selection_state = AA_SEL_NONE;
1435 _cache_single_attachment = NULL;
1440 AttachArea::saveAttachmentToFile(
1441 DtMailEnv &mail_error,
1446 Attachment *attachment = this->getSelectedAttachment();
1448 if(attachment != NULL)
1449 attachment->saveToFile(mail_error, save_path);
1452 #endif /* DEAD_WOOD */
1455 AttachArea::deleteSelectedAttachments(
1456 DtMailEnv & //mail_error
1459 Attachment **list = getList();
1462 for (i = 0; i<getIconCount(); i++) {
1463 if (list[i]->isSelected() && !list[i]->isDeleted()) {
1465 // unselect it first. Else, when undeleted it comes
1468 list[i]->unselect();
1469 list[i]->deleteIt();
1475 // Their positions need to get recomputed and the undeleted
1476 // ones get remanaged in manageList().
1478 for (i=0; i<getIconCount(); i++) {
1479 list[i]->unmanageIconWidget();
1482 _cache_single_attachment = NULL;
1483 _attach_area_selection_state = AA_SEL_NONE;
1491 AttachArea::undeleteAllDeletedAttachments(
1492 DtMailEnv & //mail_error
1496 #endif /* DEAD_WOOD */
1499 AttachArea::undeleteLastDeletedAttachment(
1500 DtMailEnv &mail_error
1504 Attachment *tmpAttachment;
1506 time_t time_deleted = 0, tmpTime = 0;
1509 if (_deleteCount == 0) {
1515 tmpAttachment = list[0];
1516 time_deleted = tmpAttachment->getBodyPart()->getDeleteTime(mail_error);
1517 if (mail_error.isSet()) {
1521 for (i=1; i<getIconCount(); i++) {
1522 if (list[i]->isDeleted()) {
1523 tmpTime = list[i]->getBodyPart()->getDeleteTime(mail_error);
1524 if (mail_error.isSet()) {
1527 if ( tmpTime > time_deleted) {
1528 time_deleted = tmpTime;
1529 tmpAttachment = list[i];
1534 tmpAttachment->undeleteIt();
1538 // Their positions need to get recomputed and the deleted
1539 // ones get remanaged in manageList().
1541 for (i=0; i<getIconCount(); i++) {
1542 list[i]->unmanageIconWidget();
1552 AttachArea::unselectOtherSelectedAttachments(
1553 Attachment *attachment
1556 if(_attach_area_selection_state == AA_SEL_NONE)
1559 if(_attach_area_selection_state == AA_SEL_ALL) {
1565 for (i=0; i < getIconCount(); i++)
1566 if (list[i]->isSelected() && list[i] != attachment)
1567 list[i]->unselect();
1569 else if (_cache_single_attachment &&
1570 (attachment != _cache_single_attachment)) {
1571 _cache_single_attachment->unselect();
1572 _cache_single_attachment = NULL;
1575 if(attachment == NULL) {
1576 // Grey out the appropriate menu items in the RMW...
1577 _myOwner->owner()->all_attachments_deselected();
1578 _attach_area_selection_state = AA_SEL_NONE;
1579 _cache_single_attachment = NULL;
1584 AttachArea::addAttachmentActions(
1590 _myOwner->owner()->addAttachmentActions(
1598 AttachArea::setOwnerShell(
1606 AttachArea::setOwnerShell(
1614 AttachArea::setOwnerShell(
1622 AttachArea::ownerShellWidget()
1625 return(_myRMW->baseWidget());
1628 return(_myVMD->baseWidget());
1631 return(_mySMD->baseWidget());
1636 return((Widget) NULL);
1640 AttachArea::isOwnerShellEditable()
1642 // only SMD is editable
1643 if (_mySMD != NULL) {
1652 AttachArea::setPendingAction(
1656 _pendingAction = bval;
1658 _numPendingActions++;
1661 if (_numPendingActions > 0) {
1662 _numPendingActions--;
1668 AttachArea::resetPendingAction()
1671 _numPendingActions = 0;
1675 AttachArea::getNumPendingActions()
1677 return(_numPendingActions);
1681 AttachArea::selectAllAttachments()
1685 int numAttachments = getIconCount();
1692 // if there's only 1 attachment, select it and
1693 // add its actions to the menu bar...
1695 if (numAttachments == 1) {
1696 list[0]->primitive_select();
1697 list[0]->set_selected();
1700 // More than 1 attachment.
1701 // Select them all. Don't enable their actions however.
1703 for (int i=0; i < numAttachments; i++)
1704 list[i]->primitive_select();
1706 // Grey out the appropriate menu items in the RMW...
1707 _myOwner->owner()->all_attachments_selected();
1708 _cache_single_attachment = NULL;
1709 _attach_area_selection_state = AA_SEL_ALL;
1714 AttachArea::handleQuestionDialog(
1720 DtMailGenDialog *dialog;
1724 dialog = _myRMW->genDialog();
1727 dialog = _myVMD->genDialog();
1730 dialog = _mySMD->genDialog();
1734 if (!dialog) return(-1);
1736 dialog->setToQuestionDialog(
1739 answer = dialog->post_and_return(helpId);
1744 AttachArea::handleErrorDialog(
1750 DtMailGenDialog *dialog;
1754 dialog = _myRMW->genDialog();
1757 dialog = _myVMD->genDialog();
1760 dialog = _mySMD->genDialog();
1764 if (!dialog) return(-1);
1766 dialog->setToErrorDialog(title, buf);
1767 answer = dialog->post_and_return(helpId);