1 /*
2 * src/client/match.c, part of Complete Goban (player program)
3 * Copyright (C) 1996 William Shubert
4 * See "configure.h.in" for more copyright information.
5 */
6
7 #include <wms.h>
8 #include "../msg.h"
9 #include <but/but.h>
10 #include <but/plain.h>
11 #include <but/ctext.h>
12 #include <but/textin.h>
13 #include <but/checkbox.h>
14 #include <abut/msg.h>
15 #include "../goTime.h"
16 #ifdef _CLIENT_MATCH_H_
17 Levelization Error.
18 #endif
19 #include "match.h"
20
21
22 /**********************************************************************
23 * Forward Declarations
24 **********************************************************************/
25 static ButOut resize(ButWin *win);
26 static ButOut destroy(ButWin *win);
27 static ButOut newSize(But *but, const char *value);
28 static ButOut newHcap(But *but, const char *value);
29 static ButOut newKomi(But *but, const char *value);
30 static ButOut newMainTime(But *but, const char *value);
31 static ButOut newBYTime(But *but, const char *value);
32 static ButOut okPressed(But *but);
33 static ButOut cancelPressed(But *but);
34 static ButOut newFree(But *but, bool newVal);
35 static ButOut swapPressed(But *but);
36 static CliMatch *playerLookup(CliMatch *chain, const char *player);
37 static ButOut changeMain(But *but);
38 static ButOut changeBy(But *but);
39 static ButOut changeSize(But *but);
40 static ButOut changeKomi(But *but);
41 static ButOut changeHcap(But *but);
42
43
44 /**********************************************************************
45 * Functions
46 **********************************************************************/
cliMatch_matchCommand(CliData * data,const char * command,CliMatch ** next,int rankDiff)47 CliMatch *cliMatch_matchCommand(CliData *data, const char *command,
48 CliMatch **next, int rankDiff) {
49 char oppName[21];
50 char colorChar;
51 int args, size, mainTime, byTime;
52 CliMatch *match;
53
54 args = sscanf(command, "Use <match %20s %c %d %d %d>",
55 oppName, &colorChar, &size, &mainTime, &byTime);
56 assert(args == 5);
57 assert((colorChar == 'W') || (colorChar == 'B'));
58 match = playerLookup(*next, oppName);
59 if (match == NULL) {
60 /* Start up a new match window. */
61 match = cliMatch_create(data, oppName, next, rankDiff);
62 if ((colorChar == 'B') != match->meFirst)
63 swapPressed(match->swap);
64 } else {
65 /* Modify an old one. */
66 XRaiseWindow(butEnv_dpy(butWin_env(match->win)), butWin_xwin(match->win));
67 if ((colorChar == 'B') != match->meFirst)
68 swapPressed(match->swap);
69 }
70 str_print(&data->cmdBuild, "%d", match->size = size);
71 butTextin_set(match->sizeIn, str_chars(&data->cmdBuild), TRUE);
72 goTime_str(match->mainTime = mainTime * 60, &data->cmdBuild);
73 butTextin_set(match->mainIn, str_chars(&data->cmdBuild), TRUE);
74 goTime_str(match->byTime = byTime * 60, &data->cmdBuild);
75 butTextin_set(match->byIn, str_chars(&data->cmdBuild), TRUE);
76 match->state = cliMatch_recvd;
77 butText_set(match->title, msg_cliGameSetupRecvd);
78 return(match);
79 }
80
81
cliMatch_create(CliData * data,const char * oppName,CliMatch ** next,int rankDiff)82 CliMatch *cliMatch_create(CliData *data, const char *oppName,
83 CliMatch **next, int rankDiff) {
84 CliMatch *m;
85 Cgoban *cg;
86 int i, h, w;
87 char curText[20];
88 bool err;
89 uint flags;
90
91 assert(MAGIC(data));
92 m = playerLookup(*next, oppName);
93 if (m != NULL) {
94 XRaiseWindow(butEnv_dpy(butWin_env(m->win)), butWin_xwin(m->win));
95 return(m);
96 }
97 cg = data->cg;
98 m = wms_malloc(sizeof(CliMatch));
99 MAGIC_SET(m);
100 m->next = *next;
101 m->prev = next;
102 *next = m;
103 m->data = data;
104 m->state = cliMatch_nil;
105 if (rankDiff == 0) {
106 m->meFirst = clp_getBool(cg->clp, "client.match.meFirst");
107 m->komi = 5.5;
108 m->hcap = 0;
109 } else if (rankDiff > 0) {
110 m->meFirst = FALSE;
111 m->komi = 0.5;
112 m->hcap = 0;
113 } else /* rankDiff < 0 */ {
114 m->meFirst = TRUE;
115 m->komi = 0.5;
116 m->hcap = 0;
117 }
118 if (m->meFirst) {
119 str_initChars(&m->wName, oppName);
120 str_initChars(&m->bName, str_chars(&data->userName));
121 } else {
122 str_initChars(&m->bName, oppName);
123 str_initChars(&m->wName, str_chars(&data->userName));
124 }
125 h = cg->fontH * 18 + butEnv_stdBw(cg->env) * 19;
126 w = (h * 1.4142136) + 0.5;
127 m->win = butWin_create(m, cg->env, "Server Game Setup",
128 w, h, NULL, NULL, resize, destroy);
129 if (m->next == NULL) {
130 /*
131 * We only want to set the window to the "standard" place if it is the
132 * first one. Otherwise all the windows would stack up on each other,
133 * which is kind of annoying.
134 */
135 i = clp_iGetInt(cg->clp, "client.match.x", &err);
136 if (!err)
137 butWin_setX(m->win, i);
138 i = clp_iGetInt(cg->clp, "client.match.y", &err);
139 if (!err)
140 butWin_setY(m->win, i);
141 }
142 butWin_activate(m->win);
143 m->bg = butBoxFilled_create(m->win, 0, BUT_DRAWABLE);
144 butBoxFilled_setPixmaps(m->bg, cg->bgLitPixmap, cg->bgShadPixmap,
145 cg->bgPixmap);
146
147 m->title = butText_create(m->win, 1, BUT_DRAWABLE, msg_cliGameSetup,
148 butText_center);
149 butText_setFont(m->title, 2);
150
151 m->namesBox = butBox_create(m->win, 1, BUT_DRAWABLE);
152 butBox_setPixmaps(m->namesBox, cg->bgLitPixmap, cg->bgShadPixmap);
153
154 m->wBox = butBoxFilled_create(m->win, 1, BUT_DRAWABLE);
155 butBoxFilled_setColors(m->wBox, BUT_LIT, BUT_SHAD, BUT_BG);
156 str_print(&data->cmdBuild, CGBUTS_WSTONECHAR " %s", str_chars(&m->wName));
157 m->wTitle = butText_create(m->win, 2, BUT_DRAWABLE,
158 str_chars(&data->cmdBuild), butText_left);
159
160 m->bBox = butBoxFilled_create(m->win, 1, BUT_DRAWABLE);
161 butBoxFilled_setColors(m->bBox, BUT_LIT, BUT_SHAD, BUT_BG);
162 str_print(&data->cmdBuild, CGBUTS_BSTONECHAR " %s", str_chars(&m->bName));
163 m->bTitle = butText_create(m->win, 2, BUT_DRAWABLE,
164 str_chars(&data->cmdBuild), butText_left);
165
166 m->swap = butAct_create(swapPressed, m, m->win, 1,
167 BUT_DRAWABLE|BUT_PRESSABLE,
168 msg_swapColors, BUT_ALEFT|BUT_ARIGHT);
169
170 m->size = clp_getInt(cg->clp, "client.match.size");
171 m->mainTime = clp_getInt(cg->clp, "client.match.mainTime");
172 m->byTime = clp_getInt(cg->clp, "client.match.byTime");
173
174 m->rulesBox = butBox_create(m->win, 1, BUT_DRAWABLE);
175 butBox_setPixmaps(m->rulesBox, cg->bgLitPixmap, cg->bgShadPixmap);
176 m->sizeStr = butText_create(m->win, 1, BUT_DRAWABLE,
177 msg_boardSize, butText_center);
178 sprintf(curText, "%d", m->size);
179 m->sizeIn = butTextin_create(newSize, m, m->win, 1,
180 BUT_DRAWABLE|BUT_PRESSABLE, curText, 10);
181 flags = BUT_DRAWABLE;
182 if (m->size < 19)
183 flags |= BUT_PRESSABLE;
184 m->sizeUp = butAct_create(changeSize, m, m->win, 1, flags, CGBUTS_FWDCHAR,
185 BUT_RRIGHT|BUT_SLEFT);
186 flags = BUT_DRAWABLE;
187 if (m->size > 9)
188 flags |= BUT_PRESSABLE;
189 m->sizeDown = butAct_create(changeSize, m, m->win, 1, flags, CGBUTS_BACKCHAR,
190 BUT_RLEFT|BUT_SRIGHT);
191
192 m->hcapStr = butText_create(m->win, 1, BUT_DRAWABLE,
193 msg_handicap, butText_center);
194 sprintf(curText, "%d", m->hcap);
195 m->hcapIn = butTextin_create(newHcap, m, m->win, 1,
196 BUT_DRAWABLE|BUT_PRESSABLE, curText, 10);
197 flags = BUT_DRAWABLE;
198 if (m->hcap < 9)
199 flags |= BUT_PRESSABLE;
200 m->hcapUp = butAct_create(changeHcap, m, m->win, 1, flags, CGBUTS_FWDCHAR,
201 BUT_RRIGHT|BUT_SLEFT);
202 flags = BUT_DRAWABLE;
203 if (m->hcap > 0)
204 flags |= BUT_PRESSABLE;
205 m->hcapDown = butAct_create(changeHcap, m, m->win, 1, flags, CGBUTS_BACKCHAR,
206 BUT_RLEFT|BUT_SRIGHT);
207
208 m->komiStr = butText_create(m->win, 1, BUT_DRAWABLE,
209 msg_komi, butText_center);
210 sprintf(curText, "%g", m->komi);
211 m->komiIn = butTextin_create(newKomi, m, m->win, 1,
212 BUT_DRAWABLE|BUT_PRESSABLE, curText, 10);
213 m->komiUp = butAct_create(changeKomi, m, m->win, 1,
214 BUT_DRAWABLE|BUT_PRESSABLE, CGBUTS_FWDCHAR,
215 BUT_RRIGHT|BUT_SLEFT);
216 m->komiDown = butAct_create(changeKomi, m, m->win, 1,
217 BUT_DRAWABLE|BUT_PRESSABLE, CGBUTS_BACKCHAR,
218 BUT_RLEFT|BUT_SRIGHT);
219
220 m->timeBox = butBox_create(m->win, 1, BUT_DRAWABLE);
221 butBox_setPixmaps(m->timeBox, cg->bgLitPixmap, cg->bgShadPixmap);
222
223 m->mainStr = butText_create(m->win, 1, BUT_DRAWABLE,
224 msg_primaryTime, butText_center);
225 m->mainIn = butTextin_create(newMainTime, m, m->win, 1,
226 BUT_PRESSABLE|BUT_DRAWABLE,
227 clp_getStr(cg->clp, "client.match.mainTime"),
228 10);
229 m->mainUp1 = butAct_create(changeMain, m, m->win, 1,
230 BUT_DRAWABLE|BUT_PRESSABLE, CGBUTS_FWDCHAR,
231 BUT_SRIGHT|BUT_SLEFT);
232 flags = BUT_DRAWABLE;
233 m->mainTime = goTime_parseChars(butTextin_get(m->mainIn), FALSE, NULL);
234 if (m->mainTime > 0)
235 flags |= BUT_PRESSABLE;
236 m->mainDown1 = butAct_create(changeMain, m, m->win, 1, flags,
237 CGBUTS_BACKCHAR, BUT_SRIGHT|BUT_SLEFT);
238 m->mainUp5 = butAct_create(changeMain, m, m->win, 1,
239 BUT_DRAWABLE|BUT_PRESSABLE, CGBUTS_FFCHAR,
240 BUT_RRIGHT|BUT_SLEFT);
241 m->mainDown5 = butAct_create(changeMain, m, m->win, 1, flags,
242 CGBUTS_REWCHAR, BUT_RLEFT|BUT_SRIGHT);
243
244 m->byStr = butText_create(m->win, 1, BUT_DRAWABLE,
245 msg_byoYomi, butText_center);
246 m->byIn = butTextin_create(newBYTime, m, m->win, 1,
247 BUT_PRESSABLE|BUT_DRAWABLE,
248 clp_getStr(cg->clp, "client.match.byTime"), 10);
249 m->byTime = goTime_parseChars(butTextin_get(m->byIn), FALSE, NULL);
250 m->byUp1 = butAct_create(changeBy, m, m->win, 1, BUT_DRAWABLE|BUT_PRESSABLE,
251 CGBUTS_FWDCHAR, BUT_SRIGHT|BUT_SLEFT);
252 flags = BUT_DRAWABLE;
253 if (m->byTime > 0)
254 flags |= BUT_PRESSABLE;
255 m->byDown1 = butAct_create(changeBy, m, m->win, 1, flags, CGBUTS_BACKCHAR,
256 BUT_SRIGHT|BUT_SLEFT);
257 m->byUp5 = butAct_create(changeBy, m, m->win, 1, BUT_DRAWABLE|BUT_PRESSABLE,
258 CGBUTS_FFCHAR, BUT_RRIGHT|BUT_SLEFT);
259 m->byDown5 = butAct_create(changeBy, m, m->win, 1, flags, CGBUTS_REWCHAR,
260 BUT_RLEFT|BUT_SRIGHT);
261
262 m->freeTitle = butText_create(m->win, 1, BUT_DRAWABLE|BUT_PRESSABLE,
263 msg_freeGame, butText_center);
264 m->freeGame = butCb_create(newFree, m, m->win, 1, BUT_DRAWABLE|BUT_PRESSABLE,
265 clp_getBool(cg->clp, "client.match.free"));
266
267 m->help = butCt_create(cgoban_createHelpWindow,
268 &help_cliMatch, m->win, 1,
269 BUT_DRAWABLE|BUT_PRESSABLE, msg_help);
270 m->ok = butCt_create(okPressed, m, m->win, 1,
271 BUT_DRAWABLE|BUT_PRESSABLE, msg_ok);
272 m->cancel = butCt_create(cancelPressed, m, m->win, 1,
273 BUT_DRAWABLE|BUT_PRESSABLE, msg_cancel);
274
275 return(m);
276 }
277
278
cliMatch_destroy(CliMatch * match)279 void cliMatch_destroy(CliMatch *match) {
280 assert(MAGIC(match));
281 butWin_destroy(match->win);
282 }
283
284
cliMatch_destroyChain(CliMatch * match,const char * oppName,int * hcap,float * komi,bool * free)285 bool cliMatch_destroyChain(CliMatch *match, const char *oppName,
286 int *hcap, float *komi, bool *free) {
287 bool result = FALSE;
288
289 /*
290 * This code wouldn't work if things were done right in the but library
291 * and the windows were destroyed as soon as I asked for it. But since
292 * the library is too broken for me to fix right now I'll have to do it
293 * this way. The second assert in the loop will fail when the but library
294 * is rewritten to do things right.
295 */
296 while (match != NULL) {
297 assert(MAGIC(match));
298 if (oppName != NULL) {
299 if (!strcmp(oppName, str_chars(&match->wName)) ||
300 !strcmp(oppName, str_chars(&match->bName))) {
301 result = TRUE;
302 *hcap = match->hcap;
303 *komi = match->komi;
304 *free = butCb_get(match->freeGame);
305 match->state = cliMatch_nil;
306 }
307 }
308 cliMatch_destroy(match);
309 assert(MAGIC(match));
310 match = match->next;
311 }
312 return(result);
313 }
314
315
resize(ButWin * win)316 static ButOut resize(ButWin *win) {
317 CliMatch *m = butWin_packet(win);
318 Cgoban *cg;
319 int w, butW, h, x, y;
320 int bw, fh;
321 ButEnv *env;
322
323 assert(MAGIC(m));
324 cg = m->data->cg;
325 assert(MAGIC(cg));
326 env = cg->env;
327 bw = butEnv_stdBw(env);
328 fh = cg->fontH;
329 w = butWin_w(win);
330 h = butWin_h(win);
331 butW = w/2-5*bw;
332
333 but_resize(m->bg, 0,0, w,h);
334 but_resize(m->title, 0,bw*2, w, fh*2);
335
336 but_resize(m->namesBox, bw,bw*3+fh*2, w-bw*2,bw*4+fh*2);
337 but_resize(m->wBox, bw*3, bw*5+fh*2,
338 w/2 - (bw * 4 + fh * 4), fh * 2);
339 but_resize(m->wTitle, bw * 5, bw * 5 + fh * 2,
340 w/2 - (bw * 8 + fh * 4), fh * 2);
341 but_resize(m->bBox, w/2 + bw + fh*4, bw*5+fh*2,
342 w - (w/2+bw*4 + fh * 4), fh*2);
343 but_resize(m->bTitle, w/2 + bw * 3 + fh*4, bw*5+fh*2,
344 w - (w/2+bw*8 + fh * 4), fh*2);
345
346 but_resize(m->swap, w/2 - fh * 4, bw*5+fh*2, fh * 8, fh * 2);
347
348 y = bw*7+fh*4;
349 but_resize(m->rulesBox, bw,y, w/2-bw,fh*12+bw*9);
350
351 but_resize(m->sizeStr, bw*3,y+bw*2+fh*0, butW,fh*2);
352 but_resize(m->sizeIn, bw*3+fh*2,y+bw*3+fh*2, butW-fh*4,fh*2);
353 but_resize(m->sizeDown, bw*3,y+bw*3+fh*2, fh*2,fh*2);
354 but_resize(m->sizeUp, bw*3+butW-fh*2,y+bw*3+fh*2, fh*2,fh*2);
355
356 but_resize(m->hcapStr, bw*3,y+bw*4+fh*4, butW,fh*2);
357 but_resize(m->hcapIn, bw*3+fh*2,y+bw*5+fh*6, butW-fh*4,fh*2);
358 but_resize(m->hcapDown, bw*3,y+bw*5+fh*6, fh*2,fh*2);
359 but_resize(m->hcapUp, bw*3+butW-fh*2,y+bw*5+fh*6, fh*2,fh*2);
360
361 but_resize(m->komiStr, bw*3,y+bw*6+fh*8, butW,fh*2);
362 but_resize(m->komiIn, bw*3+fh*2,y+bw*7+fh*10, butW-fh*4,fh*2);
363 but_resize(m->komiDown, bw*3,y+bw*7+fh*10, fh*2,fh*2);
364 but_resize(m->komiUp, bw*3+butW-fh*2,y+bw*7+fh*10, fh*2,fh*2);
365
366 but_resize(m->timeBox, w/2,y, w-bw-w/2,fh*12+bw*9);
367 x = w/2 + bw*2;
368 butW = w-x-bw*3;
369
370 but_resize(m->mainStr, x,y+bw*2+fh*0, butW,fh*2);
371 but_resize(m->mainIn, x+fh*4,y+bw*3+fh*2, butW-fh*8,fh*2);
372 but_resize(m->mainDown5, x,y+bw*3+fh*2, fh*2,fh*2);
373 but_resize(m->mainDown1, x+fh*2,y+bw*3+fh*2, fh*2,fh*2);
374 but_resize(m->mainUp1, x+butW-fh*4,y+bw*3+fh*2, fh*2,fh*2);
375 but_resize(m->mainUp5, x+butW-fh*2,y+bw*3+fh*2, fh*2,fh*2);
376
377 but_resize(m->byStr, x,y+bw*4+fh*4, butW,fh*2);
378 but_resize(m->byIn, x+fh*4,y+bw*5+fh*6, butW-fh*8,fh*2);
379 but_resize(m->byDown5, x,y+bw*5+fh*6, fh*2,fh*2);
380 but_resize(m->byDown1, x+fh*2,y+bw*5+fh*6, fh*2,fh*2);
381 but_resize(m->byUp1, x+butW-fh*4,y+bw*5+fh*6, fh*2,fh*2);
382 but_resize(m->byUp5, x+butW-fh*2,y+bw*5+fh*6, fh*2,fh*2);
383
384 but_resize(m->freeTitle, x,y+bw*6+fh*8, butW,fh*2);
385 but_resize(m->freeGame, x + butW/2 - fh,y+bw*7+fh*10, fh*2,fh*2);
386
387 but_resize(m->help, bw*2,y+bw*10+fh*12, (w-bw*6+1)/3,fh*2);
388 but_resize(m->cancel, bw*3+(w-bw*6+1)/3,y+bw*10+fh*12,
389 w-2*(bw*3+(w-bw*6+1)/3),fh*2);
390 but_resize(m->ok, w-(bw*2+(w-bw*6+1)/3),y+bw*10+fh*12,
391 (w-bw*6+1)/3,fh*2);
392
393 return(0);
394 }
395
396
destroy(ButWin * win)397 static ButOut destroy(ButWin *win) {
398 CliMatch *m;
399 Clp *clp;
400 Str *opp;
401
402 m = butWin_packet(win);
403 assert(MAGIC(m));
404 if (m->state != cliMatch_nil) {
405 if (m->meFirst)
406 opp = &m->wName;
407 else
408 opp = &m->bName;
409 str_print(&m->data->cmdBuild, "decline %s\n", str_chars(opp));
410 cliConn_send(&m->data->conn, str_chars(&m->data->cmdBuild));
411 }
412 clp = m->data->cg->clp;
413 clp_setInt(clp, "client.match.x", butWin_x(win));
414 clp_setInt(clp, "client.match.y", butWin_y(win));
415 clp_setBool(clp, "client.match.meFirst", m->meFirst);
416 str_deinit(&m->wName);
417 str_deinit(&m->bName);
418 *(m->prev) = m->next;
419 MAGIC_UNSET(m);
420 wms_free(m);
421 return(0);
422 }
423
424
newSize(But * but,const char * value)425 static ButOut newSize(But *but, const char *value) {
426 CliMatch *m = but_packet(but);
427 int newSize;
428 char curValue[3];
429
430 assert(MAGIC(m));
431 newSize = atoi(value);
432 if ((newSize > 19) ||
433 !clp_setStr(m->data->cg->clp, "client.match.size", value)) {
434 str_print(&m->data->cmdBuild, msg_badSize, value, 19);
435 cgoban_createMsgWindow(m->data->cg, "Cgoban Error",
436 str_chars(&m->data->cmdBuild));
437 sprintf(curValue, "%d", m->size);
438 butTextin_set(but, curValue, FALSE);
439 return(BUTOUT_ERR);
440 }
441 m->size = newSize;
442 if (m->size > 9) {
443 but_setFlags(m->sizeDown, BUT_PRESSABLE);
444 } else {
445 but_setFlags(m->sizeDown, BUT_NOPRESS);
446 }
447 if (m->size < 19)
448 but_setFlags(m->sizeUp, BUT_PRESSABLE);
449 else
450 but_setFlags(m->sizeUp, BUT_NOPRESS);
451 return(0);
452 }
453
454
newHcap(But * but,const char * value)455 static ButOut newHcap(But *but, const char *value) {
456 CliMatch *m = but_packet(but);
457 int newHcap;
458 char curValue[2];
459 bool err;
460
461 assert(MAGIC(m));
462 newHcap = wms_atoi(value, &err);
463 if ((newHcap > 9) || (newHcap == 1) || (newHcap < 0) || err) {
464 str_print(&m->data->cmdBuild, msg_badHcap, value, 9);
465 cgoban_createMsgWindow(m->data->cg, "Cgoban Error",
466 str_chars(&m->data->cmdBuild));
467 sprintf(curValue, "%d", m->hcap);
468 butTextin_set(but, curValue, FALSE);
469 return(BUTOUT_ERR);
470 }
471 m->hcap = newHcap;
472 if (m->hcap > 0) {
473 but_setFlags(m->hcapDown, BUT_PRESSABLE);
474 } else {
475 but_setFlags(m->hcapDown, BUT_NOPRESS);
476 }
477 if (m->hcap < 9)
478 but_setFlags(m->hcapUp, BUT_PRESSABLE);
479 else
480 but_setFlags(m->hcapUp, BUT_NOPRESS);
481 return(0);
482 }
483
484
newKomi(But * but,const char * value)485 static ButOut newKomi(But *but, const char *value) {
486 CliMatch *m = but_packet(but);
487 float newKomi;
488 char curValue[7];
489 bool err;
490
491 assert(MAGIC(m));
492 newKomi = wms_atof(value, &err);
493 if ((newKomi > 999.5) || (newKomi < -999.5) || err ||
494 ((int)(newKomi * 2.0) != newKomi * 2.0)) {
495 str_print(&m->data->cmdBuild, msg_badKomi, value);
496 cgoban_createMsgWindow(m->data->cg, "Cgoban Error",
497 str_chars(&m->data->cmdBuild));
498 sprintf(curValue, "%g", m->komi);
499 butTextin_set(but, curValue, FALSE);
500 return(BUTOUT_ERR);
501 }
502 m->komi = newKomi;
503 if (m->komi > -99.5) {
504 but_setFlags(m->hcapDown, BUT_PRESSABLE);
505 } else {
506 but_setFlags(m->hcapDown, BUT_NOPRESS);
507 }
508 if (m->hcap < 99.5)
509 but_setFlags(m->hcapUp, BUT_PRESSABLE);
510 else
511 but_setFlags(m->hcapUp, BUT_NOPRESS);
512 return(0);
513 }
514
515
newMainTime(But * but,const char * value)516 static ButOut newMainTime(But *but, const char *value) {
517 CliMatch *m = but_packet(but);
518 Str errMsg;
519
520 assert(MAGIC(m));
521 if (!clp_setStr(m->data->cg->clp, "client.match.mainTime", value)) {
522 str_init(&errMsg);
523 str_print(&errMsg, msg_badTime, value);
524 cgoban_createMsgWindow(m->data->cg, "Cgoban Error", str_chars(&errMsg));
525 goTime_str(m->mainTime, &errMsg);
526 butTextin_set(but, str_chars(&errMsg), FALSE);
527 str_deinit(&errMsg);
528 return(BUTOUT_ERR);
529 }
530 m->mainTime = goTime_parseChars(value, FALSE, NULL);
531 if (but_getFlags(but) & BUT_KEYED)
532 but_setFlags(m->byIn, BUT_KEYED);
533 if (m->mainTime > 0) {
534 but_setFlags(m->mainDown1, BUT_PRESSABLE);
535 but_setFlags(m->mainDown5, BUT_PRESSABLE);
536 } else {
537 but_setFlags(m->mainDown1, BUT_NOPRESS);
538 but_setFlags(m->mainDown5, BUT_NOPRESS);
539 }
540 return(0);
541 }
542
543
newBYTime(But * but,const char * value)544 static ButOut newBYTime(But *but, const char *value) {
545 CliMatch *m = but_packet(but);
546 Str errMsg;
547
548 assert(MAGIC(m));
549 if (!clp_setStr(m->data->cg->clp, "client.match.byTime", value)) {
550 str_init(&errMsg);
551 str_print(&errMsg, msg_badTime, value);
552 cgoban_createMsgWindow(m->data->cg, "Cgoban Error", str_chars(&errMsg));
553 goTime_str(m->byTime, &errMsg);
554 butTextin_set(but, str_chars(&errMsg), FALSE);
555 str_deinit(&errMsg);
556 return(BUTOUT_ERR);
557 }
558 m->byTime = goTime_parseChars(value, FALSE, NULL);
559 but_setFlags(but, BUT_NOKEY);
560 if (m->byTime > 0) {
561 but_setFlags(m->byDown1, BUT_PRESSABLE);
562 but_setFlags(m->byDown5, BUT_PRESSABLE);
563 } else {
564 but_setFlags(m->byDown1, BUT_NOPRESS);
565 but_setFlags(m->byDown5, BUT_NOPRESS);
566 }
567 return(0);
568 }
569
570
okPressed(But * but)571 static ButOut okPressed(But *but) {
572 CliMatch *m = but_packet(but);
573 const char *oppName, *myName;
574 ButOut result;
575
576 assert(MAGIC(m));
577 if (m->meFirst) {
578 oppName = str_chars(&m->wName);
579 myName = str_chars(&m->bName);
580 } else {
581 myName = str_chars(&m->wName);
582 oppName = str_chars(&m->bName);
583 }
584 result = newSize(m->sizeIn, butTextin_get(m->sizeIn)) |
585 newMainTime(m->mainIn, butTextin_get(m->mainIn)) |
586 newBYTime(m->byIn, butTextin_get(m->byIn));
587 if (!(result & BUTOUT_ERR)) {
588 str_print(&m->data->cmdBuild,
589 "match %s %c %d %d %d\n"
590 "tell %s CLIENT: <cgoban " VERSION "> match %s wants "
591 "handicap %d, komi %g",
592 oppName,
593 (int)("wb"[m->meFirst]),
594 m->size, (m->mainTime + 59) / 60, (m->byTime + 59) / 60,
595 oppName, myName, m->hcap, m->komi);
596 if (butCb_get(m->freeGame))
597 str_catChars(&m->data->cmdBuild, ", free\n");
598 else
599 str_catChar(&m->data->cmdBuild, '\n');
600 cliConn_send(&m->data->conn, str_chars(&m->data->cmdBuild));
601 m->state = cliMatch_sent;
602 butText_set(m->title, msg_cliGameSetupSent);
603 }
604 return(result);
605 }
606
607
cancelPressed(But * but)608 static ButOut cancelPressed(But *but) {
609 butWin_destroy(but_win(but));
610 return(0);
611 }
612
613
newFree(But * but,bool newVal)614 static ButOut newFree(But *but, bool newVal) {
615 CliMatch *m;
616
617 m = but_packet(but);
618 assert(MAGIC(m));
619 clp_setBool(m->data->cg->clp, "client.match.free", newVal);
620 return(0);
621 }
622
623
swapPressed(But * but)624 static ButOut swapPressed(But *but) {
625 CliMatch *m;
626 Str temp, *cmdBuild;
627
628 m = but_packet(but);
629 assert(MAGIC(m));
630 temp = m->wName;
631 m->wName = m->bName;
632 m->bName = temp;
633 m->meFirst = !m->meFirst;
634 cmdBuild = &m->data->cmdBuild;
635 str_print(cmdBuild, CGBUTS_WSTONECHAR " %s", str_chars(&m->wName));
636 butText_set(m->wTitle, str_chars(cmdBuild));
637 str_print(cmdBuild, CGBUTS_BSTONECHAR " %s", str_chars(&m->bName));
638 butText_set(m->bTitle, str_chars(cmdBuild));
639 return(0);
640 }
641
642
cliMatch_declineCommand(CliMatch * match,const char * buf)643 void cliMatch_declineCommand(CliMatch *match, const char *buf) {
644 char name[30];
645
646 sscanf(buf, "%s", name);
647 match = playerLookup(match, name);
648 if (match != NULL) {
649 match->state = cliMatch_nil;
650 butText_set(match->title, msg_cliGameSetupRej);
651 }
652 }
653
654
playerLookup(CliMatch * chain,const char * player)655 static CliMatch *playerLookup(CliMatch *chain, const char *player) {
656 while (chain != NULL) {
657 if (!strcmp(player, str_chars(&chain->wName)) ||
658 !strcmp(player, str_chars(&chain->bName)))
659 return(chain);
660 chain = chain->next;
661 }
662 return(NULL);
663 }
664
665
changeMain(But * but)666 static ButOut changeMain(But *but) {
667 CliMatch *m = but_packet(but);
668
669 assert(MAGIC(m));
670 if (newMainTime(m->mainIn, butTextin_get(m->mainIn)) & BUTOUT_ERR)
671 return(BUTOUT_ERR);
672 if (but == m->mainUp1) {
673 m->mainTime += 60;
674 } else if (but == m->mainUp5) {
675 m->mainTime += 60 * 5;
676 } else if (but == m->mainDown1) {
677 m->mainTime -= 60;
678 if (m->mainTime < 0)
679 m->mainTime = 0;
680 } else {
681 assert(but == m->mainDown5);
682 m->mainTime -= 60 * 5;
683 if (m->mainTime < 0)
684 m->mainTime = 0;
685 }
686 goTime_str(m->mainTime, &m->data->cmdBuild);
687 butTextin_set(m->mainIn, str_chars(&m->data->cmdBuild), TRUE);
688 return(0);
689 }
690
691
changeBy(But * but)692 static ButOut changeBy(But *but) {
693 CliMatch *m = but_packet(but);
694
695 assert(MAGIC(m));
696 if (newBYTime(m->byIn, butTextin_get(m->byIn)) & BUTOUT_ERR)
697 return(BUTOUT_ERR);
698 if (but == m->byUp1) {
699 m->byTime += 60;
700 } else if (but == m->byUp5) {
701 m->byTime += 60 * 5;
702 } else if (but == m->byDown1) {
703 m->byTime -= 60;
704 if (m->byTime < 0)
705 m->byTime = 0;
706 } else {
707 assert(but == m->byDown5);
708 m->byTime -= 60 * 5;
709 if (m->byTime < 0)
710 m->byTime = 0;
711 }
712 goTime_str(m->byTime, &m->data->cmdBuild);
713 butTextin_set(m->byIn, str_chars(&m->data->cmdBuild), TRUE);
714 return(0);
715 }
716
717
changeSize(But * but)718 static ButOut changeSize(But *but) {
719 CliMatch *m = but_packet(but);
720 char sizeStr[3];
721
722 assert(MAGIC(m));
723 if (newSize(m->sizeIn, butTextin_get(m->sizeIn)) & BUTOUT_ERR)
724 return(BUTOUT_ERR);
725 if (but == m->sizeUp) {
726 if (m->size < 13)
727 m->size = 13;
728 else
729 m->size = 19;
730 } else {
731 assert(but == m->sizeDown);
732 if (m->size > 13)
733 m->size = 13;
734 else
735 m->size = 9;
736 }
737 sprintf(sizeStr, "%d", m->size);
738 butTextin_set(m->sizeIn, sizeStr, TRUE);
739 return(0);
740 }
741
742
changeKomi(But * but)743 static ButOut changeKomi(But *but) {
744 CliMatch *m = but_packet(but);
745 char komiStr[10];
746
747 assert(MAGIC(m));
748 if (newKomi(m->komiIn, butTextin_get(m->komiIn)) & BUTOUT_ERR)
749 return(BUTOUT_ERR);
750 if (but == m->komiUp) {
751 m->komi += 1.0;
752 if (m->komi > 99.5)
753 m->komi = 99.5;
754 } else {
755 assert(but == m->komiDown);
756 m->komi -= 1.0;
757 if (m->komi < -99.5)
758 m->komi = -99.5;
759 }
760 sprintf(komiStr, "%g", m->komi);
761 butTextin_set(m->komiIn, komiStr, TRUE);
762 return(0);
763 }
764
765
changeHcap(But * but)766 static ButOut changeHcap(But *but) {
767 CliMatch *m = but_packet(but);
768 char hcapStr[3];
769
770 assert(MAGIC(m));
771 if (newHcap(m->hcapIn, butTextin_get(m->hcapIn)) & BUTOUT_ERR)
772 return(BUTOUT_ERR);
773 if (but == m->hcapUp) {
774 ++m->hcap;
775 if (m->hcap == 1)
776 m->hcap = 2;
777 if (m->hcap > 9)
778 m->hcap = 9;
779 } else {
780 assert(but == m->hcapDown);
781 --m->hcap;
782 if (m->hcap == 1)
783 m->hcap = 0;
784 if (m->hcap < 0)
785 m->hcap = 0;
786 }
787 sprintf(hcapStr, "%d", m->hcap);
788 butTextin_set(m->hcapIn, hcapStr, TRUE);
789 return(0);
790 }
791
792
cliMatch_extraInfo(CliMatch * match,const char * oppName,int hcap,float komi,bool free)793 void cliMatch_extraInfo(CliMatch *match, const char *oppName, int hcap,
794 float komi, bool free) {
795 char temp[20];
796
797 match = playerLookup(match, oppName);
798 if (match != NULL) {
799 sprintf(temp, "%d", hcap);
800 butTextin_set(match->hcapIn, temp, TRUE);
801 sprintf(temp, "%g", komi);
802 butTextin_set(match->komiIn, temp, TRUE);
803 match->komi = komi;
804 butCb_set(match->freeGame, free, TRUE);
805 }
806 }
807