1 /***************************************************************************
2 
3     file                 : driverconfig.cpp
4     created              : Wed Apr 26 20:05:12 CEST 2000
5     copyright            : (C) 2000 by Eric Espie
6     email                : torcs@free.fr
7     version              : $Id: driverconfig.cpp,v 1.7.2.8 2012/06/10 01:38:23 berniw Exp $
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *   This program is free software; you can redistribute it and/or modify  *
14  *   it under the terms of the GNU General Public License as published by  *
15  *   the Free Software Foundation; either version 2 of the License, or     *
16  *   (at your option) any later version.                                   *
17  *                                                                         *
18  ***************************************************************************/
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <tgfclient.h>
23 #include <track.h>
24 #include <robot.h>
25 #include <playerpref.h>
26 #include <controlconfig.h>
27 #include <portability.h>
28 
29 #include "driverconfig.h"
30 
31 #define NO_DRV	"--- empty ---"
32 #define dllname   "human"
33 
34 static const char *level_str[] = { ROB_VAL_ROOKIE, ROB_VAL_AMATEUR, ROB_VAL_SEMI_PRO, ROB_VAL_PRO };
35 static const int nbLevels = sizeof(level_str) / sizeof(level_str[0]);
36 
37 static float LabelColor[] = {1.0, 0.0, 1.0, 1.0};
38 
39 static int	scrollList;
40 static void	*scrHandle = NULL;
41 static void	*prevHandle = NULL;
42 
43 static int NameEditId;
44 static int CarEditId;
45 static int CatEditId;
46 static int RaceNumEditId;
47 static int TransEditId;
48 static int PitsEditId;
49 static int SkillId;
50 static int AutoReverseId;
51 
52 #define NB_DRV	10
53 
54 typedef struct tInfo
55 {
56     char	*name;
57     char	*dispname;
58 } tInfo;
59 
60 struct tCarInfo;
61 struct tCatInfo;
62 
63 GF_TAILQ_HEAD(CarsInfoHead, struct tCarInfo);
64 GF_TAILQ_HEAD(CatsInfoHead, struct tCatInfo);
65 
66 typedef struct tCatInfo
67 {
68     struct tCatInfo	*next;
69     struct tCatInfo	*prev;
70     tInfo		info;
71     tCarsInfoHead	CarsInfoList;
72     GF_TAILQ_ENTRY(struct tCatInfo) link;
73 } tCatInfo;
74 
75 typedef struct tCarInfo
76 {
77     struct tCarInfo	*next;
78     struct tCarInfo	*prev;
79     tInfo		info;
80     tCatInfo		*cat;
81     GF_TAILQ_ENTRY(struct tCarInfo) link;
82 } tCarInfo;
83 
84 typedef struct PlayerInfo
85 {
86     tInfo	info;
87     tCarInfo	*carinfo;
88     int		racenumber;
89     const char *transmission;
90     int		nbpitstops;
91     float	color[4];
92     int		skilllevel;
93     int		autoreverse;
94 } tPlayerInfo;
95 
96 #define _Name		info.name
97 #define _DispName	info.dispname
98 
99 static tPlayerInfo PlayersInfo[NB_DRV];
100 
101 static tCatsInfoHead CatsInfoList;
102 
103 static tPlayerInfo	*curPlayer;
104 
105 static const char *Yn[] = {HM_VAL_YES, HM_VAL_NO};
106 
107 static void
refreshEditVal(void)108 refreshEditVal(void)
109 {
110 	const int BUFSIZE = 1024;
111 	char buf[BUFSIZE];
112 
113 	if (curPlayer == NULL) {
114 		GfuiEditboxSetString(scrHandle, NameEditId, "");
115 		GfuiEnable(scrHandle, NameEditId, GFUI_DISABLE);
116 
117 		GfuiEditboxSetString(scrHandle, RaceNumEditId, "");
118 		GfuiEnable(scrHandle, RaceNumEditId, GFUI_DISABLE);
119 
120 		GfuiLabelSetText(scrHandle, CarEditId, "");
121 		GfuiEnable(scrHandle, CarEditId, GFUI_DISABLE);
122 
123 		GfuiLabelSetText(scrHandle, CatEditId, "");
124 
125 		GfuiEditboxSetString(scrHandle, RaceNumEditId, "");
126 		GfuiEnable(scrHandle, RaceNumEditId, GFUI_DISABLE);
127 
128 		GfuiLabelSetText(scrHandle, TransEditId, "");
129 
130 		GfuiEditboxSetString(scrHandle, PitsEditId, "");
131 		GfuiEnable(scrHandle, PitsEditId, GFUI_DISABLE);
132 
133 		GfuiLabelSetText(scrHandle, SkillId, "");
134 
135 		GfuiLabelSetText(scrHandle, AutoReverseId, "");
136 	} else {
137 		GfuiEditboxSetString(scrHandle, NameEditId, curPlayer->_DispName);
138 		GfuiEnable(scrHandle, NameEditId, GFUI_ENABLE);
139 
140 		snprintf(buf, BUFSIZE, "%d", curPlayer->racenumber);
141 		GfuiEditboxSetString(scrHandle, RaceNumEditId, buf);
142 		GfuiEnable(scrHandle, RaceNumEditId, GFUI_ENABLE);
143 
144 		GfuiLabelSetText(scrHandle, CarEditId, curPlayer->carinfo->_DispName);
145 		GfuiEnable(scrHandle, CarEditId, GFUI_ENABLE);
146 
147 		GfuiLabelSetText(scrHandle, CatEditId, curPlayer->carinfo->cat->_DispName);
148 
149 		snprintf(buf, BUFSIZE, "%d", curPlayer->racenumber);
150 		GfuiEditboxSetString(scrHandle, RaceNumEditId, buf);
151 		GfuiEnable(scrHandle, RaceNumEditId, GFUI_ENABLE);
152 
153 		GfuiLabelSetText(scrHandle, TransEditId, curPlayer->transmission);
154 
155 		snprintf(buf, BUFSIZE, "%d", curPlayer->nbpitstops);
156 		GfuiEditboxSetString(scrHandle, PitsEditId, buf);
157 		GfuiEnable(scrHandle, PitsEditId, GFUI_ENABLE);
158 
159 		GfuiLabelSetText(scrHandle, SkillId, level_str[curPlayer->skilllevel]);
160 
161 		GfuiLabelSetText(scrHandle, AutoReverseId, Yn[curPlayer->autoreverse]);
162 	}
163 }
164 
165 static void
onSelect(void *)166 onSelect(void * /* Dummy */)
167 {
168     GfuiScrollListGetSelectedElement(scrHandle, scrollList, (void**)&curPlayer);
169     refreshEditVal();
170 }
171 
172 static void
GenCarsInfo(void)173 GenCarsInfo(void)
174 {
175 	tCarInfo *curCar;
176 	tCatInfo *curCat;
177 	tCatInfo *tmpCat;
178 	tFList *files;
179 	tFList *curFile;
180 	void *carparam;
181 	void *hdle;
182 	const int BUFSIZE = 1024;
183 	char buf[BUFSIZE];
184 
185 	/* Empty the lists */
186 	while ((curCat = GF_TAILQ_FIRST(&CatsInfoList)) != NULL) {
187 		GF_TAILQ_REMOVE(&CatsInfoList, curCat, link);
188 		while ((curCar = GF_TAILQ_FIRST(&(curCat->CarsInfoList))) != NULL) {
189 			GF_TAILQ_REMOVE(&(curCat->CarsInfoList), curCar, link);
190 			free(curCar->_Name);
191 			free(curCar->_DispName);
192 			free(curCar);
193 		}
194 		free(curCat->_Name);
195 		free(curCat->_DispName);
196 		free(curCat);
197 	}
198 
199 	files = GfDirGetList("categories");
200 	curFile = files;
201 	if ((curFile != NULL) && (curFile->name[0] != '.')) {
202 		do {
203 			curFile = curFile->next;
204 			curCat = (tCatInfo*)calloc(1, sizeof(tCatInfo));
205 			GF_TAILQ_INIT(&(curCat->CarsInfoList));
206 			char* str = strchr(curFile->name, '.');
207 			*str = '\0';
208 			curCat->_Name = strdup(curFile->name);
209 			snprintf(buf, BUFSIZE, "categories/%s.xml", curFile->name);
210 			hdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
211 			if (!hdle) {
212 				continue;
213 			}
214 			curCat->_DispName = strdup(GfParmGetName(hdle));
215 			GfParmReleaseHandle(hdle);
216 			GF_TAILQ_INSERT_TAIL(&CatsInfoList, curCat, link);
217 		} while (curFile != files);
218 	}
219 	GfDirFreeList(files, NULL, true, false);
220 
221 	files = GfDirGetList("cars");
222 	curFile = files;
223 	if ((curFile != NULL) && (curFile->name[0] != '.')) {
224 		do {
225 			curFile = curFile->next;
226 			curCar = (tCarInfo*)calloc(1, sizeof(tCarInfo));
227 			curCar->_Name = strdup(curFile->name);
228 			snprintf(buf, BUFSIZE, "cars/%s/%s.xml", curFile->name, curFile->name);
229 			carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
230 			if (!carparam) {
231 				continue;
232 			}
233 
234 			curCar->_DispName = strdup(GfParmGetName(carparam));
235 			/* search for the category */
236 			const char* str = GfParmGetStr(carparam, SECT_CAR, PRM_CATEGORY, "");
237 			curCat = GF_TAILQ_FIRST(&CatsInfoList);
238 			if (curCat != NULL) {
239 				do {
240 					if (strcmp(curCat->_Name, str) == 0) {
241 					break;
242 					}
243 				} while ((curCat = GF_TAILQ_NEXT(curCat, link)) != NULL);
244 			}
245 			curCar->cat = curCat;
246 			GF_TAILQ_INSERT_TAIL(&(curCat->CarsInfoList), curCar, link);
247 			GfParmReleaseHandle(carparam);
248 		} while (curFile != files);
249 	}
250 	GfDirFreeList(files, NULL, true, false);
251 
252 	/* Remove the empty categories */
253 	curCat = GF_TAILQ_FIRST(&CatsInfoList);
254 	do {
255 		curCar = GF_TAILQ_FIRST(&(curCat->CarsInfoList));
256 		tmpCat = curCat;
257 		curCat = GF_TAILQ_NEXT(curCat, link);
258 		if (curCar == NULL) {
259 			GfOut("Removing empty category %s\n", tmpCat->_DispName);
260 			GF_TAILQ_REMOVE(&CatsInfoList, tmpCat, link);
261 			free(tmpCat->_Name);
262 			free(tmpCat->_DispName);
263 			free(tmpCat);
264 		}
265 	} while (curCat  != NULL);
266 
267 }
268 
269 static void
UpdtScrollList(void)270 UpdtScrollList(void)
271 {
272 	char	*str;
273 	int		i;
274 	void	*tmp;
275 
276 	/* free the previous scrollist elements */
277 	while((str = GfuiScrollListExtractElement(scrHandle, scrollList, 0, (void**)&tmp)) != NULL) {
278 	}
279 
280 	for (i = 0; i < NB_DRV; i++) {
281 		GfuiScrollListInsertElement(scrHandle, scrollList, PlayersInfo[i]._DispName, i, (void*)&(PlayersInfo[i]));
282 	}
283 }
284 
285 static void
DeletePlayer(void *)286 DeletePlayer(void * /* dummy */)
287 {
288 	if (curPlayer) {
289 		curPlayer->_DispName = strdup(NO_DRV);
290 		refreshEditVal();
291 		UpdtScrollList();
292 	}
293 }
294 
295 static void
ConfControls(void *)296 ConfControls(void * /* dummy */ )
297 {
298 	int index;
299 
300 	if (curPlayer) {
301 		index = curPlayer - PlayersInfo + 1;
302 		GfuiScreenActivate(TorcsControlMenuInit(scrHandle, index));
303 	}
304 }
305 
306 static int
GenDrvList(void)307 GenDrvList(void)
308 {
309 	void *drvinfo;
310 	const int SSTRINGSIZE = 256;
311 	char sstring[SSTRINGSIZE];
312 	int i;
313 	int j;
314 	const char *driver;
315 	tCarInfo *car;
316 	tCatInfo *cat;
317 	const char *str;
318 	int found;
319 	const int BUFSIZE = 1024;
320 	char buf[BUFSIZE];
321 
322 	snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), HM_DRV_FILE);
323 	drvinfo = GfParmReadFile(buf, GFPARM_RMODE_REREAD);
324 	if (drvinfo == NULL) {
325 		return -1;
326 	}
327 
328 	for (i = 0; i < NB_DRV; i++) {
329 		snprintf(sstring, SSTRINGSIZE, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, i+1);
330 		driver = GfParmGetStr(drvinfo, sstring, ROB_ATTR_NAME, "");
331 		if (strlen(driver) == 0) {
332 			PlayersInfo[i]._DispName = strdup(NO_DRV);
333 			PlayersInfo[i]._Name = strdup(dllname);
334 			PlayersInfo[i].carinfo = GF_TAILQ_FIRST(&((GF_TAILQ_FIRST(&CatsInfoList))->CarsInfoList));
335 			PlayersInfo[i].racenumber = 0;
336 			PlayersInfo[i].color[0] = 1.0;
337 			PlayersInfo[i].color[1] = 1.0;
338 			PlayersInfo[i].color[2] = 0.5;
339 			PlayersInfo[i].color[3] = 1.0;
340 		} else {
341 			PlayersInfo[i]._DispName = strdup(driver);
342 			PlayersInfo[i]._Name = strdup(dllname);
343 			PlayersInfo[i].skilllevel = 0;
344 			str = GfParmGetStr(drvinfo, sstring, ROB_ATTR_LEVEL, level_str[0]);
345 			for(j = 0; j < nbLevels; j++) {
346 				if (strcmp(level_str[j], str) == 0) {
347 					PlayersInfo[i].skilllevel = j;
348 					break;
349 				}
350 			}
351 			str = GfParmGetStr(drvinfo, sstring, ROB_ATTR_CAR, "");
352 			found = 0;
353 			cat = GF_TAILQ_FIRST(&CatsInfoList);
354 			PlayersInfo[i].carinfo = GF_TAILQ_FIRST(&(cat->CarsInfoList));
355 			do {
356 				car = GF_TAILQ_FIRST(&(cat->CarsInfoList));
357 				if (car != NULL) {
358 					do {
359 						if (strcmp(car->_Name, str) == 0) {
360 							found = 1;
361 							PlayersInfo[i].carinfo = car;
362 						}
363 					} while (!found && ((car = GF_TAILQ_NEXT(car, link)) != NULL));
364 				}
365 			} while (!found && ((cat = GF_TAILQ_NEXT(cat, link)) != NULL));
366 			PlayersInfo[i].racenumber  = (int)GfParmGetNum(drvinfo, sstring, ROB_ATTR_RACENUM, (char*)NULL, 0);
367 			PlayersInfo[i].color[0]    = (float)GfParmGetNum(drvinfo, sstring, ROB_ATTR_RED, (char*)NULL, 1.0);
368 			PlayersInfo[i].color[1]    = (float)GfParmGetNum(drvinfo, sstring, ROB_ATTR_GREEN, (char*)NULL, 1.0);;
369 			PlayersInfo[i].color[2]    = (float)GfParmGetNum(drvinfo, sstring, ROB_ATTR_BLUE, (char*)NULL, 0.5);;
370 			PlayersInfo[i].color[3]    = 1.0;
371 		}
372     }
373     UpdtScrollList();
374 
375     snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), HM_PREF_FILE);
376     void* PrefHdle = GfParmReadFile(buf, GFPARM_RMODE_REREAD);
377     if (PrefHdle == NULL) {
378 		GfParmReleaseHandle(drvinfo);
379 		return -1;
380     }
381 
382     for (i = 0; i < NB_DRV; i++) {
383 		snprintf(sstring, SSTRINGSIZE, "%s/%s/%d", HM_SECT_PREF, HM_LIST_DRV, i+1);
384 		str = GfParmGetStr(PrefHdle, sstring, HM_ATT_TRANS, HM_VAL_AUTO);
385 		if (strcmp(str, HM_VAL_AUTO) == 0) {
386 			PlayersInfo[i].transmission = HM_VAL_AUTO;
387 		} else {
388 			PlayersInfo[i].transmission = HM_VAL_MANUAL;
389 		}
390 		PlayersInfo[i].nbpitstops = (int)GfParmGetNum(PrefHdle, sstring, HM_ATT_NBPITS, (char*)NULL, 0);
391 		if (!strcmp(GfParmGetStr(PrefHdle, sstring, HM_ATT_AUTOREVERSE, Yn[0]), Yn[0])) {
392 			PlayersInfo[i].autoreverse = 0;
393 		} else {
394 			PlayersInfo[i].autoreverse = 1;
395 		}
396     }
397 
398 	GfParmReleaseHandle(PrefHdle);
399 	GfParmReleaseHandle(drvinfo);
400 
401     return 0;
402 }
403 
404 static void
SaveDrvList(void *)405 SaveDrvList(void * /* dummy */)
406 {
407 	void	*drvinfo;
408 	int		i;
409 	const int BUFSIZE = 1024;
410 	char buf[BUFSIZE];
411 
412 	snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), HM_DRV_FILE);
413 	drvinfo = GfParmReadFile(buf, GFPARM_RMODE_STD);
414 	if (drvinfo == NULL) {
415 		return;
416 	}
417 
418 	for (i = 0; i < NB_DRV; i++) {
419 		snprintf(buf, BUFSIZE, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, i+1);
420 		if (strcmp(PlayersInfo[i]._DispName, NO_DRV) == 0) {
421 			GfParmSetStr(drvinfo, buf, ROB_ATTR_NAME, "");
422 		} else {
423 			GfParmSetStr(drvinfo, buf, ROB_ATTR_NAME, PlayersInfo[i]._DispName);
424 			GfParmSetStr(drvinfo, buf, ROB_ATTR_CAR, PlayersInfo[i].carinfo->_Name);
425 			GfParmSetNum(drvinfo, buf, ROB_ATTR_RACENUM, (char*)NULL, PlayersInfo[i].racenumber);
426 			GfParmSetNum(drvinfo, buf, ROB_ATTR_RED, (char*)NULL, PlayersInfo[i].color[0]);
427 			GfParmSetNum(drvinfo, buf, ROB_ATTR_GREEN, (char*)NULL, PlayersInfo[i].color[1]);
428 			GfParmSetNum(drvinfo, buf, ROB_ATTR_BLUE, (char*)NULL, PlayersInfo[i].color[2]);
429 			GfParmSetStr(drvinfo, buf, ROB_ATTR_TYPE, ROB_VAL_HUMAN);
430 			GfParmSetStr(drvinfo, buf, ROB_ATTR_LEVEL, level_str[PlayersInfo[i].skilllevel]);
431 		}
432 	}
433 	GfParmWriteFile(NULL, drvinfo, dllname);
434 	GfParmReleaseHandle(drvinfo);
435 
436 	snprintf(buf, BUFSIZE, "%s%s", GetLocalDir(), HM_PREF_FILE);
437 	void* PrefHdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
438 	for (i = 0; i < NB_DRV; i++) {
439 		snprintf(buf, BUFSIZE, "%s/%s/%d", HM_SECT_PREF, HM_LIST_DRV, i+1);
440 		GfParmSetStr(PrefHdle, buf, HM_ATT_TRANS, PlayersInfo[i].transmission);
441 		GfParmSetNum(PrefHdle, buf, HM_ATT_NBPITS, (char*)NULL, (tdble)PlayersInfo[i].nbpitstops);
442 		GfParmSetStr(PrefHdle, buf, HM_ATT_AUTOREVERSE, Yn[PlayersInfo[i].autoreverse]);
443 	}
444 
445 	GfParmWriteFile(NULL, PrefHdle, "preferences");
446 	GfParmReleaseHandle(PrefHdle);
447 	GfuiScreenActivate(prevHandle);
448 	return;
449 }
450 
451 
452 static void
ChangeName(void *)453 ChangeName(void * /* dummy */)
454 {
455 	char	*val;
456 
457 	val = GfuiEditboxGetString(scrHandle, NameEditId);
458 	if (curPlayer != NULL) {
459 		if (curPlayer->_DispName) {
460 			free(curPlayer->_DispName);
461 		}
462 
463 		if (strlen(val)) {
464 			curPlayer->_DispName = strdup(val);
465 		} else {
466 			curPlayer->_DispName = strdup(NO_DRV);
467 		}
468 	}
469 	UpdtScrollList();
470 }
471 
472 static void
ChangeNum(void *)473 ChangeNum(void * /* dummy */)
474 {
475 	char *val;
476 	const int BUFSIZE = 1024;
477 	char buf[BUFSIZE];
478 
479 	val = GfuiEditboxGetString(scrHandle, RaceNumEditId);
480 	if (curPlayer != NULL) {
481 		curPlayer->racenumber = (int)strtol(val, (char **)NULL, 0);
482 		snprintf(buf, BUFSIZE, "%d", curPlayer->racenumber);
483 		GfuiEditboxSetString(scrHandle, RaceNumEditId, buf);
484 	}
485 }
486 
487 static void
ChangePits(void *)488 ChangePits(void * /* dummy */)
489 {
490 	char *val;
491 	const int BUFSIZE = 1024;
492 	char buf[BUFSIZE];
493 
494 	val = GfuiEditboxGetString(scrHandle, PitsEditId);
495 	if (curPlayer != NULL) {
496 		curPlayer->nbpitstops = (int)strtol(val, (char **)NULL, 0);
497 		snprintf(buf, BUFSIZE, "%d", curPlayer->nbpitstops);
498 		GfuiEditboxSetString(scrHandle, PitsEditId, buf);
499 	}
500 }
501 
502 static void
ChangeCar(void * vp)503 ChangeCar(void *vp)
504 {
505 	tCarInfo	*car;
506 	tCatInfo	*cat;
507 
508 	if (curPlayer == NULL) {
509 		return;
510 	}
511 
512 	cat = curPlayer->carinfo->cat;
513 	if (vp == 0) {
514 		car = GF_TAILQ_PREV(curPlayer->carinfo, CarsInfoHead, link);
515 		if (car == NULL) {
516 			car = GF_TAILQ_LAST(&(cat->CarsInfoList), CarsInfoHead);
517 		}
518 	} else {
519 		car = GF_TAILQ_NEXT(curPlayer->carinfo, link);
520 		if (car == NULL) {
521 			car = GF_TAILQ_FIRST(&(cat->CarsInfoList));
522 		}
523 	}
524 	curPlayer->carinfo = car;
525 	refreshEditVal();
526 }
527 
528 static void
ChangeCat(void * vp)529 ChangeCat(void *vp)
530 {
531 	tCarInfo	*car;
532 	tCatInfo	*cat;
533 
534 	if (curPlayer == NULL) {
535 		return;
536 	}
537 
538 	cat = curPlayer->carinfo->cat;
539 	if (vp == 0) {
540 		do {
541 			cat = GF_TAILQ_PREV(cat, CatsInfoHead, link);
542 			if (cat == NULL) {
543 			cat = GF_TAILQ_LAST(&CatsInfoList, CatsInfoHead);
544 			}
545 			car = GF_TAILQ_FIRST(&(cat->CarsInfoList));
546 		} while (car == NULL);	/* skip empty categories */
547 	} else {
548 		do {
549 			cat = GF_TAILQ_NEXT(cat, link);
550 			if (cat == NULL) {
551 			cat = GF_TAILQ_FIRST(&CatsInfoList);
552 			}
553 			car = GF_TAILQ_FIRST(&(cat->CarsInfoList));
554 		} while (car == NULL);	/* skip empty categories */
555 	}
556 
557 	curPlayer->carinfo = car;
558 	refreshEditVal();
559 }
560 
561 static void
ChangeLevel(void * vp)562 ChangeLevel(void *vp)
563 {
564 	if (curPlayer == NULL) {
565 		return;
566 	}
567 
568 	if (vp == 0) {
569 		curPlayer->skilllevel--;
570 		if (curPlayer->skilllevel < 0) {
571 			curPlayer->skilllevel = nbLevels - 1;
572 		}
573 	} else {
574 		curPlayer->skilllevel++;
575 		if (curPlayer->skilllevel == nbLevels) {
576 			curPlayer->skilllevel = 0;
577 		}
578 	}
579 	refreshEditVal();
580 }
581 
582 static void
ChangeReverse(void * vdelta)583 ChangeReverse(void *vdelta)
584 {
585 	long delta = (long)vdelta;
586 
587 	if (curPlayer == NULL) {
588 		return;
589 	}
590 
591 	curPlayer->autoreverse += (int)delta;
592 	if (curPlayer->autoreverse < 0) {
593 		curPlayer->autoreverse = 1;
594 	} else if (curPlayer->autoreverse > 1) {
595 		curPlayer->autoreverse = 0;
596 	}
597 
598 	refreshEditVal();
599 }
600 
601 static void
ChangeTrans(void *)602 ChangeTrans(void * /* dummy */)
603 {
604 	if (curPlayer == NULL) {
605 		return;
606 	}
607 
608 	if (strcmp(curPlayer->transmission,HM_VAL_AUTO) != 0) {
609 		curPlayer->transmission = HM_VAL_AUTO;
610 	} else {
611 		curPlayer->transmission = HM_VAL_MANUAL;
612 	}
613 	refreshEditVal();
614 }
615 
616 void *
TorcsDriverMenuInit(void * prevMenu)617 TorcsDriverMenuInit(void *prevMenu)
618 {
619 	int		x, y, x2, x3, x4, dy;
620 	static int	firstTime = 1;
621 
622 	if (firstTime) {
623 		firstTime = 0;
624 		GF_TAILQ_INIT(&CatsInfoList);
625 	}
626 
627 	/* screen already created */
628 	if (scrHandle) {
629 		GenCarsInfo();
630 		GenDrvList();
631 		return scrHandle;
632 	}
633 	prevHandle = prevMenu;
634 
635 	scrHandle = GfuiScreenCreate();
636 	GfuiTitleCreate(scrHandle, "Player Configuration", 0);
637 
638 	GfuiScreenAddBgImg(scrHandle, "data/img/splash-qrdrv.png");
639 
640 	GfuiLabelCreate(scrHandle, "Players", GFUI_FONT_LARGE, 496, 400, GFUI_ALIGN_HC_VB, 0);
641 
642 	scrollList = GfuiScrollListCreate(scrHandle, GFUI_FONT_MEDIUM_C,
643 						396, 390 - NB_DRV * GfuiFontHeight(GFUI_FONT_MEDIUM_C),
644 						GFUI_ALIGN_HL_VB, 200, NB_DRV * GfuiFontHeight(GFUI_FONT_MEDIUM_C), GFUI_SB_NONE,
645 						NULL, onSelect);
646 
647 	GfuiButtonCreate(scrHandle, "Delete", GFUI_FONT_LARGE, 496, 340 - NB_DRV * GfuiFontHeight(GFUI_FONT_MEDIUM_C),
648 				140, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
649 				NULL, DeletePlayer, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
650 
651 	GfuiButtonCreate(scrHandle, "Controls", GFUI_FONT_LARGE, 496, 340 - NB_DRV * GfuiFontHeight(GFUI_FONT_MEDIUM_C) - 30,
652 				140, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
653 				NULL, ConfControls, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
654 
655 	GenCarsInfo();
656 	if (GenDrvList()) {
657 		GfuiScreenRelease(scrHandle);
658 		return NULL;
659 	}
660 
661 	x = 20;
662 	x2 = 170;
663 	x3 = x2 + 100;
664 	x4 = x2 + 200;
665 	y = 370;
666 	dy = 30;
667 
668 	GfuiLabelCreate(scrHandle, "Name:", GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0);
669 	NameEditId = GfuiEditboxCreate(scrHandle, "", GFUI_FONT_MEDIUM_C,
670 					x2+10, y, 180, 16, NULL, (tfuiCallback)NULL, ChangeName);
671 
672 	y -= dy;
673 	GfuiLabelCreate(scrHandle, "Category:", GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0);
674 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-left.png", "data/img/arrow-left.png",
675 				"data/img/arrow-left.png", "data/img/arrow-left-pushed.png",
676 				x2, y, GFUI_ALIGN_HL_VB, 1,
677 				(void*)0, ChangeCat,
678 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
679 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-right.png", "data/img/arrow-right.png",
680 				"data/img/arrow-right.png", "data/img/arrow-right-pushed.png",
681 				x4, y, GFUI_ALIGN_HR_VB, 1,
682 				(void*)1, ChangeCat,
683 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
684 	CatEditId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HC_VB, 32);
685 	GfuiLabelSetColor(scrHandle, CatEditId, LabelColor);
686 
687 	y -= dy;
688 	GfuiLabelCreate(scrHandle, "Car:", GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0);
689 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-left.png", "data/img/arrow-left.png",
690 				"data/img/arrow-left.png", "data/img/arrow-left-pushed.png",
691 				x2, y, GFUI_ALIGN_HL_VB, 1,
692 				(void*)0, ChangeCar,
693 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
694 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-right.png", "data/img/arrow-right.png",
695 				"data/img/arrow-right.png", "data/img/arrow-right-pushed.png",
696 				x4, y, GFUI_ALIGN_HR_VB, 1,
697 				(void*)1, ChangeCar,
698 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
699 	CarEditId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HC_VB, 32);
700 	GfuiLabelSetColor(scrHandle, CarEditId, LabelColor);
701 
702 	y -= dy;
703 	GfuiLabelCreate(scrHandle, "Race Number:", GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0);
704 	RaceNumEditId = GfuiEditboxCreate(scrHandle, "0", GFUI_FONT_MEDIUM_C,
705 						x2+10, y, 0, 2, NULL, (tfuiCallback)NULL, ChangeNum);
706 	y -= dy;
707 	GfuiLabelCreate(scrHandle, "Transmission:", GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0);
708 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-left.png", "data/img/arrow-left.png",
709 				"data/img/arrow-left.png", "data/img/arrow-left-pushed.png",
710 				x2, y, GFUI_ALIGN_HL_VB, 1,
711 				(void*)0, ChangeTrans,
712 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
713 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-right.png", "data/img/arrow-right.png",
714 				"data/img/arrow-right.png", "data/img/arrow-right-pushed.png",
715 				x4, y, GFUI_ALIGN_HR_VB, 1,
716 				(void*)1, ChangeTrans,
717 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
718 	TransEditId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HC_VB, 32);
719 	GfuiLabelSetColor(scrHandle, TransEditId, LabelColor);
720 
721 	y -= dy;
722 	GfuiLabelCreate(scrHandle, "Pit Stops:", GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0);
723 	PitsEditId = GfuiEditboxCreate(scrHandle, "", GFUI_FONT_MEDIUM_C,
724 					x2+10, y, 0, 2, NULL, (tfuiCallback)NULL, ChangePits);
725 	y -= dy;
726 	GfuiLabelCreate(scrHandle, "Level:", GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0);
727 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-left.png", "data/img/arrow-left.png",
728 				"data/img/arrow-left.png", "data/img/arrow-left-pushed.png",
729 				x2, y, GFUI_ALIGN_HL_VB, 1,
730 				(void*)0, ChangeLevel,
731 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
732 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-right.png", "data/img/arrow-right.png",
733 				"data/img/arrow-right.png", "data/img/arrow-right-pushed.png",
734 				x4, y, GFUI_ALIGN_HR_VB, 1,
735 				(void*)1, ChangeLevel,
736 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
737 	SkillId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HC_VB, 32);
738 	GfuiLabelSetColor(scrHandle, SkillId, LabelColor);
739 
740 	y -= dy;
741 	GfuiLabelCreate(scrHandle, "Auto Reverse:", GFUI_FONT_MEDIUM, x, y, GFUI_ALIGN_HL_VB, 0);
742 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-left.png", "data/img/arrow-left.png",
743 				"data/img/arrow-left.png", "data/img/arrow-left-pushed.png",
744 				x2, y, GFUI_ALIGN_HL_VB, 1,
745 				(void*)-1, ChangeReverse,
746 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
747 	GfuiGrButtonCreate(scrHandle, "data/img/arrow-right.png", "data/img/arrow-right.png",
748 				"data/img/arrow-right.png", "data/img/arrow-right-pushed.png",
749 				x4, y, GFUI_ALIGN_HR_VB, 1,
750 				(void*)1, ChangeReverse,
751 				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
752 	AutoReverseId = GfuiLabelCreate(scrHandle, "", GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HC_VB, 32);
753 	GfuiLabelSetColor(scrHandle, AutoReverseId, LabelColor);
754 
755 	GfuiButtonCreate(scrHandle, "Accept", GFUI_FONT_LARGE, 210, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
756 		NULL, SaveDrvList, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
757 
758 	GfuiButtonCreate(scrHandle, "Cancel", GFUI_FONT_LARGE, 430, 40, 150, GFUI_ALIGN_HC_VB, GFUI_MOUSE_UP,
759 		prevMenu, GfuiScreenActivate, NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
760 
761 	GfuiAddKey(scrHandle, 13, "Save Drivers", NULL, SaveDrvList, NULL);
762 	GfuiAddKey(scrHandle, 27, "Cancel Selection", prevMenu, GfuiScreenActivate, NULL);
763 	GfuiAddSKey(scrHandle, GLUT_KEY_F12, "Screen-Shot", NULL, GfuiScreenShot, NULL);
764 	GfuiAddSKey(scrHandle, GLUT_KEY_LEFT, "Previous Car", (void*)0, ChangeCar, NULL);
765 	GfuiAddSKey(scrHandle, GLUT_KEY_RIGHT, "Next Car", (void*)1, ChangeCar, NULL);
766 	GfuiAddSKey(scrHandle, GLUT_KEY_UP, "Previous Car Category", (void*)0, ChangeCat, NULL);
767 	GfuiAddSKey(scrHandle, GLUT_KEY_DOWN, "Next Car Category", (void*)1, ChangeCat, NULL);
768 
769 	refreshEditVal();
770 	return scrHandle;
771 }
772 
773