/* ========================== Module _Drag ========================== */

#include "Python.h"
#include "pymactoolbox.h"

#if APPLE_SUPPORTS_QUICKTIME

/* Macro to test whether a weak-loaded CFM function exists */
#define PyMac_PRECHECK(rtn) do { if ( &rtn == NULL )  {\
        PyErr_SetString(PyExc_NotImplementedError, \
            "Not available in this shared library/OS version"); \
        return NULL; \
    }} while(0)


#include <Carbon/Carbon.h>

/* Callback glue routines */
DragTrackingHandlerUPP dragglue_TrackingHandlerUPP;
DragReceiveHandlerUPP dragglue_ReceiveHandlerUPP;
DragSendDataUPP dragglue_SendDataUPP;
#if 0
DragInputUPP dragglue_InputUPP;
DragDrawingUPP dragglue_DrawingUPP;
#endif

#ifdef USE_TOOLBOX_OBJECT_GLUE
extern PyObject *_DragObj_New(DragRef);
extern int _DragObj_Convert(PyObject *, DragRef *);

#define DragObj_New _DragObj_New
#define DragObj_Convert _DragObj_Convert
#endif

static PyObject *Drag_Error;

/* ---------------------- Object type DragObj ----------------------- */

PyTypeObject DragObj_Type;

#define DragObj_Check(x) ((x)->ob_type == &DragObj_Type || PyObject_TypeCheck((x), &DragObj_Type))

typedef struct DragObjObject {
    PyObject_HEAD
    DragRef ob_itself;
    PyObject *sendproc;
} DragObjObject;

PyObject *DragObj_New(DragRef itself)
{
    DragObjObject *it;
    if (itself == NULL) {
                                    PyErr_SetString(Drag_Error,"Cannot create null Drag");
                                    return NULL;
                            }
    it = PyObject_NEW(DragObjObject, &DragObj_Type);
    if (it == NULL) return NULL;
    it->ob_itself = itself;
    it->sendproc = NULL;
    return (PyObject *)it;
}

int DragObj_Convert(PyObject *v, DragRef *p_itself)
{
    if (!DragObj_Check(v))
    {
        PyErr_SetString(PyExc_TypeError, "DragObj required");
        return 0;
    }
    *p_itself = ((DragObjObject *)v)->ob_itself;
    return 1;
}

static void DragObj_dealloc(DragObjObject *self)
{
    Py_XDECREF(self->sendproc);
    self->ob_type->tp_free((PyObject *)self);
}

static PyObject *DragObj_DisposeDrag(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
#ifndef DisposeDrag
    PyMac_PRECHECK(DisposeDrag);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = DisposeDrag(_self->ob_itself);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_AddDragItemFlavor(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    FlavorType theType;
    char *dataPtr__in__;
    long dataPtr__len__;
    int dataPtr__in_len__;
    FlavorFlags theFlags;
#ifndef AddDragItemFlavor
    PyMac_PRECHECK(AddDragItemFlavor);
#endif
    if (!PyArg_ParseTuple(_args, "lO&z#l",
                          &theItemRef,
                          PyMac_GetOSType, &theType,
                          &dataPtr__in__, &dataPtr__in_len__,
                          &theFlags))
        return NULL;
    dataPtr__len__ = dataPtr__in_len__;
    _err = AddDragItemFlavor(_self->ob_itself,
                             theItemRef,
                             theType,
                             dataPtr__in__, dataPtr__len__,
                             theFlags);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_SetDragItemFlavorData(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    FlavorType theType;
    char *dataPtr__in__;
    long dataPtr__len__;
    int dataPtr__in_len__;
    UInt32 dataOffset;
#ifndef SetDragItemFlavorData
    PyMac_PRECHECK(SetDragItemFlavorData);
#endif
    if (!PyArg_ParseTuple(_args, "lO&z#l",
                          &theItemRef,
                          PyMac_GetOSType, &theType,
                          &dataPtr__in__, &dataPtr__in_len__,
                          &dataOffset))
        return NULL;
    dataPtr__len__ = dataPtr__in_len__;
    _err = SetDragItemFlavorData(_self->ob_itself,
                                 theItemRef,
                                 theType,
                                 dataPtr__in__, dataPtr__len__,
                                 dataOffset);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_SetDragImage(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    PixMapHandle imagePixMap;
    RgnHandle imageRgn;
    Point imageOffsetPt;
    DragImageFlags theImageFlags;
#ifndef SetDragImage
    PyMac_PRECHECK(SetDragImage);
#endif
    if (!PyArg_ParseTuple(_args, "O&O&O&l",
                          ResObj_Convert, &imagePixMap,
                          ResObj_Convert, &imageRgn,
                          PyMac_GetPoint, &imageOffsetPt,
                          &theImageFlags))
        return NULL;
    _err = SetDragImage(_self->ob_itself,
                        imagePixMap,
                        imageRgn,
                        imageOffsetPt,
                        theImageFlags);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_ChangeDragBehaviors(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    DragBehaviors inBehaviorsToSet;
    DragBehaviors inBehaviorsToClear;
#ifndef ChangeDragBehaviors
    PyMac_PRECHECK(ChangeDragBehaviors);
#endif
    if (!PyArg_ParseTuple(_args, "ll",
                          &inBehaviorsToSet,
                          &inBehaviorsToClear))
        return NULL;
    _err = ChangeDragBehaviors(_self->ob_itself,
                               inBehaviorsToSet,
                               inBehaviorsToClear);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_TrackDrag(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    EventRecord theEvent;
    RgnHandle theRegion;
#ifndef TrackDrag
    PyMac_PRECHECK(TrackDrag);
#endif
    if (!PyArg_ParseTuple(_args, "O&O&",
                          PyMac_GetEventRecord, &theEvent,
                          ResObj_Convert, &theRegion))
        return NULL;
    _err = TrackDrag(_self->ob_itself,
                     &theEvent,
                     theRegion);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_CountDragItems(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    UInt16 numItems;
#ifndef CountDragItems
    PyMac_PRECHECK(CountDragItems);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = CountDragItems(_self->ob_itself,
                          &numItems);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("H",
                         numItems);
    return _res;
}

static PyObject *DragObj_GetDragItemReferenceNumber(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    UInt16 index;
    ItemReference theItemRef;
#ifndef GetDragItemReferenceNumber
    PyMac_PRECHECK(GetDragItemReferenceNumber);
#endif
    if (!PyArg_ParseTuple(_args, "H",
                          &index))
        return NULL;
    _err = GetDragItemReferenceNumber(_self->ob_itself,
                                      index,
                                      &theItemRef);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("l",
                         theItemRef);
    return _res;
}

static PyObject *DragObj_CountDragItemFlavors(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    UInt16 numFlavors;
#ifndef CountDragItemFlavors
    PyMac_PRECHECK(CountDragItemFlavors);
#endif
    if (!PyArg_ParseTuple(_args, "l",
                          &theItemRef))
        return NULL;
    _err = CountDragItemFlavors(_self->ob_itself,
                                theItemRef,
                                &numFlavors);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("H",
                         numFlavors);
    return _res;
}

static PyObject *DragObj_GetFlavorType(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    UInt16 index;
    FlavorType theType;
#ifndef GetFlavorType
    PyMac_PRECHECK(GetFlavorType);
#endif
    if (!PyArg_ParseTuple(_args, "lH",
                          &theItemRef,
                          &index))
        return NULL;
    _err = GetFlavorType(_self->ob_itself,
                         theItemRef,
                         index,
                         &theType);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("O&",
                         PyMac_BuildOSType, theType);
    return _res;
}

static PyObject *DragObj_GetFlavorFlags(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    FlavorType theType;
    FlavorFlags theFlags;
#ifndef GetFlavorFlags
    PyMac_PRECHECK(GetFlavorFlags);
#endif
    if (!PyArg_ParseTuple(_args, "lO&",
                          &theItemRef,
                          PyMac_GetOSType, &theType))
        return NULL;
    _err = GetFlavorFlags(_self->ob_itself,
                          theItemRef,
                          theType,
                          &theFlags);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("l",
                         theFlags);
    return _res;
}

static PyObject *DragObj_GetFlavorDataSize(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    FlavorType theType;
    Size dataSize;
#ifndef GetFlavorDataSize
    PyMac_PRECHECK(GetFlavorDataSize);
#endif
    if (!PyArg_ParseTuple(_args, "lO&",
                          &theItemRef,
                          PyMac_GetOSType, &theType))
        return NULL;
    _err = GetFlavorDataSize(_self->ob_itself,
                             theItemRef,
                             theType,
                             &dataSize);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("l",
                         dataSize);
    return _res;
}

static PyObject *DragObj_GetFlavorData(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    FlavorType theType;
    char *dataPtr__out__;
    long dataPtr__len__;
    int dataPtr__in_len__;
    UInt32 dataOffset;
#ifndef GetFlavorData
    PyMac_PRECHECK(GetFlavorData);
#endif
    if (!PyArg_ParseTuple(_args, "lO&il",
                          &theItemRef,
                          PyMac_GetOSType, &theType,
                          &dataPtr__in_len__,
                          &dataOffset))
        return NULL;
    if ((dataPtr__out__ = malloc(dataPtr__in_len__)) == NULL)
    {
        PyErr_NoMemory();
        goto dataPtr__error__;
    }
    dataPtr__len__ = dataPtr__in_len__;
    _err = GetFlavorData(_self->ob_itself,
                         theItemRef,
                         theType,
                         dataPtr__out__, &dataPtr__len__,
                         dataOffset);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("s#",
                         dataPtr__out__, (int)dataPtr__len__);
    free(dataPtr__out__);
 dataPtr__error__: ;
    return _res;
}

static PyObject *DragObj_GetDragItemBounds(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    Rect itemBounds;
#ifndef GetDragItemBounds
    PyMac_PRECHECK(GetDragItemBounds);
#endif
    if (!PyArg_ParseTuple(_args, "l",
                          &theItemRef))
        return NULL;
    _err = GetDragItemBounds(_self->ob_itself,
                             theItemRef,
                             &itemBounds);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("O&",
                         PyMac_BuildRect, &itemBounds);
    return _res;
}

static PyObject *DragObj_SetDragItemBounds(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    ItemReference theItemRef;
    Rect itemBounds;
#ifndef SetDragItemBounds
    PyMac_PRECHECK(SetDragItemBounds);
#endif
    if (!PyArg_ParseTuple(_args, "lO&",
                          &theItemRef,
                          PyMac_GetRect, &itemBounds))
        return NULL;
    _err = SetDragItemBounds(_self->ob_itself,
                             theItemRef,
                             &itemBounds);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_GetDropLocation(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    AEDesc dropLocation;
#ifndef GetDropLocation
    PyMac_PRECHECK(GetDropLocation);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = GetDropLocation(_self->ob_itself,
                           &dropLocation);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("O&",
                         AEDesc_New, &dropLocation);
    return _res;
}

static PyObject *DragObj_SetDropLocation(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    AEDesc dropLocation;
#ifndef SetDropLocation
    PyMac_PRECHECK(SetDropLocation);
#endif
    if (!PyArg_ParseTuple(_args, "O&",
                          AEDesc_Convert, &dropLocation))
        return NULL;
    _err = SetDropLocation(_self->ob_itself,
                           &dropLocation);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_GetDragAttributes(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    DragAttributes flags;
#ifndef GetDragAttributes
    PyMac_PRECHECK(GetDragAttributes);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = GetDragAttributes(_self->ob_itself,
                             &flags);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("l",
                         flags);
    return _res;
}

static PyObject *DragObj_GetDragMouse(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    Point mouse;
    Point globalPinnedMouse;
#ifndef GetDragMouse
    PyMac_PRECHECK(GetDragMouse);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = GetDragMouse(_self->ob_itself,
                        &mouse,
                        &globalPinnedMouse);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("O&O&",
                         PyMac_BuildPoint, mouse,
                         PyMac_BuildPoint, globalPinnedMouse);
    return _res;
}

static PyObject *DragObj_SetDragMouse(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    Point globalPinnedMouse;
#ifndef SetDragMouse
    PyMac_PRECHECK(SetDragMouse);
#endif
    if (!PyArg_ParseTuple(_args, "O&",
                          PyMac_GetPoint, &globalPinnedMouse))
        return NULL;
    _err = SetDragMouse(_self->ob_itself,
                        globalPinnedMouse);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_GetDragOrigin(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    Point globalInitialMouse;
#ifndef GetDragOrigin
    PyMac_PRECHECK(GetDragOrigin);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = GetDragOrigin(_self->ob_itself,
                         &globalInitialMouse);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("O&",
                         PyMac_BuildPoint, globalInitialMouse);
    return _res;
}

static PyObject *DragObj_GetDragModifiers(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    SInt16 modifiers;
    SInt16 mouseDownModifiers;
    SInt16 mouseUpModifiers;
#ifndef GetDragModifiers
    PyMac_PRECHECK(GetDragModifiers);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = GetDragModifiers(_self->ob_itself,
                            &modifiers,
                            &mouseDownModifiers,
                            &mouseUpModifiers);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("hhh",
                         modifiers,
                         mouseDownModifiers,
                         mouseUpModifiers);
    return _res;
}

static PyObject *DragObj_ShowDragHilite(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    RgnHandle hiliteFrame;
    Boolean inside;
#ifndef ShowDragHilite
    PyMac_PRECHECK(ShowDragHilite);
#endif
    if (!PyArg_ParseTuple(_args, "O&b",
                          ResObj_Convert, &hiliteFrame,
                          &inside))
        return NULL;
    _err = ShowDragHilite(_self->ob_itself,
                          hiliteFrame,
                          inside);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_HideDragHilite(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
#ifndef HideDragHilite
    PyMac_PRECHECK(HideDragHilite);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = HideDragHilite(_self->ob_itself);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_DragPreScroll(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    SInt16 dH;
    SInt16 dV;
#ifndef DragPreScroll
    PyMac_PRECHECK(DragPreScroll);
#endif
    if (!PyArg_ParseTuple(_args, "hh",
                          &dH,
                          &dV))
        return NULL;
    _err = DragPreScroll(_self->ob_itself,
                         dH,
                         dV);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_DragPostScroll(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
#ifndef DragPostScroll
    PyMac_PRECHECK(DragPostScroll);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = DragPostScroll(_self->ob_itself);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *DragObj_UpdateDragHilite(DragObjObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    RgnHandle updateRgn;
#ifndef UpdateDragHilite
    PyMac_PRECHECK(UpdateDragHilite);
#endif
    if (!PyArg_ParseTuple(_args, "O&",
                          ResObj_Convert, &updateRgn))
        return NULL;
    _err = UpdateDragHilite(_self->ob_itself,
                            updateRgn);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyMethodDef DragObj_methods[] = {
    {"DisposeDrag", (PyCFunction)DragObj_DisposeDrag, 1,
     PyDoc_STR("() -> None")},
    {"AddDragItemFlavor", (PyCFunction)DragObj_AddDragItemFlavor, 1,
     PyDoc_STR("(ItemReference theItemRef, FlavorType theType, Buffer dataPtr, FlavorFlags theFlags) -> None")},
    {"SetDragItemFlavorData", (PyCFunction)DragObj_SetDragItemFlavorData, 1,
     PyDoc_STR("(ItemReference theItemRef, FlavorType theType, Buffer dataPtr, UInt32 dataOffset) -> None")},
    {"SetDragImage", (PyCFunction)DragObj_SetDragImage, 1,
     PyDoc_STR("(PixMapHandle imagePixMap, RgnHandle imageRgn, Point imageOffsetPt, DragImageFlags theImageFlags) -> None")},
    {"ChangeDragBehaviors", (PyCFunction)DragObj_ChangeDragBehaviors, 1,
     PyDoc_STR("(DragBehaviors inBehaviorsToSet, DragBehaviors inBehaviorsToClear) -> None")},
    {"TrackDrag", (PyCFunction)DragObj_TrackDrag, 1,
     PyDoc_STR("(EventRecord theEvent, RgnHandle theRegion) -> None")},
    {"CountDragItems", (PyCFunction)DragObj_CountDragItems, 1,
     PyDoc_STR("() -> (UInt16 numItems)")},
    {"GetDragItemReferenceNumber", (PyCFunction)DragObj_GetDragItemReferenceNumber, 1,
     PyDoc_STR("(UInt16 index) -> (ItemReference theItemRef)")},
    {"CountDragItemFlavors", (PyCFunction)DragObj_CountDragItemFlavors, 1,
     PyDoc_STR("(ItemReference theItemRef) -> (UInt16 numFlavors)")},
    {"GetFlavorType", (PyCFunction)DragObj_GetFlavorType, 1,
     PyDoc_STR("(ItemReference theItemRef, UInt16 index) -> (FlavorType theType)")},
    {"GetFlavorFlags", (PyCFunction)DragObj_GetFlavorFlags, 1,
     PyDoc_STR("(ItemReference theItemRef, FlavorType theType) -> (FlavorFlags theFlags)")},
    {"GetFlavorDataSize", (PyCFunction)DragObj_GetFlavorDataSize, 1,
     PyDoc_STR("(ItemReference theItemRef, FlavorType theType) -> (Size dataSize)")},
    {"GetFlavorData", (PyCFunction)DragObj_GetFlavorData, 1,
     PyDoc_STR("(ItemReference theItemRef, FlavorType theType, Buffer dataPtr, UInt32 dataOffset) -> (Buffer dataPtr)")},
    {"GetDragItemBounds", (PyCFunction)DragObj_GetDragItemBounds, 1,
     PyDoc_STR("(ItemReference theItemRef) -> (Rect itemBounds)")},
    {"SetDragItemBounds", (PyCFunction)DragObj_SetDragItemBounds, 1,
     PyDoc_STR("(ItemReference theItemRef, Rect itemBounds) -> None")},
    {"GetDropLocation", (PyCFunction)DragObj_GetDropLocation, 1,
     PyDoc_STR("() -> (AEDesc dropLocation)")},
    {"SetDropLocation", (PyCFunction)DragObj_SetDropLocation, 1,
     PyDoc_STR("(AEDesc dropLocation) -> None")},
    {"GetDragAttributes", (PyCFunction)DragObj_GetDragAttributes, 1,
     PyDoc_STR("() -> (DragAttributes flags)")},
    {"GetDragMouse", (PyCFunction)DragObj_GetDragMouse, 1,
     PyDoc_STR("() -> (Point mouse, Point globalPinnedMouse)")},
    {"SetDragMouse", (PyCFunction)DragObj_SetDragMouse, 1,
     PyDoc_STR("(Point globalPinnedMouse) -> None")},
    {"GetDragOrigin", (PyCFunction)DragObj_GetDragOrigin, 1,
     PyDoc_STR("() -> (Point globalInitialMouse)")},
    {"GetDragModifiers", (PyCFunction)DragObj_GetDragModifiers, 1,
     PyDoc_STR("() -> (SInt16 modifiers, SInt16 mouseDownModifiers, SInt16 mouseUpModifiers)")},
    {"ShowDragHilite", (PyCFunction)DragObj_ShowDragHilite, 1,
     PyDoc_STR("(RgnHandle hiliteFrame, Boolean inside) -> None")},
    {"HideDragHilite", (PyCFunction)DragObj_HideDragHilite, 1,
     PyDoc_STR("() -> None")},
    {"DragPreScroll", (PyCFunction)DragObj_DragPreScroll, 1,
     PyDoc_STR("(SInt16 dH, SInt16 dV) -> None")},
    {"DragPostScroll", (PyCFunction)DragObj_DragPostScroll, 1,
     PyDoc_STR("() -> None")},
    {"UpdateDragHilite", (PyCFunction)DragObj_UpdateDragHilite, 1,
     PyDoc_STR("(RgnHandle updateRgn) -> None")},
    {NULL, NULL, 0}
};

#define DragObj_getsetlist NULL


#define DragObj_compare NULL

#define DragObj_repr NULL

#define DragObj_hash NULL
#define DragObj_tp_init 0

#define DragObj_tp_alloc PyType_GenericAlloc

static PyObject *DragObj_tp_new(PyTypeObject *type, PyObject *_args, PyObject *_kwds)
{
    PyObject *_self;
    DragRef itself;
    char *kw[] = {"itself", 0};

    if (!PyArg_ParseTupleAndKeywords(_args, _kwds, "O&", kw, DragObj_Convert, &itself)) return NULL;
    if ((_self = type->tp_alloc(type, 0)) == NULL) return NULL;
    ((DragObjObject *)_self)->ob_itself = itself;
    return _self;
}

#define DragObj_tp_free PyObject_Del


PyTypeObject DragObj_Type = {
    PyObject_HEAD_INIT(NULL)
    0, /*ob_size*/
    "_Drag.DragObj", /*tp_name*/
    sizeof(DragObjObject), /*tp_basicsize*/
    0, /*tp_itemsize*/
    /* methods */
    (destructor) DragObj_dealloc, /*tp_dealloc*/
    0, /*tp_print*/
    (getattrfunc)0, /*tp_getattr*/
    (setattrfunc)0, /*tp_setattr*/
    (cmpfunc) DragObj_compare, /*tp_compare*/
    (reprfunc) DragObj_repr, /*tp_repr*/
    (PyNumberMethods *)0, /* tp_as_number */
    (PySequenceMethods *)0, /* tp_as_sequence */
    (PyMappingMethods *)0, /* tp_as_mapping */
    (hashfunc) DragObj_hash, /*tp_hash*/
    0, /*tp_call*/
    0, /*tp_str*/
    PyObject_GenericGetAttr, /*tp_getattro*/
    PyObject_GenericSetAttr, /*tp_setattro */
    0, /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
    0, /*tp_doc*/
    0, /*tp_traverse*/
    0, /*tp_clear*/
    0, /*tp_richcompare*/
    0, /*tp_weaklistoffset*/
    0, /*tp_iter*/
    0, /*tp_iternext*/
    DragObj_methods, /* tp_methods */
    0, /*tp_members*/
    DragObj_getsetlist, /*tp_getset*/
    0, /*tp_base*/
    0, /*tp_dict*/
    0, /*tp_descr_get*/
    0, /*tp_descr_set*/
    0, /*tp_dictoffset*/
    DragObj_tp_init, /* tp_init */
    DragObj_tp_alloc, /* tp_alloc */
    DragObj_tp_new, /* tp_new */
    DragObj_tp_free, /* tp_free */
};

/* -------------------- End object type DragObj --------------------- */


static PyObject *Drag_NewDrag(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    DragRef theDrag;
#ifndef NewDrag
    PyMac_PRECHECK(NewDrag);
#endif
    if (!PyArg_ParseTuple(_args, ""))
        return NULL;
    _err = NewDrag(&theDrag);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("O&",
                         DragObj_New, theDrag);
    return _res;
}

static PyObject *Drag_GetDragHiliteColor(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    WindowPtr window;
    RGBColor color;
#ifndef GetDragHiliteColor
    PyMac_PRECHECK(GetDragHiliteColor);
#endif
    if (!PyArg_ParseTuple(_args, "O&",
                          WinObj_Convert, &window))
        return NULL;
    _err = GetDragHiliteColor(window,
                              &color);
    if (_err != noErr) return PyMac_Error(_err);
    _res = Py_BuildValue("O&",
                         QdRGB_New, &color);
    return _res;
}

static PyObject *Drag_WaitMouseMoved(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    Boolean _rv;
    Point initialMouse;
#ifndef WaitMouseMoved
    PyMac_PRECHECK(WaitMouseMoved);
#endif
    if (!PyArg_ParseTuple(_args, "O&",
                          PyMac_GetPoint, &initialMouse))
        return NULL;
    _rv = WaitMouseMoved(initialMouse);
    _res = Py_BuildValue("b",
                         _rv);
    return _res;
}

static PyObject *Drag_ZoomRects(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    Rect fromRect;
    Rect toRect;
    SInt16 zoomSteps;
    ZoomAcceleration acceleration;
#ifndef ZoomRects
    PyMac_PRECHECK(ZoomRects);
#endif
    if (!PyArg_ParseTuple(_args, "O&O&hh",
                          PyMac_GetRect, &fromRect,
                          PyMac_GetRect, &toRect,
                          &zoomSteps,
                          &acceleration))
        return NULL;
    _err = ZoomRects(&fromRect,
                     &toRect,
                     zoomSteps,
                     acceleration);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *Drag_ZoomRegion(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;
    OSErr _err;
    RgnHandle region;
    Point zoomDistance;
    SInt16 zoomSteps;
    ZoomAcceleration acceleration;
#ifndef ZoomRegion
    PyMac_PRECHECK(ZoomRegion);
#endif
    if (!PyArg_ParseTuple(_args, "O&O&hh",
                          ResObj_Convert, &region,
                          PyMac_GetPoint, &zoomDistance,
                          &zoomSteps,
                          &acceleration))
        return NULL;
    _err = ZoomRegion(region,
                      zoomDistance,
                      zoomSteps,
                      acceleration);
    if (_err != noErr) return PyMac_Error(_err);
    Py_INCREF(Py_None);
    _res = Py_None;
    return _res;
}

static PyObject *Drag_InstallTrackingHandler(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;

        PyObject *callback;
        WindowPtr theWindow = NULL;
        OSErr _err;

        if ( !PyArg_ParseTuple(_args, "O|O&", &callback, WinObj_Convert, &theWindow) )
        return NULL;
        Py_INCREF(callback);        /* Cannot decref later, too bad */
        _err = InstallTrackingHandler(dragglue_TrackingHandlerUPP, theWindow, (void *)callback);
        if (_err != noErr) return PyMac_Error(_err);
        Py_INCREF(Py_None);
        _res = Py_None;
        return _res;

}

static PyObject *Drag_InstallReceiveHandler(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;

        PyObject *callback;
        WindowPtr theWindow = NULL;
        OSErr _err;

        if ( !PyArg_ParseTuple(_args, "O|O&", &callback, WinObj_Convert, &theWindow) )
        return NULL;
        Py_INCREF(callback);        /* Cannot decref later, too bad */
        _err = InstallReceiveHandler(dragglue_ReceiveHandlerUPP, theWindow, (void *)callback);
        if (_err != noErr) return PyMac_Error(_err);
        Py_INCREF(Py_None);
        _res = Py_None;
        return _res;

}

static PyObject *Drag_RemoveTrackingHandler(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;

        WindowPtr theWindow = NULL;
        OSErr _err;

        if ( !PyArg_ParseTuple(_args, "|O&", WinObj_Convert, &theWindow) )
        return NULL;
        _err = RemoveTrackingHandler(dragglue_TrackingHandlerUPP, theWindow);
        if (_err != noErr) return PyMac_Error(_err);
        Py_INCREF(Py_None);
        _res = Py_None;
        return _res;

}

static PyObject *Drag_RemoveReceiveHandler(PyObject *_self, PyObject *_args)
{
    PyObject *_res = NULL;

        WindowPtr theWindow = NULL;
        OSErr _err;

        if ( !PyArg_ParseTuple(_args, "|O&", WinObj_Convert, &theWindow) )
        return NULL;
        _err = RemoveReceiveHandler(dragglue_ReceiveHandlerUPP, theWindow);
        if (_err != noErr) return PyMac_Error(_err);
        Py_INCREF(Py_None);
        _res = Py_None;
        return _res;

}

static PyMethodDef Drag_methods[] = {
    {"NewDrag", (PyCFunction)Drag_NewDrag, 1,
     PyDoc_STR("() -> (DragRef theDrag)")},
    {"GetDragHiliteColor", (PyCFunction)Drag_GetDragHiliteColor, 1,
     PyDoc_STR("(WindowPtr window) -> (RGBColor color)")},
    {"WaitMouseMoved", (PyCFunction)Drag_WaitMouseMoved, 1,
     PyDoc_STR("(Point initialMouse) -> (Boolean _rv)")},
    {"ZoomRects", (PyCFunction)Drag_ZoomRects, 1,
     PyDoc_STR("(Rect fromRect, Rect toRect, SInt16 zoomSteps, ZoomAcceleration acceleration) -> None")},
    {"ZoomRegion", (PyCFunction)Drag_ZoomRegion, 1,
     PyDoc_STR("(RgnHandle region, Point zoomDistance, SInt16 zoomSteps, ZoomAcceleration acceleration) -> None")},
    {"InstallTrackingHandler", (PyCFunction)Drag_InstallTrackingHandler, 1,
     PyDoc_STR(NULL)},
    {"InstallReceiveHandler", (PyCFunction)Drag_InstallReceiveHandler, 1,
     PyDoc_STR(NULL)},
    {"RemoveTrackingHandler", (PyCFunction)Drag_RemoveTrackingHandler, 1,
     PyDoc_STR(NULL)},
    {"RemoveReceiveHandler", (PyCFunction)Drag_RemoveReceiveHandler, 1,
     PyDoc_STR(NULL)},
    {NULL, NULL, 0}
};



static pascal OSErr
dragglue_TrackingHandler(DragTrackingMessage theMessage, WindowPtr theWindow,
                         void *handlerRefCon, DragReference theDrag)
{
    PyObject *args, *rv;
    int i;

    args = Py_BuildValue("hO&O&", theMessage, DragObj_New, theDrag, WinObj_WhichWindow, theWindow);
    if ( args == NULL )
        return -1;
    rv = PyEval_CallObject((PyObject *)handlerRefCon, args);
    Py_DECREF(args);
    if ( rv == NULL ) {
        PySys_WriteStderr("Drag: Exception in TrackingHandler\n");
        PyErr_Print();
        return -1;
    }
    i = -1;
    if ( rv == Py_None )
        i = 0;
    else
        PyArg_Parse(rv, "l", &i);
    Py_DECREF(rv);
    return i;
}

static pascal OSErr
dragglue_ReceiveHandler(WindowPtr theWindow, void *handlerRefCon,
                        DragReference theDrag)
{
    PyObject *args, *rv;
    int i;

    args = Py_BuildValue("O&O&", DragObj_New, theDrag, WinObj_WhichWindow, theWindow);
    if ( args == NULL )
        return -1;
    rv = PyEval_CallObject((PyObject *)handlerRefCon, args);
    Py_DECREF(args);
    if ( rv == NULL ) {
        PySys_WriteStderr("Drag: Exception in ReceiveHandler\n");
        PyErr_Print();
        return -1;
    }
    i = -1;
    if ( rv == Py_None )
        i = 0;
    else
        PyArg_Parse(rv, "l", &i);
    Py_DECREF(rv);
    return i;
}

static pascal OSErr
dragglue_SendData(FlavorType theType, void *dragSendRefCon,
                      ItemReference theItem, DragReference theDrag)
{
    DragObjObject *self = (DragObjObject *)dragSendRefCon;
    PyObject *args, *rv;
    int i;

    if ( self->sendproc == NULL )
        return -1;
    args = Py_BuildValue("O&l", PyMac_BuildOSType, theType, theItem);
    if ( args == NULL )
        return -1;
    rv = PyEval_CallObject(self->sendproc, args);
    Py_DECREF(args);
    if ( rv == NULL ) {
        PySys_WriteStderr("Drag: Exception in SendDataHandler\n");
        PyErr_Print();
        return -1;
    }
    i = -1;
    if ( rv == Py_None )
        i = 0;
    else
        PyArg_Parse(rv, "l", &i);
    Py_DECREF(rv);
    return i;
}

#if 0
static pascal OSErr
dragglue_Input(Point *mouse, short *modifiers,
                   void *dragSendRefCon, DragReference theDrag)
{
    return 0;
}

static pascal OSErr
dragglue_Drawing(xxxx
                   void *dragSendRefCon, DragReference theDrag)
{
    return 0;
}
#endif
#else /* __LP64__ */
static PyMethodDef Drag_methods[] = {
    {NULL, NULL, 0}
};
#endif /* __LP64__ */


void init_Drag(void)
{
    PyObject *m;
#if APPLE_SUPPORTS_QUICKTIME
    PyObject *d;



        PyMac_INIT_TOOLBOX_OBJECT_NEW(DragRef, DragObj_New);
        PyMac_INIT_TOOLBOX_OBJECT_CONVERT(DragRef, DragObj_Convert);
#endif /* APPLE_SUPPORTS_QUICKTIME */


    m = Py_InitModule("_Drag", Drag_methods);
#if APPLE_SUPPORTS_QUICKTIME
    d = PyModule_GetDict(m);
    Drag_Error = PyMac_GetOSErrException();
    if (Drag_Error == NULL ||
        PyDict_SetItemString(d, "Error", Drag_Error) != 0)
        return;
    DragObj_Type.ob_type = &PyType_Type;
    if (PyType_Ready(&DragObj_Type) < 0) return;
    Py_INCREF(&DragObj_Type);
    PyModule_AddObject(m, "DragObj", (PyObject *)&DragObj_Type);
    /* Backward-compatible name */
    Py_INCREF(&DragObj_Type);
    PyModule_AddObject(m, "DragObjType", (PyObject *)&DragObj_Type);

    dragglue_TrackingHandlerUPP = NewDragTrackingHandlerUPP(dragglue_TrackingHandler);
    dragglue_ReceiveHandlerUPP = NewDragReceiveHandlerUPP(dragglue_ReceiveHandler);
    dragglue_SendDataUPP = NewDragSendDataUPP(dragglue_SendData);
#if 0
    dragglue_InputUPP = NewDragInputUPP(dragglue_Input);
    dragglue_DrawingUPP = NewDragDrawingUPP(dragglue_Drawing);
#endif

#endif /* APPLE_SUPPORTS_QUICKTIME */

}

/* ======================== End module _Drag ======================== */