home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
evbl0627.zip
/
everblue_20010627.zip
/
x11
/
Xlib_private.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-03-09
|
29KB
|
971 lines
#include "Xlib_private.h"
#ifndef RGB_DB
#define RGB_DB "/XFree86/lib/X11/rgb"
#endif
int _Xdebug = 0;
int xinitialized = 0;
int wndcount = 0;
int auto_repeat = 1;
PID mypid = 0;
XErrorHandler _XErrorFunction = NULL;
XIOErrorHandler _XIOErrorFunction = NULL;
void * _qfree = NULL;
Display * _XHeadOfDisplayList = NULL;
Display * maindisplay = NULL;
char *rgbPath = RGB_DB;
volatile int Xlib_DebugOffset = 0;
USHORT GXtoMixMode[16] = {
FM_ZERO, /* GXclear */
FM_AND, /* GXand */
FM_MASKSRCNOT, /* GXandReverse */
FM_OVERPAINT, /* GXcopy */
FM_SUBTRACT, /* GXandInverted */
FM_LEAVEALONE, /* GXnoop */
FM_XOR, /* GXxor */
FM_OR, /* GXor */
FM_NOTMERGESRC, /* GXnor */
FM_NOTXORSRC, /* GXequiv */
FM_INVERT, /* GXinvert */
FM_MERGESRCNOT, /* GXorReverse */
FM_NOTCOPYSRC, /* GXcopyInverted */
FM_MERGENOTSRC, /* GXorInverted */
FM_NOTMASKSRC, /* GXnand */
FM_ONE, /* GXset */
};
USHORT GXtoROPMode[16] = {
ROP_ZERO, /* GXclear */
ROP_SRCAND, /* GXand */
ROP_SRCERASE, /* GXandReverse */
ROP_SRCCOPY, /* GXcopy */
0x0022, /* GXandInverted */
0x00aa, /* GXnoop */
0x0066, /* GXxor */
ROP_SRCPAINT, /* GXor */
ROP_NOTSRCERASE,/* GXnor */
0x0099, /* GXequiv */
ROP_DSTINVERT, /* GXinvert */
0x00dd, /* GXorReverse */
ROP_NOTSRCCOPY, /* GXcopyInverted */
ROP_MERGEPAINT, /* GXorInverted */
0x0077, /* GXnand */
ROP_ONE, /* GXset */
};
USHORT LineStyletoLineType[3] = {
LINETYPE_SOLID, /* LineSolid */
LINETYPE_SHORTDASH, /* LineOnOffDash */
LINETYPE_LONGDASH, /* LineDoubleDash */
};
USHORT CapStyletoLineEnd[4] = {
LINEEND_FLAT, /* CapNotLast */
LINEEND_FLAT, /* CapButt */
LINEEND_ROUND, /* CapRound */
LINEEND_SQUARE, /* CapProjecting */
};
USHORT JoinStyletoLineJoin[3] = {
LINEJOIN_MITRE, /* JoinMiter */
LINEJOIN_ROUND, /* JoinRound */
LINEJOIN_BEVEL, /* JoinBevel */
};
#if defined(__DATE__) && defined(__TIME__)
static const char Xlib_built[] = __DATE__ " " __TIME__;
#else
static const char Xlib_built[] = "unknown";
#endif
#ifdef DEBUG
int Xlib_DebugEnter(char* name,int lnum,char* proc, char* info)
{
int DebugLevel = ++Xlib_DebugOffset;
Xlib_DebugInfo[DebugLevel].filename = name;
Xlib_DebugInfo[DebugLevel].linenumb = lnum;
Xlib_DebugInfo[DebugLevel].procname = proc;
Xlib_DebugInfo[DebugLevel].procinfo = info;
return DebugLevel;
}
#endif
/* We are getting lots of crashes while in this function,
* however the crashes are occuring in thread 2 (PM).
* Brian */
XWindowAttributes *GetWinAttrib(Drawable w, HPS *hps)
{
DBUG_ENTER("GetWinAttrib")
WinAttribData *winattrib = NULL;
if (hps) *hps = NULLHANDLE;
if (!w) DBUG_RETURN(NULL);
DBUG_POINT("WinIsWindow()");
if (WinIsWindow(mainhab,(HWND)w)) {
char winclass[32];
PID pid;
if (!WinQueryWindowProcess((HWND)w,&pid,NULL) || pid != mypid)
DBUG_RETURN(NULL);
winclass[WinQueryClassName((HWND)w, sizeof(winclass), winclass)] = 0;
if (strcmp(winclass,"XPMChild") == 0)
winattrib = WinQueryWindowPtr((HWND)w,QWP_WINATTRIB);
if (winattrib) {
if (hps) *hps = winattrib->hps;
DBUG_RETURN(&winattrib->winattrib);
}
}
/* it is a Pixmap, so no WinAttrib data! */
DBUG_RETURN(NULL);
}
int Xlib_SetFont(Pixmap, Font);
int Xlib_SetStipple(Pixmap, Pixmap);
int RestoreGCValues(HPS hps, XGCValues *oldvalues, XGCValues *newvalues)
{
if (!hps || !newvalues) return FALSE;
if (!oldvalues || oldvalues->function != newvalues->function) {
GpiSetMix(hps, GXtoMixMode[newvalues->function]);
GpiSetBackMix(hps, GXtoMixMode[newvalues->function]);
}
if (!oldvalues || oldvalues->foreground != newvalues->foreground)
GpiSetColor(hps,newvalues->foreground);
if (!oldvalues || oldvalues->background != newvalues->background)
GpiSetBackColor(hps,newvalues->background);
if (!oldvalues || oldvalues->line_style != newvalues->line_style)
GpiSetLineType(hps,LineStyletoLineType[newvalues->line_style]);
if (!oldvalues || oldvalues->cap_style != newvalues->cap_style)
GpiSetLineEnd(hps,CapStyletoLineEnd[newvalues->cap_style]);
if (!oldvalues || oldvalues->join_style != newvalues->join_style)
GpiSetLineJoin(hps,JoinStyletoLineJoin[newvalues->join_style]);
if (!oldvalues || oldvalues->line_width != newvalues->line_width)
GpiSetLineWidthGeom(hps,newvalues->line_width);
return TRUE;
}
int GetDrawableHeight(Drawable d, GC gc, HPS *hps, int pathtype)
{
long height, width;
DBUG_ENTER("GetDrawableHeight");
Xlib_GetDrawableInfo(d, gc, hps, pathtype, &width, &height);
DBUG_RETURN(height);
}
void Xlib_GetDrawableInfo(Drawable d, GC gc, HPS *hps, int pathtype, long *width, long *height)
{
DBUG_ENTER("Xlib_GetDrawableInfo")
*height = *width = 0L;
/*printf("[");*/
if (d == (Drawable)0L) {
Xlib_GC *newgc = (Xlib_GC *)gc;
HDC hdc;
/*printf("z");*/
if (!gc) DBUG_VOID_RETURN;
if ((hdc = GpiQueryDevice(*hps = (HPS)newgc->gid))) {
/*printf("d");*/
DevQueryCaps(hdc, CAPS_HEIGHT, 1L, height);
DevQueryCaps(hdc, CAPS_WIDTH, 1L, width);
RestoreGCValues((HPS)newgc->gid, NULL, &newgc->values);
if (newgc->values.font) {
Xlib_Font *font = (Xlib_Font *)newgc->values.font;
GpiCreateLogFont((HPS)newgc->gid,NULL,1,&font->fattrs);
GpiSetCharSet((HPS)newgc->gid,1);
if (font->psmode)
GpiSetCharBox((HPS)newgc->gid, &font->sizef);
}
if (*height < 0) *height = 0;
if (*width < 0) *width = 0;
}
DBUG_VOID_RETURN;
} else
if (WinIsWindow(mainhab, (HWND)d)) {
char winclass[32];
RECTL rectl;
HDC hdc;
PID pid;
winclass[WinQueryClassName((HWND)d, sizeof(winclass), winclass)] = 0;
if (WinQueryWindowProcess((HWND)d,&pid,NULL) && pid == mypid &&
strcmp(winclass,"XPMChild") == 0) {
WinAttribData *winattrib = WinQueryWindowPtr((HWND)d, QWP_WINATTRIB);
Xlib_GC *newgc = (Xlib_GC *)(gc?gc:winattrib->currentGC);
/*printf("x");*/
/*if (!winattrib) printf("?");*/
*hps = winattrib->hps;
if (winattrib->currentGC != gc) {
Xlib_GC *oldgc = (Xlib_GC *)(winattrib->currentGC);
int prevpath = GC_NOPATH;
if (pathtype == GC_NOPATH && oldgc) pathtype = oldgc->path;
if (oldgc && pathtype != (prevpath = oldgc->path))
XFlushGC(maindisplay,(GC)oldgc);
if (newgc && newgc->path != GC_NOPATH)
XFlushGC(maindisplay,(GC)newgc);
if (oldgc) {
GpiQueryCurrentPosition((HPS)oldgc->gid, &oldgc->cp);
oldgc->path = GC_NOPATH;
}
RestoreGCValues(*hps, (oldgc)?&oldgc->values:NULL,
(newgc)?&newgc->values:NULL );
if (newgc) {
SIZEL sizl;
/*printf("(");*/
if ((GpiQueryPS((HPS)newgc->gid, &sizl) & GPIT_MICRO) == 0)
GpiDestroyPS((HPS)newgc->gid);
if (newgc->winattrib && newgc->winattrib->currentGC == gc)
newgc->winattrib->currentGC = (GC)0L;
if (newgc->pixmap && newgc->pixmap->currentGC == gc)
newgc->pixmap->currentGC = (GC)0L;
newgc->gid = *hps;
newgc->path = pathtype;
newgc->winattrib = winattrib; winattrib->currentGC = gc;
newgc->pixmap = NULL;
Xlib_SetFont((Pixmap)winattrib, newgc->values.font);
Xlib_SetStipple((Pixmap)winattrib, newgc->values.stipple);
GpiMove(*hps, &newgc->cp);
if (pathtype != GC_NOPATH && prevpath != pathtype)
GpiBeginPath(*hps, 1L);
/*printf(")");*/
}
} else
if (newgc) {
if (newgc->path != GC_NOPATH && newgc->path != pathtype)
XFlushGC(maindisplay, gc);
Xlib_SetFont((Pixmap)winattrib, newgc->values.font);
Xlib_SetStipple((Pixmap)winattrib, newgc->values.stipple);
switch (pathtype) {
case GC_AREAFILL:
GpiBeginArea(*hps, BA_BOUNDARY |
(newgc->values.fill_rule == WindingRule ?
BA_WINDING : BA_ALTERNATE ));
newgc->path = GC_AREAFILL;
break;
case GC_STROKEPATH:
case GC_FILLPATH:
GpiBeginPath(*hps, 1L);
newgc->path = pathtype;
}
}
/*printf("]");*/
/*if (!gc) return 0;*/
*height = winattrib->winattrib.height;
*width = winattrib->winattrib.width;
DBUG_VOID_RETURN;
}
if (WinQueryWindowRect((HWND)d, &rectl)) {
HDC newhdc = gc?WinQueryWindowDC((HWND)d):NULLHANDLE;
Xlib_GC *newgc = (Xlib_GC *)gc;
hdc = gc?GpiQueryDevice((HPS)newgc->gid):NULLHANDLE;
/*printf("w");*/
if (!hdc || !newhdc) {
/*printf("!]");*/
*height = *width = 0;
DBUG_VOID_RETURN;
}
if (newhdc != hdc) {
XFlushGC(maindisplay,gc);
if (hdc)
if (!GpiAssociate((HPS)newgc->gid, NULLHANDLE)) {
SIZEL sizl = {0,0};
(HPS)newgc->gid = GpiCreatePS( mainhab, NULLHANDLE, &sizl,
PU_PELS | GPIT_NORMAL );
GpiCreateLogColorTable((HPS)newgc->gid, 0, LCOLF_RGB, 0, 0, NULL );
}
if (!GpiAssociate((HPS)newgc->gid, newhdc))
{
*height = *width = 0;
DBUG_VOID_RETURN;
}
RestoreGCValues((HPS)newgc->gid, NULL, &newgc->values);
GpiSetCurrentPosition(*hps, &newgc->cp);
}
*hps = (HPS)newgc->gid;
if (newgc->winattrib && newgc->winattrib->currentGC == gc)
newgc->winattrib->currentGC = (GC)0L;
if (newgc->pixmap && newgc->pixmap->currentGC == gc)
newgc->pixmap->currentGC = (GC)0L;
newgc->gid = *hps;
newgc->path = pathtype;
newgc->winattrib = NULL; newgc->pixmap = NULL;
if (newgc->values.font) {
Xlib_Font *font = (Xlib_Font *)newgc->values.font;
GpiCreateLogFont((HPS)newgc->gid,NULL,1,&font->fattrs);
GpiSetCharSet((HPS)newgc->gid,1);
if (font->psmode)
GpiSetCharBox((HPS)newgc->gid, &font->sizef);
}
if (pathtype != GC_NOPATH) GpiBeginPath(*hps, 1L);
/*printf("]");*/
*height = rectl.yTop - rectl.yBottom;
*width = rectl.xRight - rectl.xLeft;
DBUG_VOID_RETURN;
}
/* rely on current GC data... */
if ((hdc = GpiQueryDevice(*hps = (HPS)((Xlib_GC *)gc)->gid))) {
Xlib_GC *newgc = (Xlib_GC *)gc;
/*printf("d");*/
DevQueryCaps(hdc, CAPS_HEIGHT, 1L, height);
DevQueryCaps(hdc, CAPS_WIDTH, 1L, width);
RestoreGCValues((HPS)newgc->gid, NULL, &newgc->values);
if (*height < 0) *height = 0;
if (*width < 0) *width = 0;
DBUG_VOID_RETURN;
}
/*printf("n]");*/
*height = *width = 0;
DBUG_VOID_RETURN;
}
/*printf("p");*/
/* assume it is a Pixmap, cross fingers! */
{
Xlib_Pixmap *pixmap = (Xlib_Pixmap *)d;
Xlib_GC *newgc = (Xlib_GC *)(gc?gc:pixmap->currentGC);
Xlib_GC *oldgc = (Xlib_GC *)pixmap->currentGC;
*hps = pixmap->hps;
if (oldgc != newgc) {
int prevpath = GC_NOPATH;
if (pathtype == GC_NOPATH && oldgc) pathtype = oldgc->path;
if (oldgc && pathtype != (prevpath = oldgc->path))
XFlushGC(maindisplay,(GC)oldgc);
if (newgc && newgc->path != GC_NOPATH)
XFlushGC(maindisplay,(GC)newgc);
if (oldgc) {
GpiQueryCurrentPosition((HPS)oldgc->gid, &oldgc->cp);
oldgc->path = GC_NOPATH;
}
RestoreGCValues(*hps, (oldgc)?&oldgc->values:NULL,
(newgc)?&newgc->values:NULL );
if (newgc) {
SIZEL sizl;
if ((GpiQueryPS((HPS)newgc->gid, &sizl) & GPIT_MICRO) == 0)
GpiDestroyPS((HPS)newgc->gid);
if (newgc->winattrib && newgc->winattrib->currentGC == gc)
newgc->winattrib->currentGC = (GC)0L;
if (newgc->pixmap && newgc->pixmap->currentGC == gc)
newgc->pixmap->currentGC = (GC)0L;
newgc->gid = *hps;
newgc->path = pathtype;
newgc->winattrib = NULL;
newgc->pixmap = pixmap; pixmap->currentGC = gc;
Xlib_SetFont((Pixmap)pixmap, newgc->values.font);
Xlib_SetStipple((Pixmap)pixmap, newgc->values.stipple);
GpiMove(*hps, &newgc->cp);
if (pathtype != GC_NOPATH && prevpath != pathtype)
GpiBeginPath(*hps, 1L);
}
} else
if (newgc) {
if (newgc->path != GC_NOPATH && newgc->path != pathtype)
XFlushGC(maindisplay, gc);
Xlib_SetFont((Pixmap)pixmap, newgc->values.font);
Xlib_SetStipple((Pixmap)pixmap, newgc->values.stipple);
switch (pathtype) {
case GC_AREAFILL:
GpiBeginArea(*hps, BA_BOUNDARY |
(newgc->values.fill_rule == WindingRule ?
BA_WINDING : BA_ALTERNATE ));
newgc->path = GC_AREAFILL;
break;
case GC_STROKEPATH:
case GC_FILLPATH:
GpiBeginPath(*hps, 1L);
newgc->path = pathtype;
}
}
/*printf("]");*/
/*if (!gc) return 0;*/
*height = pixmap->height;
*width = pixmap->width;
DBUG_VOID_RETURN;
}
}
void Xlib_buildmark(char *mark, int len)
{
strncpy(mark, Xlib_built, len);
}
XEvent *Xlib_NewEvent(void)
{
Xlib_EventQueue *newq;
/* Add event to the bottom of the list */
pthread_mutex_lock(&evmutex);
newq = malloc(sizeof(Xlib_EventQueue));
newq->next = NULL;
if(EventQueue == NULL)
EventQueue = newq;
else
{
Xlib_EventQueue *tmp;
tmp = EventQueue;
while(tmp->next != NULL)
tmp = tmp->next;
tmp->next = newq;
}
pthread_mutex_unlock(&evmutex);
return &(newq->event);
}
void Xlib_RemoveEvent(XEvent *ev)
{
Xlib_EventQueue *prev = NULL, *tmp = EventQueue;
pthread_mutex_lock(&evmutex);
while(tmp != NULL)
{
if(&(tmp->event) == ev)
{
if(prev)
prev->next = tmp->next;
else
EventQueue = tmp->next;
free(tmp);
pthread_mutex_unlock(&evmutex);
return;
}
prev = tmp;
tmp=tmp->next;
}
pthread_mutex_unlock(&evmutex);
return;
}
/* This is here because functions often times generate an event,
* so I figured it would be nice to be able to have a function to
* send an Event and beable to specify if it was "send_event" or
* not for convenience. Brian Smith.
*/
Status Xlib_SendEvent(Display *display, Window w, Bool propagate,
long event_mask, XEvent *event_send, Bool send_event)
{
DBUG_ENTER("Xlib_SendEvent")
XEvent *new;
/* Need to look into how the event mask should be
handled here. */
pthread_mutex_lock(&evmutex);
new = Xlib_NewEvent();
memcpy(new, event_send, sizeof(XEvent));
/* Does serial get incremented in sent events? */
new->xany.serial = 0;
new->xany.send_event = send_event;
new->xany.display = display;
new->xany.window = w;
display->qlen++;
write(pmout[1], (char *) &new, sizeof(void *));
pthread_mutex_unlock(&evmutex);
DBUG_RETURN(True);
}
#define POLLFD_CACHE_SIZE 5
/* initialize the struct array passed to poll() below */
Bool _XPollfdCacheInit(dpy)
Display *dpy;
{
#ifdef USE_POLL
struct pollfd *pfp;
pfp = (struct pollfd *)Xmalloc(POLLFD_CACHE_SIZE * sizeof(struct pollfd));
if (!pfp)
return False;
pfp[0].fd = dpy->fd;
pfp[0].events = POLLIN;
dpy->filedes = (XPointer)pfp;
#endif
return True;
}
void _XPollfdCacheAdd(dpy, fd)
Display *dpy;
int fd;
{
#ifdef USE_POLL
struct pollfd *pfp = (struct pollfd *)dpy->filedes;
if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
pfp[dpy->im_fd_length].fd = fd;
pfp[dpy->im_fd_length].events = POLLIN;
}
#endif
}
/* ARGSUSED */
void _XPollfdCacheDel(dpy, fd)
Display *dpy;
int fd; /* not used */
{
#ifdef USE_POLL
struct pollfd *pfp = (struct pollfd *)dpy->filedes;
struct _XConnectionInfo *conni;
/* just recalculate whole list */
if (dpy->im_fd_length <= POLLFD_CACHE_SIZE) {
int loc = 1;
for (conni = dpy->im_fd_info; conni; conni=conni->next) {
pfp[loc].fd = conni->fd;
pfp[loc].events = POLLIN;
loc++;
}
}
#endif
}
/*
* This routine can be used to (cheaply) get some memory within a single
* Xlib routine for scratch space. A single buffer is reused each time
* if possible. To be MT safe, you can only call this between a call to
* GetReq* and a call to Data* or _XSend*, or in a context when the thread
* is guaranteed to not unlock the display.
*/
char *_XAllocScratch (dpy, nbytes)
register Display *dpy;
unsigned long nbytes;
{
DBUG_ENTER("_XAllocScratch")
if (nbytes > dpy->scratch_length) {
if (dpy->scratch_buffer) Xfree (dpy->scratch_buffer);
if ((dpy->scratch_buffer = Xmalloc((unsigned) nbytes)))
dpy->scratch_length = nbytes;
else dpy->scratch_length = 0;
}
DBUG_RETURN(dpy->scratch_buffer);
}
/*
* Scratch space allocator you can call any time, multiple times, and be
* MT safe, but you must hand the buffer back with _XFreeTemp.
*/
char *_XAllocTemp (dpy, nbytes)
register Display *dpy;
unsigned long nbytes;
{
DBUG_ENTER("_XAllocTemp")
char *buf;
buf = _XAllocScratch(dpy, nbytes);
dpy->scratch_buffer = NULL;
dpy->scratch_length = 0;
DBUG_RETURN(buf);
}
void _XFreeTemp (dpy, buf, nbytes)
register Display *dpy;
char *buf;
unsigned long nbytes;
{
DBUG_ENTER("_XFreeTemp")
if (dpy->scratch_buffer)
Xfree(dpy->scratch_buffer);
dpy->scratch_buffer = buf;
dpy->scratch_length = nbytes;
DBUG_VOID_RETURN;
}
/* _XRegisterInternalConnection
* Each IM (or Xlib extension) that opens a file descriptor that Xlib should
* include in its select/poll mask must call this function to register the
* fd with Xlib. Any XConnectionWatchProc registered by XAddConnectionWatch
* will also be called.
*
* Whenever Xlib detects input available on fd, it will call callback
* with call_data to process it. If non-Xlib code calls select/poll
* and detects input available, it must call XProcessInternalConnection,
* which will call the associated callback.
*
* Non-Xlib code can learn about these additional fds by calling
* XInternalConnectionNumbers or, more typically, by registering
* a XConnectionWatchProc with XAddConnectionWatch
* to be called when fds are registered or unregistered.
*
* Returns True if registration succeeded, False if not, typically
* because could not allocate memory.
* Assumes Display locked when called.
*/
#if NeedFunctionPrototypes
Status _XRegisterInternalConnection(
Display* dpy,
int fd,
_XInternalConnectionProc callback,
XPointer call_data
)
#else
Status
_XRegisterInternalConnection(dpy, fd, callback, call_data)
Display *dpy;
int fd;
_XInternalConnectionProc callback;
XPointer call_data;
#endif
{
DBUG_ENTER("_XRegisterInternalConnection")
struct _XConnectionInfo *new_conni, **iptr;
struct _XConnWatchInfo *watchers;
XPointer *wd;
new_conni = (struct _XConnectionInfo*)Xmalloc(sizeof(struct _XConnectionInfo));
if (!new_conni)
DBUG_RETURN(0);
new_conni->watch_data = (XPointer *)Xmalloc(dpy->watcher_count * sizeof(XPointer));
if (!new_conni->watch_data) {
Xfree(new_conni);
DBUG_RETURN(0);
}
new_conni->fd = fd;
new_conni->read_callback = callback;
new_conni->call_data = call_data;
new_conni->next = NULL;
/* link new structure onto end of list */
for (iptr = &dpy->im_fd_info; *iptr; iptr = &(*iptr)->next)
;
*iptr = new_conni;
dpy->im_fd_length++;
_XPollfdCacheAdd(dpy, fd);
for (watchers=dpy->conn_watchers, wd=new_conni->watch_data;
watchers;
watchers=watchers->next, wd++) {
*wd = NULL; /* for cleanliness */
(*watchers->fn) (dpy, watchers->client_data, fd, True, wd);
}
DBUG_RETURN(1);
}
/* _XUnregisterInternalConnection
* Each IM (or Xlib extension) that closes a file descriptor previously
* registered with _XRegisterInternalConnection must call this function.
* Any XConnectionWatchProc registered by XAddConnectionWatch
* will also be called.
*
* Assumes Display locked when called.
*/
#if NeedFunctionPrototypes
void _XUnregisterInternalConnection(
Display* dpy,
int fd
)
#else
void
_XUnregisterInternalConnection(dpy, fd)
Display *dpy;
int fd;
#endif
{
DBUG_ENTER("_XUnregisterInternalConnection")
struct _XConnectionInfo *info_list, **prev;
struct _XConnWatchInfo *watch;
XPointer *wd;
for (prev = &dpy->im_fd_info; (info_list = *prev); prev = &info_list->next) {
if (info_list->fd == fd) {
*prev = info_list->next;
dpy->im_fd_length--;
for (watch=dpy->conn_watchers, wd=info_list->watch_data;
watch;
watch=watch->next, wd++) {
(*watch->fn) (dpy, watch->client_data, fd, False, wd);
}
if (info_list->watch_data)
Xfree (info_list->watch_data);
Xfree (info_list);
break;
}
}
_XPollfdCacheDel(dpy, fd);
DBUG_VOID_RETURN;
}
/* XInternalConnectionNumbers
* Returns an array of fds and an array of corresponding call data.
* Typically a XConnectionWatchProc registered with XAddConnectionWatch
* will be used instead of this function to discover
* additional fds to include in the select/poll mask.
*
* The list is allocated with Xmalloc and should be freed by the caller
* with Xfree;
*/
#if NeedFunctionPrototypes
Status XInternalConnectionNumbers(
Display *dpy,
int **fd_return,
int *count_return
)
#else
Status
XInternalConnectionNumbers(dpy, fd_return, count_return)
Display *dpy;
int **fd_return;
int *count_return;
#endif
{
DBUG_ENTER("XInternalConnectionNumbers")
int count;
struct _XConnectionInfo *info_list;
int *fd_list;
LockDisplay(dpy);
count = 0;
for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next)
count++;
fd_list = (int*) Xmalloc (count * sizeof(int));
if (!fd_list) {
UnlockDisplay(dpy);
DBUG_RETURN(0);
}
count = 0;
for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
fd_list[count] = info_list->fd;
count++;
}
UnlockDisplay(dpy);
*fd_return = fd_list;
*count_return = count;
DBUG_RETURN(1);
}
static void _XProcessInternalConnection(dpy, conn_info)
Display *dpy;
struct _XConnectionInfo *conn_info;
{
DBUG_ENTER("_XProcessInternalConnection")
/*dpy->flags |= XlibDisplayProcConni;*/
#ifdef XTHREADS
if (dpy->lock) {
/* check cache to avoid call to thread_self */
if (xthread_have_id(dpy->lock->reading_thread))
dpy->lock->conni_thread = dpy->lock->reading_thread;
else
dpy->lock->conni_thread = XThread_Self();
}
#endif /* XTHREADS */
UnlockDisplay(dpy);
(*conn_info->read_callback) (dpy, conn_info->fd, conn_info->call_data);
LockDisplay(dpy);
#ifdef XTHREADS
if (dpy->lock)
xthread_clear_id(dpy->lock->conni_thread);
#endif /* XTHREADS */
/*dpy->flags &= ~XlibDisplayProcConni;*/
DBUG_VOID_RETURN;
}
/* XProcessInternalConnection
* Call the _XInternalConnectionProc registered by _XRegisterInternalConnection
* for this fd.
* The Display is NOT locked during the call.
*/
#if NeedFunctionPrototypes
void XProcessInternalConnection(
Display* dpy,
int fd
)
#else
void
XProcessInternalConnection(dpy, fd)
Display *dpy;
int fd;
#endif
{
DBUG_ENTER("XProcessInternalConnection")
struct _XConnectionInfo *info_list;
LockDisplay(dpy);
for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
if (info_list->fd == fd) {
_XProcessInternalConnection(dpy, info_list);
break;
}
}
UnlockDisplay(dpy);
DBUG_VOID_RETURN;
}
/* XAddConnectionWatch
* Register a callback to be called whenever _XRegisterInternalConnection
* or _XUnregisterInternalConnection is called.
* Callbacks are called with the Display locked.
* If any connections are already registered, the callback is immediately
* called for each of them.
*/
#if NeedFunctionPrototypes
Status XAddConnectionWatch(
Display* dpy,
XConnectionWatchProc callback,
XPointer client_data
)
#else
Status
XAddConnectionWatch(dpy, callback, client_data)
Display *dpy;
XConnectionWatchProc callback;
XPointer client_data;
#endif
{
DBUG_ENTER("XAddConnectionWatch")
struct _XConnWatchInfo *new_watcher, **wptr;
struct _XConnectionInfo *info_list;
XPointer *wd_array;
LockDisplay(dpy);
/* allocate new watch data */
for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
wd_array = (XPointer *)Xrealloc((char *)info_list->watch_data,
(dpy->watcher_count + 1) *
sizeof(XPointer));
if (!wd_array) {
UnlockDisplay(dpy);
DBUG_RETURN(0);
}
wd_array[dpy->watcher_count] = NULL; /* for cleanliness */
}
new_watcher = (struct _XConnWatchInfo*)Xmalloc(sizeof(struct _XConnWatchInfo));
if (!new_watcher) {
UnlockDisplay(dpy);
DBUG_RETURN(0);
}
new_watcher->fn = callback;
new_watcher->client_data = client_data;
new_watcher->next = NULL;
/* link new structure onto end of list */
for (wptr = &dpy->conn_watchers; *wptr; wptr = &(*wptr)->next)
;
*wptr = new_watcher;
dpy->watcher_count++;
/* call new watcher on all currently registered fds */
for (info_list=dpy->im_fd_info; info_list; info_list=info_list->next) {
(*callback) (dpy, client_data, info_list->fd, True,
info_list->watch_data + dpy->watcher_count - 1);
}
UnlockDisplay(dpy);
DBUG_RETURN(1);
}
/* XRemoveConnectionWatch
* Unregister a callback registered by XAddConnectionWatch.
* Both callback and client_data must match what was passed to
* XAddConnectionWatch.
*/
#if NeedFunctionPrototypes
void XRemoveConnectionWatch(
Display* dpy,
XConnectionWatchProc callback,
XPointer client_data
)
#else
void
XRemoveConnectionWatch(dpy, callback, client_data)
Display *dpy;
XConnectionWatchProc callback;
XPointer client_data;
#endif
{
DBUG_ENTER("XRemoveConnectionWatch")
struct _XConnWatchInfo *watch;
struct _XConnWatchInfo *previous = NULL;
struct _XConnectionInfo *conni;
int counter = 0;
LockDisplay(dpy);
for (watch=dpy->conn_watchers; watch; watch=watch->next) {
if (watch->fn == callback && watch->client_data == client_data) {
if (previous)
previous->next = watch->next;
else
dpy->conn_watchers = watch->next;
Xfree (watch);
dpy->watcher_count--;
/* remove our watch_data for each connection */
for (conni=dpy->im_fd_info; conni; conni=conni->next) {
/* don't bother realloc'ing; these arrays are small anyway */
/* overlapping */
memmove(conni->watch_data+counter,
conni->watch_data+counter+1,
dpy->watcher_count - counter);
}
break;
}
previous = watch;
counter++;
}
UnlockDisplay(dpy);
DBUG_VOID_RETURN;
}
/* end of internal connections support */
int XSync (dpy, discard)
register Display *dpy;
Bool discard;
{
DBUG_ENTER("XSync")
QMSG qmsg;
pthread_mutex_lock(&evmutex);
while (WinPeekMsg(mainhab, &qmsg, 0, 0, 0, PM_REMOVE))
WinDispatchMsg(mainhab, &qmsg);
pthread_mutex_unlock(&evmutex);
DBUG_RETURN(1);
}
void Xlib_crash(int signal)
{
extern HMODULE hk_module;
extern HAB pmctls_hab;
x11_console_notice("SIGSEGV caught! Removing input queue hook.\n");
if(WinReleaseHook(pmctls_hab, NULLHANDLE, HK_INPUT, Xlib_InputQueueHook, hk_module)==FALSE)
x11_console_notice("Error removing the input hook!\n");
else
{
x11_console_notice("Xlib/PM successfully shutdown. (Xlib_crash)\n");
DosFreeModule(hk_module);
}
}
void Xlib_SetGC(HPS hps, Xlib_GC *xgc)
{
LONG alTable[18];
GpiQueryLogColorTable(hps, 0L, 0L, 18L, alTable);
alTable[16] = xgc->values.foreground;
alTable[17] = xgc->values.background;
GpiCreateLogColorTable(hps,
0L,
LCOLF_CONSECRGB,
0L,
18,
alTable);
GpiSetColor(hps, 16);
GpiSetBackColor(hps, 17);
GpiSetMix(hps, GXtoMixMode[xgc->values.function]);
GpiSetBackMix(hps, GXtoMixMode[xgc->values.function]);
GpiSetLineWidthGeom(hps, xgc->values.line_width);
GpiSetLineType(hps, LineStyletoLineType[xgc->values.line_style]);
GpiSetLineEnd(hps, CapStyletoLineEnd[xgc->values.cap_style]);
GpiSetLineJoin(hps, JoinStyletoLineJoin[xgc->values.join_style]);
}