home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v92.tgz
/
v92.tar
/
v92
/
src
/
runtime
/
rxwin.ri
< prev
Wrap
Text File
|
1996-03-22
|
90KB
|
3,559 lines
/*
* File: rxwin.ri - X11 system-specific graphics interface code.
*/
#ifdef Graphics
#define RootState IconicState+1
/*
* Global variables specific to X
*/
XSizeHints size_hints;
/*
* function prototypes
*/
int seticonicstate Params((wbp w, char *s));
int seticonpos Params((wbp w, char *s));
int handle_misc Params((wdp display, wbp w));
hidden int handle_config Params((wbp w, XConfigureEvent *event));
hidden int handle_exposures Params((wbp w, XExposeEvent *event));
hidden novalue handle_mouse Params((wbp w, XButtonEvent *event));
hidden novalue handle_keypress Params((wbp w, XKeyEvent *event));
hidden novalue postcursor Params((wbp w));
hidden novalue scrubcursor Params((wbp w));
hidden XImage * getximage Params((wbp w, int x, int y,
int width, int height, int init));
novalue moveWindow Params((wbp w, int x, int y));
int setdisplay Params((wbp w, char *s));
novalue makeIcon Params((wbp w, int x, int y));
int wmap Params((wbp w));
Pixmap loadimage Params((wbp w, char *filename, unsigned int *height, unsigned int *width, int atorigin, int *status));
novalue unsetclip Params((wbp w));
/*
* write some text to both the window and the pixmap
*/
novalue xdis(w,s,n)
register wbp w;
char *s;
int n;
{
int x, y, fh, delta_x;
STDLOCALS(w);
pollctr>>=1; pollctr++;
x = ws->x;
y = ws->y;
delta_x = XTextWidth(wc->font->fsp,s,n);
RENDER4(XDrawImageString,x,y,s,n);
ws->x += delta_x;
}
/*
* put a character out to a window using the current attributes
*/
int wputc(ci,w)
int ci;
wbp w;
{
int fh, lh, width, height, over;
char c = (char)ci;
STDLOCALS(w);
fh = wc->font->height;
lh = wc->leading;
width = ws->width;
height = ws->height;
switch(c) {
case '\r': {
ws->x = wc->dx;
break;
}
case '\n': {
if (ISCEOLON(w)) {
/*
* Clear the rest of the line, like a terminal would.
* Its arguable whether this should clear to the window
* background or the current context background. If you
* change it to use the context background you have to
* change the XClearArea call to another XFillRectangle
* (cf. eraseArea()).
*/
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, GXcopy);
XSetForeground(stddpy, stdgc, wc->bg->c);
XClearArea(stddpy, stdwin,
ws->x, ws->y-wc->font->fsp->max_bounds.ascent,
width-ws->x, lh, False);
XFillRectangle(stddpy, stdpix, stdgc,
ws->x, ws->y - wc->font->fsp->max_bounds.ascent,
width - ws->x, lh);
XSetForeground(stddpy, stdgc,wc->fg->c^(ISXORREVERSE(w)?wc->bg->c:0));
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, wc->drawop);
}
ws->y += lh;
ws->x = wc->dx;
/*
* Now for the exciting part: do we scroll the window?
* Copy the pixmap upward, then repaint the window.
*/
over = ws->y + wc->font->fsp->max_bounds.descent - height;
if (over > 0) {
ws->y -= over;
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, GXcopy);
XCopyArea(stddpy, stdpix, stdpix, stdgc,
0, over, /* x, y */
width, height - over, /* w, h */
0, 0); /* dstx,dsty */
XSetForeground(stddpy, stdgc, wc->bg->c);
XFillRectangle(stddpy, stdpix, stdgc,
0, height - over, width, over);
XSetForeground(stddpy, stdgc,wc->fg->c^(ISXORREVERSE(w)?wc->bg->c:0));
if (stdwin)
XCopyArea(stddpy, stdpix, stdwin, stdgc, 0, 0, width, height, 0,0);
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, wc->drawop);
}
break;
}
case '\t': {
xdis(w, " ", 8 - ((XTOCOL(w,ws->x))&7));
break;
}
/*
* Handle backspaces. This implements cooked mode echo handling.
*/
case '\177':
case '\010': {
int i = 0, pre_x;
/*
* Start with the last character queued up.
*/
i--;
/*
* Trot back to the control-H itself.
*/
while ((i>-EQUEUELEN) && (EVQUESUB(w,i) != c)) i--;
if (i == -EQUEUELEN) break;
/*
* Go past the control-H.
*/
i--;
/*
* Go back through any number of control-H's from prior lifetimes.
*/
while((i > -EQUEUELEN) && !isprint(EVQUESUB(w,i))) i--;
if (i == -EQUEUELEN) break;
/*
* OK, here's the character we're actually rubbing out. Back up.
*/
c = EVQUESUB(w,i);
pre_x = ws->x;
ws->x -= XTextWidth(wc->font->fsp, &c, 1);
/*
* Physically erase the character from the queue. This results in
* two control-H's present in the queue.
*/
*evquesub(w,i) = '\010';
/*
* Save the backed-up position, and draw spaces through the erased.
*/
i = ws->x;
while(ws->x < pre_x) xdis(w," ",1);
ws->x = i;
break;
}
default: {
xdis(w,&c,1);
}
}
return 1;
}
/*
* handle_misc processes pending events on display.
* if w is non-null, block until a returnable event arrives.
* returns 1 on success, 0 on failure, and -1 on error.
*/
int handle_misc(display, w)
wdp display;
wbp w;
{
XEvent event;
Window evwin;
int i;
static int presscount = 0;
wbp wb;
wsp ws;
while ((w != NULL) || XPending(display->display)) {
XNextEvent(display->display, &event);
evwin = event.xexpose.window; /* go ahead, criticize all you like */
/* could avoid doing this search every event by handling 1 window at a time */
for (wb = wbndngs; wb; wb=wb->next) {
ws = wb->window;
if ((ws->display == display) &&
((ws->win == evwin) || (ws->iconwin == evwin) ||
(ws->pix == evwin) || (ws->initialPix == evwin))) break;
}
if (!wb) continue;
if (evwin == ws->iconwin) {
switch (event.type) {
case Expose:
if (ws->iconpix)
XCopyArea(display->display, ws->iconpix, ws->iconwin,
display->icongc, 0, 0, ws->iconw, ws->iconh, 3, 3);
else
XDrawString(display->display, evwin, display->icongc, 4,
ws->display->fonts->fsp->max_bounds.ascent + 2,
ws->iconlabel, strlen(ws->iconlabel));
if (ws->iconic == IconicState)
SETEXPOSED(wb);
break;
case KeyPress:
handle_keypress(wb, (XKeyEvent *)&event);
break;
case ButtonPress:
if (ws->iconic == IconicState)
XMapWindow(ws->display->display, ws->win);
ws->iconic = NormalState; /* set the current state */
break;
case ConfigureNotify:
ws->iconx = ((XConfigureEvent *)&event)->x;
ws->icony = ((XConfigureEvent *)&event)->y;
break;
}
}
else {
switch (event.type) {
case KeyPress:
handle_keypress(wb, (XKeyEvent *)&event);
break;
case ButtonPress:
presscount++;
handle_mouse(wb, (XButtonEvent *)&event);
break;
case ButtonRelease:
if (--presscount < 0) presscount = 0;
handle_mouse(wb, (XButtonEvent *)&event);
break;
case MotionNotify:
if (presscount)
handle_mouse(wb, (XButtonEvent *)&event);
break;
case NoExpose:
break;
case Expose:
if (!handle_exposures(wb, (XExposeEvent *)&event))
return 1;
continue;
case UnmapNotify:
wb->window->iconic = IconicState;
continue;
case MapNotify:
ws->iconic = NormalState;
continue;
case ConfigureNotify:
if (!handle_config(wb, (XConfigureEvent *)&event)) {
return 0;
}
break;
case DestroyNotify:
if (!ISZOMBIE(wb)) return -1; /* error #141 */
/*
* first of all, we are done with this window
*/
ws->win = (Window) NULL;
/*
* if there are no more references, we are done with the pixmap
* too. Free it and the colors allocated for this canvas.
*/
if (ws->refcount == 0) {
if (wb->window->pix) {
Display *d = ws->display->display;
XSync(d, False);
if (ws->pix)
XFreePixmap(d, ws->pix);
ws->pix = (Pixmap) NULL;
}
if (ws->initialPix != (Pixmap) NULL) {
Display *d = ws->display->display;
XSync(d, False);
XFreePixmap(d, ws->initialPix);
ws->initialPix = (Pixmap) NULL;
}
free_xcolors(wb, 2); /* free regular colors */
free_xcolors(wb, 1); /* free icon colors */
}
break;
default:
continue;
}
if ((w != NULL) &&
((evwin == w->window->win) || (evwin == w->window->iconwin))) {
return 1;
}
}
}
return 1;
}
/*
* poll for available events on all opened displays.
* this is where the interpreter calls into the X interface.
*/
int pollevent()
{
wdp wd;
int hm;
for (wd = wdsplys; wd; wd = wd->next) {
if ((hm = handle_misc(wd, NULL)) < 1) {
if (hm == -1) return -1;
else if (hm == 0) {
/* how to handle failure? */
}
}
}
return 400;
}
/*
* get a single item from w's pending queue
*/
int wgetq(w,res)
wbp w;
dptr res;
{
int posted = 0;
while (1) {
STDLOCALS(w); /* leave inside loop; ws->pix can change! */
if (!EVQUEEMPTY(w)) {
EVQUEGET(w,*res);
if (posted)
scrubcursor(w);
return 1;
}
postcursor(w); /* post every time in case resize erased it */
posted = 1;
if (handle_misc(wd, w) == -1) {
if (posted)
scrubcursor(w);
return -1;
}
}
}
/*
* postcursor/scrubcursor calls must be paired without any intervening output.
*/
hidden novalue postcursor(w)
wbp w;
{
STDLOCALS(w);
if (!ISCURSORON(w) || !stdwin) return;
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, GXcopy);
if (ISXORREVERSE(w)) XSetForeground(stddpy, stdgc, wc->fg->c);
/* Draw only on window, not on backing pixmap */
XFillRectangle(stddpy, stdwin, stdgc, ws->x, ws->y, FWIDTH(w), DESCENT(w));
XSync(stddpy, False);
}
hidden novalue scrubcursor(w)
wbp w;
{
STDLOCALS(w);
if (!ISCURSORON(w) || !stdwin) return;
XCopyArea(stddpy, stdpix, stdwin, stdgc, /* restore window from pixmap */
ws->x, ws->y, FWIDTH(w), DESCENT(w), ws->x, ws->y);
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, wc->drawop);
if (ISXORREVERSE(w)) XSetForeground(stddpy, stdgc, wc->fg->c ^ wc->bg->c);
}
/*
* wclose - close a window. If is a real on-screen window,
* wait for a DestroyNotify event from the server before returning.
*/
int wclose(w)
wbp w;
{
STDLOCALS(w);
XSync(stddpy, False);
if (pollevent() == -1) return -1;
/*
* Force window to close (turn into a pixmap)
*/
if (ws->win && ws->refcount > 1) {
SETZOMBIE(w);
XDestroyWindow(stddpy,stdwin);
XFlush(stddpy);
ws->refcount--;
while (ws->win)
if (pollevent() == -1) return -1;
}
/*
* Entire canvas terminates
*/
else {
free_xcolors(w, 2);
free_xcolors(w, 1);
free_window(ws);
}
return 0;
}
/*
* flush a window
*/
novalue wflush(w)
wbp w;
{
STDLOCALS(w);
XFlush(stddpy);
}
/*
* flush all windows
*/
novalue wflushall()
{
wdp wd;
for (wd = wdsplys; wd != NULL; wd = wd->next) {
XFlush(wd->display);
}
}
/*
* sync all the servers
*/
novalue wsync(w)
wbp w;
{
wdp wd;
if (w == NULL) {
for (wd = wdsplys; wd != NULL; wd = wd->next) {
XSync(wd->display, False);
}
}
else
XSync(w->window->display->display, False);
}
/*
* open a window
* This routine really just allocates a window data structure.
* The interesting part is done in wmap, after the user preferences
* passed to Icon have been parsed. Returns NULL on error/failure;
* err_index is set to one of:
* >= 0: the index of an offending attribute value
* -1 : ordinary failure
* -2 : out of memory
*/
FILE *wopen(name, lp, attr, n, err_index)
char *name;
struct b_list *lp;
dptr attr;
int n, *err_index;
{
wbp w;
wsp ws;
char dispchrs[256];
char answer[128];
char *display = NULL;
int i;
tended struct b_list *tlp;
tended struct descrip attrrslt;
tlp = lp;
for(i=0;i<n;i++) {
if (is:string(attr[i]) &&
(StrLen(attr[i])>8) &&
!strncmp("display=",StrLoc(attr[i]),8)) {
mystrncpy(dispchrs,StrLoc(attr[i])+8,StrLen(attr[i])-8);
display = dispchrs;
}
}
if ((w = alc_wbinding()) == NULL) {
*err_index = -2;
return NULL;
}
if ((w->window = alc_winstate()) == NULL) {
*err_index = -2;
free_binding(w);
return NULL;
}
if ((w->window->display = alc_display(display)) == NULL) {
*err_index = -1; /* might be out of memory, probably bad DISPLAY var. */
free_binding(w);
return NULL;
}
ws = w->window;
ws->listp.dword = D_List;
BlkLoc(ws->listp) = (union block *)tlp;
/*
* some attributes of the display and window are used in the context
*/
if ((w->context = alc_context(w)) == NULL) {
*err_index = -2;
free_binding(w);
return NULL;
}
/*
* some attributes of the context determine window defaults
*/
ws->height = w->context->font->height * 12;
ws->width = w->context->font->fsp->max_bounds.width * 80;
ws->y = w->context->font->fsp->max_bounds.ascent;
ws->x = 0;
ws->y += w->context->dy;
ws->x += w->context->dx;
/*
* Loop through any remaining arguments.
*/
for (i = 0; i < n; i++){
/*
* write the attribute,
* except "display=" attribute, which is done earlier
*/
if((StrLen(attr[i])<9)||strncmp(StrLoc(attr[i]),"display=",8)) {
switch (wattrib((wbp) w, StrLoc(attr[i]), StrLen(attr[i]), &attrrslt,
answer)) {
case Error:
*err_index = i;
return NULL;
case Failed:
free_binding((wbp)w);
*err_index = -1;
return NULL;
}
}
}
if (ws->windowlabel == NULL) {
ws->windowlabel = salloc(name);
if (ws->windowlabel == NULL) { /* out of memory */
*err_index = -2;
return NULL;
}
}
if ((i = wmap(w)) != Succeeded) {
if (i == Failed) *err_index = -1;
else *err_index = 0;
return NULL;
}
return (FILE *)w;
}
/*
* make an icon for a window
*/
novalue makeIcon(w, x, y)
wbp w;
int x, y; /* current mouse position */
{
char *name;
int status;
STDLOCALS(w);
/* if a pixmap image has been specified, load it */
if (ws->initicon.width) {
ws->iconpix = XCreatePixmap(stddpy, DefaultRootWindow(stddpy),
ws->iconw, ws->iconh,
DefaultDepth(stddpy,wd->screen));
}
else if (ws->iconimage && strcmp(ws->iconimage, "")) {
ws->iconpix = loadimage(w, ws->iconimage, &(ws->iconh), &(ws->iconw),
0, &status);
ws->iconh += 6;
ws->iconw += 6;
}
else { /* determine the size of the icon window */
ws->iconh = wd->fonts->fsp->max_bounds.ascent +
wd->fonts->fsp->max_bounds.descent + 5;
if (ws->iconlabel == NULL) ws->iconlabel = "";
ws->iconw = XTextWidth(wd->fonts->fsp, ws->iconlabel,
strlen(ws->iconlabel)) + 6;
}
/* if icon position hint exists, get it */
if (ws->wmhintflags & IconPositionHint) {
x = ws->iconx;
y = ws->icony;
}
/* create the icon window */
ws->iconwin = XCreateSimpleWindow(stddpy, DefaultRootWindow(stddpy), x, y,
ws->iconw, ws->iconh, 2, wc->fg->c,
wc->bg->c);
/* select events for the icon window */
XSelectInput(stddpy, ws->iconwin,
ExposureMask | KeyPressMask | ButtonPressMask |
StructureNotifyMask);
}
/*
* Create a canvas.
* If a window, cause the window to actually become visible on the screen.
* returns Succeeded, Failed, or Error
*/
int wmap(w)
wbp w;
{
XWindowAttributes attrs;
XGCValues gcv;
unsigned long gcmask =
GCFont | GCForeground | GCBackground | GCFillStyle | GCCapStyle;
struct imgdata *imd;
int i, r;
int new_pixmap = 0;
char *p, *s;
XWMHints wmhints;
XClassHint clhints;
STDLOCALS(w);
/*
* Create a pixmap for this canvas if there isn't one already.
*/
if (ws->pix == (Pixmap) NULL) {
if (ws->initialPix) {
ws->pix = ws->initialPix;
ws->initialPix = (Pixmap) NULL;
ws->pixwidth = ws->width;
ws->pixheight = ws->height;
}
else {
ws->pix = XCreatePixmap(stddpy, DefaultRootWindow(stddpy),
ws->width, ws->height,
DefaultDepth(stddpy,wd->screen));
ws->pixwidth = ws->width;
ws->pixheight = ws->height;
new_pixmap = 1;
}
stdpix = ws->pix;
}
/*
* create the X window (or use the DefaultRootWindow if requested)
*/
if (ws->iconic != HiddenState) {
ws->win = ((ws->iconic == RootState) ? DefaultRootWindow(stddpy) :
XCreateSimpleWindow(stddpy, DefaultRootWindow(stddpy),
ws->posx < 0 ? 0 : ws->posx,
ws->posy < 0 ? 0 : ws->posy, ws->width,
ws->height, 1, wc->fg->c, wc->bg->c));
if (ws->win == (Window) NULL)
return Failed;
stdwin = ws->win;
XClearWindow(stddpy, stdwin);
}
/*
* before creating the graphics context, construct a description
* of any non-default initial graphics context values.
*/
gcv.foreground = wc->fg->c ^ (ISXORREVERSE(w) ? wc->bg->c : 0);
gcv.background = wc->bg->c;
gcv.font = wc->font->fsp->fid;
if (wc->fillstyle)
gcv.fill_style = wc->fillstyle;
else
gcv.fill_style = wc->fillstyle = FillSolid;
if (wc->linestyle || wc->linewidth) {
gcmask |= (GCLineWidth | GCLineStyle);
gcv.line_width = wc->linewidth;
gcv.line_style = wc->linestyle;
if (wc->linewidth > 1) {
gcv.dashes = 3 * wc->linewidth;
gcmask |= GCDashList;
}
}
else
wc->linestyle = LineSolid;
gcv.cap_style = CapProjecting;
/*
* Create a graphics context (or change an existing one to conform
* with initial values).
*/
if (stdgc == NULL) {
wc->gc = XCreateGC(stddpy, stdpix, gcmask, &gcv);
stdgc = wc->gc;
if (stdgc == NULL) return Failed;
}
else
XChangeGC(stddpy, stdgc, gcmask, &gcv);
if (wc->clipw >= 0)
setclip(w);
if (new_pixmap) {
XSetForeground(stddpy, stdgc, wc->bg->c);
XFillRectangle(stddpy, ws->pix, stdgc, 0, 0, ws->width, ws->height);
XSetForeground(stddpy, stdgc, wc->fg->c ^(ISXORREVERSE(w)?wc->bg->c:0));
}
imd = &ws->initimage;
if (imd->width) {
r = strimage(w, 0, 0, imd->width, imd->height, imd->paltbl,
imd->data, (word)imd->width * (word)imd->height, 0);
free((pointer)imd->paltbl);
free((pointer)imd->data);
imd->width = 0;
if (r < 0)
return Failed;
}
imd = &ws->initicon;
if (imd->width) {
r = strimage(w, 0, 0, imd->width, imd->height, imd->paltbl,
imd->data, (word)imd->width * (word)imd->height, 1);
free((pointer)imd->paltbl);
free((pointer)imd->data);
imd->width = 0;
if (r < 0)
return Failed;
wmhints.icon_window = ws->iconwin;
ws->wmhintflags |= IconWindowHint;
}
if (wc->patternname != NULL) {
if (SetPattern(w, wc->patternname, strlen(wc->patternname)) != Succeeded)
return Failed;
}
/*
* if we are opening a pixmap, we are done at this point.
*/
if (stdwin == (Window) NULL) return Succeeded;
if (ws->iconic != RootState) {
size_hints.flags = PSize | PMinSize | PMaxSize;
size_hints.width = ws->width;
size_hints.height= ws->height;
if (ws->posx == -(MaxInt)) ws->posx = 0;
else size_hints.flags |= USPosition;
if (ws->posy == -(MaxInt)) ws->posy = 0;
else size_hints.flags |= USPosition;
size_hints.x = ws->posx;
size_hints.y = ws->posy;
if (ISRESIZABLE(w)) {
size_hints.min_width = 0;
size_hints.min_height = 0;
size_hints.max_width = DisplayWidth(stddpy, wd->screen);
size_hints.max_height = DisplayHeight(stddpy, wd->screen);
}
else {
size_hints.min_width = size_hints.max_width = ws->width;
size_hints.min_height = size_hints.max_height = ws->height;
}
if (ws->iconlabel == NULL) {
if ((ws->iconlabel = salloc(ws->windowlabel)) == NULL)
ReturnErrNum(305, Error);
}
XSetStandardProperties(stddpy, stdwin, ws->windowlabel, ws->iconlabel,
0,0,0, &size_hints);
XSelectInput(stddpy, stdwin, ExposureMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
StructureNotifyMask);
}
wmhints.input = True;
wmhints.flags = InputHint;
if (ws->iconic != RootState) {
if (ws->iconimage != NULL) {
makeIcon(w, ws->posx < 0 ? 0 : ws->posx, ws->posy < 0 ? 0 : ws->posy);
wmhints.icon_window = ws->iconwin;
ws->wmhintflags |= IconWindowHint;
}
wmhints.flags |= (ws->wmhintflags | StateHint);
wmhints.initial_state = ws->iconic;
wmhints.icon_x = ws->iconx;
wmhints.icon_y = ws->icony;
}
XSetWMHints(stddpy, stdwin, &wmhints);
/*
* Set the class hints that name the program (for reference by the
* window manager) following conventions given in O'Reilly.
*/
if (! (s = getenv("RESOURCE_NAME"))) {
p = StrLoc(kywd_prog);
s = p + StrLen(kywd_prog);
while (s > p && s[-1] != '/')
s--; /* find tail of prog_name */
}
clhints.res_name = s;
clhints.res_class = "IconProg";
XSetClassHint(stddpy, stdwin, &clhints);
if (wd->cmap != DefaultColormap(stddpy,wd->screen))
XSetWindowColormap(stddpy, stdwin, wd->cmap);
if (ws->iconic != RootState)
XMapWindow(stddpy, stdwin);
XGetWindowAttributes(stddpy, stdwin, &attrs);
ws->width = attrs.width;
ws->height = attrs.height;
if (!resizePixmap(w, ws->width, ws->height)) return Failed;
if (stdwin) {
i = ws->theCursor;
if (!(wd->cursors[i]))
wd->cursors[i] = XCreateFontCursor(stddpy, 2 * i);
XDefineCursor(stddpy, stdwin, wd->cursors[i]);
}
/*
* busy loop for an expose event, unless of course we are starting out
* in an iconic state
*/
CLRZOMBIE(w);
if (ws->win != (Window) NULL) {
int hm;
while (!ISEXPOSED(w) && (ws->iconic != IconicState || ws->iconwin)) {
if ((hm = handle_misc(wd, w)) < 1) {
if (hm == -1) return Error;
else if (hm == 0) {
/* how to handle failure? */
}
}
}
}
XSetFunction(stddpy, stdgc, wc->drawop);
XSync(stddpy, False);
return Succeeded;
}
int do_config(w, status)
wbp w;
int status;
{
wsp ws = w->window;
wdp wd = ws->display;
int wid = ws->width, ht = ws->height;
int posx = ws->posx, posy = ws->posy;
XTextProperty textprop;
if (! resizePixmap(w, ws->width, ws->height))
return Failed;
if (ws->win) {
XSync(wd->display, False);
pollevent();
if (status == 1)
moveWindow(w, posx, posy);
else {
if (status == 2)
posx = posy = -MaxInt;
if (moveResizeWindow(w, posx, posy, wid, ht) == Failed)
return Failed;
}
/* XSync is not enough because the window manager gets involved here. */
XFlush(wd->display); /* force out request */
XGetWMName(wd->display, ws->win, &textprop); /* force WM round trip */
XSync(wd->display, False); /* NOW sync */
}
return Succeeded;
}
int setheight(w, new_height)
wbp w;
SHORT new_height;
{
STDLOCALS(w);
if (new_height < 0) return Failed;
ws->height = size_hints.height = new_height;
return Succeeded;
}
int setwidth(w, new_width)
wbp w;
SHORT new_width;
{
STDLOCALS(w);
if (new_width < 0) return Failed;
ws->width = size_hints.width = new_width;
return Succeeded;
}
int setgeometry(w, geo)
wbp w;
char *geo;
{
int width = 0, height = 0;
int x = 0, y = 0, status;
char *tmps;
STDLOCALS(w);
if ((status = parsegeometry(geo, &x, &y, &width, &height)) == 0)
return Error;
if (status & 1) {
ws->width = size_hints.width = width;
ws->height = size_hints.height = height;
}
if (status & 2) {
ws->posx = x;
ws->posy = y;
}
/* insert assigns here:
* ws->posx = ((sign > 0) ? tmp :
* DisplayWidth(stddpy,wd->screen) - ws->width - tmp);
* ws->posy = ((sign > 0) ? tmp :
* DisplayHeight(stddpy,wd->screen) - ws->height - tmp);
*/
return Succeeded;
}
int allowresize(w, on)
wbp w;
int on;
{
if (on)
SETRESIZABLE(w);
else
CLRRESIZABLE(w);
return Succeeded;
}
novalue warpPointer(w, x, y)
wbp w;
int x, y;
{
wsp ws = w->window;
XWarpPointer(ws->display->display, None, ws->win, 0,0,0,0, x, y);
}
/*
* #@#@ This is a bug
*/
int seticonlabel(w, val)
wbp w;
char *val;
{
STDLOCALS(w);
if (ws->iconlabel != NULL) free(ws->iconlabel);
if ((ws->iconlabel = salloc(val)) == NULL)
ReturnErrNum(305, Error);
if (stddpy && stdwin) {
XSetIconName(stddpy, stdwin, w->window->iconlabel);
if (ws->iconic == IconicState && !ws->iconpix && ws->iconwin) {
XClearWindow(stddpy, ws->iconwin);
XDrawString(stddpy, ws->iconwin, wd->icongc, 4,
wd->fonts->fsp->max_bounds.ascent + 2,
ws->iconlabel, strlen(ws->iconlabel));
}
}
return Succeeded;
}
/*
* setwindowlabel
*/
int setwindowlabel(w, s)
wbp w;
char *s;
{
wsp ws = w->window;
if (ws->windowlabel != NULL) free(ws->windowlabel);
if ((ws->windowlabel = salloc(s)) == NULL)
ReturnErrNum(305, Error);
if (ws->display && ws->display->display && ws->win)
XStoreName(ws->display->display, ws->win,
*ws->windowlabel ? ws->windowlabel : " "); /* empty string fails */
return Succeeded;
}
/*
* setcursor() - a no-op under X at present
*/
int setcursor(w, on)
wbp w;
int on;
{
if (on)
SETCURSORON(w);
else
CLRCURSORON(w);
return Succeeded;
}
/*
* setpointer() - define a mouse pointer shape
*/
int setpointer(w, val)
wbp w;
char *val;
{
int i = si_s2i(cursorsyms,val) >> 1;
STDLOCALS(w);
if (i < 0 || i >= NUMCURSORSYMS) return Failed;
ws->theCursor = i;
if (!(wd->cursors[i]))
wd->cursors[i] = XCreateFontCursor(stddpy, 2 * i);
if (stdwin)
XDefineCursor(stddpy, stdwin, wd->cursors[i]);
return Succeeded;
}
/*
* setdrawop() - set the drawing operation
*/
int setdrawop(w, val)
wbp w;
char *val;
{
STDLOCALS(w);
XSync(stddpy, False);
if (!strcmp(val,"reverse")) {
if (!ISXORREVERSE(w)) {
SETXORREVERSE(w);
wc->drawop = GXxor;
if (stdgc)
XSetForeground(stddpy, stdgc, wc->fg->c ^ wc->bg->c);
}
}
else {
if (ISXORREVERSE(w)) {
CLRXORREVERSE(w);
if (stdgc)
XSetForeground(stddpy, stdgc, wc->fg->c);
}
wc->drawop = si_s2i(drawops,val);
if (wc->drawop == -1) { wc->drawop = GXcopy; return Error; }
}
if (stdgc) XSetFunction(stddpy, stdgc, wc->drawop);
return Succeeded;
}
/*
* rebind() - bind w's context to that of w2.
*/
int rebind(w, w2)
wbp w, w2;
{
if (w->window->display != w2->context->display) return Failed;
w->context = w2->context;
return Succeeded;
}
novalue setclip(w)
wbp w;
{
wcp wc = w->context;
XRectangle rec;
if (wc->gc) {
rec.x = wc->clipx;
rec.y = wc->clipy;
rec.width = wc->clipw;
rec.height = wc->cliph;
XSetClipRectangles(wc->display->display, wc->gc, 0, 0, &rec, 1,Unsorted);
}
}
novalue unsetclip(w)
wbp w;
{
wcp wc = w->context;
if (wc->gc) {
XSetClipMask(wc->display->display, wc->gc, None);
}
}
novalue getcanvas(w, s)
wbp w;
char *s;
{
if (w->window->win == (Window) NULL) sprintf(s, "hidden");
else
switch (w->window->iconic) {
case RootState:
sprintf(s, "root");
break;
case NormalState:
sprintf(s, "normal");
break;
case IconicState:
sprintf(s, "iconic");
break;
case MaximizedState:
sprintf(s, "maximal");
break;
case HiddenState:
sprintf(s, "hidden");
break;
default:
sprintf(s, "???");
}
}
/*
* Set the canvas type, either during open (pixmap is null, set a flag)
* or change an existing canvas to a different type.
*/
int setcanvas(w,s)
wbp w;
char *s;
{
XWindowAttributes attrs;
XGCValues gcv;
int hm;
XWMHints wmhints;
STDLOCALS(w);
if (!strcmp(s, "iconic")) {
if (ws->pix == (Pixmap) NULL) {
ws->wmhintflags |= StateHint;
ws->iconic = IconicState;
}
else {
if (!ISICONIC(w)) {
#ifdef Iconify
XIconifyWindow(ws->display->display, ws->win, ws->display->screen);
XSync(stddpy, False);
while (ws->iconic != IconicState)
if ((hm = handle_misc(wd, NULL)) < 1) {
if (hm == -1) return Error;
else if (hm == 0) {
return Failed;
}
}
#else /* Iconify */
return Failed;
#endif /* Iconify */
}
}
}
else if (!strcmp(s, "normal")) {
if (ws->pix == (Pixmap) NULL) {
ws->iconic = NormalState;
}
else {
if (ws->win == (Window) NULL) {
ws->iconic = NormalState;
ws->initialPix = ws->pix;
ws->pix = (Window) NULL;
wmap(w);
}
else if (ISICONIC(w)) {
XMapWindow(stddpy, stdwin);
XSync(stddpy, False);
while (ws->iconic != NormalState)
pollevent();
}
else if (ws->iconic == MaximizedState) {
moveResizeWindow(w, ws->normalx, ws->normaly,
ws->normalw, ws->normalh);
ws->iconic = NormalState;
}
}
}
else if (!strcmp(s, "maximal")) {
if (ws->iconic != MaximizedState) {
int expect_config= (ws->width != DisplayWidth(stddpy, wd->screen)) ||
(ws->height != DisplayHeight(stddpy, wd->screen));
ws->normalx = ws->posx;
ws->normaly = ws->posy;
ws->normalw = ws->width;
ws->normalh = ws->height;
ws->width = DisplayWidth(stddpy, wd->screen);
ws->height= DisplayHeight(stddpy, wd->screen);
if (ws->pix != (Pixmap) NULL) {
if (ws->win == (Window) NULL) wmap(w);
XSync(stddpy, False);
pollevent();
if (expect_config) {
moveResizeWindow(w, 0, 0, ws->width, ws->height);
ws->posx = -1000;
while (ws->posx == -1000) pollevent();
moveWindow(w, -ws->posx, -ws->posy);
}
if (ISICONIC(w)) {
XMapWindow(stddpy, stdwin);
}
XSync(stddpy, False);
if ((hm = handle_misc(wd, NULL)) < 1) {
if (hm == -1) return Error;
else if (hm == 0) {
return Failed;
}
}
}
ws->iconic = MaximizedState;
}
}
else if (!strcmp(s, "hidden")) {
if (ws->pix == (Pixmap)NULL) {
ws->iconic = HiddenState;
}
else {
if (ws->win != (Window) NULL) {
if (ws->iconic == MaximizedState) {
ws->posx = ws->normalx;
ws->posy = ws->normaly;
ws->width = ws->normalw;
ws->height = ws->normalh;
ws->iconic = NormalState;
}
if (!ISICONIC(w)) {
SETZOMBIE(w);
XDestroyWindow(stddpy, stdwin);
XFlush(stddpy);
while (ws->win)
if (pollevent() == -1)
return Error;
}
}
}
}
else return Error;
XSync(ws->display->display, False);
return Succeeded;
}
int seticonicstate(w,s)
wbp w;
char *s;
{
STDLOCALS(w);
if (!strcmp(s, "icon")) {
if (ws->pix == (Pixmap) NULL) {
ws->wmhintflags |= StateHint;
ws->iconic = IconicState;
}
else {
if (!ISICONIC(w)) {
#ifdef Iconify
XIconifyWindow(ws->display->display, ws->win, ws->display->screen);
#else /* Iconify */
return Failed;
#endif /* Iconify */
}
}
}
else if (!strcmp(s, "window")) {
if (ws->win != (Window) NULL) {
if (ISICONIC(w)) {
XMapWindow(stddpy, stdwin);
}
}
}
else if (!strcmp(s, "root")) {
if (ws->win == (Window) NULL)
ws->iconic = RootState;
else return Failed;
}
else return Error;
XSync(ws->display->display, False);
return Succeeded;
}
int seticonpos(w,s)
wbp w;
char *s;
{
char *s2;
wsp ws = w->window;
ws->wmhintflags |= IconPositionHint;
s2 = s;
ws->iconx = atol(s2);
while (isspace(*s2)) s2++;
while (isdigit(*s2)) s2++;
if (*s2++ != ',') return Error;
ws->icony = atol(s2);
if (ws->win) {
if (ws->iconwin == (Window) NULL)
makeIcon(w, ws->iconx, ws->icony);
if (remap(w, ws->iconx, ws->icony) == -1) return Error;
}
return Succeeded;
}
geticonpos(w, s)
wbp w;
char *s;
{
wsp ws = w->window;
sprintf(s,"%d,%d", ws->iconx, ws->icony);
return Succeeded;
}
/*
* if the window exists and is visible, set its position to (x,y)
*/
novalue moveWindow(w,x,y)
wbp w;
int x, y;
{
STDLOCALS(w);
ws->posx = x;
ws->posy = y;
if (stdwin) {
XMoveWindow(stddpy, stdwin, ws->posx, ws->posy);
XSync(stddpy, False);
}
}
int moveResizeWindow(w, x, y, width, height)
wbp w;
int x, y, width, height;
{
wsp ws = w->window;
wdp wd = ws->display;
ws->width = width;
ws->height = height;
size_hints.flags = PMinSize | PMaxSize;
if (ISRESIZABLE(w)) {
size_hints.min_width = 0;
size_hints.min_height = 0;
size_hints.max_width = DisplayWidth(wd->display, wd->screen);
size_hints.max_height = DisplayHeight(wd->display, wd->screen);
}
else {
size_hints.min_width = size_hints.max_width = width;
size_hints.min_height = size_hints.max_height = height;
}
XSetNormalHints(wd->display, ws->win, &size_hints);
if (resizePixmap(w, width, height) == 0) return Failed;
if (ws->win != (Window) NULL) {
if (x == -MaxInt && y == -MaxInt)
XResizeWindow(wd->display, ws->win, width, height);
else
XMoveResizeWindow(wd->display, ws->win, x, y, width, height);
XSync(wd->display, False);
}
return Succeeded;
}
/*
* Set the context's fill style by name.
*/
int setfillstyle(w, s)
wbp w;
char *s;
{
STDLOCALS(w);
if (!strcmp(s, "solid")) {
wc->fillstyle = FillSolid;
}
else if (!strcmp(s, "masked")
|| !strcmp(s, "stippled") || !strcmp(s, "patterned")) {
wc->fillstyle = FillStippled;
}
else if (!strcmp(s, "textured")
|| !strcmp(s, "opaquestippled") || !strcmp(s, "opaquepatterned")) {
wc->fillstyle = FillOpaqueStippled;
}
else return Error;
if (stdpix) {
XSetFillStyle(stddpy, stdgc, wc->fillstyle);
}
return Succeeded;
}
/*
* Set the context's line style by name.
*/
int setlinestyle(w, s)
wbp w;
char *s;
{
STDLOCALS(w);
if (!strcmp(s, "solid")) {
wc->linestyle = LineSolid;
}
else if (!strcmp(s, "onoff") || !strcmp(s, "dashed")) {
wc->linestyle = LineOnOffDash;
}
else if (!strcmp(s, "doubledash") || !strcmp(s, "striped")) {
wc->linestyle = LineDoubleDash;
}
else return Error;
if (stdpix) {
XSetLineAttributes(stddpy, stdgc,
wc->linewidth, wc->linestyle, CapProjecting, JoinMiter);
}
return Succeeded;
}
/*
* Set the context's line width
*/
int setlinewidth(w, linewid)
wbp w;
LONG linewid;
{
unsigned long gcmask;
XGCValues gcv;
STDLOCALS(w);
if (linewid < 0) return Error;
wc->linewidth = linewid;
if (stdpix) {
gcv.line_width = linewid;
gcv.line_style = wc->linestyle;
if (linewid > 1)
gcv.dashes = 3 * wc->linewidth;
else
gcv.dashes = 4;
gcmask = GCLineWidth | GCLineStyle | GCDashList;
XChangeGC(stddpy, stdgc, gcmask, &gcv);
}
return Succeeded;
}
/*
* Reset the context's foreground color to whatever it is supposed to be.
*/
int resetfg(w)
wbp w;
{
wcp wc = w->context;
if (wc->gc != NULL)
XSetForeground(wc->display->display, wc->gc,
wc->fg->c ^ (ISXORREVERSE(w) ? wc->bg->c : 0));
return Succeeded;
}
/*
* Set the context's foreground color by name.
*/
int setfg(w,s)
wbp w;
char *s;
{
wclrp cp;
STDLOCALS(w);
Protect(cp = alc_color(w,s), return Failed);
wc->fg = cp;
return resetfg(w);
}
int setfgrgb(w, r, g, b)
wbp w;
int r, g, b;
{
char sbuf1[MaxCvtLen];
sprintf(sbuf1, "%d,%d,%d", r, g, b);
return setfg(w, sbuf1);
}
/*
* Set the context's foreground color by color cell.
*/
int isetfg(w,fg)
wbp w;
int fg;
{
int i, r, g, b;
STDLOCALS(w);
if (fg >= 0) {
b = fg & 255;
fg >>= 8;
g = fg & 255;
fg >>= 8;
r = fg & 255;
return setfgrgb(w, r * 257, g * 257, b * 257);
}
for (i = 2; i < DMAXCOLORS; i++)
if (wd->colors[i].type == MUTABLE && wd->colors[i].c == -fg - 1)
break;
if (i == DMAXCOLORS) return Failed;
wc->fg = &(wd->colors[i]);
return resetfg(w);
}
/*
* Set the window context's background color by name.
*/
int setbg(w,s)
wbp w;
char *s;
{
wclrp cp;
STDLOCALS(w);
Protect(cp = alc_color(w,s), return Failed);
wc->bg = cp;
if (stdgc != NULL)
XSetBackground(stddpy, stdgc, wc->bg->c);
return ISXORREVERSE(w) ? resetfg(w) : Succeeded;
}
int setbgrgb(w, r, g, b)
wbp w;
int r, g, b;
{
char sbuf1[MaxCvtLen];
sprintf(sbuf1, "%d,%d,%d", r, g, b);
return setbg(w, sbuf1);
}
/*
* Set the context's background color by color cell.
*/
int isetbg(w,bg)
wbp w;
int bg;
{
int i, r, g, b;
STDLOCALS(w);
if (bg >= 0) {
b = bg & 255;
bg >>= 8;
g = bg & 255;
bg >>= 8;
r = bg & 255;
return setbgrgb(w, r * 257, g * 257, b * 257);
}
for (i = 2; i < DMAXCOLORS; i++)
if (wd->colors[i].type == MUTABLE && wd->colors[i].c == -bg - 1)
break;
if (i == DMAXCOLORS) return Failed;
wc->bg = &(wd->colors[i]);
if (stdgc != NULL)
XSetBackground(stddpy, stdgc, wc->bg->c);
return ISXORREVERSE(w) ? resetfg(w) : Succeeded;
}
/*
* Set the gamma correction value.
*/
int setgamma(w, gamma)
wbp w;
double gamma;
{
w->context->gamma = gamma;
setfg(w, w->context->fg->name); /* reinterpret current Fg/Bg spec */
setbg(w, w->context->bg->name);
return Succeeded;
}
/*
* Set the display by name. Really should cache answers as per fonts below;
* for now just open a new display each time. Note that this can only be
* called before a window is instantiated...
*/
int setdisplay(w,s)
wbp w;
char *s;
{
wdp d;
/* can't change display for mapped window! */
if (w->window->pix != (Pixmap) NULL)
return Failed;
Protect(d = alc_display(s), return 0);
w->window->display = d;
w->context->fg = &(d->colors[0]);
w->context->bg = &(d->colors[1]);
w->context->font = d->fonts;
return Succeeded;
}
setleading(w, i)
wbp w;
int i;
{
w->context->leading = i;
}
setimage(w, val)
wbp w;
char *val;
{
wsp ws = w->window;
int status;
ws->initialPix = loadimage(w, val, &(ws->height), &(ws->width),
0, &status);
if (ws->initialPix == (Pixmap) NULL) return Failed;
return Succeeded;
}
novalue toggle_fgbg(w)
wbp w;
{
wclrp tmp;
STDLOCALS(w);
tmp = wc->fg;
wc->fg = wc->bg;
wc->bg = tmp;
if (stdpix) {
XSetForeground(stddpy, stdgc,
wc->fg->c ^ (ISXORREVERSE(w)?wc->bg->c:0));
XSetBackground(stddpy, stdgc, wc->bg->c);
}
}
novalue getdisplay(w, answer)
wbp w;
char *answer;
{
char *tmp;
wdp wd = w->window->display;
if (!strcmp(wd->name, "")) {
if (tmp = getenv("DISPLAY"))
sprintf(answer, "%s", tmp);
else
strcpy(answer, "");
}
else sprintf(answer, "%s", wd->name);
}
int getvisual(w, answer)
wbp w;
char *answer;
{
wdp wd = w->window->display;
Visual * v = DefaultVisual(wd->display,wd->screen);
sprintf(answer, "%d,%d,%d", v->class, v->bits_per_rgb, v->map_entries );
return Succeeded;
}
/*
* getpos() - update the window state's notion of its current position
*/
int getpos(w)
wbp w;
{
Window garbage1, garbage2;
int root_x, root_y, win_x, win_y;
unsigned int key_buttons, width, height, depth;
STDLOCALS(w);
if (!stdwin) return Failed;
/*
* This call is made because it is guaranteed to generate
* a synchronous request of the server, not just ask Xlib
* what the window position was last it knew.
*/
if (XQueryPointer(stddpy, stdwin, &garbage1, &garbage2,
&root_x, &root_y, &win_x, &win_y, &key_buttons) ==
False) {
return Failed;
}
ws->posx = root_x - win_x;
ws->posy = root_y - win_y;
return Succeeded;
}
novalue getfg(w, answer)
wbp w;
char *answer;
{
sprintf(answer, "%s", w->context->fg->name);
}
novalue getbg(w, answer)
wbp w;
char *answer;
{
sprintf(answer, "%s", w->context->bg->name);
}
novalue getlinestyle(w, answer)
wbp w;
char *answer;
{
wcp wc = w->context;
sprintf(answer,"%s",
(wc->linestyle==LineSolid)?"solid":
((wc->linestyle==LineOnOffDash)?"dashed":"striped"));
}
novalue getfntnam(w, answer)
wbp w;
char *answer;
{
sprintf(answer,"%s", w->context->font->name);
}
novalue getpointername(w, answer)
wbp w;
char *answer;
{
strcpy(answer, si_i2s(cursorsyms, 2 * w->window->theCursor));
}
novalue getdrawop(w, answer)
wbp w;
char *answer;
{
char *s;
if (ISXORREVERSE(w)) s = "reverse";
else s = si_i2s(drawops, w->context->drawop);
if (s) sprintf(answer, "%s", s);
else strcpy(answer, "copy");
}
novalue geticonic(w, answer)
wbp w;
char *answer;
{
switch (w->window->iconic) {
case RootState:
sprintf(answer, "root");
break;
case NormalState:
sprintf(answer, "window");
break;
case IconicState:
sprintf(answer, "icon");
break;
default:
sprintf(answer, "???");
}
}
/*
* Set the window's font by name.
*/
int setfont(w,s)
wbp w;
char **s;
{
wfp tmp;
STDLOCALS(w);
/* could free up previously allocated font here */
Protect(tmp = alc_font(w,s), return Failed);
wc->font = tmp;
if (stdgc != NULL)
XSetFont(stddpy, stdgc, wc->font->fsp->fid);
if (stdpix == (Pixmap) NULL) {
ws->y = wc->font->fsp->max_bounds.ascent;
ws->x = 0;
}
return Succeeded;
}
/*
* callback procedures
*/
hidden int handle_exposures(w, event)
wbp w;
XExposeEvent *event;
{
int returnval;
STDLOCALS(w);
returnval = ISEXPOSED(w);
SETEXPOSED(w);
if (stdwin && !ISZOMBIE(w)) {
if (wc->drawop != GXcopy)
XSetFunction(stddpy, stdgc, GXcopy);
if (wc->clipw >= 0)
unsetclip(w);
XCopyArea(stddpy, stdpix, stdwin, stdgc, event->x,event->y,
event->width,event->height, event->x,event->y);
if (wc->clipw >= 0)
setclip(w);
if (wc->drawop != GXcopy)
XSetFunction(stddpy,stdgc,wc->drawop);
}
return returnval;
}
#ifndef min
#define min(x,y) (((x)<(y))?(x):(y))
#define max(x,y) (((x)>(y))?(x):(y))
#endif
/*
* resizePixmap(w,width,height) -- ensure w's backing pixmap is at least
* width x height pixels.
*
* Resizes the backing pixmap, if needed. Called when X resize events
* arrive, as well as when programs make explicit resize requests.
*
* Returns 0 on failure.
*/
int resizePixmap(w,width,height)
wbp w;
int width;
int height;
{
Pixmap p;
STDLOCALS(w);
if (ws->pix == (Pixmap) NULL) return 1;
if ((width > ws->pixwidth) || (height > ws->pixheight)) {
int x = ws->pixwidth, y = ws->pixheight;
ws->pixheight = max(ws->pixheight, height);
ws->pixwidth = max(ws->pixwidth, width);
p = XCreatePixmap(stddpy, DefaultRootWindow(stddpy), ws->pixwidth,
ws->pixheight, DefaultDepth(stddpy,wd->screen));
if (p == (Pixmap) NULL)
return 0;
/*
* This staggering amount of redudancy manages to make sure the new
* pixmap gets initialized including areas not in the old pixmap.
* The window is redrawn.
*/
XSetForeground(stddpy, stdgc, wc->bg->c);
if (wc->drawop != GXcopy)
XSetFunction(stddpy, stdgc, GXcopy);
if (wc->fillstyle != FillSolid)
XSetFillStyle(stddpy, stdgc, FillSolid);
if (wc->clipw >= 0)
unsetclip(w);
if (width > x) {
XFillRectangle(stddpy, p, stdgc, x, 0, width-x, ws->pixheight);
if (stdwin != (Window) NULL)
XFillRectangle(stddpy,stdwin,stdgc, x, 0, width-x, ws->pixheight);
}
if (height > y) {
XFillRectangle(stddpy, p, stdgc, 0, y, x, height - y);
if (stdwin != (Window) NULL)
XFillRectangle(stddpy, stdwin, stdgc, 0, y, x, height - y);
}
XSetForeground(stddpy, stdgc, wc->fg->c ^ (ISXORREVERSE(w)?wc->bg->c:0));
XCopyArea(stddpy, stdpix, p, stdgc, 0, 0, x, y, 0, 0);
if (wc->drawop != GXcopy)
XSetFunction(stddpy,stdgc,wc->drawop);
if (wc->fillstyle != FillSolid)
XSetFillStyle(stddpy, stdgc, wc->fillstyle);
if (wc->clipw >= 0)
setclip(w);
XFreePixmap(stddpy, stdpix); /* free old pixmap */
ws->pix = p;
}
return 1;
}
/*
* Resize operations are made as painless as possible, but the
* user program is informed anyhow. The integer coordinates are
* the new size of the window, in pixels.
*/
hidden int handle_config(w, event)
wbp w;
XConfigureEvent *event;
{
struct descrip d;
STDLOCALS(w);
/*
* Update X-Icon's information about the window's configuration
*/
ws->x = min(ws->x, event->width - FWIDTH(w));
ws->y = min(ws->y, event->height);
ws->posx = event->x;
ws->posy = event->y;
/*
* If this was not a resize, drop it
*/
if ((event->width == ws->width) && (event->height == ws->height))
return 1;
ws->width = event->width;
ws->height = event->height;
if (! resizePixmap(w, event->width, event->height)) return 0;
/*
* The initial configure event generates no Icon-level "events"
*/
if (!ISEXPOSED(w))
return 1;
MakeInt(RESIZED, &d);
qevent(w->window, &d, ws->width, ws->height, ~(uword)0, 0);
return 1;
}
/*
* Queue up characters for keypress events.
*/
hidden novalue handle_keypress(w,event)
wbp w;
XKeyEvent *event;
{
int i,j;
char s[10];
struct descrip d;
KeySym k;
w->window->pointerx = event->x;
w->window->pointery = event->y;
switch (i=translate_key_event(event, s, &k)) {
case -1:
return;
case 0:
MakeInt(k, &d);
qevent(w->window, &d, event->x, event->y,
(uword)event->time, event->state);
break;
default:
StrLen(d) = 1;
for (j = 0; j < i; j++) {
StrLoc(d) = (char *)&allchars[FromAscii(s[j]) & 0xFF];
qevent(w->window, &d, event->x, event->y,
(uword)event->time, event->state);
}
}
}
#define swap(a,b) { tmp = a; a = b; b = tmp; }
/*
* Handle button presses and drag events. In the case of drags, we should
* really be looking at an XMotionEvent instead of an XButtonEvent, but
* the structures are identical up to the button field (which we do not
* examine for drag events). Mouse coordinates are queued up after the event.
*/
hidden novalue handle_mouse(w,event)
wbp w;
XButtonEvent *event;
{
static unsigned int buttonorder[3] =
{ Button1Mask, Button2Mask, Button3Mask };
unsigned int tmp;
int eventcode = 0;
struct descrip d;
if (event->type == MotionNotify) {
if (event->state | buttonorder[0]) {
if (buttonorder[0] == Button1Mask)
eventcode = MOUSELEFTDRAG;
else if (buttonorder[0] == Button2Mask)
eventcode = MOUSEMIDDRAG;
else
eventcode = MOUSERIGHTDRAG;
}
else if (event->state | buttonorder[1]) {
if (buttonorder[1] == Button1Mask)
eventcode = MOUSELEFTDRAG;
else if (buttonorder[1] == Button2Mask)
eventcode = MOUSEMIDDRAG;
else
eventcode = MOUSERIGHTDRAG;
}
else if (event->state | buttonorder[2]) {
if (buttonorder[2] == Button1Mask)
eventcode = MOUSELEFTDRAG;
else if (buttonorder[2] == Button2Mask)
eventcode = MOUSEMIDDRAG;
else
eventcode = MOUSERIGHTDRAG;
}
}
else switch (event->button) {
case Button1: {
eventcode = MOUSELEFT;
if (buttonorder[2] == Button1Mask)
swap(buttonorder[1],buttonorder[2]);
if (buttonorder[1] == Button1Mask)
swap(buttonorder[0],buttonorder[1]);
break;
}
case Button2: {
eventcode = MOUSEMID;
if (buttonorder[2] == Button2Mask)
swap(buttonorder[1],buttonorder[2]);
if (buttonorder[1] == Button2Mask)
swap(buttonorder[0],buttonorder[1]);
break;
}
case Button3: {
eventcode = MOUSERIGHT;
if (buttonorder[2] == Button3Mask)
swap(buttonorder[1],buttonorder[2]);
if (buttonorder[1] == Button3Mask)
swap(buttonorder[0],buttonorder[1]);
break;
}
}
if (event->type == ButtonRelease) {
eventcode -= (MOUSELEFT - MOUSELEFTUP);
swap(buttonorder[0],buttonorder[1]);
swap(buttonorder[1],buttonorder[2]);
}
w->window->pointerx = event->x;
w->window->pointery = event->y;
MakeInt(eventcode,&d);
qevent(w->window, &d, event->x, event->y, (uword)event->time, event->state);
}
/*
* fill a series of rectangles
*/
novalue fillrectangles(w, recs, nrecs)
wbp w;
XRectangle *recs;
int nrecs;
{
STDLOCALS(w);
/*
* Free colors if drawop=copy, fillstyle~=masked, no clipping,
* and a single rectangle that fills the whole window.
*/
if (!RECX(*recs) && !RECY(*recs) && RECWIDTH(*recs) >= ws->width &&
RECHEIGHT(*recs) >= ws->height && nrecs == 1 &&
wc->drawop == GXcopy && wc->fillstyle != FillStippled && wc->clipw < 0) {
RECWIDTH(*recs) = ws->pixwidth; /* fill hidden part */
RECHEIGHT(*recs) = ws->pixheight;
free_xcolors(w, 0); /* free old colors */
}
RENDER2(XFillRectangles, recs, nrecs);
}
/*
* erase an area
*/
novalue eraseArea(w,x,y,width,height)
wbp w;
int x, y, width, height;
{
STDLOCALS(w);
/*
* if width >= window width or height >= window height, clear any
* offscreen portion as well in order to allow the freeing of colors.
*/
if (width >= ws->width) width = ws->pixwidth;
if (height >= ws->height) height = ws->pixheight;
/*
* fill the rectangle with the background color
*/
XSetForeground(stddpy, stdgc, wc->bg->c);
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, GXcopy);
if (wc->fillstyle != FillSolid) XSetFillStyle(stddpy, stdgc, FillSolid);
RENDER4(XFillRectangle, x, y, width, height);
XSetForeground(stddpy, stdgc, wc->fg->c ^ (ISXORREVERSE(w)?wc->bg->c:0));
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, wc->drawop);
if (wc->fillstyle != FillSolid) XSetFillStyle(stddpy, stdgc, wc->fillstyle);
/*
* if the entire window is cleared, free up colors
*/
if (!x && !y && width >= ws->pixwidth && height >= ws->pixheight &&
wc->clipw < 0)
free_xcolors(w, 0);
}
/*
* copy an area
*/
int copyArea(w,w2,x,y,width,height,x2,y2)
wbp w, w2;
int x, y, width, height, x2, y2;
{
int lpad, rpad, tpad, bpad;
Pixmap src;
wsp ws1 = w->window, ws2 = w2->window;
wclrp cp, cp2 = NULL;
STDLOCALS(w2);
if (w->window->display->display != w2->window->display->display) {
wdp wd1 = ws1->display;
unsigned long c;
int i, j, rv;
Display *d1 = wd1->display;
XColor clr;
XImage *xim;
/*
* Copying is between windows on two different displays.
*/
if (x<0 || y<0 || x+width > ws1->pixwidth || y+height > ws1->pixheight)
return Failed; /*#%#%# BOGUS, NEEDS FIXING */
xim = XGetImage(d1, ws1->pix, x, y, width, height,
(1<<DefaultDepth(d1,wd1->screen))-1,XYPixmap);
XSetFunction(stddpy, stdgc, GXcopy);
for (i=0; i < width; i++) {
for (j=0; j < height; j++) {
clr.pixel = XGetPixel(xim, i, j);
if (cp2 != NULL && c == clr.pixel) {
XSetForeground(stddpy, stdgc, cp2->c);
RENDER2(XDrawPoint, i + x2, j + y2);
continue;
}
c = clr.pixel;
cp2 = NULL;
for ( cp = wd1->colors; cp < wd->colors + wd->numColors; cp++) {
if (cp->c == c) {
if (cp->name[0]=='\0') {
XQueryColor(d1, wd1->cmap, &clr);
cp->r = clr.red;
cp->g = clr.green;
cp->b = clr.blue;
sprintf(cp->name,"%d,%d,%d",cp->r,cp->g,cp->b);
}
cp2 = alc_rgb(w2, cp->name, cp->r, cp->g, cp->b, 0);
if (cp2 == NULL) return Failed;
break;
}
}
if (cp2 == NULL) {
XQueryColor(d1, wd1->cmap, &clr);
cp2 = alc_rgb(w2, "unknown", clr.red, clr.green, clr.blue, 0);
}
if (cp2 == NULL) return Failed;
XSetForeground(stddpy, stdgc, cp2->c);
RENDER2(XDrawPoint, i + x2, j + y2);
}
}
XSetForeground(stddpy, stdgc,
wc->fg->c ^ (ISXORREVERSE(w2) ? wc->bg->c : 0));
XSetFunction(stddpy, stdgc, wc->drawop);
XSync(stddpy,False);
XDestroyImage(xim);
}
else {
/*
* Copying is between windows on one display, perhaps the same window.
*/
src = ws1->pix;
if (src != stdpix) {
/* copying between different windows; handle color bookkeeping */
if (!x2 && !y2 &&
((width >= ws2->pixwidth) || !width) &&
((height >= ws2->pixheight) || !height) && w2->context->clipw < 0)
free_xcolors(w2, 0);
copy_colors(w, w2);
}
XSetForeground(stddpy, stdgc, wc->bg->c);
XSetFunction(stddpy, stdgc, GXcopy);
if (x+width<0 || y+height<0 || x>=ws1->pixwidth || y>=ws1->pixheight) {
/* source is entirely offscreen */
RENDER4(XFillRectangle, x2, y2, width, height);
}
else {
/*
* Check for source partially offscreen, but copy first and
* fill later in case the source and destination overlap.
*/
lpad = rpad = tpad = bpad = 0;
if (x < 0) { /* source extends past left edge */
lpad = -x;
width -= lpad;
x2 += lpad;
x = 0;
}
if (x + width > ws1->pixwidth) { /* source extends past right edge */
rpad = x + width - ws1->pixwidth;
width -= rpad;
}
if (y < 0) { /* source extends above top edge */
tpad = -y;
height -= tpad;
y2 += tpad;
y = 0;
}
if (y + height > ws1->pixheight) { /* source extends below bottom */
bpad = y + height - ws1->pixheight;
height -= bpad;
}
/*
* Copy the area.
*/
if (stdwin)
XCopyArea(stddpy, src, stdwin, stdgc, x, y, width, height, x2, y2);
XCopyArea(stddpy, src, stdpix, stdgc, x, y, width, height, x2, y2);
/*
* Fill any edges not provided by source.
*/
if (lpad > 0)
RENDER4(XFillRectangle, x2-lpad, y2-tpad, lpad, tpad+height+bpad);
if (rpad > 0)
RENDER4(XFillRectangle, x2+width, y2-tpad, rpad, tpad+height+bpad);
if (tpad > 0)
RENDER4(XFillRectangle, x2, y2-tpad, width, tpad);
if (bpad > 0)
RENDER4(XFillRectangle, x2, y2+height, width, bpad);
}
XSetForeground(stddpy,stdgc,wc->fg->c^(ISXORREVERSE(w2) ? wc->bg->c :0));
XSetFunction(stddpy, stdgc, wc->drawop);
}
return Succeeded;
}
wbp sprite;
int tics;
int lastx,lasty;
int animwidth, animheight;
void animHelper(w,p,n)
wbp w;
XPoint p[];
int n;
{
int i=0;
STDLOCALS(w);
for ( ; i < n; i++) {
int j;
/*
* redraw that portion of the previous image that isn't overlapped
* by the new image being drawn
*/
if (lastx >= 0) {
int dx = p[i].x - lastx, dy = p[i].y - lasty;
if (dx > 0) XCopyArea(stddpy,stdpix,stdwin,stdgc, lastx, lasty,
dx, animheight, lastx, lasty);
else if (dx < 0)
XCopyArea(stddpy,stdpix,stdwin,stdgc, lastx+animwidth+dx, lasty,
-dx, animheight, lastx+animwidth+dx, lasty);
if (dy > 0) XCopyArea(stddpy, stdpix, stdwin, stdgc, lastx, lasty,
animwidth, dy, lastx, lasty);
else if (dy < 0)
XCopyArea(stddpy,stdpix,stdwin,stdgc, lastx, lasty+animheight+dy,
animwidth, -dy, lastx, lasty+animheight+dy);
}
XCopyArea(stddpy, sprite->window->pix, stdwin, stdgc,
0, 0, animwidth, animheight, p[i].x, p[i].y);
XFlush(stddpy);
for (j = 0; j < tics; j++);
/*
* erase the whole box approach:
* XCopyArea(stddpy, stdpix, stdwin, stdgc,
* 0, 0, animwidth, animheight, p[i].x, p[i].y);
*/
lastx = p[i].x;
lasty = p[i].y;
}
}
animate(w, pixs, npix, p, n, delay)
wbp w;
dptr pixs;
int npix;
XPoint *p;
int n, delay;
{
wbp w2 = (wbp)(BlkLoc(*pixs)->file.fd);
STDLOCALS(w);
sprite = w2;
animheight = sprite->window->height;
animwidth = sprite->window->width;
tics = delay;
lastx = lasty = -1;
genCurve(w, p, n, animHelper);
XCopyArea(stddpy, stdpix, stdwin, stdgc, lastx, lasty,
animwidth, animheight, lastx, lasty);
}
int getdefault(w, prog, opt, answer)
wbp w;
char *prog, *opt, *answer;
{
char *p;
STDLOCALS(w);
if ((p = XGetDefault(stddpy,prog,opt)) == NULL)
return Failed;
strcpy(answer, p);
return Succeeded;
}
/*
* Allocate a mutable color
*/
int mutable_color(w, argv, ac, retval)
wbp w;
dptr argv;
int ac;
int *retval;
{
XColor colorcell;
LinearColor clr;
unsigned long plane_masks[1], pixels[1];
char *colorname;
tended char *str;
int i;
{
STDLOCALS(w);
/*
* X11 Bug Warning: some old versions of the X server, but not X11R5,
* will crash sometime after a failed call to XNewColor. This happens
* only if a virtual colormap has been allocated and completely filled
* and then XNewColor is called to allocate a new, unshared entry. The
* request fails, as it should, but when the program eventually exits
* the X server crashes. This has been seen on OpenWindows 3.0,
* Irix 4.0.1, and HP-UX 7.0.
*/
if (!XAllocColorCells(stddpy,wd->cmap,False,plane_masks,0,pixels,1)) {
/*
* try again with a virtual colormap
*/
if (!go_virtual(w) ||
!XAllocColorCells(stddpy,wd->cmap,False,plane_masks,0,pixels,1))
return Failed; /* cannot allocate an entry */
}
/*
* allocate a slot in wdisplay->colors and wstate->theColors arrays
*/
i = alc_centry(wd);
if (i == 0)
return Failed;
wd->colors[i].type = MUTABLE;
wd->colors[i].c = pixels[0];
/* save color index as "name", followed by a null string for value */
colorname = wd->colors[i].name;
sprintf(colorname, "%ld", -pixels[0] - 1); /* index is name */
colorname = colorname + strlen(colorname) + 1;
*colorname = '\0'; /* value unknown */
if (ws->numColors < WMAXCOLORS) {
if (ws->theColors == NULL) {
ws->theColors = (short *)calloc(WMAXCOLORS, sizeof(short));
if (ws->theColors == NULL)
return Error;
}
ws->theColors[ws->numColors++] = i;
}
if (ac > 0) { /* set the color */
if (ac != 1) return Error;
/*
* old-style check for C integer
*/
else if (argv[0].dword == D_Integer) {/* check for color cell */
if (IntVal(argv[0]) >= 0)
return Failed; /* must be negative */
colorcell.pixel = -IntVal(argv[0]) - 1;
XQueryColor(stddpy, wd->cmap, &colorcell);
clr = lcolor(w, colorcell);
sprintf(colorname, "%d,%d,%d", clr.red, clr.green, clr.blue);
}
else {
if (!cnv:C_string(argv[0],str)) {
ReturnErrVal(103,argv[0], Error);
}
if (parsecolor(w, str, &clr.red, &clr.green, &clr.blue) != Succeeded) {
free_xcolor(w, pixels[0]);
return Failed; /* invalid color specification */
}
strcpy(colorname, str);
colorcell = xcolor(w, clr);
}
colorcell.pixel = pixels[0];
XStoreColor(stddpy, wd->cmap, &colorcell);
}
*retval = (-pixels[0] - 1);
return Succeeded;
}
}
char *get_mutable_name(w, mute_index)
wbp w;
int mute_index;
{
wdp dp;
Display *d;
int i;
char *colorname;
dp = w->window->display;
d = dp->display;
for (i = 2; i < DMAXCOLORS; i++)
if (dp->colors[i].type == MUTABLE && dp->colors[i].c == - mute_index - 1)
break;
if (i == DMAXCOLORS)
return NULL;
colorname = dp->colors[i].name; /* color name field */
colorname = colorname + strlen(colorname) + 1; /* set value follows */
return colorname;
}
int set_mutable(w, i, s)
wbp w;
int i;
char *s;
{
LinearColor clr;
XColor colorcell;
wdp dp = w->window->display;
if (parsecolor(w, s, &clr.red, &clr.green, &clr.blue) != Succeeded)
return Failed; /* invalid color specification */
colorcell = xcolor(w, clr);
colorcell.pixel = -i - 1;
XStoreColor(dp->display, dp->cmap, &colorcell);
return Succeeded;
}
novalue free_mutable(w, mute_index)
wbp w;
int mute_index;
{
wdp dp;
Display *d;
int i;
char *colorname;
dp = w->window->display;
d = dp->display;
for (i = 2; i < DMAXCOLORS; i++)
if (dp->colors[i].type == MUTABLE && dp->colors[i].c == - mute_index - 1)
break;
if (i != DMAXCOLORS)
free_xcolor(w, dp->colors[i].c);
}
novalue freecolor(w, s)
wbp w;
char *s;
{
wdp dp;
Display *d;
int i;
LinearColor clr;
XColor color;
if (parsecolor(w, s, &clr.red, &clr.green, &clr.blue) != Succeeded)
return;
dp = w->window->display;
d = dp->display;
color = xcolor(w, clr);
for (i = 2; i < DMAXCOLORS; i++)
if (dp->colors[i].r == color.red && dp->colors[i].g == color.green
&& dp->colors[i].b == color.blue && dp->colors[i].type != MUTABLE)
break;
if (i != DMAXCOLORS)
free_xcolor(w, dp->colors[i].c);
}
/*
* Draw a bilevel image
*/
int blimage(w, x, y, width, height, ch, s, len)
wbp w;
int x, y, width, height, ch;
unsigned char *s;
word len;
{
unsigned int m, msk1, c, ix, iy;
long fg, bg;
XImage *im;
STDLOCALS(w);
/*
* Get an XImage structure and free the old color set if possible.
*/
im = getximage(w, x, y, width, height, ch == TCH1);
if (im == NULL)
return Error;
/*
* Read the image string and set the pixel values. Note that
* the hex digits in sequence fill the rows *right to left*.
*/
m = width % 4;
if (m == 0)
msk1 = 8;
else
msk1 = 1 << (m - 1); /* mask for first byte of row */
fg = wc->fg->c;
bg = wc->bg->c;
ix = width;
iy = 0;
m = msk1;
while (len--) {
if (isxdigit(c = *s++)) { /* if hexadecimal character */
if (!isdigit(c)) /* fix bottom 4 bits if necessary */
c += 9;
while (m > 0) { /* set (usually) 4 pixel values */
--ix;
if (c & m)
XPutPixel(im, ix, iy, fg);
else if (ch != TCH1) /* if zeroes aren't transparent */
XPutPixel(im, ix, iy, bg);
m >>= 1;
}
if (ix == 0) { /* if end of row */
ix = width;
iy++;
m = msk1;
}
else
m = 8;
}
}
if (ix > 0) /* pad final row if incomplete */
while (ix < width)
XPutPixel(im, ix++, iy, bg);
/*
* Put it on the screen.
*/
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, GXcopy);
RENDER7(XPutImage, im, 0, 0, x, y, width, height);
XDestroyImage(im);
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, wc->drawop);
return Succeeded;
}
/*
* Draw a character-per-pixel image
*/
int strimage(w, x, y, width, height, e, s, len, on_icon)
wbp w;
int x, y, width, height;
struct palentry *e;
unsigned char *s;
word len;
int on_icon;
{
int c, v, ret, trans;
unsigned int r, g, b, ix, iy;
wclrp cp, cplist[256];
char tmp[24];
XImage *im;
STDLOCALS(w);
/*
* Get an XImage structure and free the old color set if possible.
*/
trans = 0;
for (c = 0; c < 256; c++)
trans |= e[c].used && e[c].transpt;
im = getximage(w, x, y, width, height, trans);
if (im == NULL)
return -1;
/*
* Allocate the colors we need. Use black or white if unsuccessful.
*/
ret = 0;
for (c = 0; c < 256; c++)
if (e[c].used && e[c].valid) {
r = e[c].clr.red;
g = e[c].clr.green;
b = e[c].clr.blue;
sprintf(tmp, "%d,%d,%d", r, g, b);
cp = alc_rgb(w, tmp, r, g, b, 0);
if (cp == NULL) {
ret++;
if ((0.299 * r + 0.587 * g + 0.114 * b) > 32767)
cp = alc_rgb(w, "white", 65535, 65535, 65535, 0);
else
cp = alc_rgb(w, "black", 0, 0, 0, 0);
}
cplist[c] = cp;
}
/*
* Read the image string and set the pixel values.
*/
ix = iy = 0;
while (len--) {
c = *s++;
v = e[c].valid;
if (v) /* put char if valid */
XPutPixel(im, ix, iy, cplist[c]->c);
if (v || e[c].transpt) { /* advance if valid or transparent */
if (++ix >= width) {
ix = 0; /* reset for new row */
iy++;
}
}
}
if (ix > 0) /* pad final row if incomplete */
while (ix < width)
XPutPixel(im, ix++, iy, wc->bg->c);
/*
* Put it on the screen.
*/
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, GXcopy);
if (on_icon) {
if (ws->iconwin == (Window) NULL) makeIcon(w, 0, 0);
XPutImage(stddpy, ws->iconwin, stdgc, im, 0, 0, x, y, width, height);
XPutImage(stddpy, ws->iconpix, stdgc, im, 0, 0, x, y, width, height);
}
else {
XPutImage(stddpy, ws->pix, stdgc, im, 0, 0, x, y, width, height);
if (ws->win)
XCopyArea(stddpy, ws->pix, ws->win, stdgc, x, y, width, height, x, y);
}
XDestroyImage(im);
if (wc->drawop != GXcopy) XSetFunction(stddpy, stdgc, wc->drawop);
return ret;
}
/*
* getimstr(w, x, y, width, height, paltbl, data) -- get image as a string.
*
* Stores the specified subimage in data, one pixel per byte, and sets
* entries in paltbl corresponding to the pixel values that were used.
*/
/*
* The getimstr() code assumes that a maximum of 256 colors can be onscreen
* at one time. If DMAXCOLORS maximum is raised, code must be added for the
* depth>8 case to reduce the local copy of the image to no more than the
* 256-color maximum allowed in a GIF file. This reduction operation is
* nontrivial; look up "color quantization" in computer graphics literature.
*/
#passthru #if (DMAXCOLORS > 256)
#passthru Deliberate Syntax error
#passthru #endif /* DMAXCOLORS */
int getimstr(w, x, y, width, height, paltbl, data)
wbp w;
int x, y, width, height;
struct palentry paltbl[DMAXCOLORS];
unsigned char *data;
{
XImage *im;
XColor colorcell;
wclrp cp;
unsigned long px, clist[DMAXCOLORS], *lp;
int i, ncolors;
STDLOCALS(w);
/*
* Get an XImage structure containing window pixel values.
*/
im = getximage(w, x, y, width, height, 1);
if (!im)
return 0;
if (im->depth <= 8) {
/*
* We can use the pixel values directly as color indices.
* Put them in the data string, noting which colors are used.
*/
for (i = 0; i < DMAXCOLORS; i++)
clist[i] = i;
for (y = 0; y < height; y++)
for (x = 0; x < width; x++) {
*data++ = px = XGetPixel(im, x, y) & 0xFF;
paltbl[px].used = 1;
}
}
else {
/*
* Make a sorted list of the pixel values of the colors that are in
* use. Search this list for every pixel and store the resulting
* list index as the color index.
*/
lp = clist;
for (cp = wd->colors; cp < wd->colors + wd->numColors; cp++)
*lp++ = cp->c;
ncolors = lp - clist;
qsort((char *)clist, ncolors, sizeof(*clist), (int (*)())ulcmp);
for (y = 0; y < height; y++)
for (x = 0; x < width; x++) {
px = XGetPixel(im, x, y);
lp = (unsigned long *)qsearch((char *)&px, (char *)clist,
ncolors, sizeof(*clist), (int (*)())ulcmp);
if (lp)
i = lp - clist;
else
i = 0; /* use black if not found */
*data++ = i;
paltbl[i].used = 1;
}
}
/*
* Query the real color values from X; Icon's data structures
* may show several entries for any particular pixel value.
*/
for (i = 0; i < DMAXCOLORS; i++)
if (paltbl[i].used) {
colorcell.pixel = clist[i];
colorcell.flags = DoRed | DoGreen | DoBlue;
XQueryColor(stddpy, wd->cmap, &colorcell);
paltbl[i].clr = lcolor(w, colorcell);
paltbl[i].valid = 1;
}
XDestroyImage(im);
return 1;
}
/*
* Create an XImage structure corresponding to subimage (x, y, w, h).
* If init is nonzero, initialize it with current contents.
* If init is zero and (x,y,w,h) fills the window, free existing color set.
*/
hidden XImage *getximage(w, x, y, width, height, init)
wbp w;
int x, y, width, height, init;
{
int tx, ty;
XImage *im;
STDLOCALS(w);
im = XCreateImage(stddpy, DefaultVisual(stddpy, wd->screen),
DefaultDepth(stddpy, wd->screen), ZPixmap, 0, NULL, width, height, 32, 0);
if (im == NULL)
return NULL;
im->data = malloc((msize)(im->bytes_per_line * height));
if (im->data == NULL) {
XDestroyImage(im);
return NULL;
}
if (!init) {
if (x <= 0 && y <= 0 && x + width >= ws->pixwidth &&
y + height >= ws->pixheight && wc->clipw < 0)
free_xcolors(w, 0);
return im;
}
tx = ty = 0;
if (x < 0) { tx -= x; width += x; x = 0; }
if (y < 0) { ty -= y; height += y; y = 0; }
if (x + width > ws->width) { width = ws->width - x; }
if (y + height > ws->height) { height = ws->height - y; }
if (width > 0 && height > 0)
XGetSubImage(stddpy, stdpix, x, y, width, height, AllPlanes, ZPixmap,
im, tx, ty);
return im;
}
int readimage(w, filename, x, y, status)
wbp w;
char *filename;
int x, y, *status;
{
Pixmap p;
unsigned int width, height;
STDLOCALS(w);
if (!x && !y)
p = loadimage(w, filename, &height, &width, 1, status);
else
p = loadimage(w, filename, &height, &width, 0, status);
if (p == (Pixmap) NULL) return Failed;
if (wc->drawop != GXcopy)
XSetFunction(stddpy, stdgc, GXcopy);
if (stdwin)
XCopyArea(stddpy, p, stdwin, stdgc, 0, 0, width, height, x, y);
XCopyArea(stddpy, p, stdpix, stdgc, 0, 0, width, height, x, y);
if (wc->drawop != GXcopy)
XSetFunction(stddpy,stdgc,wc->drawop);
/*
* Make sure previous ops on p are complete, then free it.
*/
XSync(stddpy, False);
XFreePixmap(stddpy, p);
return Succeeded;
}
static XImage *im;
static int im_x, im_y, im_width, im_height;
/*
* Initialize client for producing pixels from a window
*/
int getpixel_init(w, x, y, width, height)
wbp w;
int x, y, width, height;
{
STDLOCALS(w);
im_x = x;
im_y = y;
im_width = width;
im_height = height;
if (width <= 0 || height <= 0)
return Succeeded;
im = XGetImage(stddpy, stdpix, x, y, width, height,
(1 << DefaultDepth(stddpy, wd->screen))-1, XYPixmap);
if (im == NULL) return Failed;
return Succeeded;
}
/*
* Return pixel (x,y) from a window in long value (rv)
*/
int getpixel(w, x, y, rv, s)
wbp w;
int x, y;
long *rv;
char *s;
{
XColor colorcell;
LinearColor clr;
wclrp cp;
unsigned long c;
STDLOCALS(w);
if (x < im_x || x >= im_x + im_width || y < im_y || y >= im_y + im_height)
c = colorcell.pixel = wc->bg->c;
else
c = colorcell.pixel = XGetPixel(im, x - im_x, y - im_y);
*rv = 0xff000000;
for (cp = wd->colors ; cp < wd->colors + wd->numColors; cp++) {
if (cp->c == c) {
if (cp->type == MUTABLE)
*rv = -c - 1;
else {
*rv = 1;
colorcell.red = cp->r;
colorcell.green = cp->g;
colorcell.blue = cp->b;
clr = lcolor(w, colorcell);
sprintf(s, "%d,%d,%d", clr.red, clr.green, clr.blue);
}
break;
}
}
if (*rv == 0xff000000) {
XQueryColor(stddpy, wd->cmap, &colorcell);
*rv = 1;
clr = lcolor(w, colorcell);
sprintf(s, "%d,%d,%d", clr.red, clr.green, clr.blue);
}
return Succeeded;
}
int query_pointer(w, pp)
wbp w;
XPoint *pp;
{
Display *theDisplay;
Window theWindow;
Window garbage1, garbage2;
int root_x, root_y, win_x, win_y;
unsigned int key_buttons;
theDisplay = w->window->display->display;
theWindow = w->window->win;
if (theWindow == (Window) NULL) return Failed;
XQueryPointer(theDisplay, theWindow, &garbage1, &garbage2,
&root_x, &root_y, &win_x, &win_y, &key_buttons);
pp->x = w->window->pointerx = win_x;
pp->y = w->window->pointery = win_y;
}
int query_rootpointer(pp)
XPoint *pp;
{
Display *theDisplay;
Window theWindow;
Window garbage1, garbage2;
int root_x, root_y, win_x, win_y;
unsigned int key_buttons;
int i;
wdp wd;
if (wdsplys == NULL) {
/*
* Initialize the window system
*/
Protect(wd = alc_display(NULL), return Failed);
theDisplay = wd->display;
theWindow = DefaultRootWindow(wd->display);
}
else {
wd = wdsplys;
theDisplay = wd->display;
theWindow = DefaultRootWindow(wd->display);
}
XQueryPointer(theDisplay, theWindow, &garbage1, &garbage2,
&root_x, &root_y, &win_x, &win_y, &key_buttons);
pp->x = root_x;
pp->y = root_y;
return Succeeded;
}
int patbits[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFE,0xFF,0xEF,0xFF,0xFE,0xFF,0xEF,0xFF,
0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,
0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
0x01,0x00,0x10,0x00,0x01,0x00,0x10,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,
0x82,0x44,0x28,0x10,0x28,0x44,0x82,0x01,
0x0F,0x0F,0x0F,0x0F,0xF0,0xF0,0xF0,0xF0,
0x1B,0x18,0x81,0xB1,0x36,0x06,0x60,0x63,
0x02,0x02,0x05,0xF8,0x20,0x20,0x50,0x8F,
0x03,0x84,0x48,0x30,0x03,0x84,0x48,0x30,
};
/*
* pattern symbols
*/
stringint siPatternSyms[] = {
{0, 16},
{ "black", 0},
{ "checkers", 12},
{ "darkgray", 2},
{ "diagonal", 8},
{ "grains", 13},
{ "gray", 3},
{ "grid", 10},
{ "horizontal",9},
{ "lightgray", 4},
{ "scales", 14},
{ "trellis", 11},
{ "vertical", 7},
{ "verydark", 1},
{ "verylight", 5},
{ "waves", 15},
{ "white", 6},
};
/*
* SetPattern
*/
int SetPattern(w, name, len)
wbp w;
char *name;
int len;
{
int width, nbits;
int i, j;
int symbol;
C_integer v, bits[MAXXOBJS];
Pixmap p;
char data[MAXXOBJS];
char *buf = data;
STDLOCALS(w);
if (wc->patternname != NULL)
free(wc->patternname);
wc->patternname = malloc(len+1);
if (wc->patternname == NULL) ReturnErrNum(305, Error);
mystrncpy(wc->patternname, name, len);
/*
* If the pattern starts with a number it is a width , bits encoding
*/
if ((len > 0) && isdigit(name[0])) {
nbits = MAXXOBJS;
switch (parsepattern(name, len, &width, &nbits, bits)) {
case Failed:
return Failed;
case Error:
ReturnErrNum(145, Error);
}
if (!stdgc) return Succeeded;
return SetPatternBits(w, width, bits, nbits);
}
/*
* Otherwise, it is a named pattern. Find the symbol id.
*/
if ((symbol = si_s2i(siPatternSyms, wc->patternname)) >= 0) {
if (!stdgc) return Succeeded;
for(i = 0; i < 8; i++) {
v = patbits[symbol * 8 + i];
*buf++ = v;
}
p = XCreateBitmapFromData(stddpy, stdpix, data, 8, 8);
XSetStipple(stddpy, stdgc, p);
XSync(stddpy, False);
XFreePixmap(stddpy, p);
return Succeeded;
}
return Failed;
}
int SetPatternBits(w, width, bits, nbits)
wbp w;
int width;
C_integer *bits;
int nbits;
{
C_integer v;
int i, j;
Pixmap p;
char data[MAXXOBJS];
char *buf = data;
STDLOCALS(w);
for(i = 0; i < nbits; i++) {
v = bits[i];
for(j=0; j<width; j+=8) {
*buf++ = v;
v >>= 8;
}
}
p = XCreateBitmapFromData(stddpy, stdpix, data, width, nbits);
XSetStipple(stddpy, stdgc, p);
XSync(stddpy, False);
XFreePixmap(stddpy, p);
return Succeeded;
}
/*
* remap a window ... this time with an iconwin
*/
int remap(w,x,y)
wbp w;
int x,y;
{
XSizeHints size_hints;
XWMHints *wmhints;
Window root;
unsigned int width, height, bw, depth;
STDLOCALS(w);
XGetSizeHints(stddpy, stdwin, &size_hints, XA_WM_NORMAL_HINTS);
wmhints = XGetWMHints(stddpy, stdwin);
if (ws->iconwin)
XDestroyWindow(stddpy, ws->iconwin);
if (stdwin)
XDestroyWindow(stddpy, stdwin);
ws->win = XCreateSimpleWindow(stddpy, DefaultRootWindow(stddpy),
ws->posx, ws->posy, ws->width,
ws->height, 4, wc->fg->c, wc->bg->c);
XSetStandardProperties(stddpy, ws->win, ws->windowlabel,
ws->iconlabel, 0, 0, 0, &size_hints);
XSelectInput(stddpy, ws->win, ExposureMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
StructureNotifyMask);
ws->iconwin = XCreateSimpleWindow(stddpy, DefaultRootWindow(stddpy),
ws->iconx, ws->icony, ws->iconw,
ws->iconh, 2, wc->fg->c, wc->bg->c);
XSelectInput(stddpy, ws->iconwin,
ExposureMask | KeyPressMask | ButtonPressMask);
wmhints->flags |= IconPositionHint;
wmhints->icon_x = x;
wmhints->icon_y = y;
wmhints->initial_state = ws->iconic;
wmhints->icon_window = ws->iconwin;
wmhints->flags |= IconWindowHint;
XSetWMHints(stddpy, ws->win, wmhints);
CLREXPOSED(w);
XMapWindow(stddpy, ws->win);
if (ws->iconic == NormalState) {
while (!ISEXPOSED(w))
if (pollevent() == -1) return -1;
}
ws->iconx = x;
ws->icony = y;
XSync(stddpy, False);
XFree((char *)wmhints);
return 1;
}
int seticonimage(w, dp)
wbp w;
dptr dp;
{
int status;
Pixmap pix;
tended char *tmp;
{
STDLOCALS(w);
/*
* get the preloaded (in another window value) pixmap image
*/
if (is:file(*dp) && (BlkLoc(*dp)->file.status & Fs_Window)) {
wbp x = (wbp)BlkLoc(*dp)->file.fd;
if ((ws->iconimage = salloc(x->window->windowlabel)) == NULL)
ReturnErrNum(305, Error);
pix = XCreatePixmap(stddpy, DefaultRootWindow(stddpy),
x->window->width, x->window->height,
DefaultDepth(stddpy,wd->screen));
XCopyArea(stddpy, x->window->pix, pix, wd->icongc, 0, 0,
x->window->width, x->window->height, 0, 0);
if (ws->iconpix) {
XSync(stddpy, False);
XFreePixmap(stddpy, ws->iconpix);
}
ws->iconpix = pix;
ws->iconw = x->window->width;
ws->iconh = x->window->height;
if (!ws->iconx && !ws->icony) {
ws->iconx = ws->x;
ws->icony = ws->y;
}
if (remap(w,ws->iconx,ws->icony) == -1)
ReturnErrNum(144, Error);
}
/* get the pixmap file named by x */
else if (is:string(*dp)) {
unsigned int height, width;
if (!cnv:C_string(*dp,tmp))
ReturnErrVal(103, *dp, Error);
if ((ws->iconimage != NULL) && strcmp(ws->iconimage, ""))
free(ws->iconimage);
if ((ws->iconimage = salloc(tmp)) == NULL)
ReturnErrNum(305, Error);
if (ws->iconwin == (Window) NULL) makeIcon(w,0,0);
else {
pix = loadimage(w, ws->iconimage, &height, &width, 0, &status);
if (pix == (Pixmap) NULL)
return Failed;
XCopyArea(stddpy, pix, ws->iconwin, wd->icongc,
0, 0, width, height, 0, 0);
if (ws->iconpix) {
XSync(stddpy, False);
XFreePixmap(stddpy, ws->iconpix);
}
ws->iconpix = pix;
ws->iconw = width;
ws->iconh = height;
if (remap(w,ws->iconx,ws->icony) == -1)
ReturnErrNum(144, Error);
}
}
else
return Failed;
return Succeeded;
}
}
/*
* dumpimage -- write an image to a disk file in an X format.
*
* Accepts only .xpm and .xbm file names, returning NoCvt for anything else.
*/
int dumpimage(w,filename,x,y,width,height)
wbp w;
char *filename;
unsigned int x, y, height, width;
{
int status;
STDLOCALS(w);
/*
* Check for bilevel XBM (X BitMap) format.
*/
if (!strcmp(".xbm", filename + strlen(filename) - 4) ||
!strcmp(".XBM", filename + strlen(filename) - 4)) {
/*
* Write a bitmap from a "color" window (presumed to have only BW in it).
* BlackPixel ^ WhitePixel will have a 1 in the first bit in which
* they are different, so this bit is the plane we want to copy.
*/
if (DefaultDepth(stddpy,wd->screen) != 1) {
unsigned long bw =
BlackPixel(stddpy,wd->screen) ^ WhitePixel(stddpy,wd->screen);
Pixmap p1 = XCreatePixmap(stddpy, DefaultRootWindow(stddpy),
width, height, 1);
XGCValues xgc;
GC thinGC;
int i;
/*
* pick out the bitplane on which Black and White differ
*/
for(i=0;!((1<<i) & bw);i++);
bw &= (1<<i);
/*
* Construct a 1-bit-deep GC for use in copying the plane.
*/
xgc.foreground = BlackPixel(stddpy,wd->screen);
xgc.background = WhitePixel(stddpy,wd->screen);
thinGC = XCreateGC(stddpy,p1,GCForeground|GCBackground,&xgc);
if (i>DefaultDepth(stddpy,wd->screen)) return Failed;
XCopyPlane(stddpy,stdpix,p1,thinGC,x,y,width,height,0,0,bw);
status= XWriteBitmapFile(stddpy, filename, p1, width, height, -1, -1);
XSync(stddpy, False);
XFreePixmap(stddpy, p1);
XFreeGC(stddpy,thinGC);
if (status != BitmapSuccess) return Failed;
}
else {
if(x || y) {
Pixmap p1 = XCreatePixmap(stddpy, DefaultRootWindow(stddpy), width,
height, DefaultDepth(stddpy,wd->screen));
XCopyArea(stddpy, stdpix, p1, stdgc, x, y, width, height, 0, 0);
XSync(stddpy, False);
status = XWriteBitmapFile(stddpy, filename, p1, width, height, -1, -1);
XSync(stddpy, False);
XFreePixmap(stddpy, p1);
if (status != BitmapSuccess) return Failed;
}
else if (XWriteBitmapFile(stddpy, filename, stdpix,
width, height, -1, -1) != BitmapSuccess)
return Failed;
}
return Succeeded;
}
/*
* Check for XPM (color X PixMap) format.
*/
else if (!strcmp(".xpm", filename + strlen(filename) - 4) ||
!strcmp(".XPM", filename + strlen(filename) - 4) ||
!strcmp(".xpm.Z", filename + strlen(filename) - 6)) {
#ifdef HaveXpmFormat
/*
* Could optimize by calling XpmWriteFileFromPixmap directly on the
* stdpix...
*/
Pixmap p1 = XCreatePixmap(stddpy, DefaultRootWindow(stddpy), width,
height, DefaultDepth(stddpy,wd->screen));
XCopyArea(stddpy, stdpix, p1, stdgc, x, y, width, height, 0, 0);
XSync(stddpy, False);
status = XpmWriteFileFromPixmap(stddpy, filename, p1,
(Pixmap) NULL, NULL);
XSync(stddpy, False);
XFreePixmap(stddpy, p1);
if (status == XpmSuccess)
return Succeeded;
#endif /* HaveXpmFormat */
return Failed;
}
else
return NoCvt; /* not an X format -- write GIF instead */
}
/*
* Load an image, in any format we can figure out.
*/
Pixmap loadimage(w, filename, height, width, atorigin, status)
wbp w;
char *filename;
unsigned int *height, *width;
int atorigin;
int *status;
{
Pixmap p1, p2 = (Pixmap) NULL;
int xhot, yhot, i, j;
XImage *theImage;
XGCValues gcv;
static unsigned long *thePixels;
static unsigned int nPixels;
unsigned long gcmask = GCFont | GCForeground | GCBackground;
int isxbm;
STDLOCALS(w);
if (!strcmp(".xbm", filename + strlen(filename) - 4))
isxbm = 1;
else if (!strcmp(".xpm", filename + strlen(filename) - 4) ||
!strcmp(".xpm.Z", filename + strlen(filename) - 6))
isxbm = 0;
else {
/*
* Not sure what kind of file this is, make a guess
* For example, the format might be on the first line of the file,
* so open it up and read some.
*/
FILE *ftemp = fopen(filename,"r");
char s[6];
int i;
if (!ftemp) {
return (Pixmap) NULL;
}
if ((long)fread(s,1,6,ftemp) < (long)6) {
fclose(ftemp);
return (Pixmap) NULL;
}
fclose(ftemp);
/* check s for XPM string */
isxbm = 1; /* default to xbm */
for (i = 0; i <= 3; i++)
if (!strncmp(&s[i], "XPM", 3))
isxbm = 0;
}
if (isxbm) { /* isxbm = 1 => .xbm file */
if (XReadBitmapFile(stddpy, DefaultRootWindow(stddpy), filename,
width, height, &p1, &xhot, &yhot) != BitmapSuccess)
return (Pixmap) NULL;
else *status = 0;
p2 = XCreatePixmap(stddpy, DefaultRootWindow(stddpy), *width, *height,
DefaultDepth(stddpy,DefaultScreen(stddpy)));
}
else { /* isxbm == 0 => .xpm file */
#ifndef HaveXpmFormat
return NULL;
#else /* HaveXpmFormat */
XpmAttributes a;
XColor color;
LinearColor clr;
Pixmap dummy;
a.npixels = 0;
a.colormap = wd->cmap;
a.valuemask = XpmReturnPixels | XpmColormap;
*status = XpmReadFileToPixmap(stddpy, DefaultRootWindow(stddpy),
filename, &p2, &dummy, &a);
if (*status == XpmColorFailed && go_virtual(w)) {
/* try again with a virtual colormap */
a.npixels = 0;
a.colormap = wd->cmap;
a.valuemask = XpmReturnPixels | XpmColormap;
*status = XpmReadFileToPixmap(stddpy, DefaultRootWindow(stddpy),
filename, &p2, &dummy, &a);
}
if (*status != XpmSuccess) {
if (*status == XpmColorFailed)
*status = 1;
else
return (Pixmap) NULL;
}
else *status = 0;
*height = a.height;
*width = a.width;
/*
* if the loaded image is to cover an entire window, free up colors
* currently in use by the window
*/
if (atorigin && *width >= ws->pixwidth && *height >= ws->pixheight
&& wc->clipw < 0)
free_xcolors(w, 0);
/*
* OK, now register all the allocated colors with the display
* and window in which we are residing.
*/
for (i = 0; i < a.npixels; i++) {
for (j = 2; j < DMAXCOLORS; j++)
if (wd->colors[j].refcount == 0) break;
if (j == DMAXCOLORS) {
return (Pixmap) NULL;
}
if (j == wd->numColors) wd->numColors++;
else if (j > wd->numColors) {
wd->numColors = j+1;
}
wd->colors[j].refcount = 1;
/*
* Store their allocated pixel (r,g,b) values.
*/
color.pixel = wd->colors[j].c = a.pixels[i];
XQueryColor(stddpy, wd->cmap, &color);
wd->colors[j].r = color.red;
wd->colors[j].g = color.green;
wd->colors[j].b = color.blue;
clr = lcolor(w, color);
sprintf(wd->colors[j].name, "%d,%d,%d", clr.red, clr.green, clr.blue);
if (ws->numColors == WMAXCOLORS)
;
else {
if (ws->theColors == NULL) {
ws->theColors = (short *)calloc(WMAXCOLORS, sizeof(short));
if (ws->theColors == NULL)
return (Pixmap) NULL;
}
ws->theColors[ws->numColors++] = j;
}
}
#endif /* HaveXpmFormat */
}
if (p2 == (Pixmap) NULL) {
return (Pixmap) NULL;
}
if (stdgc == NULL) {
gcv.foreground = wc->fg->c;
gcv.background = wc->bg->c;
gcv.font = wc->font->fsp->fid;
wc->gc = XCreateGC(stddpy, p2, gcmask, &gcv);
stdgc = wc->gc;
}
if (isxbm) {
XCopyPlane(stddpy, p1, p2, stdgc, 0, 0, *width, *height, 0, 0, 1);
XSync(stddpy, False);
XFreePixmap(stddpy, p1);
}
return p2;
}
/*
* Interpret a platform-specific color name s.
* Under X, we can do this only if there is a window.
*/
int nativecolor(w, s, r, g, b)
wbp w;
char *s;
long *r, *g, *b;
{
XColor colorcell;
LinearColor clr;
wsp ws;
wdp wd;
if (!w) /* if no window, give up */
return 0;
ws = w->window;
wd = ws->display;
if (!XParseColor(wd->display, wd->cmap, s, &colorcell))
return 0; /* if unknown to X */
clr = lcolor(w, colorcell);
*r = clr.red;
*g = clr.green;
*b = clr.blue;
return 1;
}
/*
* Convert an X color into an Icon linear color.
*/
LinearColor lcolor(w, colorcell)
wbp w;
XColor colorcell;
{
LinearColor l;
double gamma = w->context->gamma;
l.red = 65535 * pow((int)colorcell.red / 65535.0, gamma);
l.green = 65535 * pow((int)colorcell.green / 65535.0, gamma);
l.blue = 65535 * pow((int)colorcell.blue / 65535.0, gamma);
return l;
}
/*
* Convert an Icon linear color into an X colorcell.
*/
XColor xcolor(w, c)
wbp w;
LinearColor c;
{
XColor x;
double invgamma = 1.0 / w->context->gamma;
x.red = 65535 * pow(c.red / 65535.0, invgamma);
x.green = 65535 * pow(c.green / 65535.0, invgamma);
x.blue = 65535 * pow(c.blue / 65535.0, invgamma);
x.flags = DoRed | DoGreen | DoBlue;
return x;
}
int raiseWindow(w)
wbp w;
{
if (w->window->win)
XRaiseWindow(w->window->display->display, w->window->win);
return Succeeded;
}
int lowerWindow(w)
wbp w;
{
if (w->window->win)
XLowerWindow(w->window->display->display, w->window->win);
return Succeeded;
}
int walert(w, volume)
wbp w;
int volume;
{
STDLOCALS(w);
XBell(stddpy, volume);
XFlush(stddpy);
return Succeeded;
}
#else /* Graphics */
static char junk; /* avoid empty module */
#endif /* Graphics */