1 /*
2  *   XFrisk - The classic board game for X
3  *   Copyright (C) 1993-1999 Elan Feingold (elan@aetherworks.com)
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  *   $Id: addPlayer.c,v 1.12 2000/01/23 18:37:44 tony Exp $
20  *
21  *   $Log: addPlayer.c,v $
22  *   Revision 1.12  2000/01/23 18:37:44  tony
23  *   removed a debug printf
24  *
25  *   Revision 1.11  2000/01/15 17:34:12  morphy
26  *   Fixes to update color indicator to initial color and after editing color
27  *
28  *   Revision 1.10  2000/01/10 22:47:39  tony
29  *   made colorstuff more private to colormap.c, only scrollbars get set wrong, rest seems to work ok now
30  *
31  *
32  *
33  \file "Add player" dialog
34  */
35 
36 #include <X11/X.h>
37 #include <X11/Intrinsic.h>
38 #include <X11/StringDefs.h>
39 #include <X11/Shell.h>
40 #include <X11/Xaw/Scrollbar.h>
41 #include <X11/Xaw/Form.h>
42 #include <X11/Xaw/Command.h>
43 #include <X11/Xaw/AsciiText.h>
44 #include <X11/Xaw/Viewport.h>
45 #include <X11/Xaw/List.h>
46 
47 #include <stdlib.h>
48 
49 #include "addPlayer.h"
50 #include "colorEdit.h"
51 #include "client.h"
52 #include "utils.h"
53 #include "types.h"
54 #include "gui-vars.h"
55 #include "riskgame.h"
56 #include "callbacks.h"
57 #include "debug.h"
58 
59 
60 /* Private functions */
61 void  PLAYER_EditColor(void);
62 void  PLAYER_SetSpecies(Int32 iSpecies);
63 void  PLAYER_SpeciesCreated(Int32 iSpecies);
64 void  PLAYER_SpeciesDestroyed(Int32 iSpecies);
65 void  PLAYER_RenderSpecies(void);
66 void  PLAYER_Ok(void);
67 void  PLAYER_Cancel(void);
68 void  PLAYER_SelectSpecies(Widget w, XtPointer pData, XtPointer call_data);
69 Int32 PLAYER_SlotToSpecies(Int32 iSlot);
70 Int32 PLAYER_SpeciesToSlot(Int32 iSpecies);
71 
72 
73 /* Globals */
74 static Flag    fPoppedUp = FALSE;
75 static String *ppstrStrings = NULL;
76 static Int32  *piSlotToSpecies = NULL;
77 static Int32   iCurrentSpecies = SPECIES_HUMAN;
78 static Int32   iNumSlots = 1;
79 Int32 r, g, b; /* really static? at least keep global */
80 
81 /* Action tables */
82 static XtActionsRec actionTable[] =
83 {
84   { "playerEditColor", (XtActionProc)PLAYER_EditColor },
85   { "playerOk",        (XtActionProc)PLAYER_Ok },
86   { "playerCancel",    (XtActionProc)PLAYER_Cancel },
87   { NULL, NULL }
88 };
89 
90 /* Widgets */
91 static Widget wAddPlayerShell;
92 static Widget wPlayerNameText;
93 static Widget wPlayerSpeciesListbox;
94 static Widget wPlayerDescText;
95 static Widget wPlayerVersionText;
96 static Widget wPlayerAuthorText;
97 static Widget wPlayerDummy1;
98 static Widget wPlayerDummy2;
99 static Widget wPlayerDummy3;
100 static Widget wPlayerDummy4;
101 static Widget wAddPlayerForm;
102 static Widget wPlayerNameLabel;
103 static Widget wPlayerSpeciesLabel;
104 static Widget wPlayerSpeciesViewport;
105 static Widget wPlayerAuthorLabel;
106 static Widget wPlayerVersionLabel;
107 static Widget wPlayerDescLabel;
108 static Widget wPlayerColorLabel;
109 static Widget wPlayerColorDisplay;
110 static Widget wPlayerOk;
111 static Widget wPlayerCancel;
112 
113 
114 /**
115  * Pick a color for this player
116  \par store in map
117  */
118 
PLAYER_InitColor()119 void PLAYER_InitColor() {
120   r = rand() % 65536;
121   g = rand() % 65536;
122   b = rand() % 65536;
123   while ((r+g+b) < 120000)
124   {
125     r = r + (rand() % 30000);
126     g = g + (rand() % 30000);
127     b = b + (rand() % 30000);
128   }
129   if (r>=65536)
130     r = 65535;
131   if (g>=65536)
132     g = 65535;
133   if (b>=65536)
134     b = 65535;
135   COLOR_StoreColor(COLOR_DieToColor(0), r, g, b);
136 }
137 
138 
139 /************************************************************************
140  *  FUNCTION: PLAYER_BuildDialog
141  *  HISTORY:
142  *     01.29.95  ESF  Created.
143  *  PURPOSE:
144  *  NOTES:
145  ************************************************************************/
PLAYER_BuildDialog(void)146 void PLAYER_BuildDialog(void)
147 {
148   wAddPlayerShell = XtCreatePopupShell("wAddPlayerShell",
149 				       transientShellWidgetClass,
150 				       wToplevel, pVisualArgs, iVisualCount);
151 
152   /* The form */
153   wAddPlayerForm = XtCreateManagedWidget("wAddPlayerForm",
154 					  formWidgetClass, wAddPlayerShell,
155 					  NULL, 0);
156 
157   /* Player name */
158   wPlayerNameLabel = XtCreateManagedWidget("wPlayerNameLabel",
159 					   labelWidgetClass,
160 					   wAddPlayerForm, NULL, 0);
161   wPlayerNameText = XtVaCreateManagedWidget("wPlayerNameText",
162 					    asciiTextWidgetClass,
163 					    wAddPlayerForm,
164 					    XtNeditType, XawtextEdit,
165 					    NULL);
166 
167   /* Player species */
168   wPlayerSpeciesLabel = XtCreateManagedWidget("wPlayerSpeciesLabel",
169 					      labelWidgetClass,
170 					      wAddPlayerForm, NULL, 0);
171   wPlayerSpeciesViewport = XtCreateManagedWidget("wPlayerSpeciesViewport",
172 						 viewportWidgetClass,
173 						 wAddPlayerForm, NULL, 0);
174   wPlayerSpeciesListbox = XtVaCreateManagedWidget("wPlayerSpeciesListbox",
175 						  listWidgetClass,
176 						  wPlayerSpeciesViewport,
177 						  NULL);
178   XtAddCallback(wPlayerSpeciesListbox, XtNcallback, PLAYER_SelectSpecies,
179 		NULL);
180 
181   /* Player description */
182   wPlayerDummy1 = XtCreateManagedWidget("wPlayerDummy1",
183 					labelWidgetClass,
184 					wAddPlayerForm, NULL, 0);
185   wPlayerDescLabel = XtCreateManagedWidget("wPlayerDescLabel",
186 					   labelWidgetClass,
187 					   wAddPlayerForm, NULL, 0);
188   wPlayerDescText = XtVaCreateManagedWidget("wPlayerDescText",
189 					    asciiTextWidgetClass,
190 					    wAddPlayerForm,
191 					    XtNwrap, XawtextWrapWord,
192 					    XtNautoFill, True,
193 					    NULL);
194 
195   /* Player version */
196   wPlayerDummy2 = XtCreateManagedWidget("wPlayerDummy2",
197 					labelWidgetClass,
198 					wAddPlayerForm, NULL, 0);
199   wPlayerVersionLabel = XtCreateManagedWidget("wPlayerVersionLabel",
200 					      labelWidgetClass,
201 					      wAddPlayerForm, NULL, 0);
202   wPlayerVersionText = XtCreateManagedWidget("wPlayerVersionText",
203 					     asciiTextWidgetClass,
204 					     wAddPlayerForm, NULL, 0);
205 
206   /* Player author */
207   wPlayerAuthorLabel = XtCreateManagedWidget("wPlayerAuthorLabel",
208 					     labelWidgetClass,
209 					     wAddPlayerForm, NULL, 0);
210   wPlayerAuthorText = XtCreateManagedWidget("wPlayerAuthorText",
211 					    asciiTextWidgetClass,
212 					    wAddPlayerForm, NULL, 0);
213 
214   /* Player color */
215   wPlayerColorLabel = XtCreateManagedWidget("wPlayerColorLabel",
216 					    labelWidgetClass,
217 					    wAddPlayerForm, NULL, 0);
218   wPlayerColorDisplay = XtVaCreateManagedWidget("wPlayerColorDisplay",
219 						labelWidgetClass,
220 						wAddPlayerForm,
221 						XtNbackground,
222 						COLOR_QueryColor(COLOR_DieToColor(0)),
223 						NULL);
224 
225   /* Space */
226   wPlayerDummy3 = XtCreateManagedWidget("wPlayerDummy3", formWidgetClass,
227 					wAddPlayerForm, NULL, 0);
228 
229   /* OK and Cancel buttons */
230   wPlayerDummy4 = XtCreateManagedWidget("wPlayerDummy4", formWidgetClass,
231 					wAddPlayerForm, NULL, 0);
232   wPlayerOk = XtCreateManagedWidget("wPlayerOk", commandWidgetClass,
233 				    wAddPlayerForm, NULL, 0);
234   XtAddCallback(wPlayerOk, XtNcallback, (XtCallbackProc)PLAYER_Ok, NULL);
235   wPlayerCancel = XtCreateManagedWidget("wPlayerCancel", commandWidgetClass,
236 					wAddPlayerForm, NULL, 0);
237   XtAddCallback(wPlayerCancel, XtNcallback,
238 		(XtCallbackProc)PLAYER_Cancel, NULL);
239 
240   /* Add Actions */
241   XtAppAddActions(appContext, actionTable, XtNumber(actionTable));
242 
243   /* Init the string table and mapping function */
244   ppstrStrings = (String *)MEM_Alloc(sizeof(String)*2);
245   ppstrStrings[0] = (String)MEM_Alloc(strlen(
246 				      RISK_GetNameOfSpecies(SPECIES_HUMAN))+1);
247   strcpy(ppstrStrings[0], RISK_GetNameOfSpecies(SPECIES_HUMAN));
248   ppstrStrings[1] = (String)NULL;
249   piSlotToSpecies = (Int32 *)MEM_Alloc(sizeof(Int32)*1);
250   piSlotToSpecies[0] = SPECIES_HUMAN;
251 }
252 
253 
254 /************************************************************************
255  *  FUNCTION: PLAYER_PopupDialog
256  *  HISTORY:
257  *     01.29.95  ESF  Created.
258  *     02.26.95  ESF  Fixed to generate brighter random colors.
259  *     04.30.95  ESF  Fixed to generate even brighter random colors.
260  *     05.06.95  ESF  Fixed a bug whereas the wrong species was highlighted.
261  *     15.01.00  MSH  Fixed to update color indicator to initial color.
262  *  PURPOSE:
263  *  NOTES: called from "Register players"
264  ************************************************************************/
PLAYER_PopupDialog(void)265 void PLAYER_PopupDialog(void)
266 {
267     Int32 x, y;
268   /* Center the new shell */
269   UTIL_CenterShell(wAddPlayerShell, wToplevel, &x, &y);
270   XtVaSetValues(wAddPlayerShell,
271 		XtNallowShellResize, False,
272 		XtNx, x,
273 		XtNy, y,
274 		XtNborderWidth, 1,
275 		XtNtitle, "Add Player",
276 		NULL);
277 
278 
279   /* TBD: Could make sure here that COLOR_DieToColor(0) had a
280    * reasonable color for the new player, i.e. unique, nice...
281    * for now pick a random color...but not too dim!!
282    */
283   PLAYER_InitColor();
284 
285   /* Update the color indicator */
286   XtVaSetValues(wPlayerColorDisplay, XtNbackground,
287 		COLOR_QueryColor(COLOR_DieToColor(0)), NULL);
288 
289   /* Do the species stuff */
290   PLAYER_RenderSpecies();
291   PLAYER_SetSpecies(iCurrentSpecies);
292   XawListHighlight(wPlayerSpeciesListbox,
293 		   PLAYER_SpeciesToSlot(iCurrentSpecies));
294 
295   /* Pop the dialog up, set the keyboard focus */
296   XtPopup(wAddPlayerShell, XtGrabExclusive);
297   fPoppedUp = TRUE;
298   XtSetKeyboardFocus(wToplevel, wPlayerNameText);
299   XtSetKeyboardFocus(wAddPlayerShell, wPlayerNameText);
300 }
301 
302 
303 /************************************************************************
304  *  FUNCTION: PLAYER_Ok
305  *  HISTORY:
306  *     01.29.94  ESF  Created.
307  *     01.31.94  ESF  Delete the strings after registering.
308  *     02.05.94  ESF  Remove local registration from here.
309  *     02.05.94  ESF  Adding color validity checking.
310  *     03.07.94  ESF  Switched to varargs Xt calls.
311  *     03.08.94  ESF  Fixed lack of NULL termination in XtVa calls.
312  *     05.04.94  ESF  Fixed DistObj changes, added SetNumLivePlayers()
313  *     05.07.94  ESF  Fixed to not let too many players register.
314  *     11.16.94  ESF  Fixed to not send info to the server re. new player.
315  *     01.15.95  ESF  Fixed to not allocate memory for the empty strings.
316  *  PURPOSE:
317  *  NOTES:
318  ************************************************************************/
PLAYER_Ok(void)319 void PLAYER_Ok(void)
320 {
321   CString  strPlayerName;
322   Int32    iNewPlayer;
323   XColor   xColor;
324   char buf[256];
325 
326   /* Get the name */
327   XtVaGetValues(wPlayerNameText, XtNstring, &strPlayerName, NULL);
328 
329   /* Don't bother doing anything if something's not filled out */
330   if (!strlen(strPlayerName))
331     return;
332 
333   /* See if there are too many players */
334   if ((iNewPlayer=CLNT_AllocPlayer(CBK_IncomingMessage)) == -1)
335     {
336       (void)UTIL_PopupDialog("Error", "Maximum number of players exceeded!",
337 			     1, "Ok", NULL, NULL);
338       return;
339     }
340 
341   /* Get the XColor from the color index */
342   COLOR_GetColor(COLOR_DieToColor(0),
343 		 &xColor.red, &xColor.green, &xColor.blue);
344   snprintf(buf, sizeof(buf), "#%02x%02x%02x",
345 	  xColor.red/256, xColor.green/256, xColor.blue/256);
346 
347   /* Init. the player */
348   RISK_SetColorCStringOfPlayer(iNewPlayer, buf);
349   RISK_SetSpeciesOfPlayer(iNewPlayer, iCurrentSpecies);
350   RISK_SetNameOfPlayer(iNewPlayer, strPlayerName);
351 
352   /* If the client is human, then the client is this one, otherwise
353    * it's the AI client that registered it.
354    */
355 
356   if (iCurrentSpecies == SPECIES_HUMAN)
357     RISK_SetClientOfPlayer(iNewPlayer, CLNT_GetThisClientID());
358   else
359     RISK_SetClientOfPlayer(iNewPlayer,
360 			   RISK_GetClientOfSpecies(iCurrentSpecies));
361 
362   /* This player is now finished.  Note this */
363   RISK_SetAllocationStateOfPlayer(iNewPlayer, ALLOC_COMPLETE);
364 
365   /* Make sure the name's erased */
366   XtVaSetValues(wPlayerNameText, XtNstring, "", NULL);
367 
368   XtPopdown(wAddPlayerShell);
369   fPoppedUp = FALSE;
370 
371   /* Reset keyboard focus */
372   XtSetKeyboardFocus(wToplevel, wToplevel);
373 }
374 
375 
376 /************************************************************************
377  *  FUNCTION: PLAYER_Cancel
378  *  HISTORY:
379  *     01.29.95  ESF  Created.
380  *     02.12.95  ESF  Finished.
381  *  PURPOSE:
382  *  NOTES:
383  ************************************************************************/
PLAYER_Cancel(void)384 void PLAYER_Cancel(void)
385 {
386   CString strName;
387 
388   /* Make sure the player name widget
389    * is empty, popup warning if not.
390    */
391 
392   XtVaGetValues(wPlayerNameText, XtNstring, &strName, NULL);
393   if (strlen(strName))
394     if (UTIL_PopupDialog("Warning", "Discard current registration data?",
395 			 2, "Yes", "No", NULL) == QUERY_NO)
396       return;
397 
398   XtPopdown(wAddPlayerShell);
399 
400   /* Reset keyboard focus */
401   XtSetKeyboardFocus(wToplevel, wToplevel);
402 }
403 
404 
405 /************************************************************************
406  *  FUNCTION: PLAYER_EditColor
407  *  HISTORY:
408  *     01.29.95  ESF  Created.
409  *     15.01.00  MSH  Fixed to update color indicator widget after edit.
410  *  PURPOSE:
411  *  NOTES:
412  ************************************************************************/
PLAYER_EditColor(void)413 void PLAYER_EditColor(void)
414 {
415   /* Relinquish the keyboard focus */
416   XtUngrabKeyboard(wPlayerNameText, CurrentTime);
417 
418   /* Popup the color editing dialog */
419   COLEDIT_EditColor(COLOR_DieToColor(0), FALSE);
420 
421   /* Update the color indicator */
422   XtVaSetValues(wPlayerColorDisplay, XtNbackground,
423 		COLOR_QueryColor(COLOR_DieToColor(0)), NULL);
424 
425   /* Regain the keyboard focus */
426   while(XtGrabKeyboard(wPlayerNameText, True, GrabModeAsync, GrabModeAsync,
427 		       CurrentTime) == GrabNotViewable)
428     ; /* TwiddleThumbs() */
429 }
430 
431 
432 /************************************************************************
433  *  FUNCTION: PLAYER_SetSpecies
434  *  HISTORY:
435  *     02.12.95  ESF  Created.
436  *  PURPOSE:
437  *  NOTES:
438  ************************************************************************/
PLAYER_SetSpecies(Int32 iSpecies)439 void PLAYER_SetSpecies(Int32 iSpecies)
440 {
441   if ((RISK_GetNameOfSpecies(iSpecies)) == NULL)
442     {
443       printf("Warning: Illegal species (%d)\n", iSpecies);
444       return;
445     }
446 
447   XtVaSetValues(wPlayerDescText, XtNstring,
448 		RISK_GetDescriptionOfSpecies(iSpecies), NULL);
449   XtVaSetValues(wPlayerAuthorText, XtNstring,
450 		RISK_GetAuthorOfSpecies(iSpecies), NULL);
451   XtVaSetValues(wPlayerVersionText, XtNstring,
452 		RISK_GetVersionOfSpecies(iSpecies), NULL);
453 }
454 
455 
456 /************************************************************************
457  *  FUNCTION: PLAYER_Callback
458  *  HISTORY:
459  *     02.23.95  ESF  Created.
460  *  PURPOSE:
461  *  NOTES:
462  ************************************************************************/
PLAYER_Callback(Int32 iMessType,void * pvMess)463 void PLAYER_Callback(Int32 iMessType, void *pvMess)
464 {
465   /*
466    * SpeciesCreated         --> Add species to species list
467    * SpeciesDestroyed       --> Delete species from species list
468    */
469 
470   if (iMessType == MSG_OBJINTUPDATE &&
471       ((MsgObjIntUpdate *)pvMess)->iField == SPE_ALLOCATION &&
472       ((MsgObjIntUpdate *)pvMess)->iNewValue == ALLOC_COMPLETE)
473     {
474       /* SpeciesCreated */
475       PLAYER_SpeciesCreated(((MsgObjStrUpdate *)pvMess)->iIndex1);
476     }
477 
478   else if (iMessType == MSG_OBJINTUPDATE &&
479 	   ((MsgObjIntUpdate *)pvMess)->iField == SPE_ALLOCATION &&
480 	   ((MsgObjIntUpdate *)pvMess)->iNewValue == ALLOC_NONE)
481     {
482       /* SpeciesDestroyed */
483       PLAYER_SpeciesDestroyed(((MsgObjIntUpdate *)pvMess)->iIndex1);
484     }
485 }
486 
487 
488 #define PAD_LENGTH 34
489 
490 /************************************************************************
491  *  FUNCTION: PLAYER_RenderSpecies
492  *  HISTORY:
493  *     02.23.95  ESF  Created.
494  *     03.03.95  ESF  Finished.
495  *     04.01.95  ESF  Fixed a bug, needed parens around iNumSpecies+1.
496  *  PURPOSE:
497  *  NOTES:
498  ************************************************************************/
PLAYER_RenderSpecies(void)499 void PLAYER_RenderSpecies(void)
500 {
501   /* This is just a first approximation of a future, perhaps much
502    * faster or smarter version.  This one does its job, though...
503    */
504 
505   XawListReturnStruct  *pItem;
506   Int32     i, j, k, iLastSelection, iLastSpecies;
507   Int32     iNumSpecies = RISK_GetNumSpecies();
508   CString  *ppstr = (CString *)MEM_Alloc(sizeof(CString)*(iNumSpecies+1));
509   Int32    *piMap = (Int32 *)MEM_Alloc(sizeof(Int32)*iNumSpecies);
510   CString   str;
511 
512   for (i=j=0; i<RISK_GetNumSpecies(); i++, j++)
513     {
514       /* Find the next live species */
515       while(RISK_GetAllocationStateOfSpecies(j) == FALSE)
516 	j++;
517 
518       str = RISK_GetNameOfSpecies(j);
519       D_Assert(str, "Null species.");
520 
521       /* Add it to the list, with a padding of spaces */
522       ppstr[i] = MEM_Alloc(sizeof(Char)*PAD_LENGTH);
523       strcpy(ppstr[i], str);
524       for(k=strlen(str); k<PAD_LENGTH-1; k++)
525 	ppstr[i][k] = ' ';
526       ppstr[i][k] = '\0';
527 
528       /* Add the mapping from slot to species */
529       piMap[i] = j;
530     }
531   ppstr[i] = (String)NULL;
532 
533   /* Find out the last selection */
534   pItem          = XawListShowCurrent(wPlayerSpeciesListbox);
535   iLastSelection = pItem->list_index;
536   iLastSpecies   = PLAYER_SlotToSpecies(iLastSelection);
537   XtFree((void *)pItem);
538 
539   /* Display the list! */
540   XtVaSetValues(wPlayerSpeciesListbox,
541 		XtNlist, ppstr,
542 		XtNnumberStrings, iNumSpecies,
543 		NULL);
544 
545   /* If there were old strings, free all of the memory */
546   if (ppstrStrings)
547     {
548       for (i=0; i!=iNumSlots; i++)
549 	MEM_Free(ppstrStrings[i]);
550       MEM_Free(ppstrStrings);
551     }
552   if (piSlotToSpecies)
553     MEM_Free(piSlotToSpecies);
554 
555   /* Keep the new list of strings and the new mapping */
556   ppstrStrings     = ppstr;
557   piSlotToSpecies  = piMap;
558   iNumSlots        = iNumSpecies;
559 
560   /* Select the last species if it's still around */
561   if ((iLastSpecies = PLAYER_SpeciesToSlot(iLastSpecies)) != -1)
562     XawListHighlight(wPlayerSpeciesListbox, iLastSpecies);
563   else
564     XawListHighlight(wPlayerSpeciesListbox,
565 		     MIN(iLastSelection, iNumSpecies-1));
566 }
567 
568 
569 /************************************************************************
570  *  FUNCTION: PLAYER_SpeciesDestroyed
571  *  HISTORY:
572  *     02.23.95  ESF  Created.
573  *  PURPOSE:
574  *  NOTES:
575  ************************************************************************/
PLAYER_SpeciesDestroyed(Int32 iSpecies)576 void PLAYER_SpeciesDestroyed(Int32 iSpecies)
577 {
578   UNUSED(iSpecies);
579   if (fPoppedUp == TRUE)
580     PLAYER_RenderSpecies();
581 }
582 
583 
584 /************************************************************************
585  *  FUNCTION: PLAYER_SpeciesCreated
586  *  HISTORY:
587  *     02.23.95  ESF  Created.
588  *  PURPOSE:
589  *  NOTES:
590  ************************************************************************/
PLAYER_SpeciesCreated(Int32 iSpecies)591 void PLAYER_SpeciesCreated(Int32 iSpecies)
592 {
593   UNUSED(iSpecies);
594   if (fPoppedUp == TRUE)
595     PLAYER_RenderSpecies();
596 }
597 
598 
599 /************************************************************************
600  *  FUNCTION: PLAYER_SelectSpecies
601  *  HISTORY:
602  *     03.03.95  ESF  Created.
603  *  PURPOSE:
604  *  NOTES:
605  ************************************************************************/
PLAYER_SelectSpecies(Widget w,XtPointer pData,XtPointer call_data)606 void PLAYER_SelectSpecies(Widget w, XtPointer pData, XtPointer call_data)
607 {
608   const XawListReturnStruct  *pItem =
609                                   XawListShowCurrent(wPlayerSpeciesListbox);
610   const Int32                 iIndex = pItem->list_index;
611   UNUSED(w);
612   UNUSED(pData);
613   UNUSED(call_data);
614 
615   /* Free up memory */
616   XtFree((void *)pItem);
617 
618   /* If it's off any of the species, then set the one that was set */
619   if (iIndex == -1)
620     {
621       PLAYER_SetSpecies(iCurrentSpecies);
622       XawListHighlight(wPlayerSpeciesListbox,
623 		       PLAYER_SpeciesToSlot(iCurrentSpecies));
624       return;
625     }
626 
627   /* Find out what species it is */
628   iCurrentSpecies = PLAYER_SlotToSpecies(iIndex);
629 
630   /* Put in the description, author, etc. */
631   PLAYER_SetSpecies(iCurrentSpecies);
632 }
633 
634 
635 /************************************************************************
636  *  FUNCTION: PLAYER_SlotToSpecies
637  *  HISTORY:
638  *     03.03.95  ESF  Created.
639  *  PURPOSE:
640  *  NOTES:
641  ************************************************************************/
PLAYER_SlotToSpecies(Int32 iSlot)642 Int32 PLAYER_SlotToSpecies(Int32 iSlot)
643 {
644   D_Assert(iSlot>=-1, "Wierd slot!");
645   D_Assert(piSlotToSpecies, "No mapping!");
646 
647   /* This means that the user has clicked off of any slot */
648   if (iSlot == -1)
649     return iCurrentSpecies;
650 
651   return piSlotToSpecies[iSlot];
652 }
653 
654 
655 /************************************************************************
656  *  FUNCTION: PLAYER_SpeciesToSlot
657  *  HISTORY:
658  *     03.03.95  ESF  Created.
659  *     05.13.95  ESF  Fixed to not return error.
660  *  PURPOSE:
661  *  NOTES:
662  ************************************************************************/
PLAYER_SpeciesToSlot(Int32 iSpecies)663 Int32 PLAYER_SpeciesToSlot(Int32 iSpecies)
664 {
665   Int32 i;
666 
667   for (i=0;
668        ppstrStrings[i]!=NULL;
669        i++)
670     {
671       if (piSlotToSpecies[i] == iSpecies)
672 	return i;
673     }
674 
675   /* The species doesn't exist, return SPECIES_HUMAN */
676   iCurrentSpecies = SPECIES_HUMAN;
677   return iCurrentSpecies;
678 }
679