1 /*****************************************************************************/
2 /*									     */
3 /*									     */
4 /*	X patience version 2 -- module X-cards.c			     */
5 /*									     */
6 /*	Card drawing interface for X11					     */
7 /*	written by Heiko Eissfeldt and Michael Bischoff			     */
8 /*	see COPYRIGHT.xpat2 for Copyright details			     */
9 /*									     */
10 /*									     */
11 /*****************************************************************************/
12 #include "X-pat.h"
13 
14 struct graphic graphic;
15 struct card card;
16 int table_clear = 1;
17 
win_game(void)18 void win_game(void) {
19 #if 0
20 #ifdef useXlib
21     XMoveWindow(dpy, finished_win, (graphic.width - FINISHED_W) / 2,
22 		(graphic.height - FINISHED_H) / 2);
23     XMapWindow(dpy, finished_win);
24     redraw_finwin((XExposeEvent *)0);	/* must unmap it later! */
25 #endif
26 #endif
27 #ifdef useXview
28     xv_set(xv_default_server, SERVER_SYNC, FALSE, 0);
29 #else
30     XSync(dpy, 0);	/* show all requests and let it be for now */
31 #endif
32 }
33 
34 
init_gfx(void)35 void init_gfx(void) {
36     XGCValues gcv;
37     long gcflags;
38 
39     blackpixel = BlackPixel(dpy, screen);
40     whitepixel = WhitePixel(dpy, screen);
41 
42 
43     /* make gc for white */
44     gcv.foreground = WhitePixel(dpy, screen);
45     gcv.background = BlackPixel(dpy, screen);
46     gcv.graphics_exposures = False;
47     gcflags = GCForeground | GCBackground | GCGraphicsExposures;
48 
49     whitegc = XCreateGC(dpy, RootWindow(dpy, screen), gcflags, &gcv);
50 
51     /* make gc for black */
52     gcv.foreground = BlackPixel(dpy, screen);
53     gcv.background = WhitePixel(dpy, screen);
54     gcflags = GCForeground | GCBackground | GCGraphicsExposures;
55 
56     blackgc = XCreateGC(dpy, RootWindow(dpy, screen), gcflags, &gcv);
57 }
58 
59 
60 /* this is a helper routine only called by do_move(): */
61 /* it transfers card game.which is unknown to the generic part */
62 /* these transfers do not necessarily affect the appearance on the screen, */
63 /* they are needed due to the design of the game.structures as arrays */
64 /* instead of linked lists */
65 
66 
move_card_data(Cardindex dst,Cardindex src)67 void move_card_data(Cardindex dst, Cardindex src) {
68     game.cards[dst] = game.cards[src];
69     game.visible[dst] = game.visible[src];
70 /*    graphic.cardy[dst] = graphic.cardy[src]; */
71 }
72 
73 
refresh_screen(void)74 void refresh_screen(void) {
75 #ifdef LABER
76     printf("refresh_screen called\n");
77 #endif
78     if (table_clear) {
79 #ifdef LABER
80 	printf("(ignored)\n");
81 #endif
82 	return;
83     }
84     table_clear = 1;
85     XClearArea(dpy, table, 0, 0, 0, 0, True);	/* force redraw */
86 }
87 
88 /* all card drawings go through this routine:			     */
89 /* inform the graphics interface that cards are added (delta > 0)    */
90 /* or removed (delta < 0) from the specified pile. if delta = 0,     */
91 /* then redrawing of the complete pile is necessary (possibly caused */
92 /* by "new game" commands)					     */
93 /* if cards on the pile are marked (selected), the mark is refreshed */
94 
draw_pileupdate(int pile,int delta)95 void draw_pileupdate(int pile, int delta) {
96     struct pilegeometry *p = geo.pg + pile;
97     int cx, cy;
98 
99     if (!game.graphic) {        /* this is off when replaying saved games */
100 	/* only log changes */
101 	if (game.pile_changed[pile] == PILE_UNCHANGED)
102 	    game.pile_changed[pile] = delta;
103 	else
104 	    if ((delta > 0 && game.pile_changed[pile] > 0) ||
105 		(delta < 0 && game.pile_changed[pile] < 0))
106 		game.pile_changed[pile] += delta;
107 	    else
108 		game.pile_changed[pile] = 0;
109         return;
110     }
111     if (game.disable[pile])	/* don't draw THIS pile */
112 	return;
113     if (NOT_DISPLAYED(geo.pg+pile))
114 	return;			/* draw nothing */
115 
116     cx = p->x + p->ox;		/* card position of lowest card */
117     cy = p->y + p->oy;
118     if (EMPTY(pile)) {		/* draw empty pile */
119 	int c;
120 	XClearArea(dpy, table, p->x, p->y, p->w, p->h, False);
121 	switch (game.piletype[pile]) {
122 	case Stack:
123 	    c = SUITSYMBOL + SUIT(pile);
124 	    break;
125 	default:
126 	    c = OUTLINE;
127 	    break;
128 	}
129 	PaintCard(cx, cy, c, 0, 0);
130 	return;
131     }
132     if (!p->cdx && !p->cdy) {	/* only topmost card is visible */
133 	Cardindex c;
134 	c = INDEX_OF_LAST_CARD(pile);
135 	PaintCard(cx, cy, game.visible[c] ? game.cards[c] : CARDBACK, 0, 0);
136     } else {
137 	if (pile_resize(pile))	/* delta changed => complete redraw */
138 	    delta = 0;
139 
140 	if ((p->cdx < 0 || p->cdy < 0) && delta < 0)
141 	    /* this does not work correctly yet. simply avoid the case */
142 	    delta = 0;
143 
144 	if (delta < 0) {	/* cards were removed. Clear area and redraw top */
145 	    int x, y;
146 	    if (p->cdx) {
147 		x = (CARDS_ON_PILE(pile)-1) * p->cdx + geo.cw - geo.rx;
148 		y = (CARDS_ON_PILE(pile)-1) * p->cdy;
149 		XClearArea(dpy, table, p->x+x, p->y+y, p->w-x, p->h-y, False);
150 	    }
151 	    if (p->cdy) {
152 		x = (CARDS_ON_PILE(pile)-1) * p->cdx;
153 		y = (CARDS_ON_PILE(pile)-1) * p->cdy + geo.cw - geo.rx;
154 		XClearArea(dpy, table, p->x+x, p->y+y, p->w-x, p->h-y, False);
155 	    }
156 	    delta = 1;	/* only last card is to be drawn new */
157 	} else if (!delta) {	/* draw complete pile */
158 	    XClearArea(dpy, table, p->x, p->y, p->w, p->h, False);
159 	    delta = CARDS_ON_PILE(pile);
160 	}
161 	/* (delta > 0) */
162 	/* draw last cards */
163 	{   Cardindex c = INDEX_OF_LAST_CARD(pile) + 1 - delta;
164 	    int i = c - INDEX_OF_FIRST_CARD(pile);
165 /*	    printf("Drawing %d cards on slot %d: d=%d,%d\n",
166 		   delta, pile, p->cdx, p->cdy); */
167 	    while (--delta >= 0) {
168 		int pw, ph;	/* paint-width and height */
169 		pw = geo.cw;
170 		ph = geo.ch;
171 		if (delta) {
172 		    /* Not the last card. May use card clipping optimisation */
173 		    if (p->cdx == 0 && p->cdy > 0)
174 			ph = p->cdy + geo.ry;
175 		    if (p->cdy == 0 && p->cdx > 0)
176 			pw = p->cdx + geo.rx;
177 		}
178 		PaintCard(cx + p->cdx*i,
179 			  cy + p->cdy*i,
180 			  (game.visible[c] ? game.cards[c] : CARDBACK),
181 			  pw, ph);
182 		++c;
183 		++i;
184 	    }
185 	}
186     }
187     if (game.srcind >= 0 && getpile(game.srcind) == pile)
188 	show_mark(True);
189 }
190