Commit | Line | Data |
---|---|---|
cb290b32 C |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 |