/* * The Rubik's cube. * * Sed - april 1999 / december 2003. * * This program is in the public domain. *-------------------- * The screen stuff, ie X. * * Heavily hacked by J.-P. Demailly during week-end in October 2003, * to make following additions work : * wm_delete ClientMessage intercepted + menu popup + automatic resize * */ #include "screen.h" #include #include #include #include #include #include #include #include #include #include #include "cube.h" #include "device.h" extern char help1[]; extern char help2[]; extern char help3[]; extern char control_str[]; extern char close_str[]; extern char *controlwin_str[]; extern char save_output_str[]; extern char perspective_str[]; extern char cube_saved_str[]; static Atom wm_protocols, wm_delete_window; static int mark = 1; static short color_marks[54]; static int gl_u[6] = { 150, 30, 150, 270, 390, 150}; static int gl_v[6] = { 120, 240, 240, 240, 240, 360}; /* color pixels */ unsigned long pixel[11]; int set_colors(SCREEN *s) { XColor color, exact; int i, failed; failed = 0; for (i=10; i>=0; i--) { if (!XAllocNamedColor(s->d, s->cm, palette[i], &color, &exact)) failed = 1; pixel[i] = color.pixel; /* printf("%lu %d %d %d\n", pixel[i], color.red, color.green, color.blue); */ } /* printf("Failure : %d\n", failed); */ return failed; } void error_statement(SCREEN *s) { perror(""); fprintf(stderr, "Meaning no rubix\n"); XCloseDisplay(s->d); s->d=(Display *)0; } int reset_data_buffers(SCREEN *s) { if (s->im) XDestroyImage(s->im); s->buffer=(char *)malloc(((SCREEN_X+7)/8)*SCREEN_Y*s->depth); if (!s->buffer) { error_statement(s); return -1; } if (the_lines) free(the_lines); the_lines = (device_line *)malloc(SCREEN_Y*sizeof(device_line)); if (!the_lines) { error_statement(s); return -1; } /* create our XImage */ /* bitmap_pad, what the heck is it ?? mail sed@free.fr if you know, please... * Well, seems it has to be 32... */ /* Sed - december 2003 - no it has to be 8 */ s->im=XCreateImage(s->d, DefaultVisual(s->d, DefaultScreen(s->d)), s->depth==32?24:s->depth, ZPixmap, 0, s->buffer, SCREEN_X, SCREEN_Y, 8, 0); if (!s->im) { error_statement(s); return -1; } else return 0; } void set_cube_size() { int s; s = SCREEN_X; if (SCREEN_Y < s) s = SCREEN_Y; CUBE_SIZE = s * (0.95 - 0.2 * fabs(PERSPECTIVE)); } /* return -1 if error, 0 if ok */ int init_screen(SCREEN *s) { extern device d; XGCValues gcv; XEvent ev; XClassHint xch; memset(s, 0, sizeof(SCREEN)); if (!(s->d=XOpenDisplay((char *)0))) return -1; s->depth=DefaultDepth(s->d, DefaultScreen(s->d)); if (s->depth!=8 && s->depth!=16 && s->depth!=24) { fprintf(stderr, "screen depth not supported (only 8, 16 and 24bpp (which means 32bpp too) handled\n"); XCloseDisplay(s->d); s->d=(Display *)0; return -1; } wm_protocols = XInternAtom(s->d, "WM_PROTOCOLS", False); wm_delete_window = XInternAtom(s->d, "WM_DELETE_WINDOW", False); s->font = XLoadQueryFont(s->d, FONT); if (!s->font) { fprintf(stderr, "cannot load font %s !!\n", FONT); return -1; } HELP_X = (help_maxlen + 1) * XTextWidth(s->font, "w", 1); HELP_Y = (help_numlines + 2) * (s->font->max_bounds.ascent + s->font->max_bounds.descent + 2) + 3; /* we don't know if s->depth==24 if it's 24 or 32bpp, let's check it */ if (s->depth==24) { int n; XPixmapFormatValues *v; v=XListPixmapFormats(s->d, &n); if (!v || !n) { if (v) XFree(v); fprintf(stderr, "Error while trying to distinguish between 24 or 32bpp, damned...\n"); XCloseDisplay(s->d); s->d=(Display *)0; return -1; } for (n--; n>=0; n--) if (v[n].bits_per_pixel==32) s->depth=32; XFree(v); } s->cm = DefaultColormap(s->d, DefaultScreen(s->d)); /* let's create and map our window */ s->w=XCreateWindow(s->d, DefaultRootWindow(s->d), 0, 0, SCREEN_X, SCREEN_Y, 3, s->depth==32?24:s->depth, CopyFromParent, CopyFromParent, 0, NULL); s->h=XCreateWindow(s->d, DefaultRootWindow(s->d), 0, 0, HELP_X, HELP_Y, 3, s->depth==32?24:s->depth, CopyFromParent, CopyFromParent, 0, NULL); xch.res_name = "rubix"; xch.res_class = "Rubix"; XSetClassHint(s->d, s->w, &xch); XStoreName(s->d, s->w, xch.res_name); XSelectInput(s->d, s->w, KeyPressMask|ExposureMask|StructureNotifyMask| PointerMotionMask|ButtonPressMask|ButtonReleaseMask); XSetWMProtocols(s->d, s->w, &wm_delete_window, 1); XSelectInput(s->d, s->h, ExposureMask|ButtonReleaseMask); XSetWMProtocols(s->d, s->h, &wm_delete_window, 1); XMapWindow(s->d, s->w); do XNextEvent(s->d, &ev); while (ev.type!=Expose || ev.xexpose.window!=s->w); /* XFlush(s->d); no xflush */ XSetWMProtocols(s->d, s->w, &wm_delete_window, 1); gcv.function=GXcopy; s->gc=XCreateGC(s->d, s->w, GCFunction, &gcv); XSetFont(s->d, s->gc, s->font->fid); if (reset_data_buffers(s) == -1) return -1; d.buffer=s->buffer; d.depth=s->depth; return 0; } void realize_colors(SCREEN *s) { if (set_colors(s) && s->depth<=8) { s->cm=XCreateColormap(s->d, DefaultRootWindow(s->d), DefaultVisual(s->d, DefaultScreen(s->d)), AllocNone); set_colors(s); } if (s->depth<=8) { XSetWindowColormap(s->d, s->w, s->cm); XSetWindowColormap(s->d, s->h, s->cm); } XSetWindowBackground(s->d, s->w, pixel[10]); XSetWindowBackground(s->d, s->h, pixel[10]); } void grab_pointer(SCREEN *s, int mode) { static Cursor void_cursor = None; static Cursor arrow_cursor = None; Pixmap p; XColor a; GC pixgc; XSetWindowAttributes attributs; if (mode == 0) { XUngrabPointer(s->d, 0); if (arrow_cursor == None) arrow_cursor = XCreateFontCursor(s->d, XC_hand2); attributs.cursor = arrow_cursor; XChangeWindowAttributes(s->d, s->w, CWCursor, &attributs); return; } /* let's create a void cursor for our window */ if (void_cursor == None) { p=XCreatePixmap(s->d, DefaultRootWindow(s->d), 1, 1, 1); pixgc=XCreateGC(s->d, p, 0, 0); a.red=a.green=a.blue=0; XFillRectangle(s->d, p, pixgc, 0, 0, 2, 2); XFreeGC(s->d, pixgc); void_cursor = XCreatePixmapCursor(s->d, p, p, &a, &a, 0, 0); /* XFreePixmap(s->d, p); */ } attributs.cursor = void_cursor; XChangeWindowAttributes(s->d, s->w, CWCursor, &attributs); if (XGrabPointer(s->d, s->w, False, PointerMotionMask|ButtonPressMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, s->w, None, 0)) fprintf(stderr, "Could not grab the pointer, the program won't run very nice.\n"); place_mouse(s); } void display_help(SCREEN *s) { int i, dx, dy; XStoreName(s->d, s->h, "rubix/help"); /* XFlush(s->d); no xflush */ /* usleep(50000); no usleep */ XSetForeground(s->d, s->gc, pixel[9]); dy = s->font->max_bounds.ascent + s->font->max_bounds.descent + 2; for (i=0; id, s->h, s->gc, 6, s->font->max_bounds.ascent + 6 + i * dy, help_index[i], strlen(help_index[i])); dx = XTextWidth(s->font, control_str, strlen(control_str)); XDrawString(s->d, s->h, s->gc, 13, HELP_Y - s->font->max_bounds.descent - 12, control_str, strlen(control_str)); XDrawRectangle(s->d, s->h, s->gc, 6, HELP_Y - dy - 14, dx+14, dy+6); XDrawRectangle(s->d, s->h, s->gc, 5, HELP_Y - dy - 15, dx+16, dy+8); dx = XTextWidth(s->font, close_str, strlen(close_str)); XDrawString(s->d, s->h, s->gc, HELP_X - dx - 15, HELP_Y - s->font->max_bounds.descent - 12, close_str, strlen(close_str)); XDrawRectangle(s->d, s->h, s->gc, HELP_X - dx - 22, HELP_Y - dy - 14, dx+14, dy+6); XDrawRectangle(s->d, s->h, s->gc, HELP_X - dx - 23, HELP_Y - dy - 15, dx+16, dy+8); /* XFlush(s->d); no xflush */ } void show_text(SCREEN *s, int mode) { char dum[50]; int h; h = s->font->max_bounds.ascent + s->font->max_bounds.descent + 17; XClearArea(s->d, s->w, 0, SCREEN_Y - h, SCREEN_X, h, 0); switch(mode) { case 0: sprintf(dum, "%s = %s", save_output_str, formats[FORMAT]); break; case 1: sprintf(dum, "%s = %.1f", perspective_str, PERSPECTIVE); break; case 2: sprintf(dum, "%s ./rubix.%s", cube_saved_str, formats[FORMAT]); dum[25] = '\0'; break; default: strcpy(dum, "???"); break; } XSetForeground(s->d, s->gc, pixel[9]); XDrawString(s->d, s->w, s->gc, SCREEN_X - XTextWidth(s->font, dum, strlen(dum)) - 8, SCREEN_Y - s->font->max_bounds.descent - 6, dum, strlen(dum)); } void get_marks(CUBE *c) { c->cubes[25].colors[1] = color_marks[0]; c->cubes[22].colors[1] = color_marks[1]; c->cubes[20].colors[1] = color_marks[2]; c->cubes[24].colors[1] = color_marks[3]; c->cubes[1].colors[1] = color_marks[4]; c->cubes[19].colors[1] = color_marks[5]; c->cubes[23].colors[1] = color_marks[6]; c->cubes[21].colors[1] = color_marks[7]; c->cubes[18].colors[1] = color_marks[8]; c->cubes[25].colors[2] = color_marks[9]; c->cubes[24].colors[2] = color_marks[10]; c->cubes[23].colors[2] = color_marks[11]; c->cubes[23].colors[4] = color_marks[18]; c->cubes[21].colors[4] = color_marks[19]; c->cubes[18].colors[4] = color_marks[20]; c->cubes[18].colors[3] = color_marks[27]; c->cubes[19].colors[3] = color_marks[28]; c->cubes[20].colors[3] = color_marks[29]; c->cubes[20].colors[5] = color_marks[36]; c->cubes[22].colors[5] = color_marks[37]; c->cubes[25].colors[5] = color_marks[38]; c->cubes[17].colors[2] = color_marks[12]; c->cubes[2].colors[2] = color_marks[13]; c->cubes[16].colors[2] = color_marks[14]; c->cubes[16].colors[4] = color_marks[21]; c->cubes[4].colors[4] = color_marks[22]; c->cubes[14].colors[4] = color_marks[23]; c->cubes[14].colors[3] = color_marks[30]; c->cubes[3].colors[3] = color_marks[31]; c->cubes[15].colors[3] = color_marks[32]; c->cubes[15].colors[5] = color_marks[39]; c->cubes[5].colors[5] = color_marks[40]; c->cubes[17].colors[5] = color_marks[41]; c->cubes[13].colors[2] = color_marks[15]; c->cubes[12].colors[2] = color_marks[16]; c->cubes[11].colors[2] = color_marks[17]; c->cubes[11].colors[4] = color_marks[24]; c->cubes[9].colors[4] = color_marks[25]; c->cubes[6].colors[4] = color_marks[26]; c->cubes[6].colors[3] = color_marks[33]; c->cubes[7].colors[3] = color_marks[34]; c->cubes[8].colors[3] = color_marks[35]; c->cubes[8].colors[5] = color_marks[42]; c->cubes[10].colors[5] = color_marks[43]; c->cubes[13].colors[5] = color_marks[44]; c->cubes[11].colors[0] = color_marks[45]; c->cubes[9].colors[0] = color_marks[46]; c->cubes[6].colors[0] = color_marks[47]; c->cubes[12].colors[0] = color_marks[48]; c->cubes[0].colors[0] = color_marks[49]; c->cubes[7].colors[0] = color_marks[50]; c->cubes[13].colors[0] = color_marks[51]; c->cubes[10].colors[0] = color_marks[52]; c->cubes[8].colors[0] = color_marks[53]; } void set_marks(CUBE *c) { color_marks[0] = c->cubes[25].colors[1]; color_marks[1] = c->cubes[22].colors[1]; color_marks[2] = c->cubes[20].colors[1]; color_marks[3] = c->cubes[24].colors[1]; color_marks[4] = c->cubes[1].colors[1]; color_marks[5] = c->cubes[19].colors[1]; color_marks[6] = c->cubes[23].colors[1]; color_marks[7] = c->cubes[21].colors[1]; color_marks[8] = c->cubes[18].colors[1]; color_marks[9] = c->cubes[25].colors[2]; color_marks[10] = c->cubes[24].colors[2]; color_marks[11] = c->cubes[23].colors[2]; color_marks[18] = c->cubes[23].colors[4]; color_marks[19] = c->cubes[21].colors[4]; color_marks[20] = c->cubes[18].colors[4]; color_marks[27] = c->cubes[18].colors[3]; color_marks[28] = c->cubes[19].colors[3]; color_marks[29]= c->cubes[20].colors[3]; color_marks[36]= c->cubes[20].colors[5]; color_marks[37]= c->cubes[22].colors[5]; color_marks[38]= c->cubes[25].colors[5]; color_marks[12] = c->cubes[17].colors[2]; color_marks[13] = c->cubes[2].colors[2]; color_marks[14] = c->cubes[16].colors[2]; color_marks[21] = c->cubes[16].colors[4]; color_marks[22] = c->cubes[4].colors[4]; color_marks[23] = c->cubes[14].colors[4]; color_marks[30] = c->cubes[14].colors[3]; color_marks[31] = c->cubes[3].colors[3]; color_marks[32]= c->cubes[15].colors[3]; color_marks[39]= c->cubes[15].colors[5]; color_marks[40]= c->cubes[5].colors[5]; color_marks[41]= c->cubes[17].colors[5]; color_marks[15] = c->cubes[13].colors[2]; color_marks[16] = c->cubes[12].colors[2]; color_marks[17] = c->cubes[11].colors[2]; color_marks[24] = c->cubes[11].colors[4]; color_marks[25] = c->cubes[9].colors[4]; color_marks[26] = c->cubes[6].colors[4]; color_marks[33] = c->cubes[6].colors[3]; color_marks[34] = c->cubes[7].colors[3]; color_marks[35]= c->cubes[8].colors[3]; color_marks[42]= c->cubes[8].colors[5]; color_marks[43]= c->cubes[10].colors[5]; color_marks[44]= c->cubes[13].colors[5]; color_marks[45] = c->cubes[11].colors[0]; color_marks[46] = c->cubes[9].colors[0]; color_marks[47] = c->cubes[6].colors[0]; color_marks[48] = c->cubes[12].colors[0]; color_marks[49] = c->cubes[0].colors[0]; color_marks[50] = c->cubes[7].colors[0]; color_marks[51] = c->cubes[13].colors[0]; color_marks[52] = c->cubes[10].colors[0]; color_marks[53] = c->cubes[8].colors[0]; } void display_controls(SCREEN *s) { int i, j, k, p, dx, dy; static char faces[] = "BCEDFA"; dy = s->font->max_bounds.ascent + s->font->max_bounds.descent + 2; XStoreName(s->d, s->h, "rubix/control"); /* XFlush(s->d); no xflush */ /* usleep(50000); no usleep */ color_marks[4] = 2; color_marks[13] = 3; color_marks[22] = 5; color_marks[31] = 4; color_marks[40] = 6; color_marks[49] = 1; for (i=0; i<6; i++) { XSetForeground(s->d, s->gc, (i+1==mark)?pixel[9]:pixel[10]); XDrawRectangle(s->d, s->h, s->gc, 29+60*i, 19, 42, 42); XSetForeground(s->d, s->gc, pixel[7]); XDrawRectangle(s->d, s->h, s->gc, 30+60*i, 20, 40, 40); XDrawRectangle(s->d, s->h, s->gc, 31+60*i, 21, 38, 38); XSetForeground(s->d, s->gc, pixel[i+1]); XFillRectangle(s->d, s->h, s->gc, 32+60*i, 22, 37, 37); } for (i=0; i<6; i++) { for (j=0; j<3; j++) for (k=0; k<3; k++) { XSetForeground(s->d, s->gc, pixel[7]); XDrawRectangle(s->d, s->h, s->gc, gl_u[i]+40*j, gl_v[i]+40*k, 40, 40); p = color_marks[9*i+j+3*k]; XSetForeground(s->d, s->gc, pixel[p]); XFillRectangle(s->d, s->h, s->gc, gl_u[i]+40*j+1, gl_v[i]+40*k+1, 39, 39); } XSetForeground(s->d, s->gc, pixel[8]); XDrawString(s->d, s->h, s->gc, gl_u[i]+58, gl_v[i]+64, faces+i, 1); XSetForeground(s->d, s->gc, pixel[7]); XDrawRectangle(s->d, s->h, s->gc, gl_u[i], gl_v[i], 120, 120); XDrawRectangle(s->d, s->h, s->gc, gl_u[i]+1, gl_v[i]+1, 118, 118); } XSetForeground(s->d, s->gc, pixel[9]); dx = XTextWidth(s->font, controlwin_str[3], strlen(controlwin_str[3])); for (i=0; i<5; i++) { XDrawString(s->d, s->h, s->gc, 30 + (dx+40)*i, HELP_Y - s->font->max_bounds.descent - 12, controlwin_str[i], strlen(controlwin_str[i])); XDrawRectangle(s->d, s->h, s->gc, 20+(dx+40)*i, HELP_Y - dy - 14, dx+14, dy+6); XDrawRectangle(s->d, s->h, s->gc, 19+(dx+40)*i, HELP_Y - dy - 15, dx+16, dy+8); } /* XFlush(s->d); no xflush */ } /* return -1 if end, 0 otherwise */ int screen_key(SCREEN *s, CUBE *c, XKeyEvent *ev) { char dum[50]; KeySym ks; int n; XLookupString(ev, dum, 50, &ks, (XComposeStatus *)0); switch(ks) { case XK_Escape : case XK_q : case XK_Q : return -1; case XK_a: case XK_A: case XK_b: case XK_B: case XK_c: case XK_C: case XK_d: case XK_D: case XK_e: case XK_E: case XK_f: case XK_F: n = -1; if (!c->letters) { c->letters = 1; display_cube(c, s); break; } if ((ks>=XK_a) && (ks<=XK_f)) { c->rotated = n = ks-XK_a; c->orient = 0; } if ((ks>=XK_A) && (ks<=XK_F)) { c->rotated = n = ks-XK_A; c->orient = 1; } if (n == -1) break; c->letters = 1; c->anim = -1; c->time = get_time(); break; case XK_l: case XK_L: c->letters = 1 - c->letters; display_cube(c, s); break; case XK_exclam : XMapRaised(s->d, s->h); XClearWindow(s->d, s->h); s->control = 2; set_marks(c); display_controls(s); s->pause = 0; goto do_pause; case XK_asterisk : case XK_KP_Multiply : FORMAT = (FORMAT+1)%3; show_text(s, 0); break; case XK_plus : case XK_KP_Add : n = (int) (10*PERSPECTIVE + 10.5); ++n; if (n>20) n = 20; PERSPECTIVE = 0.1 * n - 1.0; set_cube_size(); display_cube(c, s); show_text(s, 1); break; case XK_minus : case XK_KP_Subtract : n = (int) (10*PERSPECTIVE + 10.5); --n; if (n<0) n = 0; PERSPECTIVE = 0.1 * n - 1.0; set_cube_size(); display_cube(c, s); show_text(s, 1); break; case XK_h : case XK_H : XMapRaised(s->d, s->h); XClearWindow(s->d, s->h); s->pause = 0; s->control = 0; display_help(s); case XK_space : do_pause: s->pause=1-s->pause; if (s->pause) { grab_pointer(s, 0); } else { grab_pointer(s, 1); } display_cube(c, s); break; case XK_i : case XK_I : init_cube(c, NULL, -1); display_cube(c, s); break; case XK_p : case XK_P : init_cube(c, NULL, 1); display_cube(c, s); break; case XK_r : case XK_R : reset_cube(c); display_cube(c, s); break; case XK_s : case XK_S : save_cube(c); show_text(s, 2); break; case XK_Left : if (!s->pause) cube_generate_rotate(c, s, 0); break; case XK_Right : if (!s->pause) cube_generate_rotate(c, s, 1); break; } return 0; } void place_mouse(SCREEN *s) { if (!s->pause) { XWarpPointer(s->d, None, s->w, 0, 0, 0, 0, SCREEN_X/2, SCREEN_Y/2); /* XFlush(s->d); no xflush */ } } void mouse_pre_event(XMotionEvent *ev, int *a, int *b) { if (ev->x==SCREEN_X/2 && ev->y==SCREEN_Y/2) return; *a=ev->y-SCREEN_Y/2; *b=ev->x-SCREEN_X/2; } void mouse_event(SCREEN *s, CUBE *c, int a, int b) { #define SPEED (1024.) if (s->pause) return; if (a==0 && b==0) return; place_mouse(s); /* the x is y and vice-versa */ cube_rotate(s, c, a*M_PI/SPEED, b*M_PI/SPEED); display_cube(c, s); } /* danger: this returns the incorrect height with some window managers */ void get_window_size(SCREEN *s, int *x, int*y) { Window root, parent, *children; int u, v, b, d, n; XQueryTree(s->d, s->w, &root, &parent, &children, &n); if (!parent) { fprintf(stderr, "Cannot query window tree!\n"); return; } XGetGeometry(s->d, parent, &root, &u, &v, x, y, &b, &d); } Bool evpred(Display *d, XEvent *ev, XPointer a) { return (True); } Bool confpred(Display *d, XEvent *ev, XPointer a) { if (ev->type==ConfigureNotify) return (True); else return (False); } /* Discard all events but last expose event */ void purge_events(Display *dpy) { XEvent ev, evp; evp.type = 0; while (XPending(dpy)) { XNextEvent(dpy, &ev); if (ev.type==Expose) evp = ev; } if (evp.type==Expose) XPutBackEvent(dpy, &evp); } /* return -1 if end, 0 if ok */ int screen_event(SCREEN *s, CUBE *c) { #define EXPOSE 1 #define MOTION 2 extern device d; int type=0; int i, j, k, a=0, b=0, dx, dy; static int new_x, new_y, notify = 0; XEvent ev; dy = s->font->max_bounds.ascent + s->font->max_bounds.descent + 2; while(XCheckIfEvent(s->d, &ev, evpred, (XPointer)0)) { switch(ev.type) { case ClientMessage : if (ev.xclient.message_type == wm_protocols && ev.xclient.format == 32 && ev.xclient.data.l[0] == wm_delete_window) { if (ev.xexpose.window == s->w) { close_screen(s); exit(0); } if (ev.xexpose.window == s->h) { XUnmapWindow(s->d, s->h); s->control = 0; } } break; case Expose : type|=EXPOSE; break; case KeyPress : if (screen_key(s, c, &ev.xkey)==-1) return -1; break; case ButtonRelease : if (ev.xexpose.window==s->w) { if (!s->pause) break; dx = XTextWidth(s->font, help1, strlen(help1)); if (ev.xbutton.x>=6 && ev.xbutton.x<=dx+20 && ev.xbutton.y>=6 && ev.xbutton.y<=dy+12) { s->pause=0; grab_pointer(s, 1); display_cube(c, s); break; } dx = XTextWidth(s->font, help2, strlen(help2)); if (ev.xbutton.x>=6 && ev.xbutton.x<=dx+20 && ev.xbutton.y>=SCREEN_Y - dy - 14 && ev.xbutton.y<=SCREEN_Y - 8) { XMapRaised(s->d, s->h); XClearWindow(s->d, s->h); s->control = 0; display_help(s); break;; } dx = XTextWidth(s->font, help3, strlen(help3)); if (ev.xbutton.x>=SCREEN_X - dx - 22 && ev.xbutton.x<=SCREEN_X - 8 && ev.xbutton.y>=SCREEN_Y - dy - 14 && ev.xbutton.y<=SCREEN_Y - 8) { XMapRaised(s->d, s->h); XClearWindow(s->d, s->h); set_marks(c); s->control = 2; display_controls(s); break; } break; } if (ev.xexpose.window==s->h) { dx = XTextWidth(s->font, control_str, strlen(control_str)); if (s->control == 0 && ev.xbutton.x>=6 && ev.xbutton.x<=dx+20 && ev.xbutton.y>=HELP_Y - dy - 14 && ev.xbutton.y<=HELP_Y - 8) { s->control = 2; XClearWindow(s->d, s->h); set_marks(c); display_controls(s); break; } dx = XTextWidth(s->font, close_str, strlen(close_str)); if (s->control == 0 && ev.xbutton.x>=HELP_X - dx - 22 && ev.xbutton.x<=HELP_X - 8 && ev.xbutton.y>=HELP_Y - dy - 14 && ev.xbutton.y<=HELP_Y - 8) { XUnmapWindow(s->d, s->h); } if (s->control == 0) break; j = -1; dx = XTextWidth(s->font, controlwin_str[3], strlen(controlwin_str[3])); for (i=0; i<5; i++) if (ev.xbutton.x>=20+(dx+40)*i && ev.xbutton.x<=-6+(dx+40)*(i+1) && ev.xbutton.y>=HELP_Y - dy - 14 && ev.xbutton.y<=HELP_Y - 8) { j = i; break; } if (j>=0) switch(j) { case 0: s->control = 1; memset(color_marks, 0, 54*sizeof(short)); goto skip; case 1: s->control = 2; get_marks(c); display_cube(c, s); goto endcontrol; case 2: s->control = 2; init_cube(c, NULL, -1); display_cube(c, s); goto skip; case 3: s->control = 2; init_cube(c, NULL, 1); display_cube(c, s); goto skip; case 4: s->control = 0; XUnmapWindow(s->d, s->h); goto endcontrol; } for (i=0; i<6; i++) { if (ev.xbutton.x>=30+60*i && ev.xbutton.x<=70+60*i && ev.xbutton.y>=20 && ev.xbutton.y<=60) { mark = i+1; goto skip; } } for (i=0; i<6; i++) { for (j=0; j<3; j++) for (k=0; k<3; k++) { if (ev.xbutton.x>=gl_u[i]+40*j && ev.xbutton.x<=gl_u[i]+40+40*j && ev.xbutton.y>=gl_v[i]+40*k && ev.xbutton.y<=gl_v[i]+40+40*k) { color_marks[9*i+j+3*k] = mark; if (s->control==2) s->control = 1; goto skip; } } } skip: display_controls(s); if (!s->control) break; } endcontrol: break; case ButtonPress : if (ev.xexpose.window != s->w) break; if (c->letters) { c->letters = 0; display_cube(c, s); break; } if (ev.xbutton.button==Button1) { cube_generate_rotate(c, s, 0); } else if (ev.xbutton.button==Button2) { s->pause=1; grab_pointer(s, 0); display_cube(c, s); } else if (ev.xbutton.button==Button3) { cube_generate_rotate(c, s, 1); } break; case MotionNotify : if (ev.xexpose.window != s->w) break; mouse_pre_event(&ev.xmotion, &a, &b); type |= MOTION; break; case PropertyNotify: case ConfigureNotify: new_x = ev.xconfigure.width; new_y = ev.xconfigure.height; if (new_x!=SCREEN_X || new_y!=SCREEN_Y) notify = 1; break; #if 0 case FocusOut : if (!s->pause) place_mouse(s); break; #endif } } if (notify) { /* XFlush(s->d); no xflush */ /* usleep(200000); no usleep */ if (new_x!=SCREEN_X || new_y!=SCREEN_Y || XCheckIfEvent(s->d, &ev, confpred, (XPointer)0)) { if (new_x<80) new_x = 80; if (new_y<60) new_y = 60; XResizeWindow(s->d, s->w, new_x, new_y); XClearArea(s->d, s->w, 0, 0, 1, 1, True); SCREEN_X = new_x; SCREEN_Y = new_y; reset_data_buffers(s); d.buffer=s->buffer; set_cube_size(); } else { display_cube(c, s); /* XFlush(s->d); no xflush */ put_screen(c, s); notify = 0; } purge_events(s->d); return 0; } if (type & MOTION) { i = s->control; s->control = 0; mouse_event(s, c, a, b); s->control = i; } else if (type & EXPOSE) { if (ev.xexpose.window == s->w) put_screen(c, s); if (ev.xexpose.window == s->h) { if (s->control) display_controls(s); if (!s->control) display_help(s); } } return 0; } void close_screen(SCREEN *s) { XDestroyWindow(s->d, s->w); XFreeGC(s->d, s->gc); if (s->depth==8) XFreeColormap(s->d, s->cm); XCloseDisplay(s->d); } void clear_screen(SCREEN *s) { /* fill s->im with pixel[10], avoid XPutPixel which is rather slow... */ int i, w, dw; w = (SCREEN_X+7)/8; dw = s->depth/8; XPutPixel(s->im, 0, 0, pixel[10]); for (i=1; i<8*w; i++) memcpy(s->buffer + i*dw, s->buffer, dw); w = w * s->depth; for (i=1; ibuffer + i*w, s->buffer, w); } void put_screen(CUBE *c, SCREEN *s) { int dx, dy; XPutImage(s->d, s->w, s->gc, s->im, 0, 0, 0, 0, SCREEN_X, SCREEN_Y); if (s->pause) { XSetForeground(s->d, s->gc, pixel[9]); dy = s->font->max_bounds.ascent + s->font->max_bounds.descent + 2; dx = XTextWidth(s->font, help1, strlen(help1)); XDrawString(s->d, s->w, s->gc, 13, s->font->max_bounds.ascent + 10, help1, strlen(help1)); XDrawRectangle(s->d, s->w, s->gc, 6, 6, dx+14, dy+6); XDrawRectangle(s->d, s->w, s->gc, 5, 5, dx+16, dy+8); dx = XTextWidth(s->font, help2, strlen(help2)); XDrawString(s->d, s->w, s->gc, 13, SCREEN_Y - s->font->max_bounds.descent - 12, help2, strlen(help2)); XDrawRectangle(s->d, s->w, s->gc, 6, SCREEN_Y - dy - 14, dx+14, dy+6); XDrawRectangle(s->d, s->w, s->gc, 5, SCREEN_Y - dy - 15, dx+16, dy+8); dx = XTextWidth(s->font, help3, strlen(help3)); XDrawString(s->d, s->w, s->gc, SCREEN_X - dx - 15, SCREEN_Y - s->font->max_bounds.descent - 12, help3, strlen(help3)); XDrawRectangle(s->d, s->w, s->gc, SCREEN_X - dx - 22, SCREEN_Y - dy - 14, dx+14, dy+6); XDrawRectangle(s->d, s->w, s->gc, SCREEN_X - dx - 23, SCREEN_Y - dy - 15, dx+16, dy+8); XFlush(s->d); } if (s->control == 2 && c->anim==0) { set_marks(c); display_controls(s); /* XFlush(s->d); no xflush */ } /* XFlush(s->d); */ } /* return ms */ struct timeval get_time(void) { struct timeval t; struct timezone d; if (gettimeofday(&t, &d)==-1) { perror("gettimeofday"); return t; } return t; }