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)));
678 map = (char *) mmap(0, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
680 if (map == (char *)-1) {
681 // We could not map it for some reason. Let's just read it into
682 // buffer and pass it to XmText.
685 buffer = new char[s.st_size + 1];
689 GETMSG(DT_catd, 3, 36, "Unable to allocate memory."));
690 helpId = DTMAILHELPNOALLOCMEM;
691 answer = this->handleErrorDialog(GETMSG(DT_catd, 1, 83, "Mailer"),
697 if (read(fd, buffer, (unsigned int) s.st_size) < 0) {
704 buffer[s.st_size] = 0;
706 mail_error, buffer, s.st_size, NULL, fname_start, 0, NULL
710 // We now have a mapped file. XmText wants a zero terminated
711 // buffer. We get luck with mmap because unless the file is
712 // an even page size, we will have some zero fill bytes that
713 // are legal to access.
715 // Of course in the case of an even page size file we must
716 // copy the buffer, terminate it and then give it to XmText.
719 mail_error, map, s.st_size, NULL, fname_start, 0, NULL
721 munmap(map, map_size);
726 // _iconCount + 1 because iconCount starts at 0 and we want
727 // attachmentCount to begin at 1. attachmentCount is set to be
728 // in the widget's userData.
734 if(strchr(filename, '/') == NULL) // The name does not include a slash
735 lbl = strdup(filename);
736 else // The name does include a slash
737 lbl = strdup(strrchr(filename, '/')+1);
739 Attachment *attachment = new Attachment(this, lbl, bp, _iconCount + 1);
740 attachment->setAttachArea(this);
741 attachment->initialize();
742 addToList( attachment );
744 // Update the display. The Compose Window needs immediate update.
754 AttachArea::addAttachment(
755 DtMail::Message *msg,
756 DtMail::BodyPart *lastAttBP,
761 DtMailEnv mail_error;
762 DtMail::BodyPart * bp = NULL;
769 bp = msg->newBodyPart(mail_error, lastAttBP);
770 bp->setContents(mail_error, buf.buffer, buf.size, NULL, name, 0, NULL);
772 Attachment *attachment = new Attachment(this,
776 attachment->setAttachArea(this);
777 attachment->initialize();
778 addToList(attachment);
780 // Update the display. The Compose Window needs immediate update.
788 AttachArea::addAttachment(
790 DtMail::BodyPart *body_part
793 // _iconCount + 1 because iconCount starts at 0 and we want
794 // attachmentCount to begin at 1. attachmentCount is set to be
795 // in the widget's userData.
797 Attachment *attachment = new Attachment(
803 attachment->setAttachArea(this);
804 attachment->initialize();
805 addToList( attachment );
812 AttachArea::add_attachment(
813 Attachment *attachment
817 attachment->setAttachArea(this);
818 attachment->initialize();
819 addToList( attachment );
823 // This function truly deletes all the attachments in the AttachArea
824 // The widgets are unmanaged and the attachment classes are deleted.
827 void AttachArea::deleteAttachments( )
830 WidgetList deleteList;
833 Attachment **list = getList();
835 // First, unmanaged all the attachment at once so there is no
836 // flickering when we delete them
838 deleteList = (WidgetList)XtMalloc(sizeof(Widget) * getIconCount());
840 for(i=0;i<getIconCount();i++)
841 deleteList[i] = list[i]->baseWidget();
842 XtUnmanageChildren(deleteList, i);
845 XtFree((char *)deleteList);
847 // Delete each attachment in the list
848 count = getIconCount();
849 for(i=count-1;i>=0;i--) {
855 _iconSelectedCount = 0;
859 SetScrollBarSize(getLastRow()+1);
860 activateDeactivate();
861 _attachmentList=NULL;
862 _attachmentsSize = 0;
863 _selectedAttachmentsSize = 0;
865 #endif /* DEAD_WOOD */
867 void AttachArea::manageList( )
870 Attachment **list = getList();
872 for (i=0; i<getIconCount(); i++)
873 list[i]->unmanageIconWidget();
875 CalcAllAttachmentPositions();
878 SetScrollBarSize(getLastRow()+1);
879 DisplayAttachmentsInRow(_currentRow);
884 // Find the x and y position for a newly created attachment
887 void AttachArea::CalcAttachmentPosition(Attachment *item)
890 Boolean found_managed = FALSE;
892 Attachment **list = getList();
893 for(i=0, j=0;i<getIconCount();i++)
894 if(!list[i]->isDeleted()) {
896 found_managed = TRUE;
898 calculate_attachment_position(
899 found_managed ? list[j] : (Attachment *)NULL, item
903 #endif /* DEAD_WOOD */
906 // Display the attachments in row X
909 void AttachArea::DisplayAttachmentsInRow(unsigned int X)
912 int managecount, unmanagecount;
914 Attachment **list = getList();
915 WidgetList manageIconList, unmanageIconList;
919 manageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
920 unmanageIconList = (WidgetList) XtMalloc(sizeof(Widget)*getIconCount());
922 managecount = unmanagecount = 0;
923 for(i=0;i<getIconCount();i++) {
924 if(!list[i]->isDeleted()) {
925 if(list[i]->getRow() == X) {
926 if(!list[i]->isManaged()) {
927 manageIconList[managecount] = list[i]->baseWidget();
932 if(list[i]->isManaged()) {
933 unmanageIconList[unmanagecount] = list[i]->baseWidget();
940 XtUnmanageChildren(unmanageIconList, unmanagecount);
941 XtManageChildren(manageIconList, managecount);
944 XtFree((char *)manageIconList);
945 XtFree((char *)unmanageIconList);
948 this->attachment_summary(_iconCount - _deleteCount, _deleteCount);
952 // Calculate the position of every non-deleted Attachment
955 void AttachArea::CalcAllAttachmentPositions()
958 Attachment **list = getList();
961 for(i=0;i<getIconCount();i++) {
962 if(!list[i]->isDeleted()) {
963 calculate_attachment_position(
964 (j == -1) ? (Attachment *)NULL : list[j],
972 // Determine the position of attachment "item" given reference
976 void AttachArea::calculate_attachment_position(
987 if(((Dimension)(ref->getX() +
990 item->getWidth())) > getAAWidth() ) {
993 item->setRow(ref->getRow() + 1);
995 item->setX(ref->getX() + ref->getWidth() + HSPACE);
996 item->setRow(ref->getRow());
1002 // Invoked when the user moves the slider by any method
1003 // If the user is dragging the slider then this callback
1004 // is only invoked when the user releases the mouse button
1007 void AttachArea::valueChangedCallback (
1009 XtPointer clientData,
1013 AttachArea *obj = (AttachArea *) clientData;
1015 obj->valueChanged( callData );
1018 void AttachArea::valueChanged( XtPointer callData )
1020 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
1022 _currentRow = cbs->value;
1023 DisplayAttachmentsInRow(_currentRow);
1027 // Invoked when the user drags the slider
1030 void AttachArea::dragCallback (
1032 XtPointer clientData,
1036 AttachArea *obj = (AttachArea *) clientData;
1038 obj->dragSlider( callData );
1041 void AttachArea::dragSlider( XtPointer callData )
1043 XmScrollBarCallbackStruct *cbs = (XmScrollBarCallbackStruct *)callData;
1045 if(cbs->value == _currentRow)
1047 _currentRow = cbs->value;
1048 DisplayAttachmentsInRow(_currentRow);
1052 // Calculate the number of rows
1055 void AttachArea::CalcLastRow()
1059 Attachment **list = getList();
1061 for(i=0;i<getIconCount();i++) {
1062 if(!list[i]->isDeleted()) {
1063 row = list[i]->getRow();
1070 // Set the XmmNmaximum resource to size
1073 void AttachArea::SetScrollBarSize(unsigned int size)
1081 // If the current row is greater than the last row, adjust the
1082 // current row to be equal to the last row.
1085 void AttachArea::AdjustCurrentRow()
1087 if(_currentRow > _lastRow) {
1088 _currentRow = _lastRow;
1089 XtVaSetValues(_vsb, XmNvalue, _currentRow, NULL);
1094 AttachArea::getSelectedAttachName()
1096 XmString str = (XmString)NULL;
1098 if(_cache_single_attachment)
1099 str = _cache_single_attachment->getLabel();
1105 AttachArea::setSelectedAttachName(
1110 Boolean set = FALSE;
1111 Attachment **list = this->getList();
1113 XmString nn = XmStringCopy(new_name);
1115 // Set name of first selected attachment to new_name
1116 for(i=0;i<this->getIconCount() && !set;i++)
1117 if(list[i]->isSelected()) {
1118 list[i]->rename(nn);
1126 AttachArea::attachmentSelected(
1127 Attachment *attachment
1130 // First deselect other selected attachments
1131 this->unselectOtherSelectedAttachments(attachment);
1133 // Enable the menu item at the toplevel shell's menubar.
1134 if(_cache_single_attachment == NULL)
1135 _myOwner->owner()->attachment_selected();
1137 // Cache the single selected attachment
1138 _cache_single_attachment = attachment;
1139 _attach_area_selection_state = AA_SEL_SINGLE;
1143 AttachArea::attachmentFeedback(
1147 _myOwner->owner()->attachmentFeedback(value);
1151 AttachArea::calcKbytes(unsigned int bytes)
1153 static char kstring[64];
1156 sprintf(kstring, "%d bytes",bytes);
1157 else if(bytes < 1024)
1158 sprintf(kstring, " .%dk", bytes/103);
1160 sprintf(kstring, "%dk", bytes/1024);
1166 AttachArea::addToRowOfAttachmentsStatus()
1170 // Size of first label
1172 labelStr2 = XmStringCreateLocalized(
1173 GETMSG(DT_catd, 3, 37, "Summary of attachments"));
1176 _attachments_summary = XtCreateManagedWidget("Attachments_Summary",
1178 rowOfAttachmentsStatus, NULL, 0);
1180 XtVaSetValues(_attachments_summary,
1181 XmNalignment, XmALIGNMENT_END,
1182 XmNlabelString, labelStr2,
1183 XmNrightAttachment, XmATTACH_FORM,
1186 XmStringFree(labelStr2);
1190 AttachArea::parseAttachments(
1191 DtMailEnv &mail_error,
1192 DtMail::Message* msg,
1197 DtMail::BodyPart * tmpBP;
1199 int num_attachments = 0;
1203 // First unmanage and empty out the current contents.
1205 // SMD sets this boolean to FALSE so that previous message's attachments
1206 // are not cleared. E.g. Including/forwarding multiple messages each
1207 // with attachments.
1208 // RMW sets this boolean to TRUE so that all attachments are cleared in
1209 // the attachment pane everytime a new message is displayed.
1213 // First unmanage the clipWindow.
1214 // Unmanaging the attachment pane is visually ugly
1216 XtUnmanageChild(_clipWindow);
1217 this->clearAttachArea();
1222 // Now fill list with new attachments.
1224 tmpBP = msg->getFirstBodyPart(mail_error);
1225 if (mail_error.isSet()) {
1229 // Sync up the index with the bodyPart from which to begin
1230 // adding attachments into attachPane.
1232 while (startBP > index) {
1233 tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1237 while (tmpBP != NULL) {
1248 if (mail_error.isSet()) {
1252 // It is possible for an attachment to not have a name.
1257 this->addAttachment(name, tmpBP);
1258 tmpBP = msg->getNextBodyPart(mail_error, tmpBP);
1259 if (mail_error.isSet()) {
1268 AttachArea::attachment_summary(
1278 if ((live == 1) && (dead == 0)) {
1279 tmp1 = GETMSG(DT_catd, 3, 38, "attachment");
1280 buf = new char[strlen(tmp1) + 64];
1281 sprintf(buf, "%d %s", live, tmp1);
1283 else if ((live >= 0) && (dead == 0)) {
1285 * "attachments" is the plural form of "attachment".
1287 tmp1 = GETMSG(DT_catd, 3, 39, "attachments");
1288 buf = new char[strlen(tmp1) + 64];
1289 sprintf(buf, "%d %s", live, tmp1);
1291 else if ((live >= 0) && (dead > 0)) {
1292 tmp1 = GETMSG(DT_catd, 3, 40, "attachments");
1293 tmp2 = GETMSG(DT_catd, 3, 41, "deleted");
1294 buf = new char[strlen(tmp1) + strlen(tmp2) + 64];
1295 sprintf(buf, "%d %s, %d %s", live, tmp1, dead, tmp2);
1299 XmString buf_str = XmStringCreateLocalized(buf);
1300 XtVaSetValues(_attachments_summary,
1301 XmNlabelString, buf_str,
1305 XmStringFree(buf_str);
1310 AttachArea::manage()
1312 XtArgVal /* Dimension */ ht;
1313 XtArgVal /* Dimension */ pht;
1316 // Update the display
1317 sww = getSWWindow();
1322 XmNresizeCallback, &AttachArea::resizeCallback,
1327 XmNinputCallback, &AttachArea::inputCallback,
1331 _clipWindow, ButtonPressMask,
1332 FALSE, MenuButtonHandler,
1336 XtVaGetValues(sww, XmNheight, &ht, NULL);
1337 XtVaGetValues(_w, XmNheight, &pht, NULL);
1338 // Manage the clipWindow back
1339 if (!XtIsManaged(_clipWindow)) XtManageChild(_clipWindow);
1342 XtVaSetValues(sww, XmNheight, ht, NULL);
1343 UIComponent::manage();
1344 XtVaSetValues(_w, XmNheight, pht, NULL);
1348 AttachArea::unmanage()
1351 Attachment **list = getList();
1353 // Unmanage the widgets it currently has
1354 for (i=0; i<getIconCount(); i++)
1355 list[i]->unmanageIconWidget();
1359 XmNresizeCallback, &AttachArea::resizeCallback,
1364 XmNinputCallback, &AttachArea::inputCallback,
1367 XtRemoveEventHandler(
1368 _clipWindow, ButtonPressMask,
1369 FALSE, MenuButtonHandler,
1372 UIComponent::unmanage();
1376 AttachArea::removeCurrentAttachments()
1379 Attachment **list = getList();
1382 // Unmanage the widgets it currently has
1384 for (i=0; i<getIconCount(); i++) {
1386 list[i]->unmanageIconWidget();
1387 list[i]->deleteIt();
1391 if (_attachmentList)
1392 delete []_attachmentList;
1393 _attachmentList = NULL;
1396 _attach_area_selection_state = AA_SEL_NONE;
1397 _cache_single_attachment = NULL;
1399 this->attachment_summary(_iconCount, _deleteCount);
1402 // Similar to removeCurrentAttachments().
1403 // Except we don't display a summary that there are no attachments.
1404 // Plus has potential for other (different) usage.
1407 AttachArea::clearAttachArea()
1410 Attachment **list = getList();
1413 // Unmanage the widgets it currently has
1415 for (i=0; i<getIconCount(); i++) {
1417 list[i]->unmanageIconWidget();
1422 if (_attachmentList)
1423 delete []_attachmentList;
1424 _attachmentList = NULL;
1427 _attach_area_selection_state = AA_SEL_NONE;
1428 _cache_single_attachment = NULL;
1433 AttachArea::saveAttachmentToFile(
1434 DtMailEnv &mail_error,
1439 Attachment *attachment = this->getSelectedAttachment();
1441 if(attachment != NULL)
1442 attachment->saveToFile(mail_error, save_path);
1445 #endif /* DEAD_WOOD */
1448 AttachArea::deleteSelectedAttachments(
1449 DtMailEnv & //mail_error
1452 Attachment **list = getList();
1455 for (i = 0; i<getIconCount(); i++) {
1456 if (list[i]->isSelected() && !list[i]->isDeleted()) {
1458 // unselect it first. Else, when undeleted it comes
1461 list[i]->unselect();
1462 list[i]->deleteIt();
1468 // Their positions need to get recomputed and the undeleted
1469 // ones get remanaged in manageList().
1471 for (i=0; i<getIconCount(); i++) {
1472 list[i]->unmanageIconWidget();
1475 _cache_single_attachment = NULL;
1476 _attach_area_selection_state = AA_SEL_NONE;
1484 AttachArea::undeleteAllDeletedAttachments(
1485 DtMailEnv & //mail_error
1489 #endif /* DEAD_WOOD */
1492 AttachArea::undeleteLastDeletedAttachment(
1493 DtMailEnv &mail_error
1497 Attachment *tmpAttachment;
1499 time_t time_deleted = 0, tmpTime = 0;
1502 if (_deleteCount == 0) {
1508 tmpAttachment = list[0];
1509 time_deleted = tmpAttachment->getBodyPart()->getDeleteTime(mail_error);
1510 if (mail_error.isSet()) {
1514 for (i=1; i<getIconCount(); i++) {
1515 if (list[i]->isDeleted()) {
1516 tmpTime = list[i]->getBodyPart()->getDeleteTime(mail_error);
1517 if (mail_error.isSet()) {
1520 if ( tmpTime > time_deleted) {
1521 time_deleted = tmpTime;
1522 tmpAttachment = list[i];
1527 tmpAttachment->undeleteIt();
1531 // Their positions need to get recomputed and the deleted
1532 // ones get remanaged in manageList().
1534 for (i=0; i<getIconCount(); i++) {
1535 list[i]->unmanageIconWidget();
1545 AttachArea::unselectOtherSelectedAttachments(
1546 Attachment *attachment
1549 if(_attach_area_selection_state == AA_SEL_NONE)
1552 if(_attach_area_selection_state == AA_SEL_ALL) {
1558 for (i=0; i < getIconCount(); i++)
1559 if (list[i]->isSelected() && list[i] != attachment)
1560 list[i]->unselect();
1562 else if (_cache_single_attachment &&
1563 (attachment != _cache_single_attachment)) {
1564 _cache_single_attachment->unselect();
1565 _cache_single_attachment = NULL;
1568 if(attachment == NULL) {
1569 // Grey out the appropriate menu items in the RMW...
1570 _myOwner->owner()->all_attachments_deselected();
1571 _attach_area_selection_state = AA_SEL_NONE;
1572 _cache_single_attachment = NULL;
1577 AttachArea::addAttachmentActions(
1583 _myOwner->owner()->addAttachmentActions(
1591 AttachArea::setOwnerShell(
1599 AttachArea::setOwnerShell(
1607 AttachArea::setOwnerShell(
1615 AttachArea::ownerShellWidget()
1618 return(_myRMW->baseWidget());
1621 return(_myVMD->baseWidget());
1624 return(_mySMD->baseWidget());
1629 return((Widget) NULL);
1633 AttachArea::isOwnerShellEditable()
1635 // only SMD is editable
1636 if (_mySMD != NULL) {
1645 AttachArea::setPendingAction(
1649 _pendingAction = bval;
1651 _numPendingActions++;
1654 if (_numPendingActions > 0) {
1655 _numPendingActions--;
1661 AttachArea::resetPendingAction()
1664 _numPendingActions = 0;
1668 AttachArea::getNumPendingActions()
1670 return(_numPendingActions);
1674 AttachArea::selectAllAttachments()
1678 int numAttachments = getIconCount();
1685 // if there's only 1 attachment, select it and
1686 // add its actions to the menu bar...
1688 if (numAttachments == 1) {
1689 list[0]->primitive_select();
1690 list[0]->set_selected();
1693 // More than 1 attachment.
1694 // Select them all. Don't enable their actions however.
1696 for (int i=0; i < numAttachments; i++)
1697 list[i]->primitive_select();
1699 // Grey out the appropriate menu items in the RMW...
1700 _myOwner->owner()->all_attachments_selected();
1701 _cache_single_attachment = NULL;
1702 _attach_area_selection_state = AA_SEL_ALL;
1707 AttachArea::handleQuestionDialog(
1713 DtMailGenDialog *dialog;
1717 dialog = _myRMW->genDialog();
1720 dialog = _myVMD->genDialog();
1723 dialog = _mySMD->genDialog();
1727 if (!dialog) return(-1);
1729 dialog->setToQuestionDialog(
1732 answer = dialog->post_and_return(helpId);
1737 AttachArea::handleErrorDialog(
1743 DtMailGenDialog *dialog;
1747 dialog = _myRMW->genDialog();
1750 dialog = _myVMD->genDialog();
1753 dialog = _mySMD->genDialog();
1757 if (!dialog) return(-1);
1759 dialog->setToErrorDialog(title, buf);
1760 answer = dialog->post_and_return(helpId);