1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/examples/dtdnd/buff.c
2018-04-28 12:36:44 -06:00

655 lines
18 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: buff.c /main/5 1999/07/20 14:48:23 mgreess $ */
/*****************************************************************************
*****************************************************************************
**
** File: buff.c
**
** Description: Buffer transfer functions for the CDE Drag & Drop Demo.
**
** (c) Copyright 1993, 1994 Hewlett-Packard Company
** (c) Copyright 1993, 1994 International Business Machines Corp.
** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
** (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
** Novell, Inc.
**
****************************************************************************
************************************<+>*************************************/
#include <time.h>
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/List.h>
#include <Dt/Dt.h>
#include <Dt/Dnd.h>
#include "icon.h"
#include "file.h"
#include "demo.h"
#include "buff.h"
extern Widget topLevel;
/*************************************************************************
*
* Data Structures & Private Declarations For Appointment Buffers
*
**************************************************************************/
/*
* Appointment structure used to store appointments internally.
*/
typedef struct _Appointment {
char *date;
char *start;
char *end;
char *what;
} Appointment;
/*
* List of appointments which always appear to be for the current date.
*/
char today[9]; /* initialized in apptCreateList() */
Appointment todaysApptList[] = {
#ifdef TEST_APPT_NAMES
{ today, "", "", "Staff Meeting" }, /* no name */
{ today, " 9:30am", "10:00am", "Will's Party1" }, /* duplicate names */
{ today, " 9:30am", "10:00am", "Will's Party2" },
#else
{ today, " 9:00am", " 9:30am", "Staff Meeting" },
{ today, " 9:30am", "10:00am", "Will's Party" },
#endif
{ today, "10:00am", "10:30am", "Conference Call" },
{ today, "10:30am", "11:30am", "Work on Mail" },
{ today, "11:00am", "11:30pm", "B'fast w/ Robert" },
{ today, " 1:30pm", " 2:30pm", "Design Meeting" },
{ today, " 3:00pm", " 4:00pm", "Communications" },
{ today, " 4:00pm", " 4:30pm", "Pick up Dogs" },
{ today, " 5:00pm", " 6:30pm", "Beer Bust" },
{ today, " 7:00pm", " 9:00pm", "Dinner - Stuart" },
{ NULL, NULL, NULL, NULL }
};
/*
* CDE appointment format used to transfer the appointments via drag & drop.
*/
char *apptFormat =
" ** Calendar Appointment **\n\
\n\
Date: %s\n\
Start: %s\n\
End: %s\n\
What: %s\n";
/*
* Private Appointment Buffer Function Declarations
*/
static void apptConvertCallback(Widget, XtPointer, XtPointer);
static int apptCreateList(XmString**);
static void apptDestroyList(XmString*,int);
static Appointment* apptFromListEntry(XmString);
static char* apptGetLabel(char*);
/*************************************************************************
*
* Appointment Drag & Drop
*
**************************************************************************/
/*
* apptConvertCallback
*
* Fills in buffer structure with calendar appointment string based on which
* appointments are selected in the scrolled list when the drag is started.
* ihen no appointments are selected, the appointment under the pointer is
* used. Supply a label for the calendar appointment based on the contents
* of the appointment.
*/
static void
apptConvertCallback(
Widget dragContext,
XtPointer clientData,
XtPointer callData)
{
DtDndConvertCallbackStruct *convertInfo =
(DtDndConvertCallbackStruct *) callData;
DtDndBuffer *buffers = convertInfo->dragData->data.buffers;
Widget apptList = (Widget)clientData;
int selectedPos, ii,
selectedItemCount;
XmStringTable selectedItems;
char apptString[1024];
String labelString;
Appointment *appt;
if (convertInfo == NULL) {
return;
}
/*
* Verify the validity of the callback reason
*/
if (convertInfo->dragData->protocol != DtDND_BUFFER_TRANSFER ||
(convertInfo->reason != DtCR_DND_CONVERT_DATA &&
convertInfo->reason != DtCR_DND_CONVERT_DELETE)) {
return;
}
/*
* Get selected items from the list
*/
XtVaGetValues(apptList,
XmNuserData, &selectedPos,
XmNselectedItemCount, &selectedItemCount,
XmNselectedItems, &selectedItems,
NULL);
for (ii = 0; ii < convertInfo->dragData->numItems; ii++) {
/*
* Get the actual appointment(s)
*/
if (selectedItemCount == 0) {
appt = &todaysApptList[selectedPos-1+ii];
} else {
appt = apptFromListEntry(selectedItems[ii]);
}
sprintf(apptString, apptFormat,
appt->date, appt->start, appt->end, appt->what);
/*
* Supply the appointment(s) for transfer
*/
if (convertInfo->reason == DtCR_DND_CONVERT_DATA) {
/* Copy the appointment into the buffer for transfer */
buffers[ii].bp = XtNewString(apptString);
buffers[ii].size = strlen(buffers[ii].bp);
/* Supply the name for the appointment */
labelString = apptGetLabel(apptString);
if (labelString == NULL) {
buffers[ii].name = (char *)NULL;
} else {
buffers[ii].name = XtNewString(labelString);
XtFree(labelString);
}
/*
* Delete the moved appointment(s)
*/
} else if (convertInfo->reason == DtCR_DND_CONVERT_DELETE) {
printf("Delete appointment for %s\n", appt->what);
}
}
}
/*
* apptDragFinishCallback
*
* Free buffer data/names allocated in apptConvertCallback()
*/
void
apptDragFinishCallback(
Widget widget,
XtPointer clientData,
XtPointer callData)
{
DtDndDragFinishCallbackStruct *dropFinishInfo =
(DtDndDragFinishCallbackStruct *)callData;
DtDndContext *dragData = dropFinishInfo->dragData;
int ii;
for (ii = 0; ii < dragData->numItems; ii++) {
XtFree(dragData->data.buffers[ii].bp);
if (dragData->data.buffers[ii].name != NULL)
XtFree(dragData->data.buffers[ii].name);
}
}
/*
* apptTransferCallback
*
* Handles the transfer of an appointment to the draw area drop site.
* Adds the appropriate icon to the list of icons on the draw area.
*/
void
apptTransferCallback(
Widget widget,
XtPointer clientData,
XtPointer callData)
{
DtDndTransferCallbackStruct *transferInfo =
(DtDndTransferCallbackStruct*) callData;
DtDndBuffer *buffers;
IconInfo *iconList, *iconPtr;
char *name;
char *filename;
int ii;
if (transferInfo == NULL) {
return;
}
/*
* Verify the validity of the callback reason.
*/
if (transferInfo->dropData->protocol != DtDND_BUFFER_TRANSFER ||
transferInfo->reason != DtCR_DND_TRANSFER_DATA) {
return;
}
/*
* Use abbreviated method of reffering to the data buffers.
*/
if (transferInfo != NULL && transferInfo->dropData != NULL) {
buffers = transferInfo->dropData->data.buffers;
} else {
return;
}
/*
* Process each item being transfered.
*/
XtVaGetValues(widget, XmNuserData, &iconList, NULL);
for (ii = 0; ii < transferInfo->dropData->numItems; ii++) {
/*
* Check format of buffer
*/
/*
* Transfer the buffer data. Here there is no actual transfer
* taking place. Only the icons representing the appointments
* are created to indicate the transfer.
*/
name = buffers[ii].name;
if (name == NULL)
name = "unnamed";
/* Create file from buffer */
filename = fileStoreBuffer(buffers[ii].name,
buffers[ii].bp, buffers[ii].size);
printf("Stored buffer into '%s'\n", filename);
XtFree(filename);
/* Create icon */
iconPtr = IconNew();
IconInitialize(widget, iconPtr,
transferInfo->x + ii * 10,
transferInfo->y + ii * 10,
buffers[ii].bp, buffers[ii].size, name, IconByData);
/* Add to icon list on drop site */
iconPtr->next = iconList;
if (iconList != NULL) {
iconList->prev = iconPtr;
}
iconList = iconPtr;
XtVaSetValues(widget, XmNuserData, iconList, NULL);
}
}
/*
* apptDragSetup
*
* Prepares the appointment list to source drags of appointments with button 1.
*/
void apptDragSetup(Widget apptDragSource)
{
static char translations[] = "\
~c ~s ~m ~a <Btn1Down>:\
demoProcessPress(ListBeginSelect,apptDragStart)\n\
c ~s ~m ~a <Btn1Down>:\
demoProcessPress(ListBeginToggle,apptDragStart)";
static char btn2_translations[] = "\
~c ~s ~m ~a <Btn2Down>:\
demoProcessPress(ListBeginSelect,apptDragStart)\n\
c ~s ~m ~a <Btn2Down>:\
demoProcessPress(ListBeginToggle,apptDragStart)\n\
<Btn2Motion>:ListButtonMotion()\n\
~c ~s ~m ~a <Btn2Up>:ListEndSelect()\n\
c ~s ~m ~a <Btn2Up>:ListEndToggle()";
static XtActionsRec actionTable[] =
{
{"apptDragStart", (XtActionProc) &apptDragStart},
{"demoProcessPress", (XtActionProc) &demoProcessPress}
};
int btn1_transfer = 0;
XtTranslations new_translations;
XtAppAddActions(
demoAppContext,
actionTable,
sizeof(actionTable)/sizeof(actionTable[0]));
new_translations = XtParseTranslationTable(translations);
XtOverrideTranslations(apptDragSource, new_translations);
XtVaGetValues(
(Widget) XmGetXmDisplay(XtDisplayOfObject(apptDragSource)),
"enableBtn1Transfer", &btn1_transfer,
NULL);
if (btn1_transfer != True)
{
new_translations = XtParseTranslationTable(btn2_translations);
XtOverrideTranslations(apptDragSource, new_translations);
}
#if 0
XtAddEventHandler(apptDragSource, Button1MotionMask, False,
(XtEventHandler)demoDragMotionHandler,
(XtPointer)DtDND_BUFFER_TRANSFER);
#endif
}
/*
* apptDropSetup
*
* Such a function is not needed since the demoDropSetup in demo.c registers
* the draw area as a drop site for drops of buffers such as appointments.
*/
/*
* apptDragStart
*
* Initiates a drag of an appointment from the appointment list provided
* the pointer is over an appointment in the list.
*/
void
apptDragStart(
Widget widget,
XEvent *event)
{
static XtCallbackRec convertCBRec[] = { {apptConvertCallback, NULL},
{NULL, NULL} };
static XtCallbackRec dragFinishCBRec[] =
{ {demoDragFinishCallback, NULL},
{apptDragFinishCallback, NULL},
{NULL, NULL} };
static IconInfo *iconPtr = NULL;
Widget dragIcon;
Display *display = XtDisplay(widget);
int itemCount,
selectedPos,
selectedItemCount;
char apptString[1024];
convertCBRec[0].closure = (XtPointer)widget;
/*
* Get list of selected items from the scrolled list of appointments
*/
XtVaGetValues(widget,
XmNitemCount, &itemCount,
XmNselectedItemCount, &selectedItemCount,
NULL);
/*
* Find out which item the pointer was over when the drag began
*/
selectedPos = XmListYToPos(widget, event->xmotion.y);
if (selectedPos == 0 || selectedPos > itemCount) {
return;
}
XtVaSetValues(widget, XmNuserData, selectedPos, NULL);
/*
* Copy the appointment information into an appointment string
*/
sprintf(apptString, apptFormat,
todaysApptList[1].date, todaysApptList[1].start,
todaysApptList[1].end, todaysApptList[1].what);
/*
* Create drag icon for appointment buffer drag
*/
if (iconPtr == NULL) {
iconPtr = IconNew();
IconInitialize(widget, iconPtr, 0, 0,
apptString, strlen(apptString), NULL, IconByData);
}
if (iconPtr->dragIcon == NULL) {
iconPtr->dragIcon = DtDndCreateSourceIcon(widget,
iconPtr->bitmap, iconPtr->mask);
}
if (selectedItemCount > 1) {
dragIcon = NULL;
itemCount = selectedItemCount;
} else {
dragIcon = iconPtr->dragIcon;
itemCount = 1;
}
/*
* Start the drag
*/
if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, itemCount,
XmDROP_COPY,
convertCBRec, dragFinishCBRec,
DtNsourceIcon, dragIcon,
DtNbufferIsText, True,
NULL)
== NULL) {
printf("DragStart returned NULL.\n");
}
}
/*************************************************************************
*
* Appointment Creation, Initialization & Destruction
*
*************************************************************************/
/*
* apptCreateDragSource
*
* Create a scrolling list filled with appointments.
*/
Widget
apptCreateDragSource(
Widget parent)
{
Widget apptList;
XmString *apptListItems;
int apptCount;
apptCount = apptCreateList(&apptListItems);
apptList = XtVaCreateManagedWidget("apptList",
xmListWidgetClass, parent,
/*
* Uncomment the line specifying the selection policy to
* enable multiple buffer transfers from the scrolled list
* of appointments. WARNING: There is a bug in the interaction
* of the scrolled list and Drag and Drop which causes items
* in the scrolled list which are selected to appear unselected
* and vice versa.
*/
/* XmNselectionPolicy, XmMULTIPLE_SELECT, */
XmNitems, apptListItems,
XmNitemCount, apptCount,
NULL);
apptDestroyList(apptListItems, apptCount);
return apptList;
}
/*
* apptCreateDropSite
*
* Such a function is not needed since the drop site is the draw area which
* is created in demoCreateDropSite() in demo.c
*/
/*
* apptCreateList
*
* Creates a list of XmStrings with appointment data in them.
*/
static int
apptCreateList(
XmString **appts)
{
int ii, apptCount;
char tmpStr[256];
time_t now;
struct tm *tm;
now = time(&now);
tm = localtime(&now);
sprintf(today, "%2d/%2d/%2d", tm->tm_mon+1, tm->tm_mday, tm->tm_year);
for (ii = 0; todaysApptList[ii].date; ii++);
apptCount = ii;
*appts = (XmString *) XtMalloc(sizeof(XmString) * apptCount);
for (ii = 0; todaysApptList[ii].date; ii++) {
sprintf(tmpStr, "%s %s", todaysApptList[ii].start,
todaysApptList[ii].what);
(*appts)[ii] = XmStringCreate(tmpStr, XmFONTLIST_DEFAULT_TAG);
}
return apptCount;
}
/*
* apptDestroyList
*
* Destroys a list of XmStrings with appointment data in them.
*/
static void
apptDestroyList(
XmString *appts,
int apptCount)
{
int ii;
for (ii = 0; ii < apptCount; ii++) {
XmStringFree(appts[ii]);
}
XtFree((char *)appts);
}
/*************************************************************************
*
* Appointment Utility Functions
*
*************************************************************************/
/*
* apptFromListEntry
*
* Returns the full appointment based on the text of the appointment as
* given in the text entry from the scrolled list of appointments.
*/
static Appointment*
apptFromListEntry(
XmString listEntry)
{
int ii;
char *entryText,
*string;
/*
* Get text string from XmString for use in comparisons
*/
entryText = XmStringUnparse(listEntry, NULL, XmCHARSET_TEXT,
XmCHARSET_TEXT, NULL, 0, XmOUTPUT_ALL);
for (ii = 0; todaysApptList[ii].what != NULL; ii++) {
string = strstr(entryText, todaysApptList[ii].what);
if (string != NULL) {
XtFree(entryText);
return(&todaysApptList[ii]);
}
}
XtFree(entryText);
return NULL;
}
/*
* apptGetLabel
*
* Creates a label for an appointment icon given an appointment.
*/
static char*
apptGetLabel(
char *appt)
{
char start[128];
int count;
if (appt == NULL) {
return NULL;
}
appt = strstr(appt, "Start:");
count = sscanf(appt, "Start:%*[ \t]%[^\n]", start);
if (count != 1) {
return NULL;
}
return XtNewString(start);
}