xref: /386bsd/usr/src/games/chess/Xchess/window.c (revision a2142627)
1 /* This file contains code for X-CHESS.
2    Copyright (C) 1986 Free Software Foundation, Inc.
3 
4 This file is part of X-CHESS.
5 
6 X-CHESS is distributed in the hope that it will be useful,
7 but WITHOUT ANY WARRANTY.  No author or distributor
8 accepts responsibility to anyone for the consequences of using it
9 or for whether it serves any particular purpose or works at all,
10 unless he says so in writing.  Refer to the X-CHESS General Public
11 License for full details.
12 
13 Everyone is granted permission to copy, modify and redistribute
14 X-CHESS, but only under the conditions described in the
15 X-CHESS General Public License.   A copy of this license is
16 supposed to have been given to you along with X-CHESS so you
17 can know your rights and responsibilities.  It should be in a
18 file named COPYING.  Among other things, the copyright notice
19 and this notice must be preserved on all copies.  */
20 
21 
22 /* RCS Info: $Revision: 1.5 $ on $Date: 86/11/26 12:11:15 $
23  *           $Source: /users/faustus/xchess/RCS/window.c,v $
24  * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
25  *	Permission is granted to do anything with this code except sell it
26  *	or remove this message.
27  *
28  * Deal with the two (or one) windows.
29  */
30 
31 #include "xchess.h"
32 #include <X11/Xutil.h>
33 #include <sys/time.h>
34 
35 #include "pawn.bitmap"
36 #include "rook.bitmap"
37 #include "knight.bitmap"
38 #include "bishop.bitmap"
39 #include "queen.bitmap"
40 #include "king.bitmap"
41 
42 #include "pawn_outline.bitmap"
43 #include "rook_outline.bitmap"
44 #include "knight_outline.bitmap"
45 #include "bishop_outline.bitmap"
46 #include "queen_outline.bitmap"
47 #include "king_outline.bitmap"
48 
49 #include "pawn_mask.bitmap"
50 #include "rook_mask.bitmap"
51 #include "knight_mask.bitmap"
52 #include "bishop_mask.bitmap"
53 #include "queen_mask.bitmap"
54 #include "king_mask.bitmap"
55 
56 #include "shade.bitmap"
57 
58 #include "xchess.cur"
59 #include "xchess_mask.cur"
60 
61 #include "xchess.icon"
62 
63 windata *win1, *win2;
64 bool win_flashmove = false;
65 
66 extern bool setup();
67 extern void service(), drawgrid(), icon_refresh();
68 
69 bool
win_setup(disp1,disp2)70 win_setup(disp1, disp2)
71 	char *disp1, *disp2;
72 {
73 	win1 = alloc(windata);
74 	if (!oneboard)
75 		win2 = alloc(windata);
76 
77 	if (!setup(disp1, win1) || (!oneboard && !setup(disp2, win2)))
78 		return (false);
79 
80 	if (blackflag) {
81 		win1->color = BLACK;
82 		win1->flipped = true;
83 	} else
84 		win1->color = WHITE;
85 	win_drawboard(win1);
86 
87 	if (!oneboard) {
88 		win2->color = BLACK;
89 		win2->flipped = true;
90 		win_drawboard(win2);
91 	}
92 
93 	return(true);
94 }
95 
96 /* Draw the chess board... */
97 
98 void
win_drawboard(win)99 win_drawboard(win)
100 	windata *win;
101 {
102 	int i, j;
103 
104 	drawgrid(win);
105 
106 	/* Now toss on the squares... */
107 	for (i = 0; i < SIZE; i++)
108 		for (j = 0; j < SIZE; j++)
109 			win_erasepiece(j, i, win->color);
110 
111 	return;
112 }
113 
114 /* Draw one piece. */
115 
116 void
win_drawpiece(p,y,x,wnum)117 win_drawpiece(p, y, x, wnum)
118 	piece *p;
119 	int y, x;
120 	color wnum;
121 {
122     char *bits, *maskbits, *outline;
123     windata *win;
124     char buf[BSIZE];
125     XImage *tmpImage;
126     Pixmap tmpPM, maskPM;
127     XGCValues gc;
128 
129     if (oneboard || (wnum == win1->color))
130 	win = win1;
131     else
132 	win = win2;
133 
134     if (win->flipped) {
135 	y = SIZE - y - 1;
136 	x = SIZE - x - 1;
137     }
138 
139     /*
140       if (debug)
141       fprintf(stderr, "draw a %s at (%d, %d) on board %d\n",
142       piecenames[(int) p->type], y, x, wnum);
143       */
144 
145     if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1);
146 
147     switch (p->type) {
148     case PAWN:
149 	bits = pawn_bits;
150 	maskbits = pawn_mask_bits;
151 	outline = pawn_outline_bits;
152 	break;
153 
154     case ROOK:
155 	bits = rook_bits;
156 	maskbits = rook_mask_bits;
157 	outline = rook_outline_bits;
158 	break;
159 
160     case KNIGHT:
161 	bits = knight_bits;
162 	maskbits = knight_mask_bits;
163 	outline = knight_outline_bits;
164 	break;
165 
166     case BISHOP:
167 	bits = bishop_bits;
168 	maskbits = bishop_mask_bits;
169 	outline = bishop_outline_bits;
170 	break;
171 
172     case QUEEN:
173 	bits = queen_bits;
174 	maskbits = queen_mask_bits;
175 	outline = queen_outline_bits;
176 	break;
177 
178     case KING:
179 	bits = king_bits;
180 	maskbits = king_mask_bits;
181 	outline = king_outline_bits;
182 	break;
183 
184     default:
185 	fprintf(stderr,
186 		"Internal Error: win_drawpiece: bad piece type %d\n",
187 		p->type);
188     }
189 
190     /* There are two things we can do... If this is a black and white
191      * display, we have to shade the square and use an outline if the piece
192      * is white.  We also have to use a mask...  Since we don't want
193      * to use up too many bitmaps, create the mask bitmap, put the bits,
194      * and then destroy it.
195      */
196     if (win->bnw && (p->color == WHITE))
197 	bits = outline;
198     if (win->bnw && !iswhite(win, x, y)) {
199 	XSetState(win->display, DefaultGC(win->display, 0),
200 		  BlackPixel(win->display, 0),
201 		  WhitePixel(win->display, 0), GXcopy, AllPlanes);
202 
203 	tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
204 				shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT);
205 
206 	XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
207 		   0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
208 		   x * (SQUARE_WIDTH + BORDER_WIDTH),
209 		   y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
210 
211 	XFreePixmap(win->display, tmpPM);
212 
213 	XSetFunction(win->display, DefaultGC(win->display, 0),
214 		     GXandInverted);
215 	maskPM = XCreateBitmapFromData(win->display, win->boardwin,
216 				      maskbits, SQUARE_WIDTH, SQUARE_HEIGHT);
217 	XCopyPlane(win->display, maskPM, win->boardwin, DefaultGC(win->display, 0),
218 		   0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
219 		   x * (SQUARE_WIDTH + BORDER_WIDTH),
220 		   y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
221 	XFreePixmap(win->display, maskPM);
222 
223 	XSetFunction(win->display, DefaultGC(win->display, 0),
224 		     GXor);
225 	tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
226 				bits, SQUARE_WIDTH, SQUARE_HEIGHT);
227 	XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
228 		   0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
229 		   x * (SQUARE_WIDTH + BORDER_WIDTH),
230 		   y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
231 	XFreePixmap(win->display, tmpPM);
232 
233 	XSetFunction(win->display, DefaultGC(win->display, 0), GXcopy);
234 
235     } else if (win->bnw){
236 	XSetState(win->display, DefaultGC(win->display, 0),
237 		  BlackPixel(win->display, 0),
238 		  WhitePixel(win->display, 0), GXcopy, AllPlanes);
239 
240 	tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
241 				bits, SQUARE_WIDTH, SQUARE_HEIGHT);
242 	XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
243 		   0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
244 		   x * (SQUARE_WIDTH + BORDER_WIDTH),
245 		   y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
246 	XFreePixmap(win->display, tmpPM);
247     } else {
248 	XSetState(win->display, DefaultGC(win->display, 0),
249 		 ((p->color == WHITE) ? win->whitepiece.pixel :
250 		  			win->blackpiece.pixel),
251 		  (iswhite(win, x, y) ? win->whitesquare.pixel :
252 		   			win->blacksquare.pixel),
253 		  GXcopy, AllPlanes);
254 	tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
255 				bits, SQUARE_WIDTH, SQUARE_HEIGHT);
256 	XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
257 		   0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
258 		   x * (SQUARE_WIDTH + BORDER_WIDTH),
259 		   y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
260 	XFreePixmap(win->display, tmpPM);
261     }
262 
263     if (!record_english) {
264 	gc.foreground = win->textcolor.pixel;
265 	if (iswhite(win, x, y) || win->bnw)
266 	    gc.background = win->whitesquare.pixel;
267 	else
268 	    gc.background = win->blacksquare.pixel;
269 
270 	gc.font = win->small->fid;
271 
272 	XChangeGC(win->display, DefaultGC(win->display, 0),
273 		  GCForeground | GCBackground | GCFont, &gc);
274 
275 	if (!x) {
276 	    sprintf(buf, " %d", SIZE - y);
277 	    XDrawImageString(win->display, win->boardwin,
278 			     DefaultGC(win->display, 0),
279 			     1, (y + 1) * (SQUARE_HEIGHT +
280 					   BORDER_WIDTH) - BORDER_WIDTH +
281 			     win->small->max_bounds.ascent - 1, buf, 2);
282 	}
283 	if (y == SIZE - 1) {
284 	    sprintf(buf, "%c", 'A' + x);
285 	    XDrawImageString(win->display, win->boardwin,
286 			     DefaultGC(win->display, 0),
287 			     x * (SQUARE_WIDTH + BORDER_WIDTH) + 1,
288 			     SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH +
289 			     win->small->max_bounds.ascent - 1, buf, 1);
290 	}
291     }
292     return;
293 }
294 
295 void
win_erasepiece(y,x,wnum)296 win_erasepiece(y, x, wnum)
297 	int y, x;
298 	color wnum;
299 {
300     windata *win;
301     char buf[BSIZE];
302     XGCValues gc;
303     Pixmap tmpPM;
304 
305     if (oneboard || (wnum == win1->color))
306 	win = win1;
307     else
308 	win = win2;
309 
310     if (win->flipped) {
311 	y = SIZE - y - 1;
312 	x = SIZE - x - 1;
313     }
314 
315     /*
316       if (debug)
317       fprintf(stderr, "erase square (%d, %d) on board %d\n", y, x,
318       wnum);
319       */
320 
321     if ((x < 0) || (x > 7) || (y < 0) || (y > 7)) exit(1);
322 
323     if (win->bnw && !iswhite(win, x, y)) {
324 	XSetState(win->display, DefaultGC(win->display, 0),
325 		  BlackPixel(win->display, 0),
326 		  WhitePixel(win->display, 0), GXcopy, AllPlanes);
327 	tmpPM = XCreateBitmapFromData(win->display, win->boardwin,
328 				shade_bits, SQUARE_WIDTH, SQUARE_HEIGHT);
329 
330 	XCopyPlane(win->display, tmpPM, win->boardwin, DefaultGC(win->display, 0),
331 		   0, 0, SQUARE_WIDTH, SQUARE_HEIGHT,
332 		   x * (SQUARE_WIDTH + BORDER_WIDTH),
333 		   y * (SQUARE_HEIGHT + BORDER_WIDTH), 1);
334 
335 	XFreePixmap(win->display, tmpPM);
336     } else {
337 	XSetFillStyle(win->display, DefaultGC(win->display, 0),
338 		      FillSolid);
339 	XSetForeground(win->display, DefaultGC(win->display, 0),
340 		       iswhite(win, x, y) ? win->whitesquare.pixel :
341 		       win->blacksquare.pixel);
342 	XFillRectangle(win->display, win->boardwin,
343 		       DefaultGC(win->display, 0),
344 		       x * (SQUARE_WIDTH + BORDER_WIDTH),
345 		       y * (SQUARE_HEIGHT + BORDER_WIDTH),
346 		       SQUARE_WIDTH, SQUARE_HEIGHT);
347     }
348 
349     if (!record_english) {
350 	gc.foreground = win->textcolor.pixel;
351 	if (iswhite(win, x, y) || win->bnw)
352 	    gc.background = win->whitesquare.pixel;
353 	else
354 	    gc.background = win->blacksquare.pixel;
355 
356 	gc.font = win->small->fid;
357 
358 	XChangeGC(win->display, DefaultGC(win->display, 0),
359 		  GCForeground | GCBackground | GCFont, &gc);
360 
361 	if (!x) {
362 	    sprintf(buf, " %d", SIZE - y);
363 	    XDrawImageString(win->display, win->boardwin,
364 			     DefaultGC(win->display, 0),
365 			     1, (y + 1) * (SQUARE_HEIGHT +
366 					   BORDER_WIDTH) - BORDER_WIDTH +
367 			     win->small->max_bounds.ascent - 1, buf, 2);
368 	}
369 	if (y == SIZE - 1) {
370 	    sprintf(buf, "%c", 'A' + x);
371 	    XDrawImageString(win->display, win->boardwin,
372 			     DefaultGC(win->display, 0),
373 			     x * (SQUARE_WIDTH + BORDER_WIDTH) + 1,
374 			     SIZE * (SQUARE_HEIGHT + BORDER_WIDTH) - BORDER_WIDTH +
375 			     win->small->max_bounds.ascent - 1, buf, 1);
376 	}
377     }
378 
379 
380     return;
381 }
382 
383 void
win_flash(m,wnum)384 win_flash(m, wnum)
385 	move *m;
386 	color wnum;
387 {
388 	windata *win;
389 	int sx, sy, ex, ey, i;
390 
391 	if (oneboard || (wnum == win1->color))
392 		win = win1;
393 	else
394 		win = win2;
395 
396 	if (win->flipped) {
397 		sx = SIZE - m->fromx - 1;
398 		sy = SIZE - m->fromy - 1;
399 		ex = SIZE - m->tox - 1;
400 		ey = SIZE - m->toy - 1;
401 	} else {
402 		sx = m->fromx;
403 		sy = m->fromy;
404 		ex = m->tox;
405 		ey = m->toy;
406 	}
407 	sx = sx * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2;
408 	sy = sy * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2;
409 	ex = ex * (SQUARE_WIDTH + BORDER_WIDTH) + SQUARE_WIDTH / 2;
410 	ey = ey * (SQUARE_HEIGHT + BORDER_WIDTH) + SQUARE_HEIGHT / 2;
411 
412 	XSetFunction(win->display, DefaultGC(win->display, 0), GXinvert);
413 	XSetLineAttributes(win->display, DefaultGC(win->display, 0),
414 		0, LineSolid, 0, 0);
415 	for (i = 0; i < num_flashes * 2; i++) {
416 	    XDrawLine(win->display,win->boardwin,
417 		      DefaultGC(win->display, 0),
418 		      sx, sy, ex, ey);
419 	}
420 
421 	XSetFunction(win->display, DefaultGC(win->display, 0), GXcopy);
422 	return;
423 }
424 
425 /* Handle input from the players. */
426 
427 void
win_process(quick)428 win_process(quick)
429 	bool quick;
430 {
431 	int i, rfd = 0, wfd = 0, xfd = 0;
432 	struct timeval timeout;
433 
434 	timeout.tv_sec = 0;
435 	timeout.tv_usec = (quick ? 0 : 500000);
436 
437 	if (XPending(win1->display))
438 		service(win1);
439 	if (!oneboard) {
440 	    if (XPending(win1->display))
441 		service(win2);
442 	}
443 
444 	if (oneboard)
445 		rfd = 1 << win1->display->fd;
446 	else
447 		rfd = (1 << win1->display->fd) | (1 << win2->display->fd);
448 	if (!(i = select(32, &rfd, &wfd, &xfd, &timeout)))
449 		return;
450 	if (i == -1) {
451 		perror("select");
452 		exit(1);
453 	}
454 	if (rfd & (1 << win1->display->fd))
455 		service(win1);
456 	if (!oneboard && (rfd & (1 << win2->display->fd)))
457 		service(win2);
458 
459 	return;
460 }
461 
462 static void
service(win)463 service(win)
464 	windata *win;
465 {
466 	XEvent ev;
467 
468 	while(XPending(win->display)) {
469 		XNextEvent(win->display, &ev);
470 		if (TxtFilter(win->display, &ev))
471 			continue;
472 
473 		if (ev.xany.window == win->boardwin) {
474 			switch (ev.type) {
475 			    case ButtonPress:
476 				button_pressed(&ev, win);
477 				break;
478 
479 			    case ButtonRelease:
480 				button_released(&ev, win);
481 				break;
482 
483 			    case Expose:
484 				/* Redraw... */
485 				win_redraw(win, &ev);
486 				break;
487 
488 			    case 0:
489 			    case NoExpose:
490 				break;
491 			    default:
492 				fprintf(stderr, "Bad event type %d\n", ev.type);
493 				exit(1);
494 			}
495 		} else if (ev.xany.window == win->wclockwin) {
496 			switch (ev.type) {
497 			    case Expose:
498 				clock_draw(win, WHITE);
499 				break;
500 
501 			    case 0:
502 			    case NoExpose:
503 				break;
504 			    default:
505 				fprintf(stderr, "Bad event type %d\n", ev.type);
506 				exit(1);
507 			}
508 		} else if (ev.xany.window == win->bclockwin) {
509 			switch (ev.type) {
510 			    case Expose:
511 				clock_draw(win, BLACK);
512 				break;
513 
514 			    case 0:
515 			    case NoExpose:
516 				break;
517 			    default:
518 				fprintf(stderr, "Bad event type %d\n", ev.type);
519 				exit(1);
520 			}
521 		} else if (ev.xany.window == win->jailwin) {
522 			switch (ev.type) {
523 			    case Expose:
524 				jail_draw(win);
525 				break;
526 
527 			    case 0:
528 			    case NoExpose:
529 				break;
530 			    default:
531 				fprintf(stderr, "Bad event type %d\n", ev.type);
532 				exit(1);
533 			}
534 		} else if (ev.xany.window == win->buttonwin) {
535 			switch (ev.type) {
536 			    case ButtonPress:
537 				button_service(win, &ev);
538 				break;
539 
540 			    case Expose:
541 				button_draw(win);
542 				break;
543 
544 			    case 0:
545 			    case NoExpose:
546 				break;
547 			    default:
548 				fprintf(stderr, "Bad event type %d\n", ev.type);
549 				exit(1);
550 			}
551 		} else if (ev.xany.window == win->icon) {
552 			icon_refresh(win);
553 		} else if (ev.xany.window == win->basewin) {
554 			message_send(win, &ev);
555 		} else {
556 			fprintf(stderr, "Internal Error: service: bad win\n");
557 			fprintf(stderr, "window = %d, event = %d\n", ev.xany.window,
558 					ev.type);
559 		}
560 	}
561 	return;
562 }
563 
564 void
win_redraw(win,event)565 win_redraw(win, event)
566 	windata *win;
567 	XEvent *event;
568 {
569 	XExposeEvent *ev = &event->xexpose;
570 	int x1, y1, x2, y2, i, j;
571 
572 	drawgrid(win);
573 	if (ev) {
574 		x1 = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
575 		y1 = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
576 		x2 = (ev->x + ev->width) / (SQUARE_WIDTH + BORDER_WIDTH);
577 		y2 = (ev->y + ev->height) / (SQUARE_HEIGHT + BORDER_WIDTH);
578 	} else {
579 		x1 = 0;
580 		y1 = 0;
581 		x2 = SIZE - 1;
582 		y2 = SIZE - 1;
583 	}
584 
585 	if (x1 < 0) x1 = 0;
586 	if (y1 < 0) y1 = 0;
587 	if (x2 < 0) x2 = 0;
588 	if (y2 < 0) y2 = 0;
589 	if (x1 > SIZE - 1) x1 = SIZE - 1;
590 	if (y1 > SIZE - 1) y1 = SIZE - 1;
591 	if (x2 > SIZE - 1) x2 = SIZE - 1;
592 	if (y2 > SIZE - 1) y2 = SIZE - 1;
593 
594 	if (win->flipped) {
595 		y1 = SIZE - y2 - 1;
596 		y2 = SIZE - y1 - 1;
597 		x1 = SIZE - x2 - 1;
598 		x2 = SIZE - x1 - 1;
599 	}
600 
601 	for (i = x1; i <= x2; i++)
602 		for (j = y1; j <= y2; j++) {
603 			if (chessboard->square[j][i].color == NONE)
604 				win_erasepiece(j, i, WHITE);
605 			else
606 				win_drawpiece(&chessboard->square[j][i], j, i,
607 						WHITE);
608 			if (!oneboard) {
609 				if (chessboard->square[j][i].color == NONE)
610 					win_erasepiece(j, i, BLACK);
611 				else
612 					win_drawpiece(&chessboard->square[j][i],
613 							j, i, BLACK);
614 			}
615 		}
616 
617 	return;
618 }
619 
620 static bool
setup(dispname,win)621 setup(dispname, win)
622 	char *dispname;
623 	windata *win;
624 {
625 	char buf[BSIZE], *s;
626 	Pixmap bm, bmask;
627 	Cursor cur;
628 	extern char *program, *recfile;
629 	XSizeHints xsizes;
630 
631 
632 	if (!(win->display = XOpenDisplay(dispname)))
633 		return (false);
634 
635 
636 	/* Now get boolean defaults... */
637 	if ((s = XGetDefault(win->display, program, "noisy")) && eq(s, "on"))
638 		noisyflag = true;
639 	if ((s = XGetDefault(win->display, program, "savemoves")) && eq(s, "on"))
640 		saveflag = true;
641 	if ((s = XGetDefault(win->display, program, "algebraic")) && eq(s, "on"))
642 		record_english = false;
643 	if ((s = XGetDefault(win->display, program, "blackandwhite")) && eq(s, "on"))
644 		bnwflag = true;
645 	if ((s = XGetDefault(win->display, program, "quickrestore")) && eq(s, "on"))
646 		quickflag = true;
647 	if ((s = XGetDefault(win->display, program, "flash")) && eq(s, "on"))
648 		win_flashmove = true;
649 
650 	/* ... numeric variables ... */
651 	if (s = XGetDefault(win->display, program, "numflashes"))
652 		num_flashes = atoi(s);
653 	if (s = XGetDefault(win->display, program, "flashsize"))
654 		flash_size = atoi(s);
655 
656 	/* ... and strings. */
657 	if (s = XGetDefault(win->display, program, "progname"))
658 		progname = s;
659 	if (s = XGetDefault(win->display, program, "proghost"))
660 		proghost = s;
661 	if (s = XGetDefault(win->display, program, "recordfile"))
662 		recfile = s;
663 	if (s = XGetDefault(win->display, program, "blackpiece"))
664 		black_piece_color = s;
665 	if (s = XGetDefault(win->display, program, "whitepiece"))
666 		white_piece_color = s;
667 	if (s = XGetDefault(win->display, program, "blacksquare"))
668 		black_square_color = s;
669 	if (s = XGetDefault(win->display, program, "whitesquare"))
670 		white_square_color = s;
671 	if (s = XGetDefault(win->display, program, "bordercolor"))
672 		border_color = s;
673 	if (s = XGetDefault(win->display, program, "textcolor"))
674 		text_color = s;
675 	if (s = XGetDefault(win->display, program, "textback"))
676 		text_back = s;
677 	if (s = XGetDefault(win->display, program, "errortext"))
678 		error_text = s;
679 	if (s = XGetDefault(win->display, program, "playertext"))
680 		player_text = s;
681 	if (s = XGetDefault(win->display, program, "cursorcolor"))
682 		cursor_color = s;
683 
684 	if ((DisplayPlanes(win->display, 0) == 1) || bnwflag)
685 		win->bnw = true;
686 
687 	/* Allocate colors... */
688 	if (win->bnw) {
689 		win->blackpiece.pixel = BlackPixel (win->display, 0);
690 		win->whitepiece.pixel = WhitePixel (win->display, 0);
691 		win->blacksquare.pixel = BlackPixel (win->display, 0);
692 		win->whitesquare.pixel = WhitePixel (win->display, 0);
693 		win->border.pixel = BlackPixel (win->display, 0);
694 		win->textcolor.pixel = BlackPixel (win->display, 0);
695 		win->textback.pixel = WhitePixel (win->display, 0);
696 		win->playertext.pixel = BlackPixel (win->display, 0);
697 		win->errortext.pixel = BlackPixel (win->display, 0);
698 		win->cursorcolor.pixel = BlackPixel (win->display, 0) ;
699 	} else {
700 	    if (!XParseColor(win->display,
701 			     DefaultColormap(win->display, 0),
702 			     black_piece_color, &win->blackpiece) ||
703 		!XParseColor(win->display,
704 			     DefaultColormap(win->display, 0),
705 			     white_piece_color, &win->whitepiece) ||
706 		!XParseColor(win->display,
707 			     DefaultColormap(win->display, 0),
708 			     black_square_color, &win->blacksquare) ||
709 		!XParseColor(win->display,
710 			     DefaultColormap(win->display, 0),
711 			     white_square_color, &win->whitesquare) ||
712 		!XParseColor(win->display,
713 			     DefaultColormap(win->display, 0),
714 			     border_color, &win->border) ||
715 		!XParseColor(win->display,
716 			     DefaultColormap(win->display, 0),
717 			     text_color, &win->textcolor) ||
718 		!XParseColor(win->display,
719 			     DefaultColormap(win->display, 0),
720 			     text_back, &win->textback) ||
721 		!XParseColor(win->display,
722 			     DefaultColormap(win->display, 0),
723 			     error_text, &win->errortext) ||
724 		!XParseColor(win->display,
725 			     DefaultColormap(win->display, 0),
726 			     player_text, &win->playertext) ||
727 		!XParseColor(win->display,
728 			     DefaultColormap(win->display, 0),
729 			     cursor_color, &win->cursorcolor) ||
730 		!XAllocColor(win->display,
731 			     DefaultColormap(win->display, 0),
732 			     &win->blackpiece) ||
733 		!XAllocColor(win->display,
734 			     DefaultColormap(win->display, 0),
735 			     &win->whitepiece) ||
736 		!XAllocColor(win->display,
737 			     DefaultColormap(win->display, 0),
738 			     &win->blacksquare) ||
739 		!XAllocColor(win->display,
740 			     DefaultColormap(win->display, 0),
741 			     &win->whitesquare) ||
742 		!XAllocColor(win->display,
743 			     DefaultColormap(win->display, 0),
744 			     &win->border) ||
745 		!XAllocColor(win->display,
746 			     DefaultColormap(win->display, 0),
747 			     &win->textcolor) ||
748 		!XAllocColor(win->display,
749 			     DefaultColormap(win->display, 0),
750 			     &win->textback) ||
751 		!XAllocColor(win->display,
752 			     DefaultColormap(win->display, 0),
753 			     &win->errortext) ||
754 		!XAllocColor(win->display,
755 			     DefaultColormap(win->display, 0),
756 			     &win->playertext) ||
757 		!XAllocColor(win->display,
758 			     DefaultColormap(win->display, 0),
759 			     &win->cursorcolor))
760 		fprintf(stderr, "Can't get colors...\n");
761 	}
762 
763 	/* Get fonts... */
764 	if ((win->small = XLoadQueryFont(win->display,SMALL_FONT)) ==
765 	    NULL)
766 		fprintf(stderr, "Can't get small font...\n");
767 
768 	if ((win->medium = XLoadQueryFont(win->display,MEDIUM_FONT))
769 	    == NULL)
770 	    fprintf(stderr, "Can't get medium font...\n");
771 
772 	if ((win->large = XLoadQueryFont(win->display,LARGE_FONT)) ==
773 	    NULL)
774 	    fprintf(stderr, "Can't get large font...\n");
775 
776 
777 	/* Create the windows... */
778 
779 	win->basewin =
780 	    XCreateSimpleWindow(win->display,DefaultRootWindow(win->display),
781 			  BASE_XPOS, BASE_YPOS,
782 			  BASE_WIDTH, BASE_HEIGHT, 0,
783 			  BlackPixel(win->display, 0),
784 			  WhitePixel(win->display, 0));
785 	win->boardwin = XCreateSimpleWindow(win->display,win->basewin,
786 					    BOARD_XPOS, BOARD_YPOS,
787 					    BOARD_WIDTH, BOARD_HEIGHT,
788 					    BORDER_WIDTH,
789 					    win->border.pixel,
790 					    WhitePixel(win->display, 0));
791 	win->recwin = XCreateSimpleWindow(win->display,win->basewin,
792 					  RECORD_XPOS, RECORD_YPOS,
793 					  RECORD_WIDTH, RECORD_HEIGHT,
794 					  BORDER_WIDTH, win->border.pixel,
795 					  win->textback.pixel);
796 	win->jailwin = XCreateSimpleWindow(win->display,win->basewin,
797 					   JAIL_XPOS, JAIL_YPOS,
798 					   JAIL_WIDTH, JAIL_HEIGHT,
799 					   BORDER_WIDTH,
800 					   win->border.pixel,
801 					   win->textback.pixel);
802 	win->wclockwin = XCreateSimpleWindow(win->display,win->basewin,
803 					     WCLOCK_XPOS, WCLOCK_YPOS,
804 					     CLOCK_WIDTH, CLOCK_HEIGHT,
805 					     BORDER_WIDTH, win->border.pixel,
806 					     win->textback.pixel);
807 	win->bclockwin = XCreateSimpleWindow(win->display,win->basewin,
808 					     BCLOCK_XPOS, BCLOCK_YPOS,
809 					     CLOCK_WIDTH, CLOCK_HEIGHT,
810 					     BORDER_WIDTH, win->border.pixel,
811 					     win->textback.pixel);
812 	win->messagewin = XCreateSimpleWindow(win->display,win->basewin,
813 					      MESS_XPOS, MESS_YPOS,
814 					      MESS_WIDTH, MESS_HEIGHT,
815 					      BORDER_WIDTH, win->border.pixel,
816 					      win->textback.pixel);
817 	win->buttonwin = XCreateSimpleWindow(win->display,win->basewin,
818 					     BUTTON_XPOS, BUTTON_YPOS,
819 					     BUTTON_WIDTH, BUTTON_HEIGHT,
820 					     BORDER_WIDTH, win->border.pixel,
821 					     win->textback.pixel);
822 
823 	/* Let's define an icon... */
824 	win->iconpixmap = XCreatePixmapFromBitmapData(win->display,
825 						      win->basewin, icon_bits,
826 						      icon_width, icon_height,
827 						      win->blacksquare.pixel,
828 						      win->whitesquare.pixel,
829 						      1);
830 	xsizes.flags = PSize | PMinSize | PPosition;
831 	xsizes.min_width = BASE_WIDTH;
832 	xsizes.min_height = BASE_HEIGHT;
833 	xsizes.x = BASE_XPOS;
834 	xsizes.y = BASE_YPOS;
835 	XSetStandardProperties(win->display, win->basewin,
836 			       program, program, win->iconpixmap,
837 			       0, NULL, &xsizes);
838 
839 	bm = XCreateBitmapFromData(win->display,
840 				   win->basewin, xchess_bits,
841 				   xchess_width, xchess_height);
842 	bmask = XCreateBitmapFromData(win->display,
843 				   win->basewin, xchess_mask_bits,
844 				   xchess_width, xchess_height);
845 	cur = XCreatePixmapCursor(win->display, bm, bmask,
846 			    &win->cursorcolor,
847 			    &WhitePixel(win->display, 0),
848 			    xchess_x_hot, xchess_y_hot);
849 	XFreePixmap(win->display, bm);
850 	XFreePixmap(win->display, bmask);
851 
852 	XDefineCursor(win->display,win->basewin, cur);
853 
854 	XMapSubwindows(win->display,win->basewin);
855 	XMapRaised(win->display,win->basewin);
856 
857 	XSelectInput(win->display,win->basewin, KeyPressMask);
858 	XSelectInput(win->display,win->boardwin,
859 		     ButtonPressMask | ButtonReleaseMask | ExposureMask);
860 	XSelectInput(win->display,win->recwin,
861 		     ButtonReleaseMask | ExposureMask);
862 	XSelectInput(win->display,win->jailwin, ExposureMask);
863 	XSelectInput(win->display,win->wclockwin, ExposureMask);
864 	XSelectInput(win->display,win->bclockwin, ExposureMask);
865 	XSelectInput(win->display,win->messagewin,
866 		     ButtonReleaseMask | ExposureMask);
867 	XSelectInput(win->display,win->buttonwin,
868 		     ButtonPressMask | ExposureMask);
869 
870 	message_init(win);
871 	record_init(win);
872 	button_draw(win);
873 	jail_init(win);
874 	clock_init(win, WHITE);
875 	clock_init(win, BLACK);
876 	if (timeunit) {
877 		if (timeunit > 1800)
878 			sprintf(buf, "%d moves every %.2lg hours.\n",
879 				movesperunit, ((double) timeunit) / 3600);
880 		else if (timeunit > 30)
881 			sprintf(buf, "%d moves every %.2lg minutes.\n",
882 				movesperunit, ((double) timeunit) / 60);
883 		else
884 			sprintf(buf, "%d moves every %d seconds.\n",
885 				movesperunit, timeunit);
886 		message_add(win, buf, false);
887 	}
888 	return (true);
889 }
890 
891 static void
drawgrid(win)892 drawgrid(win)
893 	windata *win;
894 {
895 	int i;
896 	XGCValues gc;
897 
898 	gc.function = GXcopy;
899 	gc.plane_mask = AllPlanes;
900 	gc.foreground = win->border.pixel;
901 	gc.line_width = 0;
902 	gc.line_style = LineSolid;
903 
904 	XChangeGC(win->display,
905 		  DefaultGC(win->display, 0),
906 		  GCFunction | GCPlaneMask | GCForeground |
907 		  GCLineWidth | GCLineStyle, &gc);
908 
909 	/* Draw the lines... horizontal, */
910 	for (i = 1; i < SIZE; i++)
911 		XDrawLine(win->display, win->boardwin,
912 			  DefaultGC(win->display, 0), 0,
913 			  i * (SQUARE_WIDTH + BORDER_WIDTH) -
914 			      BORDER_WIDTH / 2,
915 			  SIZE * (SQUARE_WIDTH + BORDER_WIDTH),
916 			  i * (SQUARE_WIDTH + BORDER_WIDTH) -
917 			      BORDER_WIDTH / 2);
918 
919 	/* and vertical... */
920 	for (i = 1; i < SIZE; i++)
921 		XDrawLine(win->display, win->boardwin,
922 			  DefaultGC(win->display, 0),
923 			  i * (SQUARE_WIDTH + BORDER_WIDTH) -
924 				BORDER_WIDTH / 2, 0,
925 			  i * (SQUARE_WIDTH + BORDER_WIDTH) -
926 			        BORDER_WIDTH / 2,
927 			  SIZE * (SQUARE_WIDTH + BORDER_WIDTH));
928 	return;
929 }
930 
931 void
win_restart()932 win_restart()
933 {
934 	win1->flipped = false;
935 	win_redraw(win1, (XEvent *) NULL);
936 	if (!oneboard) {
937 		win2->flipped = true;
938 		win_redraw(win2, (XEvent *) NULL);
939 	}
940 	return;
941 }
942 
943 static void
icon_refresh(win)944 icon_refresh(win)
945 	windata *win;
946 {
947 	XCopyArea(win->display, win->iconpixmap, win->icon,
948 		  DefaultGC(win->display, 0),
949 		  0, 0, icon_width, icon_height, 0, 0);
950 	return;
951 }
952 
953