mirror of
https://github.com/gryf/wmaker.git
synced 2026-01-03 20:34:14 +01:00
removed listbag added tree bag
started drag & drop
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
changes since wmaker 0.61.1:
|
||||
............................
|
||||
|
||||
- WARNING: semantic of bags has changed!
|
||||
An index assigned to an item will always keep that index unless
|
||||
you insert an item before it.
|
||||
|
||||
For example:
|
||||
bag = WMCreateBag();
|
||||
WMSetInBag(bag, 10, "bla");
|
||||
That code will put "bla" in index 10, instead of 0, as it used to be.
|
||||
- fixed WMInsertInBag(). It ignored index, and always put the new item at end.
|
||||
- added WMSaveUserDefaults().
|
||||
- rewrote WMPopUpButton to use WMMenuItem
|
||||
|
||||
@@ -60,6 +60,8 @@ libWINGs_a_SOURCES = \
|
||||
WINGs.h \
|
||||
WINGsP.h \
|
||||
configuration.c \
|
||||
dragdestination.c \
|
||||
dragsource.c \
|
||||
international.c \
|
||||
notification.c \
|
||||
selection.c \
|
||||
@@ -97,7 +99,7 @@ libWINGs_a_SOURCES = \
|
||||
error.c \
|
||||
findfile.c \
|
||||
bagarray.c \
|
||||
baglist.c \
|
||||
bagtree.c \
|
||||
connection.c \
|
||||
data.c \
|
||||
hashtable.c \
|
||||
@@ -110,7 +112,7 @@ libWUtil_a_SOURCES = \
|
||||
WINGs.h \
|
||||
WINGsP.h \
|
||||
bagarray.c \
|
||||
baglist.c \
|
||||
bagtree.c \
|
||||
connection.c \
|
||||
data.c \
|
||||
host.c \
|
||||
|
||||
@@ -69,6 +69,7 @@ GFXLIBS = @GFXLIBS@
|
||||
HEADER_SEARCH_PATH = @HEADER_SEARCH_PATH@
|
||||
ICONEXT = @ICONEXT@
|
||||
INTLIBS = @INTLIBS@
|
||||
LD = @LD@
|
||||
LIBPL = @LIBPL@
|
||||
LIBRARY_SEARCH_PATH = @LIBRARY_SEARCH_PATH@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
@@ -78,6 +79,7 @@ MAKEINFO = @MAKEINFO@
|
||||
MOFILES = @MOFILES@
|
||||
NETLIBS = @NETLIBS@
|
||||
NLSDIR = @NLSDIR@
|
||||
NM = @NM@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
PACKAGE = @PACKAGE@
|
||||
RANLIB = @RANLIB@
|
||||
@@ -144,10 +146,10 @@ connect_LDADD = libWUtil.a @LIBRARY_SEARCH_PATH@ @NETLIBS@ @LIBPL@
|
||||
EXTRA_DIST = logo.xpm BUGS
|
||||
|
||||
# wbutton.c
|
||||
libWINGs_a_SOURCES = WINGs.h WINGsP.h configuration.c international.c notification.c selection.c userdefaults.c wapplication.c wappresource.c wballoon.c wbrowser.c wbutton.c wcolor.c wcolorpanel.c wcolorwell.c wevent.c wfilepanel.c wframe.c wfont.c wfontpanel.c widgets.c wlabel.c wlist.c wmenuitem.c wmisc.c wpanel.c wpixmap.c wpopupbutton.c wprogressindicator.c wscroller.c wscrollview.c wslider.c wsplitview.c wtabview.c wtextfield.c wwindow.c wview.c error.c findfile.c bagarray.c baglist.c connection.c data.c hashtable.c host.c memory.c usleep.c
|
||||
libWINGs_a_SOURCES = WINGs.h WINGsP.h configuration.c dragdestination.c dragsource.c international.c notification.c selection.c userdefaults.c wapplication.c wappresource.c wballoon.c wbrowser.c wbutton.c wcolor.c wcolorpanel.c wcolorwell.c wevent.c wfilepanel.c wframe.c wfont.c wfontpanel.c widgets.c wlabel.c wlist.c wmenuitem.c wmisc.c wpanel.c wpixmap.c wpopupbutton.c wprogressindicator.c wscroller.c wscrollview.c wslider.c wsplitview.c wtabview.c wtextfield.c wwindow.c wview.c error.c findfile.c bagarray.c bagtree.c connection.c data.c hashtable.c host.c memory.c usleep.c
|
||||
|
||||
|
||||
libWUtil_a_SOURCES = WINGs.h WINGsP.h bagarray.c baglist.c connection.c data.c host.c international.c notification.c userdefaults.c wapplication.c wutil.c error.c findfile.c hashtable.c memory.c usleep.c
|
||||
libWUtil_a_SOURCES = WINGs.h WINGsP.h bagarray.c bagtree.c connection.c data.c host.c international.c notification.c userdefaults.c wapplication.c wutil.c error.c findfile.c hashtable.c memory.c usleep.c
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/wrlib -I$(top_srcdir)/src -DRESOURCE_PATH=\"$(datadir)/WINGs\" @HEADER_SEARCH_PATH@ -DDEBUG
|
||||
@@ -166,16 +168,17 @@ X_CFLAGS = @X_CFLAGS@
|
||||
X_LIBS = @X_LIBS@
|
||||
X_PRE_LIBS = @X_PRE_LIBS@
|
||||
libWINGs_a_LIBADD =
|
||||
libWINGs_a_OBJECTS = configuration.o international.o notification.o \
|
||||
selection.o userdefaults.o wapplication.o wappresource.o wballoon.o \
|
||||
wbrowser.o wbutton.o wcolor.o wcolorpanel.o wcolorwell.o wevent.o \
|
||||
wfilepanel.o wframe.o wfont.o wfontpanel.o widgets.o wlabel.o wlist.o \
|
||||
wmenuitem.o wmisc.o wpanel.o wpixmap.o wpopupbutton.o \
|
||||
wprogressindicator.o wscroller.o wscrollview.o wslider.o wsplitview.o \
|
||||
wtabview.o wtextfield.o wwindow.o wview.o error.o findfile.o bagarray.o \
|
||||
baglist.o connection.o data.o hashtable.o host.o memory.o usleep.o
|
||||
libWINGs_a_OBJECTS = configuration.o dragdestination.o dragsource.o \
|
||||
international.o notification.o selection.o userdefaults.o \
|
||||
wapplication.o wappresource.o wballoon.o wbrowser.o wbutton.o wcolor.o \
|
||||
wcolorpanel.o wcolorwell.o wevent.o wfilepanel.o wframe.o wfont.o \
|
||||
wfontpanel.o widgets.o wlabel.o wlist.o wmenuitem.o wmisc.o wpanel.o \
|
||||
wpixmap.o wpopupbutton.o wprogressindicator.o wscroller.o wscrollview.o \
|
||||
wslider.o wsplitview.o wtabview.o wtextfield.o wwindow.o wview.o \
|
||||
error.o findfile.o bagarray.o bagtree.o connection.o data.o hashtable.o \
|
||||
host.o memory.o usleep.o
|
||||
libWUtil_a_LIBADD =
|
||||
libWUtil_a_OBJECTS = bagarray.o baglist.o connection.o data.o host.o \
|
||||
libWUtil_a_OBJECTS = bagarray.o bagtree.o connection.o data.o host.o \
|
||||
international.o notification.o userdefaults.o wapplication.o wutil.o \
|
||||
error.o findfile.o hashtable.o memory.o usleep.o
|
||||
AR = ar
|
||||
@@ -217,7 +220,7 @@ DIST_COMMON = README ChangeLog Makefile.am Makefile.in TODO
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
SOURCES = $(libWINGs_a_SOURCES) $(libWUtil_a_SOURCES) $(wtest_SOURCES) $(wmquery_SOURCES) $(wmfile_SOURCES) $(fontl_SOURCES) $(testmywidget_SOURCES) $(testcolorpanel_SOURCES) $(connect_SOURCES)
|
||||
OBJECTS = $(libWINGs_a_OBJECTS) $(libWUtil_a_OBJECTS) $(wtest_OBJECTS) $(wmquery_OBJECTS) $(wmfile_OBJECTS) $(fontl_OBJECTS) $(testmywidget_OBJECTS) $(testcolorpanel_OBJECTS) $(connect_OBJECTS)
|
||||
@@ -226,7 +229,7 @@ all: all-redirect
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .S .c .lo .o .s
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps WINGs/Makefile
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --gnu WINGs/Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
@@ -481,7 +484,7 @@ distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
cp -pr $$/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|
||||
@@ -107,14 +107,14 @@ DIST_COMMON = Makefile.am Makefile.in
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
TAR = gtar
|
||||
GZIP_ENV = --best
|
||||
all: all-redirect
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps WINGs/Resources/Makefile
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --gnu WINGs/Resources/Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
@@ -146,10 +146,15 @@ distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
subdir = WINGs/Resources
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
here=`cd $(top_builddir) && pwd`; \
|
||||
top_distdir=`cd $(top_distdir) && pwd`; \
|
||||
distdir=`cd $(distdir) && pwd`; \
|
||||
cd $(top_srcdir) \
|
||||
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu WINGs/Resources/Makefile
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
if test -d $$d/$$file; then \
|
||||
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||
cp -pr $$/$$file $(distdir)/$$file; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|
||||
@@ -474,6 +474,31 @@ typedef struct WMTabViewDelegate {
|
||||
|
||||
|
||||
|
||||
typedef struct W_DraggingInfo WMDraggingInfo;
|
||||
|
||||
|
||||
typedef struct W_DragSourceProcs {
|
||||
unsigned (*draggingSourceOperation)(WMView *self, Bool local);
|
||||
void (*beganDragImage)(WMView *self, WMPixmap *image, WMPoint point);
|
||||
void (*endedDragImage)(WMView *self, WMPixmap *image, WMPoint point,
|
||||
Bool deposited);
|
||||
WMData* (*fetchDragData)(WMView *self, char *type, Bool local);
|
||||
/* Bool (*ignoreModifierKeysWhileDragging)(WMView *view);*/
|
||||
} WMDragSourceProcs;
|
||||
|
||||
|
||||
|
||||
typedef struct W_DragDestinationProcs {
|
||||
unsigned (*draggingEntered)(WMView *self, WMDraggingInfo *info);
|
||||
unsigned (*draggingUpdated)(WMView *self, WMDraggingInfo *info);
|
||||
void (*draggingExited)(WMView *self, WMDraggingInfo *info);
|
||||
Bool (*prepareForDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||
Bool (*performDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||
void (*concludeDragOperation)(WMView *self, WMDraggingInfo *info);
|
||||
} WMDragDestinationProcs;
|
||||
|
||||
|
||||
|
||||
/* ...................................................................... */
|
||||
|
||||
|
||||
@@ -727,6 +752,8 @@ WMSize WMGetViewSize(WMView *view);
|
||||
|
||||
WMPoint WMGetViewPosition(WMView *view);
|
||||
|
||||
WMPoint WMGetViewScreenPosition(WMView *view);
|
||||
|
||||
WMWidget *WMWidgetOfView(WMView *view);
|
||||
|
||||
/* notifications */
|
||||
|
||||
@@ -24,7 +24,7 @@ extern "C" {
|
||||
|
||||
#define DOUBLE_BUFFER
|
||||
|
||||
|
||||
|
||||
|
||||
#define WC_UserWidget 128
|
||||
|
||||
@@ -32,22 +32,11 @@ extern "C" {
|
||||
|
||||
#define SCROLLER_WIDTH 20
|
||||
|
||||
/* internal messages */
|
||||
#define WM_UPDATE_COLORWELL 130
|
||||
|
||||
|
||||
#define WM_USER_MESSAGE 1024
|
||||
|
||||
|
||||
#define SETUP_INTERNAL_MESSAGE(event, scrPtr) \
|
||||
event.xclient.type=ClientMessage;\
|
||||
event.xclient.display=scrPtr->display;\
|
||||
event.xclient.send_event=False;\
|
||||
event.xclient.serial=0;\
|
||||
event.xclient.format=32;\
|
||||
event.xclient.message_type=scrPtr->internalMessage;
|
||||
|
||||
|
||||
|
||||
#define XDND_VERSION 4
|
||||
|
||||
|
||||
typedef struct W_Application {
|
||||
char *applicationName;
|
||||
int argc;
|
||||
@@ -101,6 +90,27 @@ typedef struct W_FocusInfo {
|
||||
} W_FocusInfo;
|
||||
|
||||
|
||||
|
||||
struct W_DraggingInfo {
|
||||
Window destinationWindow;
|
||||
Window sourceWindow;
|
||||
|
||||
WMPoint location;
|
||||
|
||||
unsigned sourceOperation;
|
||||
WMPixmap *image;
|
||||
WMPoint imageLocation;
|
||||
|
||||
Time timestamp;
|
||||
|
||||
int protocolVersion;
|
||||
|
||||
/* only valid if in the same app.. should be treated as internal data */
|
||||
// WMView *destination;
|
||||
// WMView *source;
|
||||
};
|
||||
|
||||
|
||||
typedef struct W_Screen {
|
||||
Display *display;
|
||||
int screen;
|
||||
@@ -145,6 +155,8 @@ typedef struct W_Screen {
|
||||
|
||||
Pixmap stipple;
|
||||
|
||||
struct W_DraggingInfo dragInfo;
|
||||
|
||||
/* colors */
|
||||
W_Color *white;
|
||||
W_Color *black;
|
||||
@@ -232,17 +244,26 @@ typedef struct W_Screen {
|
||||
Cursor textCursor;
|
||||
|
||||
Cursor invisibleCursor;
|
||||
|
||||
Atom internalMessage; /* for ClientMessage */
|
||||
|
||||
Atom attribsAtom; /* GNUstepWindowAttributes */
|
||||
|
||||
Atom deleteWindowAtom; /* WM_DELETE_WINDOW */
|
||||
|
||||
Atom protocolsAtom; /* _XA_WM_PROTOCOLS */
|
||||
|
||||
|
||||
Atom clipboardAtom; /* CLIPBOARD */
|
||||
|
||||
Atom xdndAwareAtom; /* XdndAware */
|
||||
Atom xdndSelectionAtom;
|
||||
Atom xdndEnterAtom;
|
||||
Atom xdndLeaveAtom;
|
||||
Atom xdndPositionAtom;
|
||||
Atom xdndDropAtom;
|
||||
Atom xdndFinishedAtom;
|
||||
Atom xdndTypeListAtom;
|
||||
Atom xdndStatusAtom;
|
||||
|
||||
Atom wmStateAtom; /* WM_STATE */
|
||||
|
||||
/* stuff for detecting double-clicks */
|
||||
Time lastClickTime; /* time of last mousedown event */
|
||||
@@ -302,11 +323,12 @@ typedef struct W_View {
|
||||
|
||||
WMColor *backColor;
|
||||
|
||||
#if 0
|
||||
|
||||
Atom *droppableTypes;
|
||||
struct W_DragSourceProcs *dragSourceProcs;
|
||||
struct W_DragDestinationProcs *dragDestinationProcs;
|
||||
int helpContext;
|
||||
#endif
|
||||
|
||||
|
||||
struct {
|
||||
unsigned int realized:1;
|
||||
@@ -329,6 +351,7 @@ typedef struct W_View {
|
||||
unsigned int pendingRelease3:1;
|
||||
unsigned int pendingRelease4:1;
|
||||
unsigned int pendingRelease5:1;
|
||||
unsigned int xdndHintSet:1;
|
||||
} flags;
|
||||
|
||||
int refCount;
|
||||
@@ -442,8 +465,6 @@ void W_BroadcastMessage(W_View *targetParent, XEvent *event);
|
||||
|
||||
void W_DispatchMessage(W_View *target, XEvent *event);
|
||||
|
||||
Bool W_CheckInternalMessage(W_Screen *scr, XClientMessageEvent *cev, int event);
|
||||
|
||||
void W_SetFocusOfToplevel(W_View *toplevel, W_View *view);
|
||||
|
||||
W_View *W_FocusedViewOfToplevel(W_View *view);
|
||||
@@ -468,6 +489,7 @@ char *W_GetTextSelection(WMScreen *scr, Atom selection);
|
||||
|
||||
void W_HandleSelectionEvent(XEvent *event);
|
||||
|
||||
void W_HandleDNDClientMessage(WMView *toplevel, XClientMessageEvent *event);
|
||||
|
||||
void W_FlushASAPNotificationQueue();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define _WUTIL_H_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* SunOS 4.x Blargh.... */
|
||||
@@ -10,7 +10,6 @@
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Warning: proplist.h #defines BOOL which will clash with the
|
||||
* typedef BOOL in Xmd.h
|
||||
@@ -102,6 +101,12 @@ typedef enum {
|
||||
} WMConnectionState;
|
||||
|
||||
|
||||
|
||||
enum {
|
||||
WBNotFound = INT_MAX /* element was not found in bag */
|
||||
};
|
||||
|
||||
|
||||
typedef struct W_Bag WMBag;
|
||||
typedef struct W_Data WMData;
|
||||
typedef struct W_HashTable WMHashTable;
|
||||
@@ -139,6 +144,8 @@ typedef struct {
|
||||
void (*releaseKey)(const void *);
|
||||
} WMHashTableCallbacks;
|
||||
|
||||
|
||||
typedef void *WMBagIterator;
|
||||
|
||||
typedef struct W_BagFunctions {
|
||||
int (*getItemCount)(WMBag *self);
|
||||
@@ -151,15 +158,17 @@ typedef struct W_BagFunctions {
|
||||
int (*firstInBag)(WMBag *bag, void *item);
|
||||
int (*countInBag)(WMBag *bag, void *item);
|
||||
void *(*replaceInBag)(WMBag *bag, int index, void *item);
|
||||
void (*sortBag)(WMBag *bag, int (*comparer)(const void*, const void*));
|
||||
int (*sortBag)(WMBag *bag, int (*comparer)(const void*, const void*));
|
||||
void (*emptyBag)(WMBag *bag);
|
||||
void (*freeBag)(WMBag *bag);
|
||||
WMBag *(*mapBag)(WMBag *bag, void * (*function)(void*));
|
||||
void (*mapBag)(WMBag *bag, void (*function)(void*, void*), void *data);
|
||||
int (*findInBag)(WMBag *bag, int (*match)(void*));
|
||||
void *(*first)(WMBag *bag, void **ptr);
|
||||
void *(*last)(WMBag *bag, void **ptr);
|
||||
void *(*next)(WMBag *bag, void **ptr);
|
||||
void *(*previous)(WMBag *bag, void **ptr);
|
||||
void *(*first)(WMBag *bag, WMBagIterator *ptr);
|
||||
void *(*last)(WMBag *bag, WMBagIterator *ptr);
|
||||
void *(*next)(WMBag *bag, WMBagIterator *ptr);
|
||||
void *(*previous)(WMBag *bag, WMBagIterator *ptr);
|
||||
void *(*iteratorAtIndex)(WMBag *bag, int index, WMBagIterator *ptr);
|
||||
int (*indexForIterator)(WMBag *bag, WMBagIterator ptr);
|
||||
} W_BagFunctions;
|
||||
|
||||
|
||||
@@ -305,14 +314,44 @@ extern const WMHashTableCallbacks WMStringPointerHashCallbacks;
|
||||
/*......................................................................*/
|
||||
|
||||
|
||||
WMBag* WMCreateArrayBag(int size);
|
||||
WMBag* WMCreateArrayBagWithDestructor(int size, void (*destructor)(void*));
|
||||
/*
|
||||
* Array bags use an array to store the elements.
|
||||
* Item indexes may be any integer number.
|
||||
*
|
||||
* Pros:
|
||||
* Fast [O(1)] access to elements
|
||||
* Fast [O(1)] push/pop
|
||||
*
|
||||
* Cons:
|
||||
* A little slower [O(n)] for insertion/deletion of elements that
|
||||
* arent in the end
|
||||
* Element indexes with large difference will cause large holes
|
||||
*/
|
||||
#if 0
|
||||
WMBag* WMCreateArrayBag(int initialSize);
|
||||
WMBag* WMCreateArrayBagWithDestructor(int initialSize,
|
||||
void (*destructor)(void*));
|
||||
#endif
|
||||
/*
|
||||
* Tree bags use a red-black tree for storage.
|
||||
* Item indexes may be any integer number.
|
||||
*
|
||||
* Pros:
|
||||
* O(lg n) insertion/deletion/search
|
||||
* Good for large numbers of elements with sparse indexes
|
||||
*
|
||||
* Cons:
|
||||
* O(lg n) insertion/deletion/search
|
||||
* Slow for storing small numbers of elements
|
||||
*/
|
||||
WMBag *WMCreateTreeBag(void);
|
||||
WMBag *WMCreateTreeBagWithDestructor(void (*destructor)(void*));
|
||||
|
||||
|
||||
WMBag *WMCreateListBag(void);
|
||||
WMBag *WMCreateListBagWithDestructor(void (*destructor)(void*));
|
||||
|
||||
#define WMCreateBag(size) WMCreateArrayBag(size)
|
||||
|
||||
#define WMCreateArrayBag(a) WMCreateTreeBag()
|
||||
#define WMCreateArrayBagWithDestructor(a,d) WMCreateTreeBagWithDestructor(d)
|
||||
|
||||
#define WMCreateBag(size) WMCreateTreeBag()
|
||||
|
||||
#define WMGetBagItemCount(bag) bag->func.getItemCount(bag)
|
||||
|
||||
@@ -321,7 +360,8 @@ WMBag *WMCreateListBagWithDestructor(void (*destructor)(void*));
|
||||
#define WMPutInBag(bag, item) bag->func.putInBag(bag, item)
|
||||
|
||||
#define WMInsertInBag(bag, index, item) bag->func.insertInBag(bag, index, item)
|
||||
|
||||
|
||||
/* this is slow */
|
||||
#define WMRemoveFromBag(bag, item) bag->func.removeFromBag(bag, item)
|
||||
|
||||
#define WMDeleteFromBag(bag, index) bag->func.deleteFromBag(bag, index)
|
||||
@@ -331,6 +371,7 @@ WMBag *WMCreateListBagWithDestructor(void (*destructor)(void*));
|
||||
#define WMCountInBag(bag, item) bag->func.countInBag(bag, item)
|
||||
|
||||
#define WMReplaceInBag(bag, index, item) bag->func.replaceInBag(bag, index, item)
|
||||
#define WMSetInBag(bag, index, item) bag->func.replaceInBag(bag, index, item)
|
||||
|
||||
/* comparer must return:
|
||||
* < 0 if a < b
|
||||
@@ -342,8 +383,8 @@ WMBag *WMCreateListBagWithDestructor(void (*destructor)(void*));
|
||||
#define WMEmptyBag(bag) bag->func.emptyBag(bag)
|
||||
|
||||
#define WMFreeBag(bag) bag->func.freeBag(bag)
|
||||
|
||||
#define WMMapBag(bag, function) bag->func.mapBag(bag, function)
|
||||
|
||||
#define WMMapBag(bag, function, cdata) bag->func.mapBag(bag, function, cdata)
|
||||
|
||||
#define WMGetFirstInBag(bag, item) bag->func.firstInBag(bag, item)
|
||||
|
||||
@@ -359,6 +400,10 @@ WMBag *WMCreateListBagWithDestructor(void (*destructor)(void*));
|
||||
|
||||
#define WMBagPrevious(bag, ptr) bag->func.previous(bag, ptr)
|
||||
|
||||
#define WMBagIteratorAtIndex(bag, index, ptr) bag->func.iteratorAtIndex(bag, index, ptr)
|
||||
|
||||
#define WMBagIndexForIterator(bag, ptr) bag->func.indexForIterator(bag, ptr)
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
114
WINGs/bagarray.c
114
WINGs/bagarray.c
@@ -13,6 +13,10 @@ typedef struct W_ArrayBag {
|
||||
void **items;
|
||||
int size;
|
||||
int count;
|
||||
|
||||
int base;
|
||||
int first;
|
||||
int last;
|
||||
} W_ArrayBag;
|
||||
|
||||
|
||||
@@ -26,15 +30,17 @@ static void* getFromBag(WMBag *bag, int index);
|
||||
static int firstInBag(WMBag *bag, void *item);
|
||||
static int countInBag(WMBag *bag, void *item);
|
||||
static void* replaceInBag(WMBag *bag, int index, void *item);
|
||||
static void sortBag(WMBag *bag, int (*comparer)(const void*, const void*));
|
||||
static int sortBag(WMBag *bag, int (*comparer)(const void*, const void*));
|
||||
static void emptyBag(WMBag *bag);
|
||||
static void freeBag(WMBag *bag);
|
||||
static WMBag* mapBag(WMBag *bag, void *(*function)(void *));
|
||||
static int findInBag(WMBag *bag, int (*match)(void*));
|
||||
static void mapBag(WMBag *bag, void (*function)(void*, void*), void *data);
|
||||
static int findInBag(WMBag *bag, int (*match)(void*));
|
||||
static void* first(WMBag *bag, void **ptr);
|
||||
static void* last(WMBag *bag, void **ptr);
|
||||
static void* next(WMBag *bag, void **ptr);
|
||||
static void* previous(WMBag *bag, void **ptr);
|
||||
static void* iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr);
|
||||
static int indexForIterator(WMBag *bag, WMBagIterator ptr);
|
||||
|
||||
|
||||
static W_BagFunctions arrayFunctions = {
|
||||
@@ -56,21 +62,26 @@ static W_BagFunctions arrayFunctions = {
|
||||
first,
|
||||
last,
|
||||
next,
|
||||
previous
|
||||
previous,
|
||||
iteratorAtIndex,
|
||||
indexForIterator
|
||||
};
|
||||
|
||||
|
||||
#define ARRAY ((W_ArrayBag*)bag->data)
|
||||
|
||||
|
||||
#define I2O(a, i) ((a)->base + i)
|
||||
|
||||
|
||||
WMBag*
|
||||
WMCreateArrayBagWithDestructor(int size, void (*destructor)(void*))
|
||||
WMCreateArrayBagWithDestructor(int initialSize, void (*destructor)(void*))
|
||||
{
|
||||
WMBag *bag;
|
||||
W_ArrayBag *array;
|
||||
int size;
|
||||
|
||||
wassertrv(size > 0, NULL);
|
||||
|
||||
|
||||
bag = wmalloc(sizeof(WMBag));
|
||||
|
||||
array = wmalloc(sizeof(W_ArrayBag));
|
||||
@@ -80,6 +91,9 @@ WMCreateArrayBagWithDestructor(int size, void (*destructor)(void*))
|
||||
array->items = wmalloc(sizeof(void*) * size);
|
||||
array->size = size;
|
||||
array->count = 0;
|
||||
array->first = 0;
|
||||
array->last = 0;
|
||||
array->base = 0;
|
||||
|
||||
bag->func = arrayFunctions;
|
||||
|
||||
@@ -90,9 +104,9 @@ WMCreateArrayBagWithDestructor(int size, void (*destructor)(void*))
|
||||
|
||||
|
||||
WMBag*
|
||||
WMCreateArrayBag(int size)
|
||||
WMCreateArrayBag(int initialSize)
|
||||
{
|
||||
return WMCreateArrayBagWithDestructor(size, NULL);
|
||||
return WMCreateArrayBagWithDestructor(initialSize, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -106,20 +120,18 @@ getItemCount(WMBag *bag)
|
||||
static int
|
||||
appendBag(WMBag *bag, WMBag *appendedBag)
|
||||
{
|
||||
W_ArrayBag *array1 = ARRAY;
|
||||
W_ArrayBag *array2 = (W_ArrayBag*)appendedBag->data;
|
||||
W_ArrayBag *array = (W_ArrayBag*)appendedBag->data;
|
||||
int ok;
|
||||
int i;
|
||||
|
||||
if (array1->count + array2->count >= array1->size) {
|
||||
array1->items =
|
||||
wrealloc(array1->items, sizeof(void*) * (array1->size+array2->count));
|
||||
array1->size += array2->count;
|
||||
for (i = array->first; i <= array->last; i++) {
|
||||
if (array->items[array->base+i]) {
|
||||
ok = putInBag(bag, array->items[array->base+i]);
|
||||
if (!ok)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(array1->items + array1->count, array2->items,
|
||||
sizeof(void*) * array2->count);
|
||||
|
||||
array1->count += array2->count;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -128,7 +140,7 @@ appendBag(WMBag *bag, WMBag *appendedBag)
|
||||
static int
|
||||
putInBag(WMBag *bag, void *item)
|
||||
{
|
||||
return insertInBag(bag, ARRAY->count, item);
|
||||
return insertInBag(bag, ARRAY->last+1, item);
|
||||
}
|
||||
|
||||
|
||||
@@ -138,19 +150,29 @@ insertInBag(WMBag *bag, int index, void *item)
|
||||
{
|
||||
W_ArrayBag *array = ARRAY;
|
||||
|
||||
if (array->count == array->size) {
|
||||
array->size += 16;
|
||||
if (I2O(array, index) >= array->size) {
|
||||
array->size = WMAX(array->size + 16, I2O(array, index));
|
||||
array->items = wrealloc(array->items, sizeof(void*) * array->size);
|
||||
memset(array->items + I2O(array, array->last), 0,
|
||||
sizeof(void*) * (array->size - I2O(array, array->last)));
|
||||
}
|
||||
|
||||
if (index >= 0 && index < array->count) {
|
||||
memmove(&array->items[index+1], &array->items[index],
|
||||
(array->count - index) * sizeof(void*));
|
||||
|
||||
if (index > array->last) {
|
||||
array->last = index;
|
||||
} else if (index >= array->first) {
|
||||
memmove(array->items + I2O(array, index),
|
||||
array->items + (I2O(array, index) + 1), sizeof(void*));
|
||||
array->last++;
|
||||
} else {
|
||||
/* If index is invalid, place it at end */
|
||||
index = array->count;
|
||||
memmove(array->items,
|
||||
array->items + (abs(index) - array->base),
|
||||
sizeof(void*) * (abs(index) - array->base));
|
||||
memset(array->items, 0, sizeof(void*) * (abs(index) - array->base));
|
||||
array->first = index;
|
||||
array->base = abs(index);
|
||||
}
|
||||
array->items[index] = item;
|
||||
|
||||
array->items[array->base + index] = item;
|
||||
array->count++;
|
||||
|
||||
return 1;
|
||||
@@ -261,10 +283,11 @@ replaceInBag(WMBag *bag, int index, void *item)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static int
|
||||
sortBag(WMBag *bag, int (*comparer)(const void*, const void*))
|
||||
{
|
||||
qsort(ARRAY->items, ARRAY->count, sizeof(void*), comparer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -294,20 +317,15 @@ freeBag(WMBag *bag)
|
||||
}
|
||||
|
||||
|
||||
static WMBag*
|
||||
mapBag(WMBag *bag, void *(*function)(void *))
|
||||
static void
|
||||
mapBag(WMBag *bag, void (*function)(void *, void *), void *clientData)
|
||||
{
|
||||
int i;
|
||||
void *data;
|
||||
WMBag *new = WMCreateArrayBagWithDestructor(ARRAY->size, bag->destructor);
|
||||
|
||||
for (i = 0; i < ARRAY->count; i++) {
|
||||
data = (*function)(ARRAY->items[i]);
|
||||
if (data)
|
||||
putInBag(new, data);
|
||||
for (i = 0; i < ARRAY->last; i++) {
|
||||
if (ARRAY->items[i])
|
||||
(*function)(ARRAY->items[i], clientData);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
@@ -316,7 +334,7 @@ findInBag(WMBag *bag, int (*match)(void*))
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY->count; i++) {
|
||||
for (i = 0; i < ARRAY->last; i++) {
|
||||
if ((*match)(ARRAY->items[i]))
|
||||
return i;
|
||||
}
|
||||
@@ -384,3 +402,15 @@ previous(WMBag *bag, void **ptr)
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void*
|
||||
iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
indexForIterator(WMBag *bag, WMBagIterator ptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ typedef struct W_Item {
|
||||
struct W_Item *next;
|
||||
struct W_Item *prev;
|
||||
void *data;
|
||||
int index;
|
||||
} W_Item;
|
||||
|
||||
|
||||
@@ -23,9 +24,6 @@ typedef struct W_ListBag {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int getItemCount(WMBag *self);
|
||||
static int appendBag(WMBag *self, WMBag *bag);
|
||||
static int putInBag(WMBag *self, void *item);
|
||||
@@ -39,12 +37,15 @@ static void *replaceInBag(WMBag *bag, int index, void *item);
|
||||
static void sortBag(WMBag *bag, int (*comparer)(const void*, const void*));
|
||||
static void emptyBag(WMBag *bag);
|
||||
static void freeBag(WMBag *bag);
|
||||
static WMBag *mapBag(WMBag *bag, void * (*function)(void*));
|
||||
static void mapBag(WMBag *bag, void (*function)(void*, void*), void *data);
|
||||
static int findInBag(WMBag *bag, int (*match)(void*));;
|
||||
static void *first(WMBag *bag, void **ptr);
|
||||
static void *last(WMBag *bag, void **ptr);
|
||||
static void *next(WMBag *bag, void **ptr);
|
||||
static void *previous(WMBag *bag, void **ptr);
|
||||
static void *first(WMBag *bag, WMBagIterator *ptr);
|
||||
static void *last(WMBag *bag, WMBagIterator *ptr);
|
||||
static void *next(WMBag *bag, WMBagIterator *ptr);
|
||||
static void *previous(WMBag *bag, WMBagIterator *ptr);
|
||||
static void *iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr);
|
||||
static int indexForIterator(WMBag *bag, WMBagIterator ptr);
|
||||
|
||||
|
||||
static W_BagFunctions bagFunctions = {
|
||||
getItemCount,
|
||||
@@ -65,7 +66,9 @@ static W_BagFunctions bagFunctions = {
|
||||
first,
|
||||
last,
|
||||
next,
|
||||
previous
|
||||
previous,
|
||||
iteratorAtIndex,
|
||||
indexForIterator
|
||||
};
|
||||
|
||||
|
||||
@@ -353,14 +356,14 @@ static void freeBag(WMBag *self)
|
||||
}
|
||||
|
||||
|
||||
static WMBag *mapBag(WMBag *self, void * (*function)(void*))
|
||||
static WMBag *mapBag(WMBag *self, void * (*function)(void*, void*), void *data)
|
||||
{
|
||||
WMBag *bag = WMCreateListBagWithDestructor(self->destructor);
|
||||
W_Item *ptr = SELF->first;
|
||||
|
||||
while (ptr) {
|
||||
if ((*function)(ptr->data))
|
||||
putInBag(bag, ptr->data);
|
||||
(*function)(ptr->data, data);
|
||||
|
||||
ptr = ptr->next;
|
||||
}
|
||||
return bag;
|
||||
@@ -386,7 +389,7 @@ static int findInBag(WMBag *self, int (*match)(void*))
|
||||
|
||||
|
||||
|
||||
static void *first(WMBag *self, void **ptr)
|
||||
static void *first(WMBag *self, WMBagIterator *ptr)
|
||||
{
|
||||
*ptr = SELF->first;
|
||||
|
||||
@@ -398,7 +401,7 @@ static void *first(WMBag *self, void **ptr)
|
||||
|
||||
|
||||
|
||||
static void *last(WMBag *self, void **ptr)
|
||||
static void *last(WMBag *self, WMBagIterator *ptr)
|
||||
{
|
||||
*ptr = SELF->last;
|
||||
|
||||
@@ -410,7 +413,7 @@ static void *last(WMBag *self, void **ptr)
|
||||
|
||||
|
||||
|
||||
static void *next(WMBag *bag, void **ptr)
|
||||
static void *next(WMBag *bag, WMBagIterator *ptr)
|
||||
{
|
||||
W_Item *item = *(W_Item**)ptr;
|
||||
|
||||
@@ -424,7 +427,7 @@ static void *next(WMBag *bag, void **ptr)
|
||||
|
||||
|
||||
|
||||
static void *previous(WMBag *bag, void **ptr)
|
||||
static void *previous(WMBag *bag, WMBagIterator *ptr)
|
||||
{
|
||||
W_Item *item = *(W_Item**)ptr;
|
||||
|
||||
@@ -438,4 +441,12 @@ static void *previous(WMBag *bag, void **ptr)
|
||||
|
||||
|
||||
|
||||
static void *iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static int indexForIterator(WMBag *bag, WMBagIterator ptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
838
WINGs/bagtree.c
Normal file
838
WINGs/bagtree.c
Normal file
@@ -0,0 +1,838 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "WUtil.h"
|
||||
|
||||
|
||||
typedef struct W_Node {
|
||||
struct W_Node *parent;
|
||||
struct W_Node *left;
|
||||
struct W_Node *right;
|
||||
int color;
|
||||
|
||||
void *data;
|
||||
int index;
|
||||
} W_Node;
|
||||
|
||||
|
||||
typedef struct W_TreeBag {
|
||||
W_Node *root;
|
||||
|
||||
W_Node *nil; /* sentinel */
|
||||
|
||||
int count;
|
||||
} W_TreeBag;
|
||||
|
||||
|
||||
|
||||
static int getItemCount(WMBag *self);
|
||||
static int appendBag(WMBag *self, WMBag *bag);
|
||||
static int putInBag(WMBag *self, void *item);
|
||||
static int insertInBag(WMBag *self, int index, void *item);
|
||||
static int removeFromBag(WMBag *bag, void *item);
|
||||
static int deleteFromBag(WMBag *bag, int index);
|
||||
static void *getFromBag(WMBag *bag, int index);
|
||||
static int countInBag(WMBag *bag, void *item);
|
||||
static int firstInBag(WMBag *bag, void *item);
|
||||
static void *replaceInBag(WMBag *bag, int index, void *item);
|
||||
static int sortBag(WMBag *bag, int (*comparer)(const void*, const void*));
|
||||
static void emptyBag(WMBag *bag);
|
||||
static void freeBag(WMBag *bag);
|
||||
static void mapBag(WMBag *bag, void (*function)(void*, void*), void *data);
|
||||
static int findInBag(WMBag *bag, int (*match)(void*));;
|
||||
static void *first(WMBag *bag, WMBagIterator *ptr);
|
||||
static void *last(WMBag *bag, WMBagIterator *ptr);
|
||||
static void *next(WMBag *bag, WMBagIterator *ptr);
|
||||
static void *previous(WMBag *bag, WMBagIterator *ptr);
|
||||
static void *iteratorAtIndex(WMBag *bag, int index, WMBagIterator *ptr);
|
||||
static int indexForIterator(WMBag *bag, WMBagIterator ptr);
|
||||
|
||||
|
||||
static W_BagFunctions bagFunctions = {
|
||||
getItemCount,
|
||||
appendBag,
|
||||
putInBag,
|
||||
insertInBag,
|
||||
removeFromBag,
|
||||
deleteFromBag,
|
||||
getFromBag,
|
||||
firstInBag,
|
||||
countInBag,
|
||||
replaceInBag,
|
||||
sortBag,
|
||||
emptyBag,
|
||||
freeBag,
|
||||
mapBag,
|
||||
findInBag,
|
||||
first,
|
||||
last,
|
||||
next,
|
||||
previous,
|
||||
iteratorAtIndex,
|
||||
indexForIterator
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#define IS_LEFT(node) (node == node->parent->left)
|
||||
#define IS_RIGHT(node) (node == node->parent->right)
|
||||
|
||||
|
||||
|
||||
static void leftRotate(W_TreeBag *tree, W_Node *node)
|
||||
{
|
||||
W_Node *node2;
|
||||
|
||||
node2 = node->right;
|
||||
node->right = node2->left;
|
||||
|
||||
node2->left->parent = node;
|
||||
|
||||
node2->parent = node->parent;
|
||||
|
||||
if (node->parent == tree->nil) {
|
||||
tree->root = node2;
|
||||
} else {
|
||||
if (IS_LEFT(node)) {
|
||||
node->parent->left = node2;
|
||||
} else {
|
||||
node->parent->right = node2;
|
||||
}
|
||||
}
|
||||
node2->left = node;
|
||||
node->parent = node2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void rightRotate(W_TreeBag *tree, W_Node *node)
|
||||
{
|
||||
W_Node *node2;
|
||||
|
||||
node2 = node->left;
|
||||
node->left = node2->right;
|
||||
|
||||
node2->right->parent = node;
|
||||
|
||||
node2->parent = node->parent;
|
||||
|
||||
if (node->parent == tree->nil) {
|
||||
tree->root = node2;
|
||||
} else {
|
||||
if (IS_LEFT(node)) {
|
||||
node->parent->left = node2;
|
||||
} else {
|
||||
node->parent->right = node2;
|
||||
}
|
||||
}
|
||||
node2->right = node;
|
||||
node->parent = node2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void treeInsert(W_TreeBag *tree, W_Node *node)
|
||||
{
|
||||
W_Node *y = tree->nil;
|
||||
W_Node *x = tree->root;
|
||||
|
||||
while (x != tree->nil) {
|
||||
y = x;
|
||||
if (node->index < x->index)
|
||||
x = x->left;
|
||||
else
|
||||
x = x->right;
|
||||
}
|
||||
node->parent = y;
|
||||
if (y == tree->nil)
|
||||
tree->root = node;
|
||||
else if (node->index < y->index)
|
||||
y->left = node;
|
||||
else
|
||||
y->right = node;
|
||||
}
|
||||
|
||||
|
||||
static void rbTreeInsert(W_TreeBag *tree, W_Node *node)
|
||||
{
|
||||
W_Node *y;
|
||||
|
||||
treeInsert(tree, node);
|
||||
|
||||
node->color = 'R';
|
||||
|
||||
while (node != tree->root && node->parent->color == 'R') {
|
||||
if (IS_LEFT(node->parent)) {
|
||||
y = node->parent->parent->right;
|
||||
|
||||
if (y->color == 'R') {
|
||||
|
||||
node->parent->color = 'B';
|
||||
y->color = 'B';
|
||||
node->parent->parent->color = 'R';
|
||||
node = node->parent->parent;
|
||||
|
||||
} else {
|
||||
if (IS_RIGHT(node)) {
|
||||
node = node->parent;
|
||||
leftRotate(tree, node);
|
||||
}
|
||||
node->parent->color = 'B';
|
||||
node->parent->parent->color = 'R';
|
||||
rightRotate(tree, node->parent->parent);
|
||||
}
|
||||
} else {
|
||||
y = node->parent->parent->left;
|
||||
|
||||
if (y->color == 'R') {
|
||||
|
||||
node->parent->color = 'B';
|
||||
y->color = 'B';
|
||||
node->parent->parent->color = 'R';
|
||||
node = node->parent->parent;
|
||||
|
||||
} else {
|
||||
if (IS_LEFT(node)) {
|
||||
node = node->parent;
|
||||
rightRotate(tree, node);
|
||||
}
|
||||
node->parent->color = 'B';
|
||||
node->parent->parent->color = 'R';
|
||||
leftRotate(tree, node->parent->parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
tree->root->color = 'B';
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void rbDeleteFixup(W_TreeBag *tree, W_Node *node)
|
||||
{
|
||||
W_Node *w;
|
||||
|
||||
while (node != tree->root && node->color == 'B') {
|
||||
if (IS_LEFT(node)) {
|
||||
w = node->parent->right;
|
||||
if (w->color == 'R') {
|
||||
w->color = 'B';
|
||||
node->parent->color = 'R';
|
||||
leftRotate(tree, node->parent);
|
||||
w = node->parent->right;
|
||||
}
|
||||
if (w->left->color == 'B' && w->right->color == 'B') {
|
||||
w->color = 'R';
|
||||
node = node->parent;
|
||||
} else {
|
||||
if (w->right->color == 'B') {
|
||||
w->left->color = 'B';
|
||||
w->color = 'R';
|
||||
rightRotate(tree, w);
|
||||
w = node->parent->right;
|
||||
}
|
||||
w->color = node->parent->color;
|
||||
node->parent->color = 'B';
|
||||
w->right->color = 'B';
|
||||
leftRotate(tree, node->parent);
|
||||
node = tree->root;
|
||||
}
|
||||
} else {
|
||||
w = node->parent->left;
|
||||
if (w->color == 'R') {
|
||||
w->color = 'B';
|
||||
node->parent->color = 'R';
|
||||
leftRotate(tree, node->parent);
|
||||
w = node->parent->left;
|
||||
}
|
||||
if (w->left->color == 'B' && w->right->color == 'B') {
|
||||
w->color = 'R';
|
||||
node = node->parent;
|
||||
} else {
|
||||
if (w->left->color == 'B') {
|
||||
w->right->color = 'B';
|
||||
w->color = 'R';
|
||||
rightRotate(tree, w);
|
||||
w = node->parent->left;
|
||||
}
|
||||
w->color = node->parent->color;
|
||||
node->parent->color = 'B';
|
||||
w->left->color = 'B';
|
||||
leftRotate(tree, node->parent);
|
||||
node = tree->root;
|
||||
}
|
||||
}
|
||||
}
|
||||
node->color = 'B';
|
||||
}
|
||||
|
||||
|
||||
static W_Node *treeMinimum(W_Node *node, W_Node *nil)
|
||||
{
|
||||
while (node->left != nil)
|
||||
node = node->left;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
static W_Node *treeMaximum(W_Node *node, W_Node *nil)
|
||||
{
|
||||
while (node->right != nil)
|
||||
node = node->right;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
static W_Node *treeSuccessor(W_Node *node, W_Node *nil)
|
||||
{
|
||||
W_Node *y;
|
||||
|
||||
if (node->right != nil) {
|
||||
return treeMinimum(node->right, nil);
|
||||
}
|
||||
y = node->parent;
|
||||
while (y != nil && node == y->right) {
|
||||
node = y;
|
||||
y = y->parent;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
static W_Node *treePredecessor(W_Node *node, W_Node *nil)
|
||||
{
|
||||
W_Node *y;
|
||||
|
||||
if (node->left != nil) {
|
||||
return treeMaximum(node->left, nil);
|
||||
}
|
||||
y = node->parent;
|
||||
while (y != nil && node == y->left) {
|
||||
node = y;
|
||||
y = y->parent;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
static W_Node *rbTreeDelete(W_TreeBag *tree, W_Node *node)
|
||||
{
|
||||
W_Node *nil = tree->nil;
|
||||
W_Node *x, *y;
|
||||
|
||||
if (node->left == nil || node->right == nil) {
|
||||
y = node;
|
||||
} else {
|
||||
y = treeSuccessor(node, nil);
|
||||
}
|
||||
|
||||
if (y->left != nil) {
|
||||
x = y->left;
|
||||
} else {
|
||||
x = y->right;
|
||||
}
|
||||
|
||||
x->parent = y->parent;
|
||||
|
||||
if (y->parent == nil) {
|
||||
tree->root = x;
|
||||
} else {
|
||||
if (IS_LEFT(y)) {
|
||||
y->parent->left = x;
|
||||
} else {
|
||||
y->parent->right = x;
|
||||
}
|
||||
}
|
||||
if (y != node) {
|
||||
node->index = y->index;
|
||||
node->data = y->data;
|
||||
}
|
||||
if (y->color == 'B') {
|
||||
rbDeleteFixup(tree, x);
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static W_Node *treeSearch(W_Node *root, W_Node *nil, int index)
|
||||
{
|
||||
if (root == nil || root->index == index) {
|
||||
return root;
|
||||
}
|
||||
|
||||
if (index < root->index) {
|
||||
return treeSearch(root->left, nil, index);
|
||||
} else {
|
||||
return treeSearch(root->right, nil, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static W_Node *treeFind(W_Node *root, W_Node *nil, void *data)
|
||||
{
|
||||
W_Node *tmp;
|
||||
|
||||
if (root == nil || root->data == data)
|
||||
return root;
|
||||
|
||||
tmp = treeFind(root->left, nil, data);
|
||||
if (tmp != nil)
|
||||
return tmp;
|
||||
|
||||
tmp = treeFind(root->right, nil, data);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
static char buf[512];
|
||||
|
||||
static void printNodes(W_Node *node, W_Node *nil, int depth)
|
||||
{
|
||||
if (node == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
printNodes(node->left, nil, depth+1);
|
||||
|
||||
memset(buf, ' ', depth*2);
|
||||
buf[depth*2] = 0;
|
||||
if (IS_LEFT(node))
|
||||
printf("%s/(%2i\n", buf, node->index);
|
||||
else
|
||||
printf("%s\\(%2i\n", buf, node->index);
|
||||
|
||||
printNodes(node->right, nil, depth+1);
|
||||
}
|
||||
|
||||
|
||||
void PrintTree(WMBag *bag)
|
||||
{
|
||||
W_TreeBag *tree = (W_TreeBag*)bag->data;
|
||||
|
||||
printNodes(tree->root, tree->nil, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#define SELF ((W_TreeBag*)self->data)
|
||||
|
||||
WMBag *WMCreateTreeBag(void)
|
||||
{
|
||||
return WMCreateTreeBagWithDestructor(NULL);
|
||||
}
|
||||
|
||||
|
||||
WMBag *WMCreateTreeBagWithDestructor(void (*destructor)(void*))
|
||||
{
|
||||
WMBag *bag;
|
||||
W_TreeBag *tree;
|
||||
|
||||
bag = wmalloc(sizeof(WMBag));
|
||||
|
||||
bag->data = tree = wmalloc(sizeof(W_TreeBag));
|
||||
memset(tree, 0, sizeof(W_TreeBag));
|
||||
|
||||
tree->nil = wmalloc(sizeof(W_Node));
|
||||
memset(tree->nil, 0, sizeof(W_Node));
|
||||
tree->nil->left = tree->nil->right = tree->nil->parent = tree->nil;
|
||||
tree->nil->index = WBNotFound;
|
||||
|
||||
tree->root = tree->nil;
|
||||
|
||||
bag->destructor = destructor;
|
||||
|
||||
bag->func = bagFunctions;
|
||||
|
||||
return bag;
|
||||
}
|
||||
|
||||
|
||||
static int getItemCount(WMBag *self)
|
||||
{
|
||||
return SELF->count;
|
||||
}
|
||||
|
||||
|
||||
static int appendBag(WMBag *self, WMBag *bag)
|
||||
{
|
||||
WMBagIterator ptr;
|
||||
void *data;
|
||||
|
||||
for (data = first(bag, &ptr); data != NULL; data = next(bag, &ptr)) {
|
||||
if (!putInBag(self, data))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int putInBag(WMBag *self, void *item)
|
||||
{
|
||||
W_Node *ptr;
|
||||
|
||||
ptr = wmalloc(sizeof(W_Node));
|
||||
|
||||
ptr->data = item;
|
||||
ptr->index = SELF->count;
|
||||
ptr->left = SELF->nil;
|
||||
ptr->right = SELF->nil;
|
||||
ptr->parent = SELF->nil;
|
||||
|
||||
rbTreeInsert(SELF, ptr);
|
||||
|
||||
SELF->count++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int insertInBag(WMBag *self, int index, void *item)
|
||||
{
|
||||
W_Node *ptr;
|
||||
|
||||
ptr = wmalloc(sizeof(W_Node));
|
||||
|
||||
ptr->data = item;
|
||||
ptr->index = index;
|
||||
ptr->left = SELF->nil;
|
||||
ptr->right = SELF->nil;
|
||||
ptr->parent = SELF->nil;
|
||||
|
||||
rbTreeInsert(SELF, ptr);
|
||||
|
||||
while ((ptr = treeSuccessor(ptr, SELF->nil))) {
|
||||
ptr->index++;
|
||||
}
|
||||
|
||||
|
||||
SELF->count++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int removeFromBag(WMBag *self, void *item)
|
||||
{
|
||||
W_Node *ptr = treeFind(SELF->root, SELF->nil, item);
|
||||
|
||||
if (ptr != SELF->nil) {
|
||||
|
||||
SELF->count--;
|
||||
|
||||
ptr = rbTreeDelete(SELF, ptr);
|
||||
free(ptr);
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int deleteFromBag(WMBag *self, int index)
|
||||
{
|
||||
W_Node *ptr = treeSearch(SELF->root, SELF->nil, index);
|
||||
|
||||
if (ptr != SELF->nil) {
|
||||
|
||||
SELF->count--;
|
||||
|
||||
ptr = rbTreeDelete(SELF, ptr);
|
||||
free(ptr);
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *getFromBag(WMBag *self, int index)
|
||||
{
|
||||
W_Node *node;
|
||||
|
||||
if (SELF->count>0)
|
||||
assert(SELF->root != SELF->nil);
|
||||
|
||||
node = treeSearch(SELF->root, SELF->nil, index);
|
||||
if (node != SELF->nil)
|
||||
return node->data;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int firstInBag(WMBag *self, void *item)
|
||||
{
|
||||
W_Node *node;
|
||||
|
||||
node = treeFind(SELF->root, SELF->nil, item);
|
||||
if (node != SELF->nil)
|
||||
return node->index;
|
||||
else
|
||||
return WBNotFound;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int treeCount(W_Node *root, W_Node *nil, void *item)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (root == nil)
|
||||
return 0;
|
||||
|
||||
if (root->data == item)
|
||||
count++;
|
||||
|
||||
if (root->left != nil)
|
||||
count += treeCount(root->left, nil, item);
|
||||
|
||||
if (root->right != nil)
|
||||
count += treeCount(root->right, nil, item);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int countInBag(WMBag *self, void *item)
|
||||
{
|
||||
return treeCount(SELF->root, SELF->nil, item);
|
||||
}
|
||||
|
||||
|
||||
static void *replaceInBag(WMBag *self, int index, void *item)
|
||||
{
|
||||
W_Node *ptr = treeSearch(SELF->root, SELF->nil, index);
|
||||
void *old = NULL;
|
||||
|
||||
if (item == NULL) {
|
||||
SELF->count--;
|
||||
|
||||
ptr = rbTreeDelete(SELF, ptr);
|
||||
free(ptr);
|
||||
} else if (ptr != SELF->nil) {
|
||||
old = ptr->data;
|
||||
ptr->data = item;
|
||||
} else {
|
||||
insertInBag(self, index, item);
|
||||
}
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sortBag(WMBag *self, int (*comparer)(const void*, const void*))
|
||||
{
|
||||
assert(0&&"not implemented");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void deleteTree(WMBag *self, W_Node *node)
|
||||
{
|
||||
if (node == SELF->nil)
|
||||
return;
|
||||
|
||||
deleteTree(self, node->left);
|
||||
|
||||
if (self->destructor)
|
||||
self->destructor(node->data);
|
||||
|
||||
deleteTree(self, node->right);
|
||||
|
||||
free(node);
|
||||
}
|
||||
|
||||
|
||||
static void emptyBag(WMBag *self)
|
||||
{
|
||||
deleteTree(self, SELF->root);
|
||||
SELF->root = SELF->nil;
|
||||
SELF->count = 0;
|
||||
}
|
||||
|
||||
|
||||
static void freeBag(WMBag *self)
|
||||
{
|
||||
emptyBag(self);
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void mapTree(W_TreeBag *tree, W_Node *node,
|
||||
void (*function)(void*, void*), void *data)
|
||||
{
|
||||
if (node == tree->nil)
|
||||
return;
|
||||
|
||||
mapTree(tree, node->left, function, data);
|
||||
|
||||
(*function)(node->data, data);
|
||||
|
||||
mapTree(tree, node->right, function, data);
|
||||
}
|
||||
|
||||
|
||||
static void mapBag(WMBag *self, void (*function)(void*, void*), void *data)
|
||||
{
|
||||
mapTree(SELF, SELF->root, function, data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int findInTree(W_TreeBag *tree, W_Node *node, int (*function)(void*))
|
||||
{
|
||||
int index;
|
||||
|
||||
if (node == tree->nil)
|
||||
return WBNotFound;
|
||||
|
||||
index = findInTree(tree, node->left, function);
|
||||
if (index != WBNotFound)
|
||||
return index;
|
||||
|
||||
if ((*function)(node->data)) {
|
||||
return node->index;
|
||||
}
|
||||
|
||||
return findInTree(tree, node->right, function);
|
||||
}
|
||||
|
||||
|
||||
static int findInBag(WMBag *self, int (*match)(void*))
|
||||
{
|
||||
return findInTree(SELF, SELF->root, match);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void *first(WMBag *self, WMBagIterator *ptr)
|
||||
{
|
||||
W_Node *node;
|
||||
|
||||
node = treeMinimum(SELF->root, SELF->nil);
|
||||
|
||||
if (node == SELF->nil) {
|
||||
*ptr = NULL;
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
*ptr = node;
|
||||
|
||||
return node->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *last(WMBag *self, WMBagIterator *ptr)
|
||||
{
|
||||
|
||||
W_Node *node;
|
||||
|
||||
node = treeMaximum(SELF->root, SELF->nil);
|
||||
|
||||
if (node == SELF->nil) {
|
||||
*ptr = NULL;
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
*ptr = node;
|
||||
|
||||
return node->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *next(WMBag *self, WMBagIterator *ptr)
|
||||
{
|
||||
W_Node *node;
|
||||
|
||||
if (*ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
node = treeSuccessor(*ptr, SELF->nil);
|
||||
|
||||
if (node == SELF->nil) {
|
||||
*ptr = NULL;
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
*ptr = node;
|
||||
|
||||
return node->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *previous(WMBag *self, WMBagIterator *ptr)
|
||||
{
|
||||
W_Node *node;
|
||||
|
||||
if (*ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
node = treePredecessor(*ptr, SELF->nil);
|
||||
|
||||
|
||||
if (node == SELF->nil) {
|
||||
*ptr = NULL;
|
||||
|
||||
return NULL;
|
||||
} else {
|
||||
*ptr = node;
|
||||
|
||||
return node->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void *iteratorAtIndex(WMBag *self, int index, WMBagIterator *ptr)
|
||||
{
|
||||
W_Node *node;
|
||||
|
||||
node = treeSearch(SELF->root, SELF->nil, index);
|
||||
|
||||
if (node == SELF->nil) {
|
||||
*ptr = NULL;
|
||||
return NULL;
|
||||
} else {
|
||||
*ptr = node;
|
||||
return node->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int indexForIterator(WMBag *bag, WMBagIterator ptr)
|
||||
{
|
||||
return ((W_Node*)ptr)->index;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef struct W_Data {
|
||||
unsigned growth; /* How much to grow */
|
||||
void *bytes; /* Actual data */
|
||||
unsigned retainCount;
|
||||
unsigned freeData:1; /* whether the data should be released */
|
||||
} W_Data;
|
||||
|
||||
|
||||
@@ -52,6 +53,7 @@ WMCreateDataWithCapacity(unsigned capacity) /*FOLD00*/
|
||||
aData->growth = capacity/2 > 0 ? capacity/2 : 1;
|
||||
aData->length = 0;
|
||||
aData->retainCount = 1;
|
||||
aData->freeData = 1;
|
||||
|
||||
return aData;
|
||||
}
|
||||
@@ -96,6 +98,7 @@ WMCreateDataWithBytesNoCopy(void *bytes, unsigned length) /*FOLD00*/
|
||||
aData->growth = length/2 > 0 ? length/2 : 1;
|
||||
aData->bytes = bytes;
|
||||
aData->retainCount = 1;
|
||||
aData->freeData = 0;
|
||||
|
||||
return aData;
|
||||
}
|
||||
@@ -125,7 +128,7 @@ WMReleaseData(WMData *aData) /*FOLD00*/
|
||||
aData->retainCount--;
|
||||
if (aData->retainCount > 0)
|
||||
return;
|
||||
if (aData->bytes)
|
||||
if (aData->bytes && aData->freeData)
|
||||
wfree(aData->bytes);
|
||||
wfree(aData);
|
||||
}
|
||||
|
||||
118
WINGs/dragdestination.c
Normal file
118
WINGs/dragdestination.c
Normal file
@@ -0,0 +1,118 @@
|
||||
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
/* dropping */
|
||||
|
||||
typedef struct W_DNDTargetInfo {
|
||||
/* data types accepted for drops */
|
||||
Atom *dropTypes;
|
||||
int dropTypeCount;
|
||||
|
||||
|
||||
} DNDTargetInfo;
|
||||
|
||||
|
||||
static Atom XDNDversion = XDND_VERSION;
|
||||
|
||||
|
||||
static void
|
||||
realizedObserver(void *self, WMNotification *notif)
|
||||
{
|
||||
WMView *view = (WMView*)WMGetNotificationObject(notif);
|
||||
|
||||
XChangeProperty(W_VIEW_SCREEN(view)->display, W_VIEW_DRAWABLE(view),
|
||||
W_VIEW_SCREEN(view)->xdndAwareAtom,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char*)&XDNDversion, 1);
|
||||
|
||||
WMRemoveNotificationObserver(self);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_SetXdndAwareProperty(WMScreen *scr, WMView *view, Atom *types, int typeCount)
|
||||
{
|
||||
Display *dpy = scr->display;
|
||||
|
||||
view = W_TopLevelOfView(view);
|
||||
|
||||
if (!view->flags.xdndHintSet) {
|
||||
view->flags.xdndHintSet = 1;
|
||||
|
||||
if (view->flags.realized) {
|
||||
XChangeProperty(dpy, W_VIEW_DRAWABLE(view), scr->xdndAwareAtom,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
(unsigned char*)&XDNDversion, 1);
|
||||
} else {
|
||||
WMAddNotificationObserver(realizedObserver, view,
|
||||
WMViewRealizedNotification,
|
||||
/* just use as an id */
|
||||
view->dragDestinationProcs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
WMData*
|
||||
WMGetDroppedData(WMView *view, WMDraggingInfo *info)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMRegisterViewForDraggedTypes(WMView *view, char *acceptedTypes[])
|
||||
{
|
||||
Atom *types;
|
||||
int typeCount;
|
||||
int i;
|
||||
|
||||
typeCount = 0;
|
||||
while (acceptedTypes[typeCount++]);
|
||||
|
||||
types = wmalloc(sizeof(Atom)*(typeCount+1));
|
||||
|
||||
for (i = 0; i < typeCount; i++) {
|
||||
types[i] = XInternAtom(W_VIEW_SCREEN(view)->display,
|
||||
acceptedTypes[i], False);
|
||||
}
|
||||
types[i] = 0;
|
||||
|
||||
view->droppableTypes = types;
|
||||
|
||||
W_SetXdndAwareProperty(W_VIEW_SCREEN(view), view, types, typeCount);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMUnregisterViewDraggedTypes(WMView *view)
|
||||
{
|
||||
if (view->droppableTypes != NULL)
|
||||
free(view->droppableTypes);
|
||||
view->droppableTypes = NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void
|
||||
WMSetViewDragDestinationProcs(WMView *view, WMDragDestinationProcs *procs)
|
||||
{
|
||||
if (view->dragDestinationProcs == NULL) {
|
||||
free(view->dragDestinationProcs);
|
||||
view->dragDestinationProcs = wmalloc(sizeof(WMDragDestinationProcs));
|
||||
}
|
||||
*view->dragDestinationProcs = *procs;
|
||||
|
||||
/*XXX fill in non-implemented stuffs */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1042
WINGs/dragsource.c
Normal file
1042
WINGs/dragsource.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -46,18 +46,43 @@ static void willResizeColorWell();
|
||||
|
||||
W_ViewDelegate _ColorWellViewDelegate = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
willResizeColorWell
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
willResizeColorWell
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
static WMDragSourceProcs dragProcs = {
|
||||
|
||||
static unsigned draggingSourceOperation(WMView *self, Bool local);
|
||||
static void beganDragImage(WMView *self, WMPixmap *image, WMPoint point);
|
||||
static void endedDragImage(WMView *self, WMPixmap *image, WMPoint point,
|
||||
Bool deposited);
|
||||
|
||||
|
||||
static WMDragSourceProcs _DragSourceProcs = {
|
||||
draggingSourceOperation,
|
||||
beganDragImage,
|
||||
endedDragImage,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned draggingEntered(WMView *self, WMDraggingInfo *info);
|
||||
static unsigned draggingUpdated(WMView *self, WMDraggingInfo *info);
|
||||
static void draggingExited(WMView *self, WMDraggingInfo *info);
|
||||
static Bool prepareForDragOperation(WMView *self, WMDraggingInfo *info);
|
||||
static Bool performDragOperation(WMView *self, WMDraggingInfo *info);
|
||||
static void concludeDragOperation(WMView *self, WMDraggingInfo *info);
|
||||
|
||||
static WMDragDestinationProcs _DragDestinationProcs = {
|
||||
draggingEntered,
|
||||
draggingUpdated,
|
||||
draggingExited,
|
||||
prepareForDragOperation,
|
||||
performDragOperation,
|
||||
concludeDragOperation
|
||||
};
|
||||
|
||||
|
||||
#define DEFAULT_WIDTH 60
|
||||
#define DEFAULT_HEIGHT 30
|
||||
@@ -168,7 +193,16 @@ WMCreateColorWell(WMWidget *parent)
|
||||
|
||||
WMAddNotificationObserver(colorChangedObserver, cPtr,
|
||||
WMColorPanelColorChangedNotification, NULL);
|
||||
|
||||
// WMSetViewDragSourceProcs(cPtr->view, &_DragSourceProcs);
|
||||
// WMSetViewDragDestinationProcs(cPtr->view, &_DragDestinationProcs);
|
||||
|
||||
{
|
||||
char *types[2] = {"application/X-color", NULL};
|
||||
|
||||
//WMRegisterViewForDraggedTypes(cPtr->view, types);
|
||||
}
|
||||
|
||||
return cPtr;
|
||||
}
|
||||
|
||||
@@ -276,6 +310,32 @@ handleEvents(XEvent *event, void *data)
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
draggingSourceOperation(WMView *self, Bool local)
|
||||
{
|
||||
puts("DRAG SOURCE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
beganDragImage(WMView *self, WMPixmap *image, WMPoint point)
|
||||
{
|
||||
puts("BEGAN DRAG");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
endedDragImage(WMView *self, WMPixmap *image, WMPoint point, Bool deposited)
|
||||
{
|
||||
if (deposited)
|
||||
puts("ENDED DRAG SUCCESS");
|
||||
else
|
||||
puts("ENDED DRAG CANCEL");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static WMPixmap*
|
||||
makeDragPixmap(WMColorWell *cPtr)
|
||||
{
|
||||
@@ -292,221 +352,6 @@ makeDragPixmap(WMColorWell *cPtr)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
slideView(WMView *view, int srcX, int srcY, int dstX, int dstY)
|
||||
{
|
||||
double x, y, dx, dy;
|
||||
int i;
|
||||
|
||||
srcX -= 8;
|
||||
srcY -= 8;
|
||||
dstX -= 8;
|
||||
dstY -= 8;
|
||||
|
||||
x = srcX;
|
||||
y = srcY;
|
||||
|
||||
dx = (double)(dstX-srcX)/20.0;
|
||||
dy = (double)(dstY-srcY)/20.0;
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
W_MoveView(view, x, y);
|
||||
XFlush(view->screen->display);
|
||||
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Window
|
||||
findChildInWindow(Display *dpy, Window toplevel, int x, int y)
|
||||
{
|
||||
Window foo, bar;
|
||||
Window *children;
|
||||
unsigned nchildren;
|
||||
int i;
|
||||
|
||||
if (!XQueryTree(dpy, toplevel, &foo, &bar,
|
||||
&children, &nchildren) || children == NULL) {
|
||||
return None;
|
||||
}
|
||||
|
||||
/* first window that contains the point is the one */
|
||||
for (i = nchildren-1; i >= 0; i--) {
|
||||
XWindowAttributes attr;
|
||||
|
||||
if (XGetWindowAttributes(dpy, children[i], &attr)
|
||||
&& attr.map_state == IsViewable
|
||||
&& x >= attr.x && y >= attr.y
|
||||
&& x < attr.x + attr.width && y < attr.y + attr.height) {
|
||||
Window child;
|
||||
|
||||
child = findChildInWindow(dpy, children[i],
|
||||
x - attr.x, y - attr.y);
|
||||
|
||||
XFree(children);
|
||||
|
||||
if (!child)
|
||||
return toplevel;
|
||||
else
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
XFree(children);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
static Window
|
||||
findWindowUnderDragPointer(WMScreen *scr, int x, int y, Window iconWindow)
|
||||
{
|
||||
Window foo, bar;
|
||||
Window *children;
|
||||
unsigned nchildren;
|
||||
int i;
|
||||
|
||||
if (!XQueryTree(scr->display, scr->rootWin, &foo, &bar,
|
||||
&children, &nchildren) || children == NULL) {
|
||||
return None;
|
||||
}
|
||||
|
||||
/* try to find the window below the iconWindow by traversing
|
||||
* the whole window list */
|
||||
|
||||
/* first find the position of the iconWindow */
|
||||
for (i = nchildren-1; i >= 0; i--) {
|
||||
if (children[i] == iconWindow) {
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i <= 0) {
|
||||
XFree(children);
|
||||
return scr->rootWin;
|
||||
}
|
||||
|
||||
/* first window that contains the point is the one */
|
||||
for (; i >= 0; i--) {
|
||||
XWindowAttributes attr;
|
||||
Window child;
|
||||
|
||||
if (XGetWindowAttributes(scr->display, children[i], &attr)
|
||||
&& attr.map_state == IsViewable
|
||||
&& x >= attr.x && y >= attr.y
|
||||
&& x < attr.x + attr.width && y < attr.y + attr.height
|
||||
&& (child = findChildInWindow(scr->display, children[i],
|
||||
x - attr.x, y - attr.y))) {
|
||||
XFree(children);
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
XFree(children);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
dragColor(ColorWell *cPtr, XEvent *event, WMPixmap *image)
|
||||
{
|
||||
WMView *dragView;
|
||||
WMScreen *scr = cPtr->view->screen;
|
||||
Display *dpy = scr->display;
|
||||
XColor black = {0, 0,0,0, DoRed|DoGreen|DoBlue};
|
||||
XColor green = {0x0045b045, 0x4500,0xb000,0x4500, DoRed|DoGreen|DoBlue};
|
||||
XColor back = {0, 0xffff,0xffff,0xffff, DoRed|DoGreen|DoBlue};
|
||||
Bool done = False;
|
||||
WMColorWell *activeWell = NULL;
|
||||
|
||||
dragView = W_CreateTopView(scr);
|
||||
|
||||
W_ResizeView(dragView, 16, 16);
|
||||
dragView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
|
||||
dragView->attribs.event_mask = StructureNotifyMask;
|
||||
dragView->attribs.override_redirect = True;
|
||||
dragView->attribs.save_under = True;
|
||||
|
||||
W_MoveView(dragView, event->xmotion.x_root-8, event->xmotion.y_root-8);
|
||||
|
||||
W_RealizeView(dragView);
|
||||
|
||||
W_MapView(dragView);
|
||||
|
||||
XSetWindowBackgroundPixmap(dpy, dragView->window, WMGetPixmapXID(image));
|
||||
XClearWindow(dpy, dragView->window);
|
||||
|
||||
|
||||
XGrabPointer(dpy, scr->rootWin, True,
|
||||
ButtonMotionMask|ButtonReleaseMask,
|
||||
GrabModeSync, GrabModeAsync,
|
||||
scr->rootWin, scr->defaultCursor, CurrentTime);
|
||||
|
||||
while (!done) {
|
||||
XEvent ev;
|
||||
WMView *view;
|
||||
Window win;
|
||||
|
||||
XAllowEvents(dpy, SyncPointer, CurrentTime);
|
||||
WMNextEvent(dpy, &ev);
|
||||
|
||||
switch (ev.type) {
|
||||
case ButtonRelease:
|
||||
if (activeWell != NULL) {
|
||||
WMSetColorWellColor(activeWell, cPtr->color);
|
||||
WMPostNotificationName(WMColorWellDidChangeNotification,
|
||||
activeWell, NULL);
|
||||
} else {
|
||||
slideView(dragView, ev.xbutton.x_root, ev.xbutton.y_root,
|
||||
event->xmotion.x_root, event->xmotion.y_root);
|
||||
}
|
||||
|
||||
done = True;
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
while (XCheckTypedEvent(dpy, MotionNotify, &ev)) ;
|
||||
|
||||
W_MoveView(dragView, ev.xmotion.x_root-8, ev.xmotion.y_root-8);
|
||||
|
||||
win = findWindowUnderDragPointer(scr, ev.xmotion.x_root,
|
||||
ev.xmotion.y_root,
|
||||
dragView->window);
|
||||
|
||||
if (win != None && win != scr->rootWin) {
|
||||
view = W_GetViewForXWindow(dpy, win);
|
||||
} else {
|
||||
view = NULL;
|
||||
}
|
||||
|
||||
if (view && view->self && W_CLASS(view->self) == WC_ColorWell
|
||||
&& view->self != activeWell && view->self != cPtr) {
|
||||
|
||||
activeWell = view->self;
|
||||
XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
|
||||
|
||||
} else if (!view || view->self != activeWell) {
|
||||
|
||||
XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
|
||||
activeWell = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
WMHandleEvent(&ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
XUngrabPointer(dpy, CurrentTime);
|
||||
XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
|
||||
|
||||
W_DestroyView(dragView);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleDragEvents(XEvent *event, void *data)
|
||||
{
|
||||
@@ -526,17 +371,17 @@ handleDragEvents(XEvent *event, void *data)
|
||||
|| abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
|
||||
WMSize offs;
|
||||
WMPixmap *pixmap;
|
||||
char *types[2] = {"application/X-color", NULL};
|
||||
|
||||
offs.width = 2;
|
||||
offs.height = 2;
|
||||
pixmap = makeDragPixmap(cPtr);
|
||||
|
||||
/*
|
||||
WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
|
||||
offs, event, True);
|
||||
* */
|
||||
|
||||
dragColor(cPtr, event, pixmap);
|
||||
/*
|
||||
WMDragImageFromView(cPtr->view, pixmap, types,
|
||||
wmkpoint(event->xmotion.x_root,
|
||||
event->xmotion.y_root),
|
||||
offs, event, True);
|
||||
*/
|
||||
|
||||
WMReleasePixmap(pixmap);
|
||||
}
|
||||
@@ -585,3 +430,76 @@ destroyColorWell(ColorWell *cPtr)
|
||||
wfree(cPtr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned
|
||||
draggingEntered(WMView *self, WMDraggingInfo *info)
|
||||
{
|
||||
WMPoint point = WMGetViewScreenPosition(self);
|
||||
|
||||
printf("%i %i || %i %i %i %i\n", info->location.x, info->location.y,
|
||||
point.x, point.y, W_VIEW_WIDTH(self), W_VIEW_HEIGHT(self));
|
||||
|
||||
if (info->location.x >= point.x
|
||||
&& info->location.y >= point.y
|
||||
&& info->location.x < point.x + W_VIEW_WIDTH(self)
|
||||
&& info->location.y < point.y + W_VIEW_HEIGHT(self)) {
|
||||
/* self */
|
||||
puts("ENTERED 0");
|
||||
return 0;
|
||||
} else {
|
||||
puts("ENTERED 1");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
draggingUpdated(WMView *self, WMDraggingInfo *info)
|
||||
{
|
||||
|
||||
WMPoint point = WMGetViewScreenPosition(self);
|
||||
|
||||
puts("UPDATED");
|
||||
if (info->location.x >= point.x
|
||||
&& info->location.y >= point.y
|
||||
&& info->location.x < point.x + W_VIEW_WIDTH(self)
|
||||
&& info->location.y < point.y + W_VIEW_WIDTH(self)) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
draggingExited(WMView *self, WMDraggingInfo *info)
|
||||
{
|
||||
puts("EXITED");
|
||||
}
|
||||
|
||||
|
||||
static Bool
|
||||
prepareForDragOperation(WMView *self, WMDraggingInfo *info)
|
||||
{
|
||||
puts("PREPARING");
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
static Bool
|
||||
performDragOperation(WMView *self, WMDraggingInfo *info)
|
||||
{
|
||||
WMData *data;
|
||||
|
||||
// data = WMGetDroppedData(self);
|
||||
puts("DROPPED");
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
concludeDragOperation(WMView *self, WMDraggingInfo *info)
|
||||
{
|
||||
puts("FINISHED");
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ checkIdleHandlers()
|
||||
{
|
||||
IdleHandler *handler;
|
||||
WMBag *handlerCopy;
|
||||
int i, n;
|
||||
WMBagIterator iter;
|
||||
|
||||
if (!idleHandler || WMGetBagItemCount(idleHandler)==0) {
|
||||
W_FlushIdleNotificationQueue();
|
||||
@@ -312,15 +312,14 @@ checkIdleHandlers()
|
||||
return (idleHandler!=NULL && WMGetBagItemCount(idleHandler)>0);
|
||||
}
|
||||
|
||||
n = WMGetBagItemCount(idleHandler);
|
||||
handlerCopy = WMCreateBag(n);
|
||||
for (i=0; i<n; i++)
|
||||
WMPutInBag(handlerCopy, WMGetFromBag(idleHandler, i));
|
||||
handlerCopy = WMCreateBag(WMGetBagItemCount(idleHandler));
|
||||
WMAppendBag(handlerCopy, idleHandler);
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
handler = WMGetFromBag(handlerCopy, i);
|
||||
for (handler = WMBagFirst(handlerCopy, &iter);
|
||||
iter != NULL;
|
||||
handler = WMBagNext(handlerCopy, &iter)) {
|
||||
/* check if the handler still exist or was removed by a callback */
|
||||
if (WMGetFirstInBag(idleHandler, handler)<0)
|
||||
if (WMGetFirstInBag(idleHandler, handler) == WBNotFound)
|
||||
continue;
|
||||
|
||||
(*handler->callback)(handler->clientData);
|
||||
@@ -586,6 +585,10 @@ WMHandleEvent(XEvent *event)
|
||||
|| event->type == SelectionRequest) {
|
||||
/* handle selection related events */
|
||||
W_HandleSelectionEvent(event);
|
||||
|
||||
} else if (event->type == ClientMessage) {
|
||||
|
||||
//W_HandleDNDClientMessage(toplevel, &event->xclient);
|
||||
}
|
||||
|
||||
/* if it's a key event, redispatch it to the focused control */
|
||||
@@ -640,12 +643,12 @@ WMHandleEvent(XEvent *event)
|
||||
W_RetainView(toplevel);
|
||||
|
||||
hPtr = view->handlerList;
|
||||
|
||||
|
||||
while (hPtr!=NULL) {
|
||||
W_EventHandler *tmp;
|
||||
|
||||
tmp = hPtr->nextHandler;
|
||||
|
||||
|
||||
if ((hPtr->eventMask & mask)) {
|
||||
(*hPtr->proc)(event, hPtr->clientData);
|
||||
}
|
||||
@@ -654,14 +657,14 @@ WMHandleEvent(XEvent *event)
|
||||
}
|
||||
|
||||
/* pass the event to the top level window of the widget */
|
||||
if (view->parent!=NULL) {
|
||||
if (view->parent != NULL) {
|
||||
vPtr = view;
|
||||
while (vPtr->parent!=NULL)
|
||||
while (vPtr->parent != NULL)
|
||||
vPtr = vPtr->parent;
|
||||
|
||||
hPtr = vPtr->handlerList;
|
||||
|
||||
while (hPtr!=NULL) {
|
||||
while (hPtr != NULL) {
|
||||
|
||||
if (hPtr->eventMask & mask) {
|
||||
(*hPtr->proc)(event, hPtr->clientData);
|
||||
|
||||
@@ -546,6 +546,23 @@ WMCreateScreenWithRContext(Display *display, int screen, RContext *context)
|
||||
XGCValues gcv;
|
||||
Pixmap stipple;
|
||||
static int initialized = 0;
|
||||
static char *atomNames[] = {
|
||||
"_GNUSTEP_WM_ATTR",
|
||||
"WM_DELETE_WINDOW",
|
||||
"WM_PROTOCOLS",
|
||||
"CLIPBOARD",
|
||||
"XdndAware",
|
||||
"XdndSelection",
|
||||
"XdndEnter",
|
||||
"XdndLeave",
|
||||
"XdndPosition",
|
||||
"XdndDrop",
|
||||
"XdndFinished",
|
||||
"XdndTypeList",
|
||||
"XdndStatus",
|
||||
"WM_STATE"
|
||||
};
|
||||
Atom atoms[sizeof(atomNames)/sizeof(char*)];
|
||||
|
||||
if (!initialized) {
|
||||
|
||||
@@ -738,16 +755,29 @@ WMCreateScreenWithRContext(Display *display, int screen, RContext *context)
|
||||
XFreePixmap(display, blank);
|
||||
}
|
||||
|
||||
scrPtr->internalMessage = XInternAtom(display, "_WINGS_MESSAGE", False);
|
||||
XInternAtoms(display, atomNames, sizeof(atomNames)/sizeof(char*), False,
|
||||
atoms);
|
||||
|
||||
scrPtr->attribsAtom = atoms[0];
|
||||
|
||||
scrPtr->deleteWindowAtom = atoms[1];
|
||||
|
||||
scrPtr->attribsAtom = XInternAtom(display, "_GNUSTEP_WM_ATTR", False);
|
||||
scrPtr->protocolsAtom = atoms[2];
|
||||
|
||||
scrPtr->deleteWindowAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
|
||||
scrPtr->clipboardAtom = atoms[3];
|
||||
|
||||
scrPtr->protocolsAtom = XInternAtom(display, "WM_PROTOCOLS", False);
|
||||
|
||||
scrPtr->clipboardAtom = XInternAtom(display, "CLIPBOARD", False);
|
||||
|
||||
scrPtr->xdndAwareAtom = atoms[4];
|
||||
scrPtr->xdndSelectionAtom = atoms[5];
|
||||
scrPtr->xdndEnterAtom = atoms[6];
|
||||
scrPtr->xdndLeaveAtom = atoms[7];
|
||||
scrPtr->xdndPositionAtom = atoms[8];
|
||||
scrPtr->xdndDropAtom = atoms[9];
|
||||
scrPtr->xdndFinishedAtom = atoms[10];
|
||||
scrPtr->xdndTypeListAtom = atoms[11];
|
||||
scrPtr->xdndStatusAtom = atoms[12];
|
||||
|
||||
scrPtr->wmStateAtom = atoms[13];
|
||||
|
||||
scrPtr->rootView = W_CreateRootView(scrPtr);
|
||||
|
||||
|
||||
|
||||
@@ -718,10 +718,11 @@ int main(int argc, char **argv)
|
||||
* Put the testSomething() function you want to test here.
|
||||
*/
|
||||
|
||||
testTabView(scr);
|
||||
|
||||
testColorWell(scr);
|
||||
#if 0
|
||||
testTabView(scr);
|
||||
|
||||
testFontPanel(scr);
|
||||
|
||||
testSplitView(scr);
|
||||
|
||||
@@ -229,18 +229,6 @@ W_RealizeView(W_View *view)
|
||||
}
|
||||
|
||||
|
||||
|
||||
Bool
|
||||
W_CheckInternalMessage(W_Screen *scr, XClientMessageEvent *cev, int event)
|
||||
{
|
||||
if (cev->message_type == scr->internalMessage
|
||||
&& cev->format == 32 && cev->data.l[1] == event)
|
||||
return True;
|
||||
else
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_ReparentView(W_View *view, W_View *newParent, int x, int y)
|
||||
{
|
||||
@@ -414,6 +402,9 @@ destroyView(W_View *view)
|
||||
unparentView(view);
|
||||
|
||||
W_CleanUpEvents(view);
|
||||
|
||||
// WMUnregisterViewDraggedTypes(view);
|
||||
|
||||
#if 0
|
||||
if (view->dragSourceProcs)
|
||||
wfree(view->dragSourceProcs);
|
||||
@@ -659,3 +650,19 @@ WMViewXID(WMView *view)
|
||||
return view->window;
|
||||
}
|
||||
|
||||
|
||||
WMPoint
|
||||
WMGetViewScreenPosition(WMView *view)
|
||||
{
|
||||
WMScreen *scr = W_VIEW_SCREEN(view);
|
||||
Window foo;
|
||||
int x, y;
|
||||
|
||||
XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(view),
|
||||
scr->rootWin, 0, 0, &x, &y, &foo);
|
||||
|
||||
return wmkpoint(x, y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user