/* Xbit - Simple xlib interface Copyright (C) 2005 Ian Cowburn (ianc@noddybox.demon.co.uk) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------- This is a bit messy as it based on very old K&R code. */ static char rcs_id[]="$Id: Xbit.c 11 2006-05-02 19:02:49Z ianc $"; #include #include #include #include #include /* #include */ #include #include #include #include #include #include #include #include #include #include "Xbit.h" #include "icon" #define WARN(x) fprintf(stderr,"%s(%d) : Warning:%s\n",__FILE__,__LINE__,x); #define WARN1(x,y) fprintf(stderr,"%s(%d) : Warning:%s %s\n",__FILE__,__LINE__,x,y); #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #define ABS(x) ((x) < 0 ? (-(x)) : (x)) /* GLOBALS */ #define MAXPM 256 typedef struct WEntry { Window w; Pixmap pm[MAXPM]; int used_MIT_SHM; XShmSegmentInfo shm_info; int pmi; int buffer; int use_pm; int multi; int multino; ulong multicls; GC gc; int ox; int oy; int ww; int wh; int pw; int ph; int func; int lastuserfunc; ulong lastfg; int spline_thresh; struct WEntry *next; } WEntry; static WEntry *whead=NULL; static WEntry *wtail=NULL; static WEntry *current=NULL; static WEntry *stack[128]; static int sttop; static Display *display=NULL; static XVisualInfo vinfo; static int screen; static int use_shm=True; static ulong xb_black; static ulong xb_white; /* Buffer for Xprintf() and XIprintf() */ static char prbuf[1024]; /* Definitions for XImage 8x8 charset */ #include "fontset.h" /* Put globals */ static int no_plots; static XPoint points[MAX_PUTPLOTS]; /* Set write mode */ #define WM(c) do {if ((c)!=current->func) { \ XSetFunction(display,current->gc,c); \ current->func=c; } } while(0) /* Set foreground funcrion */ #define FG(c) do {if ((c)!=current->lastfg) { \ XSetForeground(display,current->gc,c); \ current->lastfg=c; } } while(0) /* Stack current windows */ #define PUSHW do {stack[sttop++]=current;} while(0) #define POPW do {current=stack[--sttop];} while(0) /* ------------- FUNCTIONS ------------- */ static void CreateWEntry(Window w, GC g, int ww, int wh) { WEntry *new; if (!(new=malloc(sizeof(WEntry)))) { fprintf(stderr,"%s(%d) : FATAL:%s\n",__FILE__,__LINE__, "Couldn't malloc() WEntry"); exit(1); } if (!whead) { whead=new; wtail=new; } else { wtail->next=new; wtail=new; } new->next=NULL; new->w=w; new->gc=g; new->pm[0]=0; new->pm[1]=0; new->pmi=0; new->buffer=True; new->use_pm=True; new->multi=False; new->ox=0; new->oy=0; new->ww=ww; new->wh=wh; new->pw=0; new->ph=0; new->func=GXcopy; new->lastuserfunc=GXcopy; new->lastfg=-1; new->spline_thresh=1; new->used_MIT_SHM=False; } XImage *CreateXImage(void) { XImage *img; char *p; if (!use_shm) { switch(vinfo.depth) { case 8: p=malloc(current->pw*current->ph*1); break; case 16: p=malloc(current->pw*current->ph*2); break; default: p=malloc(current->pw*current->ph*4); break; } if (!p) { fprintf(stderr,"%s(%d) : FATAL:%s\n",__FILE__,__LINE__, "Couldn't malloc() XImage data"); exit(1); } img=XCreateImage (display, vinfo.visual, vinfo.depth, /* Image depth */ ZPixmap, /* Image format */ 0, /* Offset */ p, /* Data */ current->pw, /* Width */ current->ph, /* Height */ 8, /* Bitmap pad */ 0); } else { img=XShmCreateImage(display, vinfo.visual, vinfo.depth, ZPixmap, NULL, &(current->shm_info), current->pw, current->ph); if (!img) return(NULL); current->used_MIT_SHM=True; /* Get shared memory for image */ current->shm_info.shmid=shmget(IPC_PRIVATE, img->bytes_per_line*img->height, IPC_CREAT|0777); if (current->shm_info.shmid<0) { WARN("Couldn't get MITSHM mem"); exit(1); } current->shm_info.shmaddr=shmat(current->shm_info.shmid,0,0); img->data=current->shm_info.shmaddr; current->shm_info.readOnly=False; /* Try and attached shared memory */ if (!XShmAttach(display,&(current->shm_info))) { WARN("Failed to attach MITSHM block"); exit(1); } XSync(display,False); } ClsXImage(img); return img; } void ClsXImage(XImage *img) { memset(img->data,0,img->bytes_per_line*img->height); } void DestroyXImage(XImage *img) { if (current->used_MIT_SHM) { XShmDetach(display,&(current->shm_info)); if (current->shm_info.shmaddr) shmdt(current->shm_info.shmaddr); if (current->shm_info.shmid>=0) shmctl(current->shm_info.shmid,IPC_RMID,0); current->used_MIT_SHM=False; } XDestroyImage(img); XSync(display,False); } void SetCurrentWin(Window w) { WEntry *l; l=whead; while(l) { if (l->w==w) { current=l; return; } l=l->next; } WARN("Asked for non-existant window"); } int GetVisualDepth(void) { return vinfo.depth; } Window OpenWin (int argc, char **argv, char *title, int wx, int wy, int ww, int wh, int pw, int ph, unsigned long ev, XSizeHints *hints, ulong *black, ulong *white) { Window window; GC gc; char *display_name=NULL; Pixmap icon_pixmap; int i,j,k; if (!display) { if ((display=XOpenDisplay(display_name))==NULL) { fprintf(stderr,"%s: can't connect to %s\n", argv[0], XDisplayName(display_name)); exit(-1); } /* Try and find shared memory extension */ use_shm=XQueryExtension(display,"MIT-SHM",&i,&j,&k); /* Find a nice 8-bit visual for us to use... */ if (!XMatchVisualInfo(display,DefaultScreen(display),8, PseudoColor,&vinfo)) if (!XMatchVisualInfo(display,DefaultScreen(display),16, TrueColor,&vinfo)) if (!XMatchVisualInfo(display,DefaultScreen(display),24, TrueColor,&vinfo)) if (!XMatchVisualInfo(display,DefaultScreen(display),32, TrueColor,&vinfo)) { WARN("no visual found!\n"); exit(1); } } screen=DefaultScreen(display); xb_black=BlackPixel(display,screen); xb_white=WhitePixel(display,screen); *black=xb_black; *white=xb_white; window=XCreateWindow(display, RootWindow(display,screen), wx,wy,ww,wh,1, vinfo.depth, InputOutput, vinfo.visual, 0,NULL); icon_pixmap=XCreateBitmapFromData( display, window, icon_bits, icon_width,icon_height); XSetStandardProperties( display, window, title, title, icon_pixmap, argv,argc, hints); XSelectInput (display,window,ev); gc=XCreateGC(display,window,0,NULL); XSetForeground(display,gc,*black); XSetBackground(display,gc,*white); XSetPlaneMask(display,gc,AllPlanes); XSetGraphicsExposures(display,gc,False); XMapWindow (display,window); CreateWEntry(window,gc,ww,wh); SetCurrentWin(window); Resize(pw,ph); return window; } Window OpenRootWin (ulong *black,ulong *white,int *w,int *h,int pw,int ph) { Window window; GC gc; char *display_name=NULL; int i,j,k; if (!display) { int depth; if ((display=XOpenDisplay(display_name))==NULL) { fprintf(stderr,"can't connect to %s\n",XDisplayName(display_name)); exit(-1); } screen=DefaultScreen(display); depth=DefaultDepth(display,screen); /* Try and find shared memory extension */ use_shm=XQueryExtension(display,"MIT-SHM",&i,&j,&k); /* Find a visual for us to use... */ if (!XMatchVisualInfo(display,DefaultScreen(display),depth, depth==8 ? PseudoColor:TrueColor,&vinfo)) { WARN("no visual to match the root window!"); exit(1); } } xb_black=BlackPixel(display,screen); xb_white=WhitePixel(display,screen); *black=xb_black; *white=xb_white; window=RootWindow(display,screen); gc=XCreateGC(display,window,0,NULL); XSetForeground(display,gc,*black); XSetBackground(display,gc,*white); XSetPlaneMask(display,gc,AllPlanes); XMapWindow (display,window); *w=DisplayWidth(display,screen); *h=DisplayHeight(display,screen); CreateWEntry(window,gc,*w,*h); SetCurrentWin(window); Resize(pw,ph); return window; } XFontStruct *XUseFont(const char *n) { XFontStruct *ft; if (ft=XLoadQueryFont(display,n)) XSetFont(display,current->gc,ft->fid); else WARN1("couldn't load font:",n); return ft; } void XUseCursor(const char *bm, const char *mask, XColor fg, XColor bg) { Pixmap b,m; Cursor curs; int bmw,bmh,bmx,bmy; int maskw,maskh,maskx,masky; if (XReadBitmapFile(display,current->w,bm,&bmw,&bmh,&b,&bmx,&bmy) ==BitmapOpenFailed) { WARN1("Couldn't read in cursor file:",bm); return; } if (XReadBitmapFile(display,current->w,mask,&maskw,&maskh,&m,&maskx,&masky) ==BitmapOpenFailed) { WARN1("Couldn't read in mask file:",bm); return; } curs=XCreatePixmapCursor(display,b,m,&fg,&bg,bmx,bmy); XDefineCursor(display,current->w,curs); XFreePixmap(display,b); XFreePixmap(display,m); } void LoadBitmap(const char *fn,int x,int y, int resize) { Pixmap bm; int w,h,hx,hy; int cw,ch; if (!current->use_pm) { WARN("Need pixmaps to load in bitmap"); } if (XReadBitmapFile(display,current->w,fn,&w,&h,&bm,&hx,&hy) ==BitmapOpenFailed) { WARN1("Couldn't read in bitmap file:",fn); return; } if ((w!=current->pw)||(h!=current->ph)) { if (resize) { Resize(w+x,h+y); cw=w; ch=h; } else { cw=current->pw-x; ch=current->ph-y; } } XCopyPlane(display,bm,current->pm[current->pmi], current->gc,0,0,cw,ch,x,y,1L); XFreePixmap(display,bm); } Pixmap GetBitmap(const char *fn, int *w, int *h, int *hx, int *hy) { Pixmap bm,ret; if (XReadBitmapFile(display,current->w,fn,w,h,&bm,hx,hy) ==BitmapOpenFailed) { WARN1("Couldn't read in bitmap file:",fn); return(0); } ret=XCreatePixmap(display,current->w,*w,*h,vinfo.depth); XCopyPlane(display,bm,ret,current->gc,0,0,*w,*h,0,0,1L); XFreePixmap(display,bm); return ret; } void DrawXImage(XImage *img) { if (use_shm) XShmPutImage (display, current->pm[0], current->gc, img, 0,0, 0,0, current->pw,current->ph, False); else XPutImage (display, current->pm[0], current->gc, img, 0,0, 0,0, current->pw,current->ph); } void Resize(int w,int h) { int f; if (www) w=current->ww; if (hwh) h=current->wh; current->pw=w; current->ph=h; if (!current->use_pm) return; if (current->multi) { WM(GXcopy); FG(current->multicls); for(f=0;fmultino;f++) { XFreePixmap(display,current->pm[f]); current->pm[f]=XCreatePixmap(display,current->w,w,h,vinfo.depth); XFillRectangle(display,current->pm[f], current->gc,0,0,current->pw,current->ph); } WM(current->lastuserfunc); return; } if (current->pm[0]) { XFreePixmap(display,current->pm[0]); if (current->buffer) XFreePixmap(display,current->pm[1]); } current->pmi=0; current->pm[0]=XCreatePixmap(display,current->w,w,h,vinfo.depth); if (current->buffer) current->pm[1]=XCreatePixmap(display,current->w,w,h,vinfo.depth); } void Redraw(int x,int y) { if ((x+current->ww)>current->pw) x=current->pw-current->ww; if ((y+current->wh)>current->ph) y=current->ph-current->wh; current->ox=x; current->oy=y; if (!current->use_pm) { XSync(display,False); return; } WM(GXcopy); if (current->buffer) { XCopyArea(display,current->pm[current->pmi^1],current->w, current->gc,x,y,current->ww,current->wh,0,0); XSync(display,False); } else { XCopyArea(display,current->pm[current->pmi],current->w, current->gc,x,y,current->ww,current->wh,0,0); XSync(display,False); } WM(current->lastuserfunc); } Pixmap GetCurrentPixmap(void) { if (!current->use_pm) return(0); return current->pm[current->pmi]; } GC GetCurrentGC(void) { return current->gc; } void DisableDoubleBuffer(void) { current->pmi=0; XFreePixmap(display,current->pm[1]); current->buffer=False; } void DisablePixmap(void) { current->pmi=0; if (current->use_pm) XFreePixmap(display,current->pm[0]); if (current->buffer) XFreePixmap(display,current->pm[1]); current->buffer=False; current->use_pm=False; current->pm[0]=current->w; } void DisableShm(void) { use_shm=False; } void EnableBuffers(int no, ulong clscol) { int f; current->pmi=0; if (current->use_pm) XFreePixmap(display,current->pm[0]); if (current->buffer) XFreePixmap(display,current->pm[1]); current->buffer=False; current->use_pm=True; current->multi=True; if (no>MAXPM) current->multino=MAXPM; else current->multino=no; current->multicls=clscol; WM(GXcopy); FG(current->multicls); for(f=0;fmultino;f++) { current->pm[f]=XCreatePixmap(display,current->w,current->ww,current->wh, vinfo.depth); XFillRectangle(display,current->pm[f], current->gc,0,0,current->pw,current->ph); } WM(current->lastuserfunc); } void Pageflip(void) { if (current->buffer) current->pmi=current->pmi^1; if (current->multi) if ((++current->pmi)>=current->multino) current->pmi=0; } void SetAsBackdrop(void) { XSetWindowBackgroundPixmap (display, current->w, current->pm[current->pmi]); XSync(display,False); } void XUseFunction(int f) { WM(f); current->lastuserfunc=f; } void XSetLineStyle(unsigned int w, int ls, int cs, int js) { XSetLineAttributes(display,current->gc,w,ls,cs,js); } void XCls(ulong c) { if (current->use_pm) { WM(GXcopy); FG(c); XFillRectangle(display,current->pm[current->pmi], current->gc,0,0,current->pw,current->ph); WM(current->lastuserfunc); } else { /* XSetBackground(display,current->gc,c); XClearWindow(display,current->pm[0]); */ WM(GXcopy); FG(c); XFillRectangle(display,current->pm[current->pmi], current->gc,0,0,current->pw,current->ph); WM(current->lastuserfunc); } } void XPlot(int x,int y, ulong c) { FG(c); XDrawPoint(display,current->pm[current->pmi],current->gc,x,y); } void XLine(int x1,int y1,int x2,int y2, ulong c) { FG(c); XDrawLine(display,current->pm[current->pmi],current->gc,x1,y1,x2,y2); } void SetSplineThresh(int t) { current->spline_thresh=t; } static void XDoSpline(int x0,int y0,int x1,int y1,int x2,int y2,ulong c) { int xa, ya, xb, yb, xc, yc, xp, yp; if ((x0==x1==x2)&&(y0==y1==y2)) { XPlot(x0,y0,c); return; } if ((x0==x1)&&(y0==y1)) { XLine(x1,y1,x2,y2,c); return; } if ((x0==x2)&&(y0==y2)) { XLine(x0,y0,x1,y1,c); return; } if ((x1==x2)&&(y1==y2)) { XLine(x0,y0,x2,y2,c); return; } xa = ( x0 + x1 ) / 2; ya = ( y0 + y1 ) / 2; xc = ( x1 + x2 ) / 2; yc = ( y1 + y2 ) / 2; xb = ( xa + xc ) / 2; yb = ( ya + yc ) / 2; xp = ( x0 + xb ) / 2; yp = ( y0 + yb ) / 2; if ( ABS( xa - xp ) + ABS( ya - yp ) > current->spline_thresh ) XDoSpline(x0,y0,xa,ya,xb,yb,c); else XDrawLine(display,current->pm[current->pmi],current->gc,x0,y0,xb,yb); xp = ( x2 + xb ) / 2; yp = ( y2 + yb ) / 2; if ( ABS( xc - xp ) + ABS( yc - yp ) > current->spline_thresh ) XDoSpline(xb,yb,xc,yc,x2,y2,c); else XDrawLine(display,current->pm[current->pmi],current->gc,xb,yb,x2,y2); } void XSpline(int x1,int y1,int x2,int y2,int x3,int y3,ulong c) { FG(c); if ((x1==x2==x3)&&(y1==y2==y3)) { XPlot(x1,y1,c); return; } if ((x1==x2)&&(y1==y2)) { XLine(x2,y2,x3,y3,c); return; } if ((x1==x3)&&(y1==y3)) { XLine(x1,y1,x2,y2,c); return; } if ((x2==x3)&&(y2==y3)) { XLine(x1,y1,x3,y3,c); return; } XDoSpline(x1,y1,x2,y2,x3,y3,c); } void XPrint(int x,int y, const char *s, ulong c) { FG(c); XDrawString(display,current->pm[current->pmi],current->gc,x,y,s,strlen(s)); } void Xprintf(int x, int y, ulong colour, const char *fmt, ...) { va_list va; va_start(va,fmt); vsprintf(prbuf,fmt,va); va_end(va); FG(colour); XDrawString(display,current->pm[current->pmi],current->gc, x,y,prbuf,strlen(prbuf)); } void XISetFont(XImageFont n) { switch(n) { case XI_FONT1: xifont=xifont1; break; case XI_FONT2: xifont=xifont2; break; } } static void XIPlot(XImage *img,int x,int y, ulong c) { if ((y<0)||(y>=img->height)||(x<0)||(x>=img->width)) return; XPutPixel(img,x,y,c); } void XIprintf(XImage *img, int x, int y, int sx, int sy, ulong col, const char *fmt, ...) { int f,px,py,psx,psy,ch; char *data; va_list arg; va_start(arg,fmt); vsprintf(prbuf,fmt,arg); va_end(arg); if ((sx==1)&&(sy==1)) { for(f=0;f=0)&&(y+pyheight)) for(px=0;px=0)&&(x+pxwidth)) if (xifont[ch].data[py][px]) XPutPixel(img,x+px,y+py,col); x+=XIFONTW; } } else { for(f=0;fpm[current->pmi],current->gc,x,y,w,h); } void XFillBox(int x,int y,int w,int h,ulong c) { FG(c); XFillRectangle(display,current->pm[current->pmi],current->gc,x,y,w,h); } void XCircle(int x,int y,int rx,int ry,int a1,int a2,ulong c) { FG(c); XDrawArc(display,current->pm[current->pmi],current->gc,x,y,rx,ry,a1,a2); } void XFillCircle(int x,int y,int rx,int ry,int a1,int a2,ulong c) { FG(c); XFillArc(display,current->pm[current->pmi],current->gc,x,y,rx,ry,a1,a2); } void XStartPlots(void) { no_plots=0; } void XAddPlot(int x,int y) { points[no_plots].x=x; points[no_plots].y=y; no_plots++; } void XPutPlots(ulong c) { FG(c); XDrawPoints(display,current->pm[current->pmi],current->gc, points,no_plots,CoordModeOrigin); } void XPutPlotsAsLines(ulong c) { FG(c); XDrawLines(display,current->pm[current->pmi],current->gc, points,no_plots,CoordModeOrigin); } void XFillPoly(XPoint *xp,int n,int shape,ulong c) { FG(c); XFillPolygon(display,current->pm[current->pmi],current->gc,xp,n, shape,CoordModeOrigin); } void XScroll(int dx,int dy) { int destx,desty,srcx,srcy; int w,h; if (dx>=0) { destx=0; srcx=dx; w=current->pw-dx; } if (dx<0) { destx=-(dx); srcx=0; w=current->pw+dx; } if (dy>=0) { desty=0; srcy=dy; h=current->ph-dy; } if (dy<0) { desty=-(dy); srcy=0; h=current->ph+dy; } WM(GXcopy); XCopyArea(display,current->pm[current->pmi],current->pm[current->pmi], current->gc,srcx,srcy,current->pw-dx,current->ph,destx,desty); WM(current->lastuserfunc); } void XCopy(int sx,int sy,int w,int h,int dx,int dy) { WM(GXcopy); XCopyArea(display,current->pm[current->pmi],current->pm[current->pmi], current->gc,sx,sy,current->pw,current->ph,dx,dy); WM(current->lastuserfunc); } void XPut(Pixmap spm,int sx,int sy,int w,int h,int dx,int dy) { WM(GXcopy); XCopyArea(display,spm,current->pm[current->pmi], current->gc,sx,sy,w,h,dx,dy); WM(current->lastuserfunc); } void XGet(Pixmap dpm,int sx,int sy,int w,int h,int dx,int dy) { WM(GXcopy); XCopyArea(display,dpm,current->pm[current->pmi], current->gc,sx,sy,w,h,dx,dy); WM(current->lastuserfunc); } void ScreenCopy(void) { if (current->buffer) { WM(GXcopy); XCopyArea(display,current->pm[current->pmi^1], current->pm[current->pmi],current->gc,0,0, current->pw,current->ph,0,0); WM(current->lastuserfunc); } } Display *GetDisplay(void) { return display; } void XFinished(void) { XCloseDisplay(display); } void XDoTillButtonPress(XVoidCallback func) { XEvent event; int ignore=True; while (True) if (XPending(display)) { XNextEvent(display,&event); switch (event.type) { case Expose: if (event.xexpose.count) break; Redraw(current->ox,current->oy); break; case ButtonPress: if (event.xbutton.button) if (!ignore) return; break; } } else if (func) switch (func()) { case XFUNCCONT: ignore=False; break; case XFUNCIGNORE: ignore=True; break; case XFUNCSTOP: return; break; } } void XDoMouse(XButtonCallback button, XMoveCallBack move, XVoidCallback process) { XEvent event; while (True) if ((XPending(display))||(!process)) { XNextEvent(display,&event); switch (event.type) { case Expose: if (event.xexpose.count) break; Redraw(current->ox,current->oy); break; case MotionNotify: if (move) switch(move(event.xmotion.window, event.xmotion.x,event.xmotion.y)) { case XFUNCSTOP: return; break; } break; case ButtonPress: if (button) switch(button(event.xbutton.window,XPRESS, event.xbutton.button, event.xbutton.x,event.xbutton.y)) { case XFUNCSTOP: return; break; } break; } } else if (process) switch (process()) { case XFUNCCONT: case XFUNCIGNORE: break; case XFUNCSTOP: return; break; } } static int IsMoveWin(Window w, XWindowMoveCallBack call[] ,int *i) { int f; if (!call) { return(False); } f=0; while(call[f].w) { if (call[f].w==w) { *i=f; return call[f].func ? True:False; } else { f++; } } return False; } static int IsButtonWin(Window w, XWindowButtonCallback call[] ,int *i) { int f; if (!call) { return(False); } f=0; while(call[f].w) { if (call[f].w==w) { *i=f; return call[f].func ? True:False; } else { f++; } } return False; } static int IsKeyWin(Window w, XWindowKeyCallback call[] ,int *i) { int f; if (!call) { return(False); } f=0; while(call[f].w) { if (call[f].w==w) { *i=f; return call[f].func ? True:False; } else { f++; } } return False; } void XDoWindows(XWindowButtonCallback button[], XWindowMoveCallBack move[], XWindowKeyCallback key[], XVoidCallback process) { int i; XEvent event; while (True) if ((XPending(display))||(!process)) { XNextEvent(display,&event); switch (event.type) { case Expose: if (event.xexpose.count) break; PUSHW; SetCurrentWin(event.xexpose.window); Redraw(current->ox,current->oy); POPW; break; case MotionNotify: if (IsMoveWin(event.xmotion.window,move,&i)) { switch(move[i].func(event.xmotion.window, event.xmotion.x, event.xmotion.y)) { case XFUNCSTOP: return; break; } } break; case ButtonPress: if (IsButtonWin(event.xbutton.window,button,&i)) { switch(button[i].func (event.xbutton.window, XPRESS, event.xbutton.button, event.xbutton.x,event.xbutton.y)) { case XFUNCSTOP: return; break; } } break; case ButtonRelease: if (IsButtonWin(event.xbutton.window,button,&i)) { switch(button[i].func (event.xbutton.window, XRELEASE, event.xbutton.button, event.xbutton.x,event.xbutton.y)) { case XFUNCSTOP: return; break; } } break; case KeyPress: if (IsKeyWin(event.xkey.window,key,&i)) { switch(key[i].func(event.xkey.window, XPRESS, &event)) { case XFUNCSTOP: return; break; } } break; case KeyRelease: if (IsKeyWin(event.xkey.window,key,&i)) { switch(key[i].func(event.xkey.window, XRELEASE, &event)) { case XFUNCSTOP: return; break; } } break; default: break; } } else if (process) { switch (process()) { case XFUNCCONT: case XFUNCIGNORE: break; case XFUNCSTOP: return; break; } } } /* Sprite routines */ void LoadSprite(const char *fn, XSprite *spr, const XColor xc[256]) { Pixmap piximg,pixmask,pixsave; int fd,x,y; char magic[11]; unsigned char *data,*p; unsigned short us; GC gc; if ((fd=open(fn,O_RDONLY))==-1) { WARN1("Couldn't open sprite file",fn); return; } read(fd,magic,11); if (strncmp(magic,"XbitSprite",10)) { WARN1(fn,"is not a sprite file!"); close(fd); return; } spr->x=spr->y=0; read(fd,&us,sizeof(unsigned short)); spr->w=ntohs(us); read(fd,&us,sizeof(unsigned short)); spr->h=ntohs(us); if (!(data=malloc(spr->w*spr->h))) { WARN("Couldn't grab memory for sprite image"); close(fd); return; } if (read(fd,data,spr->w*spr->h)!=spr->w*spr->h) { WARN("Couldn't load sprite image"); close(fd); free(data); return; } close(fd); gc=XCreateGC(display,current->w,0,NULL); XSetPlaneMask(display,gc,AllPlanes); XSetGraphicsExposures(display,gc,False); piximg=XCreatePixmap(display,current->w,spr->w,spr->h,vinfo.depth); pixmask=XCreatePixmap(display,current->w,spr->w,spr->h,vinfo.depth); pixsave=XCreatePixmap(display,current->w,spr->w,spr->h,vinfo.depth); p=data; for(y=0;yh;y++) { for(x=0;xw;x++) { XSetForeground(display,gc,xc[*p].pixel); XDrawPoint(display,piximg,gc,x,y); if (*p) XSetForeground(display,gc,xb_white); else XSetForeground(display,gc,xb_black); XDrawPoint(display,pixmask,gc,x,y); p++; } } spr->data=piximg; spr->mask=pixmask; spr->save=pixsave; free(data); } void XDrawSprites(XSprite *spr[],int no, XSpriteControl ctl) { int f; WM(GXcopy); if (!(ctl&XSPRNOSAVE)) for(f=0;fbuffer) { spr[f]->lx=spr[f]->x; spr[f]->ly=spr[f]->y; XCopyArea(display,current->pm[current->pmi^1], spr[f]->save,current->gc,spr[f]->x,spr[f]->y, spr[f]->w,spr[f]->h,0,0); } else { spr[f]->lx=spr[f]->x; spr[f]->ly=spr[f]->y; XCopyArea(display,current->pm[current->pmi], spr[f]->save,current->gc,spr[f]->x,spr[f]->y, spr[f]->w,spr[f]->h,0,0); } WM(GXand); for(f=0;fbuffer) XCopyArea(display,spr[f]->mask,current->pm[current->pmi^1], current->gc,0,0, spr[f]->w,spr[f]->h,spr[f]->x,spr[f]->y); else XCopyArea(display,spr[f]->mask,current->pm[current->pmi], current->gc,0,0, spr[f]->w,spr[f]->h,spr[f]->x,spr[f]->y); WM(GXor); for(f=0;fbuffer) XCopyArea(display,spr[f]->data,current->pm[current->pmi^1], current->gc,0,0, spr[f]->w,spr[f]->h,spr[f]->x,spr[f]->y); else XCopyArea(display,spr[f]->data,current->pm[current->pmi], current->gc,0,0, spr[f]->w,spr[f]->h,spr[f]->x,spr[f]->y); WM(current->lastuserfunc); } void XEraseSprites(XSprite *spr[],int no) { int f; WM(GXcopy); for(f=0;fbuffer) XCopyArea(display,spr[f]->save,current->pm[current->pmi^1], current->gc,0,0, spr[f]->w,spr[f]->h,spr[f]->lx,spr[f]->ly); else XCopyArea(display,spr[f]->save,current->pm[current->pmi], current->gc,0,0, spr[f]->w,spr[f]->h,spr[f]->lx,spr[f]->ly); WM(current->lastuserfunc); } void LoadColormap(const char *fn, XColor xc[256]) { int fd,f; unsigned short us; if ((fd=open(fn,O_RDONLY))==-1) { WARN1("Couldn't open cmap",fn); return; } for(f=0;f<256;f++) { xc[f].pixel=f; xc[f].flags=DoRed|DoGreen|DoBlue; read(fd,&us,sizeof(unsigned short)); xc[f].red=ntohs(us); read(fd,&us,sizeof(unsigned short)); xc[f].green=ntohs(us); read(fd,&us,sizeof(unsigned short)); xc[f].blue=ntohs(us); } } void AllocColors(int no,ulong pix[],const char *name[]) { int f,col; XColor xc; for(f=0;f(0x8000*3)) { WARN("defaulting to white"); pix[f]=WhitePixel(display,screen); } else { WARN("defaulting to black"); pix[f]=BlackPixel(display,screen); } } } else { WARN1("not a color ",name[f]); pix[f]=WhitePixel(display,screen); } } } void AllocColorsRGB(int no, ulong pix[], const Colour col[]) { int f; XColor xc; for(f=0;f(0x8000*3)) { WARN("defaulting to white"); pix[f]=WhitePixel(display,screen); } else { WARN("defaulting to black"); pix[f]=BlackPixel(display,screen); } } } } void LoadSpriteDataSet (const char *cmapfn, const char *sprfn[], SpriteDataSet *set) { int f,r,fd; char magic[11]; XColor xcol[256]; Colour col[256]; SpriteData *spr; int no; int used[256]; unsigned short us; unsigned char byte; /* Allocate referenced table */ for(f=0;f<256;f++) used[f]=-1; /* Count and allocate referenced sprites */ no=0; while(sprfn[no]) no++; /* Load in colourmap */ LoadColormap(cmapfn,xcol); set->no_col=0; set->no_spr=no; /* Load in sprites and sort out colour usage */ spr=malloc(sizeof(SpriteData)*no); for(f=0;fno_col].r=xcol[byte].red; col[set->no_col].g=xcol[byte].green; col[set->no_col].b=xcol[byte].blue; used[byte]=set->no_col++; } spr[f].data[r]=used[byte]; } close(fd); } /* Got all sprites - allocate and remap colours */ AllocColoursRGB(set->no_col,set->pix,col); /* Remap sprites */ for(f=0;fpix[spr[f].data[r]]; /* Set up return, all done */ set->spr=spr; } /* END OF FILE */