4 * $TOG: DtMailEditor.C /main/10 1998/07/24 16:05:41 mgreess $
6 * RESTRICTED CONFIDENTIAL INFORMATION:
8 * The information in this document is subject to special
9 * restrictions in a confidential disclosure agreement between
10 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
11 * document outside HP, IBM, Sun, USL, SCO, or Univel without
12 * Sun's specific written approval. This document and all copies
13 * and derivative works thereof must be returned or destroyed at
16 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
21 #ifndef I_HAVE_NO_IDENT
26 #include <Xm/SeparatoG.h>
28 #include "DtMailEditor.hh"
29 #include "XmTextEditor.h"
30 #include "AttachArea.h"
31 #include "Attachment.h"
33 #include "DtEditor.hh"
36 #include "EUSDebug.hh"
40 extern XtPointer _XmStringUngenerate (
44 XmTextType output_type);
48 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
51 #ifndef DRAG_THRESHOLD
52 #define DRAG_THRESHOLD 4
55 DtMailEditor::DtMailEditor(
57 AbstractEditorParent *owner
58 ) : UIComponent("DtMailEditor")
62 // Create a manager widget (say a form) and set it to the private
63 // variable _container. Parent private instances to this widget.
64 // Expose only _container externally (for attachment stuff...)
66 _w = XmCreateForm(parent, "DtMailEditor", NULL, 0);
67 installDestroyHandler();
70 if ( use_XmTextEditor ) {
71 _myTextEditor = new XmTextEditor(_w, this);
73 _myTextEditor = new CDEM_DtWidgetEditor(_w, this);
76 _myTextEditor = new XmTextEditor(_w, this);
79 _myAttachArea = new AttachArea(_w, this, "AttachPane");
81 _showAttachArea = TRUE;
91 DtMailEditor::~DtMailEditor()
99 DtMailEditor::initialize()
102 Widget editor_widget;
104 _myTextEditor->initialize();
106 _separator = XtVaCreateManagedWidget("Sep1",
107 xmSeparatorGadgetClass,
111 XmNrightAttachment, XmATTACH_FORM,
112 XmNleftAttachment, XmATTACH_FORM,
115 // Create an *UNMANAGED* attachArea.
116 // If the message has an attachment, the DtMailEditor instance
117 // will receive a manageAttachArea where it will adjust the
118 // attachments and manage the attachArea accordingly
120 _myAttachArea->initialize();
122 attachDropRegister();
126 editor_widget = _myTextEditor->get_editor();
128 XtVaSetValues(editor_widget,
129 XmNtopAttachment,XmATTACH_FORM,
130 XmNbottomAttachment, XmATTACH_WIDGET,
131 XmNbottomWidget, _separator,
132 XmNrightAttachment,XmATTACH_FORM,
134 XmNleftAttachment,XmATTACH_FORM,
138 XtVaSetValues(_myAttachArea->baseWidget(),
139 XmNrightAttachment, XmATTACH_FORM,
141 XmNleftAttachment, XmATTACH_FORM,
143 XmNbottomAttachment, XmATTACH_FORM,
146 XtVaSetValues(_separator,
147 XmNbottomAttachment, XmATTACH_WIDGET,
148 XmNbottomWidget, _myAttachArea->baseWidget(),
151 // Unmanage the attachArea. If a message has attachments,
152 // manageAttachArea() will get called by the consumer of this
155 this->unmanageAttachArea();
161 AbstractEditorParent *
162 DtMailEditor::owner()
168 DtMailEditor::textEditor()
170 return(_myTextEditor);
174 DtMailEditor::attachArea()
176 return(_myAttachArea);
180 DtMailEditor::container()
186 DtMailEditor::setEditable(Boolean bval)
188 textEditor()->set_editable(bval);
197 DtMailEditor::manageAttachArea()
200 if (!_showAttachArea && (_myAttachArea->getIconCount() == 0)) {
204 _myAttachArea->manage();
205 XtManageChild(_separator);
207 Widget editor_widget = _myTextEditor->get_editor();
209 XtVaSetValues(editor_widget,
210 XmNbottomAttachment, XmATTACH_WIDGET,
211 XmNbottomWidget, _separator,
214 XtVaSetValues(_separator,
215 XmNbottomAttachment, XmATTACH_WIDGET,
216 XmNbottomWidget, _myAttachArea->baseWidget(),
219 XtVaSetValues(_myAttachArea->baseWidget(),
220 XmNbottomAttachment, XmATTACH_FORM,
226 DtMailEditor::unmanageAttachArea()
229 // Already unmanaged?
230 if (!XtIsManaged(_myAttachArea->baseWidget())) return;
232 Widget editor_widget = _myTextEditor->get_editor();
234 XtVaSetValues(editor_widget,
235 XmNbottomAttachment, XmATTACH_FORM,
238 _myAttachArea->unmanage();
240 XtUnmanageChild(_separator);
244 // Initialize _msgHandle
246 DtMailEditor::setMsgHnd(DtMail::Message * msgHandle)
248 _msgHandle = msgHandle;
251 // attachTransferCallback
253 // Handles the transfer of data that is dropped on the attachment list.
254 // The data is turned into an attachment and appended to the list.
257 DtMailEditor::attachTransferCallback(
259 XtPointer client_data,
262 DtDndTransferCallbackStruct *transferInfo =
263 (DtDndTransferCallbackStruct *) call_data;
264 DtDndContext *dropData = transferInfo->dropData;
265 int numItems = dropData->numItems, ii;
266 DtMailEditor *editor = (DtMailEditor *) client_data;
267 DtMailEnv mail_error;
271 DebugPrintf(3, "In DtMailEditor::attachTransferCallback\n");
273 // Initialize mail_error.
276 switch (transferInfo->dropData->protocol) {
278 case DtDND_FILENAME_TRANSFER:
280 // Loop through the dropped files and turn each
281 // into an attachment.
283 for (ii = 0; ii < numItems; ii++) {
284 editor->owner()->add_att(dropData->data.files[ii]);
288 case DtDND_BUFFER_TRANSFER:
290 // Loop through the dropped buffers and turn each
291 // into an attachment.
293 for (ii = 0; ii < numItems; ii++) {
295 buf.buffer = (char *)dropData->data.buffers[ii].bp;
296 buf.size = (unsigned long)dropData->data.buffers[ii].size;
297 attachname = dropData->data.buffers[ii].name;
300 attachname = "Untitled";
302 editor->owner()->add_att(attachname, buf);
307 transferInfo->status = DtDND_FAILURE;
313 // attachDropRegister
315 // Register the attachment list to accept drops of buffer and files
318 DtMailEditor::attachDropRegister()
320 static XtCallbackRec transferCBRec[] = {
321 {&DtMailEditor::attachTransferCallback, NULL}, {NULL, NULL} };
323 // Pass the DtMailEditor object (this) as clientData.
324 transferCBRec[0].closure = (XtPointer) this;
326 DtDndVaDropRegister(_myAttachArea->baseWidget(),
327 DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
328 (unsigned char)(XmDROP_COPY), transferCBRec,
329 DtNtextIsBuffer, TRUE,
335 // Enable the attachment list for drops by restoring the operation
338 DtMailEditor::attachDropEnable()
342 XtSetArg(args[0], XmNdropSiteOperations, XmDROP_MOVE | XmDROP_COPY);
343 XmDropSiteUpdate(_myAttachArea->baseWidget(), args, 1);
348 // Disable the attachment list for drops by setting the operation to noop
351 DtMailEditor::attachDropDisable()
355 XtSetArg(args[0], XmNdropSiteOperations, XmDROP_NOOP);
356 XmDropSiteUpdate(_myAttachArea->baseWidget(), args, 1);
359 // attachConvertCallback
361 // Provides the selected attachments for the drag
364 DtMailEditor::attachConvertCallback(
365 Widget /* dragContext */,
366 XtPointer clientData,
369 DtDndConvertCallbackStruct *convertInfo =
370 (DtDndConvertCallbackStruct *) callData;
371 DtDndBuffer *buffers = convertInfo->dragData->data.buffers;
372 DtMailEditor *editor = (DtMailEditor *) clientData;
373 int numIcons = editor->attachArea()->getIconCount();
374 Attachment **list = editor->attachArea()->getList();
378 DtMailEnv mail_error;
381 DebugPrintf(3, "In DtMailEditor::attachConvertCallback\n");
383 switch(convertInfo->reason) {
384 case DtCR_DND_CONVERT_DATA:
385 for (ii = 0; ii < numIcons; ii++) {
386 if (!list[ii]->isDeleted() && list[ii]->isSelected()) {
387 buffers[current].bp = list[ii]->getContents();
388 buffers[current].size = (int)list[ii]->getContentsSize();
389 str = list[ii]->getLabel();
390 buffers[current].name =
391 (char *) _XmStringUngenerate(
393 XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
400 case DtCR_DND_CONVERT_DELETE:
401 editor->attachArea()->deleteSelectedAttachments(mail_error);
405 convertInfo->status = DtDND_FAILURE;
409 // attachDragFinishCallback
411 // Clean up from the convert callback and restore state
414 DtMailEditor::attachDragFinishCallback(
416 XtPointer clientData,
419 DtDndDragFinishCallbackStruct *finishInfo =
420 (DtDndDragFinishCallbackStruct *) callData;
421 DtDndContext *dragData = finishInfo->dragData;
422 DtMailEditor *editor = (DtMailEditor *) clientData;
425 DebugPrintf(3, "In DtMailEditor::attachDragFinishCallback\n");
427 editor->setDoingDrag(FALSE);
428 editor->setDragX(-1);
429 editor->setDragY(-1);
431 if (editor->editable())
432 editor->attachDropEnable();
434 for (ii = 0; ii < dragData->numItems; ii++) {
435 XtFree((char *)dragData->data.buffers[ii].name);
440 DtMailEditor::attachDragStart( Widget widget,
443 static XtCallbackRec convertCBRec[] = {
444 {&DtMailEditor::attachConvertCallback, NULL}, {NULL, NULL} };
445 static XtCallbackRec dragFinishCBRec[] = {
446 {&DtMailEditor::attachDragFinishCallback, NULL}, {NULL, NULL} };
448 unsigned char operations;
450 convertCBRec[0].closure = (XtPointer) this;
451 dragFinishCBRec[0].closure = (XtPointer) this;
455 // Count the number of items to be dragged.
456 itemCount = attachArea()->getSelectedIconCount();
461 operations = (unsigned char)(XmDROP_COPY | XmDROP_MOVE);
463 operations = (unsigned char)(XmDROP_COPY);
466 if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, itemCount,
467 operations, convertCBRec, dragFinishCBRec,
468 // DtNsourceIcon, dragIcon,
472 DebugPrintf(3, "DragStart returned NULL.\n");
477 DtMailEditor::attachDragMotionHandler(
484 // If the drag is just starting, set initial button down coordinates.
485 if (dragX() == -1 && dragY() == -1) {
486 setDragX(event->xmotion.x);
487 setDragY(event->xmotion.y);
490 // Find out how far the pointer has moved since the button press.
491 diffX = dragX() - event->xmotion.x;
492 diffY = dragY() - event->xmotion.y;
494 if ((ABS(diffX) >= DRAG_THRESHOLD) ||
495 (ABS(diffY) >= DRAG_THRESHOLD)) {
496 attachDragStart(widget, event);
503 DtMailEditor::attachDragSetup()
505 Boolean btn1_transfer;
506 Widget widget = _myAttachArea->baseWidget();
508 DebugPrintf(3, "In DtMailEditor::attachDragSetup()\n");
510 XtAddEventHandler(widget, Button1MotionMask, FALSE,
511 (XtEventHandler)&DtMailEditor::attachDragMotionHandler,
515 (Widget)XmGetXmDisplay(XtDisplayOfObject(widget)),
516 "enableBtn1Transfer", &btn1_transfer,
519 if (!btn1_transfer) {
520 XtAddEventHandler(widget, Button2MotionMask, FALSE,
521 (XtEventHandler)&DtMailEditor::attachDragMotionHandler,
528 DtMailEditor::stripCRLF(char **buffer, const char * buf, const unsigned long len)
530 char * out = *buffer;
534 for (const char * in = buf; in < (buf + len);) {
535 _len = mblen( in, MB_CUR_MAX );
538 if ( ( _len == 1 ) && ( *in == '\r' ) ){
542 strncpy( out, in, _len );
543 out += _len, in += _len;
549 DtMailEditor::needBuf(char **buffer, unsigned long *buflen, unsigned long newlen)
551 if (newlen > *buflen) {
552 // Need a bigger buffer.
557 *buffer = new char[newlen];
560 // Clear buffer content -- get ready for new data
562 memset(*buffer, 0, (unsigned int)*buflen);
568 DtMailEditor::showAttachArea()
570 _showAttachArea = TRUE;
571 this->manageAttachArea();
576 DtMailEditor::hideAttachArea()
578 _showAttachArea = FALSE;
579 this->unmanageAttachArea();