The widget passed to the callback routine is the DragContext object for the drag and drop transfer. The routine
retrieves the source icon from the DragContext and destroys it using XtDestroyWidget().
19.5 Working With Drop Sites
In order to handle data from drag sources that provide something other than textual data, an application has to register
drop sites that understand other types of data. To make the file_manager.c application useful, we need an application
that has drop sites that can handle file objects. In this section, we are going to modify the text editor from Chapter 14,
Text Widgets, so that it understands file data. The application contains two drop sites that handle files: the main text
entry area and a filename status area. the source code shows the main(), HandleDropLabel(),
HandleDropText(), and TransferProc() routines for editor_dnd.c. The rest of the routines in the application
are the same as in Section #stexteditor, so we have not shown them here.
/* editor_dnd.c −− create an editor application that contains drop sites
* that understand file data. A file can be dragged from another
* application and dropped in the text entry area or the filename status
* area.
*/
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/LabelG.h>
#include <Xm/PushBG.h>
#include <Xm/RowColumn.h>
#include <Xm/MainW.h>
#include <Xm/Form.h>
#include <Xm/FileSB.h>
#include <Xm/SeparatoG.h>
#include <Xm/DragDrop.h>
#include <X11/Xos.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FILE_OPEN 0
#define FILE_SAVE 1
#define FILE_EXIT 2
#define EDIT_CUT 0
#define EDIT_COPY 1
#define EDIT_PASTE 2
#define EDIT_CLEAR 3
#define SEARCH_FIND_NEXT 0
#define SEARCH_SHOW_ALL 1
#define SEARCH_REPLACE 2
#define SEARCH_CLEAR 3
/* global variables */
void (*drop_proc) ();
Widget text_edit, search_text, replace_text, text_output;
Widget toplevel, file_label;
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext app_context;
Display *dpy;
19 Drag and Drop 19.5 Working With Drop Sites
545
Atom FILE_CONTENTS, FILE_NAME;
Widget main_window, menubar, form, search_panel;
Widget sep1, sep2;
void file_cb(), edit_cb(), search_cb();
Arg args[10];
int n = 0;
XmString open, save, exit, exit_acc, file, edit, cut,
clear, copy, paste, search, next, find, replace;
Cardinal numImportTargets;
Atom *importTargets, *newTargets;
Atom importList[2];
void HandleDropLabel(), HandleDropText();
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app_context, "Demos",
NULL, 0, &argc, argv, NULL, NULL);
dpy = XtDisplay (toplevel);
FILE_CONTENTS = XmInternAtom (dpy, "FILE_CONTENTS", False);
FILE_NAME = XmInternAtom (dpy, "FILE_NAME", False);
main_window = XtVaCreateWidget ("main_window",
xmMainWindowWidgetClass, toplevel, NULL);
/* Create a simple MenuBar that contains three menus */
file = XmStringCreateLocalized ("File");
edit = XmStringCreateLocalized ("Edit");
search = XmStringCreateLocalized ("Search");
menubar = XmVaCreateSimpleMenuBar (main_window, "menubar",
XmVaCASCADEBUTTON, file, 'F',
XmVaCASCADEBUTTON, edit, 'E',
XmVaCASCADEBUTTON, search, 'S',
NULL);
XmStringFree (file);
XmStringFree (edit);
XmStringFree (search);
/* First menu is the File menu −− callback is file_cb() */
open = XmStringCreateLocalized ("Open...");
save = XmStringCreateLocalized ("Save...");
exit = XmStringCreateLocalized ("Exit");
exit_acc = XmStringCreateLocalized ("Ctrl+C");
XmVaCreateSimplePulldownMenu (menubar, "file_menu", 0, file_cb,
XmVaPUSHBUTTON, open, 'O', NULL, NULL,
XmVaPUSHBUTTON, save, 'S', NULL, NULL,
XmVaSEPARATOR,
XmVaPUSHBUTTON, exit, 'x', "Ctrl<Key>c", exit_acc,
NULL);
XmStringFree (open);
XmStringFree (save);
XmStringFree (exit);
XmStringFree (exit_acc);
/* ...create the "Edit" menu −− callback is edit_cb() */
cut = XmStringCreateLocalized ("Cut");
copy = XmStringCreateLocalized ("Copy");
clear = XmStringCreateLocalized ("Clear");
paste = XmStringCreateLocalized ("Paste");
XmVaCreateSimplePulldownMenu (menubar, "edit_menu", 1, edit_cb,
XmVaPUSHBUTTON, cut, 't', NULL, NULL,
19 Drag and Drop 19.5 Working With Drop Sites
546
XmVaPUSHBUTTON, copy, 'C', NULL, NULL,
XmVaPUSHBUTTON, paste, 'P', NULL, NULL,
XmVaSEPARATOR,
XmVaPUSHBUTTON, clear, 'l', NULL, NULL,
NULL);
XmStringFree (cut);
XmStringFree (copy);
XmStringFree (paste);
/* create the "Search" menu −− callback is search_cb() */
next = XmStringCreateLocalized ("Find Next");
find = XmStringCreateLocalized ("Show All");
replace = XmStringCreateLocalized ("Replace Text");
XmVaCreateSimplePulldownMenu (menubar, "search_menu", 2, search_cb,
XmVaPUSHBUTTON, next, 'N', NULL, NULL,
XmVaPUSHBUTTON, find, 'A', NULL, NULL,
XmVaPUSHBUTTON, replace, 'R', NULL, NULL,
XmVaSEPARATOR,
XmVaPUSHBUTTON, clear, 'C', NULL, NULL,
NULL);
XmStringFree (next);
XmStringFree (find);
XmStringFree (replace);
XmStringFree (clear);
XtManageChild (menubar);
/* create a form work are */
form = XtVaCreateWidget ("form",
xmFormWidgetClass, main_window, NULL);
/* create horizontal RowColumn inside the form */
search_panel = XtVaCreateWidget ("search_panel",
xmRowColumnWidgetClass, form,
XmNorientation, XmHORIZONTAL,
XmNpacking, XmPACK_TIGHT,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
/* Create two TextField widgets with Labels... */
XtVaCreateManagedWidget ("Search Pattern:",
xmLabelGadgetClass, search_panel, NULL);
search_text = XtVaCreateManagedWidget ("search_text",
xmTextFieldWidgetClass, search_panel, NULL);
XtVaCreateManagedWidget (" Replace Pattern:",
xmLabelGadgetClass, search_panel, NULL);
replace_text = XtVaCreateManagedWidget ("replace_text",
xmTextFieldWidgetClass, search_panel, NULL);
XtManageChild (search_panel);
text_output = XtVaCreateManagedWidget ("text_output",
xmTextFieldWidgetClass, form,
XmNeditable, False,
XmNcursorPositionVisible, False,
XmNshadowThickness, 0,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
NULL);
19 Drag and Drop 19.5 Working With Drop Sites
547
sep2 = XtVaCreateManagedWidget ("sep2",
xmSeparatorGadgetClass, form,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, text_output,
NULL);
/* create file status area */
file_label = XtVaCreateManagedWidget ("Filename:",
xmLabelGadgetClass, form,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, sep2,
NULL);
/* register the file status label as a drop site */
n = 0;
importList[0] = FILE_CONTENTS;
importList[1] = FILE_NAME;
XtSetArg (args[n], XmNimportTargets, importList); n++;
XtSetArg (args[n], XmNnumImportTargets, XtNumber (importList)); n++;
XtSetArg (args[n], XmNdropSiteOperations, XmDROP_COPY); n++;
XtSetArg (args[n], XmNdropProc, HandleDropLabel); n++;
XmDropSiteRegister (file_label, args, n);
sep1 = XtVaCreateManagedWidget ("sep1",
xmSeparatorGadgetClass, form,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, file_label,
NULL);
/* create text entry area */
n = 0;
XtSetArg (args[n], XmNrows, 10); n++;
XtSetArg (args[n], XmNcolumns, 80); n++;
XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNtopWidget, search_panel); n++;
XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg (args[n], XmNbottomWidget, sep1); n++;
text_edit = XmCreateScrolledText (form, "text_edit", args, n);
XtManageChild (text_edit);
/* retrieve drop site info so that we can modify it */
n = 0;
XtSetArg (args[n], XmNimportTargets, &importTargets); n++;
XtSetArg (args[n], XmNnumImportTargets, &numImportTargets); n++;
XtSetArg (args[n], XmNdropProc, &drop_proc); n++;
XmDropSiteRetrieve (text_edit, args, n);
/* add FILE_CONTENTS and FILE_NAME to the list of targets */
newTargets = (Atom *) XtMalloc (sizeof (Atom) * (numImportTargets + 2));
for (n = 0; n < numImportTargets; n++)
19 Drag and Drop 19.5 Working With Drop Sites
548
newTargets[n] = importTargets[n];
newTargets[n] = FILE_CONTENTS;
newTargets[n+1] = FILE_NAME;
/* update the drop site */
n = 0;
XtSetArg (args[n], XmNimportTargets, newTargets); n++;
XtSetArg (args[n], XmNnumImportTargets, numImportTargets+2); n++;
XtSetArg (args[n], XmNdropProc, HandleDropText); n++;
XmDropSiteUpdate (text_edit, args, n);
XtManageChild (form);
XtManageChild (main_window);
XtRealizeWidget (toplevel);
XtAppMainLoop (app_context);
}
/* HandleDropLabel() −− start the data transfer when data is dropped in
* the filename status area.
*/
void
HandleDropLabel(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
Display *dpy;
Atom FILE_CONTENTS, FILE_NAME;
XmDropProcCallback DropData;
XmDropTransferEntryRec transferEntries[2];
XmDropTransferEntry transferList;
Arg args[10];
int n, i;
Widget dc;
Cardinal numExportTargets;
Atom *exportTargets;
Boolean file_name = False;
void TransferProc();
/* intern the Atoms for data targets */
dpy = XtDisplay (toplevel);
FILE_CONTENTS = XmInternAtom (dpy, "FILE_CONTENTS", False);
FILE_NAME = XmInternAtom (dpy, "FILE_NAME", False);
DropData = (XmDropProcCallback) call_data;
dc = DropData−>dragContext;
/* retrieve the data targets and search for FILE_NAME */
n = 0;
XtSetArg (args[n], XmNexportTargets, &exportTargets); n++;
XtSetArg (args[n], XmNnumExportTargets, &numExportTargets); n++;
XtGetValues (dc, args, n);
for (i = 0; i < numExportTargets; i++) {
if (exportTargets[i] == FILE_NAME) {
file_name = True;
break;
}
}
19 Drag and Drop 19.5 Working With Drop Sites
549

Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.