Commit 59307314 authored by Ulrich Sibiller's avatar Ulrich Sibiller

update all files with NX relevant changes to libX11 1.3.4

parent a053df0a
......@@ -23,7 +23,6 @@ used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
/* $XFree86$ */
#ifdef HAVE_CONFIG_H
#include <config.h>
......@@ -36,15 +35,15 @@ in this Software without prior written authorization from The Open Group.
* matches, return. If all else fails, tell the user no events found.
*/
Bool XCheckIfEvent (dpy, event, predicate, arg)
register Display *dpy;
Bool XCheckIfEvent (
register Display *dpy,
register XEvent *event, /* XEvent to be filled in. */
Bool (*predicate)(
Display* /* display */,
XEvent* /* event */,
char* /* arg */
); /* function to call */
register XEvent *event; /* XEvent to be filled in. */
char *arg;
), /* function to call */
char *arg)
{
register _XQEvent *prev, *qelt;
unsigned long qe_serial = 0;
......@@ -60,6 +59,7 @@ Bool XCheckIfEvent (dpy, event, predicate, arg)
&& (*predicate)(dpy, &qelt->event, arg)) {
*event = qelt->event;
_XDeq(dpy, prev, qelt);
_XStoreEventCookie(dpy, event);
UnlockDisplay(dpy);
return True;
}
......@@ -90,15 +90,16 @@ Bool XCheckIfEvent (dpy, event, predicate, arg)
* events.
*/
Bool XCheckIfEventNoFlush (dpy, event, predicate, arg)
register Display *dpy;
Bool XCheckIfEventNoFlush (
register Display *dpy,
register XEvent *event, /* XEvent to be filled in. */
Bool (*predicate)(
Display* /* display */,
XEvent* /* event */,
char* /* arg */
); /* function to call */
register XEvent *event; /* XEvent to be filled in. */
char *arg;
), /* function to call */
char *arg)
{
register _XQEvent *prev, *qelt;
unsigned long qe_serial = 0;
......@@ -114,6 +115,7 @@ Bool XCheckIfEventNoFlush (dpy, event, predicate, arg)
&& (*predicate)(dpy, &qelt->event, arg)) {
*event = qelt->event;
_XDeq(dpy, prev, qelt);
_XStoreEventCookie(dpy, event);
UnlockDisplay(dpy);
return True;
}
......
......@@ -35,15 +35,15 @@ in this Software without prior written authorization from The Open Group.
*/
int
XIfEvent (dpy, event, predicate, arg)
register Display *dpy;
XIfEvent (
register Display *dpy,
register XEvent *event,
Bool (*predicate)(
Display* /* display */,
XEvent* /* event */,
char* /* arg */
); /* function to call */
register XEvent *event;
char *arg;
), /* function to call */
char *arg)
{
register _XQEvent *qelt, *prev;
unsigned long qe_serial = 0;
......@@ -58,6 +58,7 @@ XIfEvent (dpy, event, predicate, arg)
&& (*predicate)(dpy, &qelt->event, arg)) {
*event = qelt->event;
_XDeq(dpy, prev, qelt);
_XStoreEventCookie(dpy, event);
UnlockDisplay(dpy);
return 0;
}
......
......@@ -41,21 +41,25 @@ extern long const _Xevent_to_mask[];
*/
int
XMaskEvent (dpy, mask, event)
register Display *dpy;
long mask; /* Selected event mask. */
register XEvent *event; /* XEvent to be filled in. */
XMaskEvent (
register Display *dpy,
long mask, /* Selected event mask. */
register XEvent *event) /* XEvent to be filled in. */
{
register _XQEvent *prev, *qelt;
unsigned long qe_serial = 0;
LockDisplay(dpy);
/* Delete unclaimed cookies */
_XFreeEventCookies(dpy);
prev = NULL;
while (1) {
for (qelt = prev ? prev->next : dpy->head;
qelt;
prev = qelt, qelt = qelt->next) {
if ((qelt->event.type < LASTEvent) &&
if ((qelt->event.type < GenericEvent) &&
(_Xevent_to_mask[qelt->event.type] & mask) &&
((qelt->event.type != MotionNotify) ||
(mask & AllPointers) ||
......
......@@ -35,14 +35,17 @@ in this Software without prior written authorization from The Open Group.
*/
int
XNextEvent (dpy, event)
register Display *dpy;
register XEvent *event;
XNextEvent (
register Display *dpy,
register XEvent *event)
{
register _XQEvent *qelt;
LockDisplay(dpy);
/* Delete unclaimed cookies */
_XFreeEventCookies(dpy);
if (dpy->head == NULL)
_XReadEvents(dpy);
#ifdef NX_TRANS_SOCKET
......@@ -54,6 +57,7 @@ XNextEvent (dpy, event)
qelt = dpy->head;
*event = qelt->event;
_XDeq(dpy, NULL, qelt);
_XStoreEventCookie(dpy, event);
UnlockDisplay(dpy);
return 0;
}
......
......@@ -36,10 +36,11 @@ in this Software without prior written authorization from The Open Group.
*/
int
XPeekEvent (dpy, event)
register Display *dpy;
register XEvent *event;
XPeekEvent (
register Display *dpy,
register XEvent *event)
{
XEvent copy;
LockDisplay(dpy);
if (dpy->head == NULL)
_XReadEvents(dpy);
......@@ -50,6 +51,10 @@ XPeekEvent (dpy, event)
}
#endif
*event = (dpy->head)->event;
if (_XCopyEventCookie(dpy, &event->xcookie, &copy.xcookie)) {
_XStoreEventCookie(dpy, &copy);
*event = copy;
}
UnlockDisplay(dpy);
return 1;
}
......
......@@ -36,15 +36,15 @@ in this Software without prior written authorization from The Open Group.
*/
int
XPeekIfEvent (dpy, event, predicate, arg)
register Display *dpy;
register XEvent *event;
XPeekIfEvent (
register Display *dpy,
register XEvent *event,
Bool (*predicate)(
Display* /* display */,
XEvent* /* event */,
char* /* arg */
);
char *arg;
),
char *arg)
{
register _XQEvent *prev, *qelt;
unsigned long qe_serial = 0;
......@@ -57,7 +57,12 @@ XPeekIfEvent (dpy, event, predicate, arg)
prev = qelt, qelt = qelt->next) {
if(qelt->qserial_num > qe_serial
&& (*predicate)(dpy, &qelt->event, arg)) {
XEvent copy;
*event = qelt->event;
if (_XCopyEventCookie(dpy, &event->xcookie, &copy.xcookie)) {
_XStoreEventCookie(dpy, &copy);
*event = copy;
}
UnlockDisplay(dpy);
return 0;
}
......
......@@ -33,9 +33,9 @@ in this Software without prior written authorization from The Open Group.
/* Read in pending events if needed and return the number of queued events. */
int XEventsQueued (dpy, mode)
register Display *dpy;
int mode;
int XEventsQueued (
register Display *dpy,
int mode)
{
int ret_val;
#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
......@@ -54,8 +54,7 @@ int XEventsQueued (dpy, mode)
return ret_val;
}
int XPending (dpy)
register Display *dpy;
int XPending (register Display *dpy)
{
int ret_val;
LockDisplay(dpy);
......
......@@ -43,23 +43,27 @@ extern long const _Xevent_to_mask[];
*/
int
XWindowEvent (dpy, w, mask, event)
register Display *dpy;
Window w; /* Selected window. */
long mask; /* Selected event mask. */
register XEvent *event; /* XEvent to be filled in. */
XWindowEvent (
register Display *dpy,
Window w, /* Selected window. */
long mask, /* Selected event mask. */
register XEvent *event) /* XEvent to be filled in. */
{
register _XQEvent *prev, *qelt;
unsigned long qe_serial = 0;
LockDisplay(dpy);
/* Delete unclaimed cookies */
_XFreeEventCookies(dpy);
prev = NULL;
while (1) {
for (qelt = prev ? prev->next : dpy->head;
qelt;
prev = qelt, qelt = qelt->next) {
if ((qelt->event.xany.window == w) &&
(qelt->event.type < LASTEvent) &&
(qelt->event.type < GenericEvent) &&
(_Xevent_to_mask[qelt->event.type] & mask) &&
((qelt->event.type != MotionNotify) ||
(mask & AllPointers) ||
......
......@@ -30,27 +30,12 @@ in this Software without prior written authorization from The Open Group.
* interface library (Xlib) to the X Window System Protocol (V11).
* Structures and symbols starting with "_" are private to the library.
*/
#if !defined(_XLIB_H_) && !defined(_X11_XLIB_H_)
#ifndef _XLIB_H_
#define _XLIB_H_
#define _X11_XLIB_H_
#define XlibSpecificationRelease 6
#ifdef USG
#ifndef __TYPES__
#include <sys/types.h> /* forgot to protect it... */
#define __TYPES__
#endif /* __TYPES__ */
#else
#if defined(_POSIX_SOURCE) && defined(MOTOROLA)
#undef _POSIX_SOURCE
#include <sys/types.h>
#define _POSIX_SOURCE
#else
#include <sys/types.h>
#endif
#endif /* USG */
#if defined(__SCO__) || defined(__UNIXWARE__)
#include <stdint.h>
......@@ -63,14 +48,6 @@ in this Software without prior written authorization from The Open Group.
#include <nx-X11/Xosdefs.h>
#ifndef X_WCHAR
#ifdef X_NOT_STDC_ENV
#ifndef ISC
#define X_WCHAR
#endif
#endif
#endif
#ifndef X_WCHAR
#include <stddef.h>
#else
#ifdef __UNIXOS2__
......@@ -143,7 +120,11 @@ typedef char *XPointer;
#define BitmapBitOrder(dpy) (((_XPrivDisplay)dpy)->bitmap_bit_order)
#define BitmapPad(dpy) (((_XPrivDisplay)dpy)->bitmap_pad)
#define ImageByteOrder(dpy) (((_XPrivDisplay)dpy)->byte_order)
#ifdef CRAY /* unable to get WORD64 without pulling in other symbols */
#define NextRequest(dpy) XNextRequest(dpy)
#else
#define NextRequest(dpy) (((_XPrivDisplay)dpy)->request + 1)
#endif
#define LastKnownRequestProcessed(dpy) (((_XPrivDisplay)dpy)->last_request_read)
/* macros for screen oriented applications (toolkit) */
......@@ -966,6 +947,33 @@ typedef struct {
Window window; /* window on which event was requested in event mask */
} XAnyEvent;
/***************************************************************
*
* GenericEvent. This event is the standard event for all newer extensions.
*/
typedef struct
{
int type; /* of event. Always GenericEvent */
unsigned long serial; /* # of last request processed */
Bool send_event; /* true if from SendEvent request */
Display *display; /* Display the event was read from */
int extension; /* major opcode of extension that caused the event */
int evtype; /* actual event type. */
} XGenericEvent;
typedef struct {
int type; /* of event. Always GenericEvent */
unsigned long serial; /* # of last request processed */
Bool send_event; /* true if from SendEvent request */
Display *display; /* Display the event was read from */
int extension; /* major opcode of extension that caused the event */
int evtype; /* actual event type. */
unsigned int cookie;
void *data;
} XGenericEventCookie;
/*
* this union is defined so Xlib can always use the same sized
* event structure internally, to avoid memory fragmentation.
......@@ -1003,6 +1011,8 @@ typedef union _XEvent {
XMappingEvent xmapping;
XErrorEvent xerror;
XKeymapEvent xkeymap;
XGenericEvent xgeneric;
XGenericEventCookie xcookie;
long pad[24];
} XEvent;
#endif
......@@ -4019,6 +4029,16 @@ extern int _Xwctomb(
wchar_t /* wc */
);
extern Bool XGetEventData(
Display* /* dpy */,
XGenericEventCookie* /* cookie*/
);
extern void XFreeEventData(
Display* /* dpy */,
XGenericEventCookie* /* cookie*/
);
_XFUNCPROTOEND
#endif /* _XLIB_H_ */
......@@ -59,12 +59,12 @@ from The Open Group.
/*ARGSUSED*/
Bool
_XAsyncErrorHandler(dpy, rep, buf, len, data)
register Display *dpy;
register xReply *rep;
char *buf;
int len;
XPointer data;
_XAsyncErrorHandler(
register Display *dpy,
register xReply *rep,
char *buf,
int len,
XPointer data)
{
register _XAsyncErrorState *state;
......@@ -87,9 +87,9 @@ _XAsyncErrorHandler(dpy, rep, buf, len, data)
return False;
}
void _XDeqAsyncHandler(dpy, handler)
Display *dpy;
register _XAsyncHandler *handler;
void _XDeqAsyncHandler(
Display *dpy,
register _XAsyncHandler *handler)
{
register _XAsyncHandler **prev;
register _XAsyncHandler *async;
......@@ -103,14 +103,14 @@ void _XDeqAsyncHandler(dpy, handler)
}
char *
_XGetAsyncReply(dpy, replbuf, rep, buf, len, extra, discard)
register Display *dpy;
register char *replbuf; /* data is read into this buffer */
register xReply *rep; /* value passed to calling handler */
char *buf; /* value passed to calling handler */
int len; /* value passed to calling handler */
int extra; /* extra words to read, ala _XReply */
Bool discard; /* discard after extra?, ala _XReply */
_XGetAsyncReply(
register Display *dpy,
register char *replbuf, /* data is read into this buffer */
register xReply *rep, /* value passed to calling handler */
char *buf, /* value passed to calling handler */
int len, /* value passed to calling handler */
int extra, /* extra words to read, ala _XReply */
Bool discard) /* discard after extra?, ala _XReply */
{
if (extra == 0) {
if (discard && (rep->generic.length << 2) > len)
......@@ -125,6 +125,11 @@ _XGetAsyncReply(dpy, replbuf, rep, buf, len, extra, discard)
_XRead(dpy, replbuf + len, size - len);
buf = replbuf;
len = size;
#ifdef MUSTCOPY
} else {
memcpy(replbuf, buf, size);
buf = replbuf;
#endif
}
if (discard && rep->generic.length > extra &&
......@@ -153,15 +158,15 @@ _XGetAsyncReply(dpy, replbuf, rep, buf, len, extra, discard)
}
void
_XGetAsyncData(dpy, data, buf, len, skip, datalen, discardtotal)
Display *dpy;
char *data; /* data is read into this buffer */
char *buf; /* value passed to calling handler */
int len; /* value passed to calling handler */
int skip; /* number of bytes already read in previous
_XGetAsyncData(
Display *dpy,
char *data, /* data is read into this buffer */
char *buf, /* value passed to calling handler */
int len, /* value passed to calling handler */
int skip, /* number of bytes already read in previous
_XGetAsyncReply or _XGetAsyncData calls */
int datalen; /* size of data buffer in bytes */
int discardtotal; /* min. bytes to consume (after skip) */
int datalen, /* size of data buffer in bytes */
int discardtotal) /* min. bytes to consume (after skip) */
{
buf += skip;
len -= skip;
......
/* Copyright (C) 2008 Jamey Sharp, Josh Triplett
* This file is licensed under the MIT license. See the file COPYING.
*
* As Xlibint.h has long become effectively public API, this header exists
* for new private functions that nothing outside of libX11 should call.
*/
#ifndef XPRIVATE_H
#define XPRIVATE_H
extern void _XIDHandler(Display *dpy);
extern void _XSeqSyncFunction(Display *dpy);
extern void _XSetPrivSyncFunction(Display *dpy);
extern void _XSetSeqSyncFunction(Display *dpy);
#ifdef XTHREADS
#if defined(XTHREADS_WARN) || defined(XTHREADS_FILE_LINE)
#define InternalLockDisplay(d,wskip) if ((d)->lock) \
(*(d)->lock->internal_lock_display)(d,wskip,__FILE__,__LINE__)
#else
#define InternalLockDisplay(d,wskip) if ((d)->lock) \
(*(d)->lock->internal_lock_display)(d,wskip)
#endif
#else /* XTHREADS else */
#define InternalLockDisplay(d,wskip)
#endif /* XTHREADS else */
#endif /* XPRIVATE_H */
......@@ -32,11 +32,7 @@
#include "Xlibint.h"
#include "XlcPubI.h"
#include <nx-X11/Xos.h>
#if 0
#include <unistd.h> /* in theory delivers getresuid/gid prototypes,
* in practice only the Linux syscall wrapper is there. */
#endif
#include <unistd.h>
/************************************************************************/
......@@ -221,7 +217,7 @@ _XlcParsePath(
#define XLOCALEDIR "/usr/lib/X11/locale"
#endif
static void
void
xlocaledir(
char *buf,
int buf_len)
......@@ -299,6 +295,84 @@ xlocaledir(
buf[buf_len-1] = '\0';
}
static void
xlocalelibdir(
char *buf,
int buf_len)
{
char *p = buf;
int len = 0;
#ifndef NO_XLOCALEDIR
char *dir;
int priv = 1;
dir = getenv("XLOCALELIBDIR");
if (dir) {
#ifndef WIN32
/*
* Only use the user-supplied path if the process isn't priviledged.
*/
if (getuid() == geteuid() && getgid() == getegid()) {
#if defined(HASSETUGID)
priv = issetugid();
#elif defined(HASGETRESUID)
{
uid_t ruid, euid, suid;
gid_t rgid, egid, sgid;
if ((getresuid(&ruid, &euid, &suid) == 0) &&
(getresgid(&rgid, &egid, &sgid) == 0))
priv = (euid != suid) || (egid != sgid);
}
#else
/*
* If there are saved ID's the process might still be priviledged
* even though the above test succeeded. If issetugid() and
* getresgid() aren't available, test this by trying to set
* euid to 0.
*
* Note: this only protects setuid-root clients. It doesn't
* protect other setuid or any setgid clients. If this tradeoff
* isn't acceptable, set DisableXLocaleDirEnv to YES in host.def.
*/
unsigned int oldeuid;
oldeuid = geteuid();
if (seteuid(0) != 0) {
priv = 0;
} else {
if (seteuid(oldeuid) == -1) {
/* XXX ouch, coudn't get back to original uid
what can we do ??? */
_exit(127);
}
priv = 1;
}
#endif
}
#else
priv = 0;
#endif
if (!priv) {
len = strlen(dir);
strncpy(p, dir, buf_len);
if (len < buf_len) {
p[len++] = LC_PATHDELIM;
p += len;
}
}
}
#endif /* NO_XLOCALEDIR */
if (len < buf_len)
#ifndef __UNIXOS2__
strncpy(p, XLOCALELIBDIR, buf_len - len);
#else
strncpy(p,__XOS2RedirRoot(XLOCALELIBDIR), buf_len - len);
#endif
buf[buf_len-1] = '\0';
}
/* Mapping direction */
typedef enum {
LtoR, /* Map first field to second field */
......@@ -428,7 +502,10 @@ _XlcFileName(
siname = XLC_PUBLIC(lcd, siname);
if (category)
lowercase(cat, category);
else
cat[0] = '\0';
xlocaledir(dir,XLC_BUFSIZE);
n = _XlcParsePath(dir, args, NUM_LOCALEDIR);
for (i = 0; i < n; ++i) {
......@@ -551,9 +628,7 @@ _XlcResolveLocaleName(
/************************************************************************/
int
_XlcResolveI18NPath(buf, buf_len)
char *buf;
int buf_len;
_XlcResolveI18NPath(char *buf, int buf_len)
{
if (buf != NULL) {
xlocaledir(buf, buf_len);
......@@ -562,10 +637,7 @@ _XlcResolveI18NPath(buf, buf_len)
}
char *
_XlcLocaleDirName(dir_name, dir_len, lc_name)
char *dir_name;
size_t dir_len;
char *lc_name;
_XlcLocaleDirName(char *dir_name, size_t dir_len, char *lc_name)
{
char dir[PATH_MAX], buf[PATH_MAX], *name = NULL;
int i, n;
......@@ -574,6 +646,15 @@ _XlcLocaleDirName(dir_name, dir_len, lc_name)
char *target_name = (char*)0;
char *target_dir = (char*)0;
char *nlc_name = NULL;
static char* last_dir_name = 0;
static size_t last_dir_len = 0;
static char* last_lc_name = 0;
if (last_lc_name != 0 && strcmp (last_lc_name, lc_name) == 0
&& dir_len >= last_dir_len) {
strcpy (dir_name, last_dir_name);
return dir_name;
}
xlocaledir (dir, PATH_MAX);
n = _XlcParsePath(dir, args, 256);
......@@ -641,5 +722,116 @@ _XlcLocaleDirName(dir_name, dir_len, lc_name)
}
if (target_name != lc_name)
Xfree(target_name);
if (last_dir_name != 0)
Xfree (last_dir_name);
if (last_lc_name != 0)
Xfree (last_lc_name);
last_dir_len = strlen (dir_name) + 1;
last_dir_name = Xmalloc (last_dir_len);
strcpy (last_dir_name, dir_name);
last_lc_name = Xmalloc (strlen (lc_name) + 1);
strcpy (last_lc_name, lc_name);
return dir_name;
}
char *
_XlcLocaleLibDirName(char *dir_name, size_t dir_len, char *lc_name)
{
char dir[PATH_MAX], buf[PATH_MAX], *name = NULL;
int i, n;
char *args[NUM_LOCALEDIR];
static char locale_alias[] = LOCALE_ALIAS;
char *target_name = (char*)0;
char *target_dir = (char*)0;
char *nlc_name = NULL;
static char* last_dir_name = 0;
static size_t last_dir_len = 0;
static char* last_lc_name = 0;
if (last_lc_name != 0 && strcmp (last_lc_name, lc_name) == 0
&& dir_len >= last_dir_len) {
strcpy (dir_name, last_dir_name);
return dir_name;
}
xlocalelibdir (dir, PATH_MAX);
n = _XlcParsePath(dir, args, 256);
for (i = 0; i < n; ++i) {
if ((2 + (args[i] ? strlen(args[i]) : 0) +
strlen(locale_alias)) < PATH_MAX) {
sprintf (buf, "%s/%s", args[i], locale_alias);
name = resolve_name(lc_name, buf, LtoR);
if (!name) {
if (!nlc_name)
nlc_name = normalize_lcname(lc_name);
if (nlc_name)
name = resolve_name (nlc_name, buf, LtoR);
}
}
/* If name is not an alias, use lc_name for locale.dir search */
if (name == NULL)
name = lc_name;
/* look at locale.dir */
target_dir = args[i];
if (!target_dir) {
/* something wrong */
if (name != lc_name)
Xfree(name);
continue;
}
if ((1 + (target_dir ? strlen (target_dir) : 0) +
strlen("locale.dir")) < PATH_MAX) {
sprintf(buf, "%s/locale.dir", target_dir);
target_name = resolve_name(name, buf, RtoL);
}
if (name != lc_name)
Xfree(name);
if (target_name != NULL) {
char *p = 0;
if ((p = strstr(target_name, "/XLC_LOCALE"))) {
*p = '\0';
break;
}
Xfree(target_name);
target_name = NULL;
}
name = NULL;
}
if (nlc_name) Xfree(nlc_name);
if (target_name == NULL) {
/* vendor locale name == Xlocale name, no expansion of alias */
target_dir = args[0];
target_name = lc_name;
}
/* snprintf(dir_name, dir_len, "%s/%", target_dir, target_name); */
strncpy(dir_name, target_dir, dir_len - 1);
if (strlen(target_dir) >= dir_len - 1) {
dir_name[dir_len - 1] = '\0';
} else {
strcat(dir_name, "/");
strncat(dir_name, target_name, dir_len - strlen(dir_name) - 1);
if (strlen(target_name) >= dir_len - strlen(dir_name) - 1)
dir_name[dir_len - 1] = '\0';
}
if (target_name != lc_name)
Xfree(target_name);
if (last_dir_name != 0)
Xfree (last_dir_name);
if (last_lc_name != 0)
Xfree (last_lc_name);
last_dir_len = strlen (dir_name) + 1;
last_dir_name = Xmalloc (last_dir_len);
strcpy (last_dir_name, dir_name);
last_lc_name = Xmalloc (strlen (lc_name) + 1);
strcpy (last_lc_name, lc_name);
return dir_name;
}
/*
Copyright (c) 2007-2009, Troy D. Hanson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UTLIST_H
#define UTLIST_H
#define UTLIST_VERSION 1.7
/* From: http://uthash.sourceforge.net/utlist.html */
/*
* This file contains macros to manipulate singly and doubly-linked lists.
*
* 1. LL_ macros: singly-linked lists.
* 2. DL_ macros: doubly-linked lists.
* 3. CDL_ macros: circular doubly-linked lists.
*
* To use singly-linked lists, your structure must have a "next" pointer.
* To use doubly-linked lists, your structure must "prev" and "next" pointers.
* Either way, the pointer to the head of the list must be initialized to NULL.
*
* ----------------.EXAMPLE -------------------------
* struct item {
* int id;
* struct item *prev, *next;
* }
*
* struct item *list = NULL:
*
* int main() {
* struct item *item;
* ... allocate and populate item ...
* DL_APPEND(list, item);
* }
* --------------------------------------------------
*
* For doubly-linked lists, the append and delete macros are O(1)
* For singly-linked lists, append and delete are O(n) but prepend is O(1)
* The sort macro is O(n log(n)) for all types of single/double/circular lists.
*/
/******************************************************************************
* doubly linked list macros (non-circular) *
*****************************************************************************/
#define DL_PREPEND(head,add) \
do { \
(add)->next = head; \
if (head) { \
(add)->prev = (head)->prev; \
(head)->prev = (add); \
} else { \
(add)->prev = (add); \
} \
(head) = (add); \
} while (0)
#define DL_APPEND(head,add) \
do { \
if (head) { \
(add)->prev = (head)->prev; \
(head)->prev->next = (add); \
(head)->prev = (add); \
(add)->next = NULL; \
} else { \
(head)=(add); \
(head)->prev = (head); \
(head)->next = NULL; \
} \
} while (0);
#define DL_DELETE(head,del) \
do { \
if ((del)->prev == (del)) { \
(head)=NULL; \
} else if ((del)==(head)) { \
(del)->next->prev = (del)->prev; \
(head) = (del)->next; \
} else { \
(del)->prev->next = (del)->next; \
if ((del)->next) { \
(del)->next->prev = (del)->prev; \
} else { \
(head)->prev = (del)->prev; \
} \
} \
} while (0);
#define DL_FOREACH(head,el) \
for(el=head;el;el=el->next)
#define DL_FOREACH_SAFE(head,el,tmp) \
for(el=head,tmp=el->next;el;el=tmp,tmp=(el) ? (el->next) : NULL)
#endif /* UTLIST_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment