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 librararies 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: DtMailEditor.C /main/10 1998/07/24 16:05:41 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
48 #include <Xm/SeparatoG.h>
50 #include "DtMailEditor.hh"
51 #include "XmTextEditor.h"
52 #include "AttachArea.h"
53 #include "Attachment.h"
55 #include "DtEditor.hh"
58 #include "EUSDebug.hh"
62 extern XtPointer _XmStringUngenerate (
66 XmTextType output_type);
70 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
73 #ifndef DRAG_THRESHOLD
74 #define DRAG_THRESHOLD 4
77 DtMailEditor::DtMailEditor(
79 AbstractEditorParent *owner
80 ) : UIComponent("DtMailEditor")
84 // Create a manager widget (say a form) and set it to the private
85 // variable _container. Parent private instances to this widget.
86 // Expose only _container externally (for attachment stuff...)
88 _w = XmCreateForm(parent, "DtMailEditor", NULL, 0);
89 installDestroyHandler();
92 if ( use_XmTextEditor ) {
93 _myTextEditor = new XmTextEditor(_w, this);
95 _myTextEditor = new CDEM_DtWidgetEditor(_w, this);
98 _myTextEditor = new XmTextEditor(_w, this);
101 _myAttachArea = new AttachArea(_w, this, "AttachPane");
103 _showAttachArea = TRUE;
113 DtMailEditor::~DtMailEditor()
115 unmanageAttachArea();
116 delete _myAttachArea;
117 delete _myTextEditor;
121 DtMailEditor::initialize()
124 Widget editor_widget;
126 _myTextEditor->initialize();
128 _separator = XtVaCreateManagedWidget("Sep1",
129 xmSeparatorGadgetClass,
133 XmNrightAttachment, XmATTACH_FORM,
134 XmNleftAttachment, XmATTACH_FORM,
137 // Create an *UNMANAGED* attachArea.
138 // If the message has an attachment, the DtMailEditor instance
139 // will receive a manageAttachArea where it will adjust the
140 // attachments and manage the attachArea accordingly
142 _myAttachArea->initialize();
144 attachDropRegister();
148 editor_widget = _myTextEditor->get_editor();
150 XtVaSetValues(editor_widget,
151 XmNtopAttachment,XmATTACH_FORM,
152 XmNbottomAttachment, XmATTACH_WIDGET,
153 XmNbottomWidget, _separator,
154 XmNrightAttachment,XmATTACH_FORM,
156 XmNleftAttachment,XmATTACH_FORM,
160 XtVaSetValues(_myAttachArea->baseWidget(),
161 XmNrightAttachment, XmATTACH_FORM,
163 XmNleftAttachment, XmATTACH_FORM,
165 XmNbottomAttachment, XmATTACH_FORM,
168 XtVaSetValues(_separator,
169 XmNbottomAttachment, XmATTACH_WIDGET,
170 XmNbottomWidget, _myAttachArea->baseWidget(),
173 // Unmanage the attachArea. If a message has attachments,
174 // manageAttachArea() will get called by the consumer of this
177 this->unmanageAttachArea();
183 AbstractEditorParent *
184 DtMailEditor::owner()
190 DtMailEditor::textEditor()
192 return(_myTextEditor);
196 DtMailEditor::attachArea()
198 return(_myAttachArea);
202 DtMailEditor::container()
208 DtMailEditor::setEditable(Boolean bval)
210 textEditor()->set_editable(bval);
219 DtMailEditor::manageAttachArea()
222 if (!_showAttachArea && (_myAttachArea->getIconCount() == 0)) {
226 _myAttachArea->manage();
227 XtManageChild(_separator);
229 Widget editor_widget = _myTextEditor->get_editor();
231 XtVaSetValues(editor_widget,
232 XmNbottomAttachment, XmATTACH_WIDGET,
233 XmNbottomWidget, _separator,
236 XtVaSetValues(_separator,
237 XmNbottomAttachment, XmATTACH_WIDGET,
238 XmNbottomWidget, _myAttachArea->baseWidget(),
241 XtVaSetValues(_myAttachArea->baseWidget(),
242 XmNbottomAttachment, XmATTACH_FORM,
248 DtMailEditor::unmanageAttachArea()
251 // Already unmanaged?
252 if (!XtIsManaged(_myAttachArea->baseWidget())) return;
254 Widget editor_widget = _myTextEditor->get_editor();
256 XtVaSetValues(editor_widget,
257 XmNbottomAttachment, XmATTACH_FORM,
260 _myAttachArea->unmanage();
262 XtUnmanageChild(_separator);
266 // Initialize _msgHandle
268 DtMailEditor::setMsgHnd(DtMail::Message * msgHandle)
270 _msgHandle = msgHandle;
273 // attachTransferCallback
275 // Handles the transfer of data that is dropped on the attachment list.
276 // The data is turned into an attachment and appended to the list.
279 DtMailEditor::attachTransferCallback(
281 XtPointer client_data,
284 DtDndTransferCallbackStruct *transferInfo =
285 (DtDndTransferCallbackStruct *) call_data;
286 DtDndContext *dropData = transferInfo->dropData;
287 int numItems = dropData->numItems, ii;
288 DtMailEditor *editor = (DtMailEditor *) client_data;
289 DtMailEnv mail_error;
293 DebugPrintf(3, "In DtMailEditor::attachTransferCallback\n");
295 // Initialize mail_error.
298 switch (transferInfo->dropData->protocol) {
300 case DtDND_FILENAME_TRANSFER:
302 // Loop through the dropped files and turn each
303 // into an attachment.
305 for (ii = 0; ii < numItems; ii++) {
306 editor->owner()->add_att(dropData->data.files[ii]);
310 case DtDND_BUFFER_TRANSFER:
312 // Loop through the dropped buffers and turn each
313 // into an attachment.
315 for (ii = 0; ii < numItems; ii++) {
317 buf.buffer = (char *)dropData->data.buffers[ii].bp;
318 buf.size = (unsigned long)dropData->data.buffers[ii].size;
319 attachname = dropData->data.buffers[ii].name;
322 attachname = "Untitled";
324 editor->owner()->add_att(attachname, buf);
329 transferInfo->status = DtDND_FAILURE;
335 // attachDropRegister
337 // Register the attachment list to accept drops of buffer and files
340 DtMailEditor::attachDropRegister()
342 static XtCallbackRec transferCBRec[] = {
343 {&DtMailEditor::attachTransferCallback, NULL}, {NULL, NULL} };
345 // Pass the DtMailEditor object (this) as clientData.
346 transferCBRec[0].closure = (XtPointer) this;
348 DtDndVaDropRegister(_myAttachArea->baseWidget(),
349 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
350 (unsigned char)(XmDROP_COPY), transferCBRec,
351 DtNtextIsBuffer, TRUE,
357 // Enable the attachment list for drops by restoring the operation
360 DtMailEditor::attachDropEnable()
364 XtSetArg(args[0], XmNdropSiteOperations, XmDROP_MOVE | XmDROP_COPY);
365 XmDropSiteUpdate(_myAttachArea->baseWidget(), args, 1);
370 // Disable the attachment list for drops by setting the operation to noop
373 DtMailEditor::attachDropDisable()
377 XtSetArg(args[0], XmNdropSiteOperations, XmDROP_NOOP);
378 XmDropSiteUpdate(_myAttachArea->baseWidget(), args, 1);
381 // attachConvertCallback
383 // Provides the selected attachments for the drag
386 DtMailEditor::attachConvertCallback(
387 Widget /* dragContext */,
388 XtPointer clientData,
391 DtDndConvertCallbackStruct *convertInfo =
392 (DtDndConvertCallbackStruct *) callData;
393 DtDndBuffer *buffers = convertInfo->dragData->data.buffers;
394 DtMailEditor *editor = (DtMailEditor *) clientData;
395 int numIcons = editor->attachArea()->getIconCount();
396 Attachment **list = editor->attachArea()->getList();
400 DtMailEnv mail_error;
403 DebugPrintf(3, "In DtMailEditor::attachConvertCallback\n");
405 switch(convertInfo->reason) {
406 case DtCR_DND_CONVERT_DATA:
407 for (ii = 0; ii < numIcons; ii++) {
408 if (!list[ii]->isDeleted() && list[ii]->isSelected()) {
409 buffers[current].bp = list[ii]->getContents();
410 buffers[current].size = (int)list[ii]->getContentsSize();
411 str = list[ii]->getLabel();
412 buffers[current].name =
413 (char *) _XmStringUngenerate(
415 XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
422 case DtCR_DND_CONVERT_DELETE:
423 editor->attachArea()->deleteSelectedAttachments(mail_error);
427 convertInfo->status = DtDND_FAILURE;
431 // attachDragFinishCallback
433 // Clean up from the convert callback and restore state
436 DtMailEditor::attachDragFinishCallback(
438 XtPointer clientData,
441 DtDndDragFinishCallbackStruct *finishInfo =
442 (DtDndDragFinishCallbackStruct *) callData;
443 DtDndContext *dragData = finishInfo->dragData;
444 DtMailEditor *editor = (DtMailEditor *) clientData;
447 DebugPrintf(3, "In DtMailEditor::attachDragFinishCallback\n");
449 editor->setDoingDrag(FALSE);
450 editor->setDragX(-1);
451 editor->setDragY(-1);
453 if (editor->editable())
454 editor->attachDropEnable();
456 for (ii = 0; ii < dragData->numItems; ii++) {
457 XtFree((char *)dragData->data.buffers[ii].name);
462 DtMailEditor::attachDragStart( Widget widget,
465 static XtCallbackRec convertCBRec[] = {
466 {&DtMailEditor::attachConvertCallback, NULL}, {NULL, NULL} };
467 static XtCallbackRec dragFinishCBRec[] = {
468 {&DtMailEditor::attachDragFinishCallback, NULL}, {NULL, NULL} };
470 unsigned char operations;
472 convertCBRec[0].closure = (XtPointer) this;
473 dragFinishCBRec[0].closure = (XtPointer) this;
477 // Count the number of items to be dragged.
478 itemCount = attachArea()->getSelectedIconCount();
483 operations = (unsigned char)(XmDROP_COPY | XmDROP_MOVE);
485 operations = (unsigned char)(XmDROP_COPY);
488 if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, itemCount,
489 operations, convertCBRec, dragFinishCBRec,
490 // DtNsourceIcon, dragIcon,
494 DebugPrintf(3, "DragStart returned NULL.\n");
499 DtMailEditor::attachDragMotionHandler(
506 // If the drag is just starting, set initial button down coordinates.
507 if (dragX() == -1 && dragY() == -1) {
508 setDragX(event->xmotion.x);
509 setDragY(event->xmotion.y);
512 // Find out how far the pointer has moved since the button press.
513 diffX = dragX() - event->xmotion.x;
514 diffY = dragY() - event->xmotion.y;
516 if ((ABS(diffX) >= DRAG_THRESHOLD) ||
517 (ABS(diffY) >= DRAG_THRESHOLD)) {
518 attachDragStart(widget, event);
525 DtMailEditor::attachDragSetup()
527 Boolean btn1_transfer;
528 Widget widget = _myAttachArea->baseWidget();
530 DebugPrintf(3, "In DtMailEditor::attachDragSetup()\n");
532 XtAddEventHandler(widget, Button1MotionMask, FALSE,
533 (XtEventHandler)&DtMailEditor::attachDragMotionHandler,
537 (Widget)XmGetXmDisplay(XtDisplayOfObject(widget)),
538 "enableBtn1Transfer", &btn1_transfer,
541 if (!btn1_transfer) {
542 XtAddEventHandler(widget, Button2MotionMask, FALSE,
543 (XtEventHandler)&DtMailEditor::attachDragMotionHandler,
550 DtMailEditor::stripCRLF(char **buffer, const char * buf, const unsigned long len)
552 char * out = *buffer;
556 for (const char * in = buf; in < (buf + len);) {
557 _len = mblen( in, MB_CUR_MAX );
560 if ( ( _len == 1 ) && ( *in == '\r' ) ){
564 strncpy( out, in, _len );
565 out += _len, in += _len;
571 DtMailEditor::needBuf(char **buffer, unsigned long *buflen, unsigned long newlen)
573 if (newlen > *buflen) {
574 // Need a bigger buffer.
579 *buffer = new char[newlen];
582 // Clear buffer content -- get ready for new data
584 memset(*buffer, 0, (unsigned int)*buflen);
590 DtMailEditor::showAttachArea()
592 _showAttachArea = TRUE;
593 this->manageAttachArea();
598 DtMailEditor::hideAttachArea()
600 _showAttachArea = FALSE;
601 this->unmanageAttachArea();