#define SPACING 2 #define BUTTON_BORDER 1 #define BUTTON_MARGIN 2 #define EDIT_SPACING 5 #define EDIT_BORDER 2 #define DIALOG_BORDER 1 #define DIALOG_MARGIN 2 #define MAXLNLEN 64 #include #include #include #include #include #include #include #include #include #include #include #include #define NEW(t) ((t *)malloc(sizeof(t))) #define OLD(v) free((char *)(v)) #include "blockade.h" #include "blockade-pix.h" #include "blockade-lev.h" #include "blockade-info.h" #include "blockade-snd.h" char **argvec; XrmDatabase db; char *defaults = "\ *Background: black\n\ *Foreground: white\n\ *BorderColor: white\n\ *BorderWidth: 1\n\ *Name: xblockade\n\ *IconName: blockade\n\ "; char *displayname; char *geometryspec; char *background; char *foreground; char *bordercstr; char *borderwstr; char *name; char *iconname; char *fontname; char *selkey; int bw_flag; int no_deflev; int new_flag; int syncX; char *levelstr; int argc; char **argv; Display *disp; Screen *scr; int width; int height; int depth; Window rootwin; Colormap defcmap; Visual *visual; GC defgc; int bw_mode; XColor fgcolor; XColor bgcolor; XColor bdcolor; XColor blackcolor; XColor whitecolor; XColor colors[B_NCOLORS]; GC wingc; XGCValues winshadow; Window topwin; Window gamewin; Window line1win; Window line2win; Window textwin; Window textpanelwin; Window creditwin; Window helpwin; Window helppanelwin; Window helpwins[N_HELP]; Window levprompt_win; Window msgwin; Window editwin; Window g_buttonwin; Window e_buttonwin; Window g_buttonwin_s; Window g_buttonwin_no_s; Colormap wincmap; Pixmap gray50; int topw; int toph; int gamew; int gameh; int gamey; int textw; int texth; int borderwidth; XFontStruct *font; XCharStruct maxdigitsize; int deffont; Font fontid; char *levprompt_buf = 0; int levprompt_fill; int levprompt_len; int levprompt_w; int levprompt_h; int levprompt_xoff; int levprompt_xclr; char *levprompt_prompt = "Level: "; char msg_buf[256]; int msg_len; int msg_w; int msg_h; int editw; int edith; int button_h; int buttoncb_help(); int buttoncb_credits(); int buttoncb_edit(); int buttoncb_quit(); int buttoncb_save(); BUTTON buttons_no_s[] = { { "Help", buttoncb_help }, { "Credits", buttoncb_credits }, { "Edit", buttoncb_edit }, { "Quit", buttoncb_quit } }; #define NBUTTONS_NO_S (sizeof(buttons_no_s)/sizeof(buttons_no_s[0])) BUTTON buttons_s[] = { { "Help", buttoncb_help }, { "Credits", buttoncb_credits }, { "Edit", buttoncb_edit }, { "Save", buttoncb_save }, { "Quit", buttoncb_quit } }; #define NBUTTONS_S (sizeof(buttons_s)/sizeof(buttons_s[0])) int buttoncb_e_junk(); int buttoncb_e_revert(); int buttoncb_e_abort(); int buttoncb_e_done(); int buttoncb_e_name(); int buttoncb_e_clone(); BUTTON edit_buttons[] = { { "Junk level", buttoncb_e_junk }, { "Revert", buttoncb_e_revert }, { "Abort", buttoncb_e_abort }, { "Done", buttoncb_e_done }, { "Name", buttoncb_e_name }, { "Clone", buttoncb_e_clone } }; #define NEDITBUTTONS (sizeof(edit_buttons)/sizeof(edit_buttons[0])) extern int help_button_h; int buttoncb_help1(); int buttoncb_help2(); int buttoncb_help3(); int buttoncb_help4(); int buttoncb_help5(); int buttoncb_helpret(); BUTTON help_buttons[] = { { (char *)&help_button_bits[1], buttoncb_help1 }, { (char *)&help_button_bits[2], buttoncb_help2 }, { (char *)&help_button_bits[3], buttoncb_help3 }, { (char *)&help_button_bits[4], buttoncb_help4 }, { (char *)&help_button_bits[5], buttoncb_help5 }, { (char *)&help_button_bits[0], buttoncb_helpret } }; #define NHELPBUTTONS (sizeof(help_buttons)/sizeof(help_buttons[0])) struct argfile_ { char *filename; struct argfile_ *link; } ; typedef struct argfile_ ARGFILE; ARGFILE *argfiles; ARGFILE **argfile_tail = &argfiles; LEVEL_SEG *level_segs; LEVEL_SEG **level_segs_tail = &level_segs; int maxlevelno; Pixmap pic_blank; Pixmap pic_s_b; Pixmap pic_s_y; Pixmap pic_r_b; Pixmap pic_r_y; Pixmap pic_d_b; Pixmap pic_d_y; Pixmap pic_p_b; Pixmap pic_p_y; Pixmap pic_color_b; Pixmap pic_color_y; Pixmap pic_color_flip; Pixmap pic_wall; Pixmap pic_mwall; Pixmap pic_teleport; Pixmap pic_mutate; Pixmap pic_player; Pixmap pic_stars[PIC_NSTARS]; Pixmap *pic_ptrs[B_NPIX]; char squaretype[BOARD_X][BOARD_Y]; #define SQ_BLANK 1 #define SQ_COLOR_B 2 #define SQ_COLOR_Y 3 #define SQ_COLOR_F 4 #define SQ_WALL 5 #define SQ_TELEPORT 6 #define SQ_MUTATE 7 #define SQ_STARS 8 char startype[BOARD_X][BOARD_Y]; /* used only when squaretype[][] == SQ_STARS */ char blocktype[BOARD_X][BOARD_Y]; #define BLK_COLOR 0x01 #define BLK_COLOR_B 0x00 #define BLK_COLOR_Y 0x01 #define BLK_SHAPE 0x0e #define BLK_SHAPE_S 0x02 #define BLK_SHAPE_R 0x04 #define BLK_SHAPE_P 0x06 #define BLK_SHAPE_D 0x08 #define BLK_SHAPE_W 0x0a /* BLK_COLOR bit ignored */ #define BLK_NONE 0 int player_x; int player_y; char save_blocktype[BOARD_X][BOARD_Y]; int save_player_x; int save_player_y; char sqdamaged[BOARD_X][BOARD_Y]; char init_blocktype[BOARD_X][BOARD_Y]; int init_player_x; int init_player_y; int curlevelno; LEVEL *curlevel; char lnbuf[MAXLNLEN+1]; int lnfill; char *levelname = ""; int levelname_len = 0; int dispstate; #define DS_GAME 0 #define DS_CREDITS 1 #define DS_HELP 2 #define DS_ASKLEVEL 3 #define DS_MSG 4 #define DS_EDIT 5 #define DS_LEVNAME 6 int helpscreen = 1; int edit_damaged[B_NPIX]; int editcurs_x; int editcurs_y; int edit_curpic = 0; #define EDIT_MX (EDIT_BORDER + PIC_W + EDIT_BORDER + EDIT_SPACING) #define EDIT_MY (EDIT_BORDER + PIC_H + EDIT_BORDER + EDIT_SPACING) #define EDIT_NCOLS (((PIC_W * BOARD_X) - EDIT_SPACING) / EDIT_MX) #define EDIT_NROWS ((B_NPIX + EDIT_NCOLS - 1) / EDIT_NCOLS) int junk_direction; int junk_ascent; int junk_descent; #define XTE_JUNK &junk_direction,&junk_ascent,&junk_descent /********************************************************************/ /********************************************************************/ /********************************************************************/ void bugchk(char *fmt, ...) { va_list ap; fprintf(stderr,"INTERNAL ERROR: "); va_start(ap, fmt); vfprintf(stderr,fmt,ap); va_end(ap); fprintf(stderr,"\n"); abort(); } 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;ilink; af->filename = fn; } void handleargs(int ac,char **av) { int skip; int errs; skip = 0; errs = 0; for (ac--,av++;ac;ac--,av++) { if (skip > 0) { skip --; continue; } if (**av != '-') { addargfile(*av); continue; } if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",argvec[0],*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,"-background") || !strcmp(*av,"-bg")) { WANTARG(); background = av[skip]; continue; } if (!strcmp(*av,"-foreground") || !strcmp(*av,"-fg")) { WANTARG(); foreground = 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,"-name")) { WANTARG(); name = av[skip]; continue; } if (!strcmp(*av,"-iconname")) { WANTARG(); iconname = av[skip]; continue; } if (!strcmp(*av,"-selkey")) { WANTARG(); selkey = av[skip]; continue; } if (!strcmp(*av,"-font") || !strcmp(*av,"-fn")) { WANTARG(); fontname = av[skip]; continue; } if (!strcmp(*av,"-level")) { WANTARG(); levelstr = av[skip]; continue; } if (!strcmp(*av,"-file")) { WANTARG(); addargfile(av[skip]); continue; } if (!strcmp(*av,"-bwmode")) { bw_flag = 1; continue; } if (!strcmp(*av,"-sync")) { syncX = 1; continue; } if (!strcmp(*av,"-nodeflev") || !strcmp(*av,"-nostdlev")) { no_deflev = 1; continue; } if (!strcmp(*av,"-new")) { new_flag = 1; continue; } #undef WANTARG fprintf(stderr,"%s: unrecognized option `%s'\n",argvec[0],*av); errs ++; } if (errs) { exit(1); } } #define MAXDIST 1000 int strdist(char *s1,char *s2) { int n1; int n2; char c1; char c2; int d; d = 0; while (1) { n1 = 0; for (;*s1&&!isalpha(*s1);s1++) n1 ++; n2 = 0; for (;*s2&&!isalpha(*s2);s2++) n2 ++; d += abs(n1-n2); c1 = *s1; c2 = *s2; if (!c1 && !c2) return(d); if (c1 != c2) d ++; if (c1) s1 ++; if (c2) s2 ++; } } void setlevel(char *s) { int alldigits; char *cp; int bestdist; int d; LEVEL_SEG *ls; int i; if (*s == '\0') { curlevelno = 0; return; } alldigits = 1; for (cp=s;*cp;cp++) { if (! isdigit(*cp)) { alldigits = 0; break; } } if (alldigits) { curlevelno = atoi(s); } else { curlevelno = 0; bestdist = MAXDIST + 1; for (ls=level_segs;ls;ls=ls->link) { for (i=0;inum;i++) { d = strdist(s,ls->levels[i]->name); if (d < bestdist) { bestdist = d; curlevelno = ls->first + i; } } } } } void maybeset(char **strp,char *str) { if (str && !*strp) *strp = str; } LEVEL *fread_level(f) FILE *f; { static LEVEL *l = 0; int namelen; int i; int c; int x; int y; if (0) { fail:; return(0); } if (l == 0) { l = NEW(LEVEL); l->name = 0; } if (l->name) { free(l->name); l->name = 0; } if (fscanf(f,"%d",&namelen) != 1) goto fail; l->name = malloc(namelen); do { c = getc(f); if (c == EOF) goto fail; } while (isspace(c)); /* ignore errors in this next loop; eof/error gets noticed shortly */ for (i=0;iname[i] = getc(f); l->namelen = namelen; for (y=0;ylayout[y][x] = c; } } { LEVEL *rv; rv = l; l = 0; return(rv); } } int read_level_file(fn,levvp) char *fn; LEVEL ***levvp; { struct level_list_ { struct level_list_ *link; LEVEL *level; } ; typedef struct level_list_ LEVEL_LIST; LEVEL_LIST *levs; LEVEL_LIST **levtail; LEVEL_LIST *ll; int nlevs; LEVEL *lev; FILE *f; int i; f = fopen(fn,"r"); if (f == 0) { if (new_flag) { int x; int y; newlevelfile:; nlevs = 1; lev = NEW(LEVEL); *levvp = (LEVEL **) malloc(sizeof(LEVEL *)); **levvp = lev; lev->namelen = 8; lev->name = malloc(8); bcopy("Untitled",lev->name,8); for (y=0;ylayout[y][x] = PIC_BLANK; } } lev->layout[0][0] = PIC_PLAYER; lev->layout[0][1] = PIC_S_B; lev->layout[0][2] = PIC_S_Y; return(-1); } else { fprintf(stderr,"%s: can't read %s\n",argvec[0],fn); return(0); } } levtail = &levs; nlevs = 0; while ((lev=fread_level(f))!=0) { ll = NEW(LEVEL_LIST); *levtail = ll; levtail = &ll->link; ll->level = lev; nlevs ++; } fclose(f); *levtail = 0; *levvp = (LEVEL **) malloc(nlevs*sizeof(LEVEL *)); for (i=0,ll=levs;ilink) levvp[0][i] = ll->level; while (levs) { ll = levs; levs = ll->link; OLD(ll); } if ((nlevs == 0) && new_flag) goto newlevelfile; return(nlevs); } void setup_levels(void) { LEVEL_SEG *ls; ARGFILE *af; int lastlevel; int i; if (! no_deflev) { ls = NEW(LEVEL_SEG); *level_segs_tail = ls; level_segs_tail = &ls->link; ls->first = 1; ls->num = N_DEF_LEVELS; ls->last = N_DEF_LEVELS; ls->source = 0; ls->levels = (LEVEL **) malloc(N_DEF_LEVELS*sizeof(LEVEL *)); ls->levels[0] = (LEVEL *) malloc(N_DEF_LEVELS*sizeof(LEVEL)); ls->dirty = 0; for (i=1;ilevels[i] = ls->levels[0] + i; for (i=0;ilevels[i]; l->levelno = i + 1; l->seg = ls; l->name = b_l_builtin[i].name; bcopy((char *)/*&*/b_l_builtin[i].layout,(char *)/*&*/l->layout,sizeof(l->layout)); l->namelen = strlen(l->name); } lastlevel = N_DEF_LEVELS; } else { lastlevel = 0; } *argfile_tail = 0; ls = 0; for (af=argfiles;af;af=af->link) { if (! ls) { ls = NEW(LEVEL_SEG); } ls->first = lastlevel + 1; ls->num = read_level_file(af->filename,&ls->levels); ls->dirty = 0; if (ls->num < 0) { ls->num = - ls->num; ls->dirty = 1; } if (ls->num > 0) { lastlevel = ls->first + ls->num - 1; ls->last = lastlevel; ls->source = af->filename; for (i=0;inum;i++) { LEVEL *l; l = ls->levels[i]; l->levelno = ls->first + i; l->seg = ls; } *level_segs_tail = ls; level_segs_tail = &ls->link; ls = 0; } } if (ls) OLD(ls); *level_segs_tail = 0; if (level_segs == 0) { fprintf(stderr,"%s: need to get some levels from somewhere!\n",argvec[0]); exit(1); } maxlevelno = lastlevel; } 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); } } } char *get_default_value(name,class) char *name; char *class; { char *type; XrmValue value; if (XrmGetResource(db,name,class,&type,&value) == False) return(0); return(value.addr); } void getcolor(XColor *col) { while (1) { if (XAllocColor(disp,wincmap,col) == 0) { if (wincmap != defcmap) { fprintf(stderr,"%s: can't allocate colormap cell\n",argvec[0]); exit(1); } wincmap = XCopyColormapAndFree(disp,wincmap); continue; } break; } } void setup_color(char *str,XColor *col) { if (XParseColor(disp,wincmap,str,col) == 0) { fprintf(stderr,"%s: bad color `%s'\n",argvec[0],str); exit(1); } getcolor(col); } void setup_visual(void) { int i; XVisualInfo *vinf; int nvinf; XVisualInfo *v; XVisualInfo template; if (0) { bwmode:; bw_mode = 1; visual = XDefaultVisualOfScreen(scr); defcmap = XDefaultColormapOfScreen(scr); defgc = XDefaultGCOfScreen(scr); depth = XDefaultDepthOfScreen(scr); return; } if (bw_flag) goto bwmode; bw_mode = 0; template.screen = XScreenNumberOfScreen(scr); template.visualid = XVisualIDFromVisual(XDefaultVisualOfScreen(scr)); vinf = XGetVisualInfo(disp,VisualIDMask|VisualScreenMask,&template,&nvinf); if (nvinf != 1) goto bwmode; /* can this happen? */ if ( ((vinf->class == PseudoColor) && (vinf->colormap_size > B_NCOLORS+3)) || ((vinf->class == DirectColor) && (vinf->colormap_size > B_NCOLORS/3)) || ((vinf->class == StaticColor) && (vinf->bits_per_rgb >= 4)) || ((vinf->class == TrueColor) && (vinf->bits_per_rgb >= 4)) ) { visual = vinf->visual; defcmap = XDefaultColormapOfScreen(scr); defgc = XDefaultGCOfScreen(scr); depth = XDefaultDepthOfScreen(scr); XFree((char *)vinf); return; } template.screen = XScreenNumberOfScreen(scr); template.class = PseudoColor; vinf = XGetVisualInfo(disp,VisualScreenMask|VisualClassMask,&template,&nvinf); if (nvinf < 1) goto bwmode; v = 0; for (i=0;i= B_NCOLORS+3) { if ((v == 0) || (vinf[i].colormap_size > v->colormap_size)) v = &vinf[i]; } } if (v == 0) goto bwmode; visual = v->visual; defcmap = None; { Pixmap pm; /* Grrr - shouldn't have to bother creating the pixmap! */ pm = XCreatePixmap(disp,rootwin,1,1,v->depth); defgc = XCreateGC(disp,pm,0L,(XGCValues *)0); XFreePixmap(disp,pm); } depth = v->depth; XFree((char *)vinf); } void setup_font(void) { int c; XCharStruct d; font = 0; deffont = 0; if (fontname) { font = XLoadQueryFont(disp,fontname); if (! font) { fprintf(stderr,"%s: can't load font %s, using server default\n",argvec[0],fontname); } else { fontid = font->fid; } } if (! font) { font = XQueryFont(disp,XGContextFromGC(defgc)); deffont = 1; fontid = None; } for (c=0;c<10;c++) { XTextExtents(font,"0123456789"+c,1,XTE_JUNK,&d); if (c == 0) { maxdigitsize = d; } else { #define TST(field,cmp) if (d.field cmp maxdigitsize.field) maxdigitsize.field = d.field TST(lbearing,<); TST(rbearing,>); TST(ascent,>); TST(descent,>); TST(width,>); #undef TST } } } void setup_colors(void) { wincmap = (defcmap != None) ? defcmap : XCreateColormap(disp,rootwin,visual,AllocNone); if (bw_mode) { blackcolor.red = 0; blackcolor.green = 0; blackcolor.blue = 0; getcolor(&blackcolor); whitecolor.red = 65535; whitecolor.green = 65535; whitecolor.blue = 65535; getcolor(&whitecolor); } else { int i; for (i=0;i>3)*PIC_H]; 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],PIC_W,PIC_H,8,(PIC_W+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); XFreePixmap(disp,rv); XSetBackground(disp,gc,0L); XSetForeground(disp,gc,1L); } acc = 0; bp = &buf[0]; for (y=0;y 7) { *bp++ = acc; n = 0; } acc = (acc << 1) | b_p_pix_bw[inx][y][x]; n ++; } if (n > 0) { *bp++ = acc << (8 - n); } } rv = XCreatePixmap(disp,rootwin,PIC_W,PIC_H,1); XPutImage(disp,rv,gc,i,0,0,0,0,PIC_W,PIC_H); } else if (depth == 8) { static XImage *i = 0; static unsigned char buf[PIC_W*PIC_H]; static GC gc; int x; int y; unsigned char *bp; if (i == 0) { i = XCreateImage(disp,visual,8,ZPixmap,0,(char *)&buf[0],PIC_W,PIC_H,8,PIC_W); 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)*PIC_H]; 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],PIC_W,PIC_H,8,(PIC_W+7)>>3); i->bitmap_unit = 8; i->bitmap_bit_order = MSBFirst; tmp = XCreatePixmap(disp,rootwin,PIC_W,PIC_H,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,PIC_W,PIC_H,depth); XSetForeground(disp,gcn,0L); XSetFunction(disp,gcn,GXcopy); XFillRectangle(disp,rv,gcn,0,0,PIC_W,PIC_H); XSetFunction(disp,gcn,GXor); for (c=0;c 7) { *bp++ = acc; n = 0; } acc <<= 1; if (b_p_pix_color[inx][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,PIC_W,PIC_H); XSetForeground(disp,gcn,colors[c].pixel); XCopyPlane(disp,tmp,rv,gcn,0,0,PIC_W,PIC_H,0,0,1L); } } } return(rv); } void setup_wingc(void) { Pixmap pm; pm = XCreatePixmap(disp,rootwin,1,1,depth); wingc = XCreateGC(disp,pm,0L,(XGCValues *)0); XFreePixmap(disp,pm); XGetGCValues(disp,wingc,GCFunction|GCForeground|GCBackground|GCLineWidth|GCFillStyle|GCTileStipXOrigin|GCTileStipYOrigin|GCClipXOrigin|GCClipYOrigin|GCPlaneMask,&winshadow); winshadow.tile = None; /* force change when first set */ winshadow.stipple = None; /* force change when first set */ winshadow.clip_mask = None; /* force change when first set */ winshadow.font = None; /* ie, the default font */ } void setup_gc(long int bit, ...) { va_list ap; int setdeffont; unsigned long int gcmask; GC gc; XGCValues *shadow; XGCValues gcval; va_start(ap, bit); gc = wingc; shadow = &winshadow; setdeffont = 0; gcmask = 0; while (1) { switch (bit) { default: fprintf(stderr,"Bad bit 0x%lx to setup_gc\n",bit); abort(); break; case 0: va_end(ap); if (gcmask != 0) XChangeGC(disp,gc,gcmask,&gcval); if (setdeffont) XCopyGC(disp,defgc,GCFont,gc); return; break; #define CASE(mask,type,field) \ case mask: \ gcval.field = va_arg(ap,type); \ if (gcval.field != shadow->field) \ { gcmask |= mask; \ shadow->field = gcval.field; \ } \ break; CASE(GCFunction,int,function) CASE(GCForeground,unsigned long int,foreground) CASE(GCBackground,unsigned long int,background) CASE(GCLineWidth,int,line_width) CASE(GCTile,Pixmap,tile) CASE(GCStipple,Pixmap,stipple) CASE(GCFillStyle,int,fill_style) CASE(GCTileStipXOrigin,int,ts_x_origin) CASE(GCTileStipYOrigin,int,ts_y_origin) CASE(GCClipMask,Pixmap,clip_mask) CASE(GCClipXOrigin,int,clip_x_origin) CASE(GCClipYOrigin,int,clip_y_origin) CASE(GCPlaneMask,unsigned long int,plane_mask) case GCFont: gcval.font = va_arg(ap,Font); if (gcval.font != shadow->font) { if (gcval.font == None) { setdeffont = 1; gcmask &= ~GCFont; } else { gcmask |= GCFont; setdeffont = 0; } shadow->font = gcval.font; } break; } bit = va_arg(ap,long int); } } void setup_pixmaps(void) { int i; #define FOO(var,inx) var = pmsetup(inx); pic_ptrs[inx] = &var; FOO(pic_blank,PIC_BLANK); FOO(pic_s_b,PIC_S_B); FOO(pic_s_y,PIC_S_Y); FOO(pic_r_b,PIC_R_B); FOO(pic_r_y,PIC_R_Y); FOO(pic_d_b,PIC_D_B); FOO(pic_d_y,PIC_D_Y); FOO(pic_p_b,PIC_P_B); FOO(pic_p_y,PIC_P_Y); FOO(pic_color_b,PIC_COLOR_B); FOO(pic_color_y,PIC_COLOR_Y); FOO(pic_color_flip,PIC_COLOR_FLIP); FOO(pic_wall,PIC_WALL); FOO(pic_mwall,PIC_MWALL); FOO(pic_teleport,PIC_TELEPORT); FOO(pic_mutate,PIC_MUTATE); FOO(pic_player,PIC_PLAYER); for (i=0;ilink) { for (i=0;inum;i++) { l = ls->levels[i]; XTextExtents(font,l->name,l->namelen,XTE_JUNK,&l->namesize); if (l->namelen > n) n = l->namelen; if ((i == 0) && (ls == level_segs)) { maxlns = l->namesize; } else { #define TST(field,cmp) if (l->namesize.field cmp maxlns.field) maxlns.field = l->namesize.field TST(lbearing,<); TST(rbearing,>); TST(ascent,>); TST(descent,>); TST(width,>); #undef TST } } } levprompt_len = n; for (n=maxlevelno,i=1;n>=10;n/=10,i++) ; if (i > levprompt_len) levprompt_len = i; d = maxdigitsize; d.width *= i; #define TST(field,cmp) if (d.field cmp maxlns.field) maxlns.field = d.field TST(lbearing,<); TST(rbearing,>); TST(ascent,>); TST(descent,>); TST(width,>); #undef TST XTextExtents(font,levprompt_prompt,strlen(levprompt_prompt),XTE_JUNK,&d); levprompt_w = DIALOG_BORDER + DIALOG_MARGIN + d.width + maxlns.width + DIALOG_MARGIN + DIALOG_BORDER; levprompt_h = DIALOG_BORDER + DIALOG_MARGIN + font->ascent + font->descent + DIALOG_MARGIN + DIALOG_BORDER; levprompt_xoff = DIALOG_BORDER + DIALOG_MARGIN + d.width; levprompt_xclr = DIALOG_BORDER + DIALOG_MARGIN + d.width + maxlns.lbearing; } void setup_buttons(void) { int i; BUTTON *b; int a; int d; button_h = 0; for (i=0;itext,strlen(b->text),XTE_JUNK,&b->textbound); d = (b->textbound.descent > font->descent) ? b->textbound.descent : font->descent; a = (b->textbound.ascent > font->ascent) ? b->textbound.ascent : font->ascent; b->w = BUTTON_BORDER + BUTTON_MARGIN + b->textbound.width + BUTTON_MARGIN + BUTTON_BORDER; b->h = BUTTON_BORDER + BUTTON_MARGIN + a + d + BUTTON_MARGIN + BUTTON_BORDER; b->textx = BUTTON_BORDER + BUTTON_MARGIN; b->texty = BUTTON_BORDER + BUTTON_MARGIN + a; if (b->h > button_h) button_h = b->h; } for (i=0;itext,strlen(b->text),XTE_JUNK,&b->textbound); d = (b->textbound.descent > font->descent) ? b->textbound.descent : font->descent; a = (b->textbound.ascent > font->ascent) ? b->textbound.ascent : font->ascent; b->w = BUTTON_BORDER + BUTTON_MARGIN + b->textbound.width + BUTTON_MARGIN + BUTTON_BORDER; b->h = BUTTON_BORDER + BUTTON_MARGIN + a + d + BUTTON_MARGIN + BUTTON_BORDER; b->textx = BUTTON_BORDER + BUTTON_MARGIN; b->texty = BUTTON_BORDER + BUTTON_MARGIN + a; if (b->h > button_h) button_h = b->h; } for (i=0;itext; b->w = ucp[0]; b->h = help_button_h; b->x = (ucp[1] << 8) | ucp[2]; b->y = (ucp[3] << 8) | ucp[4]; } for (i=0;itext,strlen(b->text),XTE_JUNK,&b->textbound); d = (b->textbound.descent > font->descent) ? b->textbound.descent : font->descent; a = (b->textbound.ascent > font->ascent) ? b->textbound.ascent : font->ascent; b->w = BUTTON_BORDER + BUTTON_MARGIN + b->textbound.width + BUTTON_MARGIN + BUTTON_BORDER; b->h = BUTTON_BORDER + BUTTON_MARGIN + a + d + BUTTON_MARGIN + BUTTON_BORDER; b->textx = BUTTON_BORDER + BUTTON_MARGIN; b->texty = BUTTON_BORDER + BUTTON_MARGIN + a; if (b->h > button_h) button_h = b->h; } } void setup_windows(void) { int x; int y; int w; int h; int bits; int i; BUTTON *b; unsigned long int attrmask; XSetWindowAttributes attr; XTextProperty wn_prop; XTextProperty in_prop; XSizeHints normal_hints; XWMHints wm_hints; XClassHint class_hints; w = borderwidth + SPACING + (BOARD_X * PIC_W) + SPACING + borderwidth; h = borderwidth + SPACING + (BOARD_Y * PIC_H) + SPACING + borderwidth + SPACING + (2 * (font->ascent + font->descent)) + SPACING + button_h + SPACING + borderwidth; x = (width - w) / 2; y = (height - h) / 2; normal_hints.min_width = w - (2 * borderwidth); normal_hints.min_height = h - (2 * borderwidth); 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 = bgcolor.pixel; attrmask |= CWBackPixel; attr.border_pixel = bdcolor.pixel; attrmask |= CWBorderPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = StructureNotifyMask | KeyPressMask; attrmask |= CWEventMask; attr.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | PointerMotionMask; attrmask |= CWDontPropagate; w -= 2 * borderwidth; h -= 2 * borderwidth; topwin = XCreateWindow(disp,rootwin,x,y,w,h,borderwidth,depth,InputOutput,visual,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.width_inc = 1; normal_hints.height_inc = 1; wm_hints.flags = InputHint; wm_hints.input = True; class_hints.res_name = "xblockade"; class_hints.res_class = "Game"; XSetWMProperties(disp,topwin,&wn_prop,&in_prop,argv,argc,&normal_hints,&wm_hints,&class_hints); if (wincmap != defcmap) XSetWindowColormap(disp,topwin,wincmap); if (selkey) XChangeProperty(disp,topwin,XInternAtom(disp,"wm_selkey",False),XA_STRING,8,PropModeReplace,(unsigned char *)selkey,strlen(selkey)); attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = ExposureMask | ButtonPressMask | ButtonMotionMask; attrmask |= CWEventMask; gamewin = XCreateWindow(disp,topwin,0,0,1,1,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 = ExposureMask; attrmask |= CWEventMask; levprompt_win = XCreateWindow(disp,topwin,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = ExposureMask; attrmask |= CWEventMask; msgwin = XCreateWindow(disp,topwin,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); attrmask = 0; attr.background_pixmap = gray50; attrmask |= CWBackPixmap; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = ExposureMask | ButtonPressMask; attrmask |= CWEventMask; editwin = XCreateWindow(disp,topwin,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = ExposureMask | ButtonPressMask; attrmask |= CWEventMask; textpanelwin = XCreateWindow(disp,gamewin,0,0,PIC_W*BOARD_X,PIC_H*BOARD_Y,0,depth,InputOutput,CopyFromParent,attrmask,&attr); attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = ExposureMask | ButtonPressMask; attrmask |= CWEventMask; creditwin = XCreateWindow(disp,textpanelwin,0,0,PIC_W*BOARD_X,PIC_H*BOARD_Y,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,creditwin); attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = ExposureMask | ButtonPressMask; attrmask |= CWEventMask; helpwin = XCreateWindow(disp,textpanelwin,0,0,PIC_W*BOARD_X,PIC_H*BOARD_Y,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,helpwin); attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = ExposureMask | ButtonPressMask; attrmask |= CWEventMask; helppanelwin = XCreateWindow(disp,helpwin,0,0,PIC_W*BOARD_X,PIC_H*BOARD_Y,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,helppanelwin); for (i=0;iwin = XCreateWindow(disp,g_buttonwin_no_s,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,b->win); } for (i=0;iwin = XCreateWindow(disp,g_buttonwin_s,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,b->win); } for (i=0;iwin = XCreateWindow(disp,helpwin,b->x,b->y,b->w,b->h,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,b->win); } attrmask = 0; attr.background_pixel = bgcolor.pixel; attrmask |= CWBackPixel; attr.backing_store = NotUseful; attrmask |= CWBackingStore; attr.event_mask = NoEventMask; attrmask |= CWEventMask; e_buttonwin = XCreateWindow(disp,topwin,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,e_buttonwin); for (i=0;iwin = XCreateWindow(disp,e_buttonwin,0,0,1,1,0,depth,InputOutput,CopyFromParent,attrmask,&attr); XMapWindow(disp,b->win); } XLowerWindow(disp,helppanelwin); XLowerWindow(disp,e_buttonwin); XRaiseWindow(disp,gamewin); XMapRaised(disp,topwin); resize(w,h); } void setup_game(void) { curlevelno = 0; if (levelstr) setlevel(levelstr); if (curlevelno < 1) curlevelno = 1; initlevel(); dispstate = DS_GAME; } int set_sq_bl(int bi,int *sqp,int *blp,int *stp) { *sqp = SQ_BLANK; *blp = BLK_NONE; switch (bi) { case PIC_BLANK: break; case PIC_S_B: *blp = BLK_SHAPE_S | BLK_COLOR_B; break; case PIC_S_Y: *blp = BLK_SHAPE_S | BLK_COLOR_Y; break; case PIC_R_B: *blp = BLK_SHAPE_R | BLK_COLOR_B; break; case PIC_R_Y: *blp = BLK_SHAPE_R | BLK_COLOR_Y; break; case PIC_D_B: *blp = BLK_SHAPE_D | BLK_COLOR_B; break; case PIC_D_Y: *blp = BLK_SHAPE_D | BLK_COLOR_Y; break; case PIC_P_B: *blp = BLK_SHAPE_P | BLK_COLOR_B; break; case PIC_P_Y: *blp = BLK_SHAPE_P | BLK_COLOR_Y; break; case PIC_COLOR_B: *sqp = SQ_COLOR_B; break; case PIC_COLOR_Y: *sqp = SQ_COLOR_Y; break; case PIC_COLOR_FLIP: *sqp = SQ_COLOR_F; break; case PIC_WALL: *sqp = SQ_WALL; break; case PIC_MWALL: *blp = BLK_SHAPE_W; break; case PIC_TELEPORT: *sqp = SQ_TELEPORT; break; case PIC_MUTATE: *sqp = SQ_MUTATE; break; case PIC_PLAYER: return(1); break; default: *stp = bi - PIC_STARS_A; if ((*stp < 0) || (*stp >= PIC_NSTARS)) *stp = 0; *sqp = SQ_STARS; break; } return(0); } void initlevel(void) { int x; int y; int sq; int st; int bl; LEVEL_SEG *ls; LEVEL *l; if (curlevelno < 1) curlevelno = 1; for (ls=level_segs;ls&&(curlevelno>ls->last);ls=ls->link) ; if (! ls) { curlevelno = 1; ls = level_segs; } l = ls->levels[curlevelno-ls->first]; st = 0; for (x=0;xlayout[y][x],&sq,&bl,&st)) { player_x = x; player_y = y; } squaretype[x][y] = sq; startype[x][y] = st; blocktype[x][y] = bl; init_blocktype[x][y] = bl; } } init_player_x = player_x; init_player_y = player_y; pushsave(); levelname = l->name; levelname_len = l->namelen; curlevel = l; XRaiseWindow(disp,curlevel->seg->dirty?g_buttonwin_s:g_buttonwin_no_s); } void run(void) { XEvent e; while (1) { XNextEvent(disp,&e); handle_event(&e); } } 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 */ redisplay(e->xexpose.window,e->xexpose.x,e->xexpose.y,e->xexpose.width,e->xexpose.height,e->xexpose.count); break; case GraphicsExpose: /* XGraphicsExposeEvent - xgraphicsexpose */ redisplay(e->xgraphicsexpose.drawable,e->xgraphicsexpose.x,e->xgraphicsexpose.y,e->xgraphicsexpose.width,e->xgraphicsexpose.height,e->xgraphicsexpose.count); break; case ButtonPress: /* XButtonPressEvent - XButtonEvent - xbutton */ buttondown(e->xbutton.window,e->xbutton.x,e->xbutton.y,e->xbutton.state,e->xbutton.button); break; case MotionNotify: /* XMotionEvent - xmotion */ motion(e->xmotion.window,e->xmotion.x,e->xmotion.y,e->xmotion.state); break; case KeyPress: /* XKeyPressedEvent - XKeyEvent - xkey */ { static XComposeStatus compose_status; KeySym ks; char string[256]; int nc; nc = XLookupString(&e->xkey,&string[0],256,&ks,&compose_status); docmd(ks,e->xkey.state,nc,&string[0]); } break; case MappingNotify: /* XMappingEvent - xmapping */ XRefreshKeyboardMapping(&e->xmapping); break; } } void docmd(KeySym ks,unsigned int state,int nc,char *str) { switch (dispstate) { case DS_GAME: if (state & ControlMask) { switch (ks) { case XK_H: case XK_h: buttoncb_help(); break; case XK_C: case XK_c: buttoncb_credits(); break; case XK_E: case XK_e: buttoncb_edit(); break; case XK_S: case XK_s: buttoncb_save(); break; case XK_Q: case XK_q: buttoncb_quit(); break; case XK_R: case XK_r: resetlevel(); break; case XK_Z: case XK_z: undopush(); break; case XK_P: case XK_p: asklevel(); break; } } else { switch (ks) { case XK_H: case XK_h: case XK_Left: cmd_move(-1, 0); break; case XK_J: case XK_j: case XK_Down: cmd_move( 0, 1); break; case XK_K: case XK_k: case XK_Up: cmd_move( 0,-1); break; case XK_L: case XK_l: case XK_Right: cmd_move( 1, 0); break; } } break; case DS_CREDITS: setdispstate(DS_GAME); break; case DS_HELP: switch (ks) { case XK_1: sethelp(1); break; case XK_2: sethelp(2); break; case XK_3: sethelp(3); break; case XK_4: sethelp(4); break; case XK_5: sethelp(5); break; case XK_6: sethelp(6); break; case XK_7: sethelp(7); break; case XK_8: sethelp(8); break; case XK_9: sethelp(9); break; case XK_space: if (helpscreen < N_HELP) sethelp(helpscreen+1); else endhelp(); break; case XK_Escape: case XK_R: case XK_r: case XK_Return: endhelp(); break; } break; case DS_ASKLEVEL: if (nc > 0) { int i; for (i=0;i 0) { levprompt_fill --; XClearArea(disp,levprompt_win,levprompt_xclr,DIALOG_BORDER,levprompt_w-levprompt_xclr-DIALOG_BORDER,levprompt_h-(2*DIALOG_BORDER),True); } break; default: if (levprompt_fill >= levprompt_len) { bcopy(levprompt_buf+1,levprompt_buf,levprompt_len-1); levprompt_fill --; } levprompt_buf[levprompt_fill++] = str[i]; } } XClearArea(disp,levprompt_win,levprompt_xclr,DIALOG_BORDER,levprompt_w-levprompt_xclr-DIALOG_BORDER,levprompt_h-(2*DIALOG_BORDER),False); redisplay(levprompt_win,levprompt_xclr,DIALOG_BORDER,levprompt_w-levprompt_xclr-DIALOG_BORDER,levprompt_h-(2*DIALOG_BORDER),0); } break; case DS_MSG: setdispstate(DS_GAME); break; case DS_EDIT: if (state & ControlMask) { switch (ks) { case XK_J: case XK_j: buttoncb_e_junk(); break; case XK_R: case XK_r: buttoncb_e_revert(); break; case XK_A: case XK_a: buttoncb_e_abort(); break; case XK_D: case XK_d: buttoncb_e_done(); break; case XK_N: case XK_n: buttoncb_e_name(); break; case XK_C: case XK_c: buttoncb_e_clone(); break; } } else { switch (ks) { case XK_H: case XK_h: case XK_Left: edit_move(-1, 0); break; case XK_J: case XK_j: case XK_Down: edit_move( 0, 1); break; case XK_K: case XK_k: case XK_Up: edit_move( 0,-1); break; case XK_L: case XK_l: case XK_Right: edit_move( 1, 0); break; case XK_plus: change_curpic( 1); break; case XK_minus: change_curpic(-1); break; case XK_space: edit_set(editcurs_x,editcurs_y); break; } } break; case DS_LEVNAME: if (nc > 0) { int i; for (i=0;i 0) { lnfill --; } break; default: if (lnfill < MAXLNLEN) { lnbuf[lnfill++] = str[i]; } else { XBell(disp,0); } break; } } levelname_len = lnfill; XClearArea(disp,textwin,0,0,0,0,False); redraw_text(); } break; } } void change_curpic(int d) { edit_damaged[edit_curpic] = 1; edit_curpic += d; if (edit_curpic < 0) edit_curpic += B_NPIX; else if (edit_curpic >= B_NPIX) edit_curpic -= B_NPIX; edit_damaged[edit_curpic] = 1; fix_edit_damage(); } void edit_set(int x,int y) { int sq; int bl; int st; int draw; if ((x < 0) || (x >= BOARD_X) || (y < 0) || (y >= BOARD_Y)) return; draw = 0; if (set_sq_bl(edit_curpic,&sq,&bl,&st)) { int ox; int oy; ox = player_x; oy = player_y; player_x = x; player_y = y; drawsq(ox,oy); draw = 1; } if ( (squaretype[x][y] != sq) || (startype[x][y] != st) || (blocktype[x][y] != bl) ) { squaretype[x][y] = sq; startype[x][y] = st; blocktype[x][y] = bl; draw = 1; } if (draw) drawsq(x,y); if ( (blocktype[player_x][player_y] != BLK_NONE) || (squaretype[player_x][player_y] != SQ_BLANK) ) { int off; int i; int ox; int oy; ox = player_x; oy = player_y; off = (player_y * BOARD_X) + player_x; for (i=0;i= BOARD_X) editcurs_x = BOARD_X - 1; if (editcurs_y < 0) editcurs_y = 0; else if (editcurs_y >= BOARD_Y) editcurs_y = BOARD_Y - 1; if ((editcurs_x != ox) || (editcurs_y != oy)) { drawsq(ox,oy); drawsq(editcurs_x,editcurs_y); } } void asklevel(void) { setdispstate(DS_ASKLEVEL); XMapRaised(disp,levprompt_win); if (! levprompt_buf) { levprompt_buf = malloc(levprompt_len+1); } sprintf(levprompt_buf,"%d",curlevelno); levprompt_fill = strlen(levprompt_buf); } void asklevel_done(void) { levprompt_buf[levprompt_fill] = '\0'; setdispstate(DS_GAME); setlevel(levprompt_buf); initlevel(); redraw(); } void beginhelp(void) { setdispstate(DS_HELP); sethelp(helpscreen); XRaiseWindow(disp,helpwin); XMapWindow(disp,textpanelwin); } void sethelp(int n) { if ((n > 0) && (n <= N_HELP)) { XRaiseWindow(disp,helpwins[n-1]); helpscreen = n; } } void endhelp(void) { setdispstate(DS_GAME); } void undopush(void) { level_juggle(save_blocktype,&save_player_x,&save_player_y,1); } void resetlevel(void) { level_juggle(init_blocktype,&init_player_x,&init_player_y,0); pushsave(); } void level_juggle(char (*bl)[BOARD_Y],int *pxp,int *pyp,int swap) /* char (*bl)[BOARD_Y]; int *pxp; int *pyp; int swap; */ { int tmp; int x; int y; for (x=0;x= BOARD_X) || (ny >= BOARD_Y)) return(1); nbt = blocktype[nx][ny]; if (nbt == BLK_NONE) { switch (squaretype[nx][ny]) { case SQ_WALL: case SQ_STARS: return(1); break; } player_x = nx; player_y = ny; drawsq(nx-dx,ny-dy); drawsq(nx,ny); } else { bx = nx + dx; by = ny + dy; if ((bx < 0) || (by < 0) || (bx >= BOARD_X) || (by >= BOARD_Y)) return(1); bbt = blocktype[bx][by]; if (bbt == (nbt^BLK_COLOR_B^BLK_COLOR_Y)) { pushsave(); player_x = nx; player_y = ny; blocktype[nx][ny] = BLK_NONE; switch (bbt & BLK_SHAPE) { case BLK_SHAPE_S: blocktype[bx][by] = BLK_NONE; if (boardisclear()) { nextlevel(); return(0); } break; case BLK_SHAPE_R: blocktype[bx][by] = (bbt & ~BLK_SHAPE) | BLK_SHAPE_S; break; case BLK_SHAPE_P: blocktype[bx][by] = (bbt & ~BLK_SHAPE) | BLK_SHAPE_R; break; case BLK_SHAPE_D: blocktype[bx][by] = (bbt & ~BLK_SHAPE) | BLK_SHAPE_P; break; default: bugchk("bad block %d in block meeting",bbt); break; } drawsq(nx-dx,ny-dy); drawsq(nx,ny); drawsq(bx,by); } else if (bbt == BLK_NONE) { switch (squaretype[bx][by]) { case SQ_WALL: case SQ_STARS: return(1); break; } pushsave(); player_x = nx; player_y = ny; blocktype[bx][by] = nbt; blocktype[nx][ny] = BLK_NONE; if ((nbt & BLK_SHAPE) != BLK_SHAPE_W) { switch (squaretype[bx][by]) { case SQ_BLANK: break; case SQ_COLOR_B: blocktype[bx][by] = (nbt & ~BLK_COLOR) | BLK_COLOR_B; break; case SQ_COLOR_Y: blocktype[bx][by] = (nbt & ~BLK_COLOR) | BLK_COLOR_Y; break; case SQ_COLOR_F: blocktype[bx][by] = nbt ^ BLK_COLOR_B ^ BLK_COLOR_Y; break; case SQ_TELEPORT: do_teleport(bx,by); break; case SQ_MUTATE: switch (nbt & BLK_SHAPE) { case BLK_SHAPE_S: blocktype[bx][by] = (nbt & ~BLK_SHAPE) | BLK_SHAPE_R; break; case BLK_SHAPE_R: blocktype[bx][by] = (nbt & ~BLK_SHAPE) | BLK_SHAPE_P; break; case BLK_SHAPE_P: blocktype[bx][by] = (nbt & ~BLK_SHAPE) | BLK_SHAPE_D; break; } break; default: bugchk("bad square type %d in block slide",squaretype[nx][ny]); break; } } drawsq(nx-dx,ny-dy); drawsq(nx,ny); drawsq(bx,by); } } return 0; } void cmd_move(int dx,int dy) { if (do_move(dx,dy)) playsound(SND_CANTMOVE); } void do_teleport(int fx,int fy) { int bestx; int besty; int bestdist; int x; int y; int dist; bestx = fx; besty = fy; bestdist = BOARD_X + BOARD_Y + 1; for (y=0;yascent + font->descent); switch (dispstate) { case DS_EDIT: case DS_LEVNAME: dy = toph - (edith + borderwidth + gameh + borderwidth + texth + button_h); ny = 7; y = 0; BUMPY(0); XMoveResizeWindow(disp,editwin,(topw-editw)/2,y,editw,edith); BUMPY(edith); XMoveResizeWindow(disp,line1win,0,y,topw,borderwidth); BUMPY(borderwidth); break; default: dy = toph - (gameh + borderwidth + texth + button_h); ny = 5; y = 0; BUMPY(0); break; } gamey = y; XMoveResizeWindow(disp,gamewin,(topw-gamew)/2,y,gamew,gameh); XMoveResizeWindow(disp,levprompt_win,(topw-levprompt_w)/2,y+(gameh-levprompt_h)/2,levprompt_w,levprompt_h); if (dispstate == DS_MSG) place_msgwin(); BUMPY(gameh); XMoveResizeWindow(disp,line2win,0,y,topw,borderwidth); BUMPY(borderwidth); XMoveResizeWindow(disp,textwin,(topw-textw)/2,y,textw,texth); BUMPY(texth); XMoveResizeWindow(disp,g_buttonwin,0,y,topw,button_h); XMoveResizeWindow(disp,e_buttonwin,0,y,topw,button_h); XMoveResizeWindow(disp,g_buttonwin_s,0,0,topw,button_h); XMoveResizeWindow(disp,g_buttonwin_no_s,0,0,topw,button_h); dx = topw; for (i=0;ix = x; b->y = (button_h - b->h) / 2; XMoveResizeWindow(disp,b->win,b->x,b->y,b->w,b->h); BUMPX(b->w); } dx = topw; for (i=0;ix = x; b->y = (button_h - b->h) / 2; XMoveResizeWindow(disp,b->win,b->x,b->y,b->w,b->h); BUMPX(b->w); } dx = topw; for (i=0;ix = x; b->y = (button_h - b->h) / 2; XMoveResizeWindow(disp,b->win,b->x,b->y,b->w,b->h); BUMPX(b->w); } BUMPY(button_h); } #undef BUMPY #undef BUMPX void redisplay(Window win,int x,int y,int w,int h,int count) { int i; if (win == gamewin) { damage_gamewin(x,y,w,h); if (count == 0) fix_damage(); } else if (win == textwin) { if (count == 0) redraw_text(); } else if (win == creditwin) { update_textpanel(creditwin,&credits_img_bits[0],x,y,w,h); if (count == 0) update_textpanel_pix(creditwin,&credits_pix[0]); } else if (win == levprompt_win) { if (count == 0) draw_levprompt(); } else if (win == msgwin) { if (count == 0) draw_msg(); } else if (win == editwin) { damage_editwin(x,y,w,h); if (count == 0) fix_edit_damage(); } else { for (i=0;i= EDIT_NCOLS) x1 = EDIT_NCOLS - 1; if (y1 >= EDIT_NCOLS) y1 = EDIT_NCOLS - 1; x0 = x; for (;y<=y1;y++) { i = (y * EDIT_NCOLS) + x0; for (x=x0;x<=x1;x++) { if (i < B_NPIX) edit_damaged[i] = 1; i ++; } } } void fix_edit_damage(void) { int i; setup_gc(GCFunction,GXcopy,0L); for (i=0;iascent,levprompt_prompt,strlen(levprompt_prompt)); XDrawString(disp,levprompt_win,wingc,levprompt_xoff,DIALOG_BORDER+DIALOG_MARGIN+font->ascent,levprompt_buf,levprompt_fill); } void draw_msg(void) { setup_gc(GCFont,fontid,GCForeground,fgcolor.pixel,GCLineWidth,0,GCFillStyle,FillSolid,GCFunction,GXcopy,0L); XDrawRectangle(disp,msgwin,wingc,0,0,msg_w-1,msg_h-1); XDrawString(disp,msgwin,wingc,DIALOG_BORDER+DIALOG_MARGIN,DIALOG_BORDER+DIALOG_MARGIN+font->ascent,&msg_buf[0],msg_len); } void update_textpanel(Window win,unsigned char *bits,int x,int y,int w,int h) { static XImage *xi = 0; if (xi == 0) { xi = XCreateImage(disp,visual,1,XYBitmap,0,bits,PIC_W*BOARD_X,PIC_H*BOARD_Y,8,((PIC_W*BOARD_X)+7)>>3); xi->byte_order = LSBFirst; xi->bitmap_unit = 8; xi->bitmap_bit_order = LSBFirst; } xi->data = (char *)bits; setup_gc(GCForeground,fgcolor.pixel,GCBackground,bgcolor.pixel,GCFunction,GXcopy,0L); XPutImage(disp,win,wingc,xi,x,y,x,y,w,h); } void update_textpanel_pix(Window win,int *pv) { if (bw_mode) { setup_gc(GCForeground,whitecolor.pixel,GCBackground,blackcolor.pixel,GCFunction,GXcopy,0L); while (pv[0] >= 0) { XCopyPlane(disp,*pic_ptrs[pv[0]],win,wingc,0,0,PIC_W,PIC_H,pv[1],pv[2],1L); pv += 3; } } else { setup_gc(GCFunction,GXcopy,0L); while (pv[0] >= 0) { XCopyArea(disp,*pic_ptrs[pv[0]],win,wingc,0,0,PIC_W,PIC_H,pv[1],pv[2]); pv += 3; } } } void pickpic(int x,int y) { int qx; int qy; int rx; int ry; int i; qx = x / EDIT_MX; rx = x % EDIT_MX; qy = y / EDIT_MY; ry = y % EDIT_MY; if ((rx >= EDIT_SPACING) && (ry >= EDIT_SPACING)) { i = (qy * EDIT_NCOLS) + qx; if (i < B_NPIX) { edit_damaged[edit_curpic] = 1; edit_curpic = i; edit_damaged[edit_curpic] = 1; fix_edit_damage(); } } } int buttondown(Window win,int x,int y,unsigned int state,unsigned int button) { int i; BUTTON *b; if (win == gamewin) { switch (dispstate) { default: setdispstate(DS_GAME); /* fall through */ case DS_GAME: mousegame(x,y); break; case DS_ASKLEVEL: break; case DS_MSG: setdispstate(DS_GAME); break; case DS_EDIT: mouseedit(x,y); break; } } else if (win == creditwin) { setdispstate(DS_GAME); } else if (win == levprompt_win) { if (dispstate == DS_ASKLEVEL) asklevel_done(); else setdispstate(DS_GAME); } else if (win == msgwin) { setdispstate(DS_GAME); } else if (win == editwin) { pickpic(x,y); } else { for (i=0;iwin) { (*b->callback)(); } } for (i=0;iwin) { (*b->callback)(); } } for (i=0;iwin) { (*b->callback)(); } } for (i=0;iwin) { (*b->callback)(); } } } return 0; } void motion(Window win,int x,int y,unsigned int state) { if (win == gamewin) { switch (dispstate) { case DS_GAME: mousegame(x,y); break; case DS_EDIT: mouseedit(x,y); break; } } } void mousegame(int x,int y) { int dx; int dy; x = ((x + PIC_W) / PIC_W) - 1; y = ((y + PIC_H) / PIC_H) - 1; dx = x - player_x; dy = y - player_y; if ((abs(dx)+abs(dy) > 1) || ((dx || dy) && do_move(dx,dy))) { static struct timeval lastfail = { 0, 0 }; struct timeval now; struct timeval dtv; gettimeofday(&now,(struct timezone *)0); dtv.tv_sec = now.tv_sec - lastfail.tv_sec; dtv.tv_usec = now.tv_usec - lastfail.tv_usec; if (dtv.tv_usec < 0) { dtv.tv_usec += 1000000; dtv.tv_sec --; } if ((dtv.tv_sec > 0) || (dtv.tv_usec > 250000)) { lastfail = now; playsound(SND_CANTMOVE); } } } void mouseedit(int x,int y) { edit_set(((x+PIC_W)/PIC_W)-1,((y+PIC_H)/PIC_H)-1); } void damage_gamewin(int x,int y,int w,int h) { int x0; int x1; int y1; x1 = x + w - 1; y1 = y + h - 1; x0 = x / PIC_W; y /= PIC_H; x1 /= PIC_W; y1 /= PIC_H; if (x0 < 0) x0 = 0; if (y < 0) y = 0; if (x1 >= BOARD_X) x1 = BOARD_X - 1; if (y1 >= BOARD_Y) y1 = BOARD_Y - 1; if ((x0 <= x1) && (y <= y1)) { for (;y<=y1;y++) { for (x=x0;x<=x1;x++) { sqdamaged[x][y] = 1; } } } } void fix_damage(void) { int x; int y; for (x=0;xascent); text_center(levelname,levelname_len,font->ascent+font->descent+font->ascent); } void redraw_button(BUTTON *b) { setup_gc(GCFont,fontid,GCForeground,fgcolor.pixel,GCLineWidth,0,GCFillStyle,FillSolid,0L); XDrawRectangle(disp,b->win,wingc,0,0,b->w-1,b->h-1); XDrawString(disp,b->win,wingc,b->textx,b->texty,b->text,strlen(b->text)); } void redraw_help_button(BUTTON *b) { static XImage *xi = 0; if (xi == 0) { xi = XCreateImage(disp,visual,1,XYBitmap,0,b->text,1,help_button_h,8,1); xi->byte_order = LSBFirst; xi->bitmap_unit = 8; xi->bitmap_bit_order = LSBFirst; } /* 5 = # of overhead bytes before bitmap begins - see setup_buttons */ xi->data = 5 + *(char **)b->text; xi->width = b->w; xi->bytes_per_line = (b->w + 7) >> 3; setup_gc(GCForeground,fgcolor.pixel,GCBackground,bgcolor.pixel,GCFunction,GXcopy,0L); XPutImage(disp,b->win,wingc,xi,0,0,0,0,b->w,b->h); } void text_center(char *str,int len,int y) { XCharStruct s; XTextExtents(font,str,len,XTE_JUNK,&s); setup_gc(GCFont,fontid,GCForeground,fgcolor.pixel,GCFillStyle,FillSolid,0L); XDrawString(disp,textwin,wingc,(textw-s.width)/2,y,str,len); } void drawsq(int x,int y) { Pixmap pm; if ((x == player_x) && (y == player_y)) { pm = pic_player; } else { int bt; bt = blocktype[x][y]; if (bt == BLK_NONE) { switch (squaretype[x][y]) { case SQ_BLANK: pm = pic_blank; break; case SQ_COLOR_B: pm = pic_color_b; break; case SQ_COLOR_Y: pm = pic_color_y; break; case SQ_COLOR_F: pm = pic_color_flip; break; case SQ_WALL: pm = pic_wall; break; case SQ_TELEPORT: pm = pic_teleport; break; case SQ_MUTATE: pm = pic_mutate; break; case SQ_STARS: { int st; st = startype[x][y]; if ((st < 0) || (st >= PIC_NSTARS)) { bugchk("invalid star number %d at (%d,%d)",st,x,y); } pm = pic_stars[st]; } break; default: bugchk("invalid square type %d at (%d,%d)\n",squaretype[x][y],x,y); break; } } else { switch (bt & BLK_SHAPE) { case BLK_SHAPE_W: pm = pic_mwall; break; case BLK_SHAPE_S: pm = ((bt & BLK_COLOR) == BLK_COLOR_B) ? pic_s_b : pic_s_y; break; case BLK_SHAPE_R: pm = ((bt & BLK_COLOR) == BLK_COLOR_B) ? pic_r_b : pic_r_y; break; case BLK_SHAPE_P: pm = ((bt & BLK_COLOR) == BLK_COLOR_B) ? pic_p_b : pic_p_y; break; case BLK_SHAPE_D: pm = ((bt & BLK_COLOR) == BLK_COLOR_B) ? pic_d_b : pic_d_y; break; default: bugchk("invalid block %d at (%d,%d)",bt,x,y); break; } } } if (bw_mode) { setup_gc(GCForeground,whitecolor.pixel,GCBackground,blackcolor.pixel,GCFunction,GXcopy,0L); XCopyPlane(disp,pm,gamewin,wingc,0,0,PIC_W,PIC_H,x*PIC_W,y*PIC_H,1L); } else { setup_gc(GCFunction,GXcopy,0L); XCopyArea(disp,pm,gamewin,wingc,0,0,PIC_W,PIC_H,x*PIC_W,y*PIC_H); } if ((dispstate == DS_EDIT) && (x == editcurs_x) && (y == editcurs_y)) { int xx; int yy; setup_gc(GCForeground,whitecolor.pixel,0L); xx = x * PIC_W; yy = y * PIC_H; XFillRectangle(disp,gamewin,wingc,xx,yy,PIC_W,3); XFillRectangle(disp,gamewin,wingc,xx,yy+PIC_H-3,PIC_W,3); XFillRectangle(disp,gamewin,wingc,xx,yy+3,3,PIC_H-6); XFillRectangle(disp,gamewin,wingc,xx+PIC_W-3,yy+3,3,PIC_H-6); } } void setdispstate(int new) { int old; if (new == dispstate) return; old = dispstate; dispstate = new; switch (old) { case DS_GAME: break; case DS_CREDITS: XUnmapWindow(disp,textpanelwin); break; case DS_HELP: XUnmapWindow(disp,textpanelwin); break; case DS_ASKLEVEL: XUnmapWindow(disp,levprompt_win); break; case DS_MSG: XUnmapWindow(disp,msgwin); break; case DS_EDIT: if (new != DS_LEVNAME) { XUnmapWindow(disp,editwin); XLowerWindow(disp,e_buttonwin); edit_ask_resize(); drawsq(editcurs_x,editcurs_y); } break; case DS_LEVNAME: if (new != DS_EDIT) { XUnmapWindow(disp,editwin); XLowerWindow(disp,e_buttonwin); edit_ask_resize(); drawsq(editcurs_x,editcurs_y); } break; } if (new == DS_GAME) /* paranoia */ { XUnmapWindow(disp,textpanelwin); XUnmapWindow(disp,levprompt_win); XUnmapWindow(disp,msgwin); XUnmapWindow(disp,editwin); } } void set_msg_size(void) { XCharStruct d; XTextExtents(font,&msg_buf[0],msg_len,XTE_JUNK,&d); msg_w = DIALOG_BORDER + DIALOG_MARGIN + d.width + DIALOG_MARGIN + DIALOG_BORDER; msg_h = DIALOG_BORDER + DIALOG_MARGIN + font->ascent + font->descent + DIALOG_MARGIN + DIALOG_BORDER; } void place_msgwin(void) { XMoveResizeWindow(disp,msgwin,(topw-msg_w)/2,gamey+(gameh-msg_h)/2,msg_w,msg_h); } void popmsg(char *fmt, ...) { va_list ap; va_start(ap, fmt); vsprintf(&msg_buf[0],fmt,ap); msg_len = strlen(&msg_buf[0]); va_end(ap); set_msg_size(); place_msgwin(); setdispstate(DS_MSG); XMapRaised(disp,msgwin); } void begin_edit(void) { if (curlevel->seg->source == 0) { popmsg("Can't edit built-in levels"); } else { setdispstate(DS_EDIT); XMapWindow(disp,editwin); XMapWindow(disp,line1win); XLowerWindow(disp,g_buttonwin); edit_ask_resize(); editcurs_x = init_player_x; editcurs_y = init_player_y; sqdamaged[editcurs_x][editcurs_y] = 1; resetlevel(); } } void finish_edit(void) { int x; int y; setdispstate(DS_GAME); for (x=0;xseg->dirty = 1; for (x=0;xlayout[y][x] = pic; } } curlevel->layout[player_y][player_x] = PIC_PLAYER; initlevel(); } void fwrite_level(FILE *f,LEVEL *l) { int x; int y; char *s; fprintf(f,"%d:",l->namelen); fwrite(l->name,1,l->namelen,f); for (y=0;ylayout[y][x]) { case PIC_BLANK: s = "__"; break; case PIC_S_B: s = "QB"; break; case PIC_S_Y: s = "QY"; break; case PIC_R_B: s = "RB"; break; case PIC_R_Y: s = "RY"; break; case PIC_P_B: s = "PB"; break; case PIC_P_Y: s = "PY"; break; case PIC_D_B: s = "DB"; break; case PIC_D_Y: s = "DY"; break; case PIC_COLOR_B: s = "CB"; break; case PIC_COLOR_Y: s = "CY"; break; case PIC_COLOR_FLIP: s = "CF"; break; case PIC_WALL: s = "WL"; break; case PIC_MWALL: s = "MW"; break; case PIC_TELEPORT: s = "TL"; break; case PIC_MUTATE: s = "MU"; break; case PIC_PLAYER: s = "PL"; break; case PIC_STARS_A: s = "SA"; break; case PIC_STARS_B: s = "SB"; break; case PIC_STARS_C: s = "SC"; break; case PIC_STARS_D: s = "SD"; break; case PIC_STARS_E: s = "SE"; break; case PIC_STARS_F: s = "SF"; break; case PIC_STARS_G: s = "SG"; break; case PIC_STARS_H: s = "SH"; break; case PIC_STARS_I: s = "SI"; break; case PIC_STARS_J: s = "SJ"; break; default: bugchk("Bad value %d in layout[%d][%d] for level %d (from %s) in fwrite_level",l->layout[y][x],y,x,l->levelno,l->seg->source); break; } fprintf(f,"%c%s",x?' ':'\n',s); } } fprintf(f,"\n"); } void saveseg(LEVEL_SEG *seg) { FILE *f; int i; if (! seg->dirty) return; if (! seg->source) bugchk("Called saveseg on dirty built-in segment"); f = fopen(seg->source,"w"); if (f == 0) { popmsg("Can't open %s",seg->source); return; } for (i=0;inum;i++) { if (i) fprintf(f,"\n"); fwrite_level(f,seg->levels[i]); } fclose(f); seg->dirty = 0; XRaiseWindow(disp,g_buttonwin_no_s); popmsg("%s written",seg->source); } void showcredits(void) { setdispstate(DS_CREDITS); XRaiseWindow(disp,creditwin); XMapWindow(disp,textpanelwin); } void levname_begin(void) { setdispstate(DS_LEVNAME); lnfill = levelname_len; if (lnfill > MAXLNLEN) lnfill = MAXLNLEN; bcopy(levelname,&lnbuf[0],lnfill); XClearArea(disp,textwin,0,0,0,0,False); levelname = &lnbuf[0]; levelname_len = lnfill; redraw_text(); } void levname_done(int saveit) { setdispstate(DS_EDIT); if (saveit) { free(curlevel->name); curlevel->namelen = lnfill; curlevel->name = malloc(lnfill); bcopy(&lnbuf[0],curlevel->name,lnfill); curlevel->seg->dirty = 1; } levelname = curlevel->name; levelname_len = curlevel->namelen; reset_sizes(); XClearArea(disp,textwin,0,0,0,0,False); } void reset_sizes(void) { setup_sizes(); resize(topw,toph); } void clonelevel(void) { LEVEL_SEG *ls; LEVEL *l; int i; LEVEL **newlevels; int o; for (ls=curlevel->seg->link;ls;ls=ls->link) { ls->first ++; ls->last ++; for (i=0;inum;i++) ls->levels[i]->levelno = ls->first + i; } ls = curlevel->seg; newlevels = (LEVEL **) malloc((ls->num+1)*sizeof(LEVEL *)); o = curlevel->levelno - ls->first; for (i=0;i<=o;i++) newlevels[i] = ls->levels[i]; for (i=ls->num-1;i>o;i--) { l = ls->levels[i]; newlevels[i+1] = l; l->levelno ++; } l = NEW(LEVEL); newlevels[o+1] = l; *l = *newlevels[o]; l->name = malloc(l->namelen+7); bcopy(newlevels[o]->name,l->name,l->namelen); l->name[l->namelen++] = ' '; l->name[l->namelen++] = '('; l->name[l->namelen++] = 'c'; l->name[l->namelen++] = 'o'; l->name[l->namelen++] = 'p'; l->name[l->namelen++] = 'y'; l->name[l->namelen++] = ')'; l->levelno ++; curlevel = l; curlevelno = l->levelno; maxlevelno ++; ls->dirty = 1; ls->num ++; ls->last ++; free((char *)ls->levels); ls->levels = newlevels; reset_sizes(); initlevel(); XClearArea(disp,textwin,0,0,0,0,False); redraw_text(); } void junklevel(void) { LEVEL_SEG *ls; int i; ls = curlevel->seg; if (ls->num < 2) { XBell(disp,0); return; } for (ls=ls->link;ls;ls=ls->link) { ls->first --; ls->last --; for (i=0;inum;i++) ls->levels[i]->levelno = ls->first + i; } ls = curlevel->seg; free(curlevel->name); OLD(curlevel); if (curlevelno == ls->last) { curlevelno --; } else { for (i=curlevelno+1-ls->first;inum;i++) { LEVEL *l; l = ls->levels[i]; ls->levels[i-1] = l; l->levelno --; } } ls->dirty = 1; ls->num --; ls->last --; reset_sizes(); initlevel(); redraw(); } int buttoncb_e_junk() { junklevel(); return 0; } int buttoncb_e_revert() { level_juggle(init_blocktype,&init_player_x,&init_player_y,0); return 0; } int buttoncb_e_abort() { resetlevel(); setdispstate(DS_GAME); return 0; } int buttoncb_e_done() { finish_edit(); return 0; } int buttoncb_e_name() { levname_begin(); return 0; } int buttoncb_e_clone() { clonelevel(); return 0; } int buttoncb_help1() { sethelp(1); return 0; } int buttoncb_help2() { sethelp(2); return 0; } int buttoncb_help3() { sethelp(3); return 0; } int buttoncb_help4() { sethelp(4); return 0; } int buttoncb_help5() { sethelp(5); return 0; } int buttoncb_helpret() { setdispstate(DS_GAME); return 0; } int buttoncb_help() { beginhelp(); return 0; } int buttoncb_credits() { showcredits(); return 0; } int buttoncb_edit() { begin_edit(); return 0; } int buttoncb_save() { if (! curlevel->seg->dirty) return 0; saveseg(curlevel->seg); return 0; } int buttoncb_quit() { exit(0); return 0; } Display *open_display(disp) char *disp; { Display *rv; rv = XOpenDisplay(disp); if (rv == 0) { fprintf(stderr,"%s: can't open display %s\n",argvec[0],XDisplayName(disp)); exit(1); } return(rv); } int main(int ac,char **av) { argvec = av; saveargv(ac,av); handleargs(ac,av); setup_levels(); disp = open_display(displayname); if (syncX) XSynchronize(disp,True); scr = XDefaultScreenOfDisplay(disp); width = XWidthOfScreen(scr); height = XHeightOfScreen(scr); rootwin = XRootWindowOfScreen(scr); setup_db(); maybeset(&geometryspec,get_default_value("xblockade.geometry","Game.Geometry")); maybeset(&fontname,get_default_value("xblockade.font","Game.Font")); maybeset(&background,get_default_value("xblockade.background","Game.Background")); maybeset(&foreground,get_default_value("xblockade.foreground","Game.Foreground")); maybeset(&bordercstr,get_default_value("xblockade.borderColor","Game.BorderColor")); maybeset(&borderwstr,get_default_value("xblockade.borderWidth","Game.BorderWidth")); maybeset(&name,get_default_value("xblockade.name","Game.Name")); maybeset(&iconname,get_default_value("xblockade.iconName","Game.IconName")); maybeset(&selkey,get_default_value("xblockade.selkey","Game.Selkey")); setup_visual(); setup_font(); setup_colors(); setup_numbers(); setup_wingc(); setup_pixmaps(); setup_sizes(); setup_buttons(); setup_windows(); setup_game(); run(); return(0); }