home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Shareware 1999 March
/
PCShareware-3-99.iso
/
IMPLE
/
DJGPP.RAR
/
DJGPP2
/
XLIB-SR0.ZIP
/
SRC
/
EXTENSIO
/
XMULTIBU.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-03
|
22KB
|
698 lines
/*
* $XConsortium: XMultibuf.c,v 1.26 91/05/04 19:32:35 rws Exp $
*
* Copyright 1989 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. M.I.T. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Authors: Jim Fulton, MIT X Consortium
*/
#define NEED_EVENTS
#define NEED_REPLIES
#include <X11/Xlibint.h>
#include "Xext.h" /* in ../include */
#include "extutil.h" /* in ../include */
#include "multibst.h" /* in ../include */
static XExtensionInfo _multibuf_info_data;
static XExtensionInfo *multibuf_info = &_multibuf_info_data;
static /* const */ char *multibuf_extension_name = MULTIBUFFER_PROTOCOL_NAME;
#define MbufCheckExtension(dpy,i,val) \
XextCheckExtension (dpy, i, multibuf_extension_name, val)
#define MbufSimpleCheckExtension(dpy,i) \
XextSimpleCheckExtension (dpy, i, multibuf_extension_name)
/*****************************************************************************
* *
* private utility routines *
* *
*****************************************************************************/
/*
* find_display - locate the display info block
*/
static int close_display();
static char *error_string();
static Bool wire_to_event();
static Status event_to_wire();
static /* const */ XExtensionHooks multibuf_extension_hooks = {
NULL, /* create_gc */
NULL, /* copy_gc */
NULL, /* flush_gc */
NULL, /* free_gc */
NULL, /* create_font */
NULL, /* free_font */
close_display, /* close_display */
wire_to_event, /* wire_to_event */
event_to_wire, /* event_to_wire */
NULL, /* error */
error_string, /* error_string */
};
static /* const */ char *multibuf_error_list[] = {
"BadBuffer", /* MultibufferBadBuffer */
};
static XEXT_GENERATE_FIND_DISPLAY (find_display, multibuf_info,
multibuf_extension_name,
&multibuf_extension_hooks,
MultibufferNumberEvents, NULL)
static XEXT_GENERATE_CLOSE_DISPLAY (close_display, multibuf_info)
static XEXT_GENERATE_ERROR_STRING (error_string, multibuf_extension_name,
MultibufferNumberErrors,
multibuf_error_list)
/*
* wire_to_event - convert a wire event in network format to a C
* event structure
*/
static Bool wire_to_event (dpy, libevent, netevent)
Display *dpy;
XEvent *libevent;
xEvent *netevent;
{
XExtDisplayInfo *info = find_display (dpy);
MbufCheckExtension (dpy, info, False);
switch ((netevent->u.u.type & 0x7f) - info->codes->first_event) {
case MultibufferClobberNotify:
{
XmbufClobberNotifyEvent *ev;
xMbufClobberNotifyEvent *event;
ev = (XmbufClobberNotifyEvent *) libevent;
event = (xMbufClobberNotifyEvent *) netevent;
ev->type = event->type & 0x7f;
ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent);
ev->send_event = ((event->type & 0x80) != 0);
ev->display = dpy;
ev->buffer = event->buffer;
return True;
}
case MultibufferUpdateNotify:
{
XmbufUpdateNotifyEvent *ev;
xMbufUpdateNotifyEvent *event;
ev = (XmbufUpdateNotifyEvent *) libevent;
event = (xMbufUpdateNotifyEvent *) netevent;
ev->type = event->type & 0x7f;
ev->serial = _XSetLastRequestRead(dpy,(xGenericReply *) netevent);
ev->send_event = ((event->type & 0x80) != 0);
ev->display = dpy;
ev->buffer = event->buffer;
return True;
}
}
return False;
}
/*
* event_to_wire - convert a C event structure to a wire event in
* network format
*/
static Status event_to_wire (dpy, libevent, netevent)
Display *dpy;
XEvent *libevent;
xEvent *netevent;
{
XExtDisplayInfo *info = find_display (dpy);
MbufCheckExtension (dpy, info, 0);
switch ((libevent->type & 0x7f) - info->codes->first_event) {
case MultibufferClobberNotify:
{
XmbufClobberNotifyEvent *ev;
xMbufClobberNotifyEvent *event;
ev = (XmbufClobberNotifyEvent *) libevent;
event = (xMbufClobberNotifyEvent *) netevent;
event->type = ev->type;
event->sequenceNumber = (ev->serial & 0xffff);
event->buffer = ev->buffer;
return 1;
}
case MultibufferUpdateNotify:
{
XmbufUpdateNotifyEvent *ev;
xMbufUpdateNotifyEvent *event;
ev = (XmbufUpdateNotifyEvent *) libevent;
event = (xMbufUpdateNotifyEvent *) netevent;
event->type = ev->type;
event->sequenceNumber = (ev->serial & 0xffff);
event->buffer = ev->buffer;
return 1;
}
}
return 0;
}
/*
* read_buffer_info - read Buffer Info descriptors from the net; if unable
* to allocate memory, read junk to make sure that stream is clear.
*/
#define TALLOC(type,count) ((type *) Xmalloc ((unsigned) count * sizeof(type)))
static XmbufBufferInfo *read_buffer_info (dpy, nbufs)
Display *dpy;
int nbufs;
{
xMbufBufferInfo *netbuf = TALLOC (xMbufBufferInfo, nbufs);
XmbufBufferInfo *bufinfo = NULL;
long netbytes = nbufs * SIZEOF(xMbufBufferInfo);
if (netbuf) {
_XRead (dpy, (char *) netbuf, netbytes);
bufinfo = TALLOC (XmbufBufferInfo, nbufs);
if (bufinfo) {
register XmbufBufferInfo *c;
register xMbufBufferInfo *net;
register int i;
for (i = 0, c = bufinfo, net = netbuf; i < nbufs;
i++, c++, net++) {
c->visualid = net->visualID;
c->max_buffers = net->maxBuffers;
c->depth = net->depth;
}
}
Xfree ((char *) netbuf);
} else { /* eat the data */
while (netbytes > 0) {
char dummy[256]; /* stack size vs loops tradeoff */
long nbytes = sizeof dummy;
if (nbytes > netbytes) nbytes = netbytes;
_XRead (dpy, dummy, nbytes);
netbytes -= nbytes;
}
}
return bufinfo;
}
#undef TALLOC
/*****************************************************************************
* *
* Multibuffering/stereo public interfaces *
* *
*****************************************************************************/
/*
* XmbufQueryExtension -
* Returns True if the multibuffering/stereo extension is available
* on the given display. If the extension exists, the value of the
* first event code (which should be added to the event type constants
* MultibufferClobberNotify and MultibufferUpdateNotify to get the
* actual values) is stored into event_base and the value of the first
* error code (which should be added to the error type constant
* MultibufferBadBuffer to get the actual value) is stored into
* error_base.
*/
Bool XmbufQueryExtension (dpy, event_base_return, error_base_return)
Display *dpy;
int *event_base_return, *error_base_return;
{
XExtDisplayInfo *info = find_display (dpy);
if (XextHasExtension (info)) {
*event_base_return = info->codes->first_event;
*error_base_return = info->codes->first_error;
return True;
} else {
return False;
}
}
/*
* XmbufGetVersion -
* Gets the major and minor version numbers of the extension. The return
* value is zero if an error occurs or non-zero if no error happens.
*/
Status XmbufGetVersion (dpy, major_version_return, minor_version_return)
Display *dpy;
int *major_version_return, *minor_version_return;
{
XExtDisplayInfo *info = find_display (dpy);
xMbufGetBufferVersionReply rep;
register xMbufGetBufferVersionReq *req;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
MbufGetReq (MbufGetBufferVersion, req, info);
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
*major_version_return = rep.majorVersion;
*minor_version_return = rep.minorVersion;
UnlockDisplay (dpy);
SyncHandle ();
return 1;
}
/*
* XmbufCreateBuffers -
* Requests that "count" buffers be created with the given update_action
* and update_hint and be associated with the indicated window. The
* number of buffers created is returned (zero if an error occurred)
* and buffers_return is filled in with that many Multibuffer identifiers.
*/
int XmbufCreateBuffers (dpy, w, count, update_action, update_hint, buffers)
Display *dpy;
Window w;
int count;
int update_action, update_hint;
Multibuffer *buffers;
{
XExtDisplayInfo *info = find_display (dpy);
xMbufCreateImageBuffersReply rep;
register xMbufCreateImageBuffersReq *req;
int i, result;
MbufCheckExtension (dpy, info, 0);
/*
* allocate the id; hopefully, it would be nice to be able to
* get rid of the ones we don't need, but this would require access
* various Xlib internals. we could do caching on this side, but the
* chances of wasting enough resources to really matter is very small
*/
for (i = 0; i < count; i++) buffers[i] = XAllocID (dpy);
LockDisplay (dpy);
MbufGetReq (MbufCreateImageBuffers, req, info);
req->window = w;
req->updateAction = update_action;
req->updateHint = update_hint;
req->length += count;
PackData32 (dpy, buffers, count * sizeof (Multibuffer));
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
result = rep.numberBuffer;
UnlockDisplay (dpy);
SyncHandle ();
return result;
}
/*
* XmbufDestroyBuffers -
* Destroys the buffers associated with the given window.
*/
void XmbufDestroyBuffers (dpy, window)
Display *dpy;
Window window;
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufDestroyImageBuffersReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufDestroyImageBuffers, req, info);
req->window = window;
UnlockDisplay (dpy);
SyncHandle ();
}
/*
* XmbufDisplayBuffers -
* Displays the indicated buffers their appropriate windows within
* max_delay milliseconds after min_delay milliseconds have passed.
* No two buffers may be associated with the same window or else a Matc
* error is generated.
*/
void XmbufDisplayBuffers (dpy, count, buffers, min_delay, max_delay)
Display *dpy;
int count;
Multibuffer *buffers;
int min_delay, max_delay;
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufDisplayImageBuffersReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufDisplayImageBuffers, req, info);
req->minDelay = min_delay;
req->maxDelay = max_delay;
req->length += count;
PackData32 (dpy, buffers, count * sizeof (Multibuffer));
UnlockDisplay (dpy);
SyncHandle();
}
/*
* XmbufGetWindowAttributes -
* Gets the multibuffering attributes that apply to all buffers associated
* with the given window. Returns non-zero on success and zero if an
* error occurs.
*/
Status XmbufGetWindowAttributes (dpy, w, attr)
Display *dpy;
Window w;
XmbufWindowAttributes *attr;
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufGetMBufferAttributesReq *req;
xMbufGetMBufferAttributesReply rep;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
MbufGetReq (MbufGetMBufferAttributes, req, info);
req->window = w;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
attr->buffers = (Multibuffer *) NULL;
if (attr->nbuffers = rep.length) {
int nbytes = rep.length * sizeof(Multibuffer);
attr->buffers = (Multibuffer *) Xmalloc((unsigned) nbytes);
nbytes = rep.length << 2;
if (! attr->buffers) {
_XEatData(dpy, (unsigned long) nbytes);
UnlockDisplay(dpy);
SyncHandle();
return (0);
}
_XRead32 (dpy, (char *) attr->buffers, nbytes);
}
attr->displayed_index = rep.displayedBuffer;
attr->update_action = rep.updateAction;
attr->update_hint = rep.updateHint;
attr->window_mode = rep.windowMode;
UnlockDisplay (dpy);
SyncHandle();
return 1;
}
/*
* XmbufChangeWindowAttributes -
* Sets the multibuffering attributes that apply to all buffers associated
* with the given window. This is currently limited to the update_hint.
*/
void XmbufChangeWindowAttributes (dpy, w, valuemask, attr)
Display *dpy;
Window w;
unsigned long valuemask;
XmbufSetWindowAttributes *attr;
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufSetMBufferAttributesReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufSetMBufferAttributes, req, info);
req->window = w;
if (req->valueMask = valuemask) { /* stolen from lib/X/XWindow.c */
unsigned long values[1]; /* one per element in if stmts below */
unsigned long *v = values;
unsigned int nvalues;
if (valuemask & MultibufferWindowUpdateHint)
*v++ = attr->update_hint;
req->length += (nvalues = v - values);
nvalues <<= 2; /* watch out for macros... */
Data32 (dpy, (long *) values, (long)nvalues);
}
UnlockDisplay (dpy);
SyncHandle();
}
/*
* XmbufGetBufferAttributes -
* Gets the attributes for the indicated buffer. Returns non-zero on
* success and zero if an error occurs.
*/
Status XmbufGetBufferAttributes (dpy, b, attr)
Display *dpy;
Multibuffer b;
XmbufBufferAttributes *attr;
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufGetBufferAttributesReq *req;
xMbufGetBufferAttributesReply rep;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
MbufGetReq (MbufGetBufferAttributes, req, info);
req->buffer = b;
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
attr->window = rep.window;
attr->event_mask = rep.eventMask;
attr->buffer_index = rep.bufferIndex;
attr->side = rep.side;
UnlockDisplay (dpy);
SyncHandle();
return 1;
}
/*
* XmbufChangeBufferAttributes -
* Sets the attributes for the indicated buffer. This is currently
* limited to the event_mask.
*/
void XmbufChangeBufferAttributes (dpy, b, valuemask, attr)
Display *dpy;
Multibuffer b;
unsigned long valuemask;
XmbufSetBufferAttributes *attr;
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufSetBufferAttributesReq *req;
MbufSimpleCheckExtension (dpy, info);
LockDisplay (dpy);
MbufGetReq (MbufSetBufferAttributes, req, info);
req->buffer = b;
if (req->valueMask = valuemask) { /* stolen from lib/X/XWindow.c */
unsigned long values[1]; /* one per element in if stmts below */
unsigned long *v = values;
unsigned int nvalues;
if (valuemask & MultibufferBufferEventMask)
*v++ = attr->event_mask;
req->length += (nvalues = v - values);
nvalues <<= 2; /* watch out for macros... */
Data32 (dpy, (long *) values, (long)nvalues);
}
UnlockDisplay (dpy);
SyncHandle();
}
/*
* XmbufGetScreenInfo -
* Gets the parameters controlling how mono and stereo windows may be
* created on the indicated screen. The numbers of sets of visual and
* depths are returned in nmono_return and nstereo_return. If
* nmono_return is greater than zero, then mono_info_return is set to
* the address of an array of XmbufBufferInfo structures describing the
* various visuals and depths that may be used. Otherwise,
* mono_info_return is set to NULL. Similarly, stereo_info_return is
* set according to nstereo_return. The storage returned in
* mono_info_return and stereo_info_return may be released by XFree.
* If no errors are encounted, non-zero will be returned.
*/
Status XmbufGetScreenInfo (dpy, d, nmono_return, mono_info_return,
nstereo_return, stereo_info_return)
Display *dpy;
Drawable d;
int *nmono_return;
XmbufBufferInfo **mono_info_return;
int *nstereo_return;
XmbufBufferInfo **stereo_info_return;
{
XExtDisplayInfo *info = find_display (dpy);
register xMbufGetBufferInfoReq *req;
xMbufGetBufferInfoReply rep;
int nmono, nstereo;
XmbufBufferInfo *minfo, *sinfo;
MbufCheckExtension (dpy, info, 0);
LockDisplay (dpy);
MbufGetReq (MbufGetBufferInfo, req, info);
req->drawable = d;
if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
UnlockDisplay (dpy);
SyncHandle ();
return 0;
}
nmono = rep.normalInfo;
nstereo = rep.stereoInfo;
minfo = ((nmono > 0) ? read_buffer_info (dpy, nmono) : NULL);
sinfo = ((nstereo > 0) ? read_buffer_info (dpy, nstereo) : NULL);
/* check for bad reads indicating we need to return an error */
if ((nmono > 0 && !minfo) || (nstereo > 0 && !sinfo)) {
if (minfo) Xfree ((char *) minfo);
if (sinfo) Xfree ((char *) sinfo);
UnlockDisplay (dpy);
SyncHandle();
return 0;
}
*nmono_return = nmono;
*mono_info_return = minfo;
*nstereo_return = nstereo;
*stereo_info_return = sinfo;
UnlockDisplay (dpy);
SyncHandle();
return 1;
}
/*
* XmbufCreateStereoWindow -
* Creates a stereo window in the same way that XCreateWindow creates
* a mono window (in fact, use the same code, except for the request)
* and returns the left and right buffers that may be
*/
Window XmbufCreateStereoWindow (dpy, parent, x, y, width, height, border_width,
depth, class, visual, valuemask, attr,
leftp, rightp)
Display *dpy;
Window parent;
int x, y;
unsigned int width, height, border_width;
int depth;
unsigned int class;
Visual *visual;
unsigned long valuemask;
XSetWindowAttributes *attr;
Multibuffer *leftp, *rightp;
{
XExtDisplayInfo *info = find_display (dpy);
Window wid;
register xMbufCreateStereoWindowReq *req;
MbufCheckExtension (dpy, info, None);
LockDisplay(dpy);
MbufGetReq(MbufCreateStereoWindow, req, info);
wid = req->wid = XAllocID(dpy);
req->parent = parent;
req->left = *leftp = XAllocID (dpy);
req->right = *rightp = XAllocID (dpy);
req->x = x;
req->y = y;
req->width = width;
req->height = height;
req->borderWidth = border_width;
req->depth = depth;
req->class = class;
if (visual == CopyFromParent)
req->visual = CopyFromParent;
else
req->visual = visual->visualid;
valuemask &= (CWBackPixmap|CWBackPixel|CWBorderPixmap|
CWBorderPixel|CWBitGravity|CWWinGravity|
CWBackingStore|CWBackingPlanes|CWBackingPixel|
CWOverrideRedirect|CWSaveUnder|CWEventMask|
CWDontPropagate|CWColormap|CWCursor);
if (req->mask = valuemask) {
unsigned long values[32];
register unsigned long *value = values;
unsigned int nvalues;
if (valuemask & CWBackPixmap)
*value++ = attr->background_pixmap;
if (valuemask & CWBackPixel)
*value++ = attr->background_pixel;
if (valuemask & CWBorderPixmap)
*value++ = attr->border_pixmap;
if (valuemask & CWBorderPixel)
*value++ = attr->border_pixel;
if (valuemask & CWBitGravity)
*value++ = attr->bit_gravity;
if (valuemask & CWWinGravity)
*value++ = attr->win_gravity;
if (valuemask & CWBackingStore)
*value++ = attr->backing_store;
if (valuemask & CWBackingPlanes)
*value++ = attr->backing_planes;
if (valuemask & CWBackingPixel)
*value++ = attr->backing_pixel;
if (valuemask & CWOverrideRedirect)
*value++ = attr->override_redirect;
if (valuemask & CWSaveUnder)
*value++ = attr->save_under;
if (valuemask & CWEventMask)
*value++ = attr->event_mask;
if (valuemask & CWDontPropagate)
*value++ = attr->do_not_propagate_mask;
if (valuemask & CWColormap)
*value++ = attr->colormap;
if (valuemask & CWCursor)
*value++ = attr->cursor;
req->length += (nvalues = value - values);
nvalues <<= 2; /* watch out for macros... */
Data32 (dpy, (long *) values, (long)nvalues);
}
UnlockDisplay(dpy);
SyncHandle();
return wid;
}