#include #include #include #include #include XtAppContext app_con; Widget app_sh, draw, StartButton, StopButton; Boolean Running = False; typedef struct { short mag, size; } ApplicationData, *ApplicationDataPtr; ApplicationData AppData; String fallback_resources[] = { "*FontList: *-helvetica-bold-r-*-140-75-*", "*background: grey90", NULL }; XrmOptionDescRec options[] = { {"-mag","*nMag",XrmoptionSepArg,NULL}, {"-size","*nSize",XrmoptionSepArg,NULL} }; #define N_OPTIONS 2 XtResource resources[] = { {"nMag","NMag",XmRShort,sizeof(short), XtOffset(ApplicationDataPtr,mag),XtRImmediate,(XtPointer)4}, {"nSize","NSIZE",XmRShort,sizeof(short), XtOffset(ApplicationDataPtr,size),XtRImmediate,(XtPointer)100}, }; unsigned char *field, *work; Display *dpy = NULL; GC gc; Window win; Pixmap pmap; Pixel black, white; unsigned short size; void setup_draw_info() { dpy = XtDisplay(app_sh); gc = DefaultGC(dpy,0); win = XtWindow(draw); pmap = XCreatePixmap(dpy,win,size,size,DefaultDepth(dpy,0)); black = BlackPixel(dpy,0); white = WhitePixel(dpy,0); } void redisplay() { int i, j; XSetForeground(dpy,gc,white); XFillRectangle(dpy,pmap,gc,0,0,size,size); XSetForeground(dpy,gc,black); for (i = 0; i < AppData.size; i ++) for (j = 0; j < AppData.size; j ++) if (field[i*AppData.size+j]) { if (AppData.mag == 1) XDrawPoint(dpy,pmap,gc,i,j); else XFillRectangle(dpy,pmap,gc, i*AppData.mag,j*AppData.mag,AppData.mag,AppData.mag); } XCopyArea(dpy,pmap,win,gc,0,0,size,size,0,0); XFlush(dpy); } void reset() { int i; for (i = 0; i < AppData.size * AppData.size; i ++) field[i] = lrand48() & 1; redisplay(); } Boolean work_one_step(cl) XtPointer cl; { int i, j, i_pre, i_post, j_pre, j_post; if (!Running) return True; for (i = 0; i < AppData.size; i ++) { i_pre = (i + AppData.size-1) % AppData.size; i_post = (i + 1) % AppData.size; for (j = 0; j < AppData.size; j ++) { j_pre = (j + AppData.size-1) % AppData.size; j_post = (j + 1) % AppData.size; work[i*AppData.size+j] = field[i_pre*AppData.size+j_pre] + field[i_pre*AppData.size+j] + field[i_pre*AppData.size+j_post] + field[i*AppData.size+j_pre] + field[i*AppData.size+j_post] + field[i_post*AppData.size+j_pre] + field[i_post*AppData.size+j] + field[i_post*AppData.size+j_post]; } } for (i = 0; i < AppData.size * AppData.size; i ++) { if (work[i] == 3) field[i] = '\001'; else if (work[i] != 2) field[i] = '\0'; } redisplay(); return !Running; } void ResetCB(w,cl,cd) Widget w; XtPointer cl,cd; { reset(); } void QuitCB(w,cl,cd) Widget w; XtPointer cl,cd; { exit(0);} void StartCB(w,cl,cd) Widget w; XtPointer cl,cd; { Running = True; XtAppAddWorkProc(app_con,work_one_step,NULL); XtVaSetValues(StartButton,XmNsensitive,False,NULL); XtVaSetValues(StopButton,XmNsensitive,True,NULL); } void StopCB(w,cl,cd) Widget w; XtPointer cl,cd; { Running = False; XtVaSetValues(StartButton,XmNsensitive,True,NULL); XtVaSetValues(StopButton,XmNsensitive,False,NULL); } void RedisplayCB(w,cl,cd) Widget w; XtPointer cl,cd; { XmDrawingAreaCallbackStruct *d = (XmDrawingAreaCallbackStruct *)cd; XExposeEvent *e = &(d->event->xexpose); XCopyArea(dpy,pmap,win,gc,e->x,e->y,e->width,e->height,e->x,e->y); } main(argc,argv) int argc; char *argv[]; { Widget main_win, menu_bar, button; Arg args[2]; app_sh = XtAppInitialize(&app_con,"Life Game",options,N_OPTIONS, &argc,argv,fallback_resources,NULL,0); XtGetApplicationResources(app_sh,(XtPointer)&AppData,resources, XtNumber(resources),NULL,0); if (AppData.mag < 1) AppData.mag = 1; if (AppData.size < 20) AppData.size = 20; field = (unsigned char *)malloc(AppData.size * AppData.size * 2); if (!field) { perror("malloc"); exit(1); } work = field + AppData.size * AppData.size; size = AppData.mag * AppData.size; XtManageChild(main_win=XmCreateMainWindow(app_sh,"main_window",NULL,0)); XtManageChild(menu_bar=XmCreateMenuBar(main_win,"menu_bar",NULL,0)); XtManageChild(button=XmCreateCascadeButton(menu_bar,"Quit",NULL,0)); XtAddCallback(button,XmNactivateCallback,QuitCB,NULL); XtManageChild(button=XmCreateCascadeButton(menu_bar,"Reset",NULL,0)); XtAddCallback(button,XmNactivateCallback,ResetCB,NULL); StartButton = XmCreateCascadeButton(menu_bar,"Start",NULL,0); XtManageChild(StartButton); XtAddCallback(StartButton,XmNactivateCallback,StartCB,NULL); XtSetArg(args[0],XmNsensitive,False); StopButton = XmCreateCascadeButton(menu_bar,"Stop",args,1); XtManageChild(StopButton); XtAddCallback(StopButton,XmNactivateCallback,StopCB,NULL); XtSetArg(args[0],XmNwidth,size); XtSetArg(args[1],XmNheight,size); XtManageChild(draw=XmCreateDrawingArea(main_win,"field",args,2)); XtRealizeWidget(app_sh); setup_draw_info(); XtAddCallback(draw,XmNexposeCallback,RedisplayCB,NULL); reset(); XtAppMainLoop(app_con); }