1 /*
2 * file mi_host.c - Menu item for host selection in networked games
3 *
4 * $Id: mi_host.c,v 1.25 2006/02/09 21:21:24 fzago Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "xblast.h"
25
26 /*
27 * local macors
28 */
29 #define FF_HOST_NAME_FOCUS (FF_Small | FF_Black | FF_Center | FF_Outlined)
30 #define FF_HOST_NAME_NO_FOCUS (FF_Small | FF_White | FF_Center)
31 #define FF_HOST_STATE_FOCUS (FF_Large | FF_Black | FF_Center | FF_Outlined)
32 #define FF_HOST_STATE_NO_FOCUS (FF_Large | FF_White | FF_Center)
33
34 /*
35 * local types
36 */
37 typedef struct
38 {
39 XBMenuItem item; /* generic item data */
40 /* host name */
41 const char **pText; /* link to current host name string */
42 const char *cText; /* displayed host name string */
43 Sprite *tSprite; /* host name text sprite */
44 /* host state */
45 XBHostState *pState; /* link to current host state */
46 XBHostState cState; /* displayed host state */
47 Sprite *sSprite; /* host state text sprite */
48 /* host ping */
49 const int *pPing; /* link to current ping time */
50 int cPing; /* currently displayed ping value */
51 char tPing[16]; /* currently displayer ping string */
52 Sprite *pSprite; /* host ping text sprite */
53
54 /* host state requests */
55 unsigned id; /* host id */
56 XBHSFocusFunc focusFunc; /* handler for state focus changes */
57 XBHSChangeFunc chgFunc; /* handler for local state changes */
58 XBHSUpdateFunc upFunc; /* handler for ping/state updates */
59 /* locally requested state */
60 XBHostState lState; /* current local requested state */
61 Sprite *lSprite; /* local request text sprite */
62 /* requests known to server */
63 XBHostState cStateReq[MAX_HOSTS]; /* displayed externak requests */
64 char tRequests[MAX_HOSTS + 1]; /* displayed requests string */
65 Sprite *rSprite; /* requests text sprite */
66 } XBMenuHostItem;
67
68 typedef struct
69 {
70 XBMenuItem item; /* generic item data */
71 /* team state */
72 XBTeamState *pTeam; /* link to current team state */
73 XBTeamState cTeam; /* displayed team state */
74 Sprite *sSprite; /* team state text sprite */
75 /* team state requests */
76 unsigned id; /* host id */
77 unsigned player; /* player id */
78 XBTSFocusFunc focusFunc; /* handler for team focus changes */
79 XBTSChangeFunc chgFunc; /* handler for local team changes */
80 XBTSUpdateFunc upFunc; /* handler for team updates */
81 /* locally requested team */
82 XBTeamState lTeam; /* currently requested team */
83 Sprite *lSprite; /* state request text sprite */
84 /* requests known to server */
85 XBTeamState cTeamReq[MAX_HOSTS]; /* display team requests */
86 char tRequests[MAX_HOSTS + 1]; /* displayed requests string */
87 Sprite *rSprite; /* requests text sprite */
88 } XBMenuTeamItem;
89
90 /*
91 * local variables
92 */
93 static XBHostState serverState = XBHS_Server;
94 static const char *stateText[NUM_XBHS] = {
95 "?", /* XBHS_None */
96 "...", /* XBHS_Wait */
97 "In", /* XBHS_In */
98 "Out", /* XBHS_Out */
99 "Srv", /* XBHS_Server */
100 "Go!", /* XBHS_Ready */
101 };
102
103 static const char *teamText[NUM_XBTS] = {
104 "", /* XBTS_Invalid */
105 "None", /* XBTS_None */
106 "Red", /* XBTS_Red */
107 "Green", /* XBTS_Green */
108 "Blue", /* XBTS_Blue */
109 "Out", /* XBTS_Out */
110 };
111
112 /*******************
113 * shared routines *
114 *******************/
115
116 /*
117 * shared host focus handler
118 */
119 static void
MenuHostFocusShared(XBMenuItem * ptr,XBBool flag)120 MenuHostFocusShared (XBMenuItem * ptr, XBBool flag)
121 {
122 XBMenuHostItem *host = (XBMenuHostItem *) ptr;
123
124 assert (NULL != host);
125 assert (NULL != host->tSprite);
126 assert (NULL != host->sSprite);
127 SetSpriteAnime (host->tSprite, flag ? FF_HOST_NAME_FOCUS : FF_HOST_NAME_NO_FOCUS);
128 SetSpriteAnime (host->sSprite, flag ? FF_HOST_STATE_FOCUS : FF_HOST_STATE_NO_FOCUS);
129 if (NULL != host->pSprite) {
130 SetSpriteAnime (host->pSprite, flag ? FF_HOST_NAME_FOCUS : FF_HOST_NAME_NO_FOCUS);
131 }
132 } /* MenuHostFocusShared */
133
134 /*
135 * polling a host item
136 */
137 static void
MenuHostPollShared(XBMenuItem * ptr)138 MenuHostPollShared (XBMenuItem * ptr)
139 {
140 XBMenuHostItem *host = (XBMenuHostItem *) ptr;
141 assert (NULL != host);
142 assert (NULL != host->tSprite);
143 assert (NULL != host->sSprite);
144 /* check state change, old style: link to array in menu_network.c */
145 if (*host->pState != host->cState) {
146 host->cState = *host->pState;
147 assert (host->cState < NUM_XBHS);
148 SetSpriteText (host->sSprite, stateText[host->cState]);
149 }
150 /* check name change */
151 if (*host->pText != host->cText) {
152 host->cText = *host->pText;
153 SetSpriteText (host->tSprite, host->cText);
154 }
155 /* update ping, old style: link to array in menu_network.c */
156 if (NULL != host->pPing && *host->pPing != host->cPing) {
157 host->cPing = *host->pPing;
158 if (host->cPing < 0) {
159 host->tPing[0] = 0;
160 }
161 else {
162 sprintf (host->tPing, "%u ms", host->cPing);
163 }
164 SetSpriteText (host->pSprite, host->tPing);
165 }
166 } /* MenuSharedPoll */
167
168 /*
169 * shared team focus handler
170 */
171 static void
MenuTeamFocusShared(XBMenuItem * ptr,XBBool flag)172 MenuTeamFocusShared (XBMenuItem * ptr, XBBool flag)
173 {
174 XBMenuTeamItem *team = (XBMenuTeamItem *) ptr;
175
176 assert (NULL != team);
177 assert (NULL != team->sSprite);
178 SetSpriteAnime (team->sSprite, flag ? FF_HOST_NAME_FOCUS : FF_HOST_NAME_NO_FOCUS);
179
180 } /* MenuTeamFocusShared */
181
182 /*
183 * polling a team item
184 */
185 static void
MenuTeamPollShared(XBMenuItem * ptr)186 MenuTeamPollShared (XBMenuItem * ptr)
187 {
188 XBMenuTeamItem *team = (XBMenuTeamItem *) ptr;
189
190 assert (NULL != team);
191 /* state */
192 if (*team->pTeam != team->cTeam) {
193 team->cTeam = *team->pTeam;
194 assert (team->cTeam < NUM_XBTS);
195 SetSpriteText (team->sSprite, teamText[team->cTeam]);
196 }
197 } /* MenuTeamPollShared */
198
199 /*********************
200 * generic host item *
201 *********************/
202
203 /*
204 * host item receives focus
205 */
206 static void
MenuHostFocus(XBMenuItem * ptr,XBBool flag)207 MenuHostFocus (XBMenuItem * ptr, XBBool flag)
208 {
209 XBMenuHostItem *host = (XBMenuHostItem *) ptr;
210 assert (NULL != host->focusFunc);
211 (*host->focusFunc) (host->id);
212 MenuHostFocusShared (ptr, flag);
213 } /* MenuHostFocus */
214
215 /*
216 * host item selected
217 */
218 static void
MenuHostSelect(XBMenuItem * ptr)219 MenuHostSelect (XBMenuItem * ptr)
220 {
221 XBMenuHostItem *host = (XBMenuHostItem *) ptr;
222 assert (NULL != host);
223 assert (NULL != host->chgFunc);
224 assert (host->id < MAX_HOSTS);
225 if ((*host->chgFunc) (host->id, &host->lState)) {
226 /* update the local request sprite */
227 if (host->lState == host->cState || host->lState == XBHS_None) {
228 SetSpriteText (host->lSprite, "");
229 }
230 else {
231 SetSpriteText (host->lSprite, stateText[host->lState]);
232 }
233 }
234 } /* MenuHostSelect */
235
236 /*
237 * host item mouse event
238 */
239 static void
MenuHostMouse(XBMenuItem * ptr,XBEventCode code)240 MenuHostMouse (XBMenuItem * ptr, XBEventCode code)
241 {
242 if (code == XBE_MOUSE_1) {
243 MenuHostSelect (ptr);
244 }
245 } /* MenuHostMouse */
246
247 /*
248 * host item polling
249 */
250 static void
MenuHostPoll(XBMenuItem * ptr)251 MenuHostPoll (XBMenuItem * ptr)
252 {
253 XBMenuHostItem *host = (XBMenuHostItem *) ptr;
254 #ifdef REQUESTS
255 unsigned i;
256 #endif
257 assert (NULL != host);
258 assert (NULL != host->tSprite);
259 assert (NULL != host->sSprite);
260 if ((*host->upFunc) (host->id, &host->cState, &host->cStateReq[0], &host->cPing)) {
261 assert (host->cState < NUM_XBHS);
262 /* create requests and ping */
263 if (host->cState == XBHS_None) {
264 host->tRequests[0] = (char)0;
265 host->tPing[0] = (char)0;
266 }
267 else {
268 #ifdef REQUESTS
269 /* update requests text */
270 for (i = 0; i < MAX_HOSTS; i++) {
271 host->tRequests[i] = *stateText[host->cStateReq[i]];
272 }
273 host->tRequests[MAX_HOSTS] = (char)0;
274 #endif
275 /* update ping text */
276 if (host->cPing < 0) {
277 host->tPing[0] = (char)0; /* ping undefined, display nothing */
278 }
279 else {
280 sprintf (host->tPing, "%u ms", host->cPing);
281 }
282 }
283 /* display requests, ping, current */
284 #ifdef REQUESTS
285 SetSpriteText (host->rSprite, host->tRequests);
286 #endif
287 SetSpriteText (host->sSprite, stateText[host->cState]);
288 SetSpriteText (host->pSprite, host->tPing);
289 }
290 /* clear local request sprite if it coincides with current state or not set */
291 if (host->lState == XBHS_None || host->lState == host->cState) {
292 SetSpriteText (host->lSprite, "");
293 }
294 /* check name change, direct link */
295 if (*(host->pText + host->id) != host->cText) {
296 host->cText = *(host->pText + host->id);
297 SetSpriteText (host->tSprite, host->cText);
298 }
299 } /* MenuHostPoll */
300
301 /*
302 * create generic host button
303 */
304 XBMenuItem *
MenuCreateHost(int x,int y,int w,unsigned client,const char ** pText,XBHSFocusFunc focusFunc,XBHSChangeFunc chgFunc,XBHSUpdateFunc upFunc)305 MenuCreateHost (int x, int y, int w, unsigned client, const char **pText, XBHSFocusFunc focusFunc,
306 XBHSChangeFunc chgFunc, XBHSUpdateFunc upFunc)
307 {
308 /* create item */
309 XBMenuHostItem *host = calloc (1, sizeof (*host));
310 assert (host != NULL);
311 MenuSetItem (&host->item, MIT_Host, x, y, w, CELL_H, MenuHostFocus, MenuHostSelect,
312 MenuHostMouse, MenuHostPoll);
313 /* remember host id */
314 host->id = client;
315 /* set handlers */
316 host->focusFunc = focusFunc;
317 host->chgFunc = chgFunc;
318 host->upFunc = upFunc;
319 /* set initial state info */
320 host->cState = XBHS_None;
321 host->sSprite =
322 CreateTextSprite (stateText[host->cState], (x + 1) * BASE_X, (y + 1) * BASE_Y,
323 (w / 4) * BASE_X, CELL_H / 2 * BASE_Y, FF_HOST_NAME_NO_FOCUS, SPM_MAPPED);
324 /* set initial local request info */
325 host->lState = XBHS_None;
326 host->lSprite =
327 CreateTextSprite ("", (x + w / 5) * BASE_X, (y + 1) * BASE_Y, (w / 4) * BASE_X,
328 CELL_H / 2 * BASE_Y, FF_HOST_NAME_NO_FOCUS, SPM_MAPPED);
329 /* set initial requests info */
330 memset (host->cStateReq, 0, sizeof (host->cStateReq));
331 host->rSprite =
332 CreateTextSprite (host->tRequests, (x + 1) * BASE_X, (y + CELL_H / 2) * BASE_Y,
333 (w / 2) * BASE_X, (CELL_H / 2 - 1) * BASE_Y, FF_HOST_NAME_NO_FOCUS,
334 SPM_MAPPED);
335 /* set initial ping info */
336 host->cPing = -1;
337 host->tPing[0] = (char)0;
338 host->pSprite =
339 CreateTextSprite (host->tPing, (x + w / 2) * BASE_X, (y + CELL_H / 2) * BASE_Y,
340 (w / 2 - 1) * BASE_X, (CELL_H / 2 - 1) * BASE_Y, FF_HOST_NAME_NO_FOCUS,
341 SPM_MAPPED);
342 /* link host name */
343 assert (pText != NULL);
344 host->pText = pText;
345 host->cText = *(pText + host->id);
346 host->tSprite =
347 CreateTextSprite (host->cText, (x + 2 * w / 5) * BASE_X, (y + 1) * BASE_Y,
348 (3 * w / 5 - 1) * BASE_X, CELL_H / 2 * BASE_Y, FF_HOST_NAME_NO_FOCUS,
349 SPM_MAPPED);
350 /* graphics */
351 MenuAddLargeFrame (x / CELL_W, (x + w - 1) / CELL_W, y / CELL_H);
352 /* poll once */
353 MenuHostPoll (&host->item);
354 return &host->item;
355 } /* MenuCreateServer */
356
357 /********************
358 * server host item *
359 ********************/
360
361 /*
362 * host item has focus
363 */
364 static void
MenuServerFocus(XBMenuItem * ptr,XBBool flag)365 MenuServerFocus (XBMenuItem * ptr, XBBool flag)
366 {
367 MenuHostFocusShared (ptr, flag);
368 } /* MenuServerFocus */
369
370 /*
371 * host item selected
372 */
373 static void
MenuServerSelect(XBMenuItem * ptr)374 MenuServerSelect (XBMenuItem * ptr)
375 {
376 } /* MenuServerSelect */
377
378 /*
379 * host item mouse event
380 */
381 static void
MenuServerMouse(XBMenuItem * ptr,XBEventCode code)382 MenuServerMouse (XBMenuItem * ptr, XBEventCode code)
383 {
384 } /* MenuServerMouse */
385
386 /*
387 * polling
388 */
389 static void
MenuServerPoll(XBMenuItem * ptr)390 MenuServerPoll (XBMenuItem * ptr)
391 {
392 MenuHostPollShared (ptr);
393 } /* MenuServerPoll */
394
395 /*
396 * create server button
397 */
398 XBMenuItem *
MenuCreateServer(int x,int y,int w,const char ** pText)399 MenuCreateServer (int x, int y, int w, const char **pText)
400 {
401 /* create item */
402 XBMenuHostItem *host = calloc (1, sizeof (*host));
403 assert (host != NULL);
404 MenuSetItem (&host->item, MIT_Host, x, y, w, CELL_H, MenuServerFocus, MenuServerSelect,
405 MenuServerMouse, MenuServerPoll);
406 /* set server specific data */
407 assert (pText != NULL);
408 host->pText = pText;
409 host->cText = *pText;
410 host->pState = &serverState;
411 host->cState = XBHS_None;
412 /* sprite with host name */
413 host->tSprite =
414 CreateTextSprite (*pText, (x + 11) * BASE_X, y * BASE_Y, (w - 12) * BASE_X, CELL_H * BASE_Y,
415 FF_HOST_NAME_NO_FOCUS, SPM_MAPPED);
416 /* sprite with host state */
417 host->sSprite =
418 CreateTextSprite (stateText[0], (x + 1) * BASE_X, y * BASE_Y, 9 * BASE_X, CELL_H * BASE_Y,
419 FF_HOST_STATE_NO_FOCUS, SPM_MAPPED);
420 /* sprite with state request */
421 host->lSprite = NULL;
422 /* sprite with requests */
423 host->rSprite = NULL;
424 /* graphics */
425 MenuAddLargeFrame (x / CELL_W, (x + w - 1) / CELL_W, y / CELL_H);
426 return &host->item;
427 } /* MenuCreateServer */
428
429 /********************
430 * client host item *
431 ********************/
432
433 /*
434 * host item has focus
435 */
436 static void
MenuClientFocus(XBMenuItem * ptr,XBBool flag)437 MenuClientFocus (XBMenuItem * ptr, XBBool flag)
438 {
439 MenuHostFocusShared (ptr, flag);
440 } /* MenuClientFocus */
441
442 /*
443 * host item selected
444 */
445 static void
MenuClientSelect(XBMenuItem * ptr)446 MenuClientSelect (XBMenuItem * ptr)
447 {
448 XBMenuHostItem *host = (XBMenuHostItem *) ptr;
449
450 assert (NULL != host);
451 assert (NULL != host->pState);
452 switch (*host->pState) {
453 case XBHS_In:
454 *host->pState = XBHS_Out;
455 break;
456 case XBHS_Out:
457 *host->pState = XBHS_In;
458 break;
459 default:
460 break;
461 }
462 } /* MenuClientSelect */
463
464 /*
465 * host item mouse event
466 */
467 static void
MenuClientMouse(XBMenuItem * ptr,XBEventCode code)468 MenuClientMouse (XBMenuItem * ptr, XBEventCode code)
469 {
470 if (code == XBE_MOUSE_1) {
471 MenuClientSelect (ptr);
472 }
473 } /* MenuClientMouse */
474
475 /*
476 * polling
477 */
478 static void
MenuClientPoll(XBMenuItem * ptr)479 MenuClientPoll (XBMenuItem * ptr)
480 {
481 MenuHostPollShared (ptr);
482 } /* MenuClientPoll */
483
484 /*
485 * create server button
486 */
487 XBMenuItem *
MenuCreateClient(int x,int y,int w,const char ** pText,XBHostState * pState,const int * pPing)488 MenuCreateClient (int x, int y, int w, const char **pText, XBHostState * pState, const int *pPing)
489 {
490 /* create item */
491 XBMenuHostItem *host = calloc (1, sizeof (*host));
492 assert (host != NULL);
493 MenuSetItem (&host->item, MIT_Host, x, y, w, CELL_H, MenuClientFocus, MenuClientSelect,
494 MenuClientMouse, MenuClientPoll);
495 /* set server specific data */
496 assert (pText != NULL);
497 assert (pState != NULL);
498 host->pText = pText;
499 host->cText = *pText;
500 host->pState = pState;
501 host->cState = *pState;
502 host->pPing = pPing;
503 host->cPing = -1;
504 host->rSprite = NULL;
505 /* sprite with host name */
506 host->tSprite =
507 CreateTextSprite (*pText, (x + 11) * BASE_X, (y + 1) * BASE_Y, (w - 12) * BASE_X,
508 (CELL_H / 2) * BASE_Y, FF_HOST_NAME_NO_FOCUS, SPM_MAPPED);
509 /* sprite with ping to host */
510 host->pSprite =
511 CreateTextSprite (host->tPing, (x + 11) * BASE_X, (y + CELL_H / 2) * BASE_Y,
512 (w - 12) * BASE_X, (CELL_H / 2 - 1) * BASE_Y, FF_HOST_NAME_NO_FOCUS,
513 SPM_MAPPED);
514 /* sprite with host state */
515 host->sSprite =
516 CreateTextSprite (stateText[*pState], (x + 1) * BASE_X, y * BASE_Y, 9 * BASE_X,
517 CELL_H * BASE_Y, FF_HOST_STATE_NO_FOCUS, SPM_MAPPED);
518 /* sprite with state request */
519 host->lSprite = NULL;
520 /* sprite with requests */
521 host->rSprite = NULL;
522 /* graphics */
523 MenuAddLargeFrame (x / CELL_W, (x + w - 1) / CELL_W, y / CELL_H);
524 return &host->item;
525 } /* MenuCreateServer */
526
527 /******************
528 * peer host item *
529 ******************/
530
531 /*
532 * host item has focus
533 */
534 static void
MenuPeerFocus(XBMenuItem * ptr,XBBool flag)535 MenuPeerFocus (XBMenuItem * ptr, XBBool flag)
536 {
537 MenuHostFocusShared (ptr, flag);
538 } /* MenuPeerFocus */
539
540 /*
541 * host item is selected
542 */
543 static void
MenuPeerSelect(XBMenuItem * ptr)544 MenuPeerSelect (XBMenuItem * ptr)
545 {
546 } /* MenuPeerSelect */
547
548 /*
549 * host item under mouse
550 */
551 static void
MenuPeerMouse(XBMenuItem * ptr,XBEventCode code)552 MenuPeerMouse (XBMenuItem * ptr, XBEventCode code)
553 {
554 } /* MenuPeerMouse */
555
556 /*
557 * polling
558 */
559 static void
MenuPeerPoll(XBMenuItem * ptr)560 MenuPeerPoll (XBMenuItem * ptr)
561 {
562 MenuHostPollShared (ptr);
563 } /* MenuPeerPoll */
564
565 /*
566 * create peer item
567 */
568 XBMenuItem *
MenuCreatePeer(int x,int y,int w,const char ** pText,XBHostState * pState,const int * pPing)569 MenuCreatePeer (int x, int y, int w, const char **pText, XBHostState * pState, const int *pPing)
570 {
571 /* create item */
572 XBMenuHostItem *host = calloc (1, sizeof (*host));
573 assert (host != NULL);
574 MenuSetItem (&host->item, MIT_Host, x, y, w, CELL_H, MenuPeerFocus, MenuPeerSelect,
575 MenuPeerMouse, MenuPeerPoll);
576 /* set server specific data */
577 assert (pText != NULL);
578 assert (pState != NULL);
579 host->pText = pText;
580 host->cText = *pText;
581 host->pState = pState;
582 host->cState = *pState;
583 host->pPing = pPing;
584 host->cPing = -1;
585 host->rSprite = NULL;
586 /* sprite with host name */
587 host->tSprite =
588 CreateTextSprite (*pText, (x + 11) * BASE_X, (y + 1) * BASE_Y, (w - 12) * BASE_X,
589 (CELL_H / 2) * BASE_Y, FF_HOST_NAME_NO_FOCUS, SPM_MAPPED);
590 /* sprite with ping to host */
591 host->pSprite =
592 CreateTextSprite (host->tPing, (x + 11) * BASE_X, (y + CELL_H / 2) * BASE_Y,
593 (w - 12) * BASE_X, (CELL_H / 2 - 1) * BASE_Y, FF_HOST_NAME_NO_FOCUS,
594 SPM_MAPPED);
595 /* sprite with host state */
596 host->sSprite =
597 CreateTextSprite (stateText[*pState], (x + 1) * BASE_X, y * BASE_Y, 9 * BASE_X,
598 CELL_H * BASE_Y, FF_HOST_STATE_NO_FOCUS, SPM_MAPPED);
599 /* sprite with state request */
600 host->lSprite = NULL;
601 /* sprite with requests */
602 host->rSprite = NULL;
603 /* graphics */
604 MenuAddLargeFrame (x / CELL_W, (x + w - 1) / CELL_W, y / CELL_H);
605 return &host->item;
606 } /* MenuCreateServer */
607
608 /*********************
609 * generic team item *
610 *********************/
611
612 /*
613 * team receives focus
614 */
615 static void
MenuTeamFocus(XBMenuItem * ptr,XBBool flag)616 MenuTeamFocus (XBMenuItem * ptr, XBBool flag)
617 {
618 XBMenuTeamItem *team = (XBMenuTeamItem *) ptr;
619 assert (NULL != team->focusFunc);
620 (*team->focusFunc) (team->id, team->player);
621 MenuTeamFocusShared (ptr, flag);
622 } /* MenuTeamFocus */
623
624 /*
625 * team item is selected
626 */
627 static void
MenuTeamSelect(XBMenuItem * ptr)628 MenuTeamSelect (XBMenuItem * ptr)
629 {
630 XBMenuTeamItem *team = (XBMenuTeamItem *) ptr;
631
632 assert (NULL != team);
633 /* first local request, init to current, if necessary */
634 if (team->lTeam == XBTS_Invalid) {
635 team->lTeam = team->cTeam;
636 }
637 /* get next reasonable local request */
638 if ((*team->chgFunc) (team->id, team->player, &team->lTeam)) {
639 assert (team->lTeam < NUM_XBTS);
640 /* no display if equal to current or invalid */
641 #ifdef REQUESTS
642 if (team->cTeam == team->lTeam || team->lTeam == XBTS_Invalid) {
643 SetSpriteText (team->lSprite, "");
644 }
645 else {
646 SetSpriteText (team->lSprite, teamText[team->lTeam]);
647 }
648 #endif
649 }
650 } /* MenuTeamSelect */
651
652 /*
653 * team item mouse event
654 */
655 static void
MenuTeamMouse(XBMenuItem * ptr,XBEventCode code)656 MenuTeamMouse (XBMenuItem * ptr, XBEventCode code)
657 {
658 if (code == XBE_MOUSE_1) {
659 MenuTeamSelect (ptr);
660 }
661 } /* MenuTeamMouse */
662
663 /*
664 * polling a team item
665 */
666 static void
MenuTeamPoll(XBMenuItem * ptr)667 MenuTeamPoll (XBMenuItem * ptr)
668 {
669 XBMenuTeamItem *team = (XBMenuTeamItem *) ptr;
670 #ifdef REQUESTS
671 unsigned i;
672 #endif
673 assert (NULL != team);
674 assert (NULL != team->upFunc);
675 /* update team data */
676 if ((*team->upFunc) (team->id, team->player, &team->cTeam, team->cTeamReq)) {
677 assert (team->cTeam < NUM_XBTS);
678 /* reset local request if state invalid */
679 if (team->cTeam == XBTS_Invalid) {
680 team->lTeam = XBTS_Invalid;
681 }
682 /* update state */
683 SetSpriteText (team->sSprite, teamText[team->cTeam]);
684 /* check if local request needs to be cleared */
685 if (team->cTeam == team->lTeam) {
686 SetSpriteText (team->lSprite, "");
687 }
688 /* update requests */
689 #ifdef REQUESTS
690 for (i = 0; i < MAX_HOSTS; i++) {
691 team->tRequests[i] = *teamText[team->cTeamReq[i]];
692 }
693 team->tRequests[MAX_HOSTS] = (char)0;
694 SetSpriteText (team->rSprite, team->tRequests);
695 #endif
696 }
697 } /* MenuTeamPoll */
698
699 /*
700 * create team item
701 */
702 XBMenuItem *
MenuCreateTeam(int x,int y,int w,unsigned id,unsigned player,XBTSFocusFunc focusFunc,XBTSChangeFunc chgFunc,XBTSUpdateFunc upFunc)703 MenuCreateTeam (int x, int y, int w, unsigned id, unsigned player, XBTSFocusFunc focusFunc,
704 XBTSChangeFunc chgFunc, XBTSUpdateFunc upFunc)
705 {
706 /* create item */
707 XBMenuTeamItem *team = calloc (1, sizeof (*team));
708 assert (team != NULL);
709 MenuSetItem (&team->item, MIT_Team, x, y, w, CELL_H, MenuTeamFocus, MenuTeamSelect,
710 MenuTeamMouse, MenuTeamPoll);
711 /* store id, player */
712 team->id = id;
713 team->player = player;
714 /* set handler */
715 team->focusFunc = focusFunc;
716 team->chgFunc = chgFunc;
717 team->upFunc = upFunc;
718 /* team state */
719 team->cTeam = XBTS_Invalid;
720 team->sSprite =
721 CreateTextSprite (teamText[team->cTeam], (x + 1) * BASE_X, y * BASE_Y, w / 4 * BASE_X,
722 (CELL_H / 2) * BASE_Y, FF_HOST_NAME_FOCUS, SPM_MAPPED);
723 /* team state request */
724 team->lTeam = XBTS_Invalid;
725 team->lSprite =
726 CreateTextSprite (teamText[team->lTeam], (x + w / 4) * BASE_X, y * BASE_Y, w / 4 * BASE_X,
727 (CELL_H / 2) * BASE_Y, FF_HOST_NAME_FOCUS, SPM_MAPPED);
728 /* team requests */
729 memset (team->cTeamReq, 0, sizeof (team->cTeamReq));
730 team->tRequests[0] = (char)0;
731 team->rSprite =
732 CreateTextSprite (team->tRequests, (x + w / 2) * BASE_X, y * BASE_Y, (w / 2 - 1) * BASE_X,
733 (CELL_H / 2) * BASE_Y, FF_HOST_NAME_FOCUS, SPM_MAPPED);
734 /* graphics */
735 MenuAddSmallFrame (x / CELL_W, (x + w - 1) / CELL_W, y / CELL_H);
736 /* poll once */
737 MenuTeamPoll (&team->item);
738 return &team->item;
739 } /* MenuCreateTeam */
740
741 /************************
742 * team item for a peer *
743 ************************/
744
745 /*
746 * team receives focus
747 */
748 static void
MenuPeerTeamFocus(XBMenuItem * ptr,XBBool flag)749 MenuPeerTeamFocus (XBMenuItem * ptr, XBBool flag)
750 {
751 XBMenuTeamItem *team = (XBMenuTeamItem *) ptr;
752
753 assert (NULL != team);
754 assert (NULL != team->sSprite);
755 SetSpriteAnime (team->sSprite, flag ? FF_HOST_NAME_FOCUS : FF_HOST_NAME_NO_FOCUS);
756
757 } /* MenuPeerTeamFocus */
758
759 /*
760 * peer team item selcted
761 */
762 static void
MenuPeerTeamSelect(XBMenuItem * ptr)763 MenuPeerTeamSelect (XBMenuItem * ptr)
764 {
765 } /* MenuPeerTeamSelect */
766
767 /*
768 * peer team item mouse event
769 */
770 static void
MenuPeerTeamMouse(XBMenuItem * ptr,XBEventCode code)771 MenuPeerTeamMouse (XBMenuItem * ptr, XBEventCode code)
772 {
773 } /* MenuPeerTeamMouse */
774
775 /*
776 * polling a team item
777 */
778 static void
MenuPeerTeamPoll(XBMenuItem * ptr)779 MenuPeerTeamPoll (XBMenuItem * ptr)
780 {
781 MenuTeamPollShared (ptr);
782 } /* MenuPeerTeamPoll */
783
784 /*
785 * create team item for a peer
786 */
787 XBMenuItem *
MenuCreatePeerTeam(int x,int y,int w,XBTeamState * pTeam)788 MenuCreatePeerTeam (int x, int y, int w, XBTeamState * pTeam)
789 {
790 /* create item */
791 XBMenuTeamItem *team = calloc (1, sizeof (*team));
792 assert (team != NULL);
793 MenuSetItem (&team->item, MIT_Team, x, y, w, CELL_H, MenuPeerTeamFocus, MenuPeerTeamSelect,
794 MenuPeerTeamMouse, MenuPeerTeamPoll);
795 /* set server specific data */
796 assert (pTeam != NULL);
797 team->pTeam = pTeam;
798 team->cTeam = *pTeam;
799 /* sprite with team state */
800 team->sSprite =
801 CreateTextSprite (teamText[*pTeam], (x + 1) * BASE_X, y * BASE_Y, (w - 2) * BASE_X,
802 (CELL_H / 2) * BASE_Y, FF_HOST_NAME_FOCUS, SPM_MAPPED);
803 /* sprite with team requests */
804 team->lSprite = NULL;
805 /* sprite with team requests */
806 team->rSprite = NULL;
807 /* graphics */
808 MenuAddSmallFrame (x / CELL_W, (x + w - 1) / CELL_W, y / CELL_H);
809 return &team->item;
810 } /* MenuCreateTeam */
811
812 /************************
813 * team item for server *
814 ************************/
815
816 /*
817 * team receives focus
818 */
819 static void
MenuServerTeamFocus(XBMenuItem * ptr,XBBool flag)820 MenuServerTeamFocus (XBMenuItem * ptr, XBBool flag)
821 {
822 MenuTeamFocusShared (ptr, flag);
823
824 } /* MenuServerTeamFocus */
825
826 /*
827 * team item is selected
828 */
829 static void
MenuServerTeamSelect(XBMenuItem * ptr)830 MenuServerTeamSelect (XBMenuItem * ptr)
831 {
832 XBMenuTeamItem *team = (XBMenuTeamItem *) ptr;
833
834 assert (NULL != team);
835 assert (NULL != team->pTeam);
836 if (*team->pTeam < NUM_XBTS - 1) {
837 *team->pTeam = *team->pTeam + 1;
838 }
839 else {
840 *team->pTeam = 2;
841 }
842 } /* MenuTeamSelect */
843
844 /*
845 * team item mouse event
846 */
847 static void
MenuServerTeamMouse(XBMenuItem * ptr,XBEventCode code)848 MenuServerTeamMouse (XBMenuItem * ptr, XBEventCode code)
849 {
850 if (code == XBE_MOUSE_1) {
851 MenuServerTeamSelect (ptr);
852 }
853 } /* MenuTeamMouse */
854
855 /*
856 * polling a team item
857 */
858 static void
MenuServerTeamPoll(XBMenuItem * ptr)859 MenuServerTeamPoll (XBMenuItem * ptr)
860 {
861 MenuTeamPollShared (ptr);
862 } /* MenuServerTeamPoll */
863
864 /*
865 * create team item for server
866 */
867 XBMenuItem *
MenuCreateServerTeam(int x,int y,int w,XBTeamState * pTeam)868 MenuCreateServerTeam (int x, int y, int w, XBTeamState * pTeam)
869 {
870 /* create item */
871 XBMenuTeamItem *team = calloc (1, sizeof (*team));
872 assert (team != NULL);
873 MenuSetItem (&team->item, MIT_Team, x, y, w, CELL_H, MenuServerTeamFocus, MenuServerTeamSelect,
874 MenuServerTeamMouse, MenuServerTeamPoll);
875 /* set server specific data */
876 assert (pTeam != NULL);
877 team->pTeam = pTeam;
878 team->cTeam = *pTeam;
879 /* sprite with team state */
880 team->sSprite =
881 CreateTextSprite (teamText[*pTeam], (x + 1) * BASE_X, y * BASE_Y, (w - 2) * BASE_X,
882 (CELL_H / 2) * BASE_Y, FF_HOST_NAME_FOCUS, SPM_MAPPED);
883 /* sprite with current team request */
884 team->lSprite = NULL;
885 /* sprite with team requests */
886 team->rSprite = NULL;
887 /* graphics */
888 MenuAddSmallFrame (x / CELL_W, (x + w - 1) / CELL_W, y / CELL_H);
889 return &team->item;
890 } /* MenuCreateTeam */
891
892 /***************
893 * destructors *
894 ***************/
895
896 /*
897 * delete a host item
898 */
899 void
MenuDeleteHost(XBMenuItem * item)900 MenuDeleteHost (XBMenuItem * item)
901 {
902 XBMenuHostItem *host = (XBMenuHostItem *) item;
903
904 assert (NULL != host);
905 assert (NULL != host->tSprite);
906 assert (NULL != host->sSprite);
907 DeleteSprite (host->tSprite);
908 DeleteSprite (host->sSprite);
909 if (NULL != host->pSprite) {
910 DeleteSprite (host->pSprite);
911 }
912 if (NULL != host->rSprite) {
913 DeleteSprite (host->rSprite);
914 }
915 if (NULL != host->lSprite) {
916 DeleteSprite (host->lSprite);
917 }
918 } /* MenuDeleteHost */
919
920 /*
921 * delete a team item
922 */
923 void
MenuDeleteTeam(XBMenuItem * item)924 MenuDeleteTeam (XBMenuItem * item)
925 {
926 XBMenuTeamItem *team = (XBMenuTeamItem *) item;
927
928 assert (NULL != team);
929 assert (NULL != team->sSprite);
930 DeleteSprite (team->sSprite);
931 if (NULL != team->rSprite) {
932 DeleteSprite (team->rSprite);
933 }
934 if (NULL != team->lSprite) {
935 DeleteSprite (team->lSprite);
936 }
937 } /* MenuDeleteTeam */
938
939 /*
940 * end of file mi_host.c
941 */
942