#include #include #include #include #include #include #include #include #include #include #include #define UNUSED_ARG(x) x __attribute__((__unused__)) #include "cards.h" #ifdef __GNUC__ #define flowsink __attribute__ ((noreturn)) #endif #if !defined(flowsink) #define flowsink #endif extern const char *__progname; #define PARK_MARGIN 15 static XrmDatabase db; static const char *defaults = "\ *Foreground: white\n\ *Background: black\n\ *BorderColor: white\n\ *BorderWidth: 1\n\ *BorderMargin: 0\n\ *Font: fixed\n\ *Name: x4x13\n\ *IconName: x4x13\n\ *DeckPath: /home/shamash/mouse/sun4/games/cards/.deck\n\ *BackNumber: 0\n\ "; static char *displayname; static char *geometryspec; static char *foreground; static char *background; static char *bordercstr; static char *borderwstr; static char *bordermstr; static char *margincstr; static char *fontname; static char *name; static char *iconname; static char *deckpath; static char *backnostr; static int argc; static char **argv; static Display *disp; static Screen *scr; static int width; static int height; static int depth; static Window rootwin; static Colormap defcmap; static Visual *visual; static int (*oldioerr)(Display *); static int (*olderr)(Display *, XErrorEvent *); static XColor fgcolor; static XColor bgcolor; static XColor bdcolor; static XColor mgcolor; typedef struct button BUTTON; typedef struct card CARD; typedef struct loc LOC; struct button { const char *label; void (*clickfn)(BUTTON *); BUTTON *flink; BUTTON *blink; void *private; Window win; int textw; int winw; XCharStruct textsize; int pressed; int disabled; } ; struct card { Window deck_win; Pixmap deck_face; int x; int y; } ; struct loc { int x; int y; int card; } ; static GC drawgc; static GC xorgc; static Window topwin; static Window iwin; static Window cwin; static Window linewin; static Window gamewin; static Window menuwin; static Colormap wincmap; static int margin; static int borderwidth; static XFontStruct *font; static int deffont; static int baselineskip; static void quit_click(BUTTON *); static void shuffle_click(BUTTON *); static void newgame_click(BUTTON *); static BUTTON newgamebutton = { "New game", newgame_click }; static BUTTON shufflebutton = { "Shuffle", shuffle_click }; static BUTTON quitbutton = { "Quit", quit_click }; static BUTTON *buttons[] = { &newgamebutton, &shufflebutton, &quitbutton }; #define NBUTTONS (sizeof(buttons)/sizeof(buttons[0])) static int button_w; static int nshuffle; static CARD cards[52]; /* static Window deck_wins[52]; static Pixmap deck_face[52]; static int c_x[52]; static int c_y[52]; */ static LOC locs[14][4]; static int parkn[4]; /* static int xy_x[14][4]; static int xy_y[14][4]; static int xy_p[14][4]; */ static XColor *deck_colors; static Pixmap *deck_back; static int b_x[4]; static int b_y[4]; static int carrycard; static int carryoffx; static int carryoffy; static int carrystartt; static int carrystartx; static int carrystarty; static int gotmotion; static BUTTON *allbuttons; static int junk_direction; static int junk_font_ascent; static int junk_font_descent; #define XTE_JUNK &junk_direction,&junk_font_ascent,&junk_font_descent #define MIN(a,b) (((a)<(b)) ? (a) : (b)) static char *deconst(const char *s) { char *rv; bcopy(&s,&rv,sizeof(char *)); return(rv); } static unsigned long int rnd(void) { #define N 63 static unsigned long int state[N]; static int h1 = -1; static int h2; if (h1 < 0) { struct timeval tv; struct stat stb; int i; stat(".",&stb); gettimeofday(&tv,0); bcopy(&stb,&state[0],MIN(sizeof(state),sizeof(stb))); for (i=0;i0;i--) { if (++h1 >= N) h1 = 0; if (++h2 >= N) h2 = 0; state[h2] += state[h1]; } } if (++h1 >= N) h1 = 0; if (++h2 >= N) h2 = 0; return(state[h2]+=state[h1]); #undef N } static void saveargv(int ac, char **av) { int i; int nc; char *abuf; argc = ac; argv = (char **) malloc((ac+1)*sizeof(char *)); nc = 1; for (i=0;i 0) { skip --; continue; } if (**av != '-') { fprintf(stderr,"%s: unrecognized argument `%s'\n",__progname,*av); errs ++; continue; } if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",__progname,*av); errs ++; continue; } #define WANTARG() do { if (++skip >= ac) goto needarg; } while (0) if (!strcmp(*av,"-display")) { WANTARG(); displayname = av[skip]; continue; } if (!strcmp(*av,"-geometry")) { WANTARG(); geometryspec = av[skip]; continue; } if (!strcmp(*av,"-foreground") || !strcmp(*av,"-fg")) { WANTARG(); foreground = av[skip]; continue; } if (!strcmp(*av,"-background") || !strcmp(*av,"-bg")) { WANTARG(); background = av[skip]; continue; } if (!strcmp(*av,"-bordercolor") || !strcmp(*av,"-bd")) { WANTARG(); bordercstr = av[skip]; continue; } if (!strcmp(*av,"-borderwidth") || !strcmp(*av,"-bw")) { WANTARG(); borderwstr = av[skip]; continue; } if (!strcmp(*av,"-bordermargin") || !strcmp(*av,"-bm")) { WANTARG(); bordermstr = av[skip]; continue; } if (!strcmp(*av,"-margincolor") || !strcmp(*av,"-mc")) { WANTARG(); margincstr = av[skip]; continue; } if (!strcmp(*av,"-name")) { WANTARG(); name = av[skip]; continue; } if (!strcmp(*av,"-iconname")) { WANTARG(); iconname = av[skip]; continue; } if (!strcmp(*av,"-font") || !strcmp(*av,"-fn")) { WANTARG(); fontname = av[skip]; continue; } if (!strcmp(*av,"-deck")) { WANTARG(); deckpath = av[skip]; continue; } if (!strcmp(*av,"-back")) { WANTARG(); backnostr = av[skip]; continue; } #undef WANTARG fprintf(stderr,"%s: unrecognized option `%s'\n",__progname,*av); errs ++; } if (errs) { exit(1); } } static void maybeset(char **strp, char *str) { if (str && !*strp) *strp = str; } static void initbutton(BUTTON *b) { XTextExtents(font,b->label,strlen(b->label),XTE_JUNK,&b->textsize); b->textw = b->textsize.rbearing - b->textsize.lbearing; b->winw = b->textw; b->pressed = 0; b->flink = allbuttons; b->blink = 0; if (b->flink) b->flink->blink = b; allbuttons = b; } static void makebuttonwindow(BUTTON *b, Window parent) { unsigned long int attrmask; XSetWindowAttributes attr; attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask; attrmask |= CWEventMask; b->win = XCreateWindow(disp,parent,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,b->win); } static void setbuttonenable(BUTTON *b, int enb) { b->disabled = ! enb; if (enb) XMapWindow(disp,b->win); else XUnmapWindow(disp,b->win); } static void setup_db(void) { char *str; char *home; XrmDatabase db2; db = XrmGetStringDatabase(defaults); str = XResourceManagerString(disp); if (str) { db2 = XrmGetStringDatabase(str); XrmMergeDatabases(db2,&db); } else { home = getenv("HOME"); if (home) { str = malloc(strlen(home)+1+10+1); sprintf(str,"%s/.Xdefaults",home); db2 = XrmGetFileDatabase(str); if (db2) { XrmMergeDatabases(db2,&db); } free(str); } } } static char *get_default_value(const char *name, const char *class) { char *type; XrmValue value; if (XrmGetResource(db,name,class,&type,&value) == False) return(0); return(value.addr); } static Pixmap pmsetup( unsigned char bmc[CARD_YSIZE][CARD_XSIZE], unsigned char bmbw[CARD_YSIZE][CARD_BW_XBYTES] ) { Pixmap rv; if (depth == 1) { static XImage *i = 0; static unsigned char buf[((CARD_XSIZE+7)>>3)*CARD_YSIZE]; #if CARD_BW_XBYTES != ((CARD_XSIZE+7)>>3) #error CARD_BW_XBYTES and CARD_XSIZE disagree #endif static GC gc; int x; int y; int n; int acc; unsigned char *bp; if (i == 0) { i = XCreateImage(disp,visual,1,XYBitmap,0,(char *)&buf[0],CARD_XSIZE,CARD_YSIZE,8,(CARD_XSIZE+7)>>3); i->bitmap_unit = 8; i->bitmap_bit_order = MSBFirst; rv = XCreatePixmap(disp,rootwin,1,1,1); gc = XCreateGC(disp,rv,0L,(XGCValues *)0); XSetBackground(disp,gc,0L); XSetForeground(disp,gc,1L); XFreePixmap(disp,rv); } rv = XCreatePixmap(disp,rootwin,CARD_XSIZE,CARD_YSIZE,1); if (bmbw) { bcopy((char *)&bmbw[0][0],(char *)&buf[0],CARD_YSIZE*CARD_BW_XBYTES); } else { acc = 0; bp = &buf[0]; for (y=0;y 7) { *bp++ = acc; n = 0; } acc <<= 1; if (deck_colors[bmc[y][x]].pixel) acc |= 1; n ++; } if (n > 0) { *bp++ = acc << (8 - n); } } } XPutImage(disp,rv,gc,i,0,0,0,0,CARD_XSIZE,CARD_YSIZE); } else if (depth == 8) { static XImage *i = 0; static unsigned char buf[CARD_YSIZE*CARD_XSIZE]; static GC gc; int x; int y; unsigned char *bp; if (i == 0) { i = XCreateImage(disp,visual,8,ZPixmap,0,(char *)&buf[0],CARD_XSIZE,CARD_YSIZE,8,CARD_XSIZE); i->bitmap_unit = 8; rv = XCreatePixmap(disp,rootwin,1,1,8); gc = XCreateGC(disp,rv,0L,(XGCValues *)0); XFreePixmap(disp,rv); } bp = &buf[0]; for (y=0;y>3)*CARD_YSIZE]; static GC gc1; static GC gcn; static Pixmap tmp; int x; int y; int n; int acc; int m; int c; unsigned char *bp; if (i == 0) { i = XCreateImage(disp,visual,1,XYBitmap,0,(char *)&buf[0],CARD_XSIZE,CARD_YSIZE,8,(CARD_XSIZE+7)>>3); i->bitmap_unit = 8; i->bitmap_bit_order = MSBFirst; tmp = XCreatePixmap(disp,rootwin,CARD_XSIZE,CARD_YSIZE,1); gc1 = XCreateGC(disp,tmp,0L,(XGCValues *)0); XSetBackground(disp,gc1,0L); XSetForeground(disp,gc1,1L); rv = XCreatePixmap(disp,rootwin,1,1,depth); gcn = XCreateGC(disp,rv,0L,(XGCValues *)0); XSetBackground(disp,gcn,0L); XFreePixmap(disp,rv); } rv = XCreatePixmap(disp,rootwin,CARD_XSIZE,CARD_YSIZE,depth); XSetForeground(disp,gcn,0L); XSetFunction(disp,gcn,GXcopy); XFillRectangle(disp,rv,gcn,0,0,CARD_XSIZE,CARD_YSIZE); XSetFunction(disp,gcn,GXor); for (c=0;c 7) { *bp++ = acc; n = 0; } acc <<= 1; if (bmc[y][x] == c) { acc |= 1; m ++; } n ++; } if (n > 0) { *bp++ = acc << (8 - n); } } if (m > 0) { XPutImage(disp,tmp,gc1,i,0,0,0,0,CARD_XSIZE,CARD_YSIZE); XSetForeground(disp,gcn,deck_colors[c].pixel); XCopyPlane(disp,tmp,rv,gcn,0,0,CARD_XSIZE,CARD_YSIZE,0,0,1L); } } } return(rv); } static void get_face(int n) { if (cards[n].deck_face != None) return; cards[n].deck_face = pmsetup(card_cards_color[n],card_cards_bw[n]); } static void setup_xcolor(XColor *col, const char *what) { while (1) { if (XAllocColor(disp,wincmap,col) == 0) { if (wincmap != defcmap) { fprintf(stderr,"%s: can't allocate colormap cell for color %s\n",__progname,what); exit(1); } wincmap = XCopyColormapAndFree(disp,wincmap); continue; } break; } } static void setup_color(char *str, XColor *col) { if (XParseColor(disp,wincmap,str,col) == 0) { fprintf(stderr,"%s: bad color `%s'\n",__progname,str); exit(1); } setup_xcolor(col,str); } static void setup_deck(void) { int i; if (card_loaddeck(deckpath) < 0) { perror(deckpath); exit(1); } deck_colors = (XColor *) malloc(card_ncol*sizeof(XColor)); for (i=0;i<52;i++) cards[i].deck_face = None; deck_back = (Pixmap *) malloc(card_nbacks*sizeof(Pixmap)); for (i=0;iascent + font->descent; } static void setup_colors(void) { int i; wincmap = defcmap; setup_color(foreground,&fgcolor); setup_color(background,&bgcolor); setup_color(bordercstr,&bdcolor); setup_color(margincstr,&mgcolor); for (i=0;itextw; } } static void resize(int topw, int toph) { int x; int y; int vm; int hm; int dx; int dy; int i; vm = toph - baselineskip - borderwidth - (CARD_YSIZE * 4); y = 0; dy = vm / 4; y += dy; vm -= dy; hm = topw - button_w; XMoveResizeWindow(disp,menuwin,0,y,topw,baselineskip); x = 0; for (i=0;iwin,x,0,buttons[i]->winw,baselineskip); x += buttons[i]->winw; } y += baselineskip; dy = vm / 3; y += dy; vm -= dy; XMoveResizeWindow(disp,linewin,0,y,topw,borderwidth); y += borderwidth; dy = vm / 2; y += dy; vm -= dy; x = (topw - (CARD_XSIZE * 14) - PARK_MARGIN) / 2; XMoveWindow(disp,gamewin,x,y); } static void setup_windows(void) { int i; int x; int y; int w; int h; int bits; unsigned long int attrmask; XSetWindowAttributes attr; XTextProperty wn_prop; XTextProperty in_prop; XSizeHints normal_hints; XWMHints wm_hints; XClassHint class_hints; w = borderwidth + margin + (CARD_XSIZE * 14) + PARK_MARGIN + margin + borderwidth; h = borderwidth + margin + baselineskip + margin + borderwidth + margin + (CARD_YSIZE * 4) + margin + borderwidth; x = (width - w) / 2; y = (height - h) / 2; bits = XParseGeometry(geometryspec,&x,&y,&w,&h); if (bits & XNegative) x = width + x - w; if (bits & YNegative) y = height + y - h; attrmask = 0; attr.background_pixel = mgcolor.pixel; attrmask |= CWBackPixel; attr.border_pixel = bdcolor.pixel; attrmask |= CWBorderPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = StructureNotifyMask; attrmask |= CWEventMask; w -= 2 * borderwidth; h -= 2 * borderwidth; topwin = XCreateWindow(disp,rootwin,x,y,w,h,borderwidth,depth,InputOutput,CopyFromParent,attrmask,&attr); wn_prop.value = (unsigned char *) name; wn_prop.encoding = XA_STRING; wn_prop.format = 8; wn_prop.nitems = strlen((char *)wn_prop.value); in_prop.value = (unsigned char *) iconname; in_prop.encoding = XA_STRING; in_prop.format = 8; in_prop.nitems = strlen((char *)in_prop.value); normal_hints.flags = PMinSize | PResizeInc; normal_hints.x = x; normal_hints.y = y; normal_hints.flags |= (bits & (XValue|YValue)) ? USPosition : PPosition; normal_hints.width = w; normal_hints.height = h; normal_hints.flags |= (bits & (WidthValue|HeightValue)) ? USSize : PSize; normal_hints.min_width = 1; normal_hints.min_height = 1; normal_hints.width_inc = 1; normal_hints.height_inc = 1; wm_hints.flags = InputHint; wm_hints.input = True; class_hints.res_name = deconst("x4x13"); class_hints.res_class = deconst("XCardGame"); XSetWMProperties(disp,topwin,&wn_prop,&in_prop,argv,argc,&normal_hints,&wm_hints,&class_hints); if (wincmap != defcmap) XSetWindowColormap(disp,topwin,wincmap); attrmask = 0; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = 0; attrmask |= CWEventMask; gamewin = XCreateWindow(disp,topwin,0,0,(CARD_XSIZE*14)+PARK_MARGIN,CARD_YSIZE*4,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,gamewin); attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = 0; attrmask |= CWEventMask; menuwin = XCreateWindow(disp,topwin,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,menuwin); for (i=0;ifid); } } XSetForeground(disp,drawgc,fgcolor.pixel); XSetBackground(disp,drawgc,bgcolor.pixel); xorgc = XCreateGC(disp,topwin,0L,(XGCValues *)0); XSetFunction(disp,xorgc,GXxor); XSetForeground(disp,xorgc,fgcolor.pixel^bgcolor.pixel); XRaiseWindow(disp,iwin); XMapRaised(disp,topwin); resize(w,h); } static void movecardwindow(int c) { int x; int y; x = cards[c].x * CARD_XSIZE; y = cards[c].y * CARD_YSIZE; if (cards[c].x >= parkn[cards[c].y]) x += PARK_MARGIN; XMoveWindow(disp,cards[c].deck_win,x,y); } static void setup_game(void) { int i; int j; int c; char left[52]; for (i=0;i<52;i++) left[i] = i; for (i=0;i<14;i++) for (j=0;j<4;j++) { locs[i][j].x = i; locs[i][j].y = j; locs[i][j].card = -1; } for (i=0;i<4;i++) parkn[i] = 0; for (i=51;i>=0;i--) { j = rnd() % (i+1); c = left[j]; if (j < i) left[j] = left[i]; cards[c].x = (i % 13) + 1; cards[c].y = i / 13; locs[cards[c].x][cards[c].y].card = c; movecardwindow(c); } for (i=0;i<4;i++) { b_x[i] = 0; b_y[i] = i; } carrycard = -1; nshuffle = 0; setbuttonenable(&shufflebutton,1); } static void move(void) { Window root; Window child; int rootx; int rooty; int x; int y; unsigned int mask; if (carrycard < 0) return; if (XQueryPointer(disp,gamewin,&root,&child,&rootx,&rooty,&x,&y,&mask) == False) return; if (x < 0) x = 0; else if (x >= CARD_XSIZE*14) x = (CARD_XSIZE * 14) - 1; if (y < 0) y = 0; else if (y >= CARD_YSIZE*4) y = (CARD_YSIZE * 4) - 1; XMoveWindow(disp,cards[carrycard].deck_win,x-carryoffx,y-carryoffy); } static void redrawbutton(BUTTON *b) { XClearArea(disp,b->win,0,0,b->winw,baselineskip,False); XDrawString(disp,(Drawable)b->win,drawgc,((b->winw-b->textw)/2)-b->textsize.lbearing,font->ascent,b->label,strlen(b->label)); if (b->pressed) XFillRectangle(disp,(Drawable)b->win,xorgc,0,0,b->winw,baselineskip); } static void doexpose(Window win, UNUSED_ARG(int x), UNUSED_ARG(int y), UNUSED_ARG(int w), UNUSED_ARG(int h), int count) { BUTTON *b; if (count != 0) return; for (b=allbuttons;b;b=b->flink) { if (win == b->win) { redrawbutton(b); return; } } } static void push(int x, int y, Time when, int downp) { if (carrycard < 0) { if (downp) { int i; int ix; carrystartt = when; carrystartx = x; carrystarty = y; carryoffy = y % CARD_YSIZE; y /= CARD_YSIZE; if ((y < 0) || (y > 3)) return; for (i=0;i<14;i++) { ix = i * CARD_XSIZE; if (i >= parkn[y]) ix += PARK_MARGIN; if ((x >= ix) && (x < ix+CARD_XSIZE)) { carryoffx = x - ix; carrycard = locs[i][y].card; if (carrycard >= 0) XRaiseWindow(disp,cards[carrycard].deck_win); if (parkn[y] > i) { x = parkn[y] - 1; parkn[y] = i; for (;x>i;x--) movecardwindow(locs[x][y].card); } return; } } } } else { int i; int dx; int dy; int ok[4]; int okd[4]; int nok; int bx; int by; int c; if (! downp) { if (when-carrystartt < 200) return; dx = x - carrystartx; dy = y - carrystarty; if ( (abs(dx) < (CARD_XSIZE/6)) && (abs(dy) < (CARD_YSIZE/6)) && (when-carrystartt < 1000) ) return; } x -= carryoffx; y -= carryoffy; nok = 0; for (i=0;i<4;i++) { dx = x - (b_x[i] * CARD_XSIZE); dy = y - (b_y[i] * CARD_YSIZE); if ((abs(dx) >= CARD_XSIZE) || (abs(dy) >= CARD_YSIZE)) { ok[i] = 0; } else if (b_x[i] == 0) { ok[i] = (CARD_VALUE(carrycard) == CARD_A); } else { int c; c = locs[b_x[i]-1][b_y[i]].card; if ((c < 0) || (CARD_VALUE(c) == CARD_K)) { ok[i] = 0; } else { ok[i] = (CARD_VALUE(c)+1 == CARD_VALUE(carrycard)); } } if (ok[i]) { nok ++; okd[i] = (dx * dx) + (dy * dy); } } if (nok > 0) { int best; best = -1; for (i=0;i<4;i++) { if (ok[i]) { if ((best < 0) || (okd[i] < okd[best])) best = i; } } bx = b_x[best]; by = b_y[best]; b_x[best] = cards[carrycard].x; b_y[best] = cards[carrycard].y; locs[cards[carrycard].x][cards[carrycard].y].card = -1; cards[carrycard].x = bx; cards[carrycard].y = by; locs[bx][by].card = carrycard; } else { bx = cards[carrycard].x; by = cards[carrycard].y; } c = carrycard; if ( (bx == parkn[by]) && ( (bx == 0) || (locs[bx-1][by].card == CARD_MAKE(CARD_SUIT(c),CARD_VALUE(c)-1)) ) ) { parkn[by] ++; while (bx < 12) { c = CARD_MAKE(CARD_SUIT(c),CARD_VALUE(c)+1); bx ++; if (locs[bx][by].card != c) break; parkn[by] ++; movecardwindow(c); } } movecardwindow(carrycard); carrycard = -1; } } static void buttonbutton(BUTTON *b, UNUSED_ARG(int bno), int downp) { if (b->disabled) return; if (downp) { b->pressed = 1; redrawbutton(b); } else { if (b->pressed) { b->pressed = 0; (*b->clickfn)(b); redrawbutton(b); } } } static void buttonevent(Window win, int x, int y, int button, Time time, int downp) { BUTTON *b; if (win == iwin) { push(x,y,time,downp); return; } for (b=allbuttons;b;b=b->flink) { if (win == b->win) { buttonbutton(b,button,downp); return; } } } static void buttonleave(BUTTON *b) { if (b->pressed) { b->pressed = 0; redrawbutton(b); } } static void enterleave(Window win, UNUSED_ARG(int x), UNUSED_ARG(int y), int enterp) { BUTTON *b; if (enterp) return; for (b=allbuttons;b;b=b->flink) { if (win == b->win) { buttonleave(b); return; } } } static void handle_event(XEvent *e) { switch (e->type) { default: break; case ConfigureNotify: /* XConfigureEvent - xconfigure */ resize(e->xconfigure.width,e->xconfigure.height); break; case Expose: /* XExposeEvent - xexpose */ doexpose(e->xexpose.window,e->xexpose.x,e->xexpose.y,e->xexpose.width,e->xexpose.height,e->xexpose.count); break; case ButtonPress: /* XButtonPressedEvent - XButtonEvent - xbutton */ buttonevent(e->xbutton.window,e->xmotion.x,e->xmotion.y,e->xbutton.button,e->xbutton.time,1); break; case ButtonRelease: /* XButtonPressedEvent - XButtonEvent - xbutton */ buttonevent(e->xbutton.window,e->xmotion.x,e->xmotion.y,e->xbutton.button,e->xbutton.time,0); break; case MotionNotify: /* XMotionEvent - xmotion */ gotmotion = 1; break; case EnterNotify: /* XEnterWindowEvent - XCrossingEvent - xcrossing */ enterleave(e->xcrossing.window,e->xcrossing.x,e->xcrossing.y,1); break; case LeaveNotify: /* XLeaveWindowEvent - XCrossingEvent - xcrossing */ enterleave(e->xcrossing.window,e->xcrossing.x,e->xcrossing.y,0); break; } } static void run(void) flowsink; static void run(void) { XEvent e; gotmotion = 0; while (1) { if (gotmotion && (XEventsQueued(disp,QueuedAfterReading) == 0)) { gotmotion = 0; move(); } XNextEvent(disp,&e); handle_event(&e); } } static void quit_click(UNUSED_ARG(BUTTON *b)) { exit(0); } static void shuffle_click(UNUSED_ARG(BUTTON *b)) { int i; int c; int x; int y; int ncl; char clist[52]; if (nshuffle >= 2) { setbuttonenable(&shufflebutton,0); return; } carrycard = -1; ncl = 0; for (y=0;y<4;y++) { for (x=parkn[y];x<14;x++) { if (locs[x][y].card >= 0) { clist[ncl++] = locs[x][y].card; locs[x][y].card = -1; } } } for (i=0;i= 2) setbuttonenable(&shufflebutton,0); } static void newgame_click(UNUSED_ARG(BUTTON *b)) { setup_game(); } static Display *open_display(char *disp) { Display *rv; rv = XOpenDisplay(disp); if (rv == 0) { fprintf(stderr,"%s: can't open display %s\n",__progname,XDisplayName(disp)); exit(1); } return(rv); } static int ioerr(Display *d) { return((*oldioerr)(d)); } static int err(Display *d, XErrorEvent *e) { return((*olderr)(d,e)); } int main(int, char **); int main(int ac, char **av) { saveargv(ac,av); handleargs(ac,av); disp = open_display(displayname); oldioerr = XSetIOErrorHandler(ioerr); olderr = XSetErrorHandler(err); scr = XDefaultScreenOfDisplay(disp); width = XWidthOfScreen(scr); height = XHeightOfScreen(scr); depth = XDefaultDepthOfScreen(scr); rootwin = XRootWindowOfScreen(scr); defcmap = XDefaultColormapOfScreen(scr); visual = XDefaultVisualOfScreen(scr); setup_db(); maybeset(&geometryspec,get_default_value("x4x13.geometry","XCardGame.Geometry")); maybeset(&fontname,get_default_value("x4x13.font","XCardGame.Font")); maybeset(&foreground,get_default_value("x4x13.foreground","XCardGame.Foreground")); maybeset(&background,get_default_value("x4x13.background","XCardGame.Background")); maybeset(&bordercstr,get_default_value("x4x13.borderColor","XCardGame.BorderColor")); maybeset(&borderwstr,get_default_value("x4x13.borderWidth","XCardGame.BorderWidth")); maybeset(&bordermstr,get_default_value("x4x13.borderMargin","XCardGame.BorderMargin")); maybeset(&margincstr,get_default_value("x4x13.marginColor","XCardGame.Background")); maybeset(&name,get_default_value("x4x13.name","XCardGame.Name")); maybeset(&iconname,get_default_value("x4x13.iconName","XCardGame.IconName")); maybeset(&deckpath,get_default_value("x4x13.deckPath","XCardGame.DeckPath")); maybeset(&backnostr,get_default_value("x4x13.backNumber","XCardGame.BackNumber")); setup_deck(); setup_font(); setup_colors(); setup_numbers(); setup_buttons(); setup_windows(); setup_game(); run(); }