You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
782 lines
22 KiB
782 lines
22 KiB
/*
|
|
* XaoS, a fast portable realtime fractal zoomer
|
|
* Copyright (C) 1996,1997 by
|
|
*
|
|
* Jan Hubicka (hubicka@paru.cas.cz)
|
|
* Thomas Marsh (tmarsh@austin.ibm.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*
|
|
* Shamelessly ripped for use in xsynaesthesia
|
|
*/
|
|
/*#include "aconfig.h"*/
|
|
#define X11_DRIVER
|
|
/*#define MITSHM*/
|
|
|
|
#ifdef X11_DRIVER
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <X11/cursorfont.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#ifndef __FreeBSD__
|
|
#include <malloc.h>
|
|
#else
|
|
#include <stdlib.h>
|
|
#endif
|
|
#include "xlib.h"
|
|
#ifdef AMIGA
|
|
#define XFlush(x) while(0)
|
|
#endif
|
|
|
|
#undef PIXMAP
|
|
|
|
#define chkalloc(n) if (!n) fprintf(stderr, "out of memory\n"), exit(-1)
|
|
|
|
int xupdate_size(xdisplay * d)
|
|
{
|
|
int tmp;
|
|
Window wtmp;
|
|
int width = d->width, height = d->height;
|
|
XGetGeometry(d->display, d->window, &wtmp, &tmp, &tmp, &d->width, &d->height, (unsigned int *) &tmp, (unsigned int *) &tmp);
|
|
if ((int)d->width != width || (int)d->height != height)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
void xflip_buffers(xdisplay * d)
|
|
{
|
|
d->back = d->vbuffs[d->current];
|
|
d->current ^= 1;
|
|
d->vbuff = d->vbuffs[d->current];
|
|
}
|
|
|
|
void draw_screen(xdisplay * d)
|
|
{
|
|
switch (d->image[0]->bits_per_pixel) {
|
|
case 16:{
|
|
unsigned short *de;
|
|
unsigned char *s;
|
|
unsigned char *e;
|
|
for (s = (unsigned char *) d->vbuffs[d->current],
|
|
e = (unsigned char *) d->vbuffs[d->current] + (d->linewidth * d->height),
|
|
de = (unsigned short *) d->data[d->current]; s < e; s += 8, de += 8)
|
|
*de = d->pixels[*s],
|
|
*(de + 1) = d->pixels[*(s + 1)],
|
|
*(de + 2) = d->pixels[*(s + 2)],
|
|
*(de + 3) = d->pixels[*(s + 3)],
|
|
*(de + 4) = d->pixels[*(s + 4)],
|
|
*(de + 5) = d->pixels[*(s + 5)],
|
|
*(de + 6) = d->pixels[*(s + 6)],
|
|
*(de + 7) = d->pixels[*(s + 7)];
|
|
s -= 8;
|
|
de -= 8;
|
|
for (; s < e; s++, de++)
|
|
*de = d->pixels[*s];
|
|
break;
|
|
}
|
|
case 24:{
|
|
unsigned char *de;
|
|
unsigned char *s;
|
|
unsigned char *e;
|
|
for (s = (unsigned char *) d->vbuffs[d->current],
|
|
e = (unsigned char *) d->vbuffs[d->current] + (d->linewidth * d->height),
|
|
de = (unsigned char *) d->data[d->current]; s < e; s++, de+=3)
|
|
de[0] = d->pixels[*s],
|
|
de[1] = d->pixels[*s]>>8,
|
|
de[2] = d->pixels[*s]>>16;
|
|
|
|
break;
|
|
}
|
|
case 32:{
|
|
unsigned long *de;
|
|
unsigned char *s;
|
|
unsigned char *e;
|
|
for (s = (unsigned char *) d->vbuffs[d->current],
|
|
e = (unsigned char *) d->vbuffs[d->current] + (d->linewidth * d->height),
|
|
de = (unsigned long *) d->data[d->current]; s < e; s += 8, de += 8)
|
|
*de = d->pixels[*s],
|
|
*(de + 1) = d->pixels[*(s + 1)],
|
|
*(de + 2) = d->pixels[*(s + 2)],
|
|
*(de + 3) = d->pixels[*(s + 3)],
|
|
*(de + 4) = d->pixels[*(s + 4)],
|
|
*(de + 5) = d->pixels[*(s + 5)],
|
|
*(de + 6) = d->pixels[*(s + 6)],
|
|
*(de + 7) = d->pixels[*(s + 7)];
|
|
s -= 8;
|
|
de -= 8;
|
|
for (; s < e; s++, de++)
|
|
*de = d->pixels[*s];
|
|
break;
|
|
}
|
|
}
|
|
#ifdef MITSHM
|
|
if (d->SharedMemFlag) {
|
|
XShmPutImage(d->display, d->window, d->gc, d->image[d->current], 0, 0, 0,
|
|
0, d->width, d->height, True);
|
|
XFlush(d->display);
|
|
} else
|
|
#endif
|
|
{
|
|
XPutImage(d->display, d->window, d->gc, d->image[d->current], 0, 0, 0, 0, d->width, d->height);
|
|
XFlush(d->display);
|
|
}
|
|
d->screen_changed = 0;
|
|
}
|
|
|
|
#ifdef MITSHM
|
|
int alloc_shm_image(xdisplay * new)
|
|
{
|
|
register char *ptr;
|
|
int temp, size = 0, i;
|
|
ptr = DisplayString(new->display);
|
|
if (!ptr || (*ptr == ':') || !strncmp(ptr, "localhost:", 10) ||
|
|
!strncmp(ptr, "unix:", 5) || !strncmp(ptr, "local:", 6)) {
|
|
new->SharedMemOption = XQueryExtension(new->display, "MIT-SHM", &temp, &temp, &temp);
|
|
} else {
|
|
new->SharedMemOption = False;
|
|
return 0;
|
|
}
|
|
new->SharedMemFlag = False;
|
|
#if 0
|
|
new->SharedMemOption = True;
|
|
new->SharedMemFlag = False;
|
|
#endif
|
|
|
|
if (new->SharedMemFlag) {
|
|
XShmDetach(new->display, &new->xshminfo[0]);
|
|
XShmDetach(new->display, &new->xshminfo[1]);
|
|
new->image[0]->data = (char *) NULL;
|
|
new->image[1]->data = (char *) NULL;
|
|
shmdt(new->xshminfo[0].shmaddr);
|
|
shmdt(new->xshminfo[1].shmaddr);
|
|
}
|
|
for (i = 0; i < 2; i++) {
|
|
if (new->SharedMemOption) {
|
|
int mul;
|
|
if (new->depth == 8)
|
|
mul = 1;
|
|
else if (new->depth <= 24)
|
|
mul = 2;
|
|
else
|
|
mul = 4;
|
|
new->SharedMemFlag = False;
|
|
new->image[i] = XShmCreateImage(new->display, new->visual, new->depth, ZPixmap,
|
|
NULL, &new->xshminfo[i], new->width, new->height * mul);
|
|
if (new->image[i]) {
|
|
temp = new->image[i]->bytes_per_line * new->image[i]->height;
|
|
new->linewidth = new->image[i]->bytes_per_line * 8 / new->image[i]->bits_per_pixel;
|
|
if (temp > size)
|
|
size = temp;
|
|
new->xshminfo[i].shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
|
|
if (new->xshminfo[i].shmid != -1) {
|
|
new->xshminfo[i].shmaddr = (char *) shmat(new->xshminfo[i].shmid, 0, 0);
|
|
if (new->xshminfo[i].shmaddr != (char *) -1) {
|
|
new->image[i]->data = new->xshminfo[i].shmaddr;
|
|
new->data[i] = new->vbuffs[i] = (char *) new->image[i]->data;
|
|
new->xshminfo[i].readOnly = True;
|
|
|
|
new->SharedMemFlag = XShmAttach(new->display, &new->xshminfo[i]);
|
|
XSync(new->display, False);
|
|
if (!new->SharedMemFlag) {
|
|
XDestroyImage(new->image[i]);
|
|
new->image[i] = (XImage *) NULL;
|
|
new->SharedMemFlag = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
/* Always Destroy Shared Memory Ident */
|
|
shmctl(new->xshminfo[i].shmid, IPC_RMID, 0);
|
|
}
|
|
if (!new->SharedMemFlag) {
|
|
XDestroyImage(new->image[i]);
|
|
new->image[i] = (XImage *) NULL;
|
|
new->SharedMemFlag = 0;
|
|
return 0;
|
|
}
|
|
} else {
|
|
new->SharedMemFlag = 0;
|
|
return 0;
|
|
}
|
|
} else {
|
|
new->SharedMemFlag = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
new->current = 0;
|
|
xflip_buffers(new);
|
|
return 1;
|
|
}
|
|
|
|
void free_shm_image(xdisplay * d)
|
|
{
|
|
if (d->SharedMemFlag) {
|
|
XDestroyImage(d->image[0]);
|
|
XDestroyImage(d->image[1]);
|
|
XShmDetach(d->display, &d->xshminfo[0]);
|
|
XShmDetach(d->display, &d->xshminfo[1]);
|
|
shmdt(d->xshminfo[0].shmaddr);
|
|
shmdt(d->xshminfo[1].shmaddr);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
int alloc_image(xdisplay * d)
|
|
{
|
|
int i;
|
|
#ifdef MITSHM
|
|
if (!d->params->nomitshm && alloc_shm_image(d)) {
|
|
if (d->depth != 8) {
|
|
for (i = 0; i < 2; i++)
|
|
d->vbuffs[i] = malloc(d->linewidth * d->height);
|
|
}
|
|
return 1;
|
|
}
|
|
#endif
|
|
for (i = 0; i < 2; i++) {
|
|
d->image[i] = XCreateImage(d->display, d->visual, d->depth, ZPixmap, 0,
|
|
NULL, d->width, d->height, 8, 0);
|
|
if (d->image[i] == NULL) {
|
|
printf("Out of memory for image..exiting\n");
|
|
exit(3);
|
|
}
|
|
/*Add a little extra memory to catch overruns when dumping image to buffer in draw_screen*/
|
|
d->image[i]->data = malloc(d->image[i]->bytes_per_line * d->height + 32);
|
|
memset(d->image[i]->data,0,d->image[i]->bytes_per_line * d->height);
|
|
|
|
if (d->image[i]->data == NULL) {
|
|
printf("Out of memory for image buffers..exiting\n");
|
|
exit(3);
|
|
}
|
|
d->data[i] = d->vbuffs[i] = (char *) d->image[i]->data;
|
|
d->linewidth = d->image[i]->bytes_per_line * 8 / d->image[i]->bits_per_pixel;
|
|
}
|
|
if (d->depth != 8) {
|
|
for (i = 0; i < 2; i++) {
|
|
/* Add a little extra memory to catch overruns */
|
|
/* when dumping image to buffer in draw_screen */
|
|
d->vbuffs[i] = malloc(d->linewidth * d->height + 32);
|
|
memset(d->vbuffs[i],0,d->linewidth * d->height);
|
|
|
|
if (d->vbuffs[i] == NULL) {
|
|
printf("Out of memory for image buffers2..exiting\n");
|
|
exit(3);
|
|
}
|
|
}
|
|
}
|
|
xflip_buffers(d);
|
|
return 1;
|
|
}
|
|
|
|
void free_image(xdisplay * d)
|
|
{
|
|
if (d->depth != 8)
|
|
free(d->vbuffs[0]), free(d->vbuffs[1]);
|
|
#ifdef MITSHM
|
|
if (d->SharedMemFlag) {
|
|
free_shm_image(d);
|
|
return;
|
|
}
|
|
#endif
|
|
XDestroyImage(d->image[0]);
|
|
XDestroyImage(d->image[1]);
|
|
}
|
|
#define MAX(x,y) ((x)>(y)?(x):(y))
|
|
|
|
|
|
xdisplay *xalloc_display(const char *s, int xHint, int yHint, int x, int y, xlibparam * params)
|
|
{
|
|
xdisplay *xd;
|
|
Visual *defaultvisual;
|
|
XVisualInfo vis;
|
|
|
|
|
|
xd = (xdisplay *) calloc(sizeof(xdisplay), 1);
|
|
chkalloc(xd);
|
|
xd->display = XOpenDisplay((char *) NULL);
|
|
if (!xd->display) {
|
|
free((void *) xd);
|
|
return NULL;
|
|
}
|
|
xd->screen = DefaultScreen(xd->display);
|
|
xd->attributes = (XSetWindowAttributes *)
|
|
malloc(sizeof(XSetWindowAttributes));
|
|
chkalloc(xd->attributes);
|
|
xd->attributes->background_pixel = BlackPixel(xd->display,
|
|
xd->screen);
|
|
xd->attributes->border_pixel = BlackPixel(xd->display, xd->screen);
|
|
xd->attributes->event_mask = ButtonPressMask | StructureNotifyMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | ExposureMask | KeyReleaseMask;
|
|
xd->attributes->override_redirect = False;
|
|
xd->attr_mask = CWBackPixel | CWBorderPixel | CWEventMask;
|
|
xd->classX = InputOutput;
|
|
xd->xcolor.n = 0;
|
|
xd->parent_window = RootWindow(xd->display, xd->screen);
|
|
defaultvisual = DefaultVisual(xd->display, xd->screen);
|
|
xd->params = params;
|
|
if (!params->usedefault) {
|
|
if (defaultvisual->class != PseudoColor || (!XMatchVisualInfo(xd->display, xd->screen, 8, PseudoColor, &vis) && vis.colormap_size > 128)) {
|
|
xd->fixedcolormap = 1;
|
|
if (!XMatchVisualInfo(xd->display, xd->screen, 15, TrueColor, &vis)) {
|
|
if (!XMatchVisualInfo(xd->display, xd->screen, 16, TrueColor, &vis)) {
|
|
if (!XMatchVisualInfo(xd->display, xd->screen, 32, TrueColor, &vis) &&
|
|
!XMatchVisualInfo(xd->display, xd->screen, 24, TrueColor, &vis)) {
|
|
if (!XMatchVisualInfo(xd->display, xd->screen, 8, PseudoColor, &vis) &&
|
|
!XMatchVisualInfo(xd->display, xd->screen, 7, PseudoColor, &vis)) {
|
|
if (!XMatchVisualInfo(xd->display, xd->screen, 8, TrueColor, &vis) &&
|
|
!XMatchVisualInfo(xd->display, xd->screen, 8, StaticColor, &vis) &&
|
|
!XMatchVisualInfo(xd->display, xd->screen, 8, StaticGray, &vis)) {
|
|
printf("Display does not support PseudoColor depth 7,8,StaticColor depth 8, StaticGray depth 8, Truecolor depth 8,15,16,24 nor 32!\n");
|
|
return NULL;
|
|
} else
|
|
xd->truecolor = 1;
|
|
} else
|
|
xd->fixedcolormap = 0, xd->truecolor = 0;
|
|
} else
|
|
xd->truecolor = 1;
|
|
} else
|
|
xd->truecolor = 1;
|
|
} else
|
|
xd->truecolor = 1;
|
|
} else {
|
|
xd->truecolor = 0;
|
|
}
|
|
xd->depth = vis.depth;
|
|
xd->visual = vis.visual;
|
|
} else { /*usedefault */
|
|
vis.depth = xd->depth = DefaultDepth(xd->display, xd->screen);
|
|
xd->visual = defaultvisual;
|
|
switch (defaultvisual->class) {
|
|
case PseudoColor:
|
|
if (xd->depth <= 8) {
|
|
xd->depth = 8;
|
|
xd->truecolor = 0;
|
|
xd->fixedcolormap = 0;
|
|
} else {
|
|
printf("Pseudocolor visual on unsuported depth\n");
|
|
return NULL;
|
|
}
|
|
break;
|
|
case TrueColor:
|
|
case StaticColor:
|
|
case StaticGray:
|
|
xd->truecolor = 1;
|
|
xd->fixedcolormap = 1;
|
|
if (xd->depth <= 8)
|
|
xd->depth = 8;
|
|
else if (xd->depth <= 16)
|
|
xd->depth = 16;
|
|
else if (xd->depth <= 32)
|
|
xd->depth = 32;
|
|
else {
|
|
printf("Truecolor visual on unsuported depth\n");
|
|
return NULL;
|
|
}
|
|
break;
|
|
default:
|
|
printf("Unusuported visual\n");
|
|
break;
|
|
}
|
|
}
|
|
/*xd->visual->map_entries = 256; */
|
|
xd->colormap = xd->defaultcolormap = DefaultColormap(xd->display, xd->screen);
|
|
|
|
xd->window_name = s;
|
|
xd->height = y;
|
|
xd->width = x;
|
|
xd->border_width = 2;
|
|
xd->lastx = 0;
|
|
xd->lasty = 0;
|
|
xd->font_struct = (XFontStruct *) NULL;
|
|
|
|
xd->window = XCreateWindow(xd->display, xd->parent_window, xHint, yHint,
|
|
xd->width, xd->height, xd->border_width,
|
|
vis.depth, xd->classX, xd->visual,
|
|
xd->attr_mask, xd->attributes);
|
|
if (!xd->fixedcolormap && params->privatecolormap) {
|
|
unsigned long pixels[256];
|
|
int i;
|
|
xd->colormap = XCreateColormap(xd->display, xd->window, xd->visual, AllocNone);
|
|
XAllocColorCells(xd->display, xd->colormap, 1, 0, 0, pixels, MAX(xd->visual->map_entries, 256));
|
|
for (i = 0; i < 16; i++) {
|
|
xd->xcolor.c[i].pixel = pixels[i];
|
|
}
|
|
XQueryColors(xd->display, xd->defaultcolormap, xd->xcolor.c, 16);
|
|
XStoreColors(xd->display, xd->colormap, xd->xcolor.c, 16);
|
|
xd->privatecolormap = 1;
|
|
}
|
|
if (!xd->fixedcolormap)
|
|
XSetWindowColormap(xd->display, xd->window, xd->colormap);
|
|
xd->gc = XCreateGC(xd->display, xd->window, 0L, &(xd->xgcvalues));
|
|
XSetBackground(xd->display, xd->gc,
|
|
BlackPixel(xd->display, xd->screen));
|
|
XSetForeground(xd->display, xd->gc,
|
|
WhitePixel(xd->display, xd->screen));
|
|
XStoreName(xd->display, xd->window, xd->window_name);
|
|
XMapWindow(xd->display, xd->window);
|
|
#if 1
|
|
XSelectInput(xd->display, xd->window,
|
|
/* ExposureMask | */
|
|
KeyPress |
|
|
/* KeyRelease | */
|
|
/* ConfigureRequest | */
|
|
/* FocusChangeMask | */
|
|
StructureNotifyMask |
|
|
ButtonPressMask | ButtonReleaseMask);
|
|
#endif
|
|
#ifdef PIXAMP
|
|
xd->pixmap = XCreatePixmap(xd->display, xd->window, xd->width,
|
|
xd->height, xd->depth);
|
|
#endif
|
|
|
|
{
|
|
XColor c;
|
|
Pixmap p = XCreatePixmap(xd->display, xd->window, 1,1,1);
|
|
memset(&c,0,sizeof(c));
|
|
xd->cursor = XCreatePixmapCursor(xd->display, p,p,
|
|
&c,&c, 0,0);
|
|
/* We don't need no fancy cursor
|
|
XDefineCursor(xd->display,xd->window,xd->cursor);
|
|
*/
|
|
XFreePixmap(xd->display, p);
|
|
}
|
|
|
|
return (xd);
|
|
}
|
|
|
|
void xsetcolor(xdisplay * d, int col)
|
|
{
|
|
switch (col) {
|
|
case 0:
|
|
XSetForeground(d->display, d->gc,
|
|
BlackPixel(d->display, d->screen));
|
|
break;
|
|
case 1:
|
|
XSetForeground(d->display, d->gc,
|
|
WhitePixel(d->display, d->screen));
|
|
break;
|
|
default:
|
|
if ((col - 2) > d->xcolor.n) {
|
|
fprintf(stderr, "color error\n");
|
|
exit(3);
|
|
}
|
|
XSetForeground(d->display, d->gc,
|
|
d->xcolor.c[col - 2].pixel);
|
|
break;
|
|
}
|
|
}
|
|
void xrotate_palette(xdisplay * d, int direction, unsigned char co[3][256], int ncolors)
|
|
{
|
|
int i, p;
|
|
|
|
if (d->privatecolormap) {
|
|
for (i = 0; i < d->xcolor.n; i++) {
|
|
p = d->xcolor.c[i].pixel;
|
|
d->xcolor.c[i].red = (int) co[0][p] * 256;
|
|
d->xcolor.c[i].green = (int) co[1][p] * 256;
|
|
d->xcolor.c[i].blue = (int) co[2][p] * 256;
|
|
}
|
|
XStoreColors(d->display, d->colormap, d->xcolor.c, d->xcolor.n);
|
|
}
|
|
if (d->truecolor) {
|
|
unsigned long oldpixels[256];
|
|
memcpy(oldpixels, d->pixels, sizeof(oldpixels));
|
|
p = (ncolors - 1 + direction) % (ncolors - 1) + 1;
|
|
for (i = 1; i < ncolors; i++) { /*this is ugly..I know */
|
|
d->pixels[i] = oldpixels[p];
|
|
p++;
|
|
if (p >= ncolors)
|
|
p = 1;
|
|
}
|
|
draw_screen(d);
|
|
}
|
|
}
|
|
int xalloc_color(xdisplay * d, int r, int g, int b, int readwrite)
|
|
{
|
|
d->xcolor.n++;
|
|
d->xcolor.c[d->xcolor.n - 1].flags = DoRed | DoGreen | DoBlue;
|
|
d->xcolor.c[d->xcolor.n - 1].red = r;
|
|
d->xcolor.c[d->xcolor.n - 1].green = g;
|
|
d->xcolor.c[d->xcolor.n - 1].blue = b;
|
|
d->xcolor.c[d->xcolor.n - 1].pixel = d->xcolor.n - 1;
|
|
if ((readwrite && !d->fixedcolormap) || d->privatecolormap) {
|
|
unsigned long cell;
|
|
if (d->privatecolormap) {
|
|
cell = d->xcolor.c[d->xcolor.n - 1].pixel += 16;
|
|
if (d->xcolor.c[d->xcolor.n - 1].pixel >= d->visual->map_entries) {
|
|
d->xcolor.n--;
|
|
return (-1);
|
|
}
|
|
} else {
|
|
if (!XAllocColorCells(d->display, d->colormap, 0, 0, 0, &cell, 1)) {
|
|
d->xcolor.n--;
|
|
if (d->xcolor.n <= 32)
|
|
printf("Colormap is too full! close some colorfull aplications or use -private\n");
|
|
return (-1);
|
|
}
|
|
d->xcolor.c[d->xcolor.n - 1].pixel = cell;
|
|
}
|
|
XStoreColor(d->display, d->colormap, &(d->xcolor.c[d->xcolor.n - 1]));
|
|
return (cell);
|
|
}
|
|
if (!XAllocColor(d->display, d->colormap, &(d->xcolor.c[d->xcolor.n - 1]))) {
|
|
d->xcolor.n--;
|
|
if (d->xcolor.n <= 32)
|
|
printf("Colormap is too full! close some colorfull aplications or use -private\n");
|
|
return (-1);
|
|
}
|
|
d->pixels[d->xcolor.n - 1] = d->xcolor.c[d->xcolor.n - 1].pixel;
|
|
return (d->depth != 8 ? d->xcolor.n - 1 : d->xcolor.c[d->xcolor.n - 1].pixel);
|
|
}
|
|
|
|
void xfree_colors(xdisplay * d)
|
|
{
|
|
unsigned long pixels[256];
|
|
int i;
|
|
for (i = 0; i < d->xcolor.n; i++)
|
|
pixels[i] = d->xcolor.c[i].pixel;
|
|
if (!d->privatecolormap)
|
|
XFreeColors(d->display, d->colormap, pixels, d->xcolor.n, 0);
|
|
d->xcolor.n = 0;
|
|
}
|
|
|
|
void xfree_display(xdisplay * d)
|
|
{
|
|
XSync(d->display, 0);
|
|
if (d->font_struct != (XFontStruct *) NULL) {
|
|
XFreeFont(d->display, d->font_struct);
|
|
}
|
|
XUnmapWindow(d->display, d->window);
|
|
#ifdef PIXMAP
|
|
XFreePixmap(d->display, d->pixmap);
|
|
#endif
|
|
XDestroyWindow(d->display, d->window);
|
|
XFreeCursor(d->display, d->cursor);
|
|
XCloseDisplay(d->display);
|
|
free((void *) d->attributes);
|
|
free((void *) d);
|
|
}
|
|
|
|
#ifdef PIXMAP
|
|
void xline(xdisplay * d, int x1, int y1, int x2, int y2)
|
|
{
|
|
XDrawLine(d->display, d->pixmap, d->gc, x1, y1, x2, y2);
|
|
d->lastx = x2, d->lasty = y2;
|
|
d->screen_changed = 1;
|
|
} void xlineto(xdisplay * d, int x, int y)
|
|
{
|
|
|
|
XDrawLine(d->display, d->pixmap, d->gc, d->lastx, d->lasty, x, y);
|
|
d->lastx = x, d->lasty = y;
|
|
d->screen_changed = 1;
|
|
} void xrect(xdisplay * d, int x1, int y1, int x2, int y2)
|
|
{
|
|
|
|
XDrawRectangle(d->display, d->pixmap, d->gc, x1, y1,
|
|
(x2 - x1), (y2 - y1));
|
|
d->lastx = x2, d->lasty = y2;
|
|
d->screen_changed = 1;
|
|
} void xfillrect(xdisplay * d, int x1, int y1, int x2, int y2)
|
|
{
|
|
|
|
XFillRectangle(d->display, d->pixmap, d->gc, x1, y1,
|
|
(x2 - x1), (y2 - y1));
|
|
d->lastx = x2, d->lasty = y2;
|
|
d->screen_changed = 1;
|
|
} void xpoint(xdisplay * d, int x, int y)
|
|
{
|
|
|
|
XDrawPoint(d->display, d->pixmap, d->gc, x, y);
|
|
d->lastx = x, d->lasty = y;
|
|
d->screen_changed = 1;
|
|
} void xflush(xdisplay * d)
|
|
{
|
|
|
|
draw_screen(d);
|
|
XFlush(d->display);
|
|
}
|
|
|
|
void xclear_screen(xdisplay * d)
|
|
{
|
|
xfillrect(d, 0, 0, d->width, d->height);
|
|
d->screen_changed = 1;
|
|
}
|
|
|
|
#endif
|
|
void xmoveto(xdisplay * d, int x, int y)
|
|
{
|
|
d->lastx = x, d->lasty = y;
|
|
} int xsetfont(xdisplay * d, char *font_name)
|
|
{
|
|
|
|
if (d->font_struct != (XFontStruct *) NULL) {
|
|
XFreeFont(d->display, d->font_struct);
|
|
}
|
|
d->font_struct = XLoadQueryFont(d->display, font_name);
|
|
if (!d->font_struct) {
|
|
fprintf(stderr, "could not load font: %s\n", font_name);
|
|
exit(3);
|
|
}
|
|
return (d->font_struct->max_bounds.ascent + d->font_struct->max_bounds.descent);
|
|
}
|
|
|
|
void xouttext(xdisplay * d, char *string)
|
|
{
|
|
int sz;
|
|
|
|
sz = strlen(string);
|
|
XDrawImageString(d->display, d->window, d->gc, d->lastx, d->lasty,
|
|
string, sz);
|
|
#if 0
|
|
d->lastx += XTextWidth(d->font_struct, string, sz);
|
|
d->screen_changed = 1;
|
|
#endif
|
|
} void xresize(xdisplay * d, XEvent * ev)
|
|
{
|
|
|
|
#ifdef PIXMAP
|
|
XFreePixmap(d->display, d->pixmap);
|
|
#endif
|
|
d->width = ev->xconfigure.width;
|
|
d->height = ev->xconfigure.height;
|
|
#ifdef PIXMAP
|
|
d->pixmap = XCreatePixmap(d->display, d->window, d->width,
|
|
d->height, d->depth);
|
|
#endif
|
|
}
|
|
|
|
#ifdef PIXMAP
|
|
void xarc(xdisplay * d, int x, int y, unsigned int w,
|
|
unsigned int h, int a1, int a2)
|
|
{
|
|
XDrawArc(d->display, d->pixmap, d->gc, x, y, w, h, a1, a2);
|
|
} void xfillarc(xdisplay * d, int x, int y, unsigned int w,
|
|
unsigned int h, int a1, int a2)
|
|
{
|
|
XFillArc(d->display, d->pixmap, d->gc, x, y, w, h, a1, a2);
|
|
}
|
|
#endif
|
|
|
|
void xsize_set(xdisplay *d, int width, int height)
|
|
{
|
|
XResizeWindow(d->display, d->window, width, height);
|
|
}
|
|
|
|
int xmouse_x(xdisplay * d)
|
|
{
|
|
|
|
return d->mouse_x;
|
|
}
|
|
|
|
int xmouse_y(xdisplay * d)
|
|
{
|
|
return d->mouse_y;
|
|
}
|
|
|
|
void xmouse_update(xdisplay * d)
|
|
{
|
|
Window rootreturn, childreturn;
|
|
int rootx = 0, rooty = 0, buttons = 0;
|
|
|
|
XEvent event;
|
|
|
|
if (XCheckMaskEvent(d->display,ButtonPressMask | ButtonReleaseMask, &event)) {
|
|
if (event.type == ButtonPress)
|
|
d->mouse_buttons |= 1 << ((XButtonEvent*)(&event))->button;
|
|
else
|
|
d->mouse_buttons &= ~( 1 << ((XButtonEvent*)(&event))->button );
|
|
}
|
|
|
|
XQueryPointer(d->display, d->window, &rootreturn, &childreturn,
|
|
&rootx, &rooty, &(d->mouse_x), &(d->mouse_y),
|
|
&buttons);
|
|
}
|
|
|
|
char xkeyboard_query(xdisplay * d) {
|
|
XEvent event;
|
|
|
|
if (XCheckMaskEvent(d->display,KeyPressMask | KeyReleaseMask, &event)) {
|
|
char *str =
|
|
XKeysymToString(XLookupKeysym((XKeyPressedEvent*)(&event),0));
|
|
|
|
if ( ((XKeyPressedEvent*)(&event))->state &
|
|
(ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) )
|
|
return 0;
|
|
|
|
if (str) {
|
|
char key;
|
|
|
|
if (strlen(str) == 1)
|
|
key = str[0];
|
|
else if (strcmp(str,"equal") == 0)
|
|
key = '=';
|
|
else if (strcmp(str,"minus") == 0)
|
|
key = '-';
|
|
else if (strcmp(str,"bracketleft") == 0)
|
|
key = '[';
|
|
else if (strcmp(str,"bracketright") == 0)
|
|
key = ']';
|
|
else if (strcmp(str,"comma") == 0)
|
|
key = ',';
|
|
else if (strcmp(str,"period") == 0)
|
|
key = '.';
|
|
else if (strcmp(str,"slash") == 0)
|
|
key = '/';
|
|
else return 0;
|
|
|
|
if ( ((XKeyPressedEvent*)(&event))->state & ShiftMask )
|
|
switch(key) {
|
|
case '=' : key = '+'; break;
|
|
case '[' : key = '{'; break;
|
|
case ']' : key = '}'; break;
|
|
case ',' : key = '<'; break;
|
|
case '/' : key = '?'; break;
|
|
default :
|
|
if (key >= 'a' && key <= 'z')
|
|
key = key+'A'-'a';
|
|
break;
|
|
}
|
|
return key;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int xsize_update(xdisplay *d,int *width,int *height) {
|
|
XEvent event;
|
|
|
|
if (XCheckMaskEvent(d->display,StructureNotifyMask, &event)) {
|
|
if (event.type == ConfigureNotify) {
|
|
xupdate_size(d);
|
|
free_image(d);
|
|
alloc_image(d);
|
|
*width = d->linewidth;
|
|
*height = d->height;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned int xmouse_buttons(xdisplay * d)
|
|
{
|
|
return d->mouse_buttons;
|
|
}
|
|
#endif
|