~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/ui/ui_shared.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert
  • Date: 2007-01-20 12:28:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070120122809-2yza5ojt7nqiyiam
Tags: upstream-0.6.0
ImportĀ upstreamĀ versionĀ 0.6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
===========================================================================
 
3
Copyright (C) 1999-2005 Id Software, Inc.
 
4
 
 
5
This file is part of Quake III Arena source code.
 
6
 
 
7
Quake III Arena source code is free software; you can redistribute it
 
8
and/or modify it under the terms of the GNU General Public License as
 
9
published by the Free Software Foundation; either version 2 of the License,
 
10
or (at your option) any later version.
 
11
 
 
12
Quake III Arena source code is distributed in the hope that it will be
 
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with Quake III Arena source code; if not, write to the Free Software
 
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
20
===========================================================================
 
21
*/
 
22
// 
 
23
// string allocation/managment
 
24
 
 
25
#include "ui_shared.h"
 
26
 
 
27
#define SCROLL_TIME_START                                       500
 
28
#define SCROLL_TIME_ADJUST                              150
 
29
#define SCROLL_TIME_ADJUSTOFFSET        40
 
30
#define SCROLL_TIME_FLOOR                                       20
 
31
 
 
32
typedef struct scrollInfo_s {
 
33
        int nextScrollTime;
 
34
        int nextAdjustTime;
 
35
        int adjustValue;
 
36
        int scrollKey;
 
37
        float xStart;
 
38
        float yStart;
 
39
        itemDef_t *item;
 
40
        qboolean scrollDir;
 
41
} scrollInfo_t;
 
42
 
 
43
static scrollInfo_t scrollInfo;
 
44
 
 
45
static void (*captureFunc) (void *p) = 0;
 
46
static void *captureData = NULL;
 
47
static itemDef_t *itemCapture = NULL;   // item that has the mouse captured ( if any )
 
48
 
 
49
displayContextDef_t *DC = NULL;
 
50
 
 
51
static qboolean g_waitingForKey = qfalse;
 
52
static qboolean g_editingField = qfalse;
 
53
 
 
54
static itemDef_t *g_bindItem = NULL;
 
55
static itemDef_t *g_editItem = NULL;
 
56
 
 
57
menuDef_t Menus[MAX_MENUS];      // defined menus
 
58
int menuCount = 0;               // how many
 
59
 
 
60
menuDef_t *menuStack[MAX_OPEN_MENUS];
 
61
int openMenuCount = 0;
 
62
 
 
63
static qboolean debugMode = qfalse;
 
64
 
 
65
#define DOUBLE_CLICK_DELAY 300
 
66
static int lastListBoxClickTime = 0;
 
67
 
 
68
void Item_RunScript(itemDef_t *item, const char *s);
 
69
void Item_SetupKeywordHash(void);
 
70
void Menu_SetupKeywordHash(void);
 
71
int BindingIDFromName(const char *name);
 
72
qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down);
 
73
itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu);
 
74
itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu);
 
75
static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y);
 
76
 
 
77
#ifdef CGAME
 
78
#define MEM_POOL_SIZE  128 * 1024
 
79
#else
 
80
#define MEM_POOL_SIZE  1024 * 1024
 
81
#endif
 
82
 
 
83
static char             memoryPool[MEM_POOL_SIZE];
 
84
static int              allocPoint, outOfMemory;
 
85
 
 
86
 
 
87
/*
 
88
===============
 
89
UI_Alloc
 
90
===============
 
91
*/                                
 
92
void *UI_Alloc( int size ) {
 
93
        char    *p; 
 
94
 
 
95
        if ( allocPoint + size > MEM_POOL_SIZE ) {
 
96
                outOfMemory = qtrue;
 
97
                if (DC->Print) {
 
98
                        DC->Print("UI_Alloc: Failure. Out of memory!\n");
 
99
                }
 
100
    //DC->trap_Print(S_COLOR_YELLOW"WARNING: UI Out of Memory!\n");
 
101
                return NULL;
 
102
        }
 
103
 
 
104
        p = &memoryPool[allocPoint];
 
105
 
 
106
        allocPoint += ( size + 15 ) & ~15;
 
107
 
 
108
        return p;
 
109
}
 
110
 
 
111
/*
 
112
===============
 
113
UI_InitMemory
 
114
===============
 
115
*/
 
116
void UI_InitMemory( void ) {
 
117
        allocPoint = 0;
 
118
        outOfMemory = qfalse;
 
119
}
 
120
 
 
121
qboolean UI_OutOfMemory( void ) {
 
122
        return outOfMemory;
 
123
}
 
124
 
 
125
 
 
126
 
 
127
 
 
128
 
 
129
#define HASH_TABLE_SIZE 2048
 
130
/*
 
131
================
 
132
return a hash value for the string
 
133
================
 
134
*/
 
135
static unsigned hashForString(const char *str) {
 
136
        int             i;
 
137
        unsigned        hash;
 
138
        char    letter;
 
139
 
 
140
        hash = 0;
 
141
        i = 0;
 
142
        while (str[i] != '\0') {
 
143
                letter = tolower(str[i]);
 
144
                hash+=(unsigned)(letter)*(i+119);
 
145
                i++;
 
146
        }
 
147
        hash &= (HASH_TABLE_SIZE-1);
 
148
        return hash;
 
149
}
 
150
 
 
151
typedef struct stringDef_s {
 
152
        struct stringDef_s *next;
 
153
        const char *str;
 
154
} stringDef_t;
 
155
 
 
156
static int strPoolIndex = 0;
 
157
static char strPool[STRING_POOL_SIZE];
 
158
 
 
159
static int strHandleCount = 0;
 
160
static stringDef_t *strHandle[HASH_TABLE_SIZE];
 
161
 
 
162
 
 
163
const char *String_Alloc(const char *p) {
 
164
        int len;
 
165
        unsigned hash;
 
166
        stringDef_t *str, *last;
 
167
        static const char *staticNULL = "";
 
168
 
 
169
        if (p == NULL) {
 
170
                return NULL;
 
171
        }
 
172
 
 
173
        if (*p == 0) {
 
174
                return staticNULL;
 
175
        }
 
176
 
 
177
        hash = hashForString(p);
 
178
 
 
179
        str = strHandle[hash];
 
180
        while (str) {
 
181
                if (strcmp(p, str->str) == 0) {
 
182
                        return str->str;
 
183
                }
 
184
                str = str->next;
 
185
        }
 
186
 
 
187
        len = strlen(p);
 
188
        if (len + strPoolIndex + 1 < STRING_POOL_SIZE) {
 
189
                int ph = strPoolIndex;
 
190
                strcpy(&strPool[strPoolIndex], p);
 
191
                strPoolIndex += len + 1;
 
192
 
 
193
                str = strHandle[hash];
 
194
                last = str;
 
195
                while (str && str->next) {
 
196
                        last = str;
 
197
                        str = str->next;
 
198
                }
 
199
 
 
200
                str  = UI_Alloc(sizeof(stringDef_t));
 
201
                str->next = NULL;
 
202
                str->str = &strPool[ph];
 
203
                if (last) {
 
204
                        last->next = str;
 
205
                } else {
 
206
                        strHandle[hash] = str;
 
207
                }
 
208
                return &strPool[ph];
 
209
        }
 
210
        return NULL;
 
211
}
 
212
 
 
213
void String_Report(void) {
 
214
        float f;
 
215
        Com_Printf("Memory/String Pool Info\n");
 
216
        Com_Printf("----------------\n");
 
217
        f = strPoolIndex;
 
218
        f /= STRING_POOL_SIZE;
 
219
        f *= 100;
 
220
        Com_Printf("String Pool is %.1f%% full, %i bytes out of %i used.\n", f, strPoolIndex, STRING_POOL_SIZE);
 
221
        f = allocPoint;
 
222
        f /= MEM_POOL_SIZE;
 
223
        f *= 100;
 
224
        Com_Printf("Memory Pool is %.1f%% full, %i bytes out of %i used.\n", f, allocPoint, MEM_POOL_SIZE);
 
225
}
 
226
 
 
227
/*
 
228
=================
 
229
String_Init
 
230
=================
 
231
*/
 
232
void String_Init(void) {
 
233
        int i;
 
234
        for (i = 0; i < HASH_TABLE_SIZE; i++) {
 
235
                strHandle[i] = NULL;
 
236
        }
 
237
        strHandleCount = 0;
 
238
        strPoolIndex = 0;
 
239
        menuCount = 0;
 
240
        openMenuCount = 0;
 
241
        UI_InitMemory();
 
242
        Item_SetupKeywordHash();
 
243
        Menu_SetupKeywordHash();
 
244
        if (DC && DC->getBindingBuf) {
 
245
                Controls_GetConfig();
 
246
        }
 
247
}
 
248
 
 
249
/*
 
250
=================
 
251
PC_SourceWarning
 
252
=================
 
253
*/
 
254
void PC_SourceWarning(int handle, char *format, ...) {
 
255
        int line;
 
256
        char filename[128];
 
257
        va_list argptr;
 
258
        static char string[4096];
 
259
 
 
260
        va_start (argptr, format);
 
261
        vsprintf (string, format, argptr);
 
262
        va_end (argptr);
 
263
 
 
264
        filename[0] = '\0';
 
265
        line = 0;
 
266
        trap_PC_SourceFileAndLine(handle, filename, &line);
 
267
 
 
268
        Com_Printf(S_COLOR_YELLOW "WARNING: %s, line %d: %s\n", filename, line, string);
 
269
}
 
270
 
 
271
/*
 
272
=================
 
273
PC_SourceError
 
274
=================
 
275
*/
 
276
void PC_SourceError(int handle, char *format, ...) {
 
277
        int line;
 
278
        char filename[128];
 
279
        va_list argptr;
 
280
        static char string[4096];
 
281
 
 
282
        va_start (argptr, format);
 
283
        vsprintf (string, format, argptr);
 
284
        va_end (argptr);
 
285
 
 
286
        filename[0] = '\0';
 
287
        line = 0;
 
288
        trap_PC_SourceFileAndLine(handle, filename, &line);
 
289
 
 
290
        Com_Printf(S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string);
 
291
}
 
292
 
 
293
/*
 
294
=================
 
295
LerpColor
 
296
=================
 
297
*/
 
298
void LerpColor(vec4_t a, vec4_t b, vec4_t c, float t)
 
299
{
 
300
        int i;
 
301
 
 
302
        // lerp and clamp each component
 
303
        for (i=0; i<4; i++)
 
304
        {
 
305
                c[i] = a[i] + t*(b[i]-a[i]);
 
306
                if (c[i] < 0)
 
307
                        c[i] = 0;
 
308
                else if (c[i] > 1.0)
 
309
                        c[i] = 1.0;
 
310
        }
 
311
}
 
312
 
 
313
/*
 
314
=================
 
315
Float_Parse
 
316
=================
 
317
*/
 
318
qboolean Float_Parse(char **p, float *f) {
 
319
        char    *token;
 
320
        token = COM_ParseExt(p, qfalse);
 
321
        if (token && token[0] != 0) {
 
322
                *f = atof(token);
 
323
                return qtrue;
 
324
        } else {
 
325
                return qfalse;
 
326
        }
 
327
}
 
328
 
 
329
/*
 
330
=================
 
331
PC_Float_Parse
 
332
=================
 
333
*/
 
334
qboolean PC_Float_Parse(int handle, float *f) {
 
335
        pc_token_t token;
 
336
        int negative = qfalse;
 
337
 
 
338
        if (!trap_PC_ReadToken(handle, &token))
 
339
                return qfalse;
 
340
        if (token.string[0] == '-') {
 
341
                if (!trap_PC_ReadToken(handle, &token))
 
342
                        return qfalse;
 
343
                negative = qtrue;
 
344
        }
 
345
        if (token.type != TT_NUMBER) {
 
346
                PC_SourceError(handle, "expected float but found %s\n", token.string);
 
347
                return qfalse;
 
348
        }
 
349
        if (negative)
 
350
                *f = -token.floatvalue;
 
351
        else
 
352
                *f = token.floatvalue;
 
353
        return qtrue;
 
354
}
 
355
 
 
356
/*
 
357
=================
 
358
Color_Parse
 
359
=================
 
360
*/
 
361
qboolean Color_Parse(char **p, vec4_t *c) {
 
362
        int i;
 
363
        float f;
 
364
 
 
365
        for (i = 0; i < 4; i++) {
 
366
                if (!Float_Parse(p, &f)) {
 
367
                        return qfalse;
 
368
                }
 
369
                (*c)[i] = f;
 
370
        }
 
371
        return qtrue;
 
372
}
 
373
 
 
374
/*
 
375
=================
 
376
PC_Color_Parse
 
377
=================
 
378
*/
 
379
qboolean PC_Color_Parse(int handle, vec4_t *c) {
 
380
        int i;
 
381
        float f;
 
382
 
 
383
        for (i = 0; i < 4; i++) {
 
384
                if (!PC_Float_Parse(handle, &f)) {
 
385
                        return qfalse;
 
386
                }
 
387
                (*c)[i] = f;
 
388
        }
 
389
        return qtrue;
 
390
}
 
391
 
 
392
/*
 
393
=================
 
394
Int_Parse
 
395
=================
 
396
*/
 
397
qboolean Int_Parse(char **p, int *i) {
 
398
        char    *token;
 
399
        token = COM_ParseExt(p, qfalse);
 
400
 
 
401
        if (token && token[0] != 0) {
 
402
                *i = atoi(token);
 
403
                return qtrue;
 
404
        } else {
 
405
                return qfalse;
 
406
        }
 
407
}
 
408
 
 
409
/*
 
410
=================
 
411
PC_Int_Parse
 
412
=================
 
413
*/
 
414
qboolean PC_Int_Parse(int handle, int *i) {
 
415
        pc_token_t token;
 
416
        int negative = qfalse;
 
417
 
 
418
        if (!trap_PC_ReadToken(handle, &token))
 
419
                return qfalse;
 
420
        if (token.string[0] == '-') {
 
421
                if (!trap_PC_ReadToken(handle, &token))
 
422
                        return qfalse;
 
423
                negative = qtrue;
 
424
        }
 
425
        if (token.type != TT_NUMBER) {
 
426
                PC_SourceError(handle, "expected integer but found %s\n", token.string);
 
427
                return qfalse;
 
428
        }
 
429
        *i = token.intvalue;
 
430
        if (negative)
 
431
                *i = - *i;
 
432
        return qtrue;
 
433
}
 
434
 
 
435
/*
 
436
=================
 
437
Rect_Parse
 
438
=================
 
439
*/
 
440
qboolean Rect_Parse(char **p, rectDef_t *r) {
 
441
        if (Float_Parse(p, &r->x)) {
 
442
                if (Float_Parse(p, &r->y)) {
 
443
                        if (Float_Parse(p, &r->w)) {
 
444
                                if (Float_Parse(p, &r->h)) {
 
445
                                        return qtrue;
 
446
                                }
 
447
                        }
 
448
                }
 
449
        }
 
450
        return qfalse;
 
451
}
 
452
 
 
453
/*
 
454
=================
 
455
PC_Rect_Parse
 
456
=================
 
457
*/
 
458
qboolean PC_Rect_Parse(int handle, rectDef_t *r) {
 
459
        if (PC_Float_Parse(handle, &r->x)) {
 
460
                if (PC_Float_Parse(handle, &r->y)) {
 
461
                        if (PC_Float_Parse(handle, &r->w)) {
 
462
                                if (PC_Float_Parse(handle, &r->h)) {
 
463
                                        return qtrue;
 
464
                                }
 
465
                        }
 
466
                }
 
467
        }
 
468
        return qfalse;
 
469
}
 
470
 
 
471
/*
 
472
=================
 
473
String_Parse
 
474
=================
 
475
*/
 
476
qboolean String_Parse(char **p, const char **out) {
 
477
        char *token;
 
478
 
 
479
        token = COM_ParseExt(p, qfalse);
 
480
        if (token && token[0] != 0) {
 
481
                *(out) = String_Alloc(token);
 
482
                return qtrue;
 
483
        }
 
484
        return qfalse;
 
485
}
 
486
 
 
487
/*
 
488
=================
 
489
PC_String_Parse
 
490
=================
 
491
*/
 
492
qboolean PC_String_Parse(int handle, const char **out) {
 
493
        pc_token_t token;
 
494
 
 
495
        if (!trap_PC_ReadToken(handle, &token))
 
496
                return qfalse;
 
497
        
 
498
        *(out) = String_Alloc(token.string);
 
499
    return qtrue;
 
500
}
 
501
 
 
502
/*
 
503
=================
 
504
PC_Script_Parse
 
505
=================
 
506
*/
 
507
qboolean PC_Script_Parse(int handle, const char **out) {
 
508
        char script[1024];
 
509
        pc_token_t token;
 
510
 
 
511
        memset(script, 0, sizeof(script));
 
512
        // scripts start with { and have ; separated command lists.. commands are command, arg.. 
 
513
        // basically we want everything between the { } as it will be interpreted at run time
 
514
  
 
515
        if (!trap_PC_ReadToken(handle, &token))
 
516
                return qfalse;
 
517
        if (Q_stricmp(token.string, "{") != 0) {
 
518
            return qfalse;
 
519
        }
 
520
 
 
521
        while ( 1 ) {
 
522
                if (!trap_PC_ReadToken(handle, &token))
 
523
                        return qfalse;
 
524
 
 
525
                if (Q_stricmp(token.string, "}") == 0) {
 
526
                        *out = String_Alloc(script);
 
527
                        return qtrue;
 
528
                }
 
529
 
 
530
                if (token.string[1] != '\0') {
 
531
                        Q_strcat(script, 1024, va("\"%s\"", token.string));
 
532
                } else {
 
533
                        Q_strcat(script, 1024, token.string);
 
534
                }
 
535
                Q_strcat(script, 1024, " ");
 
536
        }
 
537
        return qfalse;  // bk001105 - LCC   missing return value
 
538
}
 
539
 
 
540
// display, window, menu, item code
 
541
// 
 
542
 
 
543
/*
 
544
==================
 
545
Init_Display
 
546
 
 
547
Initializes the display with a structure to all the drawing routines
 
548
 ==================
 
549
*/
 
550
void Init_Display(displayContextDef_t *dc) {
 
551
        DC = dc;
 
552
}
 
553
 
 
554
 
 
555
 
 
556
// type and style painting 
 
557
 
 
558
void GradientBar_Paint(rectDef_t *rect, vec4_t color) {
 
559
        // gradient bar takes two paints
 
560
        DC->setColor( color );
 
561
        DC->drawHandlePic(rect->x, rect->y, rect->w, rect->h, DC->Assets.gradientBar);
 
562
        DC->setColor( NULL );
 
563
}
 
564
 
 
565
 
 
566
/*
 
567
==================
 
568
Window_Init
 
569
 
 
570
Initializes a window structure ( windowDef_t ) with defaults
 
571
 
 
572
==================
 
573
*/
 
574
void Window_Init(Window *w) {
 
575
        memset(w, 0, sizeof(windowDef_t));
 
576
        w->borderSize = 1;
 
577
        w->foreColor[0] = w->foreColor[1] = w->foreColor[2] = w->foreColor[3] = 1.0;
 
578
        w->cinematic = -1;
 
579
}
 
580
 
 
581
void Fade(int *flags, float *f, float clamp, int *nextTime, int offsetTime, qboolean bFlags, float fadeAmount) {
 
582
  if (*flags & (WINDOW_FADINGOUT | WINDOW_FADINGIN)) {
 
583
    if (DC->realTime > *nextTime) {
 
584
      *nextTime = DC->realTime + offsetTime;
 
585
      if (*flags & WINDOW_FADINGOUT) {
 
586
        *f -= fadeAmount;
 
587
        if (bFlags && *f <= 0.0) {
 
588
          *flags &= ~(WINDOW_FADINGOUT | WINDOW_VISIBLE);
 
589
        }
 
590
      } else {
 
591
        *f += fadeAmount;
 
592
        if (*f >= clamp) {
 
593
          *f = clamp;
 
594
          if (bFlags) {
 
595
            *flags &= ~WINDOW_FADINGIN;
 
596
          }
 
597
        }
 
598
      }
 
599
    }
 
600
  }
 
601
}
 
602
 
 
603
 
 
604
 
 
605
void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle) {
 
606
  //float bordersize = 0;
 
607
  vec4_t color;
 
608
  rectDef_t fillRect = w->rect;
 
609
 
 
610
 
 
611
  if (debugMode) {
 
612
    color[0] = color[1] = color[2] = color[3] = 1;
 
613
    DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, 1, color);
 
614
  }
 
615
 
 
616
  if (w == NULL || (w->style == 0 && w->border == 0)) {
 
617
    return;
 
618
  }
 
619
 
 
620
  if (w->border != 0) {
 
621
    fillRect.x += w->borderSize;
 
622
    fillRect.y += w->borderSize;
 
623
    fillRect.w -= w->borderSize + 1;
 
624
    fillRect.h -= w->borderSize + 1;
 
625
  }
 
626
 
 
627
  if (w->style == WINDOW_STYLE_FILLED) {
 
628
    // box, but possible a shader that needs filled
 
629
                if (w->background) {
 
630
                  Fade(&w->flags, &w->backColor[3], fadeClamp, &w->nextTime, fadeCycle, qtrue, fadeAmount);
 
631
      DC->setColor(w->backColor);
 
632
            DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
 
633
                  DC->setColor(NULL);
 
634
                } else {
 
635
            DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->backColor);
 
636
                }
 
637
  } else if (w->style == WINDOW_STYLE_GRADIENT) {
 
638
    GradientBar_Paint(&fillRect, w->backColor);
 
639
    // gradient bar
 
640
  } else if (w->style == WINDOW_STYLE_SHADER) {
 
641
    if (w->flags & WINDOW_FORECOLORSET) {
 
642
      DC->setColor(w->foreColor);
 
643
    }
 
644
    DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
 
645
    DC->setColor(NULL);
 
646
  } else if (w->style == WINDOW_STYLE_TEAMCOLOR) {
 
647
    if (DC->getTeamColor) {
 
648
      DC->getTeamColor(&color);
 
649
      DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, color);
 
650
    }
 
651
  } else if (w->style == WINDOW_STYLE_CINEMATIC) {
 
652
                if (w->cinematic == -1) {
 
653
                        w->cinematic = DC->playCinematic(w->cinematicName, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
 
654
                        if (w->cinematic == -1) {
 
655
                                w->cinematic = -2;
 
656
                        }
 
657
                } 
 
658
                if (w->cinematic >= 0) {
 
659
            DC->runCinematicFrame(w->cinematic);
 
660
                        DC->drawCinematic(w->cinematic, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
 
661
                }
 
662
  }
 
663
 
 
664
  if (w->border == WINDOW_BORDER_FULL) {
 
665
    // full
 
666
    // HACK HACK HACK
 
667
    if (w->style == WINDOW_STYLE_TEAMCOLOR) {
 
668
      if (color[0] > 0) { 
 
669
        // red
 
670
        color[0] = 1;
 
671
        color[1] = color[2] = .5;
 
672
 
 
673
      } else {
 
674
        color[2] = 1;
 
675
        color[0] = color[1] = .5;
 
676
      }
 
677
      color[3] = 1;
 
678
      DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, color);
 
679
    } else {
 
680
      DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, w->borderColor);
 
681
    }
 
682
  } else if (w->border == WINDOW_BORDER_HORZ) {
 
683
    // top/bottom
 
684
    DC->setColor(w->borderColor);
 
685
    DC->drawTopBottom(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
 
686
        DC->setColor( NULL );
 
687
  } else if (w->border == WINDOW_BORDER_VERT) {
 
688
    // left right
 
689
    DC->setColor(w->borderColor);
 
690
    DC->drawSides(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
 
691
        DC->setColor( NULL );
 
692
  } else if (w->border == WINDOW_BORDER_KCGRADIENT) {
 
693
    // this is just two gradient bars along each horz edge
 
694
    rectDef_t r = w->rect;
 
695
    r.h = w->borderSize;
 
696
    GradientBar_Paint(&r, w->borderColor);
 
697
    r.y = w->rect.y + w->rect.h - 1;
 
698
    GradientBar_Paint(&r, w->borderColor);
 
699
  }
 
700
 
 
701
}
 
702
 
 
703
 
 
704
void Item_SetScreenCoords(itemDef_t *item, float x, float y) {
 
705
  
 
706
  if (item == NULL) {
 
707
    return;
 
708
  }
 
709
 
 
710
  if (item->window.border != 0) {
 
711
    x += item->window.borderSize;
 
712
    y += item->window.borderSize;
 
713
  }
 
714
 
 
715
  item->window.rect.x = x + item->window.rectClient.x;
 
716
  item->window.rect.y = y + item->window.rectClient.y;
 
717
  item->window.rect.w = item->window.rectClient.w;
 
718
  item->window.rect.h = item->window.rectClient.h;
 
719
 
 
720
  // force the text rects to recompute
 
721
  item->textRect.w = 0;
 
722
  item->textRect.h = 0;
 
723
}
 
724
 
 
725
// FIXME: consolidate this with nearby stuff
 
726
void Item_UpdatePosition(itemDef_t *item) {
 
727
  float x, y;
 
728
  menuDef_t *menu;
 
729
  
 
730
  if (item == NULL || item->parent == NULL) {
 
731
    return;
 
732
  }
 
733
 
 
734
  menu = item->parent;
 
735
 
 
736
  x = menu->window.rect.x;
 
737
  y = menu->window.rect.y;
 
738
  
 
739
  if (menu->window.border != 0) {
 
740
    x += menu->window.borderSize;
 
741
    y += menu->window.borderSize;
 
742
  }
 
743
 
 
744
  Item_SetScreenCoords(item, x, y);
 
745
 
 
746
}
 
747
 
 
748
// menus
 
749
void Menu_UpdatePosition(menuDef_t *menu) {
 
750
  int i;
 
751
  float x, y;
 
752
 
 
753
  if (menu == NULL) {
 
754
    return;
 
755
  }
 
756
  
 
757
  x = menu->window.rect.x;
 
758
  y = menu->window.rect.y;
 
759
  if (menu->window.border != 0) {
 
760
    x += menu->window.borderSize;
 
761
    y += menu->window.borderSize;
 
762
  }
 
763
 
 
764
  for (i = 0; i < menu->itemCount; i++) {
 
765
    Item_SetScreenCoords(menu->items[i], x, y);
 
766
  }
 
767
}
 
768
 
 
769
void Menu_PostParse(menuDef_t *menu) {
 
770
        if (menu == NULL) {
 
771
                return;
 
772
        }
 
773
        if (menu->fullScreen) {
 
774
                menu->window.rect.x = 0;
 
775
                menu->window.rect.y = 0;
 
776
                menu->window.rect.w = 640;
 
777
                menu->window.rect.h = 480;
 
778
        }
 
779
        Menu_UpdatePosition(menu);
 
780
}
 
781
 
 
782
itemDef_t *Menu_ClearFocus(menuDef_t *menu) {
 
783
  int i;
 
784
  itemDef_t *ret = NULL;
 
785
 
 
786
  if (menu == NULL) {
 
787
    return NULL;
 
788
  }
 
789
 
 
790
  for (i = 0; i < menu->itemCount; i++) {
 
791
    if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
 
792
      ret = menu->items[i];
 
793
    } 
 
794
    menu->items[i]->window.flags &= ~WINDOW_HASFOCUS;
 
795
    if (menu->items[i]->leaveFocus) {
 
796
      Item_RunScript(menu->items[i], menu->items[i]->leaveFocus);
 
797
    }
 
798
  }
 
799
 
 
800
  return ret;
 
801
}
 
802
 
 
803
qboolean IsVisible(int flags) {
 
804
  return (flags & WINDOW_VISIBLE && !(flags & WINDOW_FADINGOUT));
 
805
}
 
806
 
 
807
qboolean Rect_ContainsPoint(rectDef_t *rect, float x, float y) {
 
808
  if (rect) {
 
809
    if (x > rect->x && x < rect->x + rect->w && y > rect->y && y < rect->y + rect->h) {
 
810
      return qtrue;
 
811
    }
 
812
  }
 
813
  return qfalse;
 
814
}
 
815
 
 
816
int Menu_ItemsMatchingGroup(menuDef_t *menu, const char *name) {
 
817
  int i;
 
818
  int count = 0;
 
819
  for (i = 0; i < menu->itemCount; i++) {
 
820
    if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0)) {
 
821
      count++;
 
822
    } 
 
823
  }
 
824
  return count;
 
825
}
 
826
 
 
827
itemDef_t *Menu_GetMatchingItemByNumber(menuDef_t *menu, int index, const char *name) {
 
828
  int i;
 
829
  int count = 0;
 
830
  for (i = 0; i < menu->itemCount; i++) {
 
831
    if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0)) {
 
832
      if (count == index) {
 
833
        return menu->items[i];
 
834
      }
 
835
      count++;
 
836
    } 
 
837
  }
 
838
  return NULL;
 
839
}
 
840
 
 
841
 
 
842
 
 
843
void Script_SetColor(itemDef_t *item, char **args) {
 
844
  const char *name;
 
845
  int i;
 
846
  float f;
 
847
  vec4_t *out;
 
848
  // expecting type of color to set and 4 args for the color
 
849
  if (String_Parse(args, &name)) {
 
850
      out = NULL;
 
851
      if (Q_stricmp(name, "backcolor") == 0) {
 
852
        out = &item->window.backColor;
 
853
        item->window.flags |= WINDOW_BACKCOLORSET;
 
854
      } else if (Q_stricmp(name, "forecolor") == 0) {
 
855
        out = &item->window.foreColor;
 
856
        item->window.flags |= WINDOW_FORECOLORSET;
 
857
      } else if (Q_stricmp(name, "bordercolor") == 0) {
 
858
        out = &item->window.borderColor;
 
859
      }
 
860
 
 
861
      if (out) {
 
862
        for (i = 0; i < 4; i++) {
 
863
          if (!Float_Parse(args, &f)) {
 
864
            return;
 
865
          }
 
866
          (*out)[i] = f;
 
867
        }
 
868
      }
 
869
  }
 
870
}
 
871
 
 
872
void Script_SetAsset(itemDef_t *item, char **args) {
 
873
  const char *name;
 
874
  // expecting name to set asset to
 
875
  if (String_Parse(args, &name)) {
 
876
    // check for a model 
 
877
    if (item->type == ITEM_TYPE_MODEL) {
 
878
    }
 
879
  }
 
880
}
 
881
 
 
882
void Script_SetBackground(itemDef_t *item, char **args) {
 
883
  const char *name;
 
884
  // expecting name to set asset to
 
885
  if (String_Parse(args, &name)) {
 
886
    item->window.background = DC->registerShaderNoMip(name);
 
887
  }
 
888
}
 
889
 
 
890
 
 
891
 
 
892
 
 
893
itemDef_t *Menu_FindItemByName(menuDef_t *menu, const char *p) {
 
894
  int i;
 
895
  if (menu == NULL || p == NULL) {
 
896
    return NULL;
 
897
  }
 
898
 
 
899
  for (i = 0; i < menu->itemCount; i++) {
 
900
    if (Q_stricmp(p, menu->items[i]->window.name) == 0) {
 
901
      return menu->items[i];
 
902
    }
 
903
  }
 
904
 
 
905
  return NULL;
 
906
}
 
907
 
 
908
void Script_SetTeamColor(itemDef_t *item, char **args) {
 
909
  if (DC->getTeamColor) {
 
910
    int i;
 
911
    vec4_t color;
 
912
    DC->getTeamColor(&color);
 
913
    for (i = 0; i < 4; i++) {
 
914
      item->window.backColor[i] = color[i];
 
915
    }
 
916
  }
 
917
}
 
918
 
 
919
void Script_SetItemColor(itemDef_t *item, char **args) {
 
920
  const char *itemname;
 
921
  const char *name;
 
922
  vec4_t color;
 
923
  int i;
 
924
  vec4_t *out;
 
925
  // expecting type of color to set and 4 args for the color
 
926
  if (String_Parse(args, &itemname) && String_Parse(args, &name)) {
 
927
    itemDef_t *item2;
 
928
    int j;
 
929
    int count = Menu_ItemsMatchingGroup(item->parent, itemname);
 
930
 
 
931
    if (!Color_Parse(args, &color)) {
 
932
      return;
 
933
    }
 
934
 
 
935
    for (j = 0; j < count; j++) {
 
936
      item2 = Menu_GetMatchingItemByNumber(item->parent, j, itemname);
 
937
      if (item2 != NULL) {
 
938
        out = NULL;
 
939
        if (Q_stricmp(name, "backcolor") == 0) {
 
940
          out = &item2->window.backColor;
 
941
        } else if (Q_stricmp(name, "forecolor") == 0) {
 
942
          out = &item2->window.foreColor;
 
943
          item2->window.flags |= WINDOW_FORECOLORSET;
 
944
        } else if (Q_stricmp(name, "bordercolor") == 0) {
 
945
          out = &item2->window.borderColor;
 
946
        }
 
947
 
 
948
        if (out) {
 
949
          for (i = 0; i < 4; i++) {
 
950
            (*out)[i] = color[i];
 
951
          }
 
952
        }
 
953
      }
 
954
    }
 
955
  }
 
956
}
 
957
 
 
958
 
 
959
void Menu_ShowItemByName(menuDef_t *menu, const char *p, qboolean bShow) {
 
960
        itemDef_t *item;
 
961
        int i;
 
962
        int count = Menu_ItemsMatchingGroup(menu, p);
 
963
        for (i = 0; i < count; i++) {
 
964
                item = Menu_GetMatchingItemByNumber(menu, i, p);
 
965
                if (item != NULL) {
 
966
                        if (bShow) {
 
967
                                item->window.flags |= WINDOW_VISIBLE;
 
968
                        } else {
 
969
                                item->window.flags &= ~WINDOW_VISIBLE;
 
970
                                // stop cinematics playing in the window
 
971
                                if (item->window.cinematic >= 0) {
 
972
                                        DC->stopCinematic(item->window.cinematic);
 
973
                                        item->window.cinematic = -1;
 
974
                                }
 
975
                        }
 
976
                }
 
977
        }
 
978
}
 
979
 
 
980
void Menu_FadeItemByName(menuDef_t *menu, const char *p, qboolean fadeOut) {
 
981
  itemDef_t *item;
 
982
  int i;
 
983
  int count = Menu_ItemsMatchingGroup(menu, p);
 
984
  for (i = 0; i < count; i++) {
 
985
    item = Menu_GetMatchingItemByNumber(menu, i, p);
 
986
    if (item != NULL) {
 
987
      if (fadeOut) {
 
988
        item->window.flags |= (WINDOW_FADINGOUT | WINDOW_VISIBLE);
 
989
        item->window.flags &= ~WINDOW_FADINGIN;
 
990
      } else {
 
991
        item->window.flags |= (WINDOW_VISIBLE | WINDOW_FADINGIN);
 
992
        item->window.flags &= ~WINDOW_FADINGOUT;
 
993
      }
 
994
    }
 
995
  }
 
996
}
 
997
 
 
998
menuDef_t *Menus_FindByName(const char *p) {
 
999
  int i;
 
1000
  for (i = 0; i < menuCount; i++) {
 
1001
    if (Q_stricmp(Menus[i].window.name, p) == 0) {
 
1002
      return &Menus[i];
 
1003
    } 
 
1004
  }
 
1005
  return NULL;
 
1006
}
 
1007
 
 
1008
void Menus_ShowByName(const char *p) {
 
1009
        menuDef_t *menu = Menus_FindByName(p);
 
1010
        if (menu) {
 
1011
                Menus_Activate(menu);
 
1012
        }
 
1013
}
 
1014
 
 
1015
void Menus_OpenByName(const char *p) {
 
1016
  Menus_ActivateByName(p);
 
1017
}
 
1018
 
 
1019
static void Menu_RunCloseScript(menuDef_t *menu) {
 
1020
        if (menu && menu->window.flags & WINDOW_VISIBLE && menu->onClose) {
 
1021
                itemDef_t item;
 
1022
    item.parent = menu;
 
1023
    Item_RunScript(&item, menu->onClose);
 
1024
        }
 
1025
}
 
1026
 
 
1027
void Menus_CloseByName(const char *p) {
 
1028
  menuDef_t *menu = Menus_FindByName(p);
 
1029
  if (menu != NULL) {
 
1030
                Menu_RunCloseScript(menu);
 
1031
                menu->window.flags &= ~(WINDOW_VISIBLE | WINDOW_HASFOCUS);
 
1032
  }
 
1033
}
 
1034
 
 
1035
void Menus_CloseAll(void) {
 
1036
  int i;
 
1037
  for (i = 0; i < menuCount; i++) {
 
1038
                Menu_RunCloseScript(&Menus[i]);
 
1039
                Menus[i].window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
 
1040
  }
 
1041
}
 
1042
 
 
1043
 
 
1044
void Script_Show(itemDef_t *item, char **args) {
 
1045
  const char *name;
 
1046
  if (String_Parse(args, &name)) {
 
1047
    Menu_ShowItemByName(item->parent, name, qtrue);
 
1048
  }
 
1049
}
 
1050
 
 
1051
void Script_Hide(itemDef_t *item, char **args) {
 
1052
  const char *name;
 
1053
  if (String_Parse(args, &name)) {
 
1054
    Menu_ShowItemByName(item->parent, name, qfalse);
 
1055
  }
 
1056
}
 
1057
 
 
1058
void Script_FadeIn(itemDef_t *item, char **args) {
 
1059
  const char *name;
 
1060
  if (String_Parse(args, &name)) {
 
1061
    Menu_FadeItemByName(item->parent, name, qfalse);
 
1062
  }
 
1063
}
 
1064
 
 
1065
void Script_FadeOut(itemDef_t *item, char **args) {
 
1066
  const char *name;
 
1067
  if (String_Parse(args, &name)) {
 
1068
    Menu_FadeItemByName(item->parent, name, qtrue);
 
1069
  }
 
1070
}
 
1071
 
 
1072
 
 
1073
 
 
1074
void Script_Open(itemDef_t *item, char **args) {
 
1075
  const char *name;
 
1076
  if (String_Parse(args, &name)) {
 
1077
    Menus_OpenByName(name);
 
1078
  }
 
1079
}
 
1080
 
 
1081
void Script_ConditionalOpen(itemDef_t *item, char **args) {
 
1082
        const char *cvar;
 
1083
        const char *name1;
 
1084
        const char *name2;
 
1085
        float           val;
 
1086
 
 
1087
        if ( String_Parse(args, &cvar) && String_Parse(args, &name1) && String_Parse(args, &name2) ) {
 
1088
                val = DC->getCVarValue( cvar );
 
1089
                if ( val == 0.f ) {
 
1090
                        Menus_OpenByName(name2);
 
1091
                } else {
 
1092
                        Menus_OpenByName(name1);
 
1093
                }
 
1094
        }
 
1095
}
 
1096
 
 
1097
void Script_Close(itemDef_t *item, char **args) {
 
1098
  const char *name;
 
1099
  if (String_Parse(args, &name)) {
 
1100
    Menus_CloseByName(name);
 
1101
  }
 
1102
}
 
1103
 
 
1104
void Menu_TransitionItemByName(menuDef_t *menu, const char *p, rectDef_t rectFrom, rectDef_t rectTo, int time, float amt) {
 
1105
  itemDef_t *item;
 
1106
  int i;
 
1107
  int count = Menu_ItemsMatchingGroup(menu, p);
 
1108
  for (i = 0; i < count; i++) {
 
1109
    item = Menu_GetMatchingItemByNumber(menu, i, p);
 
1110
    if (item != NULL) {
 
1111
      item->window.flags |= (WINDOW_INTRANSITION | WINDOW_VISIBLE);
 
1112
      item->window.offsetTime = time;
 
1113
                        memcpy(&item->window.rectClient, &rectFrom, sizeof(rectDef_t));
 
1114
                        memcpy(&item->window.rectEffects, &rectTo, sizeof(rectDef_t));
 
1115
                        item->window.rectEffects2.x = abs(rectTo.x - rectFrom.x) / amt;
 
1116
                        item->window.rectEffects2.y = abs(rectTo.y - rectFrom.y) / amt;
 
1117
                        item->window.rectEffects2.w = abs(rectTo.w - rectFrom.w) / amt;
 
1118
                        item->window.rectEffects2.h = abs(rectTo.h - rectFrom.h) / amt;
 
1119
      Item_UpdatePosition(item);
 
1120
    }
 
1121
  }
 
1122
}
 
1123
 
 
1124
 
 
1125
void Script_Transition(itemDef_t *item, char **args) {
 
1126
  const char *name;
 
1127
        rectDef_t rectFrom, rectTo;
 
1128
  int time;
 
1129
        float amt;
 
1130
 
 
1131
  if (String_Parse(args, &name)) {
 
1132
    if ( Rect_Parse(args, &rectFrom) && Rect_Parse(args, &rectTo) && Int_Parse(args, &time) && Float_Parse(args, &amt)) {
 
1133
      Menu_TransitionItemByName(item->parent, name, rectFrom, rectTo, time, amt);
 
1134
    }
 
1135
  }
 
1136
}
 
1137
 
 
1138
 
 
1139
void Menu_OrbitItemByName(menuDef_t *menu, const char *p, float x, float y, float cx, float cy, int time) {
 
1140
  itemDef_t *item;
 
1141
  int i;
 
1142
  int count = Menu_ItemsMatchingGroup(menu, p);
 
1143
  for (i = 0; i < count; i++) {
 
1144
    item = Menu_GetMatchingItemByNumber(menu, i, p);
 
1145
    if (item != NULL) {
 
1146
      item->window.flags |= (WINDOW_ORBITING | WINDOW_VISIBLE);
 
1147
      item->window.offsetTime = time;
 
1148
      item->window.rectEffects.x = cx;
 
1149
      item->window.rectEffects.y = cy;
 
1150
      item->window.rectClient.x = x;
 
1151
      item->window.rectClient.y = y;
 
1152
      Item_UpdatePosition(item);
 
1153
    }
 
1154
  }
 
1155
}
 
1156
 
 
1157
 
 
1158
void Script_Orbit(itemDef_t *item, char **args) {
 
1159
  const char *name;
 
1160
  float cx, cy, x, y;
 
1161
  int time;
 
1162
 
 
1163
  if (String_Parse(args, &name)) {
 
1164
    if ( Float_Parse(args, &x) && Float_Parse(args, &y) && Float_Parse(args, &cx) && Float_Parse(args, &cy) && Int_Parse(args, &time) ) {
 
1165
      Menu_OrbitItemByName(item->parent, name, x, y, cx, cy, time);
 
1166
    }
 
1167
  }
 
1168
}
 
1169
 
 
1170
 
 
1171
 
 
1172
void Script_SetFocus(itemDef_t *item, char **args) {
 
1173
  const char *name;
 
1174
  itemDef_t *focusItem;
 
1175
 
 
1176
  if (String_Parse(args, &name)) {
 
1177
    focusItem = Menu_FindItemByName(item->parent, name);
 
1178
    if (focusItem && !(focusItem->window.flags & WINDOW_DECORATION) && !(focusItem->window.flags & WINDOW_HASFOCUS)) {
 
1179
      Menu_ClearFocus(item->parent);
 
1180
      focusItem->window.flags |= WINDOW_HASFOCUS;
 
1181
      if (focusItem->onFocus) {
 
1182
        Item_RunScript(focusItem, focusItem->onFocus);
 
1183
      }
 
1184
      if (DC->Assets.itemFocusSound) {
 
1185
        DC->startLocalSound( DC->Assets.itemFocusSound, CHAN_LOCAL_SOUND );
 
1186
      }
 
1187
    }
 
1188
  }
 
1189
}
 
1190
 
 
1191
void Script_SetPlayerModel(itemDef_t *item, char **args) {
 
1192
  const char *name;
 
1193
  if (String_Parse(args, &name)) {
 
1194
    DC->setCVar("team_model", name);
 
1195
  }
 
1196
}
 
1197
 
 
1198
void Script_SetPlayerHead(itemDef_t *item, char **args) {
 
1199
  const char *name;
 
1200
  if (String_Parse(args, &name)) {
 
1201
    DC->setCVar("team_headmodel", name);
 
1202
  }
 
1203
}
 
1204
 
 
1205
void Script_SetCvar(itemDef_t *item, char **args) {
 
1206
        const char *cvar, *val;
 
1207
        if (String_Parse(args, &cvar) && String_Parse(args, &val)) {
 
1208
                DC->setCVar(cvar, val);
 
1209
        }
 
1210
        
 
1211
}
 
1212
 
 
1213
void Script_Exec(itemDef_t *item, char **args) {
 
1214
        const char *val;
 
1215
        if (String_Parse(args, &val)) {
 
1216
                DC->executeText(EXEC_APPEND, va("%s ; ", val));
 
1217
        }
 
1218
}
 
1219
 
 
1220
void Script_Play(itemDef_t *item, char **args) {
 
1221
        const char *val;
 
1222
        if (String_Parse(args, &val)) {
 
1223
                DC->startLocalSound(DC->registerSound(val, qfalse), CHAN_LOCAL_SOUND);
 
1224
        }
 
1225
}
 
1226
 
 
1227
void Script_playLooped(itemDef_t *item, char **args) {
 
1228
        const char *val;
 
1229
        if (String_Parse(args, &val)) {
 
1230
                DC->stopBackgroundTrack();
 
1231
                DC->startBackgroundTrack(val, val);
 
1232
        }
 
1233
}
 
1234
 
 
1235
 
 
1236
commandDef_t commandList[] =
 
1237
{
 
1238
  {"fadein", &Script_FadeIn},                   // group/name
 
1239
  {"fadeout", &Script_FadeOut},                 // group/name
 
1240
  {"show", &Script_Show},                       // group/name
 
1241
  {"hide", &Script_Hide},                       // group/name
 
1242
  {"setcolor", &Script_SetColor},               // works on this
 
1243
  {"open", &Script_Open},                       // menu
 
1244
        {"conditionalopen", &Script_ConditionalOpen},   // menu
 
1245
  {"close", &Script_Close},                     // menu
 
1246
  {"setasset", &Script_SetAsset},               // works on this
 
1247
  {"setbackground", &Script_SetBackground},     // works on this
 
1248
  {"setitemcolor", &Script_SetItemColor},       // group/name
 
1249
  {"setteamcolor", &Script_SetTeamColor},       // sets this background color to team color
 
1250
  {"setfocus", &Script_SetFocus},               // sets this background color to team color
 
1251
  {"setplayermodel", &Script_SetPlayerModel},   // sets this background color to team color
 
1252
  {"setplayerhead", &Script_SetPlayerHead},     // sets this background color to team color
 
1253
  {"transition", &Script_Transition},           // group/name
 
1254
  {"setcvar", &Script_SetCvar},           // group/name
 
1255
  {"exec", &Script_Exec},           // group/name
 
1256
  {"play", &Script_Play},           // group/name
 
1257
  {"playlooped", &Script_playLooped},           // group/name
 
1258
  {"orbit", &Script_Orbit}                      // group/name
 
1259
};
 
1260
 
 
1261
int scriptCommandCount = sizeof(commandList) / sizeof(commandDef_t);
 
1262
 
 
1263
 
 
1264
void Item_RunScript(itemDef_t *item, const char *s) {
 
1265
  char script[1024], *p;
 
1266
  int i;
 
1267
  qboolean bRan;
 
1268
  memset(script, 0, sizeof(script));
 
1269
  if (item && s && s[0]) {
 
1270
    Q_strcat(script, 1024, s);
 
1271
    p = script;
 
1272
    while (1) {
 
1273
      const char *command;
 
1274
      // expect command then arguments, ; ends command, NULL ends script
 
1275
      if (!String_Parse(&p, &command)) {
 
1276
        return;
 
1277
      }
 
1278
 
 
1279
      if (command[0] == ';' && command[1] == '\0') {
 
1280
        continue;
 
1281
      }
 
1282
 
 
1283
      bRan = qfalse;
 
1284
      for (i = 0; i < scriptCommandCount; i++) {
 
1285
        if (Q_stricmp(command, commandList[i].name) == 0) {
 
1286
          (commandList[i].handler(item, &p));
 
1287
          bRan = qtrue;
 
1288
          break;
 
1289
        }
 
1290
      }
 
1291
      // not in our auto list, pass to handler
 
1292
      if (!bRan) {
 
1293
        DC->runScript(&p);
 
1294
      }
 
1295
    }
 
1296
  }
 
1297
}
 
1298
 
 
1299
 
 
1300
qboolean Item_EnableShowViaCvar(itemDef_t *item, int flag) {
 
1301
  char script[1024], *p;
 
1302
  memset(script, 0, sizeof(script));
 
1303
  if (item && item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
 
1304
                char buff[1024];
 
1305
          DC->getCVarString(item->cvarTest, buff, sizeof(buff));
 
1306
 
 
1307
    Q_strcat(script, 1024, item->enableCvar);
 
1308
    p = script;
 
1309
    while (1) {
 
1310
      const char *val;
 
1311
      // expect value then ; or NULL, NULL ends list
 
1312
      if (!String_Parse(&p, &val)) {
 
1313
                                return (item->cvarFlags & flag) ? qfalse : qtrue;
 
1314
      }
 
1315
 
 
1316
      if (val[0] == ';' && val[1] == '\0') {
 
1317
        continue;
 
1318
      }
 
1319
 
 
1320
                        // enable it if any of the values are true
 
1321
                        if (item->cvarFlags & flag) {
 
1322
        if (Q_stricmp(buff, val) == 0) {
 
1323
                                        return qtrue;
 
1324
                                }
 
1325
                        } else {
 
1326
                                // disable it if any of the values are true
 
1327
        if (Q_stricmp(buff, val) == 0) {
 
1328
                                        return qfalse;
 
1329
                                }
 
1330
                        }
 
1331
 
 
1332
    }
 
1333
                return (item->cvarFlags & flag) ? qfalse : qtrue;
 
1334
  }
 
1335
        return qtrue;
 
1336
}
 
1337
 
 
1338
 
 
1339
// will optionaly set focus to this item 
 
1340
qboolean Item_SetFocus(itemDef_t *item, float x, float y) {
 
1341
        int i;
 
1342
        itemDef_t *oldFocus;
 
1343
        sfxHandle_t *sfx = &DC->Assets.itemFocusSound;
 
1344
        qboolean playSound = qfalse;
 
1345
        menuDef_t *parent; // bk001206: = (menuDef_t*)item->parent;
 
1346
        // sanity check, non-null, not a decoration and does not already have the focus
 
1347
        if (item == NULL || item->window.flags & WINDOW_DECORATION || item->window.flags & WINDOW_HASFOCUS || !(item->window.flags & WINDOW_VISIBLE)) {
 
1348
                return qfalse;
 
1349
        }
 
1350
 
 
1351
        // bk001206 - this can be NULL.
 
1352
        parent = (menuDef_t*)item->parent; 
 
1353
      
 
1354
        // items can be enabled and disabled based on cvars
 
1355
        if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
 
1356
                return qfalse;
 
1357
        }
 
1358
 
 
1359
        if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
 
1360
                return qfalse;
 
1361
        }
 
1362
 
 
1363
        oldFocus = Menu_ClearFocus(item->parent);
 
1364
 
 
1365
        if (item->type == ITEM_TYPE_TEXT) {
 
1366
                rectDef_t r;
 
1367
                r = item->textRect;
 
1368
                r.y -= r.h;
 
1369
                if (Rect_ContainsPoint(&r, x, y)) {
 
1370
                        item->window.flags |= WINDOW_HASFOCUS;
 
1371
                        if (item->focusSound) {
 
1372
                                sfx = &item->focusSound;
 
1373
                        }
 
1374
                        playSound = qtrue;
 
1375
                } else {
 
1376
                        if (oldFocus) {
 
1377
                                oldFocus->window.flags |= WINDOW_HASFOCUS;
 
1378
                                if (oldFocus->onFocus) {
 
1379
                                        Item_RunScript(oldFocus, oldFocus->onFocus);
 
1380
                                }
 
1381
                        }
 
1382
                }
 
1383
        } else {
 
1384
            item->window.flags |= WINDOW_HASFOCUS;
 
1385
                if (item->onFocus) {
 
1386
                        Item_RunScript(item, item->onFocus);
 
1387
                }
 
1388
                if (item->focusSound) {
 
1389
                        sfx = &item->focusSound;
 
1390
                }
 
1391
                playSound = qtrue;
 
1392
        }
 
1393
 
 
1394
        if (playSound && sfx) {
 
1395
                DC->startLocalSound( *sfx, CHAN_LOCAL_SOUND );
 
1396
        }
 
1397
 
 
1398
        for (i = 0; i < parent->itemCount; i++) {
 
1399
                if (parent->items[i] == item) {
 
1400
                        parent->cursorItem = i;
 
1401
                        break;
 
1402
                }
 
1403
        }
 
1404
 
 
1405
        return qtrue;
 
1406
}
 
1407
 
 
1408
int Item_ListBox_MaxScroll(itemDef_t *item) {
 
1409
        listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
 
1410
        int count = DC->feederCount(item->special);
 
1411
        int max;
 
1412
 
 
1413
        if (item->window.flags & WINDOW_HORIZONTAL) {
 
1414
                max = count - (item->window.rect.w / listPtr->elementWidth) + 1;
 
1415
        }
 
1416
        else {
 
1417
                max = count - (item->window.rect.h / listPtr->elementHeight) + 1;
 
1418
        }
 
1419
        if (max < 0) {
 
1420
                return 0;
 
1421
        }
 
1422
        return max;
 
1423
}
 
1424
 
 
1425
int Item_ListBox_ThumbPosition(itemDef_t *item) {
 
1426
        float max, pos, size;
 
1427
        listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
 
1428
 
 
1429
        max = Item_ListBox_MaxScroll(item);
 
1430
        if (item->window.flags & WINDOW_HORIZONTAL) {
 
1431
                size = item->window.rect.w - (SCROLLBAR_SIZE * 2) - 2;
 
1432
                if (max > 0) {
 
1433
                        pos = (size-SCROLLBAR_SIZE) / (float) max;
 
1434
                } else {
 
1435
                        pos = 0;
 
1436
                }
 
1437
                pos *= listPtr->startPos;
 
1438
                return item->window.rect.x + 1 + SCROLLBAR_SIZE + pos;
 
1439
        }
 
1440
        else {
 
1441
                size = item->window.rect.h - (SCROLLBAR_SIZE * 2) - 2;
 
1442
                if (max > 0) {
 
1443
                        pos = (size-SCROLLBAR_SIZE) / (float) max;
 
1444
                } else {
 
1445
                        pos = 0;
 
1446
                }
 
1447
                pos *= listPtr->startPos;
 
1448
                return item->window.rect.y + 1 + SCROLLBAR_SIZE + pos;
 
1449
        }
 
1450
}
 
1451
 
 
1452
int Item_ListBox_ThumbDrawPosition(itemDef_t *item) {
 
1453
        int min, max;
 
1454
 
 
1455
        if (itemCapture == item) {
 
1456
                if (item->window.flags & WINDOW_HORIZONTAL) {
 
1457
                        min = item->window.rect.x + SCROLLBAR_SIZE + 1;
 
1458
                        max = item->window.rect.x + item->window.rect.w - 2*SCROLLBAR_SIZE - 1;
 
1459
                        if (DC->cursorx >= min + SCROLLBAR_SIZE/2 && DC->cursorx <= max + SCROLLBAR_SIZE/2) {
 
1460
                                return DC->cursorx - SCROLLBAR_SIZE/2;
 
1461
                        }
 
1462
                        else {
 
1463
                                return Item_ListBox_ThumbPosition(item);
 
1464
                        }
 
1465
                }
 
1466
                else {
 
1467
                        min = item->window.rect.y + SCROLLBAR_SIZE + 1;
 
1468
                        max = item->window.rect.y + item->window.rect.h - 2*SCROLLBAR_SIZE - 1;
 
1469
                        if (DC->cursory >= min + SCROLLBAR_SIZE/2 && DC->cursory <= max + SCROLLBAR_SIZE/2) {
 
1470
                                return DC->cursory - SCROLLBAR_SIZE/2;
 
1471
                        }
 
1472
                        else {
 
1473
                                return Item_ListBox_ThumbPosition(item);
 
1474
                        }
 
1475
                }
 
1476
        }
 
1477
        else {
 
1478
                return Item_ListBox_ThumbPosition(item);
 
1479
        }
 
1480
}
 
1481
 
 
1482
float Item_Slider_ThumbPosition(itemDef_t *item) {
 
1483
        float value, range, x;
 
1484
        editFieldDef_t *editDef = item->typeData;
 
1485
 
 
1486
        if (item->text) {
 
1487
                x = item->textRect.x + item->textRect.w + 8;
 
1488
        } else {
 
1489
                x = item->window.rect.x;
 
1490
        }
 
1491
 
 
1492
        if (editDef == NULL && item->cvar) {
 
1493
                return x;
 
1494
        }
 
1495
 
 
1496
        value = DC->getCVarValue(item->cvar);
 
1497
 
 
1498
        if (value < editDef->minVal) {
 
1499
                value = editDef->minVal;
 
1500
        } else if (value > editDef->maxVal) {
 
1501
                value = editDef->maxVal;
 
1502
        }
 
1503
 
 
1504
        range = editDef->maxVal - editDef->minVal;
 
1505
        value -= editDef->minVal;
 
1506
        value /= range;
 
1507
        //value /= (editDef->maxVal - editDef->minVal);
 
1508
        value *= SLIDER_WIDTH;
 
1509
        x += value;
 
1510
        // vm fuckage
 
1511
        //x = x + (((float)value / editDef->maxVal) * SLIDER_WIDTH);
 
1512
        return x;
 
1513
}
 
1514
 
 
1515
int Item_Slider_OverSlider(itemDef_t *item, float x, float y) {
 
1516
        rectDef_t r;
 
1517
 
 
1518
        r.x = Item_Slider_ThumbPosition(item) - (SLIDER_THUMB_WIDTH / 2);
 
1519
        r.y = item->window.rect.y - 2;
 
1520
        r.w = SLIDER_THUMB_WIDTH;
 
1521
        r.h = SLIDER_THUMB_HEIGHT;
 
1522
 
 
1523
        if (Rect_ContainsPoint(&r, x, y)) {
 
1524
                return WINDOW_LB_THUMB;
 
1525
        }
 
1526
        return 0;
 
1527
}
 
1528
 
 
1529
int Item_ListBox_OverLB(itemDef_t *item, float x, float y) {
 
1530
        rectDef_t r;
 
1531
        listBoxDef_t *listPtr;
 
1532
        int thumbstart;
 
1533
        int count;
 
1534
 
 
1535
        count = DC->feederCount(item->special);
 
1536
        listPtr = (listBoxDef_t*)item->typeData;
 
1537
        if (item->window.flags & WINDOW_HORIZONTAL) {
 
1538
                // check if on left arrow
 
1539
                r.x = item->window.rect.x;
 
1540
                r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
 
1541
                r.h = r.w = SCROLLBAR_SIZE;
 
1542
                if (Rect_ContainsPoint(&r, x, y)) {
 
1543
                        return WINDOW_LB_LEFTARROW;
 
1544
                }
 
1545
                // check if on right arrow
 
1546
                r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
 
1547
                if (Rect_ContainsPoint(&r, x, y)) {
 
1548
                        return WINDOW_LB_RIGHTARROW;
 
1549
                }
 
1550
                // check if on thumb
 
1551
                thumbstart = Item_ListBox_ThumbPosition(item);
 
1552
                r.x = thumbstart;
 
1553
                if (Rect_ContainsPoint(&r, x, y)) {
 
1554
                        return WINDOW_LB_THUMB;
 
1555
                }
 
1556
                r.x = item->window.rect.x + SCROLLBAR_SIZE;
 
1557
                r.w = thumbstart - r.x;
 
1558
                if (Rect_ContainsPoint(&r, x, y)) {
 
1559
                        return WINDOW_LB_PGUP;
 
1560
                }
 
1561
                r.x = thumbstart + SCROLLBAR_SIZE;
 
1562
                r.w = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
 
1563
                if (Rect_ContainsPoint(&r, x, y)) {
 
1564
                        return WINDOW_LB_PGDN;
 
1565
                }
 
1566
        } else {
 
1567
                r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
 
1568
                r.y = item->window.rect.y;
 
1569
                r.h = r.w = SCROLLBAR_SIZE;
 
1570
                if (Rect_ContainsPoint(&r, x, y)) {
 
1571
                        return WINDOW_LB_LEFTARROW;
 
1572
                }
 
1573
                r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
 
1574
                if (Rect_ContainsPoint(&r, x, y)) {
 
1575
                        return WINDOW_LB_RIGHTARROW;
 
1576
                }
 
1577
                thumbstart = Item_ListBox_ThumbPosition(item);
 
1578
                r.y = thumbstart;
 
1579
                if (Rect_ContainsPoint(&r, x, y)) {
 
1580
                        return WINDOW_LB_THUMB;
 
1581
                }
 
1582
                r.y = item->window.rect.y + SCROLLBAR_SIZE;
 
1583
                r.h = thumbstart - r.y;
 
1584
                if (Rect_ContainsPoint(&r, x, y)) {
 
1585
                        return WINDOW_LB_PGUP;
 
1586
                }
 
1587
                r.y = thumbstart + SCROLLBAR_SIZE;
 
1588
                r.h = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
 
1589
                if (Rect_ContainsPoint(&r, x, y)) {
 
1590
                        return WINDOW_LB_PGDN;
 
1591
                }
 
1592
        }
 
1593
        return 0;
 
1594
}
 
1595
 
 
1596
 
 
1597
void Item_ListBox_MouseEnter(itemDef_t *item, float x, float y) 
 
1598
{
 
1599
        rectDef_t r;
 
1600
        listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
 
1601
        
 
1602
        item->window.flags &= ~(WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN);
 
1603
        item->window.flags |= Item_ListBox_OverLB(item, x, y);
 
1604
 
 
1605
        if (item->window.flags & WINDOW_HORIZONTAL) {
 
1606
                if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN))) {
 
1607
                        // check for selection hit as we have exausted buttons and thumb
 
1608
                        if (listPtr->elementStyle == LISTBOX_IMAGE) {
 
1609
                                r.x = item->window.rect.x;
 
1610
                                r.y = item->window.rect.y;
 
1611
                                r.h = item->window.rect.h - SCROLLBAR_SIZE;
 
1612
                                r.w = item->window.rect.w - listPtr->drawPadding;
 
1613
                                if (Rect_ContainsPoint(&r, x, y)) {
 
1614
                                        listPtr->cursorPos =  (int)((x - r.x) / listPtr->elementWidth)  + listPtr->startPos;
 
1615
                                        if (listPtr->cursorPos >= listPtr->endPos) {
 
1616
                                                listPtr->cursorPos = listPtr->endPos;
 
1617
                                        }
 
1618
                                }
 
1619
                        } else {
 
1620
                                // text hit.. 
 
1621
                        }
 
1622
                }
 
1623
        } else if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN))) {
 
1624
                r.x = item->window.rect.x;
 
1625
                r.y = item->window.rect.y;
 
1626
                r.w = item->window.rect.w - SCROLLBAR_SIZE;
 
1627
                r.h = item->window.rect.h - listPtr->drawPadding;
 
1628
                if (Rect_ContainsPoint(&r, x, y)) {
 
1629
                        listPtr->cursorPos =  (int)((y - 2 - r.y) / listPtr->elementHeight)  + listPtr->startPos;
 
1630
                        if (listPtr->cursorPos > listPtr->endPos) {
 
1631
                                listPtr->cursorPos = listPtr->endPos;
 
1632
                        }
 
1633
                }
 
1634
        }
 
1635
}
 
1636
 
 
1637
void Item_MouseEnter(itemDef_t *item, float x, float y) {
 
1638
        rectDef_t r;
 
1639
        if (item) {
 
1640
                r = item->textRect;
 
1641
                r.y -= r.h;
 
1642
                // in the text rect?
 
1643
 
 
1644
                // items can be enabled and disabled based on cvars
 
1645
                if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
 
1646
                        return;
 
1647
                }
 
1648
 
 
1649
                if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
 
1650
                        return;
 
1651
                }
 
1652
 
 
1653
                if (Rect_ContainsPoint(&r, x, y)) {
 
1654
                        if (!(item->window.flags & WINDOW_MOUSEOVERTEXT)) {
 
1655
                                Item_RunScript(item, item->mouseEnterText);
 
1656
                                item->window.flags |= WINDOW_MOUSEOVERTEXT;
 
1657
                        }
 
1658
                        if (!(item->window.flags & WINDOW_MOUSEOVER)) {
 
1659
                                Item_RunScript(item, item->mouseEnter);
 
1660
                                item->window.flags |= WINDOW_MOUSEOVER;
 
1661
                        }
 
1662
 
 
1663
                } else {
 
1664
                        // not in the text rect
 
1665
                        if (item->window.flags & WINDOW_MOUSEOVERTEXT) {
 
1666
                                // if we were
 
1667
                                Item_RunScript(item, item->mouseExitText);
 
1668
                                item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
 
1669
                        }
 
1670
                        if (!(item->window.flags & WINDOW_MOUSEOVER)) {
 
1671
                                Item_RunScript(item, item->mouseEnter);
 
1672
                                item->window.flags |= WINDOW_MOUSEOVER;
 
1673
                        }
 
1674
 
 
1675
                        if (item->type == ITEM_TYPE_LISTBOX) {
 
1676
                                Item_ListBox_MouseEnter(item, x, y);
 
1677
                        }
 
1678
                }
 
1679
        }
 
1680
}
 
1681
 
 
1682
void Item_MouseLeave(itemDef_t *item) {
 
1683
  if (item) {
 
1684
    if (item->window.flags & WINDOW_MOUSEOVERTEXT) {
 
1685
      Item_RunScript(item, item->mouseExitText);
 
1686
      item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
 
1687
    }
 
1688
    Item_RunScript(item, item->mouseExit);
 
1689
    item->window.flags &= ~(WINDOW_LB_RIGHTARROW | WINDOW_LB_LEFTARROW);
 
1690
  }
 
1691
}
 
1692
 
 
1693
itemDef_t *Menu_HitTest(menuDef_t *menu, float x, float y) {
 
1694
  int i;
 
1695
  for (i = 0; i < menu->itemCount; i++) {
 
1696
    if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
 
1697
      return menu->items[i];
 
1698
    }
 
1699
  }
 
1700
  return NULL;
 
1701
}
 
1702
 
 
1703
void Item_SetMouseOver(itemDef_t *item, qboolean focus) {
 
1704
  if (item) {
 
1705
    if (focus) {
 
1706
      item->window.flags |= WINDOW_MOUSEOVER;
 
1707
    } else {
 
1708
      item->window.flags &= ~WINDOW_MOUSEOVER;
 
1709
    }
 
1710
  }
 
1711
}
 
1712
 
 
1713
 
 
1714
qboolean Item_OwnerDraw_HandleKey(itemDef_t *item, int key) {
 
1715
  if (item && DC->ownerDrawHandleKey) {
 
1716
    return DC->ownerDrawHandleKey(item->window.ownerDraw, item->window.ownerDrawFlags, &item->special, key);
 
1717
  }
 
1718
  return qfalse;
 
1719
}
 
1720
 
 
1721
qboolean Item_ListBox_HandleKey(itemDef_t *item, int key, qboolean down, qboolean force) {
 
1722
        listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
 
1723
        int count = DC->feederCount(item->special);
 
1724
        int max, viewmax;
 
1725
 
 
1726
        if (force || (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS)) {
 
1727
                max = Item_ListBox_MaxScroll(item);
 
1728
                if (item->window.flags & WINDOW_HORIZONTAL) {
 
1729
                        viewmax = (item->window.rect.w / listPtr->elementWidth);
 
1730
                        if ( key == K_LEFTARROW || key == K_KP_LEFTARROW ) 
 
1731
                        {
 
1732
                                if (!listPtr->notselectable) {
 
1733
                                        listPtr->cursorPos--;
 
1734
                                        if (listPtr->cursorPos < 0) {
 
1735
                                                listPtr->cursorPos = 0;
 
1736
                                        }
 
1737
                                        if (listPtr->cursorPos < listPtr->startPos) {
 
1738
                                                listPtr->startPos = listPtr->cursorPos;
 
1739
                                        }
 
1740
                                        if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
 
1741
                                                listPtr->startPos = listPtr->cursorPos - viewmax + 1;
 
1742
                                        }
 
1743
                                        item->cursorPos = listPtr->cursorPos;
 
1744
                                        DC->feederSelection(item->special, item->cursorPos);
 
1745
                                }
 
1746
                                else {
 
1747
                                        listPtr->startPos--;
 
1748
                                        if (listPtr->startPos < 0)
 
1749
                                                listPtr->startPos = 0;
 
1750
                                }
 
1751
                                return qtrue;
 
1752
                        }
 
1753
                        if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW ) 
 
1754
                        {
 
1755
                                if (!listPtr->notselectable) {
 
1756
                                        listPtr->cursorPos++;
 
1757
                                        if (listPtr->cursorPos < listPtr->startPos) {
 
1758
                                                listPtr->startPos = listPtr->cursorPos;
 
1759
                                        }
 
1760
                                        if (listPtr->cursorPos >= count) {
 
1761
                                                listPtr->cursorPos = count-1;
 
1762
                                        }
 
1763
                                        if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
 
1764
                                                listPtr->startPos = listPtr->cursorPos - viewmax + 1;
 
1765
                                        }
 
1766
                                        item->cursorPos = listPtr->cursorPos;
 
1767
                                        DC->feederSelection(item->special, item->cursorPos);
 
1768
                                }
 
1769
                                else {
 
1770
                                        listPtr->startPos++;
 
1771
                                        if (listPtr->startPos >= count)
 
1772
                                                listPtr->startPos = count-1;
 
1773
                                }
 
1774
                                return qtrue;
 
1775
                        }
 
1776
                }
 
1777
                else {
 
1778
                        viewmax = (item->window.rect.h / listPtr->elementHeight);
 
1779
                        if ( key == K_UPARROW || key == K_KP_UPARROW ) 
 
1780
                        {
 
1781
                                if (!listPtr->notselectable) {
 
1782
                                        listPtr->cursorPos--;
 
1783
                                        if (listPtr->cursorPos < 0) {
 
1784
                                                listPtr->cursorPos = 0;
 
1785
                                        }
 
1786
                                        if (listPtr->cursorPos < listPtr->startPos) {
 
1787
                                                listPtr->startPos = listPtr->cursorPos;
 
1788
                                        }
 
1789
                                        if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
 
1790
                                                listPtr->startPos = listPtr->cursorPos - viewmax + 1;
 
1791
                                        }
 
1792
                                        item->cursorPos = listPtr->cursorPos;
 
1793
                                        DC->feederSelection(item->special, item->cursorPos);
 
1794
                                }
 
1795
                                else {
 
1796
                                        listPtr->startPos--;
 
1797
                                        if (listPtr->startPos < 0)
 
1798
                                                listPtr->startPos = 0;
 
1799
                                }
 
1800
                                return qtrue;
 
1801
                        }
 
1802
                        if ( key == K_DOWNARROW || key == K_KP_DOWNARROW ) 
 
1803
                        {
 
1804
                                if (!listPtr->notselectable) {
 
1805
                                        listPtr->cursorPos++;
 
1806
                                        if (listPtr->cursorPos < listPtr->startPos) {
 
1807
                                                listPtr->startPos = listPtr->cursorPos;
 
1808
                                        }
 
1809
                                        if (listPtr->cursorPos >= count) {
 
1810
                                                listPtr->cursorPos = count-1;
 
1811
                                        }
 
1812
                                        if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
 
1813
                                                listPtr->startPos = listPtr->cursorPos - viewmax + 1;
 
1814
                                        }
 
1815
                                        item->cursorPos = listPtr->cursorPos;
 
1816
                                        DC->feederSelection(item->special, item->cursorPos);
 
1817
                                }
 
1818
                                else {
 
1819
                                        listPtr->startPos++;
 
1820
                                        if (listPtr->startPos > max)
 
1821
                                                listPtr->startPos = max;
 
1822
                                }
 
1823
                                return qtrue;
 
1824
                        }
 
1825
                }
 
1826
                // mouse hit
 
1827
                if (key == K_MOUSE1 || key == K_MOUSE2) {
 
1828
                        if (item->window.flags & WINDOW_LB_LEFTARROW) {
 
1829
                                listPtr->startPos--;
 
1830
                                if (listPtr->startPos < 0) {
 
1831
                                        listPtr->startPos = 0;
 
1832
                                }
 
1833
                        } else if (item->window.flags & WINDOW_LB_RIGHTARROW) {
 
1834
                                // one down
 
1835
                                listPtr->startPos++;
 
1836
                                if (listPtr->startPos > max) {
 
1837
                                        listPtr->startPos = max;
 
1838
                                }
 
1839
                        } else if (item->window.flags & WINDOW_LB_PGUP) {
 
1840
                                // page up
 
1841
                                listPtr->startPos -= viewmax;
 
1842
                                if (listPtr->startPos < 0) {
 
1843
                                        listPtr->startPos = 0;
 
1844
                                }
 
1845
                        } else if (item->window.flags & WINDOW_LB_PGDN) {
 
1846
                                // page down
 
1847
                                listPtr->startPos += viewmax;
 
1848
                                if (listPtr->startPos > max) {
 
1849
                                        listPtr->startPos = max;
 
1850
                                }
 
1851
                        } else if (item->window.flags & WINDOW_LB_THUMB) {
 
1852
                                // Display_SetCaptureItem(item);
 
1853
                        } else {
 
1854
                                // select an item
 
1855
                                if (DC->realTime < lastListBoxClickTime && listPtr->doubleClick) {
 
1856
                                        Item_RunScript(item, listPtr->doubleClick);
 
1857
                                }
 
1858
                                lastListBoxClickTime = DC->realTime + DOUBLE_CLICK_DELAY;
 
1859
                                if (item->cursorPos != listPtr->cursorPos) {
 
1860
                                        item->cursorPos = listPtr->cursorPos;
 
1861
                                        DC->feederSelection(item->special, item->cursorPos);
 
1862
                                }
 
1863
                        }
 
1864
                        return qtrue;
 
1865
                }
 
1866
                if ( key == K_HOME || key == K_KP_HOME) {
 
1867
                        // home
 
1868
                        listPtr->startPos = 0;
 
1869
                        return qtrue;
 
1870
                }
 
1871
                if ( key == K_END || key == K_KP_END) {
 
1872
                        // end
 
1873
                        listPtr->startPos = max;
 
1874
                        return qtrue;
 
1875
                }
 
1876
                if (key == K_PGUP || key == K_KP_PGUP ) {
 
1877
                        // page up
 
1878
                        if (!listPtr->notselectable) {
 
1879
                                listPtr->cursorPos -= viewmax;
 
1880
                                if (listPtr->cursorPos < 0) {
 
1881
                                        listPtr->cursorPos = 0;
 
1882
                                }
 
1883
                                if (listPtr->cursorPos < listPtr->startPos) {
 
1884
                                        listPtr->startPos = listPtr->cursorPos;
 
1885
                                }
 
1886
                                if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
 
1887
                                        listPtr->startPos = listPtr->cursorPos - viewmax + 1;
 
1888
                                }
 
1889
                                item->cursorPos = listPtr->cursorPos;
 
1890
                                DC->feederSelection(item->special, item->cursorPos);
 
1891
                        }
 
1892
                        else {
 
1893
                                listPtr->startPos -= viewmax;
 
1894
                                if (listPtr->startPos < 0) {
 
1895
                                        listPtr->startPos = 0;
 
1896
                                }
 
1897
                        }
 
1898
                        return qtrue;
 
1899
                }
 
1900
                if ( key == K_PGDN || key == K_KP_PGDN ) {
 
1901
                        // page down
 
1902
                        if (!listPtr->notselectable) {
 
1903
                                listPtr->cursorPos += viewmax;
 
1904
                                if (listPtr->cursorPos < listPtr->startPos) {
 
1905
                                        listPtr->startPos = listPtr->cursorPos;
 
1906
                                }
 
1907
                                if (listPtr->cursorPos >= count) {
 
1908
                                        listPtr->cursorPos = count-1;
 
1909
                                }
 
1910
                                if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
 
1911
                                        listPtr->startPos = listPtr->cursorPos - viewmax + 1;
 
1912
                                }
 
1913
                                item->cursorPos = listPtr->cursorPos;
 
1914
                                DC->feederSelection(item->special, item->cursorPos);
 
1915
                        }
 
1916
                        else {
 
1917
                                listPtr->startPos += viewmax;
 
1918
                                if (listPtr->startPos > max) {
 
1919
                                        listPtr->startPos = max;
 
1920
                                }
 
1921
                        }
 
1922
                        return qtrue;
 
1923
                }
 
1924
        }
 
1925
        return qfalse;
 
1926
}
 
1927
 
 
1928
qboolean Item_YesNo_HandleKey(itemDef_t *item, int key) {
 
1929
 
 
1930
  if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS && item->cvar) {
 
1931
                if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
 
1932
            DC->setCVar(item->cvar, va("%i", !DC->getCVarValue(item->cvar)));
 
1933
                  return qtrue;
 
1934
                }
 
1935
  }
 
1936
 
 
1937
  return qfalse;
 
1938
 
 
1939
}
 
1940
 
 
1941
int Item_Multi_CountSettings(itemDef_t *item) {
 
1942
        multiDef_t *multiPtr = (multiDef_t*)item->typeData;
 
1943
        if (multiPtr == NULL) {
 
1944
                return 0;
 
1945
        }
 
1946
        return multiPtr->count;
 
1947
}
 
1948
 
 
1949
int Item_Multi_FindCvarByValue(itemDef_t *item) {
 
1950
        char buff[1024];
 
1951
        float value = 0;
 
1952
        int i;
 
1953
        multiDef_t *multiPtr = (multiDef_t*)item->typeData;
 
1954
        if (multiPtr) {
 
1955
                if (multiPtr->strDef) {
 
1956
            DC->getCVarString(item->cvar, buff, sizeof(buff));
 
1957
                } else {
 
1958
                        value = DC->getCVarValue(item->cvar);
 
1959
                }
 
1960
                for (i = 0; i < multiPtr->count; i++) {
 
1961
                        if (multiPtr->strDef) {
 
1962
                                if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0) {
 
1963
                                        return i;
 
1964
                                }
 
1965
                        } else {
 
1966
                                if (multiPtr->cvarValue[i] == value) {
 
1967
                                        return i;
 
1968
                                }
 
1969
                        }
 
1970
                }
 
1971
        }
 
1972
        return 0;
 
1973
}
 
1974
 
 
1975
const char *Item_Multi_Setting(itemDef_t *item) {
 
1976
        char buff[1024];
 
1977
        float value = 0;
 
1978
        int i;
 
1979
        multiDef_t *multiPtr = (multiDef_t*)item->typeData;
 
1980
        if (multiPtr) {
 
1981
                if (multiPtr->strDef) {
 
1982
            DC->getCVarString(item->cvar, buff, sizeof(buff));
 
1983
                } else {
 
1984
                        value = DC->getCVarValue(item->cvar);
 
1985
                }
 
1986
                for (i = 0; i < multiPtr->count; i++) {
 
1987
                        if (multiPtr->strDef) {
 
1988
                                if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0) {
 
1989
                                        return multiPtr->cvarList[i];
 
1990
                                }
 
1991
                        } else {
 
1992
                                if (multiPtr->cvarValue[i] == value) {
 
1993
                                        return multiPtr->cvarList[i];
 
1994
                                }
 
1995
                        }
 
1996
                }
 
1997
        }
 
1998
        return "";
 
1999
}
 
2000
 
 
2001
qboolean Item_Multi_HandleKey(itemDef_t *item, int key) {
 
2002
        multiDef_t *multiPtr = (multiDef_t*)item->typeData;
 
2003
        if (multiPtr) {
 
2004
          if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS && item->cvar) {
 
2005
                        if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
 
2006
                                int current = Item_Multi_FindCvarByValue(item) + 1;
 
2007
                                int max = Item_Multi_CountSettings(item);
 
2008
                                if ( current < 0 || current >= max ) {
 
2009
                                        current = 0;
 
2010
                                }
 
2011
                                if (multiPtr->strDef) {
 
2012
                                        DC->setCVar(item->cvar, multiPtr->cvarStr[current]);
 
2013
                                } else {
 
2014
                                        float value = multiPtr->cvarValue[current];
 
2015
                                        if (((float)((int) value)) == value) {
 
2016
                                                DC->setCVar(item->cvar, va("%i", (int) value ));
 
2017
                                        }
 
2018
                                        else {
 
2019
                                                DC->setCVar(item->cvar, va("%f", value ));
 
2020
                                        }
 
2021
                                }
 
2022
                                return qtrue;
 
2023
                        }
 
2024
                }
 
2025
        }
 
2026
  return qfalse;
 
2027
}
 
2028
 
 
2029
qboolean Item_TextField_HandleKey(itemDef_t *item, int key) {
 
2030
        char buff[1024];
 
2031
        int len;
 
2032
        itemDef_t *newItem = NULL;
 
2033
        editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
 
2034
 
 
2035
        if (item->cvar) {
 
2036
 
 
2037
                memset(buff, 0, sizeof(buff));
 
2038
                DC->getCVarString(item->cvar, buff, sizeof(buff));
 
2039
                len = strlen(buff);
 
2040
                if (editPtr->maxChars && len > editPtr->maxChars) {
 
2041
                        len = editPtr->maxChars;
 
2042
                }
 
2043
                if ( key & K_CHAR_FLAG ) {
 
2044
                        key &= ~K_CHAR_FLAG;
 
2045
 
 
2046
 
 
2047
                        if (key == 'h' - 'a' + 1 )      {       // ctrl-h is backspace
 
2048
                                if ( item->cursorPos > 0 ) {
 
2049
                                        memmove( &buff[item->cursorPos - 1], &buff[item->cursorPos], len + 1 - item->cursorPos);
 
2050
                                        item->cursorPos--;
 
2051
                                        if (item->cursorPos < editPtr->paintOffset) {
 
2052
                                                editPtr->paintOffset--;
 
2053
                                        }
 
2054
                                }
 
2055
                                DC->setCVar(item->cvar, buff);
 
2056
                        return qtrue;
 
2057
                        }
 
2058
 
 
2059
 
 
2060
                        //
 
2061
                        // ignore any non printable chars
 
2062
                        //
 
2063
                        if ( key < 32 || !item->cvar) {
 
2064
                            return qtrue;
 
2065
                    }
 
2066
 
 
2067
                        if (item->type == ITEM_TYPE_NUMERICFIELD) {
 
2068
                                if (key < '0' || key > '9') {
 
2069
                                        return qfalse;
 
2070
                                }
 
2071
                        }
 
2072
 
 
2073
                        if (!DC->getOverstrikeMode()) {
 
2074
                                if (( len == MAX_EDITFIELD - 1 ) || (editPtr->maxChars && len >= editPtr->maxChars)) {
 
2075
                                        return qtrue;
 
2076
                                }
 
2077
                                memmove( &buff[item->cursorPos + 1], &buff[item->cursorPos], len + 1 - item->cursorPos );
 
2078
                        } else {
 
2079
                                if (editPtr->maxChars && item->cursorPos >= editPtr->maxChars) {
 
2080
                                        return qtrue;
 
2081
                                }
 
2082
                        }
 
2083
 
 
2084
                        buff[item->cursorPos] = key;
 
2085
 
 
2086
                        DC->setCVar(item->cvar, buff);
 
2087
 
 
2088
                        if (item->cursorPos < len + 1) {
 
2089
                                item->cursorPos++;
 
2090
                                if (editPtr->maxPaintChars && item->cursorPos > editPtr->maxPaintChars) {
 
2091
                                        editPtr->paintOffset++;
 
2092
                                }
 
2093
                        }
 
2094
 
 
2095
                } else {
 
2096
 
 
2097
                        if ( key == K_DEL || key == K_KP_DEL ) {
 
2098
                                if ( item->cursorPos < len ) {
 
2099
                                        memmove( buff + item->cursorPos, buff + item->cursorPos + 1, len - item->cursorPos);
 
2100
                                        DC->setCVar(item->cvar, buff);
 
2101
                                }
 
2102
                                return qtrue;
 
2103
                        }
 
2104
 
 
2105
                        if ( key == K_RIGHTARROW || key == K_KP_RIGHTARROW ) 
 
2106
                        {
 
2107
                                if (editPtr->maxPaintChars && item->cursorPos >= editPtr->maxPaintChars && item->cursorPos < len) {
 
2108
                                        item->cursorPos++;
 
2109
                                        editPtr->paintOffset++;
 
2110
                                        return qtrue;
 
2111
                                }
 
2112
                                if (item->cursorPos < len) {
 
2113
                                        item->cursorPos++;
 
2114
                                } 
 
2115
                                return qtrue;
 
2116
                        }
 
2117
 
 
2118
                        if ( key == K_LEFTARROW || key == K_KP_LEFTARROW ) 
 
2119
                        {
 
2120
                                if ( item->cursorPos > 0 ) {
 
2121
                                        item->cursorPos--;
 
2122
                                }
 
2123
                                if (item->cursorPos < editPtr->paintOffset) {
 
2124
                                        editPtr->paintOffset--;
 
2125
                                }
 
2126
                                return qtrue;
 
2127
                        }
 
2128
 
 
2129
                        if ( key == K_HOME || key == K_KP_HOME) {// || ( tolower(key) == 'a' && trap_Key_IsDown( K_CTRL ) ) ) {
 
2130
                                item->cursorPos = 0;
 
2131
                                editPtr->paintOffset = 0;
 
2132
                                return qtrue;
 
2133
                        }
 
2134
 
 
2135
                        if ( key == K_END || key == K_KP_END)  {// ( tolower(key) == 'e' && trap_Key_IsDown( K_CTRL ) ) ) {
 
2136
                                item->cursorPos = len;
 
2137
                                if(item->cursorPos > editPtr->maxPaintChars) {
 
2138
                                        editPtr->paintOffset = len - editPtr->maxPaintChars;
 
2139
                                }
 
2140
                                return qtrue;
 
2141
                        }
 
2142
 
 
2143
                        if ( key == K_INS || key == K_KP_INS ) {
 
2144
                                DC->setOverstrikeMode(!DC->getOverstrikeMode());
 
2145
                                return qtrue;
 
2146
                        }
 
2147
                }
 
2148
 
 
2149
                if (key == K_TAB || key == K_DOWNARROW || key == K_KP_DOWNARROW) {
 
2150
                        newItem = Menu_SetNextCursorItem(item->parent);
 
2151
                        if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD)) {
 
2152
                                g_editItem = newItem;
 
2153
                        }
 
2154
                }
 
2155
 
 
2156
                if (key == K_UPARROW || key == K_KP_UPARROW) {
 
2157
                        newItem = Menu_SetPrevCursorItem(item->parent);
 
2158
                        if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD)) {
 
2159
                                g_editItem = newItem;
 
2160
                        }
 
2161
                }
 
2162
 
 
2163
                if ( key == K_ENTER || key == K_KP_ENTER || key == K_ESCAPE)  {
 
2164
                        return qfalse;
 
2165
                }
 
2166
 
 
2167
                return qtrue;
 
2168
        }
 
2169
        return qfalse;
 
2170
 
 
2171
}
 
2172
 
 
2173
static void Scroll_ListBox_AutoFunc(void *p) {
 
2174
        scrollInfo_t *si = (scrollInfo_t*)p;
 
2175
        if (DC->realTime > si->nextScrollTime) { 
 
2176
                // need to scroll which is done by simulating a click to the item
 
2177
                // this is done a bit sideways as the autoscroll "knows" that the item is a listbox
 
2178
                // so it calls it directly
 
2179
                Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
 
2180
                si->nextScrollTime = DC->realTime + si->adjustValue; 
 
2181
        }
 
2182
 
 
2183
        if (DC->realTime > si->nextAdjustTime) {
 
2184
                si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
 
2185
                if (si->adjustValue > SCROLL_TIME_FLOOR) {
 
2186
                        si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
 
2187
                }
 
2188
        }
 
2189
}
 
2190
 
 
2191
static void Scroll_ListBox_ThumbFunc(void *p) {
 
2192
        scrollInfo_t *si = (scrollInfo_t*)p;
 
2193
        rectDef_t r;
 
2194
        int pos, max;
 
2195
 
 
2196
        listBoxDef_t *listPtr = (listBoxDef_t*)si->item->typeData;
 
2197
        if (si->item->window.flags & WINDOW_HORIZONTAL) {
 
2198
                if (DC->cursorx == si->xStart) {
 
2199
                        return;
 
2200
                }
 
2201
                r.x = si->item->window.rect.x + SCROLLBAR_SIZE + 1;
 
2202
                r.y = si->item->window.rect.y + si->item->window.rect.h - SCROLLBAR_SIZE - 1;
 
2203
                r.h = SCROLLBAR_SIZE;
 
2204
                r.w = si->item->window.rect.w - (SCROLLBAR_SIZE*2) - 2;
 
2205
                max = Item_ListBox_MaxScroll(si->item);
 
2206
                //
 
2207
                pos = (DC->cursorx - r.x - SCROLLBAR_SIZE/2) * max / (r.w - SCROLLBAR_SIZE);
 
2208
                if (pos < 0) {
 
2209
                        pos = 0;
 
2210
                }
 
2211
                else if (pos > max) {
 
2212
                        pos = max;
 
2213
                }
 
2214
                listPtr->startPos = pos;
 
2215
                si->xStart = DC->cursorx;
 
2216
        }
 
2217
        else if (DC->cursory != si->yStart) {
 
2218
 
 
2219
                r.x = si->item->window.rect.x + si->item->window.rect.w - SCROLLBAR_SIZE - 1;
 
2220
                r.y = si->item->window.rect.y + SCROLLBAR_SIZE + 1;
 
2221
                r.h = si->item->window.rect.h - (SCROLLBAR_SIZE*2) - 2;
 
2222
                r.w = SCROLLBAR_SIZE;
 
2223
                max = Item_ListBox_MaxScroll(si->item);
 
2224
                //
 
2225
                pos = (DC->cursory - r.y - SCROLLBAR_SIZE/2) * max / (r.h - SCROLLBAR_SIZE);
 
2226
                if (pos < 0) {
 
2227
                        pos = 0;
 
2228
                }
 
2229
                else if (pos > max) {
 
2230
                        pos = max;
 
2231
                }
 
2232
                listPtr->startPos = pos;
 
2233
                si->yStart = DC->cursory;
 
2234
        }
 
2235
 
 
2236
        if (DC->realTime > si->nextScrollTime) { 
 
2237
                // need to scroll which is done by simulating a click to the item
 
2238
                // this is done a bit sideways as the autoscroll "knows" that the item is a listbox
 
2239
                // so it calls it directly
 
2240
                Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
 
2241
                si->nextScrollTime = DC->realTime + si->adjustValue; 
 
2242
        }
 
2243
 
 
2244
        if (DC->realTime > si->nextAdjustTime) {
 
2245
                si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
 
2246
                if (si->adjustValue > SCROLL_TIME_FLOOR) {
 
2247
                        si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
 
2248
                }
 
2249
        }
 
2250
}
 
2251
 
 
2252
static void Scroll_Slider_ThumbFunc(void *p) {
 
2253
        float x, value, cursorx;
 
2254
        scrollInfo_t *si = (scrollInfo_t*)p;
 
2255
        editFieldDef_t *editDef = si->item->typeData;
 
2256
 
 
2257
        if (si->item->text) {
 
2258
                x = si->item->textRect.x + si->item->textRect.w + 8;
 
2259
        } else {
 
2260
                x = si->item->window.rect.x;
 
2261
        }
 
2262
 
 
2263
        cursorx = DC->cursorx;
 
2264
 
 
2265
        if (cursorx < x) {
 
2266
                cursorx = x;
 
2267
        } else if (cursorx > x + SLIDER_WIDTH) {
 
2268
                cursorx = x + SLIDER_WIDTH;
 
2269
        }
 
2270
        value = cursorx - x;
 
2271
        value /= SLIDER_WIDTH;
 
2272
        value *= (editDef->maxVal - editDef->minVal);
 
2273
        value += editDef->minVal;
 
2274
        DC->setCVar(si->item->cvar, va("%f", value));
 
2275
}
 
2276
 
 
2277
void Item_StartCapture(itemDef_t *item, int key) {
 
2278
        int flags;
 
2279
        switch (item->type) {
 
2280
    case ITEM_TYPE_EDITFIELD:
 
2281
    case ITEM_TYPE_NUMERICFIELD:
 
2282
 
 
2283
                case ITEM_TYPE_LISTBOX:
 
2284
                {
 
2285
                        flags = Item_ListBox_OverLB(item, DC->cursorx, DC->cursory);
 
2286
                        if (flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW)) {
 
2287
                                scrollInfo.nextScrollTime = DC->realTime + SCROLL_TIME_START;
 
2288
                                scrollInfo.nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
 
2289
                                scrollInfo.adjustValue = SCROLL_TIME_START;
 
2290
                                scrollInfo.scrollKey = key;
 
2291
                                scrollInfo.scrollDir = (flags & WINDOW_LB_LEFTARROW) ? qtrue : qfalse;
 
2292
                                scrollInfo.item = item;
 
2293
                                captureData = &scrollInfo;
 
2294
                                captureFunc = &Scroll_ListBox_AutoFunc;
 
2295
                                itemCapture = item;
 
2296
                        } else if (flags & WINDOW_LB_THUMB) {
 
2297
                                scrollInfo.scrollKey = key;
 
2298
                                scrollInfo.item = item;
 
2299
                                scrollInfo.xStart = DC->cursorx;
 
2300
                                scrollInfo.yStart = DC->cursory;
 
2301
                                captureData = &scrollInfo;
 
2302
                                captureFunc = &Scroll_ListBox_ThumbFunc;
 
2303
                                itemCapture = item;
 
2304
                        }
 
2305
                        break;
 
2306
                }
 
2307
                case ITEM_TYPE_SLIDER:
 
2308
                {
 
2309
                        flags = Item_Slider_OverSlider(item, DC->cursorx, DC->cursory);
 
2310
                        if (flags & WINDOW_LB_THUMB) {
 
2311
                                scrollInfo.scrollKey = key;
 
2312
                                scrollInfo.item = item;
 
2313
                                scrollInfo.xStart = DC->cursorx;
 
2314
                                scrollInfo.yStart = DC->cursory;
 
2315
                                captureData = &scrollInfo;
 
2316
                                captureFunc = &Scroll_Slider_ThumbFunc;
 
2317
                                itemCapture = item;
 
2318
                        }
 
2319
                        break;
 
2320
                }
 
2321
        }
 
2322
}
 
2323
 
 
2324
void Item_StopCapture(itemDef_t *item) {
 
2325
 
 
2326
}
 
2327
 
 
2328
qboolean Item_Slider_HandleKey(itemDef_t *item, int key, qboolean down) {
 
2329
        float x, value, width, work;
 
2330
 
 
2331
        //DC->Print("slider handle key\n");
 
2332
        if (item->window.flags & WINDOW_HASFOCUS && item->cvar && Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
 
2333
                if (key == K_MOUSE1 || key == K_ENTER || key == K_MOUSE2 || key == K_MOUSE3) {
 
2334
                        editFieldDef_t *editDef = item->typeData;
 
2335
                        if (editDef) {
 
2336
                                rectDef_t testRect;
 
2337
                                width = SLIDER_WIDTH;
 
2338
                                if (item->text) {
 
2339
                                        x = item->textRect.x + item->textRect.w + 8;
 
2340
                                } else {
 
2341
                                        x = item->window.rect.x;
 
2342
                                }
 
2343
 
 
2344
                                testRect = item->window.rect;
 
2345
                                testRect.x = x;
 
2346
                                value = (float)SLIDER_THUMB_WIDTH / 2;
 
2347
                                testRect.x -= value;
 
2348
                                //DC->Print("slider x: %f\n", testRect.x);
 
2349
                                testRect.w = (SLIDER_WIDTH + (float)SLIDER_THUMB_WIDTH / 2);
 
2350
                                //DC->Print("slider w: %f\n", testRect.w);
 
2351
                                if (Rect_ContainsPoint(&testRect, DC->cursorx, DC->cursory)) {
 
2352
                                        work = DC->cursorx - x;
 
2353
                                        value = work / width;
 
2354
                                        value *= (editDef->maxVal - editDef->minVal);
 
2355
                                        // vm fuckage
 
2356
                                        // value = (((float)(DC->cursorx - x)/ SLIDER_WIDTH) * (editDef->maxVal - editDef->minVal));
 
2357
                                        value += editDef->minVal;
 
2358
                                        DC->setCVar(item->cvar, va("%f", value));
 
2359
                                        return qtrue;
 
2360
                                }
 
2361
                        }
 
2362
                }
 
2363
        }
 
2364
        DC->Print("slider handle key exit\n");
 
2365
        return qfalse;
 
2366
}
 
2367
 
 
2368
 
 
2369
qboolean Item_HandleKey(itemDef_t *item, int key, qboolean down) {
 
2370
 
 
2371
        if (itemCapture) {
 
2372
                Item_StopCapture(itemCapture);
 
2373
                itemCapture = NULL;
 
2374
                captureFunc = 0;
 
2375
                captureData = NULL;
 
2376
        } else {
 
2377
          // bk001206 - parentheses
 
2378
                if ( down && ( key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3 ) ) {
 
2379
                        Item_StartCapture(item, key);
 
2380
                }
 
2381
        }
 
2382
 
 
2383
        if (!down) {
 
2384
                return qfalse;
 
2385
        }
 
2386
 
 
2387
  switch (item->type) {
 
2388
    case ITEM_TYPE_BUTTON:
 
2389
      return qfalse;
 
2390
      break;
 
2391
    case ITEM_TYPE_RADIOBUTTON:
 
2392
      return qfalse;
 
2393
      break;
 
2394
    case ITEM_TYPE_CHECKBOX:
 
2395
      return qfalse;
 
2396
      break;
 
2397
    case ITEM_TYPE_EDITFIELD:
 
2398
    case ITEM_TYPE_NUMERICFIELD:
 
2399
      //return Item_TextField_HandleKey(item, key);
 
2400
      return qfalse;
 
2401
      break;
 
2402
    case ITEM_TYPE_COMBO:
 
2403
      return qfalse;
 
2404
      break;
 
2405
    case ITEM_TYPE_LISTBOX:
 
2406
      return Item_ListBox_HandleKey(item, key, down, qfalse);
 
2407
      break;
 
2408
    case ITEM_TYPE_YESNO:
 
2409
      return Item_YesNo_HandleKey(item, key);
 
2410
      break;
 
2411
    case ITEM_TYPE_MULTI:
 
2412
      return Item_Multi_HandleKey(item, key);
 
2413
      break;
 
2414
    case ITEM_TYPE_OWNERDRAW:
 
2415
      return Item_OwnerDraw_HandleKey(item, key);
 
2416
      break;
 
2417
    case ITEM_TYPE_BIND:
 
2418
                        return Item_Bind_HandleKey(item, key, down);
 
2419
      break;
 
2420
    case ITEM_TYPE_SLIDER:
 
2421
      return Item_Slider_HandleKey(item, key, down);
 
2422
      break;
 
2423
    //case ITEM_TYPE_IMAGE:
 
2424
    //  Item_Image_Paint(item);
 
2425
    //  break;
 
2426
    default:
 
2427
      return qfalse;
 
2428
      break;
 
2429
  }
 
2430
 
 
2431
  //return qfalse;
 
2432
}
 
2433
 
 
2434
void Item_Action(itemDef_t *item) {
 
2435
  if (item) {
 
2436
    Item_RunScript(item, item->action);
 
2437
  }
 
2438
}
 
2439
 
 
2440
itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu) {
 
2441
  qboolean wrapped = qfalse;
 
2442
        int oldCursor = menu->cursorItem;
 
2443
  
 
2444
  if (menu->cursorItem < 0) {
 
2445
    menu->cursorItem = menu->itemCount-1;
 
2446
    wrapped = qtrue;
 
2447
  } 
 
2448
 
 
2449
  while (menu->cursorItem > -1) {
 
2450
    
 
2451
    menu->cursorItem--;
 
2452
    if (menu->cursorItem < 0 && !wrapped) {
 
2453
      wrapped = qtrue;
 
2454
      menu->cursorItem = menu->itemCount -1;
 
2455
    }
 
2456
 
 
2457
                if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory)) {
 
2458
                        Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
 
2459
      return menu->items[menu->cursorItem];
 
2460
    }
 
2461
  }
 
2462
        menu->cursorItem = oldCursor;
 
2463
        return NULL;
 
2464
 
 
2465
}
 
2466
 
 
2467
itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu) {
 
2468
 
 
2469
  qboolean wrapped = qfalse;
 
2470
        int oldCursor = menu->cursorItem;
 
2471
 
 
2472
 
 
2473
  if (menu->cursorItem == -1) {
 
2474
    menu->cursorItem = 0;
 
2475
    wrapped = qtrue;
 
2476
  }
 
2477
 
 
2478
  while (menu->cursorItem < menu->itemCount) {
 
2479
 
 
2480
    menu->cursorItem++;
 
2481
    if (menu->cursorItem >= menu->itemCount && !wrapped) {
 
2482
      wrapped = qtrue;
 
2483
      menu->cursorItem = 0;
 
2484
    }
 
2485
                if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory)) {
 
2486
                        Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
 
2487
      return menu->items[menu->cursorItem];
 
2488
    }
 
2489
    
 
2490
  }
 
2491
 
 
2492
        menu->cursorItem = oldCursor;
 
2493
        return NULL;
 
2494
}
 
2495
 
 
2496
static void Window_CloseCinematic(windowDef_t *window) {
 
2497
        if (window->style == WINDOW_STYLE_CINEMATIC && window->cinematic >= 0) {
 
2498
                DC->stopCinematic(window->cinematic);
 
2499
                window->cinematic = -1;
 
2500
        }
 
2501
}
 
2502
 
 
2503
static void Menu_CloseCinematics(menuDef_t *menu) {
 
2504
        if (menu) {
 
2505
                int i;
 
2506
                Window_CloseCinematic(&menu->window);
 
2507
          for (i = 0; i < menu->itemCount; i++) {
 
2508
                  Window_CloseCinematic(&menu->items[i]->window);
 
2509
                        if (menu->items[i]->type == ITEM_TYPE_OWNERDRAW) {
 
2510
                                DC->stopCinematic(0-menu->items[i]->window.ownerDraw);
 
2511
                        }
 
2512
          }
 
2513
        }
 
2514
}
 
2515
 
 
2516
static void Display_CloseCinematics( void ) {
 
2517
        int i;
 
2518
        for (i = 0; i < menuCount; i++) {
 
2519
                Menu_CloseCinematics(&Menus[i]);
 
2520
        }
 
2521
}
 
2522
 
 
2523
void  Menus_Activate(menuDef_t *menu) {
 
2524
        menu->window.flags |= (WINDOW_HASFOCUS | WINDOW_VISIBLE);
 
2525
        if (menu->onOpen) {
 
2526
                itemDef_t item;
 
2527
                item.parent = menu;
 
2528
                Item_RunScript(&item, menu->onOpen);
 
2529
        }
 
2530
 
 
2531
        if (menu->soundName && *menu->soundName) {
 
2532
//              DC->stopBackgroundTrack();                                      // you don't want to do this since it will reset s_rawend
 
2533
                DC->startBackgroundTrack(menu->soundName, menu->soundName);
 
2534
        }
 
2535
 
 
2536
        Display_CloseCinematics();
 
2537
 
 
2538
}
 
2539
 
 
2540
int Display_VisibleMenuCount( void ) {
 
2541
        int i, count;
 
2542
        count = 0;
 
2543
        for (i = 0; i < menuCount; i++) {
 
2544
                if (Menus[i].window.flags & (WINDOW_FORCED | WINDOW_VISIBLE)) {
 
2545
                        count++;
 
2546
                }
 
2547
        }
 
2548
        return count;
 
2549
}
 
2550
 
 
2551
void Menus_HandleOOBClick(menuDef_t *menu, int key, qboolean down) {
 
2552
        if (menu) {
 
2553
                int i;
 
2554
                // basically the behaviour we are looking for is if there are windows in the stack.. see if 
 
2555
                // the cursor is within any of them.. if not close them otherwise activate them and pass the 
 
2556
                // key on.. force a mouse move to activate focus and script stuff 
 
2557
                if (down && menu->window.flags & WINDOW_OOB_CLICK) {
 
2558
                        Menu_RunCloseScript(menu);
 
2559
                        menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
 
2560
                }
 
2561
 
 
2562
                for (i = 0; i < menuCount; i++) {
 
2563
                        if (Menu_OverActiveItem(&Menus[i], DC->cursorx, DC->cursory)) {
 
2564
                                Menu_RunCloseScript(menu);
 
2565
                                menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
 
2566
                                Menus_Activate(&Menus[i]);
 
2567
                                Menu_HandleMouseMove(&Menus[i], DC->cursorx, DC->cursory);
 
2568
                                Menu_HandleKey(&Menus[i], key, down);
 
2569
                        }
 
2570
                }
 
2571
 
 
2572
                if (Display_VisibleMenuCount() == 0) {
 
2573
                        if (DC->Pause) {
 
2574
                                DC->Pause(qfalse);
 
2575
                        }
 
2576
                }
 
2577
                Display_CloseCinematics();
 
2578
        }
 
2579
}
 
2580
 
 
2581
static rectDef_t *Item_CorrectedTextRect(itemDef_t *item) {
 
2582
        static rectDef_t rect;
 
2583
        memset(&rect, 0, sizeof(rectDef_t));
 
2584
        if (item) {
 
2585
                rect = item->textRect;
 
2586
                if (rect.w) {
 
2587
                        rect.y -= rect.h;
 
2588
                }
 
2589
        }
 
2590
        return &rect;
 
2591
}
 
2592
 
 
2593
void Menu_HandleKey(menuDef_t *menu, int key, qboolean down) {
 
2594
        int i;
 
2595
        itemDef_t *item = NULL;
 
2596
        qboolean inHandler = qfalse;
 
2597
 
 
2598
        if (inHandler) {
 
2599
                return;
 
2600
        }
 
2601
 
 
2602
        inHandler = qtrue;
 
2603
        if (g_waitingForKey && down) {
 
2604
                Item_Bind_HandleKey(g_bindItem, key, down);
 
2605
                inHandler = qfalse;
 
2606
                return;
 
2607
        }
 
2608
 
 
2609
        if (g_editingField && down) {
 
2610
                if (!Item_TextField_HandleKey(g_editItem, key)) {
 
2611
                        g_editingField = qfalse;
 
2612
                        g_editItem = NULL;
 
2613
                        inHandler = qfalse;
 
2614
                        return;
 
2615
                } else if (key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3) {
 
2616
                        g_editingField = qfalse;
 
2617
                        g_editItem = NULL;
 
2618
                        Display_MouseMove(NULL, DC->cursorx, DC->cursory);
 
2619
                } else if (key == K_TAB || key == K_UPARROW || key == K_DOWNARROW) {
 
2620
                        return;
 
2621
                }
 
2622
        }
 
2623
 
 
2624
        if (menu == NULL) {
 
2625
                inHandler = qfalse;
 
2626
                return;
 
2627
        }
 
2628
 
 
2629
                // see if the mouse is within the window bounds and if so is this a mouse click
 
2630
        if (down && !(menu->window.flags & WINDOW_POPUP) && !Rect_ContainsPoint(&menu->window.rect, DC->cursorx, DC->cursory)) {
 
2631
                static qboolean inHandleKey = qfalse;
 
2632
                // bk001206 - parentheses
 
2633
                if (!inHandleKey && ( key == K_MOUSE1 || key == K_MOUSE2 || key == K_MOUSE3 ) ) {
 
2634
                        inHandleKey = qtrue;
 
2635
                        Menus_HandleOOBClick(menu, key, down);
 
2636
                        inHandleKey = qfalse;
 
2637
                        inHandler = qfalse;
 
2638
                        return;
 
2639
                }
 
2640
        }
 
2641
 
 
2642
        // get the item with focus
 
2643
        for (i = 0; i < menu->itemCount; i++) {
 
2644
                if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
 
2645
                        item = menu->items[i];
 
2646
                }
 
2647
        }
 
2648
 
 
2649
        if (item != NULL) {
 
2650
                if (Item_HandleKey(item, key, down)) {
 
2651
                        Item_Action(item);
 
2652
                        inHandler = qfalse;
 
2653
                        return;
 
2654
                }
 
2655
        }
 
2656
 
 
2657
        if (!down) {
 
2658
                inHandler = qfalse;
 
2659
                return;
 
2660
        }
 
2661
 
 
2662
        // default handling
 
2663
        switch ( key ) {
 
2664
 
 
2665
                case K_F11:
 
2666
                        if (DC->getCVarValue("developer")) {
 
2667
                                debugMode ^= 1;
 
2668
                        }
 
2669
                        break;
 
2670
 
 
2671
                case K_F12:
 
2672
                        if (DC->getCVarValue("developer")) {
 
2673
                                DC->executeText(EXEC_APPEND, "screenshot\n");
 
2674
                        }
 
2675
                        break;
 
2676
                case K_KP_UPARROW:
 
2677
                case K_UPARROW:
 
2678
                        Menu_SetPrevCursorItem(menu);
 
2679
                        break;
 
2680
 
 
2681
                case K_ESCAPE:
 
2682
                        if (!g_waitingForKey && menu->onESC) {
 
2683
                                itemDef_t it;
 
2684
                    it.parent = menu;
 
2685
                    Item_RunScript(&it, menu->onESC);
 
2686
                        }
 
2687
                        break;
 
2688
                case K_TAB:
 
2689
                case K_KP_DOWNARROW:
 
2690
                case K_DOWNARROW:
 
2691
                        Menu_SetNextCursorItem(menu);
 
2692
                        break;
 
2693
 
 
2694
                case K_MOUSE1:
 
2695
                case K_MOUSE2:
 
2696
                        if (item) {
 
2697
                                if (item->type == ITEM_TYPE_TEXT) {
 
2698
                                        if (Rect_ContainsPoint(Item_CorrectedTextRect(item), DC->cursorx, DC->cursory)) {
 
2699
                                                Item_Action(item);
 
2700
                                        }
 
2701
                                } else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
 
2702
                                        if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
 
2703
                                                item->cursorPos = 0;
 
2704
                                                g_editingField = qtrue;
 
2705
                                                g_editItem = item;
 
2706
                                                DC->setOverstrikeMode(qtrue);
 
2707
                                        }
 
2708
                                } else {
 
2709
                                        if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
 
2710
                                                Item_Action(item);
 
2711
                                        }
 
2712
                                }
 
2713
                        }
 
2714
                        break;
 
2715
 
 
2716
                case K_JOY1:
 
2717
                case K_JOY2:
 
2718
                case K_JOY3:
 
2719
                case K_JOY4:
 
2720
                case K_AUX1:
 
2721
                case K_AUX2:
 
2722
                case K_AUX3:
 
2723
                case K_AUX4:
 
2724
                case K_AUX5:
 
2725
                case K_AUX6:
 
2726
                case K_AUX7:
 
2727
                case K_AUX8:
 
2728
                case K_AUX9:
 
2729
                case K_AUX10:
 
2730
                case K_AUX11:
 
2731
                case K_AUX12:
 
2732
                case K_AUX13:
 
2733
                case K_AUX14:
 
2734
                case K_AUX15:
 
2735
                case K_AUX16:
 
2736
                        break;
 
2737
                case K_KP_ENTER:
 
2738
                case K_ENTER:
 
2739
                        if (item) {
 
2740
                                if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
 
2741
                                        item->cursorPos = 0;
 
2742
                                        g_editingField = qtrue;
 
2743
                                        g_editItem = item;
 
2744
                                        DC->setOverstrikeMode(qtrue);
 
2745
                                } else {
 
2746
                                                Item_Action(item);
 
2747
                                }
 
2748
                        }
 
2749
                        break;
 
2750
        }
 
2751
        inHandler = qfalse;
 
2752
}
 
2753
 
 
2754
void ToWindowCoords(float *x, float *y, windowDef_t *window) {
 
2755
        if (window->border != 0) {
 
2756
                *x += window->borderSize;
 
2757
                *y += window->borderSize;
 
2758
        } 
 
2759
        *x += window->rect.x;
 
2760
        *y += window->rect.y;
 
2761
}
 
2762
 
 
2763
void Rect_ToWindowCoords(rectDef_t *rect, windowDef_t *window) {
 
2764
        ToWindowCoords(&rect->x, &rect->y, window);
 
2765
}
 
2766
 
 
2767
void Item_SetTextExtents(itemDef_t *item, int *width, int *height, const char *text) {
 
2768
        const char *textPtr = (text) ? text : item->text;
 
2769
 
 
2770
        if (textPtr == NULL ) {
 
2771
                return;
 
2772
        }
 
2773
 
 
2774
        *width = item->textRect.w;
 
2775
        *height = item->textRect.h;
 
2776
 
 
2777
        // keeps us from computing the widths and heights more than once
 
2778
        if (*width == 0 || (item->type == ITEM_TYPE_OWNERDRAW && item->textalignment == ITEM_ALIGN_CENTER)) {
 
2779
                int originalWidth = DC->textWidth(item->text, item->textscale, 0);
 
2780
 
 
2781
                if (item->type == ITEM_TYPE_OWNERDRAW && (item->textalignment == ITEM_ALIGN_CENTER || item->textalignment == ITEM_ALIGN_RIGHT)) {
 
2782
                        originalWidth += DC->ownerDrawWidth(item->window.ownerDraw, item->textscale);
 
2783
                } else if (item->type == ITEM_TYPE_EDITFIELD && item->textalignment == ITEM_ALIGN_CENTER && item->cvar) {
 
2784
                        char buff[256];
 
2785
                        DC->getCVarString(item->cvar, buff, 256);
 
2786
                        originalWidth += DC->textWidth(buff, item->textscale, 0);
 
2787
                }
 
2788
 
 
2789
                *width = DC->textWidth(textPtr, item->textscale, 0);
 
2790
                *height = DC->textHeight(textPtr, item->textscale, 0);
 
2791
                item->textRect.w = *width;
 
2792
                item->textRect.h = *height;
 
2793
                item->textRect.x = item->textalignx;
 
2794
                item->textRect.y = item->textaligny;
 
2795
                if (item->textalignment == ITEM_ALIGN_RIGHT) {
 
2796
                        item->textRect.x = item->textalignx - originalWidth;
 
2797
                } else if (item->textalignment == ITEM_ALIGN_CENTER) {
 
2798
                        item->textRect.x = item->textalignx - originalWidth / 2;
 
2799
                }
 
2800
 
 
2801
                ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
 
2802
        }
 
2803
}
 
2804
 
 
2805
void Item_TextColor(itemDef_t *item, vec4_t *newColor) {
 
2806
        vec4_t lowLight;
 
2807
        menuDef_t *parent = (menuDef_t*)item->parent;
 
2808
 
 
2809
        Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
 
2810
 
 
2811
        if (item->window.flags & WINDOW_HASFOCUS) {
 
2812
                lowLight[0] = 0.8 * parent->focusColor[0]; 
 
2813
                lowLight[1] = 0.8 * parent->focusColor[1]; 
 
2814
                lowLight[2] = 0.8 * parent->focusColor[2]; 
 
2815
                lowLight[3] = 0.8 * parent->focusColor[3]; 
 
2816
                LerpColor(parent->focusColor,lowLight,*newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
2817
        } else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1)) {
 
2818
                lowLight[0] = 0.8 * item->window.foreColor[0]; 
 
2819
                lowLight[1] = 0.8 * item->window.foreColor[1]; 
 
2820
                lowLight[2] = 0.8 * item->window.foreColor[2]; 
 
2821
                lowLight[3] = 0.8 * item->window.foreColor[3]; 
 
2822
                LerpColor(item->window.foreColor,lowLight,*newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
2823
        } else {
 
2824
                memcpy(newColor, &item->window.foreColor, sizeof(vec4_t));
 
2825
                // items can be enabled and disabled based on cvars
 
2826
        }
 
2827
 
 
2828
        if (item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
 
2829
                if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
 
2830
                        memcpy(newColor, &parent->disableColor, sizeof(vec4_t));
 
2831
                }
 
2832
        }
 
2833
}
 
2834
 
 
2835
void Item_Text_AutoWrapped_Paint(itemDef_t *item) {
 
2836
        char text[1024];
 
2837
        const char *p, *textPtr, *newLinePtr;
 
2838
        char buff[1024];
 
2839
        int width, height, len, textWidth, newLine, newLineWidth;
 
2840
        float y;
 
2841
        vec4_t color;
 
2842
 
 
2843
        textWidth = 0;
 
2844
        newLinePtr = NULL;
 
2845
 
 
2846
        if (item->text == NULL) {
 
2847
                if (item->cvar == NULL) {
 
2848
                        return;
 
2849
                }
 
2850
                else {
 
2851
                        DC->getCVarString(item->cvar, text, sizeof(text));
 
2852
                        textPtr = text;
 
2853
                }
 
2854
        }
 
2855
        else {
 
2856
                textPtr = item->text;
 
2857
        }
 
2858
        if (*textPtr == '\0') {
 
2859
                return;
 
2860
        }
 
2861
        Item_TextColor(item, &color);
 
2862
        Item_SetTextExtents(item, &width, &height, textPtr);
 
2863
 
 
2864
        y = item->textaligny;
 
2865
        len = 0;
 
2866
        buff[0] = '\0';
 
2867
        newLine = 0;
 
2868
        newLineWidth = 0;
 
2869
        p = textPtr;
 
2870
        while (p) {
 
2871
                if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\0') {
 
2872
                        newLine = len;
 
2873
                        newLinePtr = p+1;
 
2874
                        newLineWidth = textWidth;
 
2875
                }
 
2876
                textWidth = DC->textWidth(buff, item->textscale, 0);
 
2877
                if ( (newLine && textWidth > item->window.rect.w) || *p == '\n' || *p == '\0') {
 
2878
                        if (len) {
 
2879
                                if (item->textalignment == ITEM_ALIGN_LEFT) {
 
2880
                                        item->textRect.x = item->textalignx;
 
2881
                                } else if (item->textalignment == ITEM_ALIGN_RIGHT) {
 
2882
                                        item->textRect.x = item->textalignx - newLineWidth;
 
2883
                                } else if (item->textalignment == ITEM_ALIGN_CENTER) {
 
2884
                                        item->textRect.x = item->textalignx - newLineWidth / 2;
 
2885
                                }
 
2886
                                item->textRect.y = y;
 
2887
                                ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
 
2888
                                //
 
2889
                                buff[newLine] = '\0';
 
2890
                                DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, buff, 0, 0, item->textStyle);
 
2891
                        }
 
2892
                        if (*p == '\0') {
 
2893
                                break;
 
2894
                        }
 
2895
                        //
 
2896
                        y += height + 5;
 
2897
                        p = newLinePtr;
 
2898
                        len = 0;
 
2899
                        newLine = 0;
 
2900
                        newLineWidth = 0;
 
2901
                        continue;
 
2902
                }
 
2903
                buff[len++] = *p++;
 
2904
                buff[len] = '\0';
 
2905
        }
 
2906
}
 
2907
 
 
2908
void Item_Text_Wrapped_Paint(itemDef_t *item) {
 
2909
        char text[1024];
 
2910
        const char *p, *start, *textPtr;
 
2911
        char buff[1024];
 
2912
        int width, height;
 
2913
        float x, y;
 
2914
        vec4_t color;
 
2915
 
 
2916
        // now paint the text and/or any optional images
 
2917
        // default to left
 
2918
 
 
2919
        if (item->text == NULL) {
 
2920
                if (item->cvar == NULL) {
 
2921
                        return;
 
2922
                }
 
2923
                else {
 
2924
                        DC->getCVarString(item->cvar, text, sizeof(text));
 
2925
                        textPtr = text;
 
2926
                }
 
2927
        }
 
2928
        else {
 
2929
                textPtr = item->text;
 
2930
        }
 
2931
        if (*textPtr == '\0') {
 
2932
                return;
 
2933
        }
 
2934
 
 
2935
        Item_TextColor(item, &color);
 
2936
        Item_SetTextExtents(item, &width, &height, textPtr);
 
2937
 
 
2938
        x = item->textRect.x;
 
2939
        y = item->textRect.y;
 
2940
        start = textPtr;
 
2941
        p = strchr(textPtr, '\r');
 
2942
        while (p && *p) {
 
2943
                strncpy(buff, start, p-start+1);
 
2944
                buff[p-start] = '\0';
 
2945
                DC->drawText(x, y, item->textscale, color, buff, 0, 0, item->textStyle);
 
2946
                y += height + 5;
 
2947
                start += p - start + 1;
 
2948
                p = strchr(p+1, '\r');
 
2949
        }
 
2950
        DC->drawText(x, y, item->textscale, color, start, 0, 0, item->textStyle);
 
2951
}
 
2952
 
 
2953
void Item_Text_Paint(itemDef_t *item) {
 
2954
        char text[1024];
 
2955
        const char *textPtr;
 
2956
        int height, width;
 
2957
        vec4_t color;
 
2958
 
 
2959
        if (item->window.flags & WINDOW_WRAPPED) {
 
2960
                Item_Text_Wrapped_Paint(item);
 
2961
                return;
 
2962
        }
 
2963
        if (item->window.flags & WINDOW_AUTOWRAPPED) {
 
2964
                Item_Text_AutoWrapped_Paint(item);
 
2965
                return;
 
2966
        }
 
2967
 
 
2968
        if (item->text == NULL) {
 
2969
                if (item->cvar == NULL) {
 
2970
                        return;
 
2971
                }
 
2972
                else {
 
2973
                        DC->getCVarString(item->cvar, text, sizeof(text));
 
2974
                        textPtr = text;
 
2975
                }
 
2976
        }
 
2977
        else {
 
2978
                textPtr = item->text;
 
2979
        }
 
2980
 
 
2981
        // this needs to go here as it sets extents for cvar types as well
 
2982
        Item_SetTextExtents(item, &width, &height, textPtr);
 
2983
 
 
2984
        if (*textPtr == '\0') {
 
2985
                return;
 
2986
        }
 
2987
 
 
2988
 
 
2989
        Item_TextColor(item, &color);
 
2990
 
 
2991
        //FIXME: this is a fucking mess
 
2992
/*
 
2993
        adjust = 0;
 
2994
        if (item->textStyle == ITEM_TEXTSTYLE_OUTLINED || item->textStyle == ITEM_TEXTSTYLE_OUTLINESHADOWED) {
 
2995
                adjust = 0.5;
 
2996
        }
 
2997
 
 
2998
        if (item->textStyle == ITEM_TEXTSTYLE_SHADOWED || item->textStyle == ITEM_TEXTSTYLE_OUTLINESHADOWED) {
 
2999
                Fade(&item->window.flags, &DC->Assets.shadowColor[3], DC->Assets.fadeClamp, &item->window.nextTime, DC->Assets.fadeCycle, qfalse);
 
3000
                DC->drawText(item->textRect.x + DC->Assets.shadowX, item->textRect.y + DC->Assets.shadowY, item->textscale, DC->Assets.shadowColor, textPtr, adjust);
 
3001
        }
 
3002
*/
 
3003
 
 
3004
 
 
3005
//      if (item->textStyle == ITEM_TEXTSTYLE_OUTLINED || item->textStyle == ITEM_TEXTSTYLE_OUTLINESHADOWED) {
 
3006
//              Fade(&item->window.flags, &item->window.outlineColor[3], DC->Assets.fadeClamp, &item->window.nextTime, DC->Assets.fadeCycle, qfalse);
 
3007
//              /*
 
3008
//              Text_Paint(item->textRect.x-1, item->textRect.y-1, item->textscale, item->window.foreColor, textPtr, adjust);
 
3009
//              Text_Paint(item->textRect.x, item->textRect.y-1, item->textscale, item->window.foreColor, textPtr, adjust);
 
3010
//              Text_Paint(item->textRect.x+1, item->textRect.y-1, item->textscale, item->window.foreColor, textPtr, adjust);
 
3011
//              Text_Paint(item->textRect.x-1, item->textRect.y, item->textscale, item->window.foreColor, textPtr, adjust);
 
3012
//              Text_Paint(item->textRect.x+1, item->textRect.y, item->textscale, item->window.foreColor, textPtr, adjust);
 
3013
//              Text_Paint(item->textRect.x-1, item->textRect.y+1, item->textscale, item->window.foreColor, textPtr, adjust);
 
3014
//              Text_Paint(item->textRect.x, item->textRect.y+1, item->textscale, item->window.foreColor, textPtr, adjust);
 
3015
//              Text_Paint(item->textRect.x+1, item->textRect.y+1, item->textscale, item->window.foreColor, textPtr, adjust);
 
3016
//              */
 
3017
//              DC->drawText(item->textRect.x - 1, item->textRect.y + 1, item->textscale * 1.02, item->window.outlineColor, textPtr, adjust);
 
3018
//      }
 
3019
 
 
3020
        DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, textPtr, 0, 0, item->textStyle);
 
3021
}
 
3022
 
 
3023
 
 
3024
 
 
3025
//float                 trap_Cvar_VariableValue( const char *var_name );
 
3026
//void                  trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
 
3027
 
 
3028
void Item_TextField_Paint(itemDef_t *item) {
 
3029
        char buff[1024];
 
3030
        vec4_t newColor, lowLight;
 
3031
        int offset;
 
3032
        menuDef_t *parent = (menuDef_t*)item->parent;
 
3033
        editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
 
3034
 
 
3035
        Item_Text_Paint(item);
 
3036
 
 
3037
        buff[0] = '\0';
 
3038
 
 
3039
        if (item->cvar) {
 
3040
                DC->getCVarString(item->cvar, buff, sizeof(buff));
 
3041
        } 
 
3042
 
 
3043
        parent = (menuDef_t*)item->parent;
 
3044
 
 
3045
        if (item->window.flags & WINDOW_HASFOCUS) {
 
3046
                lowLight[0] = 0.8 * parent->focusColor[0]; 
 
3047
                lowLight[1] = 0.8 * parent->focusColor[1]; 
 
3048
                lowLight[2] = 0.8 * parent->focusColor[2]; 
 
3049
                lowLight[3] = 0.8 * parent->focusColor[3]; 
 
3050
                LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
3051
        } else {
 
3052
                memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
 
3053
        }
 
3054
 
 
3055
        offset = (item->text && *item->text) ? 8 : 0;
 
3056
        if (item->window.flags & WINDOW_HASFOCUS && g_editingField) {
 
3057
                char cursor = DC->getOverstrikeMode() ? '_' : '|';
 
3058
                DC->drawTextWithCursor(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, item->cursorPos - editPtr->paintOffset , cursor, editPtr->maxPaintChars, item->textStyle);
 
3059
        } else {
 
3060
                DC->drawText(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, 0, editPtr->maxPaintChars, item->textStyle);
 
3061
        }
 
3062
 
 
3063
}
 
3064
 
 
3065
void Item_YesNo_Paint(itemDef_t *item) {
 
3066
        vec4_t newColor, lowLight;
 
3067
        float value;
 
3068
        menuDef_t *parent = (menuDef_t*)item->parent;
 
3069
 
 
3070
        value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
 
3071
 
 
3072
        if (item->window.flags & WINDOW_HASFOCUS) {
 
3073
                lowLight[0] = 0.8 * parent->focusColor[0]; 
 
3074
                lowLight[1] = 0.8 * parent->focusColor[1]; 
 
3075
                lowLight[2] = 0.8 * parent->focusColor[2]; 
 
3076
                lowLight[3] = 0.8 * parent->focusColor[3]; 
 
3077
                LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
3078
        } else {
 
3079
                memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
 
3080
        }
 
3081
 
 
3082
        if (item->text) {
 
3083
                Item_Text_Paint(item);
 
3084
                DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
 
3085
        } else {
 
3086
                DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "Yes" : "No", 0, 0, item->textStyle);
 
3087
        }
 
3088
}
 
3089
 
 
3090
void Item_Multi_Paint(itemDef_t *item) {
 
3091
        vec4_t newColor, lowLight;
 
3092
        const char *text = "";
 
3093
        menuDef_t *parent = (menuDef_t*)item->parent;
 
3094
 
 
3095
        if (item->window.flags & WINDOW_HASFOCUS) {
 
3096
                lowLight[0] = 0.8 * parent->focusColor[0]; 
 
3097
                lowLight[1] = 0.8 * parent->focusColor[1]; 
 
3098
                lowLight[2] = 0.8 * parent->focusColor[2]; 
 
3099
                lowLight[3] = 0.8 * parent->focusColor[3]; 
 
3100
                LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
3101
        } else {
 
3102
                memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
 
3103
        }
 
3104
 
 
3105
        text = Item_Multi_Setting(item);
 
3106
 
 
3107
        if (item->text) {
 
3108
                Item_Text_Paint(item);
 
3109
                DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
 
3110
        } else {
 
3111
                DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle);
 
3112
        }
 
3113
}
 
3114
 
 
3115
 
 
3116
typedef struct {
 
3117
        char    *command;
 
3118
        int             id;
 
3119
        int             defaultbind1;
 
3120
        int             defaultbind2;
 
3121
        int             bind1;
 
3122
        int             bind2;
 
3123
} bind_t;
 
3124
 
 
3125
typedef struct
 
3126
{
 
3127
        char*   name;
 
3128
        float   defaultvalue;
 
3129
        float   value;  
 
3130
} configcvar_t;
 
3131
 
 
3132
 
 
3133
static bind_t g_bindings[] = 
 
3134
{
 
3135
        {"+scores",                      K_TAB,                         -1,             -1, -1},
 
3136
        {"+button2",             K_ENTER,                       -1,             -1, -1},
 
3137
        {"+speed",                       K_SHIFT,                       -1,             -1,     -1},
 
3138
        {"+forward",             K_UPARROW,             -1,             -1, -1},
 
3139
        {"+back",                        K_DOWNARROW,   -1,             -1, -1},
 
3140
        {"+moveleft",    ',',                                   -1,             -1, -1},
 
3141
        {"+moveright",   '.',                                   -1,             -1, -1},
 
3142
        {"+moveup",                      K_SPACE,                       -1,             -1, -1},
 
3143
        {"+movedown",            'c',                                   -1,             -1, -1},
 
3144
        {"+left",                        K_LEFTARROW,   -1,             -1, -1},
 
3145
        {"+right",                       K_RIGHTARROW,  -1,             -1, -1},
 
3146
        {"+strafe",              K_ALT,                         -1,             -1, -1},
 
3147
        {"+lookup",              K_PGDN,                                -1,             -1, -1},
 
3148
        {"+lookdown",    K_DEL,                         -1,             -1, -1},
 
3149
        {"+mlook",                       '/',                                   -1,             -1, -1},
 
3150
        {"centerview",   K_END,                         -1,             -1, -1},
 
3151
        {"+zoom",                        -1,                                            -1,             -1, -1},
 
3152
        {"weapon 1",             '1',                                   -1,             -1, -1},
 
3153
        {"weapon 2",             '2',                                   -1,             -1, -1},
 
3154
        {"weapon 3",             '3',                                   -1,             -1, -1},
 
3155
        {"weapon 4",             '4',                                   -1,             -1, -1},
 
3156
        {"weapon 5",             '5',                                   -1,             -1, -1},
 
3157
        {"weapon 6",             '6',                                   -1,             -1, -1},
 
3158
        {"weapon 7",             '7',                                   -1,             -1, -1},
 
3159
        {"weapon 8",             '8',                                   -1,             -1, -1},
 
3160
        {"weapon 9",             '9',                                   -1,             -1, -1},
 
3161
        {"weapon 10",            '0',                                   -1,             -1, -1},
 
3162
        {"weapon 11",            -1,                                    -1,             -1, -1},
 
3163
        {"weapon 12",            -1,                                    -1,             -1, -1},
 
3164
        {"weapon 13",            -1,                                    -1,             -1, -1},
 
3165
        {"+attack",              K_CTRL,                                -1,             -1, -1},
 
3166
        {"weapprev",             '[',                                   -1,             -1, -1},
 
3167
        {"weapnext",             ']',                                   -1,             -1, -1},
 
3168
        {"+button3",             K_MOUSE3,                      -1,             -1, -1},
 
3169
        {"+button4",             K_MOUSE4,                      -1,             -1, -1},
 
3170
        {"prevTeamMember", 'w',                                 -1,             -1, -1},
 
3171
        {"nextTeamMember", 'r',                                 -1,             -1, -1},
 
3172
        {"nextOrder", 't',                                      -1,             -1, -1},
 
3173
        {"confirmOrder", 'y',                                   -1,             -1, -1},
 
3174
        {"denyOrder", 'n',                                      -1,             -1, -1},
 
3175
        {"taskOffense", 'o',                                    -1,             -1, -1},
 
3176
        {"taskDefense", 'd',                                    -1,             -1, -1},
 
3177
        {"taskPatrol", 'p',                                     -1,             -1, -1},
 
3178
        {"taskCamp", 'c',                                       -1,             -1, -1},
 
3179
        {"taskFollow", 'f',                                     -1,             -1, -1},
 
3180
        {"taskRetrieve", 'v',                                   -1,             -1, -1},
 
3181
        {"taskEscort", 'e',                                     -1,             -1, -1},
 
3182
        {"taskOwnFlag", 'i',                                    -1,             -1, -1},
 
3183
        {"taskSuicide", 'k',                                    -1,             -1, -1},
 
3184
        {"tauntKillInsult", K_F1,                       -1,             -1, -1},
 
3185
        {"tauntPraise", K_F2,                   -1,             -1, -1},
 
3186
        {"tauntTaunt", K_F3,                    -1,             -1, -1},
 
3187
        {"tauntDeathInsult", K_F4,                      -1,             -1, -1},
 
3188
        {"tauntGauntlet", K_F5,                 -1,             -1, -1},
 
3189
        {"scoresUp", K_KP_PGUP,                 -1,             -1, -1},
 
3190
        {"scoresDown", K_KP_PGDN,                       -1,             -1, -1},
 
3191
        // bk001205 - this one below was:  '-1' 
 
3192
        {"messagemode",  -1,                                    -1,             -1, -1},
 
3193
        {"messagemode2", -1,                                            -1,             -1, -1},
 
3194
        {"messagemode3", -1,                                            -1,             -1, -1},
 
3195
        {"messagemode4", -1,                                            -1,             -1, -1}
 
3196
};
 
3197
 
 
3198
 
 
3199
static const int g_bindCount = sizeof(g_bindings) / sizeof(bind_t);
 
3200
 
 
3201
#ifndef MISSIONPACK // bk001206
 
3202
static configcvar_t g_configcvars[] =
 
3203
{
 
3204
        {"cl_run",                      0,                                      0},
 
3205
        {"m_pitch",                     0,                                      0},
 
3206
        {"cg_autoswitch",       0,                                      0},
 
3207
        {"sensitivity",         0,                                      0},
 
3208
        {"in_joystick",         0,                                      0},
 
3209
        {"joy_threshold",       0,                                      0},
 
3210
        {"m_filter",            0,                                      0},
 
3211
        {"cl_freelook",         0,                                      0},
 
3212
        {NULL,                          0,                                      0}
 
3213
};
 
3214
#endif
 
3215
 
 
3216
/*
 
3217
=================
 
3218
Controls_GetKeyAssignment
 
3219
=================
 
3220
*/
 
3221
static void Controls_GetKeyAssignment (char *command, int *twokeys)
 
3222
{
 
3223
        int             count;
 
3224
        int             j;
 
3225
        char    b[256];
 
3226
 
 
3227
        twokeys[0] = twokeys[1] = -1;
 
3228
        count = 0;
 
3229
 
 
3230
        for ( j = 0; j < 256; j++ )
 
3231
        {
 
3232
                DC->getBindingBuf( j, b, 256 );
 
3233
                if ( *b == 0 ) {
 
3234
                        continue;
 
3235
                }
 
3236
                if ( !Q_stricmp( b, command ) ) {
 
3237
                        twokeys[count] = j;
 
3238
                        count++;
 
3239
                        if (count == 2) {
 
3240
                                break;
 
3241
                        }
 
3242
                }
 
3243
        }
 
3244
}
 
3245
 
 
3246
/*
 
3247
=================
 
3248
Controls_GetConfig
 
3249
=================
 
3250
*/
 
3251
void Controls_GetConfig( void )
 
3252
{
 
3253
        int             i;
 
3254
        int             twokeys[2];
 
3255
 
 
3256
        // iterate each command, get its numeric binding
 
3257
        for (i=0; i < g_bindCount; i++)
 
3258
        {
 
3259
 
 
3260
                Controls_GetKeyAssignment(g_bindings[i].command, twokeys);
 
3261
 
 
3262
                g_bindings[i].bind1 = twokeys[0];
 
3263
                g_bindings[i].bind2 = twokeys[1];
 
3264
        }
 
3265
 
 
3266
        //s_controls.invertmouse.curvalue  = DC->getCVarValue( "m_pitch" ) < 0;
 
3267
        //s_controls.smoothmouse.curvalue  = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "m_filter" ) );
 
3268
        //s_controls.alwaysrun.curvalue    = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_run" ) );
 
3269
        //s_controls.autoswitch.curvalue   = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cg_autoswitch" ) );
 
3270
        //s_controls.sensitivity.curvalue  = UI_ClampCvar( 2, 30, Controls_GetCvarValue( "sensitivity" ) );
 
3271
        //s_controls.joyenable.curvalue    = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "in_joystick" ) );
 
3272
        //s_controls.joythreshold.curvalue = UI_ClampCvar( 0.05, 0.75, Controls_GetCvarValue( "joy_threshold" ) );
 
3273
        //s_controls.freelook.curvalue     = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_freelook" ) );
 
3274
}
 
3275
 
 
3276
/*
 
3277
=================
 
3278
Controls_SetConfig
 
3279
=================
 
3280
*/
 
3281
void Controls_SetConfig(qboolean restart)
 
3282
{
 
3283
        int             i;
 
3284
 
 
3285
        // iterate each command, get its numeric binding
 
3286
        for (i=0; i < g_bindCount; i++)
 
3287
        {
 
3288
 
 
3289
                if (g_bindings[i].bind1 != -1)
 
3290
                {       
 
3291
                        DC->setBinding( g_bindings[i].bind1, g_bindings[i].command );
 
3292
 
 
3293
                        if (g_bindings[i].bind2 != -1)
 
3294
                                DC->setBinding( g_bindings[i].bind2, g_bindings[i].command );
 
3295
                }
 
3296
        }
 
3297
 
 
3298
        //if ( s_controls.invertmouse.curvalue )
 
3299
        //      DC->setCVar("m_pitch", va("%f),-fabs( DC->getCVarValue( "m_pitch" ) ) );
 
3300
        //else
 
3301
        //      trap_Cvar_SetValue( "m_pitch", fabs( trap_Cvar_VariableValue( "m_pitch" ) ) );
 
3302
 
 
3303
        //trap_Cvar_SetValue( "m_filter", s_controls.smoothmouse.curvalue );
 
3304
        //trap_Cvar_SetValue( "cl_run", s_controls.alwaysrun.curvalue );
 
3305
        //trap_Cvar_SetValue( "cg_autoswitch", s_controls.autoswitch.curvalue );
 
3306
        //trap_Cvar_SetValue( "sensitivity", s_controls.sensitivity.curvalue );
 
3307
        //trap_Cvar_SetValue( "in_joystick", s_controls.joyenable.curvalue );
 
3308
        //trap_Cvar_SetValue( "joy_threshold", s_controls.joythreshold.curvalue );
 
3309
        //trap_Cvar_SetValue( "cl_freelook", s_controls.freelook.curvalue );
 
3310
        DC->executeText(EXEC_APPEND, "in_restart\n");
 
3311
        //trap_Cmd_ExecuteText( EXEC_APPEND, "in_restart\n" );
 
3312
}
 
3313
 
 
3314
/*
 
3315
=================
 
3316
Controls_SetDefaults
 
3317
=================
 
3318
*/
 
3319
void Controls_SetDefaults( void )
 
3320
{
 
3321
        int     i;
 
3322
 
 
3323
        // iterate each command, set its default binding
 
3324
  for (i=0; i < g_bindCount; i++)
 
3325
        {
 
3326
                g_bindings[i].bind1 = g_bindings[i].defaultbind1;
 
3327
                g_bindings[i].bind2 = g_bindings[i].defaultbind2;
 
3328
        }
 
3329
 
 
3330
        //s_controls.invertmouse.curvalue  = Controls_GetCvarDefault( "m_pitch" ) < 0;
 
3331
        //s_controls.smoothmouse.curvalue  = Controls_GetCvarDefault( "m_filter" );
 
3332
        //s_controls.alwaysrun.curvalue    = Controls_GetCvarDefault( "cl_run" );
 
3333
        //s_controls.autoswitch.curvalue   = Controls_GetCvarDefault( "cg_autoswitch" );
 
3334
        //s_controls.sensitivity.curvalue  = Controls_GetCvarDefault( "sensitivity" );
 
3335
        //s_controls.joyenable.curvalue    = Controls_GetCvarDefault( "in_joystick" );
 
3336
        //s_controls.joythreshold.curvalue = Controls_GetCvarDefault( "joy_threshold" );
 
3337
        //s_controls.freelook.curvalue     = Controls_GetCvarDefault( "cl_freelook" );
 
3338
}
 
3339
 
 
3340
int BindingIDFromName(const char *name) {
 
3341
        int i;
 
3342
  for (i=0; i < g_bindCount; i++)
 
3343
        {
 
3344
                if (Q_stricmp(name, g_bindings[i].command) == 0) {
 
3345
                        return i;
 
3346
                }
 
3347
        }
 
3348
        return -1;
 
3349
}
 
3350
 
 
3351
char g_nameBind1[32];
 
3352
char g_nameBind2[32];
 
3353
 
 
3354
void BindingFromName(const char *cvar) {
 
3355
        int     i, b1, b2;
 
3356
 
 
3357
        // iterate each command, set its default binding
 
3358
        for (i=0; i < g_bindCount; i++)
 
3359
        {
 
3360
                if (Q_stricmp(cvar, g_bindings[i].command) == 0) {
 
3361
                        b1 = g_bindings[i].bind1;
 
3362
                        if (b1 == -1) {
 
3363
                                break;
 
3364
                        }
 
3365
                                DC->keynumToStringBuf( b1, g_nameBind1, 32 );
 
3366
                                Q_strupr(g_nameBind1);
 
3367
 
 
3368
                                b2 = g_bindings[i].bind2;
 
3369
                                if (b2 != -1)
 
3370
                                {
 
3371
                                        DC->keynumToStringBuf( b2, g_nameBind2, 32 );
 
3372
                                        Q_strupr(g_nameBind2);
 
3373
                                        strcat( g_nameBind1, " or " );
 
3374
                                        strcat( g_nameBind1, g_nameBind2 );
 
3375
                                }
 
3376
                        return;
 
3377
                }
 
3378
        }
 
3379
        strcpy(g_nameBind1, "???");
 
3380
}
 
3381
 
 
3382
void Item_Slider_Paint(itemDef_t *item) {
 
3383
        vec4_t newColor, lowLight;
 
3384
        float x, y, value;
 
3385
        menuDef_t *parent = (menuDef_t*)item->parent;
 
3386
 
 
3387
        value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
 
3388
 
 
3389
        if (item->window.flags & WINDOW_HASFOCUS) {
 
3390
                lowLight[0] = 0.8 * parent->focusColor[0]; 
 
3391
                lowLight[1] = 0.8 * parent->focusColor[1]; 
 
3392
                lowLight[2] = 0.8 * parent->focusColor[2]; 
 
3393
                lowLight[3] = 0.8 * parent->focusColor[3]; 
 
3394
                LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
3395
        } else {
 
3396
                memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
 
3397
        }
 
3398
 
 
3399
        y = item->window.rect.y;
 
3400
        if (item->text) {
 
3401
                Item_Text_Paint(item);
 
3402
                x = item->textRect.x + item->textRect.w + 8;
 
3403
        } else {
 
3404
                x = item->window.rect.x;
 
3405
        }
 
3406
        DC->setColor(newColor);
 
3407
        DC->drawHandlePic( x, y, SLIDER_WIDTH, SLIDER_HEIGHT, DC->Assets.sliderBar );
 
3408
 
 
3409
        x = Item_Slider_ThumbPosition(item);
 
3410
        DC->drawHandlePic( x - (SLIDER_THUMB_WIDTH / 2), y - 2, SLIDER_THUMB_WIDTH, SLIDER_THUMB_HEIGHT, DC->Assets.sliderThumb );
 
3411
 
 
3412
}
 
3413
 
 
3414
void Item_Bind_Paint(itemDef_t *item) {
 
3415
        vec4_t newColor, lowLight;
 
3416
        float value;
 
3417
        int maxChars = 0;
 
3418
        menuDef_t *parent = (menuDef_t*)item->parent;
 
3419
        editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
 
3420
        if (editPtr) {
 
3421
                maxChars = editPtr->maxPaintChars;
 
3422
        }
 
3423
 
 
3424
        value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
 
3425
 
 
3426
        if (item->window.flags & WINDOW_HASFOCUS) {
 
3427
                if (g_bindItem == item) {
 
3428
                        lowLight[0] = 0.8f * 1.0f;
 
3429
                        lowLight[1] = 0.8f * 0.0f;
 
3430
                        lowLight[2] = 0.8f * 0.0f;
 
3431
                        lowLight[3] = 0.8f * 1.0f;
 
3432
                } else {
 
3433
                        lowLight[0] = 0.8f * parent->focusColor[0]; 
 
3434
                        lowLight[1] = 0.8f * parent->focusColor[1]; 
 
3435
                        lowLight[2] = 0.8f * parent->focusColor[2]; 
 
3436
                        lowLight[3] = 0.8f * parent->focusColor[3]; 
 
3437
                }
 
3438
                LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
3439
        } else {
 
3440
                memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
 
3441
        }
 
3442
 
 
3443
        if (item->text) {
 
3444
                Item_Text_Paint(item);
 
3445
                BindingFromName(item->cvar);
 
3446
                DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, g_nameBind1, 0, maxChars, item->textStyle);
 
3447
        } else {
 
3448
                DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "FIXME" : "FIXME", 0, maxChars, item->textStyle);
 
3449
        }
 
3450
}
 
3451
 
 
3452
qboolean Display_KeyBindPending(void) {
 
3453
        return g_waitingForKey;
 
3454
}
 
3455
 
 
3456
qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down) {
 
3457
        int                     id;
 
3458
        int                     i;
 
3459
 
 
3460
        if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && !g_waitingForKey)
 
3461
        {
 
3462
                if (down && (key == K_MOUSE1 || key == K_ENTER)) {
 
3463
                        g_waitingForKey = qtrue;
 
3464
                        g_bindItem = item;
 
3465
                }
 
3466
                return qtrue;
 
3467
        }
 
3468
        else
 
3469
        {
 
3470
                if (!g_waitingForKey || g_bindItem == NULL) {
 
3471
                        return qtrue;
 
3472
                }
 
3473
 
 
3474
                if (key & K_CHAR_FLAG) {
 
3475
                        return qtrue;
 
3476
                }
 
3477
 
 
3478
                switch (key)
 
3479
                {
 
3480
                        case K_ESCAPE:
 
3481
                                g_waitingForKey = qfalse;
 
3482
                                return qtrue;
 
3483
        
 
3484
                        case K_BACKSPACE:
 
3485
                                id = BindingIDFromName(item->cvar);
 
3486
                                if (id != -1) {
 
3487
                                        g_bindings[id].bind1 = -1;
 
3488
                                        g_bindings[id].bind2 = -1;
 
3489
                                }
 
3490
                                Controls_SetConfig(qtrue);
 
3491
                                g_waitingForKey = qfalse;
 
3492
                                g_bindItem = NULL;
 
3493
                                return qtrue;
 
3494
 
 
3495
                        case '`':
 
3496
                                return qtrue;
 
3497
                }
 
3498
        }
 
3499
 
 
3500
        if (key != -1)
 
3501
        {
 
3502
 
 
3503
                for (i=0; i < g_bindCount; i++)
 
3504
                {
 
3505
 
 
3506
                        if (g_bindings[i].bind2 == key) {
 
3507
                                g_bindings[i].bind2 = -1;
 
3508
                        }
 
3509
 
 
3510
                        if (g_bindings[i].bind1 == key)
 
3511
                        {
 
3512
                                g_bindings[i].bind1 = g_bindings[i].bind2;
 
3513
                                g_bindings[i].bind2 = -1;
 
3514
                        }
 
3515
                }
 
3516
        }
 
3517
 
 
3518
 
 
3519
        id = BindingIDFromName(item->cvar);
 
3520
 
 
3521
        if (id != -1) {
 
3522
                if (key == -1) {
 
3523
                        if( g_bindings[id].bind1 != -1 ) {
 
3524
                                DC->setBinding( g_bindings[id].bind1, "" );
 
3525
                                g_bindings[id].bind1 = -1;
 
3526
                        }
 
3527
                        if( g_bindings[id].bind2 != -1 ) {
 
3528
                                DC->setBinding( g_bindings[id].bind2, "" );
 
3529
                                g_bindings[id].bind2 = -1;
 
3530
                        }
 
3531
                }
 
3532
                else if (g_bindings[id].bind1 == -1) {
 
3533
                        g_bindings[id].bind1 = key;
 
3534
                }
 
3535
                else if (g_bindings[id].bind1 != key && g_bindings[id].bind2 == -1) {
 
3536
                        g_bindings[id].bind2 = key;
 
3537
                }
 
3538
                else {
 
3539
                        DC->setBinding( g_bindings[id].bind1, "" );
 
3540
                        DC->setBinding( g_bindings[id].bind2, "" );
 
3541
                        g_bindings[id].bind1 = key;
 
3542
                        g_bindings[id].bind2 = -1;
 
3543
                }                                               
 
3544
        }
 
3545
 
 
3546
        Controls_SetConfig(qtrue);      
 
3547
        g_waitingForKey = qfalse;
 
3548
 
 
3549
        return qtrue;
 
3550
}
 
3551
 
 
3552
 
 
3553
 
 
3554
void AdjustFrom640(float *x, float *y, float *w, float *h) {
 
3555
        //*x = *x * DC->scale + DC->bias;
 
3556
        *x *= DC->xscale;
 
3557
        *y *= DC->yscale;
 
3558
        *w *= DC->xscale;
 
3559
        *h *= DC->yscale;
 
3560
}
 
3561
 
 
3562
void Item_Model_Paint(itemDef_t *item) {
 
3563
        float x, y, w, h;
 
3564
        refdef_t refdef;
 
3565
        refEntity_t             ent;
 
3566
        vec3_t                  mins, maxs, origin;
 
3567
        vec3_t                  angles;
 
3568
        modelDef_t *modelPtr = (modelDef_t*)item->typeData;
 
3569
 
 
3570
        if (modelPtr == NULL) {
 
3571
                return;
 
3572
        }
 
3573
 
 
3574
        // setup the refdef
 
3575
        memset( &refdef, 0, sizeof( refdef ) );
 
3576
        refdef.rdflags = RDF_NOWORLDMODEL;
 
3577
        AxisClear( refdef.viewaxis );
 
3578
        x = item->window.rect.x+1;
 
3579
        y = item->window.rect.y+1;
 
3580
        w = item->window.rect.w-2;
 
3581
        h = item->window.rect.h-2;
 
3582
 
 
3583
        AdjustFrom640( &x, &y, &w, &h );
 
3584
 
 
3585
        refdef.x = x;
 
3586
        refdef.y = y;
 
3587
        refdef.width = w;
 
3588
        refdef.height = h;
 
3589
 
 
3590
        DC->modelBounds( item->asset, mins, maxs );
 
3591
 
 
3592
        origin[2] = -0.5 * ( mins[2] + maxs[2] );
 
3593
        origin[1] = 0.5 * ( mins[1] + maxs[1] );
 
3594
 
 
3595
        // calculate distance so the model nearly fills the box
 
3596
        if (qtrue) {
 
3597
                float len = 0.5 * ( maxs[2] - mins[2] );                
 
3598
                origin[0] = len / 0.268;        // len / tan( fov/2 )
 
3599
                //origin[0] = len / tan(w/2);
 
3600
        } else {
 
3601
                origin[0] = item->textscale;
 
3602
        }
 
3603
        refdef.fov_x = (modelPtr->fov_x) ? modelPtr->fov_x : w;
 
3604
        refdef.fov_y = (modelPtr->fov_y) ? modelPtr->fov_y : h;
 
3605
 
 
3606
        //refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f);
 
3607
        //xx = refdef.width / tan( refdef.fov_x / 360 * M_PI );
 
3608
        //refdef.fov_y = atan2( refdef.height, xx );
 
3609
        //refdef.fov_y *= ( 360 / M_PI );
 
3610
 
 
3611
        DC->clearScene();
 
3612
 
 
3613
        refdef.time = DC->realTime;
 
3614
 
 
3615
        // add the model
 
3616
 
 
3617
        memset( &ent, 0, sizeof(ent) );
 
3618
 
 
3619
        //adjust = 5.0 * sin( (float)uis.realtime / 500 );
 
3620
        //adjust = 360 % (int)((float)uis.realtime / 1000);
 
3621
        //VectorSet( angles, 0, 0, 1 );
 
3622
 
 
3623
        // use item storage to track
 
3624
        if (modelPtr->rotationSpeed) {
 
3625
                if (DC->realTime > item->window.nextTime) {
 
3626
                        item->window.nextTime = DC->realTime + modelPtr->rotationSpeed;
 
3627
                        modelPtr->angle = (int)(modelPtr->angle + 1) % 360;
 
3628
                }
 
3629
        }
 
3630
        VectorSet( angles, 0, modelPtr->angle, 0 );
 
3631
        AnglesToAxis( angles, ent.axis );
 
3632
 
 
3633
        ent.hModel = item->asset;
 
3634
        VectorCopy( origin, ent.origin );
 
3635
        VectorCopy( origin, ent.lightingOrigin );
 
3636
        ent.renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;
 
3637
        VectorCopy( ent.origin, ent.oldorigin );
 
3638
 
 
3639
        DC->addRefEntityToScene( &ent );
 
3640
        DC->renderScene( &refdef );
 
3641
 
 
3642
}
 
3643
 
 
3644
 
 
3645
void Item_Image_Paint(itemDef_t *item) {
 
3646
        if (item == NULL) {
 
3647
                return;
 
3648
        }
 
3649
        DC->drawHandlePic(item->window.rect.x+1, item->window.rect.y+1, item->window.rect.w-2, item->window.rect.h-2, item->asset);
 
3650
}
 
3651
 
 
3652
void Item_ListBox_Paint(itemDef_t *item) {
 
3653
        float x, y, size, count, i, thumb;
 
3654
        qhandle_t image;
 
3655
        qhandle_t optionalImage;
 
3656
        listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
 
3657
 
 
3658
        // the listbox is horizontal or vertical and has a fixed size scroll bar going either direction
 
3659
        // elements are enumerated from the DC and either text or image handles are acquired from the DC as well
 
3660
        // textscale is used to size the text, textalignx and textaligny are used to size image elements
 
3661
        // there is no clipping available so only the last completely visible item is painted
 
3662
        count = DC->feederCount(item->special);
 
3663
        // default is vertical if horizontal flag is not here
 
3664
        if (item->window.flags & WINDOW_HORIZONTAL) {
 
3665
                // draw scrollbar in bottom of the window
 
3666
                // bar
 
3667
                x = item->window.rect.x + 1;
 
3668
                y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE - 1;
 
3669
                DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowLeft);
 
3670
                x += SCROLLBAR_SIZE - 1;
 
3671
                size = item->window.rect.w - (SCROLLBAR_SIZE * 2);
 
3672
                DC->drawHandlePic(x, y, size+1, SCROLLBAR_SIZE, DC->Assets.scrollBar);
 
3673
                x += size - 1;
 
3674
                DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowRight);
 
3675
                // thumb
 
3676
                thumb = Item_ListBox_ThumbDrawPosition(item);//Item_ListBox_ThumbPosition(item);
 
3677
                if (thumb > x - SCROLLBAR_SIZE - 1) {
 
3678
                        thumb = x - SCROLLBAR_SIZE - 1;
 
3679
                }
 
3680
                DC->drawHandlePic(thumb, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
 
3681
                //
 
3682
                listPtr->endPos = listPtr->startPos;
 
3683
                size = item->window.rect.w - 2;
 
3684
                // items
 
3685
                // size contains max available space
 
3686
                if (listPtr->elementStyle == LISTBOX_IMAGE) {
 
3687
                        // fit = 0;
 
3688
                        x = item->window.rect.x + 1;
 
3689
                        y = item->window.rect.y + 1;
 
3690
                        for (i = listPtr->startPos; i < count; i++) {
 
3691
                                // always draw at least one
 
3692
                                // which may overdraw the box if it is too small for the element
 
3693
                                image = DC->feederItemImage(item->special, i);
 
3694
                                if (image) {
 
3695
                                        DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
 
3696
                                }
 
3697
 
 
3698
                                if (i == item->cursorPos) {
 
3699
                                        DC->drawRect(x, y, listPtr->elementWidth-1, listPtr->elementHeight-1, item->window.borderSize, item->window.borderColor);
 
3700
                                }
 
3701
 
 
3702
                                size -= listPtr->elementWidth;
 
3703
                                if (size < listPtr->elementWidth) {
 
3704
                                        listPtr->drawPadding = size; //listPtr->elementWidth - size;
 
3705
                                        break;
 
3706
                                }
 
3707
                                x += listPtr->elementWidth;
 
3708
                                listPtr->endPos++;
 
3709
                                // fit++;
 
3710
                        }
 
3711
                } else {
 
3712
                        //
 
3713
                }
 
3714
        } else {
 
3715
                // draw scrollbar to right side of the window
 
3716
                x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE - 1;
 
3717
                y = item->window.rect.y + 1;
 
3718
                DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowUp);
 
3719
                y += SCROLLBAR_SIZE - 1;
 
3720
 
 
3721
                listPtr->endPos = listPtr->startPos;
 
3722
                size = item->window.rect.h - (SCROLLBAR_SIZE * 2);
 
3723
                DC->drawHandlePic(x, y, SCROLLBAR_SIZE, size+1, DC->Assets.scrollBar);
 
3724
                y += size - 1;
 
3725
                DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowDown);
 
3726
                // thumb
 
3727
                thumb = Item_ListBox_ThumbDrawPosition(item);//Item_ListBox_ThumbPosition(item);
 
3728
                if (thumb > y - SCROLLBAR_SIZE - 1) {
 
3729
                        thumb = y - SCROLLBAR_SIZE - 1;
 
3730
                }
 
3731
                DC->drawHandlePic(x, thumb, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
 
3732
 
 
3733
                // adjust size for item painting
 
3734
                size = item->window.rect.h - 2;
 
3735
                if (listPtr->elementStyle == LISTBOX_IMAGE) {
 
3736
                        // fit = 0;
 
3737
                        x = item->window.rect.x + 1;
 
3738
                        y = item->window.rect.y + 1;
 
3739
                        for (i = listPtr->startPos; i < count; i++) {
 
3740
                                // always draw at least one
 
3741
                                // which may overdraw the box if it is too small for the element
 
3742
                                image = DC->feederItemImage(item->special, i);
 
3743
                                if (image) {
 
3744
                                        DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
 
3745
                                }
 
3746
 
 
3747
                                if (i == item->cursorPos) {
 
3748
                                        DC->drawRect(x, y, listPtr->elementWidth - 1, listPtr->elementHeight - 1, item->window.borderSize, item->window.borderColor);
 
3749
                                }
 
3750
 
 
3751
                                listPtr->endPos++;
 
3752
                                size -= listPtr->elementWidth;
 
3753
                                if (size < listPtr->elementHeight) {
 
3754
                                        listPtr->drawPadding = listPtr->elementHeight - size;
 
3755
                                        break;
 
3756
                                }
 
3757
                                y += listPtr->elementHeight;
 
3758
                                // fit++;
 
3759
                        }
 
3760
                } else {
 
3761
                        x = item->window.rect.x + 1;
 
3762
                        y = item->window.rect.y + 1;
 
3763
                        for (i = listPtr->startPos; i < count; i++) {
 
3764
                                const char *text;
 
3765
                                // always draw at least one
 
3766
                                // which may overdraw the box if it is too small for the element
 
3767
 
 
3768
                                if (listPtr->numColumns > 0) {
 
3769
                                        int j;
 
3770
                                        for (j = 0; j < listPtr->numColumns; j++) {
 
3771
                                                text = DC->feederItemText(item->special, i, j, &optionalImage);
 
3772
                                                if (optionalImage >= 0) {
 
3773
                                                        DC->drawHandlePic(x + 4 + listPtr->columnInfo[j].pos, y - 1 + listPtr->elementHeight / 2, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
 
3774
                                                } else if (text) {
 
3775
                                                        DC->drawText(x + 4 + listPtr->columnInfo[j].pos, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, listPtr->columnInfo[j].maxChars, item->textStyle);
 
3776
                                                }
 
3777
                                        }
 
3778
                                } else {
 
3779
                                        text = DC->feederItemText(item->special, i, 0, &optionalImage);
 
3780
                                        if (optionalImage >= 0) {
 
3781
                                                //DC->drawHandlePic(x + 4 + listPtr->elementHeight, y, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
 
3782
                                        } else if (text) {
 
3783
                                                DC->drawText(x + 4, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, 0, item->textStyle);
 
3784
                                        }
 
3785
                                }
 
3786
 
 
3787
                                if (i == item->cursorPos) {
 
3788
                                        DC->fillRect(x + 2, y + 2, item->window.rect.w - SCROLLBAR_SIZE - 4, listPtr->elementHeight, item->window.outlineColor);
 
3789
                                }
 
3790
 
 
3791
                                size -= listPtr->elementHeight;
 
3792
                                if (size < listPtr->elementHeight) {
 
3793
                                        listPtr->drawPadding = listPtr->elementHeight - size;
 
3794
                                        break;
 
3795
                                }
 
3796
                                listPtr->endPos++;
 
3797
                                y += listPtr->elementHeight;
 
3798
                                // fit++;
 
3799
                        }
 
3800
                }
 
3801
        }
 
3802
}
 
3803
 
 
3804
 
 
3805
void Item_OwnerDraw_Paint(itemDef_t *item) {
 
3806
  menuDef_t *parent;
 
3807
 
 
3808
        if (item == NULL) {
 
3809
                return;
 
3810
        }
 
3811
  parent = (menuDef_t*)item->parent;
 
3812
 
 
3813
        if (DC->ownerDrawItem) {
 
3814
                vec4_t color, lowLight;
 
3815
                menuDef_t *parent = (menuDef_t*)item->parent;
 
3816
                Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
 
3817
                memcpy(&color, &item->window.foreColor, sizeof(color));
 
3818
                if (item->numColors > 0 && DC->getValue) {
 
3819
                        // if the value is within one of the ranges then set color to that, otherwise leave at default
 
3820
                        int i;
 
3821
                        float f = DC->getValue(item->window.ownerDraw);
 
3822
                        for (i = 0; i < item->numColors; i++) {
 
3823
                                if (f >= item->colorRanges[i].low && f <= item->colorRanges[i].high) {
 
3824
                                        memcpy(&color, &item->colorRanges[i].color, sizeof(color));
 
3825
                                        break;
 
3826
                                }
 
3827
                        }
 
3828
                }
 
3829
 
 
3830
                if (item->window.flags & WINDOW_HASFOCUS) {
 
3831
                        lowLight[0] = 0.8 * parent->focusColor[0]; 
 
3832
                        lowLight[1] = 0.8 * parent->focusColor[1]; 
 
3833
                        lowLight[2] = 0.8 * parent->focusColor[2]; 
 
3834
                        lowLight[3] = 0.8 * parent->focusColor[3]; 
 
3835
                        LerpColor(parent->focusColor,lowLight,color,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
3836
                } else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1)) {
 
3837
                        lowLight[0] = 0.8 * item->window.foreColor[0]; 
 
3838
                        lowLight[1] = 0.8 * item->window.foreColor[1]; 
 
3839
                        lowLight[2] = 0.8 * item->window.foreColor[2]; 
 
3840
                        lowLight[3] = 0.8 * item->window.foreColor[3]; 
 
3841
                        LerpColor(item->window.foreColor,lowLight,color,0.5+0.5*sin(DC->realTime / PULSE_DIVISOR));
 
3842
                }
 
3843
 
 
3844
                if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
 
3845
                  memcpy(color, parent->disableColor, sizeof(vec4_t)); // bk001207 - FIXME: Com_Memcpy
 
3846
                }
 
3847
        
 
3848
                if (item->text) {
 
3849
                        Item_Text_Paint(item);
 
3850
                                if (item->text[0]) {
 
3851
                                        // +8 is an offset kludge to properly align owner draw items that have text combined with them
 
3852
                                        DC->ownerDrawItem(item->textRect.x + item->textRect.w + 8, item->window.rect.y, item->window.rect.w, item->window.rect.h, 0, item->textaligny, item->window.ownerDraw, item->window.ownerDrawFlags, item->alignment, item->special, item->textscale, color, item->window.background, item->textStyle );
 
3853
                                } else {
 
3854
                                        DC->ownerDrawItem(item->textRect.x + item->textRect.w, item->window.rect.y, item->window.rect.w, item->window.rect.h, 0, item->textaligny, item->window.ownerDraw, item->window.ownerDrawFlags, item->alignment, item->special, item->textscale, color, item->window.background, item->textStyle );
 
3855
                                }
 
3856
                        } else {
 
3857
                        DC->ownerDrawItem(item->window.rect.x, item->window.rect.y, item->window.rect.w, item->window.rect.h, item->textalignx, item->textaligny, item->window.ownerDraw, item->window.ownerDrawFlags, item->alignment, item->special, item->textscale, color, item->window.background, item->textStyle );
 
3858
                }
 
3859
        }
 
3860
}
 
3861
 
 
3862
 
 
3863
void Item_Paint(itemDef_t *item) {
 
3864
  vec4_t red;
 
3865
  menuDef_t *parent = (menuDef_t*)item->parent;
 
3866
  red[0] = red[3] = 1;
 
3867
  red[1] = red[2] = 0;
 
3868
 
 
3869
  if (item == NULL) {
 
3870
    return;
 
3871
  }
 
3872
 
 
3873
  if (item->window.flags & WINDOW_ORBITING) {
 
3874
    if (DC->realTime > item->window.nextTime) {
 
3875
      float rx, ry, a, c, s, w, h;
 
3876
      
 
3877
      item->window.nextTime = DC->realTime + item->window.offsetTime;
 
3878
      // translate
 
3879
      w = item->window.rectClient.w / 2;
 
3880
      h = item->window.rectClient.h / 2;
 
3881
      rx = item->window.rectClient.x + w - item->window.rectEffects.x;
 
3882
      ry = item->window.rectClient.y + h - item->window.rectEffects.y;
 
3883
      a = 3 * M_PI / 180;
 
3884
          c = cos(a);
 
3885
      s = sin(a);
 
3886
      item->window.rectClient.x = (rx * c - ry * s) + item->window.rectEffects.x - w;
 
3887
      item->window.rectClient.y = (rx * s + ry * c) + item->window.rectEffects.y - h;
 
3888
      Item_UpdatePosition(item);
 
3889
 
 
3890
    }
 
3891
  }
 
3892
 
 
3893
 
 
3894
  if (item->window.flags & WINDOW_INTRANSITION) {
 
3895
    if (DC->realTime > item->window.nextTime) {
 
3896
      int done = 0;
 
3897
      item->window.nextTime = DC->realTime + item->window.offsetTime;
 
3898
                        // transition the x,y
 
3899
                        if (item->window.rectClient.x == item->window.rectEffects.x) {
 
3900
                                done++;
 
3901
                        } else {
 
3902
                                if (item->window.rectClient.x < item->window.rectEffects.x) {
 
3903
                                        item->window.rectClient.x += item->window.rectEffects2.x;
 
3904
                                        if (item->window.rectClient.x > item->window.rectEffects.x) {
 
3905
                                                item->window.rectClient.x = item->window.rectEffects.x;
 
3906
                                                done++;
 
3907
                                        }
 
3908
                                } else {
 
3909
                                        item->window.rectClient.x -= item->window.rectEffects2.x;
 
3910
                                        if (item->window.rectClient.x < item->window.rectEffects.x) {
 
3911
                                                item->window.rectClient.x = item->window.rectEffects.x;
 
3912
                                                done++;
 
3913
                                        }
 
3914
                                }
 
3915
                        }
 
3916
                        if (item->window.rectClient.y == item->window.rectEffects.y) {
 
3917
                                done++;
 
3918
                        } else {
 
3919
                                if (item->window.rectClient.y < item->window.rectEffects.y) {
 
3920
                                        item->window.rectClient.y += item->window.rectEffects2.y;
 
3921
                                        if (item->window.rectClient.y > item->window.rectEffects.y) {
 
3922
                                                item->window.rectClient.y = item->window.rectEffects.y;
 
3923
                                                done++;
 
3924
                                        }
 
3925
                                } else {
 
3926
                                        item->window.rectClient.y -= item->window.rectEffects2.y;
 
3927
                                        if (item->window.rectClient.y < item->window.rectEffects.y) {
 
3928
                                                item->window.rectClient.y = item->window.rectEffects.y;
 
3929
                                                done++;
 
3930
                                        }
 
3931
                                }
 
3932
                        }
 
3933
                        if (item->window.rectClient.w == item->window.rectEffects.w) {
 
3934
                                done++;
 
3935
                        } else {
 
3936
                                if (item->window.rectClient.w < item->window.rectEffects.w) {
 
3937
                                        item->window.rectClient.w += item->window.rectEffects2.w;
 
3938
                                        if (item->window.rectClient.w > item->window.rectEffects.w) {
 
3939
                                                item->window.rectClient.w = item->window.rectEffects.w;
 
3940
                                                done++;
 
3941
                                        }
 
3942
                                } else {
 
3943
                                        item->window.rectClient.w -= item->window.rectEffects2.w;
 
3944
                                        if (item->window.rectClient.w < item->window.rectEffects.w) {
 
3945
                                                item->window.rectClient.w = item->window.rectEffects.w;
 
3946
                                                done++;
 
3947
                                        }
 
3948
                                }
 
3949
                        }
 
3950
                        if (item->window.rectClient.h == item->window.rectEffects.h) {
 
3951
                                done++;
 
3952
                        } else {
 
3953
                                if (item->window.rectClient.h < item->window.rectEffects.h) {
 
3954
                                        item->window.rectClient.h += item->window.rectEffects2.h;
 
3955
                                        if (item->window.rectClient.h > item->window.rectEffects.h) {
 
3956
                                                item->window.rectClient.h = item->window.rectEffects.h;
 
3957
                                                done++;
 
3958
                                        }
 
3959
                                } else {
 
3960
                                        item->window.rectClient.h -= item->window.rectEffects2.h;
 
3961
                                        if (item->window.rectClient.h < item->window.rectEffects.h) {
 
3962
                                                item->window.rectClient.h = item->window.rectEffects.h;
 
3963
                                                done++;
 
3964
                                        }
 
3965
                                }
 
3966
                        }
 
3967
 
 
3968
      Item_UpdatePosition(item);
 
3969
 
 
3970
      if (done == 4) {
 
3971
        item->window.flags &= ~WINDOW_INTRANSITION;
 
3972
      }
 
3973
 
 
3974
    }
 
3975
  }
 
3976
 
 
3977
        if (item->window.ownerDrawFlags && DC->ownerDrawVisible) {
 
3978
                if (!DC->ownerDrawVisible(item->window.ownerDrawFlags)) {
 
3979
                        item->window.flags &= ~WINDOW_VISIBLE;
 
3980
                } else {
 
3981
                        item->window.flags |= WINDOW_VISIBLE;
 
3982
                }
 
3983
        }
 
3984
 
 
3985
        if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE)) {
 
3986
                if (!Item_EnableShowViaCvar(item, CVAR_SHOW)) {
 
3987
                        return;
 
3988
                }
 
3989
        }
 
3990
 
 
3991
  if (item->window.flags & WINDOW_TIMEDVISIBLE) {
 
3992
 
 
3993
        }
 
3994
 
 
3995
  if (!(item->window.flags & WINDOW_VISIBLE)) {
 
3996
    return;
 
3997
  }
 
3998
 
 
3999
  // paint the rect first.. 
 
4000
  Window_Paint(&item->window, parent->fadeAmount , parent->fadeClamp, parent->fadeCycle);
 
4001
 
 
4002
  if (debugMode) {
 
4003
                vec4_t color;
 
4004
                rectDef_t *r = Item_CorrectedTextRect(item);
 
4005
    color[1] = color[3] = 1;
 
4006
    color[0] = color[2] = 0;
 
4007
    DC->drawRect(r->x, r->y, r->w, r->h, 1, color);
 
4008
  }
 
4009
 
 
4010
  //DC->drawRect(item->window.rect.x, item->window.rect.y, item->window.rect.w, item->window.rect.h, 1, red);
 
4011
 
 
4012
  switch (item->type) {
 
4013
    case ITEM_TYPE_OWNERDRAW:
 
4014
      Item_OwnerDraw_Paint(item);
 
4015
      break;
 
4016
    case ITEM_TYPE_TEXT:
 
4017
    case ITEM_TYPE_BUTTON:
 
4018
      Item_Text_Paint(item);
 
4019
      break;
 
4020
    case ITEM_TYPE_RADIOBUTTON:
 
4021
      break;
 
4022
    case ITEM_TYPE_CHECKBOX:
 
4023
      break;
 
4024
    case ITEM_TYPE_EDITFIELD:
 
4025
    case ITEM_TYPE_NUMERICFIELD:
 
4026
      Item_TextField_Paint(item);
 
4027
      break;
 
4028
    case ITEM_TYPE_COMBO:
 
4029
      break;
 
4030
    case ITEM_TYPE_LISTBOX:
 
4031
      Item_ListBox_Paint(item);
 
4032
      break;
 
4033
    //case ITEM_TYPE_IMAGE:
 
4034
    //  Item_Image_Paint(item);
 
4035
    //  break;
 
4036
    case ITEM_TYPE_MODEL:
 
4037
      Item_Model_Paint(item);
 
4038
      break;
 
4039
    case ITEM_TYPE_YESNO:
 
4040
      Item_YesNo_Paint(item);
 
4041
      break;
 
4042
    case ITEM_TYPE_MULTI:
 
4043
      Item_Multi_Paint(item);
 
4044
      break;
 
4045
    case ITEM_TYPE_BIND:
 
4046
      Item_Bind_Paint(item);
 
4047
      break;
 
4048
    case ITEM_TYPE_SLIDER:
 
4049
      Item_Slider_Paint(item);
 
4050
      break;
 
4051
    default:
 
4052
      break;
 
4053
  }
 
4054
 
 
4055
}
 
4056
 
 
4057
void Menu_Init(menuDef_t *menu) {
 
4058
        memset(menu, 0, sizeof(menuDef_t));
 
4059
        menu->cursorItem = -1;
 
4060
        menu->fadeAmount = DC->Assets.fadeAmount;
 
4061
        menu->fadeClamp = DC->Assets.fadeClamp;
 
4062
        menu->fadeCycle = DC->Assets.fadeCycle;
 
4063
        Window_Init(&menu->window);
 
4064
}
 
4065
 
 
4066
itemDef_t *Menu_GetFocusedItem(menuDef_t *menu) {
 
4067
  int i;
 
4068
  if (menu) {
 
4069
    for (i = 0; i < menu->itemCount; i++) {
 
4070
      if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
 
4071
        return menu->items[i];
 
4072
      }
 
4073
    }
 
4074
  }
 
4075
  return NULL;
 
4076
}
 
4077
 
 
4078
menuDef_t *Menu_GetFocused(void) {
 
4079
  int i;
 
4080
  for (i = 0; i < menuCount; i++) {
 
4081
    if (Menus[i].window.flags & WINDOW_HASFOCUS && Menus[i].window.flags & WINDOW_VISIBLE) {
 
4082
      return &Menus[i];
 
4083
    }
 
4084
  }
 
4085
  return NULL;
 
4086
}
 
4087
 
 
4088
void Menu_ScrollFeeder(menuDef_t *menu, int feeder, qboolean down) {
 
4089
        if (menu) {
 
4090
                int i;
 
4091
    for (i = 0; i < menu->itemCount; i++) {
 
4092
                        if (menu->items[i]->special == feeder) {
 
4093
                                Item_ListBox_HandleKey(menu->items[i], (down) ? K_DOWNARROW : K_UPARROW, qtrue, qtrue);
 
4094
                                return;
 
4095
                        }
 
4096
                }
 
4097
        }
 
4098
}
 
4099
 
 
4100
 
 
4101
 
 
4102
void Menu_SetFeederSelection(menuDef_t *menu, int feeder, int index, const char *name) {
 
4103
        if (menu == NULL) {
 
4104
                if (name == NULL) {
 
4105
                        menu = Menu_GetFocused();
 
4106
                } else {
 
4107
                        menu = Menus_FindByName(name);
 
4108
                }
 
4109
        }
 
4110
 
 
4111
        if (menu) {
 
4112
                int i;
 
4113
    for (i = 0; i < menu->itemCount; i++) {
 
4114
                        if (menu->items[i]->special == feeder) {
 
4115
                                if (index == 0) {
 
4116
                                        listBoxDef_t *listPtr = (listBoxDef_t*)menu->items[i]->typeData;
 
4117
                                        listPtr->cursorPos = 0;
 
4118
                                        listPtr->startPos = 0;
 
4119
                                }
 
4120
                                menu->items[i]->cursorPos = index;
 
4121
                                DC->feederSelection(menu->items[i]->special, menu->items[i]->cursorPos);
 
4122
                                return;
 
4123
                        }
 
4124
                }
 
4125
        }
 
4126
}
 
4127
 
 
4128
qboolean Menus_AnyFullScreenVisible(void) {
 
4129
  int i;
 
4130
  for (i = 0; i < menuCount; i++) {
 
4131
    if (Menus[i].window.flags & WINDOW_VISIBLE && Menus[i].fullScreen) {
 
4132
                        return qtrue;
 
4133
    }
 
4134
  }
 
4135
  return qfalse;
 
4136
}
 
4137
 
 
4138
menuDef_t *Menus_ActivateByName(const char *p) {
 
4139
  int i;
 
4140
  menuDef_t *m = NULL;
 
4141
        menuDef_t *focus = Menu_GetFocused();
 
4142
  for (i = 0; i < menuCount; i++) {
 
4143
    if (Q_stricmp(Menus[i].window.name, p) == 0) {
 
4144
            m = &Menus[i];
 
4145
                        Menus_Activate(m);
 
4146
                        if (openMenuCount < MAX_OPEN_MENUS && focus != NULL) {
 
4147
                                menuStack[openMenuCount++] = focus;
 
4148
                        }
 
4149
    } else {
 
4150
      Menus[i].window.flags &= ~WINDOW_HASFOCUS;
 
4151
    }
 
4152
  }
 
4153
        Display_CloseCinematics();
 
4154
  return m;
 
4155
}
 
4156
 
 
4157
 
 
4158
void Item_Init(itemDef_t *item) {
 
4159
        memset(item, 0, sizeof(itemDef_t));
 
4160
        item->textscale = 0.55f;
 
4161
        Window_Init(&item->window);
 
4162
}
 
4163
 
 
4164
void Menu_HandleMouseMove(menuDef_t *menu, float x, float y) {
 
4165
  int i, pass;
 
4166
  qboolean focusSet = qfalse;
 
4167
 
 
4168
  itemDef_t *overItem;
 
4169
  if (menu == NULL) {
 
4170
    return;
 
4171
  }
 
4172
 
 
4173
  if (!(menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
 
4174
    return;
 
4175
  }
 
4176
 
 
4177
        if (itemCapture) {
 
4178
                //Item_MouseMove(itemCapture, x, y);
 
4179
                return;
 
4180
        }
 
4181
 
 
4182
        if (g_waitingForKey || g_editingField) {
 
4183
                return;
 
4184
        }
 
4185
 
 
4186
  // FIXME: this is the whole issue of focus vs. mouse over.. 
 
4187
  // need a better overall solution as i don't like going through everything twice
 
4188
  for (pass = 0; pass < 2; pass++) {
 
4189
    for (i = 0; i < menu->itemCount; i++) {
 
4190
      // turn off focus each item
 
4191
      // menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
 
4192
 
 
4193
      if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
 
4194
        continue;
 
4195
      }
 
4196
 
 
4197
                        // items can be enabled and disabled based on cvars
 
4198
                        if (menu->items[i]->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_ENABLE)) {
 
4199
                                continue;
 
4200
                        }
 
4201
 
 
4202
                        if (menu->items[i]->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_SHOW)) {
 
4203
                                continue;
 
4204
                        }
 
4205
 
 
4206
 
 
4207
 
 
4208
      if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
 
4209
                                if (pass == 1) {
 
4210
                                        overItem = menu->items[i];
 
4211
                                        if (overItem->type == ITEM_TYPE_TEXT && overItem->text) {
 
4212
                                                if (!Rect_ContainsPoint(Item_CorrectedTextRect(overItem), x, y)) {
 
4213
                                                        continue;
 
4214
                                                }
 
4215
                                        }
 
4216
                                        // if we are over an item
 
4217
                                        if (IsVisible(overItem->window.flags)) {
 
4218
                                                // different one
 
4219
                                                Item_MouseEnter(overItem, x, y);
 
4220
                                                // Item_SetMouseOver(overItem, qtrue);
 
4221
 
 
4222
                                                // if item is not a decoration see if it can take focus
 
4223
                                                if (!focusSet) {
 
4224
                                                        focusSet = Item_SetFocus(overItem, x, y);
 
4225
                                                }
 
4226
                                        }
 
4227
                                }
 
4228
      } else if (menu->items[i]->window.flags & WINDOW_MOUSEOVER) {
 
4229
          Item_MouseLeave(menu->items[i]);
 
4230
          Item_SetMouseOver(menu->items[i], qfalse);
 
4231
      }
 
4232
    }
 
4233
  }
 
4234
 
 
4235
}
 
4236
 
 
4237
void Menu_Paint(menuDef_t *menu, qboolean forcePaint) {
 
4238
        int i;
 
4239
 
 
4240
        if (menu == NULL) {
 
4241
                return;
 
4242
        }
 
4243
 
 
4244
        if (!(menu->window.flags & WINDOW_VISIBLE) &&  !forcePaint) {
 
4245
                return;
 
4246
        }
 
4247
 
 
4248
        if (menu->window.ownerDrawFlags && DC->ownerDrawVisible && !DC->ownerDrawVisible(menu->window.ownerDrawFlags)) {
 
4249
                return;
 
4250
        }
 
4251
        
 
4252
        if (forcePaint) {
 
4253
                menu->window.flags |= WINDOW_FORCED;
 
4254
        }
 
4255
 
 
4256
        // draw the background if necessary
 
4257
        if (menu->fullScreen) {
 
4258
                // implies a background shader
 
4259
                // FIXME: make sure we have a default shader if fullscreen is set with no background
 
4260
                DC->drawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, menu->window.background );
 
4261
        } else if (menu->window.background) {
 
4262
                // this allows a background shader without being full screen
 
4263
                //UI_DrawHandlePic(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, menu->backgroundShader);
 
4264
        }
 
4265
 
 
4266
        // paint the background and or border
 
4267
        Window_Paint(&menu->window, menu->fadeAmount, menu->fadeClamp, menu->fadeCycle );
 
4268
 
 
4269
        for (i = 0; i < menu->itemCount; i++) {
 
4270
                Item_Paint(menu->items[i]);
 
4271
        }
 
4272
 
 
4273
        if (debugMode) {
 
4274
                vec4_t color;
 
4275
                color[0] = color[2] = color[3] = 1;
 
4276
                color[1] = 0;
 
4277
                DC->drawRect(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, 1, color);
 
4278
        }
 
4279
}
 
4280
 
 
4281
/*
 
4282
===============
 
4283
Item_ValidateTypeData
 
4284
===============
 
4285
*/
 
4286
void Item_ValidateTypeData(itemDef_t *item) {
 
4287
        if (item->typeData) {
 
4288
                return;
 
4289
        }
 
4290
 
 
4291
        if (item->type == ITEM_TYPE_LISTBOX) {
 
4292
                item->typeData = UI_Alloc(sizeof(listBoxDef_t));
 
4293
                memset(item->typeData, 0, sizeof(listBoxDef_t));
 
4294
        } else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_BIND || item->type == ITEM_TYPE_SLIDER || item->type == ITEM_TYPE_TEXT) {
 
4295
                item->typeData = UI_Alloc(sizeof(editFieldDef_t));
 
4296
                memset(item->typeData, 0, sizeof(editFieldDef_t));
 
4297
                if (item->type == ITEM_TYPE_EDITFIELD) {
 
4298
                        if (!((editFieldDef_t *) item->typeData)->maxPaintChars) {
 
4299
                                ((editFieldDef_t *) item->typeData)->maxPaintChars = MAX_EDITFIELD;
 
4300
                        }
 
4301
                }
 
4302
        } else if (item->type == ITEM_TYPE_MULTI) {
 
4303
                item->typeData = UI_Alloc(sizeof(multiDef_t));
 
4304
        } else if (item->type == ITEM_TYPE_MODEL) {
 
4305
                item->typeData = UI_Alloc(sizeof(modelDef_t));
 
4306
        }
 
4307
}
 
4308
 
 
4309
/*
 
4310
===============
 
4311
Keyword Hash
 
4312
===============
 
4313
*/
 
4314
 
 
4315
#define KEYWORDHASH_SIZE        512
 
4316
 
 
4317
typedef struct keywordHash_s
 
4318
{
 
4319
        char *keyword;
 
4320
        qboolean (*func)(itemDef_t *item, int handle);
 
4321
        struct keywordHash_s *next;
 
4322
} keywordHash_t;
 
4323
 
 
4324
int KeywordHash_Key(char *keyword) {
 
4325
        int register hash, i;
 
4326
 
 
4327
        hash = 0;
 
4328
        for (i = 0; keyword[i] != '\0'; i++) {
 
4329
                if (keyword[i] >= 'A' && keyword[i] <= 'Z')
 
4330
                        hash += (keyword[i] + ('a' - 'A')) * (119 + i);
 
4331
                else
 
4332
                        hash += keyword[i] * (119 + i);
 
4333
        }
 
4334
        hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (KEYWORDHASH_SIZE-1);
 
4335
        return hash;
 
4336
}
 
4337
 
 
4338
void KeywordHash_Add(keywordHash_t *table[], keywordHash_t *key) {
 
4339
        int hash;
 
4340
 
 
4341
        hash = KeywordHash_Key(key->keyword);
 
4342
/*
 
4343
        if (table[hash]) {
 
4344
                int collision = qtrue;
 
4345
        }
 
4346
*/
 
4347
        key->next = table[hash];
 
4348
        table[hash] = key;
 
4349
}
 
4350
 
 
4351
keywordHash_t *KeywordHash_Find(keywordHash_t *table[], char *keyword)
 
4352
{
 
4353
        keywordHash_t *key;
 
4354
        int hash;
 
4355
 
 
4356
        hash = KeywordHash_Key(keyword);
 
4357
        for (key = table[hash]; key; key = key->next) {
 
4358
                if (!Q_stricmp(key->keyword, keyword))
 
4359
                        return key;
 
4360
        }
 
4361
        return NULL;
 
4362
}
 
4363
 
 
4364
/*
 
4365
===============
 
4366
Item Keyword Parse functions
 
4367
===============
 
4368
*/
 
4369
 
 
4370
// name <string>
 
4371
qboolean ItemParse_name( itemDef_t *item, int handle ) {
 
4372
        if (!PC_String_Parse(handle, &item->window.name)) {
 
4373
                return qfalse;
 
4374
        }
 
4375
        return qtrue;
 
4376
}
 
4377
 
 
4378
// name <string>
 
4379
qboolean ItemParse_focusSound( itemDef_t *item, int handle ) {
 
4380
        const char *temp;
 
4381
        if (!PC_String_Parse(handle, &temp)) {
 
4382
                return qfalse;
 
4383
        }
 
4384
        item->focusSound = DC->registerSound(temp, qfalse);
 
4385
        return qtrue;
 
4386
}
 
4387
 
 
4388
 
 
4389
// text <string>
 
4390
qboolean ItemParse_text( itemDef_t *item, int handle ) {
 
4391
        if (!PC_String_Parse(handle, &item->text)) {
 
4392
                return qfalse;
 
4393
        }
 
4394
        return qtrue;
 
4395
}
 
4396
 
 
4397
// group <string>
 
4398
qboolean ItemParse_group( itemDef_t *item, int handle ) {
 
4399
        if (!PC_String_Parse(handle, &item->window.group)) {
 
4400
                return qfalse;
 
4401
        }
 
4402
        return qtrue;
 
4403
}
 
4404
 
 
4405
// asset_model <string>
 
4406
qboolean ItemParse_asset_model( itemDef_t *item, int handle ) {
 
4407
        const char *temp;
 
4408
        modelDef_t *modelPtr;
 
4409
        Item_ValidateTypeData(item);
 
4410
        modelPtr = (modelDef_t*)item->typeData;
 
4411
 
 
4412
        if (!PC_String_Parse(handle, &temp)) {
 
4413
                return qfalse;
 
4414
        }
 
4415
        item->asset = DC->registerModel(temp);
 
4416
        modelPtr->angle = rand() % 360;
 
4417
        return qtrue;
 
4418
}
 
4419
 
 
4420
// asset_shader <string>
 
4421
qboolean ItemParse_asset_shader( itemDef_t *item, int handle ) {
 
4422
        const char *temp;
 
4423
 
 
4424
        if (!PC_String_Parse(handle, &temp)) {
 
4425
                return qfalse;
 
4426
        }
 
4427
        item->asset = DC->registerShaderNoMip(temp);
 
4428
        return qtrue;
 
4429
}
 
4430
 
 
4431
// model_origin <number> <number> <number>
 
4432
qboolean ItemParse_model_origin( itemDef_t *item, int handle ) {
 
4433
        modelDef_t *modelPtr;
 
4434
        Item_ValidateTypeData(item);
 
4435
        modelPtr = (modelDef_t*)item->typeData;
 
4436
 
 
4437
        if (PC_Float_Parse(handle, &modelPtr->origin[0])) {
 
4438
                if (PC_Float_Parse(handle, &modelPtr->origin[1])) {
 
4439
                        if (PC_Float_Parse(handle, &modelPtr->origin[2])) {
 
4440
                                return qtrue;
 
4441
                        }
 
4442
                }
 
4443
        }
 
4444
        return qfalse;
 
4445
}
 
4446
 
 
4447
// model_fovx <number>
 
4448
qboolean ItemParse_model_fovx( itemDef_t *item, int handle ) {
 
4449
        modelDef_t *modelPtr;
 
4450
        Item_ValidateTypeData(item);
 
4451
        modelPtr = (modelDef_t*)item->typeData;
 
4452
 
 
4453
        if (!PC_Float_Parse(handle, &modelPtr->fov_x)) {
 
4454
                return qfalse;
 
4455
        }
 
4456
        return qtrue;
 
4457
}
 
4458
 
 
4459
// model_fovy <number>
 
4460
qboolean ItemParse_model_fovy( itemDef_t *item, int handle ) {
 
4461
        modelDef_t *modelPtr;
 
4462
        Item_ValidateTypeData(item);
 
4463
        modelPtr = (modelDef_t*)item->typeData;
 
4464
 
 
4465
        if (!PC_Float_Parse(handle, &modelPtr->fov_y)) {
 
4466
                return qfalse;
 
4467
        }
 
4468
        return qtrue;
 
4469
}
 
4470
 
 
4471
// model_rotation <integer>
 
4472
qboolean ItemParse_model_rotation( itemDef_t *item, int handle ) {
 
4473
        modelDef_t *modelPtr;
 
4474
        Item_ValidateTypeData(item);
 
4475
        modelPtr = (modelDef_t*)item->typeData;
 
4476
 
 
4477
        if (!PC_Int_Parse(handle, &modelPtr->rotationSpeed)) {
 
4478
                return qfalse;
 
4479
        }
 
4480
        return qtrue;
 
4481
}
 
4482
 
 
4483
// model_angle <integer>
 
4484
qboolean ItemParse_model_angle( itemDef_t *item, int handle ) {
 
4485
        modelDef_t *modelPtr;
 
4486
        Item_ValidateTypeData(item);
 
4487
        modelPtr = (modelDef_t*)item->typeData;
 
4488
 
 
4489
        if (!PC_Int_Parse(handle, &modelPtr->angle)) {
 
4490
                return qfalse;
 
4491
        }
 
4492
        return qtrue;
 
4493
}
 
4494
 
 
4495
// rect <rectangle>
 
4496
qboolean ItemParse_rect( itemDef_t *item, int handle ) {
 
4497
        if (!PC_Rect_Parse(handle, &item->window.rectClient)) {
 
4498
                return qfalse;
 
4499
        }
 
4500
        return qtrue;
 
4501
}
 
4502
 
 
4503
// style <integer>
 
4504
qboolean ItemParse_style( itemDef_t *item, int handle ) {
 
4505
        if (!PC_Int_Parse(handle, &item->window.style)) {
 
4506
                return qfalse;
 
4507
        }
 
4508
        return qtrue;
 
4509
}
 
4510
 
 
4511
// decoration
 
4512
qboolean ItemParse_decoration( itemDef_t *item, int handle ) {
 
4513
        item->window.flags |= WINDOW_DECORATION;
 
4514
        return qtrue;
 
4515
}
 
4516
 
 
4517
// notselectable
 
4518
qboolean ItemParse_notselectable( itemDef_t *item, int handle ) {
 
4519
        listBoxDef_t *listPtr;
 
4520
        Item_ValidateTypeData(item);
 
4521
        listPtr = (listBoxDef_t*)item->typeData;
 
4522
        if (item->type == ITEM_TYPE_LISTBOX && listPtr) {
 
4523
                listPtr->notselectable = qtrue;
 
4524
        }
 
4525
        return qtrue;
 
4526
}
 
4527
 
 
4528
// manually wrapped
 
4529
qboolean ItemParse_wrapped( itemDef_t *item, int handle ) {
 
4530
        item->window.flags |= WINDOW_WRAPPED;
 
4531
        return qtrue;
 
4532
}
 
4533
 
 
4534
// auto wrapped
 
4535
qboolean ItemParse_autowrapped( itemDef_t *item, int handle ) {
 
4536
        item->window.flags |= WINDOW_AUTOWRAPPED;
 
4537
        return qtrue;
 
4538
}
 
4539
 
 
4540
 
 
4541
// horizontalscroll
 
4542
qboolean ItemParse_horizontalscroll( itemDef_t *item, int handle ) {
 
4543
        item->window.flags |= WINDOW_HORIZONTAL;
 
4544
        return qtrue;
 
4545
}
 
4546
 
 
4547
// type <integer>
 
4548
qboolean ItemParse_type( itemDef_t *item, int handle ) {
 
4549
        if (!PC_Int_Parse(handle, &item->type)) {
 
4550
                return qfalse;
 
4551
        }
 
4552
        Item_ValidateTypeData(item);
 
4553
        return qtrue;
 
4554
}
 
4555
 
 
4556
// elementwidth, used for listbox image elements
 
4557
// uses textalignx for storage
 
4558
qboolean ItemParse_elementwidth( itemDef_t *item, int handle ) {
 
4559
        listBoxDef_t *listPtr;
 
4560
 
 
4561
        Item_ValidateTypeData(item);
 
4562
        listPtr = (listBoxDef_t*)item->typeData;
 
4563
        if (!PC_Float_Parse(handle, &listPtr->elementWidth)) {
 
4564
                return qfalse;
 
4565
        }
 
4566
        return qtrue;
 
4567
}
 
4568
 
 
4569
// elementheight, used for listbox image elements
 
4570
// uses textaligny for storage
 
4571
qboolean ItemParse_elementheight( itemDef_t *item, int handle ) {
 
4572
        listBoxDef_t *listPtr;
 
4573
 
 
4574
        Item_ValidateTypeData(item);
 
4575
        listPtr = (listBoxDef_t*)item->typeData;
 
4576
        if (!PC_Float_Parse(handle, &listPtr->elementHeight)) {
 
4577
                return qfalse;
 
4578
        }
 
4579
        return qtrue;
 
4580
}
 
4581
 
 
4582
// feeder <float>
 
4583
qboolean ItemParse_feeder( itemDef_t *item, int handle ) {
 
4584
        if (!PC_Float_Parse(handle, &item->special)) {
 
4585
                return qfalse;
 
4586
        }
 
4587
        return qtrue;
 
4588
}
 
4589
 
 
4590
// elementtype, used to specify what type of elements a listbox contains
 
4591
// uses textstyle for storage
 
4592
qboolean ItemParse_elementtype( itemDef_t *item, int handle ) {
 
4593
        listBoxDef_t *listPtr;
 
4594
 
 
4595
        Item_ValidateTypeData(item);
 
4596
        if (!item->typeData)
 
4597
                return qfalse;
 
4598
        listPtr = (listBoxDef_t*)item->typeData;
 
4599
        if (!PC_Int_Parse(handle, &listPtr->elementStyle)) {
 
4600
                return qfalse;
 
4601
        }
 
4602
        return qtrue;
 
4603
}
 
4604
 
 
4605
// columns sets a number of columns and an x pos and width per.. 
 
4606
qboolean ItemParse_columns( itemDef_t *item, int handle ) {
 
4607
        int num, i;
 
4608
        listBoxDef_t *listPtr;
 
4609
 
 
4610
        Item_ValidateTypeData(item);
 
4611
        if (!item->typeData)
 
4612
                return qfalse;
 
4613
        listPtr = (listBoxDef_t*)item->typeData;
 
4614
        if (PC_Int_Parse(handle, &num)) {
 
4615
                if (num > MAX_LB_COLUMNS) {
 
4616
                        num = MAX_LB_COLUMNS;
 
4617
                }
 
4618
                listPtr->numColumns = num;
 
4619
                for (i = 0; i < num; i++) {
 
4620
                        int pos, width, maxChars;
 
4621
 
 
4622
                        if (PC_Int_Parse(handle, &pos) && PC_Int_Parse(handle, &width) && PC_Int_Parse(handle, &maxChars)) {
 
4623
                                listPtr->columnInfo[i].pos = pos;
 
4624
                                listPtr->columnInfo[i].width = width;
 
4625
                                listPtr->columnInfo[i].maxChars = maxChars;
 
4626
                        } else {
 
4627
                                return qfalse;
 
4628
                        }
 
4629
                }
 
4630
        } else {
 
4631
                return qfalse;
 
4632
        }
 
4633
        return qtrue;
 
4634
}
 
4635
 
 
4636
qboolean ItemParse_border( itemDef_t *item, int handle ) {
 
4637
        if (!PC_Int_Parse(handle, &item->window.border)) {
 
4638
                return qfalse;
 
4639
        }
 
4640
        return qtrue;
 
4641
}
 
4642
 
 
4643
qboolean ItemParse_bordersize( itemDef_t *item, int handle ) {
 
4644
        if (!PC_Float_Parse(handle, &item->window.borderSize)) {
 
4645
                return qfalse;
 
4646
        }
 
4647
        return qtrue;
 
4648
}
 
4649
 
 
4650
qboolean ItemParse_visible( itemDef_t *item, int handle ) {
 
4651
        int i;
 
4652
 
 
4653
        if (!PC_Int_Parse(handle, &i)) {
 
4654
                return qfalse;
 
4655
        }
 
4656
        if (i) {
 
4657
                item->window.flags |= WINDOW_VISIBLE;
 
4658
        }
 
4659
        return qtrue;
 
4660
}
 
4661
 
 
4662
qboolean ItemParse_ownerdraw( itemDef_t *item, int handle ) {
 
4663
        if (!PC_Int_Parse(handle, &item->window.ownerDraw)) {
 
4664
                return qfalse;
 
4665
        }
 
4666
        item->type = ITEM_TYPE_OWNERDRAW;
 
4667
        return qtrue;
 
4668
}
 
4669
 
 
4670
qboolean ItemParse_align( itemDef_t *item, int handle ) {
 
4671
        if (!PC_Int_Parse(handle, &item->alignment)) {
 
4672
                return qfalse;
 
4673
        }
 
4674
        return qtrue;
 
4675
}
 
4676
 
 
4677
qboolean ItemParse_textalign( itemDef_t *item, int handle ) {
 
4678
        if (!PC_Int_Parse(handle, &item->textalignment)) {
 
4679
                return qfalse;
 
4680
        }
 
4681
        return qtrue;
 
4682
}
 
4683
 
 
4684
qboolean ItemParse_textalignx( itemDef_t *item, int handle ) {
 
4685
        if (!PC_Float_Parse(handle, &item->textalignx)) {
 
4686
                return qfalse;
 
4687
        }
 
4688
        return qtrue;
 
4689
}
 
4690
 
 
4691
qboolean ItemParse_textaligny( itemDef_t *item, int handle ) {
 
4692
        if (!PC_Float_Parse(handle, &item->textaligny)) {
 
4693
                return qfalse;
 
4694
        }
 
4695
        return qtrue;
 
4696
}
 
4697
 
 
4698
qboolean ItemParse_textscale( itemDef_t *item, int handle ) {
 
4699
        if (!PC_Float_Parse(handle, &item->textscale)) {
 
4700
                return qfalse;
 
4701
        }
 
4702
        return qtrue;
 
4703
}
 
4704
 
 
4705
qboolean ItemParse_textstyle( itemDef_t *item, int handle ) {
 
4706
        if (!PC_Int_Parse(handle, &item->textStyle)) {
 
4707
                return qfalse;
 
4708
        }
 
4709
        return qtrue;
 
4710
}
 
4711
 
 
4712
qboolean ItemParse_backcolor( itemDef_t *item, int handle ) {
 
4713
        int i;
 
4714
        float f;
 
4715
 
 
4716
        for (i = 0; i < 4; i++) {
 
4717
                if (!PC_Float_Parse(handle, &f)) {
 
4718
                        return qfalse;
 
4719
                }
 
4720
                item->window.backColor[i]  = f;
 
4721
        }
 
4722
        return qtrue;
 
4723
}
 
4724
 
 
4725
qboolean ItemParse_forecolor( itemDef_t *item, int handle ) {
 
4726
        int i;
 
4727
        float f;
 
4728
 
 
4729
        for (i = 0; i < 4; i++) {
 
4730
                if (!PC_Float_Parse(handle, &f)) {
 
4731
                        return qfalse;
 
4732
                }
 
4733
                item->window.foreColor[i]  = f;
 
4734
                item->window.flags |= WINDOW_FORECOLORSET;
 
4735
        }
 
4736
        return qtrue;
 
4737
}
 
4738
 
 
4739
qboolean ItemParse_bordercolor( itemDef_t *item, int handle ) {
 
4740
        int i;
 
4741
        float f;
 
4742
 
 
4743
        for (i = 0; i < 4; i++) {
 
4744
                if (!PC_Float_Parse(handle, &f)) {
 
4745
                        return qfalse;
 
4746
                }
 
4747
                item->window.borderColor[i]  = f;
 
4748
        }
 
4749
        return qtrue;
 
4750
}
 
4751
 
 
4752
qboolean ItemParse_outlinecolor( itemDef_t *item, int handle ) {
 
4753
        if (!PC_Color_Parse(handle, &item->window.outlineColor)){
 
4754
                return qfalse;
 
4755
        }
 
4756
        return qtrue;
 
4757
}
 
4758
 
 
4759
qboolean ItemParse_background( itemDef_t *item, int handle ) {
 
4760
        const char *temp;
 
4761
 
 
4762
        if (!PC_String_Parse(handle, &temp)) {
 
4763
                return qfalse;
 
4764
        }
 
4765
        item->window.background = DC->registerShaderNoMip(temp);
 
4766
        return qtrue;
 
4767
}
 
4768
 
 
4769
qboolean ItemParse_cinematic( itemDef_t *item, int handle ) {
 
4770
        if (!PC_String_Parse(handle, &item->window.cinematicName)) {
 
4771
                return qfalse;
 
4772
        }
 
4773
        return qtrue;
 
4774
}
 
4775
 
 
4776
qboolean ItemParse_doubleClick( itemDef_t *item, int handle ) {
 
4777
        listBoxDef_t *listPtr;
 
4778
 
 
4779
        Item_ValidateTypeData(item);
 
4780
        if (!item->typeData) {
 
4781
                return qfalse;
 
4782
        }
 
4783
 
 
4784
        listPtr = (listBoxDef_t*)item->typeData;
 
4785
 
 
4786
        if (!PC_Script_Parse(handle, &listPtr->doubleClick)) {
 
4787
                return qfalse;
 
4788
        }
 
4789
        return qtrue;
 
4790
}
 
4791
 
 
4792
qboolean ItemParse_onFocus( itemDef_t *item, int handle ) {
 
4793
        if (!PC_Script_Parse(handle, &item->onFocus)) {
 
4794
                return qfalse;
 
4795
        }
 
4796
        return qtrue;
 
4797
}
 
4798
 
 
4799
qboolean ItemParse_leaveFocus( itemDef_t *item, int handle ) {
 
4800
        if (!PC_Script_Parse(handle, &item->leaveFocus)) {
 
4801
                return qfalse;
 
4802
        }
 
4803
        return qtrue;
 
4804
}
 
4805
 
 
4806
qboolean ItemParse_mouseEnter( itemDef_t *item, int handle ) {
 
4807
        if (!PC_Script_Parse(handle, &item->mouseEnter)) {
 
4808
                return qfalse;
 
4809
        }
 
4810
        return qtrue;
 
4811
}
 
4812
 
 
4813
qboolean ItemParse_mouseExit( itemDef_t *item, int handle ) {
 
4814
        if (!PC_Script_Parse(handle, &item->mouseExit)) {
 
4815
                return qfalse;
 
4816
        }
 
4817
        return qtrue;
 
4818
}
 
4819
 
 
4820
qboolean ItemParse_mouseEnterText( itemDef_t *item, int handle ) {
 
4821
        if (!PC_Script_Parse(handle, &item->mouseEnterText)) {
 
4822
                return qfalse;
 
4823
        }
 
4824
        return qtrue;
 
4825
}
 
4826
 
 
4827
qboolean ItemParse_mouseExitText( itemDef_t *item, int handle ) {
 
4828
        if (!PC_Script_Parse(handle, &item->mouseExitText)) {
 
4829
                return qfalse;
 
4830
        }
 
4831
        return qtrue;
 
4832
}
 
4833
 
 
4834
qboolean ItemParse_action( itemDef_t *item, int handle ) {
 
4835
        if (!PC_Script_Parse(handle, &item->action)) {
 
4836
                return qfalse;
 
4837
        }
 
4838
        return qtrue;
 
4839
}
 
4840
 
 
4841
qboolean ItemParse_special( itemDef_t *item, int handle ) {
 
4842
        if (!PC_Float_Parse(handle, &item->special)) {
 
4843
                return qfalse;
 
4844
        }
 
4845
        return qtrue;
 
4846
}
 
4847
 
 
4848
qboolean ItemParse_cvarTest( itemDef_t *item, int handle ) {
 
4849
        if (!PC_String_Parse(handle, &item->cvarTest)) {
 
4850
                return qfalse;
 
4851
        }
 
4852
        return qtrue;
 
4853
}
 
4854
 
 
4855
qboolean ItemParse_cvar( itemDef_t *item, int handle ) {
 
4856
        editFieldDef_t *editPtr;
 
4857
 
 
4858
        Item_ValidateTypeData(item);
 
4859
        if (!PC_String_Parse(handle, &item->cvar)) {
 
4860
                return qfalse;
 
4861
        }
 
4862
        if (item->typeData) {
 
4863
                editPtr = (editFieldDef_t*)item->typeData;
 
4864
                editPtr->minVal = -1;
 
4865
                editPtr->maxVal = -1;
 
4866
                editPtr->defVal = -1;
 
4867
        }
 
4868
        return qtrue;
 
4869
}
 
4870
 
 
4871
qboolean ItemParse_maxChars( itemDef_t *item, int handle ) {
 
4872
        editFieldDef_t *editPtr;
 
4873
        int maxChars;
 
4874
 
 
4875
        Item_ValidateTypeData(item);
 
4876
        if (!item->typeData)
 
4877
                return qfalse;
 
4878
 
 
4879
        if (!PC_Int_Parse(handle, &maxChars)) {
 
4880
                return qfalse;
 
4881
        }
 
4882
        editPtr = (editFieldDef_t*)item->typeData;
 
4883
        editPtr->maxChars = maxChars;
 
4884
        return qtrue;
 
4885
}
 
4886
 
 
4887
qboolean ItemParse_maxPaintChars( itemDef_t *item, int handle ) {
 
4888
        editFieldDef_t *editPtr;
 
4889
        int maxChars;
 
4890
 
 
4891
        Item_ValidateTypeData(item);
 
4892
        if (!item->typeData)
 
4893
                return qfalse;
 
4894
 
 
4895
        if (!PC_Int_Parse(handle, &maxChars)) {
 
4896
                return qfalse;
 
4897
        }
 
4898
        editPtr = (editFieldDef_t*)item->typeData;
 
4899
        editPtr->maxPaintChars = maxChars;
 
4900
        return qtrue;
 
4901
}
 
4902
 
 
4903
 
 
4904
 
 
4905
qboolean ItemParse_cvarFloat( itemDef_t *item, int handle ) {
 
4906
        editFieldDef_t *editPtr;
 
4907
 
 
4908
        Item_ValidateTypeData(item);
 
4909
        if (!item->typeData)
 
4910
                return qfalse;
 
4911
        editPtr = (editFieldDef_t*)item->typeData;
 
4912
        if (PC_String_Parse(handle, &item->cvar) &&
 
4913
                PC_Float_Parse(handle, &editPtr->defVal) &&
 
4914
                PC_Float_Parse(handle, &editPtr->minVal) &&
 
4915
                PC_Float_Parse(handle, &editPtr->maxVal)) {
 
4916
                return qtrue;
 
4917
        }
 
4918
        return qfalse;
 
4919
}
 
4920
 
 
4921
qboolean ItemParse_cvarStrList( itemDef_t *item, int handle ) {
 
4922
        pc_token_t token;
 
4923
        multiDef_t *multiPtr;
 
4924
        int pass;
 
4925
        
 
4926
        Item_ValidateTypeData(item);
 
4927
        if (!item->typeData)
 
4928
                return qfalse;
 
4929
        multiPtr = (multiDef_t*)item->typeData;
 
4930
        multiPtr->count = 0;
 
4931
        multiPtr->strDef = qtrue;
 
4932
 
 
4933
        if (!trap_PC_ReadToken(handle, &token))
 
4934
                return qfalse;
 
4935
        if (*token.string != '{') {
 
4936
                return qfalse;
 
4937
        }
 
4938
 
 
4939
        pass = 0;
 
4940
        while ( 1 ) {
 
4941
                if (!trap_PC_ReadToken(handle, &token)) {
 
4942
                        PC_SourceError(handle, "end of file inside menu item\n");
 
4943
                        return qfalse;
 
4944
                }
 
4945
 
 
4946
                if (*token.string == '}') {
 
4947
                        return qtrue;
 
4948
                }
 
4949
 
 
4950
                if (*token.string == ',' || *token.string == ';') {
 
4951
                        continue;
 
4952
                }
 
4953
 
 
4954
                if (pass == 0) {
 
4955
                        multiPtr->cvarList[multiPtr->count] = String_Alloc(token.string);
 
4956
                        pass = 1;
 
4957
                } else {
 
4958
                        multiPtr->cvarStr[multiPtr->count] = String_Alloc(token.string);
 
4959
                        pass = 0;
 
4960
                        multiPtr->count++;
 
4961
                        if (multiPtr->count >= MAX_MULTI_CVARS) {
 
4962
                                return qfalse;
 
4963
                        }
 
4964
                }
 
4965
 
 
4966
        }
 
4967
        return qfalse;  // bk001205 - LCC missing return value
 
4968
}
 
4969
 
 
4970
qboolean ItemParse_cvarFloatList( itemDef_t *item, int handle ) {
 
4971
        pc_token_t token;
 
4972
        multiDef_t *multiPtr;
 
4973
        
 
4974
        Item_ValidateTypeData(item);
 
4975
        if (!item->typeData)
 
4976
                return qfalse;
 
4977
        multiPtr = (multiDef_t*)item->typeData;
 
4978
        multiPtr->count = 0;
 
4979
        multiPtr->strDef = qfalse;
 
4980
 
 
4981
        if (!trap_PC_ReadToken(handle, &token))
 
4982
                return qfalse;
 
4983
        if (*token.string != '{') {
 
4984
                return qfalse;
 
4985
        }
 
4986
 
 
4987
        while ( 1 ) {
 
4988
                if (!trap_PC_ReadToken(handle, &token)) {
 
4989
                        PC_SourceError(handle, "end of file inside menu item\n");
 
4990
                        return qfalse;
 
4991
                }
 
4992
 
 
4993
                if (*token.string == '}') {
 
4994
                        return qtrue;
 
4995
                }
 
4996
 
 
4997
                if (*token.string == ',' || *token.string == ';') {
 
4998
                        continue;
 
4999
                }
 
5000
 
 
5001
                multiPtr->cvarList[multiPtr->count] = String_Alloc(token.string);
 
5002
                if (!PC_Float_Parse(handle, &multiPtr->cvarValue[multiPtr->count])) {
 
5003
                        return qfalse;
 
5004
                }
 
5005
 
 
5006
                multiPtr->count++;
 
5007
                if (multiPtr->count >= MAX_MULTI_CVARS) {
 
5008
                        return qfalse;
 
5009
                }
 
5010
 
 
5011
        }
 
5012
        return qfalse;  // bk001205 - LCC missing return value
 
5013
}
 
5014
 
 
5015
 
 
5016
 
 
5017
qboolean ItemParse_addColorRange( itemDef_t *item, int handle ) {
 
5018
        colorRangeDef_t color;
 
5019
 
 
5020
        if (PC_Float_Parse(handle, &color.low) &&
 
5021
                PC_Float_Parse(handle, &color.high) &&
 
5022
                PC_Color_Parse(handle, &color.color) ) {
 
5023
                if (item->numColors < MAX_COLOR_RANGES) {
 
5024
                        memcpy(&item->colorRanges[item->numColors], &color, sizeof(color));
 
5025
                        item->numColors++;
 
5026
                }
 
5027
                return qtrue;
 
5028
        }
 
5029
        return qfalse;
 
5030
}
 
5031
 
 
5032
qboolean ItemParse_ownerdrawFlag( itemDef_t *item, int handle ) {
 
5033
        int i;
 
5034
        if (!PC_Int_Parse(handle, &i)) {
 
5035
                return qfalse;
 
5036
        }
 
5037
        item->window.ownerDrawFlags |= i;
 
5038
        return qtrue;
 
5039
}
 
5040
 
 
5041
qboolean ItemParse_enableCvar( itemDef_t *item, int handle ) {
 
5042
        if (PC_Script_Parse(handle, &item->enableCvar)) {
 
5043
                item->cvarFlags = CVAR_ENABLE;
 
5044
                return qtrue;
 
5045
        }
 
5046
        return qfalse;
 
5047
}
 
5048
 
 
5049
qboolean ItemParse_disableCvar( itemDef_t *item, int handle ) {
 
5050
        if (PC_Script_Parse(handle, &item->enableCvar)) {
 
5051
                item->cvarFlags = CVAR_DISABLE;
 
5052
                return qtrue;
 
5053
        }
 
5054
        return qfalse;
 
5055
}
 
5056
 
 
5057
qboolean ItemParse_showCvar( itemDef_t *item, int handle ) {
 
5058
        if (PC_Script_Parse(handle, &item->enableCvar)) {
 
5059
                item->cvarFlags = CVAR_SHOW;
 
5060
                return qtrue;
 
5061
        }
 
5062
        return qfalse;
 
5063
}
 
5064
 
 
5065
qboolean ItemParse_hideCvar( itemDef_t *item, int handle ) {
 
5066
        if (PC_Script_Parse(handle, &item->enableCvar)) {
 
5067
                item->cvarFlags = CVAR_HIDE;
 
5068
                return qtrue;
 
5069
        }
 
5070
        return qfalse;
 
5071
}
 
5072
 
 
5073
 
 
5074
keywordHash_t itemParseKeywords[] = {
 
5075
        {"name", ItemParse_name, NULL},
 
5076
        {"text", ItemParse_text, NULL},
 
5077
        {"group", ItemParse_group, NULL},
 
5078
        {"asset_model", ItemParse_asset_model, NULL},
 
5079
        {"asset_shader", ItemParse_asset_shader, NULL},
 
5080
        {"model_origin", ItemParse_model_origin, NULL},
 
5081
        {"model_fovx", ItemParse_model_fovx, NULL},
 
5082
        {"model_fovy", ItemParse_model_fovy, NULL},
 
5083
        {"model_rotation", ItemParse_model_rotation, NULL},
 
5084
        {"model_angle", ItemParse_model_angle, NULL},
 
5085
        {"rect", ItemParse_rect, NULL},
 
5086
        {"style", ItemParse_style, NULL},
 
5087
        {"decoration", ItemParse_decoration, NULL},
 
5088
        {"notselectable", ItemParse_notselectable, NULL},
 
5089
        {"wrapped", ItemParse_wrapped, NULL},
 
5090
        {"autowrapped", ItemParse_autowrapped, NULL},
 
5091
        {"horizontalscroll", ItemParse_horizontalscroll, NULL},
 
5092
        {"type", ItemParse_type, NULL},
 
5093
        {"elementwidth", ItemParse_elementwidth, NULL},
 
5094
        {"elementheight", ItemParse_elementheight, NULL},
 
5095
        {"feeder", ItemParse_feeder, NULL},
 
5096
        {"elementtype", ItemParse_elementtype, NULL},
 
5097
        {"columns", ItemParse_columns, NULL},
 
5098
        {"border", ItemParse_border, NULL},
 
5099
        {"bordersize", ItemParse_bordersize, NULL},
 
5100
        {"visible", ItemParse_visible, NULL},
 
5101
        {"ownerdraw", ItemParse_ownerdraw, NULL},
 
5102
        {"align", ItemParse_align, NULL},
 
5103
        {"textalign", ItemParse_textalign, NULL},
 
5104
        {"textalignx", ItemParse_textalignx, NULL},
 
5105
        {"textaligny", ItemParse_textaligny, NULL},
 
5106
        {"textscale", ItemParse_textscale, NULL},
 
5107
        {"textstyle", ItemParse_textstyle, NULL},
 
5108
        {"backcolor", ItemParse_backcolor, NULL},
 
5109
        {"forecolor", ItemParse_forecolor, NULL},
 
5110
        {"bordercolor", ItemParse_bordercolor, NULL},
 
5111
        {"outlinecolor", ItemParse_outlinecolor, NULL},
 
5112
        {"background", ItemParse_background, NULL},
 
5113
        {"onFocus", ItemParse_onFocus, NULL},
 
5114
        {"leaveFocus", ItemParse_leaveFocus, NULL},
 
5115
        {"mouseEnter", ItemParse_mouseEnter, NULL},
 
5116
        {"mouseExit", ItemParse_mouseExit, NULL},
 
5117
        {"mouseEnterText", ItemParse_mouseEnterText, NULL},
 
5118
        {"mouseExitText", ItemParse_mouseExitText, NULL},
 
5119
        {"action", ItemParse_action, NULL},
 
5120
        {"special", ItemParse_special, NULL},
 
5121
        {"cvar", ItemParse_cvar, NULL},
 
5122
        {"maxChars", ItemParse_maxChars, NULL},
 
5123
        {"maxPaintChars", ItemParse_maxPaintChars, NULL},
 
5124
        {"focusSound", ItemParse_focusSound, NULL},
 
5125
        {"cvarFloat", ItemParse_cvarFloat, NULL},
 
5126
        {"cvarStrList", ItemParse_cvarStrList, NULL},
 
5127
        {"cvarFloatList", ItemParse_cvarFloatList, NULL},
 
5128
        {"addColorRange", ItemParse_addColorRange, NULL},
 
5129
        {"ownerdrawFlag", ItemParse_ownerdrawFlag, NULL},
 
5130
        {"enableCvar", ItemParse_enableCvar, NULL},
 
5131
        {"cvarTest", ItemParse_cvarTest, NULL},
 
5132
        {"disableCvar", ItemParse_disableCvar, NULL},
 
5133
        {"showCvar", ItemParse_showCvar, NULL},
 
5134
        {"hideCvar", ItemParse_hideCvar, NULL},
 
5135
        {"cinematic", ItemParse_cinematic, NULL},
 
5136
        {"doubleclick", ItemParse_doubleClick, NULL},
 
5137
        {NULL, 0, NULL}
 
5138
};
 
5139
 
 
5140
keywordHash_t *itemParseKeywordHash[KEYWORDHASH_SIZE];
 
5141
 
 
5142
/*
 
5143
===============
 
5144
Item_SetupKeywordHash
 
5145
===============
 
5146
*/
 
5147
void Item_SetupKeywordHash(void) {
 
5148
        int i;
 
5149
 
 
5150
        memset(itemParseKeywordHash, 0, sizeof(itemParseKeywordHash));
 
5151
        for (i = 0; itemParseKeywords[i].keyword; i++) {
 
5152
                KeywordHash_Add(itemParseKeywordHash, &itemParseKeywords[i]);
 
5153
        }
 
5154
}
 
5155
 
 
5156
/*
 
5157
===============
 
5158
Item_Parse
 
5159
===============
 
5160
*/
 
5161
qboolean Item_Parse(int handle, itemDef_t *item) {
 
5162
        pc_token_t token;
 
5163
        keywordHash_t *key;
 
5164
 
 
5165
 
 
5166
        if (!trap_PC_ReadToken(handle, &token))
 
5167
                return qfalse;
 
5168
        if (*token.string != '{') {
 
5169
                return qfalse;
 
5170
        }
 
5171
        while ( 1 ) {
 
5172
                if (!trap_PC_ReadToken(handle, &token)) {
 
5173
                        PC_SourceError(handle, "end of file inside menu item\n");
 
5174
                        return qfalse;
 
5175
                }
 
5176
 
 
5177
                if (*token.string == '}') {
 
5178
                        return qtrue;
 
5179
                }
 
5180
 
 
5181
                key = KeywordHash_Find(itemParseKeywordHash, token.string);
 
5182
                if (!key) {
 
5183
                        PC_SourceError(handle, "unknown menu item keyword %s", token.string);
 
5184
                        continue;
 
5185
                }
 
5186
                if ( !key->func(item, handle) ) {
 
5187
                        PC_SourceError(handle, "couldn't parse menu item keyword %s", token.string);
 
5188
                        return qfalse;
 
5189
                }
 
5190
        }
 
5191
        return qfalse;  // bk001205 - LCC missing return value
 
5192
}
 
5193
 
 
5194
 
 
5195
// Item_InitControls
 
5196
// init's special control types
 
5197
void Item_InitControls(itemDef_t *item) {
 
5198
        if (item == NULL) {
 
5199
                return;
 
5200
        }
 
5201
        if (item->type == ITEM_TYPE_LISTBOX) {
 
5202
                listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
 
5203
                item->cursorPos = 0;
 
5204
                if (listPtr) {
 
5205
                        listPtr->cursorPos = 0;
 
5206
                        listPtr->startPos = 0;
 
5207
                        listPtr->endPos = 0;
 
5208
                        listPtr->cursorPos = 0;
 
5209
                }
 
5210
        }
 
5211
}
 
5212
 
 
5213
/*
 
5214
===============
 
5215
Menu Keyword Parse functions
 
5216
===============
 
5217
*/
 
5218
 
 
5219
qboolean MenuParse_font( itemDef_t *item, int handle ) {
 
5220
        menuDef_t *menu = (menuDef_t*)item;
 
5221
        if (!PC_String_Parse(handle, &menu->font)) {
 
5222
                return qfalse;
 
5223
        }
 
5224
        if (!DC->Assets.fontRegistered) {
 
5225
                DC->registerFont(menu->font, 48, &DC->Assets.textFont);
 
5226
                DC->Assets.fontRegistered = qtrue;
 
5227
        }
 
5228
        return qtrue;
 
5229
}
 
5230
 
 
5231
qboolean MenuParse_name( itemDef_t *item, int handle ) {
 
5232
        menuDef_t *menu = (menuDef_t*)item;
 
5233
        if (!PC_String_Parse(handle, &menu->window.name)) {
 
5234
                return qfalse;
 
5235
        }
 
5236
        if (Q_stricmp(menu->window.name, "main") == 0) {
 
5237
                // default main as having focus
 
5238
                //menu->window.flags |= WINDOW_HASFOCUS;
 
5239
        }
 
5240
        return qtrue;
 
5241
}
 
5242
 
 
5243
qboolean MenuParse_fullscreen( itemDef_t *item, int handle ) {
 
5244
        menuDef_t *menu = (menuDef_t*)item;
 
5245
        if (!PC_Int_Parse(handle, (int*) &menu->fullScreen)) { // bk001206 - cast qboolean
 
5246
                return qfalse;
 
5247
        }
 
5248
        return qtrue;
 
5249
}
 
5250
 
 
5251
qboolean MenuParse_rect( itemDef_t *item, int handle ) {
 
5252
        menuDef_t *menu = (menuDef_t*)item;
 
5253
        if (!PC_Rect_Parse(handle, &menu->window.rect)) {
 
5254
                return qfalse;
 
5255
        }
 
5256
        return qtrue;
 
5257
}
 
5258
 
 
5259
qboolean MenuParse_style( itemDef_t *item, int handle ) {
 
5260
        menuDef_t *menu = (menuDef_t*)item;
 
5261
        if (!PC_Int_Parse(handle, &menu->window.style)) {
 
5262
                return qfalse;
 
5263
        }
 
5264
        return qtrue;
 
5265
}
 
5266
 
 
5267
qboolean MenuParse_visible( itemDef_t *item, int handle ) {
 
5268
        int i;
 
5269
        menuDef_t *menu = (menuDef_t*)item;
 
5270
 
 
5271
        if (!PC_Int_Parse(handle, &i)) {
 
5272
                return qfalse;
 
5273
        }
 
5274
        if (i) {
 
5275
                menu->window.flags |= WINDOW_VISIBLE;
 
5276
        }
 
5277
        return qtrue;
 
5278
}
 
5279
 
 
5280
qboolean MenuParse_onOpen( itemDef_t *item, int handle ) {
 
5281
        menuDef_t *menu = (menuDef_t*)item;
 
5282
        if (!PC_Script_Parse(handle, &menu->onOpen)) {
 
5283
                return qfalse;
 
5284
        }
 
5285
        return qtrue;
 
5286
}
 
5287
 
 
5288
qboolean MenuParse_onClose( itemDef_t *item, int handle ) {
 
5289
        menuDef_t *menu = (menuDef_t*)item;
 
5290
        if (!PC_Script_Parse(handle, &menu->onClose)) {
 
5291
                return qfalse;
 
5292
        }
 
5293
        return qtrue;
 
5294
}
 
5295
 
 
5296
qboolean MenuParse_onESC( itemDef_t *item, int handle ) {
 
5297
        menuDef_t *menu = (menuDef_t*)item;
 
5298
        if (!PC_Script_Parse(handle, &menu->onESC)) {
 
5299
                return qfalse;
 
5300
        }
 
5301
        return qtrue;
 
5302
}
 
5303
 
 
5304
 
 
5305
 
 
5306
qboolean MenuParse_border( itemDef_t *item, int handle ) {
 
5307
        menuDef_t *menu = (menuDef_t*)item;
 
5308
        if (!PC_Int_Parse(handle, &menu->window.border)) {
 
5309
                return qfalse;
 
5310
        }
 
5311
        return qtrue;
 
5312
}
 
5313
 
 
5314
qboolean MenuParse_borderSize( itemDef_t *item, int handle ) {
 
5315
        menuDef_t *menu = (menuDef_t*)item;
 
5316
        if (!PC_Float_Parse(handle, &menu->window.borderSize)) {
 
5317
                return qfalse;
 
5318
        }
 
5319
        return qtrue;
 
5320
}
 
5321
 
 
5322
qboolean MenuParse_backcolor( itemDef_t *item, int handle ) {
 
5323
        int i;
 
5324
        float f;
 
5325
        menuDef_t *menu = (menuDef_t*)item;
 
5326
 
 
5327
        for (i = 0; i < 4; i++) {
 
5328
                if (!PC_Float_Parse(handle, &f)) {
 
5329
                        return qfalse;
 
5330
                }
 
5331
                menu->window.backColor[i]  = f;
 
5332
        }
 
5333
        return qtrue;
 
5334
}
 
5335
 
 
5336
qboolean MenuParse_forecolor( itemDef_t *item, int handle ) {
 
5337
        int i;
 
5338
        float f;
 
5339
        menuDef_t *menu = (menuDef_t*)item;
 
5340
 
 
5341
        for (i = 0; i < 4; i++) {
 
5342
                if (!PC_Float_Parse(handle, &f)) {
 
5343
                        return qfalse;
 
5344
                }
 
5345
                menu->window.foreColor[i]  = f;
 
5346
                menu->window.flags |= WINDOW_FORECOLORSET;
 
5347
        }
 
5348
        return qtrue;
 
5349
}
 
5350
 
 
5351
qboolean MenuParse_bordercolor( itemDef_t *item, int handle ) {
 
5352
        int i;
 
5353
        float f;
 
5354
        menuDef_t *menu = (menuDef_t*)item;
 
5355
 
 
5356
        for (i = 0; i < 4; i++) {
 
5357
                if (!PC_Float_Parse(handle, &f)) {
 
5358
                        return qfalse;
 
5359
                }
 
5360
                menu->window.borderColor[i]  = f;
 
5361
        }
 
5362
        return qtrue;
 
5363
}
 
5364
 
 
5365
qboolean MenuParse_focuscolor( itemDef_t *item, int handle ) {
 
5366
        int i;
 
5367
        float f;
 
5368
        menuDef_t *menu = (menuDef_t*)item;
 
5369
 
 
5370
        for (i = 0; i < 4; i++) {
 
5371
                if (!PC_Float_Parse(handle, &f)) {
 
5372
                        return qfalse;
 
5373
                }
 
5374
                menu->focusColor[i]  = f;
 
5375
        }
 
5376
        return qtrue;
 
5377
}
 
5378
 
 
5379
qboolean MenuParse_disablecolor( itemDef_t *item, int handle ) {
 
5380
        int i;
 
5381
        float f;
 
5382
        menuDef_t *menu = (menuDef_t*)item;
 
5383
        for (i = 0; i < 4; i++) {
 
5384
                if (!PC_Float_Parse(handle, &f)) {
 
5385
                        return qfalse;
 
5386
                }
 
5387
                menu->disableColor[i]  = f;
 
5388
        }
 
5389
        return qtrue;
 
5390
}
 
5391
 
 
5392
 
 
5393
qboolean MenuParse_outlinecolor( itemDef_t *item, int handle ) {
 
5394
        menuDef_t *menu = (menuDef_t*)item;
 
5395
        if (!PC_Color_Parse(handle, &menu->window.outlineColor)){
 
5396
                return qfalse;
 
5397
        }
 
5398
        return qtrue;
 
5399
}
 
5400
 
 
5401
qboolean MenuParse_background( itemDef_t *item, int handle ) {
 
5402
        const char *buff;
 
5403
        menuDef_t *menu = (menuDef_t*)item;
 
5404
 
 
5405
        if (!PC_String_Parse(handle, &buff)) {
 
5406
                return qfalse;
 
5407
        }
 
5408
        menu->window.background = DC->registerShaderNoMip(buff);
 
5409
        return qtrue;
 
5410
}
 
5411
 
 
5412
qboolean MenuParse_cinematic( itemDef_t *item, int handle ) {
 
5413
        menuDef_t *menu = (menuDef_t*)item;
 
5414
 
 
5415
        if (!PC_String_Parse(handle, &menu->window.cinematicName)) {
 
5416
                return qfalse;
 
5417
        }
 
5418
        return qtrue;
 
5419
}
 
5420
 
 
5421
qboolean MenuParse_ownerdrawFlag( itemDef_t *item, int handle ) {
 
5422
        int i;
 
5423
        menuDef_t *menu = (menuDef_t*)item;
 
5424
 
 
5425
        if (!PC_Int_Parse(handle, &i)) {
 
5426
                return qfalse;
 
5427
        }
 
5428
        menu->window.ownerDrawFlags |= i;
 
5429
        return qtrue;
 
5430
}
 
5431
 
 
5432
qboolean MenuParse_ownerdraw( itemDef_t *item, int handle ) {
 
5433
        menuDef_t *menu = (menuDef_t*)item;
 
5434
 
 
5435
        if (!PC_Int_Parse(handle, &menu->window.ownerDraw)) {
 
5436
                return qfalse;
 
5437
        }
 
5438
        return qtrue;
 
5439
}
 
5440
 
 
5441
 
 
5442
// decoration
 
5443
qboolean MenuParse_popup( itemDef_t *item, int handle ) {
 
5444
        menuDef_t *menu = (menuDef_t*)item;
 
5445
        menu->window.flags |= WINDOW_POPUP;
 
5446
        return qtrue;
 
5447
}
 
5448
 
 
5449
 
 
5450
qboolean MenuParse_outOfBounds( itemDef_t *item, int handle ) {
 
5451
        menuDef_t *menu = (menuDef_t*)item;
 
5452
 
 
5453
        menu->window.flags |= WINDOW_OOB_CLICK;
 
5454
        return qtrue;
 
5455
}
 
5456
 
 
5457
qboolean MenuParse_soundLoop( itemDef_t *item, int handle ) {
 
5458
        menuDef_t *menu = (menuDef_t*)item;
 
5459
 
 
5460
        if (!PC_String_Parse(handle, &menu->soundName)) {
 
5461
                return qfalse;
 
5462
        }
 
5463
        return qtrue;
 
5464
}
 
5465
 
 
5466
qboolean MenuParse_fadeClamp( itemDef_t *item, int handle ) {
 
5467
        menuDef_t *menu = (menuDef_t*)item;
 
5468
 
 
5469
        if (!PC_Float_Parse(handle, &menu->fadeClamp)) {
 
5470
                return qfalse;
 
5471
        }
 
5472
        return qtrue;
 
5473
}
 
5474
 
 
5475
qboolean MenuParse_fadeAmount( itemDef_t *item, int handle ) {
 
5476
        menuDef_t *menu = (menuDef_t*)item;
 
5477
 
 
5478
        if (!PC_Float_Parse(handle, &menu->fadeAmount)) {
 
5479
                return qfalse;
 
5480
        }
 
5481
        return qtrue;
 
5482
}
 
5483
 
 
5484
 
 
5485
qboolean MenuParse_fadeCycle( itemDef_t *item, int handle ) {
 
5486
        menuDef_t *menu = (menuDef_t*)item;
 
5487
 
 
5488
        if (!PC_Int_Parse(handle, &menu->fadeCycle)) {
 
5489
                return qfalse;
 
5490
        }
 
5491
        return qtrue;
 
5492
}
 
5493
 
 
5494
 
 
5495
qboolean MenuParse_itemDef( itemDef_t *item, int handle ) {
 
5496
        menuDef_t *menu = (menuDef_t*)item;
 
5497
        if (menu->itemCount < MAX_MENUITEMS) {
 
5498
                menu->items[menu->itemCount] = UI_Alloc(sizeof(itemDef_t));
 
5499
                Item_Init(menu->items[menu->itemCount]);
 
5500
                if (!Item_Parse(handle, menu->items[menu->itemCount])) {
 
5501
                        return qfalse;
 
5502
                }
 
5503
                Item_InitControls(menu->items[menu->itemCount]);
 
5504
                menu->items[menu->itemCount++]->parent = menu;
 
5505
        }
 
5506
        return qtrue;
 
5507
}
 
5508
 
 
5509
keywordHash_t menuParseKeywords[] = {
 
5510
        {"font", MenuParse_font, NULL},
 
5511
        {"name", MenuParse_name, NULL},
 
5512
        {"fullscreen", MenuParse_fullscreen, NULL},
 
5513
        {"rect", MenuParse_rect, NULL},
 
5514
        {"style", MenuParse_style, NULL},
 
5515
        {"visible", MenuParse_visible, NULL},
 
5516
        {"onOpen", MenuParse_onOpen, NULL},
 
5517
        {"onClose", MenuParse_onClose, NULL},
 
5518
        {"onESC", MenuParse_onESC, NULL},
 
5519
        {"border", MenuParse_border, NULL},
 
5520
        {"borderSize", MenuParse_borderSize, NULL},
 
5521
        {"backcolor", MenuParse_backcolor, NULL},
 
5522
        {"forecolor", MenuParse_forecolor, NULL},
 
5523
        {"bordercolor", MenuParse_bordercolor, NULL},
 
5524
        {"focuscolor", MenuParse_focuscolor, NULL},
 
5525
        {"disablecolor", MenuParse_disablecolor, NULL},
 
5526
        {"outlinecolor", MenuParse_outlinecolor, NULL},
 
5527
        {"background", MenuParse_background, NULL},
 
5528
        {"ownerdraw", MenuParse_ownerdraw, NULL},
 
5529
        {"ownerdrawFlag", MenuParse_ownerdrawFlag, NULL},
 
5530
        {"outOfBoundsClick", MenuParse_outOfBounds, NULL},
 
5531
        {"soundLoop", MenuParse_soundLoop, NULL},
 
5532
        {"itemDef", MenuParse_itemDef, NULL},
 
5533
        {"cinematic", MenuParse_cinematic, NULL},
 
5534
        {"popup", MenuParse_popup, NULL},
 
5535
        {"fadeClamp", MenuParse_fadeClamp, NULL},
 
5536
        {"fadeCycle", MenuParse_fadeCycle, NULL},
 
5537
        {"fadeAmount", MenuParse_fadeAmount, NULL},
 
5538
        {NULL, 0, NULL}
 
5539
};
 
5540
 
 
5541
keywordHash_t *menuParseKeywordHash[KEYWORDHASH_SIZE];
 
5542
 
 
5543
/*
 
5544
===============
 
5545
Menu_SetupKeywordHash
 
5546
===============
 
5547
*/
 
5548
void Menu_SetupKeywordHash(void) {
 
5549
        int i;
 
5550
 
 
5551
        memset(menuParseKeywordHash, 0, sizeof(menuParseKeywordHash));
 
5552
        for (i = 0; menuParseKeywords[i].keyword; i++) {
 
5553
                KeywordHash_Add(menuParseKeywordHash, &menuParseKeywords[i]);
 
5554
        }
 
5555
}
 
5556
 
 
5557
/*
 
5558
===============
 
5559
Menu_Parse
 
5560
===============
 
5561
*/
 
5562
qboolean Menu_Parse(int handle, menuDef_t *menu) {
 
5563
        pc_token_t token;
 
5564
        keywordHash_t *key;
 
5565
 
 
5566
        if (!trap_PC_ReadToken(handle, &token))
 
5567
                return qfalse;
 
5568
        if (*token.string != '{') {
 
5569
                return qfalse;
 
5570
        }
 
5571
    
 
5572
        while ( 1 ) {
 
5573
 
 
5574
                memset(&token, 0, sizeof(pc_token_t));
 
5575
                if (!trap_PC_ReadToken(handle, &token)) {
 
5576
                        PC_SourceError(handle, "end of file inside menu\n");
 
5577
                        return qfalse;
 
5578
                }
 
5579
 
 
5580
                if (*token.string == '}') {
 
5581
                        return qtrue;
 
5582
                }
 
5583
 
 
5584
                key = KeywordHash_Find(menuParseKeywordHash, token.string);
 
5585
                if (!key) {
 
5586
                        PC_SourceError(handle, "unknown menu keyword %s", token.string);
 
5587
                        continue;
 
5588
                }
 
5589
                if ( !key->func((itemDef_t*)menu, handle) ) {
 
5590
                        PC_SourceError(handle, "couldn't parse menu keyword %s", token.string);
 
5591
                        return qfalse;
 
5592
                }
 
5593
        }
 
5594
        return qfalse;  // bk001205 - LCC missing return value
 
5595
}
 
5596
 
 
5597
/*
 
5598
===============
 
5599
Menu_New
 
5600
===============
 
5601
*/
 
5602
void Menu_New(int handle) {
 
5603
        menuDef_t *menu = &Menus[menuCount];
 
5604
 
 
5605
        if (menuCount < MAX_MENUS) {
 
5606
                Menu_Init(menu);
 
5607
                if (Menu_Parse(handle, menu)) {
 
5608
                        Menu_PostParse(menu);
 
5609
                        menuCount++;
 
5610
                }
 
5611
        }
 
5612
}
 
5613
 
 
5614
int Menu_Count(void) {
 
5615
        return menuCount;
 
5616
}
 
5617
 
 
5618
void Menu_PaintAll(void) {
 
5619
        int i;
 
5620
        if (captureFunc) {
 
5621
                captureFunc(captureData);
 
5622
        }
 
5623
 
 
5624
        for (i = 0; i < Menu_Count(); i++) {
 
5625
                Menu_Paint(&Menus[i], qfalse);
 
5626
        }
 
5627
 
 
5628
        if (debugMode) {
 
5629
                vec4_t v = {1, 1, 1, 1};
 
5630
                DC->drawText(5, 25, .5, v, va("fps: %f", DC->FPS), 0, 0, 0);
 
5631
        }
 
5632
}
 
5633
 
 
5634
void Menu_Reset(void) {
 
5635
        menuCount = 0;
 
5636
}
 
5637
 
 
5638
displayContextDef_t *Display_GetContext(void) {
 
5639
        return DC;
 
5640
}
 
5641
 
 
5642
#ifndef MISSIONPACK // bk001206
 
5643
static float captureX;
 
5644
static float captureY;
 
5645
#endif
 
5646
 
 
5647
void *Display_CaptureItem(int x, int y) {
 
5648
        int i;
 
5649
 
 
5650
        for (i = 0; i < menuCount; i++) {
 
5651
                // turn off focus each item
 
5652
                // menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
 
5653
                if (Rect_ContainsPoint(&Menus[i].window.rect, x, y)) {
 
5654
                        return &Menus[i];
 
5655
                }
 
5656
        }
 
5657
        return NULL;
 
5658
}
 
5659
 
 
5660
 
 
5661
// FIXME: 
 
5662
qboolean Display_MouseMove(void *p, int x, int y) {
 
5663
        int i;
 
5664
        menuDef_t *menu = p;
 
5665
 
 
5666
        if (menu == NULL) {
 
5667
    menu = Menu_GetFocused();
 
5668
                if (menu) {
 
5669
                        if (menu->window.flags & WINDOW_POPUP) {
 
5670
                                Menu_HandleMouseMove(menu, x, y);
 
5671
                                return qtrue;
 
5672
                        }
 
5673
                }
 
5674
                for (i = 0; i < menuCount; i++) {
 
5675
                        Menu_HandleMouseMove(&Menus[i], x, y);
 
5676
                }
 
5677
        } else {
 
5678
                menu->window.rect.x += x;
 
5679
                menu->window.rect.y += y;
 
5680
                Menu_UpdatePosition(menu);
 
5681
        }
 
5682
        return qtrue;
 
5683
 
 
5684
}
 
5685
 
 
5686
int Display_CursorType(int x, int y) {
 
5687
        int i;
 
5688
        for (i = 0; i < menuCount; i++) {
 
5689
                rectDef_t r2;
 
5690
                r2.x = Menus[i].window.rect.x - 3;
 
5691
                r2.y = Menus[i].window.rect.y - 3;
 
5692
                r2.w = r2.h = 7;
 
5693
                if (Rect_ContainsPoint(&r2, x, y)) {
 
5694
                        return CURSOR_SIZER;
 
5695
                }
 
5696
        }
 
5697
        return CURSOR_ARROW;
 
5698
}
 
5699
 
 
5700
 
 
5701
void Display_HandleKey(int key, qboolean down, int x, int y) {
 
5702
        menuDef_t *menu = Display_CaptureItem(x, y);
 
5703
        if (menu == NULL) {  
 
5704
                menu = Menu_GetFocused();
 
5705
        }
 
5706
        if (menu) {
 
5707
                Menu_HandleKey(menu, key, down );
 
5708
        }
 
5709
}
 
5710
 
 
5711
static void Window_CacheContents(windowDef_t *window) {
 
5712
        if (window) {
 
5713
                if (window->cinematicName) {
 
5714
                        int cin = DC->playCinematic(window->cinematicName, 0, 0, 0, 0);
 
5715
                        DC->stopCinematic(cin);
 
5716
                }
 
5717
        }
 
5718
}
 
5719
 
 
5720
 
 
5721
static void Item_CacheContents(itemDef_t *item) {
 
5722
        if (item) {
 
5723
                Window_CacheContents(&item->window);
 
5724
        }
 
5725
 
 
5726
}
 
5727
 
 
5728
static void Menu_CacheContents(menuDef_t *menu) {
 
5729
        if (menu) {
 
5730
                int i;
 
5731
                Window_CacheContents(&menu->window);
 
5732
                for (i = 0; i < menu->itemCount; i++) {
 
5733
                        Item_CacheContents(menu->items[i]);
 
5734
                }
 
5735
 
 
5736
                if (menu->soundName && *menu->soundName) {
 
5737
                        DC->registerSound(menu->soundName, qfalse);
 
5738
                }
 
5739
        }
 
5740
 
 
5741
}
 
5742
 
 
5743
void Display_CacheAll(void) {
 
5744
        int i;
 
5745
        for (i = 0; i < menuCount; i++) {
 
5746
                Menu_CacheContents(&Menus[i]);
 
5747
        }
 
5748
}
 
5749
 
 
5750
 
 
5751
static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y) {
 
5752
        if (menu && menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED)) {
 
5753
                if (Rect_ContainsPoint(&menu->window.rect, x, y)) {
 
5754
                        int i;
 
5755
                        for (i = 0; i < menu->itemCount; i++) {
 
5756
                                // turn off focus each item
 
5757
                                // menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
 
5758
 
 
5759
                                if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
 
5760
                                        continue;
 
5761
                                }
 
5762
 
 
5763
                                if (menu->items[i]->window.flags & WINDOW_DECORATION) {
 
5764
                                        continue;
 
5765
                                }
 
5766
 
 
5767
                                if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
 
5768
                                        itemDef_t *overItem = menu->items[i];
 
5769
                                        if (overItem->type == ITEM_TYPE_TEXT && overItem->text) {
 
5770
                                                if (Rect_ContainsPoint(Item_CorrectedTextRect(overItem), x, y)) {
 
5771
                                                        return qtrue;
 
5772
                                                } else {
 
5773
                                                        continue;
 
5774
                                                }
 
5775
                                        } else {
 
5776
                                                return qtrue;
 
5777
                                        }
 
5778
                                }
 
5779
                        }
 
5780
 
 
5781
                }
 
5782
        }
 
5783
        return qfalse;
 
5784
}
 
5785