codemp/ui/ui_shared.c

Go to the documentation of this file.
00001 // 
00002 // string allocation/managment
00003 
00004 #ifndef CGAME
00005         #include "ui_local.h"
00006 #endif
00007 #ifdef _XBOX
00008 #include "../client/client.h"
00009 #endif
00010 
00011 #include "ui_shared.h"
00012 #include "../game/bg_public.h"
00013 #include "../game/anims.h"
00014 #include "../ghoul2/G2.h"
00015 extern stringID_table_t animTable [MAX_ANIMATIONS+1];
00016 extern void UI_UpdateCharacterSkin( void );
00017 
00018 
00019 #define SCROLL_TIME_START                                       500
00020 #define SCROLL_TIME_ADJUST                                      150
00021 #define SCROLL_TIME_ADJUSTOFFSET                        40
00022 #define SCROLL_TIME_FLOOR                                       20
00023 
00024 typedef struct scrollInfo_s {
00025         int nextScrollTime;
00026         int nextAdjustTime;
00027         int adjustValue;
00028         int scrollKey;
00029         float xStart;
00030         float yStart;
00031         itemDef_t *item;
00032         qboolean scrollDir;
00033 } scrollInfo_t;
00034 
00035 #ifdef _XBOX
00036 //extern void *Z_Malloc(int iSize, memtag_t eTag, qboolean bZeroit, int iAlign);
00037 //extern void Z_TagFree(memtag_t eTag);
00038 #endif
00039 
00040 
00041 #ifndef CGAME   // Defined in ui_main.c, not in the namespace
00042 extern vmCvar_t ui_char_color_red;
00043 extern vmCvar_t ui_char_color_green;
00044 extern vmCvar_t ui_char_color_blue;
00045 extern vmCvar_t se_language;
00046 
00047 // Some extern functions hoisted from the middle of this file to get all the non-cgame,
00048 // non-namespace stuff together
00049 extern void UI_SaberDrawBlades( itemDef_t *item, vec3_t origin, vec3_t angles );
00050 
00051 extern void UI_SaberLoadParms( void );
00052 extern qboolean ui_saber_parms_parsed;
00053 extern void UI_CacheSaberGlowGraphics( void );
00054 
00055 #endif //
00056 
00057 #include "../namespace_begin.h"
00058 
00059 #ifdef CGAME
00060 
00061 extern int trap_Key_GetCatcher( void ) ;
00062 extern void trap_Key_SetCatcher( int catcher );
00063 extern void trap_Cvar_Set( const char *var_name, const char *value );
00064 
00065 #endif
00066 
00067 //JLF DEMOCODE
00068 #ifdef _XBOX
00069 
00070 //support for attract mode demo timer
00071 #define DEMO_TIME_MAX  45000 //g_demoTimeBeforeStart
00072 int g_demoLastKeypress = 0;  //milliseconds
00073 bool  g_ReturnToSplash = false;
00074 bool g_runningDemo = false;
00075 
00076 void G_DemoStart();
00077 void G_DemoEnd();
00078 void G_DemoFrame();
00079 void G_DemoKeypress();
00080 
00081 void PlayDemo();
00082 //void UpdateDemoTimer();
00083 bool TestDemoTimer();
00084 //END DEMOCODE
00085 
00086 //JLF used by sliders
00087 #define TICK_COUNT 20
00088 
00089 //JLF MORE PROTOTYPES
00090 qboolean Item_HandleSelectionNext(itemDef_t * item);
00091 qboolean Item_HandleSelectionPrev(itemDef_t * item);
00092 
00093 #endif  // _XBOX
00094 
00095 qboolean Item_SetFocus(itemDef_t *item, float x, float y);
00096 
00097 static scrollInfo_t scrollInfo;
00098 
00099 static void (*captureFunc) (void *p) = 0;
00100 static void *captureData = NULL;
00101 static itemDef_t *itemCapture = NULL;   // item that has the mouse captured ( if any )
00102 
00103 displayContextDef_t *DC = NULL;
00104 
00105 static qboolean g_waitingForKey = qfalse;
00106 static qboolean g_editingField = qfalse;
00107 
00108 static itemDef_t *g_bindItem = NULL;
00109 static itemDef_t *g_editItem = NULL;
00110 
00111 menuDef_t Menus[MAX_MENUS];      // defined menus
00112 int menuCount = 0;               // how many
00113 
00114 menuDef_t *menuStack[MAX_OPEN_MENUS];
00115 int openMenuCount = 0;
00116 
00117 static qboolean debugMode = qfalse;
00118 
00119 #define DOUBLE_CLICK_DELAY 300
00120 static int lastListBoxClickTime = 0;
00121 
00122 void Item_RunScript(itemDef_t *item, const char *s);
00123 void Item_SetupKeywordHash(void);
00124 void Menu_SetupKeywordHash(void);
00125 int BindingIDFromName(const char *name);
00126 qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down);
00127 itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu);
00128 itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu);
00129 static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y);
00130 static void Item_TextScroll_BuildLines ( itemDef_t* item );
00131 void Menu_SetItemText(const menuDef_t *menu,const char *itemName, const char *text);
00132 extern qboolean ItemParse_asset_model_go( itemDef_t *item, const char *name,int *runTimeLength );
00133 extern qboolean ItemParse_model_g2anim_go( itemDef_t *item, const char *animName );
00134 
00135 
00136 #ifdef CGAME
00137 #define MEM_POOL_SIZE  128 * 1024
00138 #define UI_ALLOCATION_TAG       TAG_CG_UI_ALLOC
00139 #else
00140 //#define MEM_POOL_SIZE  1024 * 1024
00141 #define MEM_POOL_SIZE  2048 * 1024
00142 #define UI_ALLOCATION_TAG       TAG_UI_ALLOC
00143 #endif
00144 
00145 #ifndef _XBOX
00146 static char             memoryPool[MEM_POOL_SIZE];
00147 #endif // _XBOX
00148 
00149 static int              allocPoint, outOfMemory;
00150 
00151 
00152 typedef struct  itemFlagsDef_s {
00153         char *string;
00154         int value;
00155 }       itemFlagsDef_t;
00156 
00157 itemFlagsDef_t itemFlags [] = {
00158 "WINDOW_INACTIVE",              WINDOW_INACTIVE,
00159 NULL,                                   (int) NULL
00160 };
00161 
00162 char *styles [] = {
00163 "WINDOW_STYLE_EMPTY",
00164 "WINDOW_STYLE_FILLED",
00165 "WINDOW_STYLE_GRADIENT",
00166 "WINDOW_STYLE_SHADER",
00167 "WINDOW_STYLE_TEAMCOLOR",
00168 "WINDOW_STYLE_CINEMATIC",
00169 NULL
00170 };
00171 
00172 char *alignment [] = {
00173 "ITEM_ALIGN_LEFT",
00174 "ITEM_ALIGN_CENTER",
00175 "ITEM_ALIGN_RIGHT",
00176 NULL
00177 };
00178 
00179 char *types [] = {
00180 "ITEM_TYPE_TEXT",
00181 "ITEM_TYPE_BUTTON",
00182 "ITEM_TYPE_RADIOBUTTON",
00183 "ITEM_TYPE_CHECKBOX",
00184 "ITEM_TYPE_EDITFIELD",
00185 "ITEM_TYPE_COMBO",
00186 "ITEM_TYPE_LISTBOX",
00187 "ITEM_TYPE_MODEL",
00188 "ITEM_TYPE_OWNERDRAW",
00189 "ITEM_TYPE_NUMERICFIELD",
00190 "ITEM_TYPE_SLIDER",
00191 "ITEM_TYPE_YESNO",
00192 "ITEM_TYPE_MULTI",
00193 "ITEM_TYPE_BIND",
00194 "ITEM_TYPE_TEXTSCROLL",
00195 NULL
00196 };
00197 
00198 
00199 extern int MenuFontToHandle(int iMenuFont);
00200 
00201 
00202 
00203 
00204 /*
00205 ===============
00206 UI_Alloc
00207 ===============
00208 */
00209 void *UI_Alloc( int size ) {
00210 #ifdef _XBOX
00211 
00212         allocPoint += size;
00213         return Z_Malloc(size, UI_ALLOCATION_TAG, qfalse, 4);
00214 
00215 #else   // _XBOX
00216 
00217         char    *p; 
00218 
00219         if ( allocPoint + size > MEM_POOL_SIZE ) {
00220                 outOfMemory = qtrue;
00221                 if (DC->Print) {
00222                         DC->Print("UI_Alloc: Failure. Out of memory!\n");
00223                 }
00224     //DC->trap_Print(S_COLOR_YELLOW"WARNING: UI Out of Memory!\n");
00225                 return NULL;
00226         }
00227 
00228         p = &memoryPool[allocPoint];
00229 
00230         allocPoint += ( size + 15 ) & ~15;
00231 
00232         return p;
00233 #endif
00234 }
00235 
00236 /*
00237 ===============
00238 UI_InitMemory
00239 ===============
00240 */
00241 void UI_InitMemory( void ) {
00242         allocPoint = 0;
00243         outOfMemory = qfalse;
00244 #ifdef _XBOX
00245         Z_TagFree(UI_ALLOCATION_TAG);
00246 #endif
00247 }
00248 
00249 qboolean UI_OutOfMemory() {
00250         return outOfMemory;
00251 }
00252 
00253 
00254 
00255 
00256 
00257 #define HASH_TABLE_SIZE 2048
00258 /*
00259 ================
00260 return a hash value for the string
00261 ================
00262 */
00263 static long hashForString(const char *str) {
00264         int             i;
00265         long    hash;
00266         char    letter;
00267 
00268         hash = 0;
00269         i = 0;
00270         while (str[i] != '\0') {
00271                 letter = tolower((unsigned char)str[i]);
00272                 hash+=(long)(letter)*(i+119);
00273                 i++;
00274         }
00275         hash &= (HASH_TABLE_SIZE-1);
00276         return hash;
00277 }
00278 
00279 typedef struct stringDef_s {
00280         struct stringDef_s *next;
00281         const char *str;
00282 } stringDef_t;
00283 
00284 static int strPoolIndex = 0;
00285 static char strPool[STRING_POOL_SIZE];
00286 
00287 static int strHandleCount = 0;
00288 static stringDef_t *strHandle[HASH_TABLE_SIZE];
00289 
00290 
00291 const char *String_Alloc(const char *p) {
00292         int len;
00293         long hash;
00294         stringDef_t *str, *last;
00295         static const char *staticNULL = "";
00296 
00297         if (p == NULL) {
00298                 return NULL;
00299         }
00300 
00301         if (*p == 0) {
00302                 return staticNULL;
00303         }
00304 
00305         hash = hashForString(p);
00306 
00307         str = strHandle[hash];
00308         while (str) {
00309                 if (strcmp(p, str->str) == 0) {
00310                         return str->str;
00311                 }
00312                 str = str->next;
00313         }
00314 
00315         len = strlen(p);
00316         if (len + strPoolIndex + 1 < STRING_POOL_SIZE) {
00317                 int ph = strPoolIndex;
00318                 strcpy(&strPool[strPoolIndex], p);
00319                 strPoolIndex += len + 1;
00320 
00321                 str = strHandle[hash];
00322                 last = str;
00323                 while (last && last->next) 
00324                 {
00325                         last = last->next;
00326                 }
00327 
00328                 str  = (stringDef_t *) UI_Alloc(sizeof(stringDef_t));
00329                 str->next = NULL;
00330                 str->str = &strPool[ph];
00331                 if (last) {
00332                         last->next = str;
00333                 } else {
00334                         strHandle[hash] = str;
00335                 }
00336                 return &strPool[ph];
00337         }
00338 
00339         //Increase STRING_POOL_SIZE.
00340         assert(0);
00341         return NULL;
00342 }
00343 
00344 void String_Report() {
00345         float f;
00346         Com_Printf("Memory/String Pool Info\n");
00347         Com_Printf("----------------\n");
00348         f = strPoolIndex;
00349         f /= STRING_POOL_SIZE;
00350         f *= 100;
00351         Com_Printf("String Pool is %.1f%% full, %i bytes out of %i used.\n", f, strPoolIndex, STRING_POOL_SIZE);
00352         f = allocPoint;
00353         f /= MEM_POOL_SIZE;
00354         f *= 100;
00355         Com_Printf("Memory Pool is %.1f%% full, %i bytes out of %i used.\n", f, allocPoint, MEM_POOL_SIZE);
00356 }
00357 
00358 /*
00359 =================
00360 String_Init
00361 =================
00362 */
00363 void String_Init() {
00364         int i;
00365         for (i = 0; i < HASH_TABLE_SIZE; i++) {
00366                 strHandle[i] = 0;
00367         }
00368         strHandleCount = 0;
00369         strPoolIndex = 0;
00370         menuCount = 0;
00371         openMenuCount = 0;
00372         UI_InitMemory();
00373         Item_SetupKeywordHash();
00374         Menu_SetupKeywordHash();
00375         if (DC && DC->getBindingBuf) {
00376                 Controls_GetConfig();
00377         }
00378 }
00379 
00380 /*
00381 =================
00382 PC_SourceWarning
00383 =================
00384 */
00385 void PC_SourceWarning(int handle, char *format, ...) {
00386         int line;
00387         char filename[128];
00388         va_list argptr;
00389         static char string[4096];
00390 
00391         va_start (argptr, format);
00392         vsprintf (string, format, argptr);
00393         va_end (argptr);
00394 
00395         filename[0] = '\0';
00396         line = 0;
00397         trap_PC_SourceFileAndLine(handle, filename, &line);
00398 
00399         Com_Printf(S_COLOR_YELLOW "WARNING: %s, line %d: %s\n", filename, line, string);
00400 }
00401 
00402 /*
00403 =================
00404 PC_SourceError
00405 =================
00406 */
00407 void PC_SourceError(int handle, char *format, ...) {
00408         int line;
00409         char filename[128];
00410         va_list argptr;
00411         static char string[4096];
00412 
00413         va_start (argptr, format);
00414         vsprintf (string, format, argptr);
00415         va_end (argptr);
00416 
00417         filename[0] = '\0';
00418         line = 0;
00419         trap_PC_SourceFileAndLine(handle, filename, &line);
00420 
00421         Com_Printf(S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string);
00422 }
00423 
00424 /*
00425 =================
00426 LerpColor
00427 =================
00428 */
00429 void LerpColor(vec4_t a, vec4_t b, vec4_t c, float t)
00430 {
00431         int i;
00432 
00433         // lerp and clamp each component
00434         for (i=0; i<4; i++)
00435         {
00436                 c[i] = a[i] + t*(b[i]-a[i]);
00437                 if (c[i] < 0)
00438                         c[i] = 0;
00439                 else if (c[i] > 1.0)
00440                         c[i] = 1.0;
00441         }
00442 }
00443 
00444 /*
00445 =================
00446 Float_Parse
00447 =================
00448 */
00449 qboolean Float_Parse(char **p, float *f) {
00450         char    *token;
00451         token = COM_ParseExt((const char **)p, qfalse);
00452         if (token && token[0] != 0) {
00453                 *f = atof(token);
00454                 return qtrue;
00455         } else {
00456                 return qfalse;
00457         }
00458 }
00459 
00460 /*
00461 =================
00462 PC_Float_Parse
00463 =================
00464 */
00465 qboolean PC_Float_Parse(int handle, float *f) {
00466         pc_token_t token;
00467         int negative = qfalse;
00468 
00469         if (!trap_PC_ReadToken(handle, &token))
00470                 return qfalse;
00471         if (token.string[0] == '-') {
00472                 if (!trap_PC_ReadToken(handle, &token))
00473                         return qfalse;
00474                 negative = qtrue;
00475         }
00476         if (token.type != TT_NUMBER) {
00477                 PC_SourceError(handle, "expected float but found %s\n", token.string);
00478                 return qfalse;
00479         }
00480         if (negative)
00481                 *f = -token.floatvalue;
00482         else
00483                 *f = token.floatvalue;
00484         return qtrue;
00485 }
00486 
00487 /*
00488 =================
00489 Color_Parse
00490 =================
00491 */
00492 qboolean Color_Parse(char **p, vec4_t *c) {
00493         int i;
00494         float f;
00495 
00496         for (i = 0; i < 4; i++) {
00497                 if (!Float_Parse(p, &f)) {
00498                         return qfalse;
00499                 }
00500                 (*c)[i] = f;
00501         }
00502         return qtrue;
00503 }
00504 
00505 /*
00506 =================
00507 PC_Color_Parse
00508 =================
00509 */
00510 qboolean PC_Color_Parse(int handle, vec4_t *c) {
00511         int i;
00512         float f;
00513 
00514         for (i = 0; i < 4; i++) {
00515                 if (!PC_Float_Parse(handle, &f)) {
00516                         return qfalse;
00517                 }
00518                 (*c)[i] = f;
00519         }
00520         return qtrue;
00521 }
00522 
00523 /*
00524 =================
00525 Int_Parse
00526 =================
00527 */
00528 qboolean Int_Parse(char **p, int *i) {
00529         char    *token;
00530         token = COM_ParseExt((const char **)p, qfalse);
00531 
00532         if (token && token[0] != 0) {
00533                 *i = atoi(token);
00534                 return qtrue;
00535         } else {
00536                 return qfalse;
00537         }
00538 }
00539 
00540 /*
00541 =================
00542 PC_Int_Parse
00543 =================
00544 */
00545 qboolean PC_Int_Parse(int handle, int *i) {
00546         pc_token_t token;
00547         int negative = qfalse;
00548 
00549         if (!trap_PC_ReadToken(handle, &token))
00550                 return qfalse;
00551         if (token.string[0] == '-') {
00552                 if (!trap_PC_ReadToken(handle, &token))
00553                         return qfalse;
00554                 negative = qtrue;
00555         }
00556         if (token.type != TT_NUMBER) {
00557                 PC_SourceError(handle, "expected integer but found %s\n", token.string);
00558                 return qfalse;
00559         }
00560         *i = token.intvalue;
00561         if (negative)
00562                 *i = - *i;
00563         return qtrue;
00564 }
00565 
00566 /*
00567 =================
00568 Rect_Parse
00569 =================
00570 */
00571 qboolean Rect_Parse(char **p, rectDef_t *r) {
00572         if (Float_Parse(p, &r->x)) {
00573                 if (Float_Parse(p, &r->y)) {
00574                         if (Float_Parse(p, &r->w)) {
00575                                 if (Float_Parse(p, &r->h)) {
00576                                         return qtrue;
00577                                 }
00578                         }
00579                 }
00580         }
00581         return qfalse;
00582 }
00583 
00584 /*
00585 =================
00586 PC_Rect_Parse
00587 =================
00588 */
00589 qboolean PC_Rect_Parse(int handle, rectDef_t *r) {
00590         if (PC_Float_Parse(handle, &r->x)) {
00591                 if (PC_Float_Parse(handle, &r->y)) {
00592                         if (PC_Float_Parse(handle, &r->w)) {
00593                                 if (PC_Float_Parse(handle, &r->h)) {
00594                                         return qtrue;
00595                                 }
00596                         }
00597                 }
00598         }
00599         return qfalse;
00600 }
00601 
00602 /*
00603 =================
00604 String_Parse
00605 =================
00606 */
00607 qboolean String_Parse(char **p, const char **out) {
00608         char *token;
00609 
00610         token = COM_ParseExt((const char **)p, qfalse);
00611         if (token && token[0] != 0) {
00612                 *(out) = String_Alloc(token);
00613                 return *(out)!=NULL;
00614         }
00615         return qfalse;
00616 }
00617 
00618 /*
00619 =================
00620 PC_String_Parse
00621 =================
00622 */
00623 qboolean PC_String_Parse(int handle, const char **out) 
00624 {
00625         static char*    squiggy = "}";
00626         pc_token_t              token;
00627 
00628         if (!trap_PC_ReadToken(handle, &token))
00629         {
00630                 return qfalse;
00631         }
00632 
00633         // Save some memory by not return the end squiggy as an allocated string
00634         if ( !Q_stricmp ( token.string, "}" ) )
00635         {
00636                 *(out) = squiggy;
00637         }
00638         else
00639         {
00640                 *(out) = String_Alloc(token.string);
00641         }
00642         return qtrue;
00643 }
00644 
00645 /*
00646 =================
00647 PC_Script_Parse
00648 =================
00649 */
00650 qboolean PC_Script_Parse(int handle, const char **out) {
00651         char script[2048];
00652         pc_token_t token;
00653 
00654         script[0] = 0;
00655         // scripts start with { and have ; separated command lists.. commands are command, arg.. 
00656         // basically we want everything between the { } as it will be interpreted at run time
00657   
00658         if (!trap_PC_ReadToken(handle, &token))
00659                 return qfalse;
00660         if (Q_stricmp(token.string, "{") != 0) {
00661             return qfalse;
00662         }
00663 
00664         while ( 1 ) {
00665                 if (!trap_PC_ReadToken(handle, &token))
00666                         return qfalse;
00667 
00668                 if (Q_stricmp(token.string, "}") == 0) {
00669                         *out = String_Alloc(script);
00670                         return qtrue;
00671                 }
00672 
00673                 if (token.string[1] != '\0') {
00674                         Q_strcat(script, 2048, va("\"%s\"", token.string));
00675                 } else {
00676                         Q_strcat(script, 2048, token.string);
00677                 }
00678                 Q_strcat(script, 2048, " ");
00679         }
00680         return qfalse;  // bk001105 - LCC   missing return value
00681 }
00682 
00683 // display, window, menu, item code
00684 // 
00685 
00686 /*
00687 ==================
00688 Init_Display
00689 
00690 Initializes the display with a structure to all the drawing routines
00691  ==================
00692 */
00693 void Init_Display(displayContextDef_t *dc) {
00694         DC = dc;
00695 }
00696 
00697 
00698 
00699 // type and style painting 
00700 
00701 void GradientBar_Paint(rectDef_t *rect, vec4_t color) {
00702         // gradient bar takes two paints
00703         DC->setColor( color );
00704         DC->drawHandlePic(rect->x, rect->y, rect->w, rect->h, DC->Assets.gradientBar);
00705         DC->setColor( NULL );
00706 }
00707 
00708 
00709 /*
00710 ==================
00711 Window_Init
00712 
00713 Initializes a window structure ( windowDef_t ) with defaults
00714  
00715 ==================
00716 */
00717 void Window_Init(Window *w) {
00718         memset(w, 0, sizeof(windowDef_t));
00719         w->borderSize = 1;
00720         w->foreColor[0] = w->foreColor[1] = w->foreColor[2] = w->foreColor[3] = 1.0;
00721         w->cinematic = -1;
00722 }
00723 
00724 void Fade(int *flags, float *f, float clamp, int *nextTime, int offsetTime, qboolean bFlags, float fadeAmount) {
00725   if (*flags & (WINDOW_FADINGOUT | WINDOW_FADINGIN)) {
00726     if (DC->realTime > *nextTime) {
00727       *nextTime = DC->realTime + offsetTime;
00728       if (*flags & WINDOW_FADINGOUT) {
00729         *f -= fadeAmount;
00730         if (bFlags && *f <= 0.0) {
00731           *flags &= ~(WINDOW_FADINGOUT | WINDOW_VISIBLE);
00732         }
00733       } else {
00734         *f += fadeAmount;
00735         if (*f >= clamp) {
00736           *f = clamp;
00737           if (bFlags) {
00738             *flags &= ~WINDOW_FADINGIN;
00739           }
00740         }
00741       }
00742     }
00743   }
00744 }
00745 
00746 
00747 
00748 void Window_Paint(Window *w, float fadeAmount, float fadeClamp, float fadeCycle) 
00749 {
00750         //float bordersize = 0;
00751         vec4_t color;
00752         rectDef_t fillRect = w->rect;
00753 
00754 
00755         if (debugMode) 
00756         {
00757                 color[0] = color[1] = color[2] = color[3] = 1;
00758                 DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, 1, color);
00759         }
00760 
00761         if (w == NULL || (w->style == 0 && w->border == 0)) 
00762         {
00763                 return;
00764         }
00765 
00766         if (w->border != 0) 
00767         {
00768                 fillRect.x += w->borderSize;
00769                 fillRect.y += w->borderSize;
00770                 fillRect.w -= w->borderSize + 1;
00771                 fillRect.h -= w->borderSize + 1;
00772         }
00773 
00774         if (w->style == WINDOW_STYLE_FILLED) 
00775         {
00776                 // box, but possible a shader that needs filled
00777                 if (w->background) 
00778                 {
00779                         Fade(&w->flags, &w->backColor[3], fadeClamp, &w->nextTime, fadeCycle, qtrue, fadeAmount);
00780                         DC->setColor(w->backColor);
00781                         DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
00782                         DC->setColor(NULL);
00783                 } 
00784                 else 
00785                 {
00786                         DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->backColor);
00787                 }
00788         } 
00789         else if (w->style == WINDOW_STYLE_GRADIENT) 
00790         {
00791                 GradientBar_Paint(&fillRect, w->backColor);
00792         // gradient bar
00793         } 
00794         else if (w->style == WINDOW_STYLE_SHADER) 
00795         {
00796 #ifndef CGAME
00797                 if (w->flags & WINDOW_PLAYERCOLOR) 
00798                 {
00799                         vec4_t  color;
00800                         color[0] = ui_char_color_red.integer/255.0f;
00801                         color[1] = ui_char_color_green.integer/255.0f;
00802                         color[2] = ui_char_color_blue.integer/255.0f;
00803                         color[3] = 1;
00804                         DC->setColor(color);
00805                 }
00806 #endif // 
00807 
00808                 if (w->flags & WINDOW_FORECOLORSET) 
00809                 {
00810                         DC->setColor(w->foreColor);
00811                 }
00812                 DC->drawHandlePic(fillRect.x, fillRect.y, fillRect.w, fillRect.h, w->background);
00813                 DC->setColor(NULL);
00814         } 
00815         else if (w->style == WINDOW_STYLE_TEAMCOLOR) 
00816         {
00817                 if (DC->getTeamColor) 
00818                 {
00819                         DC->getTeamColor(&color);
00820                         DC->fillRect(fillRect.x, fillRect.y, fillRect.w, fillRect.h, color);
00821                 }
00822         } 
00823         else if (w->style == WINDOW_STYLE_CINEMATIC) 
00824         {
00825                 if (w->cinematic == -1) 
00826                 {
00827                         w->cinematic = DC->playCinematic(w->cinematicName, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
00828                         if (w->cinematic == -1) 
00829                         {
00830                                 w->cinematic = -2;
00831                         }
00832                 } 
00833                 if (w->cinematic >= 0) 
00834                 {
00835                         DC->runCinematicFrame(w->cinematic);
00836                         DC->drawCinematic(w->cinematic, fillRect.x, fillRect.y, fillRect.w, fillRect.h);
00837                 }
00838         }
00839 
00840         if (w->border == WINDOW_BORDER_FULL) 
00841         {
00842                 // full
00843                 // HACK HACK HACK
00844                 if (w->style == WINDOW_STYLE_TEAMCOLOR) 
00845                 {
00846                         if (color[0] > 0) 
00847                         {                               
00848                                 // red
00849                                 color[0] = 1;
00850                                 color[1] = color[2] = .5;
00851                         } 
00852                         else 
00853                         {
00854                                 color[2] = 1;
00855                                 color[0] = color[1] = .5;
00856                         }
00857                         color[3] = 1;
00858                         DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, color);
00859                 } 
00860                 else 
00861                 {
00862                         DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize, w->borderColor);
00863                 }
00864         } 
00865         else if (w->border == WINDOW_BORDER_HORZ) 
00866         {
00867                 // top/bottom
00868                 DC->setColor(w->borderColor);
00869                 DC->drawTopBottom(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
00870                 DC->setColor( NULL );
00871         } 
00872         else if (w->border == WINDOW_BORDER_VERT) 
00873         {
00874                 // left right
00875                 DC->setColor(w->borderColor);
00876                 DC->drawSides(w->rect.x, w->rect.y, w->rect.w, w->rect.h, w->borderSize);
00877                 DC->setColor( NULL );
00878         } 
00879         else if (w->border == WINDOW_BORDER_KCGRADIENT) 
00880         {
00881                 // this is just two gradient bars along each horz edge
00882                 rectDef_t r = w->rect;
00883                 r.h = w->borderSize;
00884                 GradientBar_Paint(&r, w->borderColor);
00885                 r.y = w->rect.y + w->rect.h - 1;
00886                 GradientBar_Paint(&r, w->borderColor);
00887         }
00888 }
00889 
00890 
00891 void Item_SetScreenCoords(itemDef_t *item, float x, float y) 
00892 { 
00893 
00894         if (item == NULL) 
00895         {
00896                 return;
00897         }
00898 
00899         if (item->window.border != 0) 
00900         {
00901                 x += item->window.borderSize;
00902                 y += item->window.borderSize;
00903         }
00904 
00905         item->window.rect.x = x + item->window.rectClient.x;
00906         item->window.rect.y = y + item->window.rectClient.y;
00907         item->window.rect.w = item->window.rectClient.w;
00908         item->window.rect.h = item->window.rectClient.h;
00909 
00910         // force the text rects to recompute
00911         item->textRect.w = 0;
00912         item->textRect.h = 0;
00913 
00914         switch ( item->type)
00915         {
00916                 case ITEM_TYPE_TEXTSCROLL:
00917                 {
00918                         textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
00919                         if ( scrollPtr )
00920                         {
00921                                 scrollPtr->startPos = 0;
00922                                 scrollPtr->endPos = 0;
00923                         }
00924 
00925                         Item_TextScroll_BuildLines ( item );
00926 
00927                         break;
00928                 }
00929         }
00930 }
00931 
00932 // FIXME: consolidate this with nearby stuff
00933 void Item_UpdatePosition(itemDef_t *item) 
00934 {
00935         float x, y;
00936         menuDef_t *menu;
00937   
00938         if (item == NULL || item->parent == NULL) 
00939         {
00940                 return;
00941         }
00942 
00943         menu = (menuDef_t *) item->parent;
00944 
00945         x = menu->window.rect.x;
00946         y = menu->window.rect.y;
00947   
00948         if (menu->window.border != 0) 
00949         {
00950                 x += menu->window.borderSize;
00951                 y += menu->window.borderSize;
00952         }
00953 
00954         Item_SetScreenCoords(item, x, y);
00955 
00956 }
00957 
00958 // menus
00959 void Menu_UpdatePosition(menuDef_t *menu) {
00960   int i;
00961   float x, y;
00962 
00963   if (menu == NULL) {
00964     return;
00965   }
00966   
00967   x = menu->window.rect.x;
00968   y = menu->window.rect.y;
00969   if (menu->window.border != 0) {
00970     x += menu->window.borderSize;
00971     y += menu->window.borderSize;
00972   }
00973 
00974   for (i = 0; i < menu->itemCount; i++) {
00975     Item_SetScreenCoords(menu->items[i], x, y);
00976   }
00977 }
00978 
00979 void Menu_PostParse(menuDef_t *menu) {
00980         if (menu == NULL) {
00981                 return;
00982         }
00983         if (menu->fullScreen) {
00984                 menu->window.rect.x = 0;
00985                 menu->window.rect.y = 0;
00986                 menu->window.rect.w = 640;
00987                 menu->window.rect.h = 480;
00988         }
00989         Menu_UpdatePosition(menu);
00990 }
00991 
00992 itemDef_t *Menu_ClearFocus(menuDef_t *menu) {
00993   int i;
00994   itemDef_t *ret = NULL;
00995 
00996   if (menu == NULL) {
00997     return NULL;
00998   }
00999 
01000   for (i = 0; i < menu->itemCount; i++) {
01001     if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
01002       ret = menu->items[i];
01003     } 
01004     menu->items[i]->window.flags &= ~WINDOW_HASFOCUS;
01005     if (menu->items[i]->leaveFocus) {
01006       Item_RunScript(menu->items[i], menu->items[i]->leaveFocus);
01007     }
01008   }
01009  
01010   return ret;
01011 }
01012 
01013 qboolean IsVisible(int flags) {
01014   return (flags & WINDOW_VISIBLE && !(flags & WINDOW_FADINGOUT));
01015 }
01016 
01017 qboolean Rect_ContainsPoint(rectDef_t *rect, float x, float y) {
01018   if (rect) {
01019     if (x > rect->x && x < rect->x + rect->w && y > rect->y && y < rect->y + rect->h) {
01020       return qtrue;
01021     }
01022   }
01023   return qfalse;
01024 }
01025 
01026 int Menu_ItemsMatchingGroup(menuDef_t *menu, const char *name) 
01027 {
01028         int i;
01029         int count = 0;
01030 
01031         for (i = 0; i < menu->itemCount; i++) 
01032         {
01033                 if ((!menu->items[i]->window.name) && (!menu->items[i]->window.group))
01034                 {
01035                         Com_Printf(S_COLOR_YELLOW"WARNING: item has neither name or group\n");
01036                         continue;
01037                 }
01038 
01039                 if (Q_stricmp(menu->items[i]->window.name, name) == 0 || 
01040                         (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0)) 
01041                 {
01042                         count++;
01043                 } 
01044         }
01045 
01046         return count;
01047 }
01048 
01049 itemDef_t *Menu_GetMatchingItemByNumber(menuDef_t *menu, int index, const char *name) {
01050   int i;
01051   int count = 0;
01052   for (i = 0; i < menu->itemCount; i++) {
01053     if (Q_stricmp(menu->items[i]->window.name, name) == 0 || (menu->items[i]->window.group && Q_stricmp(menu->items[i]->window.group, name) == 0)) {
01054       if (count == index) {
01055         return menu->items[i];
01056       }
01057       count++;
01058     } 
01059   }
01060   return NULL;
01061 }
01062 
01063 qboolean Script_SetColor ( itemDef_t *item, char **args ) 
01064 {
01065         const char *name;
01066         int i;
01067         float f;
01068         vec4_t *out;
01069         
01070         // expecting type of color to set and 4 args for the color
01071         if (String_Parse(args, &name)) 
01072         {
01073                 out = NULL;
01074                 if (Q_stricmp(name, "backcolor") == 0) 
01075                 {
01076                         out = &item->window.backColor;
01077                         item->window.flags |= WINDOW_BACKCOLORSET;
01078                 } 
01079                 else if (Q_stricmp(name, "forecolor") == 0) 
01080                 {
01081                         out = &item->window.foreColor;
01082                         item->window.flags |= WINDOW_FORECOLORSET;
01083                 } 
01084                 else if (Q_stricmp(name, "bordercolor") == 0) 
01085                 {
01086                         out = &item->window.borderColor;
01087                 }
01088 
01089                 if (out) 
01090                 {
01091                         for (i = 0; i < 4; i++) 
01092                         {
01093                                 if (!Float_Parse(args, &f)) 
01094                                 {
01095                                         return qtrue;
01096                                 }
01097                         (*out)[i] = f;
01098                         }
01099                 }
01100         }
01101 
01102         return qtrue;
01103 }
01104 
01105 qboolean Script_SetAsset(itemDef_t *item, char **args) 
01106 {
01107         const char *name;
01108         // expecting name to set asset to
01109         if (String_Parse(args, &name)) 
01110         {
01111                 // check for a model 
01112                 if (item->type == ITEM_TYPE_MODEL) 
01113                 {
01114                 }
01115         }
01116         return qtrue;
01117 }
01118 
01119 qboolean Script_SetBackground(itemDef_t *item, char **args) 
01120 {
01121         const char *name;
01122         // expecting name to set asset to
01123         if (String_Parse(args, &name)) 
01124         {
01125                 item->window.background = DC->registerShaderNoMip(name);
01126         }
01127         return qtrue;
01128 }
01129 
01130 qboolean Script_SetItemRectCvar(itemDef_t *item, char **args) 
01131 {
01132         const char      *itemName;
01133         const char      *cvarName;
01134         char            cvarBuf[1024];
01135         const char      *holdVal;
01136         char            *holdBuf;
01137         itemDef_t       *item2=0;
01138         menuDef_t       *menu;  
01139 
01140         // expecting item group and cvar to get value from
01141         if (String_Parse(args, &itemName) && String_Parse(args, &cvarName)) 
01142         {
01143                 item2 = Menu_FindItemByName((menuDef_t *) item->parent, itemName);
01144 
01145                 if (item2)
01146                 {
01147                         // get cvar data
01148                         DC->getCVarString(cvarName, cvarBuf, sizeof(cvarBuf));
01149                         
01150                         holdBuf = cvarBuf;
01151                         if (String_Parse(&holdBuf,&holdVal))
01152                         {
01153                                 menu = (menuDef_t *) item->parent;
01154 
01155                                 item2->window.rectClient.x = atof(holdVal) + menu->window.rect.x;
01156                                 if (String_Parse(&holdBuf,&holdVal))
01157                                 {
01158                                         item2->window.rectClient.y = atof(holdVal) + menu->window.rect.y;
01159                                         if (String_Parse(&holdBuf,&holdVal))
01160                                         {
01161                                                 item2->window.rectClient.w = atof(holdVal);
01162                                                 if (String_Parse(&holdBuf,&holdVal))
01163                                                 {
01164                                                         item2->window.rectClient.h = atof(holdVal);
01165 
01166                                                         item2->window.rect.x = item2->window.rectClient.x;
01167                                                         item2->window.rect.y = item2->window.rectClient.y;
01168                                                         item2->window.rect.w = item2->window.rectClient.w;
01169                                                         item2->window.rect.h = item2->window.rectClient.h;
01170 
01171                                                         return qtrue;
01172                                                 }
01173                                         }
01174                                 }
01175                         }
01176                 }
01177         }
01178 
01179         // Default values in case things screw up
01180         if (item2)
01181         {
01182                 item2->window.rectClient.x = 0;
01183                 item2->window.rectClient.y = 0;
01184                 item2->window.rectClient.w = 0;
01185                 item2->window.rectClient.h = 0;
01186         }
01187 
01188 //      Com_Printf(S_COLOR_YELLOW"WARNING: SetItemRectCvar: problems. Set cvar to 0's\n" );
01189 
01190         return qtrue;
01191 }
01192 
01193 qboolean Script_SetItemBackground(itemDef_t *item, char **args) 
01194 {
01195         const char *itemName;
01196         const char *name;
01197 
01198         // expecting name of shader
01199         if (String_Parse(args, &itemName) && String_Parse(args, &name)) 
01200         {
01201                 Menu_SetItemBackground((menuDef_t *) item->parent, itemName, name);
01202         }
01203         return qtrue;
01204 }
01205 
01206 qboolean Script_SetItemText(itemDef_t *item, char **args) 
01207 {
01208         const char *itemName;
01209         const char *text;
01210 
01211         // expecting text
01212         if (String_Parse(args, &itemName) && String_Parse(args, &text)) 
01213         {
01214                 Menu_SetItemText((menuDef_t *) item->parent, itemName, text);
01215         }
01216         return qtrue;
01217 }
01218 
01219 
01220 itemDef_t *Menu_FindItemByName(menuDef_t *menu, const char *p) {
01221   int i;
01222   if (menu == NULL || p == NULL) {
01223     return NULL;
01224   }
01225 
01226   for (i = 0; i < menu->itemCount; i++) {
01227     if (Q_stricmp(p, menu->items[i]->window.name) == 0) {
01228       return menu->items[i];
01229     }
01230   }
01231 
01232   return NULL;
01233 }
01234 
01235 qboolean Script_SetTeamColor(itemDef_t *item, char **args) 
01236 {
01237         if (DC->getTeamColor) 
01238         {
01239                 int i;
01240                 vec4_t color;
01241                 DC->getTeamColor(&color);
01242                 for (i = 0; i < 4; i++) 
01243                 {
01244                         item->window.backColor[i] = color[i];
01245                 }
01246         }
01247         return qtrue;
01248 }
01249 
01250 qboolean Script_SetItemColor(itemDef_t *item, char **args) 
01251 {
01252         const char *itemname;
01253         const char *name;
01254         vec4_t color;
01255         int i;
01256         vec4_t *out;
01257 
01258         // expecting type of color to set and 4 args for the color
01259         if (String_Parse(args, &itemname) && String_Parse(args, &name)) 
01260         {
01261                 itemDef_t       *item2;
01262                 int                     j,count;
01263                 char buff[1024];
01264 
01265                 // Is is specifying a cvar to get the item name from?
01266                 if (itemname[0] == '*')
01267                 {
01268                         itemname += 1;
01269                     DC->getCVarString(itemname, buff, sizeof(buff));
01270                         itemname = buff;
01271                 }
01272 
01273                 count = Menu_ItemsMatchingGroup((menuDef_t *) item->parent, itemname);
01274 
01275                 if (!Color_Parse(args, &color)) 
01276                 {
01277                         return qtrue;
01278                 }
01279 
01280                 for (j = 0; j < count; j++) 
01281                 {
01282                         item2 = Menu_GetMatchingItemByNumber((menuDef_t *) item->parent, j, itemname);
01283                         if (item2 != NULL) 
01284                         {
01285                                 out = NULL;
01286                                 if (Q_stricmp(name, "backcolor") == 0) 
01287                                 {
01288                                         out = &item2->window.backColor;
01289                                 } 
01290                                 else if (Q_stricmp(name, "forecolor") == 0) 
01291                                 {
01292                                         out = &item2->window.foreColor;
01293                                         item2->window.flags |= WINDOW_FORECOLORSET;
01294                                 } 
01295                                 else if (Q_stricmp(name, "bordercolor") == 0) 
01296                                 {
01297                                         out = &item2->window.borderColor;
01298                                 }
01299 
01300                                 if (out) 
01301                                 {
01302                                         for (i = 0; i < 4; i++) 
01303                                         {
01304                                                 (*out)[i] = color[i];
01305                                         }
01306                                 }
01307                         }
01308                 }
01309         }
01310 
01311         return qtrue;
01312 }
01313 
01314 qboolean Script_SetItemColorCvar(itemDef_t *item, char **args) 
01315 {
01316         const char *itemname;
01317         char    *colorCvarName,*holdBuf,*holdVal;
01318         char cvarBuf[1024];
01319         const char *name;
01320         vec4_t color;
01321         int i;
01322         vec4_t *out;
01323 
01324         // expecting type of color to set and 4 args for the color
01325         if (String_Parse(args, &itemname) && String_Parse(args, &name)) 
01326         {
01327                 itemDef_t       *item2;
01328                 int                     j,count;
01329                 char buff[1024];
01330 
01331                 // Is is specifying a cvar to get the item name from?
01332                 if (itemname[0] == '*')
01333                 {
01334                         itemname += 1;
01335                     DC->getCVarString(itemname, buff, sizeof(buff));
01336                         itemname = buff;
01337                 }
01338 
01339                 count = Menu_ItemsMatchingGroup((menuDef_t *) item->parent, itemname);
01340 
01341                 // Get the cvar with the color
01342                 if (!String_Parse(args,(const char **) &colorCvarName))
01343                 {
01344                         return qtrue;
01345                 }
01346                 else
01347                 {
01348                         DC->getCVarString(colorCvarName, cvarBuf, sizeof(cvarBuf));
01349                         
01350                         holdBuf = cvarBuf;
01351                         if (String_Parse(&holdBuf,(const char **) &holdVal))
01352                         {
01353                                 color[0] = atof(holdVal);
01354                                 if (String_Parse(&holdBuf,(const char **) &holdVal))
01355                                 {
01356                                         color[1] = atof(holdVal);
01357                                         if (String_Parse(&holdBuf,(const char **) &holdVal))
01358                                         {
01359                                                 color[2] = atof(holdVal);
01360                                                 if (String_Parse(&holdBuf,(const char **) &holdVal))
01361                                                 {
01362                                                         color[3] = atof(holdVal);
01363                                                 }
01364                                         }
01365                                 }
01366                         }
01367                 }
01368 
01369                 for (j = 0; j < count; j++) 
01370                 {
01371                         item2 = Menu_GetMatchingItemByNumber((menuDef_t *) item->parent, j, itemname);
01372                         if (item2 != NULL) 
01373                         {
01374                                 out = NULL;
01375                                 if (Q_stricmp(name, "backcolor") == 0) 
01376                                 {
01377                                         out = &item2->window.backColor;
01378                                 } 
01379                                 else if (Q_stricmp(name, "forecolor") == 0) 
01380                                 {
01381                                         out = &item2->window.foreColor;
01382                                         item2->window.flags |= WINDOW_FORECOLORSET;
01383                                 } 
01384                                 else if (Q_stricmp(name, "bordercolor") == 0) 
01385                                 {
01386                                         out = &item2->window.borderColor;
01387                                 }
01388 
01389                                 if (out) 
01390                                 {
01391                                         for (i = 0; i < 4; i++) 
01392                                         {
01393                                                 (*out)[i] = color[i];
01394                                         }
01395                                 }
01396                         }
01397                 }
01398         }
01399 
01400         return qtrue;
01401 }
01402 
01403 qboolean Script_SetItemRect(itemDef_t *item, char **args) 
01404 {
01405         const char *itemname;
01406         rectDef_t *out;
01407         rectDef_t rect;
01408         menuDef_t       *menu;  
01409 
01410         // expecting type of color to set and 4 args for the color
01411         if (String_Parse(args, &itemname)) 
01412         {
01413                 itemDef_t *item2;
01414                 int j;
01415                 int count = Menu_ItemsMatchingGroup((menuDef_t *) item->parent, itemname);
01416 
01417                 if (!Rect_Parse(args, &rect)) 
01418                 {
01419                         return qtrue;
01420                 }
01421 
01422                 menu = (menuDef_t *) item->parent;
01423 
01424                 for (j = 0; j < count; j++) 
01425                 {
01426                         item2 = Menu_GetMatchingItemByNumber(menu, j, itemname);
01427                         if (item2 != NULL) 
01428                         {
01429                                 out = &item2->window.rect;
01430 
01431                                 if (out) 
01432                                 {
01433                                         item2->window.rect.x = rect.x  + menu->window.rect.x;
01434                                         item2->window.rect.y = rect.y  + menu->window.rect.y;
01435                                         item2->window.rect.w = rect.w;
01436                                         item2->window.rect.h = rect.h;                                  
01437                                 }
01438                         }
01439                 }
01440         }
01441         return qtrue;
01442 }
01443 
01444 void Menu_ShowGroup (menuDef_t *menu, char *groupName, qboolean showFlag)
01445 {
01446         itemDef_t *item;
01447         int count,j;
01448 
01449         count = Menu_ItemsMatchingGroup( menu, groupName);
01450         for (j = 0; j < count; j++) 
01451         {
01452                 item = Menu_GetMatchingItemByNumber( menu, j, groupName);
01453                 if (item != NULL) 
01454                 {
01455                         if (showFlag) 
01456                         {
01457                                 item->window.flags |= WINDOW_VISIBLE;
01458                         } 
01459                         else 
01460                         {
01461                                 item->window.flags &= ~(WINDOW_VISIBLE | WINDOW_HASFOCUS);
01462                         }
01463                 }
01464         }
01465 }
01466 
01467 void Menu_ShowItemByName(menuDef_t *menu, const char *p, qboolean bShow) {
01468         itemDef_t *item;
01469         int i;
01470         int count = Menu_ItemsMatchingGroup(menu, p);
01471         for (i = 0; i < count; i++) {
01472                 item = Menu_GetMatchingItemByNumber(menu, i, p);
01473                 if (item != NULL) {
01474                         if (bShow) {
01475                                 item->window.flags |= WINDOW_VISIBLE;
01476                         } else {
01477                                 item->window.flags &= ~WINDOW_VISIBLE;
01478                                 // stop cinematics playing in the window
01479                                 if (item->window.cinematic >= 0) {
01480                                         DC->stopCinematic(item->window.cinematic);
01481                                         item->window.cinematic = -1;
01482                                 }
01483                         }
01484                 }
01485         }
01486 }
01487 
01488 void Menu_FadeItemByName(menuDef_t *menu, const char *p, qboolean fadeOut) {
01489   itemDef_t *item;
01490   int i;
01491   int count = Menu_ItemsMatchingGroup(menu, p);
01492   for (i = 0; i < count; i++) {
01493     item = Menu_GetMatchingItemByNumber(menu, i, p);
01494     if (item != NULL) {
01495       if (fadeOut) {
01496         item->window.flags |= (WINDOW_FADINGOUT | WINDOW_VISIBLE);
01497         item->window.flags &= ~WINDOW_FADINGIN;
01498       } else {
01499         item->window.flags |= (WINDOW_VISIBLE | WINDOW_FADINGIN);
01500         item->window.flags &= ~WINDOW_FADINGOUT;
01501       }
01502     }
01503   }
01504 }
01505 
01506 menuDef_t *Menus_FindByName(const char *p) {
01507   int i;
01508   for (i = 0; i < menuCount; i++) {
01509     if (Q_stricmp(Menus[i].window.name, p) == 0) {
01510       return &Menus[i];
01511     } 
01512   }
01513   return NULL;
01514 }
01515 
01516 void Menus_ShowByName(const char *p) {
01517         menuDef_t *menu = Menus_FindByName(p);
01518         if (menu) {
01519                 Menus_Activate(menu);
01520         }
01521 }
01522 
01523 void Menus_OpenByName(const char *p) {
01524   Menus_ActivateByName(p);
01525 }
01526 
01527 static void Menu_RunCloseScript(menuDef_t *menu) {
01528         if (menu && menu->window.flags & WINDOW_VISIBLE && menu->onClose) {
01529                 itemDef_t item;
01530     item.parent = menu;
01531     Item_RunScript(&item, menu->onClose);
01532         }
01533 }
01534 
01535 void Menus_CloseByName ( const char *p )
01536 {
01537         menuDef_t *menu = Menus_FindByName(p);
01538         
01539         // If the menu wasnt found just exit
01540         if (menu == NULL) 
01541         {
01542                 return;
01543         }
01544 
01545         // Run the close script for the menu
01546         Menu_RunCloseScript(menu);
01547 
01548         // If this window had the focus then take it away
01549         if ( menu->window.flags & WINDOW_HASFOCUS )
01550         {       
01551                 // If there is something still in the open menu list then
01552                 // set it to have focus now
01553                 if ( openMenuCount )
01554                 {
01555                         // Subtract one from the open menu count to prepare to
01556                         // remove the top menu from the list
01557                         openMenuCount -= 1;
01558 
01559                         // Set the top menu to have focus now
01560                         menuStack[openMenuCount]->window.flags |= WINDOW_HASFOCUS;
01561 
01562                         // Remove the top menu from the list
01563                         menuStack[openMenuCount] = NULL;
01564                 }
01565         }
01566 
01567         // Window is now invisible and doenst have focus
01568         menu->window.flags &= ~(WINDOW_VISIBLE | WINDOW_HASFOCUS);
01569 }
01570 
01571 int FPMessageTime = 0;
01572 
01573 void Menus_CloseAll() 
01574 {
01575         int i;
01576         
01577         g_waitingForKey = qfalse;
01578         
01579         for (i = 0; i < menuCount; i++) 
01580         {
01581                 Menu_RunCloseScript ( &Menus[i] );
01582                 Menus[i].window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
01583         }
01584 
01585         // Clear the menu stack
01586         openMenuCount = 0;
01587 
01588         FPMessageTime = 0;
01589 }
01590 
01591 qboolean Script_Show(itemDef_t *item, char **args) 
01592 {
01593         const char *name;
01594         if (String_Parse(args, &name)) 
01595         {
01596                 Menu_ShowItemByName((menuDef_t *) item->parent, name, qtrue);
01597         }
01598         return qtrue;
01599 }
01600 
01601 qboolean Script_Hide(itemDef_t *item, char **args) 
01602 {
01603         const char *name;
01604         if (String_Parse(args, &name)) 
01605         {
01606                 Menu_ShowItemByName((menuDef_t *) item->parent, name, qfalse);
01607         }
01608         return qtrue;
01609 }
01610 
01611 qboolean Script_FadeIn(itemDef_t *item, char **args) 
01612 {
01613         const char *name;
01614         if (String_Parse(args, &name)) 
01615         {
01616                 Menu_FadeItemByName((menuDef_t *) item->parent, name, qfalse);
01617         }
01618 
01619         return qtrue;
01620 }
01621 
01622 qboolean Script_FadeOut(itemDef_t *item, char **args) 
01623 {
01624         const char *name;
01625         if (String_Parse(args, &name)) 
01626         {
01627                 Menu_FadeItemByName((menuDef_t *) item->parent, name, qtrue);
01628         }
01629         return qtrue;
01630 }
01631 
01632 qboolean Script_Open(itemDef_t *item, char **args) 
01633 {
01634         const char *name;
01635         if (String_Parse(args, &name)) 
01636         {
01637                 Menus_OpenByName(name);
01638         }
01639         return qtrue;
01640 }
01641 
01642 qboolean Script_Close(itemDef_t *item, char **args) 
01643 {
01644         const char *name;
01645         if (String_Parse(args, &name)) 
01646         {
01647                 if (Q_stricmp(name, "all") == 0)
01648                 {
01649                         Menus_CloseAll();
01650                 }
01651                 else
01652                 {
01653                         Menus_CloseByName(name);
01654                 }
01655         }
01656         return qtrue;
01657 }
01658 
01659 //void Menu_TransitionItemByName(menuDef_t *menu, const char *p, rectDef_t rectFrom, rectDef_t rectTo, int time, float amt) 
01660 void Menu_TransitionItemByName(menuDef_t *menu, const char *p, const rectDef_t *rectFrom, const rectDef_t *rectTo, int time, float amt) 
01661 {
01662         itemDef_t *item;
01663         int i;
01664         int count = Menu_ItemsMatchingGroup(menu, p);
01665         for (i = 0; i < count; i++) 
01666         {
01667                 item = Menu_GetMatchingItemByNumber(menu, i, p);
01668                 if (item != NULL) 
01669                 {
01670                         if (!rectFrom)
01671                         {
01672                                 rectFrom = &item->window.rect;  //if there are more than one of these with the same name, they'll all use the FIRST one's FROM.
01673                         }
01674                         item->window.flags |= (WINDOW_INTRANSITION | WINDOW_VISIBLE);
01675                         item->window.offsetTime = time;
01676                         memcpy(&item->window.rectClient, rectFrom, sizeof(rectDef_t));
01677                         memcpy(&item->window.rectEffects, rectTo, sizeof(rectDef_t));
01678                         item->window.rectEffects2.x = abs(rectTo->x - rectFrom->x) / amt;
01679                         item->window.rectEffects2.y = abs(rectTo->y - rectFrom->y) / amt;
01680                         item->window.rectEffects2.w = abs(rectTo->w - rectFrom->w) / amt;
01681                         item->window.rectEffects2.h = abs(rectTo->h - rectFrom->h) / amt;
01682 
01683                         Item_UpdatePosition(item);
01684                 }
01685         }
01686 }
01687 
01688 /*
01689 =================
01690 Menu_Transition3ItemByName
01691 =================
01692 */
01693 //JLF
01694 #define _TRANS3
01695 #ifdef _TRANS3
01696 void Menu_Transition3ItemByName(menuDef_t *menu, const char *p, const float minx, const float miny, const float minz,
01697                                                                 const float maxx, const float maxy, const float maxz, const float fovtx, const float fovty,
01698                                                                 const int time, const float amt)
01699 {
01700         itemDef_t *item;
01701         int i;
01702         int count = Menu_ItemsMatchingGroup(menu, p);
01703         modelDef_t  * modelptr;
01704         for (i = 0; i < count; i++) 
01705         {
01706                 item = Menu_GetMatchingItemByNumber(menu, i, p);
01707                 if (item != NULL) 
01708                 {
01709                         if ( item->type == ITEM_TYPE_MODEL)
01710                         {
01711                                 modelptr = (modelDef_t*)item->typeData;
01712 
01713                                 item->window.flags |= (WINDOW_INTRANSITIONMODEL | WINDOW_VISIBLE);
01714                                 item->window.offsetTime = time;
01715                                 modelptr->fov_x2 = fovtx;
01716                                 modelptr->fov_y2 = fovty;
01717                                 VectorSet(modelptr->g2maxs2, maxx, maxy, maxz);
01718                                 VectorSet(modelptr->g2mins2, minx, miny, minz);
01719 
01720 //                              //modelptr->g2maxs2.x= maxx;
01721 //                              modelptr->g2maxs2.y= maxy;
01722 //                              modelptr->g2maxs2.z= maxz;
01723 //                              modelptr->g2mins2.x= minx;
01724 //                              modelptr->g2mins2.y= miny;
01725 //                              modelptr->g2mins2.z= minz;
01726 
01727 //                              VectorSet(modelptr->g2maxs2, maxx, maxy, maxz);
01728 
01729                                 modelptr->g2maxsEffect[0] = abs(modelptr->g2maxs2[0] - modelptr->g2maxs[0]) / amt;
01730                                 modelptr->g2maxsEffect[1] = abs(modelptr->g2maxs2[1] - modelptr->g2maxs[1]) / amt;
01731                                 modelptr->g2maxsEffect[2] = abs(modelptr->g2maxs2[2] - modelptr->g2maxs[2]) / amt;
01732 
01733                                 modelptr->g2minsEffect[0] = abs(modelptr->g2mins2[0] - modelptr->g2mins[0]) / amt;
01734                                 modelptr->g2minsEffect[1] = abs(modelptr->g2mins2[1] - modelptr->g2mins[1]) / amt;
01735                                 modelptr->g2minsEffect[2] = abs(modelptr->g2mins2[2] - modelptr->g2mins[2]) / amt;
01736                                 
01737 
01738                                 modelptr->fov_Effectx = abs(modelptr->fov_x2 - modelptr->fov_x) / amt;
01739                                 modelptr->fov_Effecty = abs(modelptr->fov_y2 - modelptr->fov_y) / amt;
01740                         }
01741                                 
01742                 }
01743         }
01744 }
01745 
01746 #endif
01747 
01748 
01749 
01750 
01751 
01752 
01753 
01754 #define MAX_DEFERRED_SCRIPT             2048
01755 
01756 char            ui_deferredScript [ MAX_DEFERRED_SCRIPT ];
01757 itemDef_t*      ui_deferredScriptItem = NULL;
01758 
01759 /*
01760 =================
01761 Script_Defer
01762 
01763 Defers the rest of the script based on the defer condition.  The deferred
01764 portion of the script can later be run with the "rundeferred"
01765 =================
01766 */
01767 qboolean Script_Defer ( itemDef_t* item, char **args )
01768 {
01769         // Should the script be deferred?
01770         if ( DC->deferScript ( (char**)args ) )
01771         {
01772                 // Need the item the script was being run on
01773                 ui_deferredScriptItem = item;
01774 
01775                 // Save the rest of the script
01776                 Q_strncpyz ( ui_deferredScript, *args, MAX_DEFERRED_SCRIPT );
01777 
01778                 // No more running
01779                 return qfalse;
01780         }
01781 
01782         // Keep running the script, its ok
01783         return qtrue;
01784 }
01785 
01786 /*
01787 =================
01788 Script_RunDeferred
01789 
01790 Runs the last deferred script, there can only be one script deferred at a 
01791 time so be careful of recursion
01792 =================
01793 */
01794 qboolean Script_RunDeferred ( itemDef_t* item, char **args )
01795 {
01796         // Make sure there is something to run.
01797         if ( !ui_deferredScript[0] || !ui_deferredScriptItem )
01798         {
01799                 return qtrue;
01800         }
01801 
01802         // Run the deferred script now
01803         Item_RunScript ( ui_deferredScriptItem, ui_deferredScript );
01804 
01805         return qtrue;
01806 }
01807 
01808 qboolean Script_Transition(itemDef_t *item, char **args) 
01809 {
01810         const char *name;
01811         rectDef_t rectFrom, rectTo;
01812         int time;
01813         float amt;
01814 
01815         if (String_Parse(args, &name)) 
01816         {
01817             if ( Rect_Parse(args, &rectFrom) && Rect_Parse(args, &rectTo) && Int_Parse(args, &time) && Float_Parse(args, &amt)) 
01818                 {
01819                         Menu_TransitionItemByName((menuDef_t *) item->parent, name, &rectFrom, &rectTo, time, amt);
01820                 }
01821         }
01822 
01823         return qtrue;
01824 }
01825 
01826 void Menu_OrbitItemByName(menuDef_t *menu, const char *p, float x, float y, float cx, float cy, int time) 
01827 {
01828   itemDef_t *item;
01829   int i;
01830   int count = Menu_ItemsMatchingGroup(menu, p);
01831   for (i = 0; i < count; i++) {
01832     item = Menu_GetMatchingItemByNumber(menu, i, p);
01833     if (item != NULL) {
01834       item->window.flags |= (WINDOW_ORBITING | WINDOW_VISIBLE);
01835       item->window.offsetTime = time;
01836       item->window.rectEffects.x = cx;
01837       item->window.rectEffects.y = cy;
01838       item->window.rectClient.x = x;
01839       item->window.rectClient.y = y;
01840       Item_UpdatePosition(item);
01841     }
01842   }
01843 }
01844 
01845 void Menu_ItemDisable(menuDef_t *menu, char *name,int disableFlag)
01846 {
01847         int     j,count;
01848         itemDef_t *itemFound;
01849 
01850         count = Menu_ItemsMatchingGroup(menu, name);
01851         // Loop through all items that have this name
01852         for (j = 0; j < count; j++) 
01853         {
01854                 itemFound = Menu_GetMatchingItemByNumber( menu, j, name);
01855                 if (itemFound != NULL) 
01856                 {
01857                         itemFound->disabled = disableFlag;
01858                         // Just in case it had focus
01859                         itemFound->window.flags &= ~WINDOW_MOUSEOVER;
01860                 }
01861         }
01862 }
01863 
01864 // Set item disable flags
01865 qboolean Script_Disable(itemDef_t *item, char **args) 
01866 {
01867         char *name;
01868         int     value;
01869         menuDef_t *menu;
01870 
01871         if (String_Parse(args, (const char **)&name)) 
01872         {
01873                 char buff[1024];
01874 
01875                 // Is is specifying a cvar to get the item name from?
01876                 if (name[0] == '*')
01877                 {
01878                         name += 1;
01879                     DC->getCVarString(name, buff, sizeof(buff));
01880                         name = buff;
01881                 }
01882 
01883                 if ( Int_Parse(args, &value)) 
01884                 {
01885                         menu = Menu_GetFocused();
01886                         Menu_ItemDisable(menu, name,value);
01887                 }
01888         }
01889 
01890         return qtrue;
01891 }
01892 
01893 
01894 // Scale the given item instantly.
01895 qboolean Script_Scale(itemDef_t *item, char **args) 
01896 {
01897         const char *name;
01898         float scale;
01899         int     j,count;
01900         itemDef_t *itemFound;
01901         rectDef_t rectTo;
01902 
01903         if (String_Parse(args, &name)) 
01904         {
01905                 char buff[1024];
01906 
01907                 // Is is specifying a cvar to get the item name from?
01908                 if (name[0] == '*')
01909                 {
01910                         name += 1;
01911                     DC->getCVarString(name, buff, sizeof(buff));
01912                         name = buff;
01913                 }
01914 
01915                 count = Menu_ItemsMatchingGroup((menuDef_t *) item->parent, name);
01916 
01917                 if ( Float_Parse(args, &scale)) 
01918                 {
01919                         for (j = 0; j < count; j++) 
01920                         {
01921                                 itemFound = Menu_GetMatchingItemByNumber( (menuDef_t *) item->parent, j, name);
01922                                 if (itemFound != NULL) 
01923                                 {
01924                                         rectTo.h = itemFound->window.rect.h * scale;
01925                                         rectTo.w = itemFound->window.rect.w * scale;
01926 
01927                                         rectTo.x = itemFound->window.rect.x + ((itemFound->window.rect.h - rectTo.h)/2);
01928                                         rectTo.y = itemFound->window.rect.y + ((itemFound->window.rect.w - rectTo.w)/2);
01929 
01930                                         Menu_TransitionItemByName((menuDef_t *) item->parent, name, 0, &rectTo, 1, 1);
01931                                 }
01932                         }
01933                 }
01934         }
01935 
01936         return qtrue;
01937 }
01938 
01939 qboolean Script_Orbit(itemDef_t *item, char **args) 
01940 {
01941         const char *name;
01942         float cx, cy, x, y;
01943         int time;
01944 
01945         if (String_Parse(args, &name)) 
01946         {
01947                 if ( Float_Parse(args, &x) && Float_Parse(args, &y) && Float_Parse(args, &cx) && Float_Parse(args, &cy) && Int_Parse(args, &time) ) 
01948                 {
01949                         Menu_OrbitItemByName((menuDef_t *) item->parent, name, x, y, cx, cy, time);
01950                 }
01951         }
01952 
01953         return qtrue;
01954 }
01955 
01956 qboolean Script_SetFocus(itemDef_t *item, char **args) 
01957 {
01958   const char *name;
01959   itemDef_t *focusItem;
01960 
01961   if (String_Parse(args, &name)) {
01962     focusItem = Menu_FindItemByName((menuDef_t *) item->parent, name);
01963     if (focusItem && !(focusItem->window.flags & WINDOW_DECORATION) && !(focusItem->window.flags & WINDOW_HASFOCUS)) {
01964       Menu_ClearFocus((menuDef_t *) item->parent);
01965 //JLF
01966 #ifdef _XBOX
01967                         Item_SetFocus(focusItem, 0,0); 
01968 #else
01969                         focusItem->window.flags |= WINDOW_HASFOCUS;
01970 #endif
01971 //END JLF
01972 
01973       
01974       if (focusItem->onFocus) {
01975         Item_RunScript(focusItem, focusItem->onFocus);
01976       }
01977       if (DC->Assets.itemFocusSound) {
01978         DC->startLocalSound( DC->Assets.itemFocusSound, CHAN_LOCAL_SOUND );
01979       }
01980     }
01981   }
01982 
01983         return qtrue;
01984 }
01985 
01986 qboolean Script_SetPlayerModel(itemDef_t *item, char **args) 
01987 {
01988         const char *name;
01989         if (String_Parse(args, &name)) 
01990         {
01991                 DC->setCVar("model", name);
01992         }
01993 
01994         return qtrue;
01995 }
01996 
01997 /*
01998 =================
01999 ParseRect
02000 =================
02001 */
02002 qboolean ParseRect(const char **p, rectDef_t *r) 
02003 {
02004         if (!COM_ParseFloat(p, &r->x)) 
02005         {
02006                 if (!COM_ParseFloat(p, &r->y)) 
02007                 {
02008                         if (!COM_ParseFloat(p, &r->w)) 
02009                         {
02010                                 if (!COM_ParseFloat(p, &r->h)) 
02011                                 {
02012                                         return qtrue;
02013                                 }
02014                         }
02015                 }
02016         }
02017         return qfalse;
02018 }
02019 /*
02020 =================
02021 Script_Transition2
02022 uses current origin instead of specifing a starting origin
02023 
02024 transition2             lfvscr          25 0 202 264  20 25
02025 =================
02026 */
02027 qboolean Script_Transition2(itemDef_t *item, char **args) 
02028 {
02029         const char *name;
02030         rectDef_t rectTo;
02031         int time;
02032         float amt;
02033 
02034         if (String_Parse(args, &name)) 
02035         {
02036                 if ( ParseRect((const char **) args, &rectTo) && Int_Parse(args, &time) && !COM_ParseFloat((const char **) args, &amt)) 
02037                 {
02038                         Menu_TransitionItemByName((menuDef_t *) item->parent, name, 0, &rectTo, time, amt);
02039                 }
02040                 else
02041                 {
02042                         Com_Printf(S_COLOR_YELLOW"WARNING: Script_Transition2: error parsing '%s'\n", name );
02043                 }
02044         }
02045 
02046         return qtrue;
02047 }
02048 
02049 #ifdef _TRANS3
02050 /*
02051 JLF 
02052 =================
02053 Script_Transition3
02054 
02055 used exclusively with model views
02056 uses current origin instead of specifing a starting origin
02057 
02058 
02059 transition3             lfvscr          (min extent) (max extent) (fovx,y)  20 25
02060 =================
02061 */
02062 qboolean Script_Transition3(itemDef_t *item, char **args) 
02063 {
02064         const char *name;
02065         const char *value;
02066         float minx, miny, minz, maxx, maxy, maxz, fovtx, fovty;
02067         int time;
02068         float amt;
02069 
02070         if (String_Parse(args, &name)) 
02071         {       
02072                 if (String_Parse( args, &value))
02073                 {
02074                         minx = atof(value);
02075                         if (String_Parse( args, &value))
02076                         {       
02077                                 miny = atof(value);
02078                                 if (String_Parse( args, &value))
02079                                 {
02080                                         minz = atof(value);
02081                                         if (String_Parse( args, &value))
02082                                         {       
02083                                                 maxx = atof(value);
02084                                                 if (String_Parse( args, &value))
02085                                                 {
02086                                                         maxy = atof(value);
02087                                                         if (String_Parse( args, &value))
02088                                                         {
02089                                                                 maxz = atof(value);
02090                                                                 if (String_Parse( args, &value))
02091                                                                 {
02092                                                                         fovtx = atof(value);
02093                                                                         if (String_Parse( args, &value))
02094                                                                         {       
02095                                                                                 fovty = atof(value);
02096                                                                                 
02097                                                                                 if (String_Parse( args, &value))
02098                                                                                 {       
02099                                                                                         time = atoi(value);
02100                                                                                         if (String_Parse( args, &value))
02101                                                                                         {       
02102                                                                                                 amt = atof(value);
02103                                                                                                 //set up the variables
02104                                                                                                 Menu_Transition3ItemByName((menuDef_t *) item->parent, 
02105                                                                                                                 name,
02106                                                                                                                 minx, miny, minz,
02107                                                                                                                 maxx, maxy, maxz, 
02108                                                                                                                 fovtx, fovty,
02109                                                                                                                 time, amt);
02110                                                                                                 
02111                                                                                                 return qtrue;
02112                                                                                         }
02113                                                                                 }
02114                                                                         }
02115                                                                 }
02116                                                         }
02117                                                 }
02118                                         }
02119                                 }
02120                         }
02121                 }
02122         }
02123         Com_Printf(S_COLOR_YELLOW"WARNING: Script_Transition2: error parsing '%s'\n", name );
02124         return qtrue;
02125 }
02126 #endif
02127 
02128 
02129 
02130 
02131 
02132 
02133 
02134 
02135 
02136 
02137 
02138 
02139 
02140 
02141 
02142 
02143 
02144 
02145 
02146 
02147 
02148 
02149 
02150 qboolean Script_SetCvar(itemDef_t *item, char **args) 
02151 {
02152         const char *cvar, *val;
02153         if (String_Parse(args, &cvar) && String_Parse(args, &val)) 
02154         {
02155                 DC->setCVar(cvar, val);
02156         }
02157         return qtrue;
02158 }
02159 
02160 qboolean Script_SetCvarToCvar(itemDef_t *item, char **args) {
02161         const char *cvar, *val;
02162         if (String_Parse(args, &cvar) && String_Parse(args, &val)) {
02163                 char cvarBuf[1024];
02164                 DC->getCVarString(val, cvarBuf, sizeof(cvarBuf));
02165                 DC->setCVar(cvar, cvarBuf);
02166         }
02167         return qtrue;
02168 }
02169 
02170 qboolean Script_Exec(itemDef_t *item, char **args) {
02171         const char *val;
02172         if (String_Parse(args, &val)) {
02173                 DC->executeText(EXEC_APPEND, va("%s ; ", val));
02174         }
02175         return qtrue;
02176 }
02177 
02178 qboolean Script_Play(itemDef_t *item, char **args) {
02179         const char *val;
02180         if (String_Parse(args, &val)) {
02181                 DC->startLocalSound(DC->registerSound(val), CHAN_AUTO);
02182         }
02183         return qtrue;
02184 }
02185 
02186 qboolean Script_playLooped(itemDef_t *item, char **args) {
02187         const char *val;
02188         if (String_Parse(args, &val)) {
02189                 DC->stopBackgroundTrack();
02190                 DC->startBackgroundTrack(val, val, qfalse);
02191         }
02192         return qtrue;
02193 }
02194 
02195 
02196 commandDef_t commandList[] =
02197 {
02198   {"fadein", &Script_FadeIn},                   // group/name
02199   {"fadeout", &Script_FadeOut},                 // group/name
02200   {"show", &Script_Show},                       // group/name
02201   {"hide", &Script_Hide},                       // group/name
02202   {"setcolor", &Script_SetColor},               // works on this
02203   {"open", &Script_Open},                       // nenu
02204   {"close", &Script_Close},                     // menu
02205   {"setasset", &Script_SetAsset},               // works on this
02206   {"setbackground", &Script_SetBackground},     // works on this
02207   {"setitemrectcvar", &Script_SetItemRectCvar},                 // group/name
02208   {"setitembackground", &Script_SetItemBackground},// group/name
02209   {"setitemtext", &Script_SetItemText},                 // group/name
02210   {"setitemcolor", &Script_SetItemColor},       // group/name
02211   {"setitemcolorcvar", &Script_SetItemColorCvar},// group/name
02212   {"setitemrect", &Script_SetItemRect},                 // group/name
02213   {"setteamcolor", &Script_SetTeamColor},       // sets this background color to team color
02214   {"setfocus", &Script_SetFocus},               // sets focus
02215   {"setplayermodel", &Script_SetPlayerModel},   // sets model
02216   {"transition", &Script_Transition},           // group/name
02217   {"setcvar", &Script_SetCvar},                                 // name
02218   {"setcvartocvar", &Script_SetCvarToCvar},     // name
02219   {"exec", &Script_Exec},                                               // group/name
02220   {"play", &Script_Play},                                               // group/name
02221   {"playlooped", &Script_playLooped},           // group/name
02222   {"orbit", &Script_Orbit},                     // group/name
02223   {"scale",                     &Script_Scale},                         // group/name
02224   {"disable",           &Script_Disable},                       // group/name
02225   {"defer",                     &Script_Defer},                         // 
02226   {"rundeferred",       &Script_RunDeferred},           //
02227   {"transition2",       &Script_Transition2},                   // group/name
02228 };
02229 
02230 // Set all the items within a given menu, with the given itemName, to the given shader
02231 void Menu_SetItemBackground(const menuDef_t *menu,const char *itemName, const char *background) 
02232 {
02233         itemDef_t       *item;
02234         int                     j, count;
02235 
02236         if (!menu)      // No menu???
02237         {
02238                 return;
02239         }
02240 
02241         count = Menu_ItemsMatchingGroup( (menuDef_t *) menu, itemName);
02242 
02243         for (j = 0; j < count; j++) 
02244         {
02245                 item = Menu_GetMatchingItemByNumber( (menuDef_t *) menu, j, itemName);
02246                 if (item != NULL) 
02247                 {
02248                         item->window.background = DC->registerShaderNoMip(background);
02249                 }
02250         }
02251 }
02252 
02253 // Set all the items within a given menu, with the given itemName, to the given text
02254 void Menu_SetItemText(const menuDef_t *menu,const char *itemName, const char *text) 
02255 {
02256         itemDef_t       *item;
02257         int                     j, count;
02258 
02259         if (!menu)      // No menu???
02260         {
02261                 return;
02262         }
02263 
02264         count = Menu_ItemsMatchingGroup( (menuDef_t *) menu, itemName);
02265 
02266         for (j = 0; j < count; j++) 
02267         {
02268                 item = Menu_GetMatchingItemByNumber( (menuDef_t *) menu, j, itemName);
02269                 if (item != NULL) 
02270                 {
02271                         if (text[0] == '*')
02272                         {
02273                                 item->text = NULL;              // Null this out because this would take presidence over cvar text.
02274                                 item->cvar = text+1;
02275                                 // Just copying what was in ItemParse_cvar()
02276                                 if ( item->typeData)
02277                                 {
02278                                         editFieldDef_t *editPtr;
02279                                         editPtr = (editFieldDef_t*)item->typeData;
02280                                         editPtr->minVal = -1;
02281                                         editPtr->maxVal = -1;
02282                                         editPtr->defVal = -1;
02283                                 }
02284                         }
02285                         else
02286                         {
02287                                 item->text = text;
02288                                 if ( item->type == ITEM_TYPE_TEXTSCROLL )
02289                                 {
02290                                         textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
02291                                         if ( scrollPtr )
02292                                         {
02293                                                 scrollPtr->startPos = 0;
02294                                                 scrollPtr->endPos = 0;
02295                                         }
02296 
02297                                         Item_TextScroll_BuildLines ( item );
02298                                 }
02299                         }
02300                 }
02301         }
02302 }
02303 
02304 int scriptCommandCount = sizeof(commandList) / sizeof(commandDef_t);
02305 
02306 void Item_RunScript(itemDef_t *item, const char *s) 
02307 {
02308         char script[2048], *p;
02309         int i;
02310         qboolean bRan;
02311 
02312         script[0] = 0;
02313         
02314         if (item && s && s[0]) 
02315         {
02316                 Q_strcat(script, 2048, s);
02317                 p = script;
02318                 
02319                 while (1) 
02320                 {
02321                         const char *command;
02322 
02323                         // expect command then arguments, ; ends command, NULL ends script
02324                         if (!String_Parse(&p, &command)) 
02325                         {
02326                                 return;
02327                         }
02328 
02329                         if (command[0] == ';' && command[1] == '\0') 
02330                         {
02331                                 continue;
02332                         }
02333 
02334                         bRan = qfalse;
02335                         for (i = 0; i < scriptCommandCount; i++) 
02336                         {
02337                                 if (Q_stricmp(command, commandList[i].name) == 0) 
02338                                 {
02339                                         // Allow a script command to stop processing the script
02340                                         if ( !commandList[i].handler(item, &p) )
02341                                         {
02342                                                 return;
02343                                         }
02344 
02345                                         bRan = qtrue;
02346                                         break;
02347                                 }
02348                         }
02349 
02350                         // not in our auto list, pass to handler
02351                         if (!bRan) 
02352                         {
02353                                 DC->runScript(&p);
02354                         }
02355                 }
02356         }
02357 }
02358 
02359 
02360 qboolean Item_EnableShowViaCvar(itemDef_t *item, int flag) {
02361   char script[2048], *p;
02362   if (item && item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
02363                 char buff[2048];
02364           DC->getCVarString(item->cvarTest, buff, sizeof(buff));
02365 
02366     Q_strncpyz(script, item->enableCvar, 2048);
02367     p = script;
02368     while (1) {
02369       const char *val;
02370       // expect value then ; or NULL, NULL ends list
02371       if (!String_Parse(&p, &val)) {
02372                                 return (item->cvarFlags & flag) ? qfalse : qtrue;
02373       }
02374 
02375       if (val[0] == ';' && val[1] == '\0') {
02376         continue;
02377       }
02378 
02379                         // enable it if any of the values are true
02380                         if (item->cvarFlags & flag) {
02381         if (Q_stricmp(buff, val) == 0) {
02382                                         return qtrue;
02383                                 }
02384                         } else {
02385                                 // disable it if any of the values are true
02386         if (Q_stricmp(buff, val) == 0) {
02387                                         return qfalse;
02388                                 }
02389                         }
02390 
02391     }
02392                 return (item->cvarFlags & flag) ? qfalse : qtrue;
02393   }
02394         return qtrue;
02395 }
02396 
02397 
02398 // will optionaly set focus to this item 
02399 qboolean Item_SetFocus(itemDef_t *item, float x, float y) {
02400         int i;
02401         itemDef_t *oldFocus;
02402         sfxHandle_t *sfx = &DC->Assets.itemFocusSound;
02403         qboolean playSound = qfalse;
02404         menuDef_t *parent; // bk001206: = (menuDef_t*)item->parent;
02405         // sanity check, non-null, not a decoration and does not already have the focus
02406         if (item == NULL || item->window.flags & WINDOW_DECORATION || item->window.flags & WINDOW_HASFOCUS || !(item->window.flags & WINDOW_VISIBLE)) {
02407                 return qfalse;
02408         }
02409 
02410         // bk001206 - this can be NULL.
02411         parent = (menuDef_t*)item->parent; 
02412 
02413         // items can be enabled and disabled 
02414         if (item->disabled) 
02415         {
02416                 return qfalse;
02417         }
02418       
02419         // items can be enabled and disabled based on cvars
02420         if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
02421                 return qfalse;
02422         }
02423 
02424         if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
02425                 return qfalse;
02426         }
02427 
02428         oldFocus = Menu_ClearFocus((menuDef_t *) item->parent);
02429 
02430         if (item->type == ITEM_TYPE_TEXT) {
02431                 rectDef_t r;
02432                 r = item->textRect;
02433                 r.y -= r.h;
02434 
02435 //JLFMOUSE
02436 #ifndef _XBOX
02437                 if (Rect_ContainsPoint(&r, x, y)) 
02438 #endif
02439                 {
02440                         item->window.flags |= WINDOW_HASFOCUS;
02441                         if (item->focusSound) {
02442                                 sfx = &item->focusSound;
02443                         }
02444                         playSound = qtrue;
02445                 }
02446 #ifndef _XBOX
02447                 else 
02448 #endif
02449                 {
02450                         if (oldFocus) {
02451                                 oldFocus->window.flags |= WINDOW_HASFOCUS;
02452                                 if (oldFocus->onFocus) {
02453                                         Item_RunScript(oldFocus, oldFocus->onFocus);
02454                                 }
02455                         }
02456                 }
02457         } else {
02458             item->window.flags |= WINDOW_HASFOCUS;
02459                 if (item->onFocus) {
02460                         Item_RunScript(item, item->onFocus);
02461                 }
02462                 if (item->focusSound) {
02463                         sfx = &item->focusSound;
02464                 }
02465                 playSound = qtrue;
02466         }
02467 
02468         if (playSound && sfx) {
02469                 DC->startLocalSound( *sfx, CHAN_LOCAL_SOUND );
02470         }
02471 
02472         for (i = 0; i < parent->itemCount; i++) {
02473                 if (parent->items[i] == item) {
02474                         parent->cursorItem = i;
02475                         break;
02476                 }
02477         }
02478 
02479         return qtrue;
02480 }
02481 
02482 int Item_TextScroll_MaxScroll ( itemDef_t *item ) 
02483 {
02484         textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
02485         
02486         int count = scrollPtr->iLineCount;
02487         int max   = count - (int)(item->window.rect.h / scrollPtr->lineHeight) + 1;
02488 
02489         if (max < 0) 
02490         {
02491                 return 0;
02492         }
02493 
02494         return max;
02495 }
02496 
02497 int Item_TextScroll_ThumbPosition ( itemDef_t *item ) 
02498 {
02499         float max, pos, size;
02500         textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
02501 
02502         max  = Item_TextScroll_MaxScroll ( item );
02503         size = item->window.rect.h - (SCROLLBAR_SIZE * 2) - 2;
02504 
02505         if (max > 0) 
02506         {
02507                 pos = (size-SCROLLBAR_SIZE) / (float) max;
02508         } 
02509         else 
02510         {
02511                 pos = 0;
02512         }
02513         
02514         pos *= scrollPtr->startPos;
02515         
02516         return item->window.rect.y + 1 + SCROLLBAR_SIZE + pos;
02517 }
02518 
02519 int Item_TextScroll_ThumbDrawPosition ( itemDef_t *item ) 
02520 {
02521         int min, max;
02522 
02523         if (itemCapture == item) 
02524         {
02525                 min = item->window.rect.y + SCROLLBAR_SIZE + 1;
02526                 max = item->window.rect.y + item->window.rect.h - 2*SCROLLBAR_SIZE - 1;
02527 
02528                 if (DC->cursory >= min + SCROLLBAR_SIZE/2 && DC->cursory <= max + SCROLLBAR_SIZE/2) 
02529                 {
02530                         return DC->cursory - SCROLLBAR_SIZE/2;
02531                 }
02532 
02533                 return Item_TextScroll_ThumbPosition(item);
02534         }
02535 
02536         return Item_TextScroll_ThumbPosition(item);
02537 }
02538 
02539 int Item_TextScroll_OverLB ( itemDef_t *item, float x, float y ) 
02540 {
02541         rectDef_t               r;
02542         textScrollDef_t *scrollPtr;
02543         int                             thumbstart;
02544         int                             count;
02545 
02546         scrollPtr = (textScrollDef_t*)item->typeData;
02547         count     = scrollPtr->iLineCount;
02548 
02549         r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
02550         r.y = item->window.rect.y;
02551         r.h = r.w = SCROLLBAR_SIZE;
02552         if (Rect_ContainsPoint(&r, x, y)) 
02553         {
02554                 return WINDOW_LB_LEFTARROW;
02555         }
02556 
02557         r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
02558         if (Rect_ContainsPoint(&r, x, y)) 
02559         {
02560                 return WINDOW_LB_RIGHTARROW;
02561         }
02562 
02563         thumbstart = Item_TextScroll_ThumbPosition(item);
02564         r.y = thumbstart;
02565         if (Rect_ContainsPoint(&r, x, y)) 
02566         {
02567                 return WINDOW_LB_THUMB;
02568         }
02569 
02570         r.y = item->window.rect.y + SCROLLBAR_SIZE;
02571         r.h = thumbstart - r.y;
02572         if (Rect_ContainsPoint(&r, x, y)) 
02573         {
02574                 return WINDOW_LB_PGUP;
02575         }
02576 
02577         r.y = thumbstart + SCROLLBAR_SIZE;
02578         r.h = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
02579         if (Rect_ContainsPoint(&r, x, y)) 
02580         {
02581                 return WINDOW_LB_PGDN;
02582         }
02583 
02584         return 0;
02585 }
02586 
02587 void Item_TextScroll_MouseEnter (itemDef_t *item, float x, float y) 
02588 {
02589         item->window.flags &= ~(WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN);
02590         item->window.flags |= Item_TextScroll_OverLB(item, x, y);
02591 }
02592 
02593 qboolean Item_TextScroll_HandleKey ( itemDef_t *item, int key, qboolean down, qboolean force) 
02594 {
02595         textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
02596         int                             max;
02597         int                             viewmax;
02598 
02599         if (force || (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS)) 
02600         {
02601                 max = Item_TextScroll_MaxScroll(item);
02602 
02603                 viewmax = (item->window.rect.h / scrollPtr->lineHeight);
02604                 if ( key == A_CURSOR_UP || key == A_KP_8 ) 
02605                 {
02606                         scrollPtr->startPos--;
02607                         if (scrollPtr->startPos < 0)
02608                         {
02609                                 scrollPtr->startPos = 0;
02610                         }
02611                         return qtrue;
02612                 }
02613 
02614                 if ( key == A_CURSOR_DOWN || key == A_KP_2 ) 
02615                 {
02616                         scrollPtr->startPos++;
02617                         if (scrollPtr->startPos > max)
02618                         {
02619                                 scrollPtr->startPos = max;
02620                         }
02621 
02622                         return qtrue;
02623                 }
02624 
02625                 // mouse hit
02626                 if (key == A_MOUSE1 || key == A_MOUSE2) 
02627                 {
02628                         if (item->window.flags & WINDOW_LB_LEFTARROW) 
02629                         {
02630                                 scrollPtr->startPos--;
02631                                 if (scrollPtr->startPos < 0) 
02632                                 {
02633                                         scrollPtr->startPos = 0;
02634                                 }
02635                         } 
02636                         else if (item->window.flags & WINDOW_LB_RIGHTARROW) 
02637                         {
02638                                 // one down
02639                                 scrollPtr->startPos++;
02640                                 if (scrollPtr->startPos > max) 
02641                                 {
02642                                         scrollPtr->startPos = max;
02643                                 }
02644                         } 
02645                         else if (item->window.flags & WINDOW_LB_PGUP) 
02646                         {
02647                                 // page up
02648                                 scrollPtr->startPos -= viewmax;
02649                                 if (scrollPtr->startPos < 0) 
02650                                 {
02651                                         scrollPtr->startPos = 0;
02652                                 }
02653                         } 
02654                         else if (item->window.flags & WINDOW_LB_PGDN) 
02655                         {
02656                                 // page down
02657                                 scrollPtr->startPos += viewmax;
02658                                 if (scrollPtr->startPos > max) 
02659                                 {
02660                                         scrollPtr->startPos = max;
02661                                 }
02662                         } 
02663                         else if (item->window.flags & WINDOW_LB_THUMB) 
02664                         {
02665                                 // Display_SetCaptureItem(item);
02666                         } 
02667 
02668                         return qtrue;
02669                 }
02670 
02671                 if ( key == A_HOME || key == A_KP_7) 
02672                 {
02673                         // home
02674                         scrollPtr->startPos = 0;
02675                         return qtrue;
02676                 }
02677                 if ( key == A_END || key == A_KP_1) 
02678                 {
02679                         // end
02680                         scrollPtr->startPos = max;
02681                         return qtrue;
02682                 }
02683                 if (key == A_PAGE_UP || key == A_KP_9 ) 
02684                 {
02685                         scrollPtr->startPos -= viewmax;
02686                         if (scrollPtr->startPos < 0) 
02687                         {
02688                                         scrollPtr->startPos = 0;
02689                         }
02690 
02691                         return qtrue;
02692                 }
02693                 if ( key == A_PAGE_DOWN || key == A_KP_3 ) 
02694                 {
02695                         scrollPtr->startPos += viewmax;
02696                         if (scrollPtr->startPos > max) 
02697                         {
02698                                 scrollPtr->startPos = max;
02699                         }
02700                         return qtrue;
02701                 }
02702         }
02703 
02704         return qfalse;
02705 }
02706 
02707 int Item_ListBox_MaxScroll(itemDef_t *item) {
02708         listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
02709         int count = DC->feederCount(item->special);
02710         int max;
02711 
02712         if (item->window.flags & WINDOW_HORIZONTAL) {
02713                 max = count - (item->window.rect.w / listPtr->elementWidth) + 1;
02714         }
02715         else {
02716                 max = count - (item->window.rect.h / listPtr->elementHeight) + 1;
02717         }
02718         if (max < 0) {
02719                 return 0;
02720         }
02721         return max;
02722 }
02723 
02724 int Item_ListBox_ThumbPosition(itemDef_t *item) {
02725         float max, pos, size;
02726         listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
02727 
02728         max = Item_ListBox_MaxScroll(item);
02729         if (item->window.flags & WINDOW_HORIZONTAL) {
02730                 size = item->window.rect.w - (SCROLLBAR_SIZE * 2) - 2;
02731                 if (max > 0) {
02732                         pos = (size-SCROLLBAR_SIZE) / (float) max;
02733                 } else {
02734                         pos = 0;
02735                 }
02736                 pos *= listPtr->startPos;
02737                 return item->window.rect.x + 1 + SCROLLBAR_SIZE + pos;
02738         }
02739         else {
02740                 size = item->window.rect.h - (SCROLLBAR_SIZE * 2) - 2;
02741                 if (max > 0) {
02742                         pos = (size-SCROLLBAR_SIZE) / (float) max;
02743                 } else {
02744                         pos = 0;
02745                 }
02746                 pos *= listPtr->startPos;
02747                 return item->window.rect.y + 1 + SCROLLBAR_SIZE + pos;
02748         }
02749 }
02750 
02751 int Item_ListBox_ThumbDrawPosition(itemDef_t *item) 
02752 {
02753         int min, max;
02754 
02755         if (itemCapture == item) 
02756         {
02757                 if (item->window.flags & WINDOW_HORIZONTAL) 
02758                 {
02759                         min = item->window.rect.x + SCROLLBAR_SIZE + 1;
02760                         max = item->window.rect.x + item->window.rect.w - 2*SCROLLBAR_SIZE - 1;
02761                         if (DC->cursorx >= min + SCROLLBAR_SIZE/2 && DC->cursorx <= max + SCROLLBAR_SIZE/2) 
02762                         {
02763                                 return DC->cursorx - SCROLLBAR_SIZE/2;
02764                         }
02765                         else 
02766                         {
02767                                 return Item_ListBox_ThumbPosition(item);
02768                         }
02769                 }
02770                 else 
02771                 {
02772                         min = item->window.rect.y + SCROLLBAR_SIZE + 1;
02773                         max = item->window.rect.y + item->window.rect.h - 2*SCROLLBAR_SIZE - 1;
02774                         if (DC->cursory >= min + SCROLLBAR_SIZE/2 && DC->cursory <= max + SCROLLBAR_SIZE/2) 
02775                         {
02776                                 return DC->cursory - SCROLLBAR_SIZE/2;
02777                         }
02778                         else 
02779                         {
02780                                 return Item_ListBox_ThumbPosition(item);
02781                         }
02782                 }
02783         }
02784         else 
02785         {
02786                 return Item_ListBox_ThumbPosition(item);
02787         }
02788 }
02789 
02790 float Item_Slider_ThumbPosition(itemDef_t *item) {
02791         float value, range, x;
02792         editFieldDef_t *editDef = (editFieldDef_t *) item->typeData;
02793 
02794         if (item->text) {
02795                 x = item->textRect.x + item->textRect.w + 8;
02796         } else {
02797                 x = item->window.rect.x;
02798         }
02799 
02800         if (editDef == NULL && item->cvar) {
02801                 return x;
02802         }
02803 
02804         value = DC->getCVarValue(item->cvar);
02805 
02806         if (value < editDef->minVal) {
02807                 value = editDef->minVal;
02808         } else if (value > editDef->maxVal) {
02809                 value = editDef->maxVal;
02810         }
02811 
02812         range = editDef->maxVal - editDef->minVal;
02813         value -= editDef->minVal;
02814         value /= range;
02815         //value /= (editDef->maxVal - editDef->minVal);
02816         value *= SLIDER_WIDTH;
02817         x += value;
02818         // vm fuckage
02819         //x = x + (((float)value / editDef->maxVal) * SLIDER_WIDTH);
02820         return x;
02821 }
02822 
02823 int Item_Slider_OverSlider(itemDef_t *item, float x, float y) {
02824         rectDef_t r;
02825 
02826         r.x = Item_Slider_ThumbPosition(item) - (SLIDER_THUMB_WIDTH / 2);
02827         r.y = item->window.rect.y - 2;
02828         r.w = SLIDER_THUMB_WIDTH;
02829         r.h = SLIDER_THUMB_HEIGHT;
02830 
02831         if (Rect_ContainsPoint(&r, x, y)) {
02832                 return WINDOW_LB_THUMB;
02833         }
02834         return 0;
02835 }
02836 
02837 int Item_ListBox_OverLB(itemDef_t *item, float x, float y) 
02838 {
02839         rectDef_t r;
02840         listBoxDef_t *listPtr;
02841         int thumbstart;
02842         int count;
02843 
02844         count = DC->feederCount(item->special);
02845         listPtr = (listBoxDef_t*)item->typeData;
02846         if (item->window.flags & WINDOW_HORIZONTAL) 
02847         {
02848                 // check if on left arrow
02849                 r.x = item->window.rect.x;
02850                 r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
02851                 r.h = r.w = SCROLLBAR_SIZE;
02852                 if (Rect_ContainsPoint(&r, x, y)) 
02853                 {
02854                         return WINDOW_LB_LEFTARROW;
02855                 }
02856 
02857                 // check if on right arrow
02858                 r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
02859                 if (Rect_ContainsPoint(&r, x, y)) 
02860                 {
02861                         return WINDOW_LB_RIGHTARROW;
02862                 }
02863 
02864                 // check if on thumb
02865                 thumbstart = Item_ListBox_ThumbPosition(item);
02866                 r.x = thumbstart;
02867                 if (Rect_ContainsPoint(&r, x, y)) 
02868                 {
02869                         return WINDOW_LB_THUMB;
02870                 }
02871 
02872                 r.x = item->window.rect.x + SCROLLBAR_SIZE;
02873                 r.w = thumbstart - r.x;
02874                 if (Rect_ContainsPoint(&r, x, y)) 
02875                 {
02876                         return WINDOW_LB_PGUP;
02877                 }
02878 
02879                 r.x = thumbstart + SCROLLBAR_SIZE;
02880                 r.w = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
02881                 if (Rect_ContainsPoint(&r, x, y)) 
02882                 {
02883                         return WINDOW_LB_PGDN;
02884                 }
02885         }
02886         // Vertical Scroll
02887         else 
02888         {
02889                 // Multiple rows and columns (since it's more than twice as wide as an element)
02890                 if (( item->window.rect.w > (listPtr->elementWidth*2)) &&  (listPtr->elementStyle == LISTBOX_IMAGE))
02891                 {
02892                         r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
02893                         r.y = item->window.rect.y;
02894                         r.h = r.w = SCROLLBAR_SIZE;
02895                         if (Rect_ContainsPoint(&r, x, y)) 
02896                         {
02897                                 return WINDOW_LB_PGUP;
02898                         }
02899 
02900                         r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
02901                         if (Rect_ContainsPoint(&r, x, y)) 
02902                         {
02903                                 return WINDOW_LB_PGDN;
02904                         }
02905 
02906                         thumbstart = Item_ListBox_ThumbPosition(item);
02907                         r.y = thumbstart;
02908                         if (Rect_ContainsPoint(&r, x, y)) 
02909                         {
02910                                 return WINDOW_LB_THUMB;
02911                         }
02912 
02913                 }
02914                 else
02915                 {
02916                         r.x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE;
02917                         r.y = item->window.rect.y;
02918                         r.h = r.w = SCROLLBAR_SIZE;
02919                         if (Rect_ContainsPoint(&r, x, y)) 
02920                         {
02921                                 return WINDOW_LB_LEFTARROW;
02922                         }
02923 
02924                         r.y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
02925                         if (Rect_ContainsPoint(&r, x, y)) 
02926                         {
02927                                 return WINDOW_LB_RIGHTARROW;
02928                         }
02929 
02930                         thumbstart = Item_ListBox_ThumbPosition(item);
02931                         r.y = thumbstart;
02932                         if (Rect_ContainsPoint(&r, x, y)) 
02933                         {
02934                                 return WINDOW_LB_THUMB;
02935                         }
02936 
02937                         r.y = item->window.rect.y + SCROLLBAR_SIZE;
02938                         r.h = thumbstart - r.y;
02939                         if (Rect_ContainsPoint(&r, x, y)) 
02940                         {
02941                                 return WINDOW_LB_PGUP;
02942                         }
02943 
02944                         r.y = thumbstart + SCROLLBAR_SIZE;
02945                         r.h = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE;
02946                         if (Rect_ContainsPoint(&r, x, y)) 
02947                         {
02948                                 return WINDOW_LB_PGDN;
02949                         }
02950                 }
02951         }
02952         return 0;
02953 }
02954 
02955 
02956 void Item_ListBox_MouseEnter(itemDef_t *item, float x, float y) 
02957 {
02958         rectDef_t r;
02959         listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
02960         
02961         item->window.flags &= ~(WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN);
02962         item->window.flags |= Item_ListBox_OverLB(item, x, y);
02963 
02964         if (item->window.flags & WINDOW_HORIZONTAL) 
02965         {
02966                 if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN))) 
02967                 {
02968                         // check for selection hit as we have exausted buttons and thumb
02969                         if (listPtr->elementStyle == LISTBOX_IMAGE) 
02970                         {
02971                                 r.x = item->window.rect.x;
02972                                 r.y = item->window.rect.y;
02973                                 r.h = item->window.rect.h - SCROLLBAR_SIZE;
02974                                 r.w = item->window.rect.w - listPtr->drawPadding;
02975                                 if (Rect_ContainsPoint(&r, x, y)) 
02976                                 {
02977                                         listPtr->cursorPos =  (int)((x - r.x) / listPtr->elementWidth)  + listPtr->startPos;
02978                                         if (listPtr->cursorPos >= listPtr->endPos) 
02979                                         {
02980                                                 listPtr->cursorPos = listPtr->endPos;
02981                                         }
02982                                 }
02983                         } 
02984                         else 
02985                         {
02986                                 // text hit.. 
02987                         }
02988                 }
02989         } 
02990         // Window Vertical Scroll
02991         else if (!(item->window.flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW | WINDOW_LB_THUMB | WINDOW_LB_PGUP | WINDOW_LB_PGDN))) 
02992         {
02993                 // Calc which element the mouse is over
02994                 r.x = item->window.rect.x;
02995                 r.y = item->window.rect.y;
02996                 r.w = item->window.rect.w - SCROLLBAR_SIZE;
02997                 r.h = item->window.rect.h - listPtr->drawPadding;
02998                 if (Rect_ContainsPoint(&r, x, y)) 
02999                 {
03000                         // Multiple rows and columns (since it's more than twice as wide as an element)
03001                         if (( item->window.rect.w > (listPtr->elementWidth*2)) &&  (listPtr->elementStyle == LISTBOX_IMAGE))
03002                         {
03003                                 int row,column,rowLength;
03004 
03005                                 row = (int)((y - 2 - r.y) / listPtr->elementHeight);
03006                                 rowLength = (int) r.w / listPtr->elementWidth;
03007                                 column = (int)((x - r.x) / listPtr->elementWidth);
03008 
03009                                 listPtr->cursorPos = (row * rowLength)+column  + listPtr->startPos;
03010                                 if (listPtr->cursorPos >= listPtr->endPos) 
03011                                 {
03012                                         listPtr->cursorPos = listPtr->endPos;
03013                                 }
03014                         }
03015                         // single column
03016                         else
03017                         {
03018                                 listPtr->cursorPos =  (int)((y - 2 - r.y) / listPtr->elementHeight)  + listPtr->startPos;
03019                                 if (listPtr->cursorPos > listPtr->endPos) 
03020                                 {
03021                     listPtr->cursorPos = listPtr->endPos;
03022                                 }
03023                         }
03024                 }
03025         }
03026 }
03027 
03028 void Item_MouseEnter(itemDef_t *item, float x, float y) {
03029 
03030         rectDef_t r;
03031         if (item) {
03032                 r = item->textRect;
03033                 r.y -= r.h;
03034                 // in the text rect?
03035 
03036                 // items can be enabled and disabled 
03037                 if (item->disabled) 
03038                 {
03039                         return;
03040                 }
03041 
03042                 // items can be enabled and disabled based on cvars
03043                 if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
03044                         return;
03045                 }
03046 
03047                 if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(item, CVAR_SHOW)) {
03048                         return;
03049                 }
03050 
03051 //JLFMOUSE 
03052 #ifndef _XBOX
03053                 if (Rect_ContainsPoint(&r, x, y)) 
03054 #else
03055                 if (item->flags & WINDOW_HASFOCUS)
03056 #endif
03057                 {
03058                         if (!(item->window.flags & WINDOW_MOUSEOVERTEXT)) {
03059                                 Item_RunScript(item, item->mouseEnterText);
03060                                 item->window.flags |= WINDOW_MOUSEOVERTEXT;
03061                         }
03062                         if (!(item->window.flags & WINDOW_MOUSEOVER)) {
03063                                 Item_RunScript(item, item->mouseEnter);
03064                                 item->window.flags |= WINDOW_MOUSEOVER;
03065                         }
03066 
03067                 } else {
03068                         // not in the text rect
03069                         if (item->window.flags & WINDOW_MOUSEOVERTEXT) {
03070                                 // if we were
03071                                 Item_RunScript(item, item->mouseExitText);
03072                                 item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
03073                         }
03074                         if (!(item->window.flags & WINDOW_MOUSEOVER)) {
03075                                 Item_RunScript(item, item->mouseEnter);
03076                                 item->window.flags |= WINDOW_MOUSEOVER;
03077                         }
03078 
03079                         if (item->type == ITEM_TYPE_LISTBOX) {
03080                                 Item_ListBox_MouseEnter(item, x, y);
03081                         }
03082                         else if ( item->type == ITEM_TYPE_TEXTSCROLL )
03083                         {
03084                                 Item_TextScroll_MouseEnter ( item, x, y );
03085                         }
03086                 }
03087         }
03088 }
03089 
03090 void Item_MouseLeave(itemDef_t *item) {
03091   if (item) {
03092     if (item->window.flags & WINDOW_MOUSEOVERTEXT) {
03093       Item_RunScript(item, item->mouseExitText);
03094       item->window.flags &= ~WINDOW_MOUSEOVERTEXT;
03095     }
03096     Item_RunScript(item, item->mouseExit);
03097     item->window.flags &= ~(WINDOW_LB_RIGHTARROW | WINDOW_LB_LEFTARROW);
03098   }
03099 }
03100 
03101 itemDef_t *Menu_HitTest(menuDef_t *menu, float x, float y) {
03102   int i;
03103   for (i = 0; i < menu->itemCount; i++) {
03104     if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
03105       return menu->items[i];
03106     }
03107   }
03108   return NULL;
03109 }
03110 
03111 void Item_SetMouseOver(itemDef_t *item, qboolean focus) {
03112   if (item) {
03113     if (focus) {
03114       item->window.flags |= WINDOW_MOUSEOVER;
03115     } else {
03116       item->window.flags &= ~WINDOW_MOUSEOVER;
03117     }
03118   }
03119 }
03120 
03121 
03122 qboolean Item_OwnerDraw_HandleKey(itemDef_t *item, int key) {
03123   if (item && DC->ownerDrawHandleKey)
03124   {
03125         
03126           // yep this is an ugly hack
03127           if( key == A_MOUSE1 || key == A_MOUSE2 )
03128           {
03129                 switch( item->window.ownerDraw )
03130                 {
03131                         case UI_FORCE_SIDE:
03132                         case UI_FORCE_RANK_HEAL:
03133                         case UI_FORCE_RANK_LEVITATION:
03134                         case UI_FORCE_RANK_SPEED:
03135                         case UI_FORCE_RANK_PUSH:
03136                         case UI_FORCE_RANK_PULL:
03137                         case UI_FORCE_RANK_TELEPATHY:
03138                         case UI_FORCE_RANK_GRIP:
03139                         case UI_FORCE_RANK_LIGHTNING:
03140                         case UI_FORCE_RANK_RAGE:
03141                         case UI_FORCE_RANK_PROTECT:
03142                         case UI_FORCE_RANK_ABSORB:
03143                         case UI_FORCE_RANK_TEAM_HEAL:
03144                         case UI_FORCE_RANK_TEAM_FORCE:
03145                         case UI_FORCE_RANK_DRAIN:
03146                         case UI_FORCE_RANK_SEE:
03147                         case UI_FORCE_RANK_SABERATTACK:
03148                         case UI_FORCE_RANK_SABERDEFEND:
03149                         case UI_FORCE_RANK_SABERTHROW:
03150                                 if(!Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) )
03151                                 {
03152                                         return qfalse;
03153                                 }
03154                                 break;
03155                 }
03156           }
03157           
03158 
03159     return DC->ownerDrawHandleKey(item->window.ownerDraw, item->window.ownerDrawFlags, &item->special, key);
03160   }
03161   return qfalse;
03162 }
03163 
03164 
03165 #ifdef _XBOX
03166 // Xbox-only key handlers
03167 
03168 //JLF new func
03169 qboolean Item_Button_HandleKey(itemDef_t *item, int key) 
03170 {
03171         if ( key == A_CURSOR_RIGHT)
03172         {
03173                 if (Item_HandleSelectionNext(item))
03174                 {
03175                         //Item processed it 
03176                         return qtrue;
03177                 }
03178         }
03179         else if ( key ==  A_CURSOR_LEFT)
03180         {
03181                 if (Item_HandleSelectionPrev(item))
03182                 {
03183                         //Item processed it 
03184                         return qtrue;
03185                 }
03186         }
03187         return qfalse;
03188 }
03189 
03190 /*
03191 =================
03192 Item_Text_HandleKey
03193 =================
03194 */
03195 qboolean Item_Text_HandleKey(itemDef_t *item, int key) 
03196 {
03197 //JLFSELECTIONRightLeft
03198         if ( key == A_CURSOR_RIGHT)
03199         {
03200                 if (Item_HandleSelectionNext(item))
03201                 {
03202                         //Item processed it 
03203                         return qtrue;
03204                 }
03205         }
03206         else if ( key ==  A_CURSOR_LEFT)
03207         {
03208                 if (Item_HandleSelectionPrev(item))
03209                 {
03210                         //Item processed it 
03211                         return qtrue;
03212                 }
03213         }
03214         return qfalse;
03215 }
03216 
03217 #endif // _XBOX
03218 
03219 
03220 qboolean Item_ListBox_HandleKey(itemDef_t *item, int key, qboolean down, qboolean force) {
03221         listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
03222         int count = DC->feederCount(item->special);
03223         int max, viewmax;
03224 //JLFMOUSE
03225 #ifndef _XBOX
03226         if (force || (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS))
03227 #else
03228         if (force || item->window.flags & WINDOW_HASFOCUS)
03229 #endif
03230         {
03231                 max = Item_ListBox_MaxScroll(item);
03232                 if (item->window.flags & WINDOW_HORIZONTAL) {
03233                         viewmax = (item->window.rect.w / listPtr->elementWidth);
03234                         if ( key == A_CURSOR_LEFT || key == A_KP_4 ) 
03235                         {
03236                                 if (!listPtr->notselectable) {
03237                                         listPtr->cursorPos--;
03238 #ifdef _XBOX
03239                                         listPtr->startPos--;
03240 #endif
03241                                         if (listPtr->cursorPos < 0) {
03242                                                 listPtr->cursorPos = 0;
03243                                                 return qfalse;
03244                                         }
03245                                         if (listPtr->cursorPos < listPtr->startPos) {
03246                                                 listPtr->startPos = listPtr->cursorPos;
03247 //JLF
03248 #ifndef _XBOX
03249                                                 return qfalse;
03250 #endif
03251                                         }
03252                                         if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
03253                                                 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
03254                                         }
03255                                         item->cursorPos = listPtr->cursorPos;
03256                                         DC->feederSelection(item->special, item->cursorPos, NULL);
03257                                 }
03258                                 else {
03259                                         listPtr->startPos--;
03260                                         if (listPtr->startPos < 0)
03261                                                 listPtr->startPos = 0;
03262                                 }
03263                                 return qtrue;
03264                         }
03265                         if ( key == A_CURSOR_RIGHT || key == A_KP_6 ) 
03266                         {
03267                                 if (!listPtr->notselectable) {
03268                                         listPtr->cursorPos++;
03269                                         if (listPtr->cursorPos < listPtr->startPos) {
03270                                                 listPtr->startPos = listPtr->cursorPos;
03271 //JLF
03272 #ifndef _XBOX
03273                                                 return qfalse;
03274 #endif
03275                                         }
03276                                         if (listPtr->cursorPos >= count) {
03277                                                 listPtr->cursorPos = count-1;
03278                                                 return qfalse;
03279                                         }
03280                                         if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
03281                                                 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
03282                                         }
03283                                         item->cursorPos = listPtr->cursorPos;
03284                                         DC->feederSelection(item->special, item->cursorPos, NULL);
03285                                 }
03286                                 else {
03287                                         listPtr->startPos++;
03288                                         if (listPtr->startPos >= count)
03289                                                 listPtr->startPos = count-1;
03290                                 }
03291                                 return qtrue;
03292                         }
03293                 }
03294                 // Vertical scroll
03295                 else {
03296 
03297                         // Multiple rows and columns (since it's more than twice as wide as an element)
03298                         if (( item->window.rect.w > (listPtr->elementWidth*2)) &&  (listPtr->elementStyle == LISTBOX_IMAGE))
03299                         {
03300                                 viewmax = (item->window.rect.w / listPtr->elementWidth);
03301                         }
03302                         else 
03303                         {
03304                                 viewmax = (item->window.rect.h / listPtr->elementHeight);
03305                         }
03306 
03307                         if ( key == A_CURSOR_UP || key == A_KP_8 ) 
03308                         {
03309                                 if (!listPtr->notselectable) {
03310                                         listPtr->cursorPos--;
03311                                         if (listPtr->cursorPos < 0) {
03312                                                 listPtr->cursorPos = 0;
03313                                                 return qfalse;
03314                                         }
03315                                         if (listPtr->cursorPos < listPtr->startPos) {
03316                                                 listPtr->startPos = listPtr->cursorPos;
03317 //JLF
03318 #ifndef _XBOX
03319                                                 return qfalse;
03320 #endif
03321                                         }
03322                                         if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
03323                                                 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
03324                                         }
03325                                         item->cursorPos = listPtr->cursorPos;
03326                                         DC->feederSelection(item->special, item->cursorPos, NULL);
03327                                 }
03328                                 else {
03329                                         listPtr->startPos--;
03330                                         if (listPtr->startPos < 0)
03331                                                 listPtr->startPos = 0;
03332                                 }
03333                                 return qtrue;
03334                         }
03335                         if ( key == A_CURSOR_DOWN || key == A_KP_2 ) 
03336                         {
03337                                 if (!listPtr->notselectable) {
03338                                         listPtr->cursorPos++;
03339                                         if (listPtr->cursorPos < listPtr->startPos) {
03340                                                 listPtr->startPos = listPtr->cursorPos;
03341 //JLF
03342 #ifndef _XBOX
03343                                                 return qfalse;
03344 #endif
03345                                         }
03346                                         if (listPtr->cursorPos >= count) {
03347                                                 listPtr->cursorPos = count-1;
03348                                                 return qfalse;
03349                                         }
03350                                         if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
03351                                                 listPtr->startPos = listPtr->cursorPos - viewmax + 1;
03352                                         }
03353                                         item->cursorPos = listPtr->cursorPos;
03354                                         DC->feederSelection(item->special, item->cursorPos, NULL);
03355                                 }
03356                                 else {
03357                                         listPtr->startPos++;
03358                                         if (listPtr->startPos > max)
03359                                                 listPtr->startPos = max;
03360                                 }
03361                                 return qtrue;
03362                         }
03363                 }
03364                 // mouse hit
03365                 if (key == A_MOUSE1 || key == A_MOUSE2) {
03366                         if (item->window.flags & WINDOW_LB_LEFTARROW) {
03367                                 listPtr->startPos--;
03368                                 if (listPtr->startPos < 0) {
03369                                         listPtr->startPos = 0;
03370                                 }
03371                         } else if (item->window.flags & WINDOW_LB_RIGHTARROW) {
03372                                 // one down
03373                                 listPtr->startPos++;
03374                                 if (listPtr->startPos > max) {
03375                                         listPtr->startPos = max;
03376                                 }
03377                         } else if (item->window.flags & WINDOW_LB_PGUP) {
03378                                 // page up
03379                                 listPtr->startPos -= viewmax;
03380                                 if (listPtr->startPos < 0) {
03381                                         listPtr->startPos = 0;
03382                                 }
03383                         } else if (item->window.flags & WINDOW_LB_PGDN) {
03384                                 // page down
03385                                 listPtr->startPos += viewmax;
03386                                 if (listPtr->startPos > (max)) {
03387                                         listPtr->startPos = (max);
03388                                 }
03389                         } else if (item->window.flags & WINDOW_LB_THUMB) {
03390                                 // Display_SetCaptureItem(item);
03391                         } else {
03392                                 // select an item
03393 #ifdef _XBOX
03394                                 if (listPtr->doubleClick) {
03395 #else
03396                                 if (DC->realTime < lastListBoxClickTime && listPtr->doubleClick) {
03397 #endif
03398                                         Item_RunScript(item, listPtr->doubleClick);
03399                                 }
03400                                 lastListBoxClickTime = DC->realTime + DOUBLE_CLICK_DELAY;
03401 //                              if (item->cursorPos != listPtr->cursorPos) 
03402                                 {
03403                                         int prePos = item->cursorPos;
03404                                         
03405                                         item->cursorPos = listPtr->cursorPos;
03406 
03407                                         if (!DC->feederSelection(item->special, item->cursorPos, item))
03408                                         {
03409                                                 item->cursorPos = listPtr->cursorPos = prePos;
03410                                         }
03411                                 }
03412                         }
03413                         return qtrue;
03414                 }
03415                 if ( key == A_HOME || key == A_KP_7) {
03416                         // home
03417                         listPtr->startPos = 0;
03418                         return qtrue;
03419                 }
03420                 if ( key == A_END || key == A_KP_1) {
03421                         // end
03422                         listPtr->startPos = max;
03423                         return qtrue;
03424                 }
03425                 if (key == A_PAGE_UP || key == A_KP_9 ) {
03426                         // page up
03427                         if (!listPtr->notselectable) {
03428                                 listPtr->cursorPos -= viewmax;
03429                                 if (listPtr->cursorPos < 0) {
03430                                         listPtr->cursorPos = 0;
03431                                 }
03432                                 if (listPtr->cursorPos < listPtr->startPos) {
03433                                         listPtr->startPos = listPtr->cursorPos;
03434                                 }
03435                                 if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
03436                                         listPtr->startPos = listPtr->cursorPos - viewmax + 1;
03437                                 }
03438                                 item->cursorPos = listPtr->cursorPos;
03439                                 DC->feederSelection(item->special, item->cursorPos, NULL);
03440                         }
03441                         else {
03442                                 listPtr->startPos -= viewmax;
03443                                 if (listPtr->startPos < 0) {
03444                                         listPtr->startPos = 0;
03445                                 }
03446                         }
03447                         return qtrue;
03448                 }
03449                 if ( key == A_PAGE_DOWN || key == A_KP_3 ) {
03450                         // page down
03451                         if (!listPtr->notselectable) {
03452                                 listPtr->cursorPos += viewmax;
03453                                 if (listPtr->cursorPos < listPtr->startPos) {
03454                                         listPtr->startPos = listPtr->cursorPos;
03455                                 }
03456                                 if (listPtr->cursorPos >= count) {
03457                                         listPtr->cursorPos = count-1;
03458                                 }
03459                                 if (listPtr->cursorPos >= listPtr->startPos + viewmax) {
03460                                         listPtr->startPos = listPtr->cursorPos - viewmax + 1;
03461                                 }
03462                                 item->cursorPos = listPtr->cursorPos;
03463                                 DC->feederSelection(item->special, item->cursorPos, NULL);
03464                         }
03465                         else {
03466                                 listPtr->startPos += viewmax;
03467                                 if (listPtr->startPos > max) {
03468                                         listPtr->startPos = max;
03469                                 }
03470                         }
03471                         return qtrue;
03472                 }
03473         }
03474         return qfalse;
03475 }
03476 
03477 qboolean Item_YesNo_HandleKey(itemDef_t *item, int key) {
03478 //JLFMOUSE MPMOVED
03479 #ifndef _XBOX
03480   if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS && item->cvar) 
03481 #else
03482         if (item->window.flags & WINDOW_HASFOCUS && item->cvar) 
03483 #endif
03484         {
03485 
03486 //JLFDPAD MPMOVED
03487 #ifndef _XBOX
03488                 if (key == A_MOUSE1 || key == A_ENTER || key == A_MOUSE2 || key == A_MOUSE3) 
03489 #else
03490                 if ( key == A_CURSOR_RIGHT || key == A_CURSOR_LEFT)
03491 #endif
03492 //end JLFDPAD
03493 
03494                 {
03495             DC->setCVar(item->cvar, va("%i", !DC->getCVarValue(item->cvar)));
03496                   return qtrue;
03497                 }
03498   }
03499 
03500   return qfalse;
03501 
03502 }
03503 
03504 int Item_Multi_CountSettings(itemDef_t *item) {
03505         multiDef_t *multiPtr = (multiDef_t*)item->typeData;
03506         if (multiPtr == NULL) {
03507                 return 0;
03508         }
03509         return multiPtr->count;
03510 }
03511 
03512 int Item_Multi_FindCvarByValue(itemDef_t *item) {
03513         char buff[2048];
03514         float value = 0;
03515         int i;
03516         multiDef_t *multiPtr = (multiDef_t*)item->typeData;
03517         if (multiPtr) {
03518                 if (multiPtr->strDef) {
03519             DC->getCVarString(item->cvar, buff, sizeof(buff));
03520                 } else {
03521                         value = DC->getCVarValue(item->cvar);
03522                 }
03523                 for (i = 0; i < multiPtr->count; i++) {
03524                         if (multiPtr->strDef) {
03525                                 if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0) {
03526                                         return i;
03527                                 }
03528                         } else {
03529                                 if (multiPtr->cvarValue[i] == value) {
03530                                         return i;
03531                                 }
03532                         }
03533                 }
03534         }
03535         return 0;
03536 }
03537 
03538 const char *Item_Multi_Setting(itemDef_t *item) {
03539         char buff[2048];
03540         float value = 0;
03541         int i;
03542         multiDef_t *multiPtr = (multiDef_t*)item->typeData;
03543         if (multiPtr) 
03544         {
03545                 if (multiPtr->strDef) 
03546                 {
03547                         if (item->cvar)
03548                         {
03549                             DC->getCVarString(item->cvar, buff, sizeof(buff));
03550                         }
03551                 } 
03552                 else 
03553                 {
03554                         if (item->cvar) // Was a cvar given?
03555                         {
03556                                 value = DC->getCVarValue(item->cvar);
03557                         }
03558                 }
03559 
03560                 for (i = 0; i < multiPtr->count; i++) 
03561                 {
03562                         if (multiPtr->strDef) 
03563                         {
03564                                 if (Q_stricmp(buff, multiPtr->cvarStr[i]) == 0) 
03565                                 {
03566                                         return multiPtr->cvarList[i];
03567                                 }
03568                         } 
03569                         else 
03570                         {
03571                                 if (multiPtr->cvarValue[i] == value) 
03572                                 {
03573                                         return multiPtr->cvarList[i];
03574                                 }
03575                         }
03576                 }
03577         }
03578         return "";
03579 }
03580 
03581 qboolean Item_Multi_HandleKey(itemDef_t *item, int key) 
03582 {
03583         multiDef_t *multiPtr = (multiDef_t*)item->typeData;
03584         if (multiPtr) 
03585         {
03586 //JLF MPMOVED
03587 #ifndef _XBOX
03588                 if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && item->window.flags & WINDOW_HASFOCUS) 
03589 #else
03590                 if (item->window.flags & WINDOW_HASFOCUS)// JLF* && item->cvar)
03591 #endif
03592                 {
03593 #ifndef _XBOX
03594                                         
03595                         if (key == A_MOUSE1 || key == A_ENTER || key == A_MOUSE2 || key == A_MOUSE3) 
03596 #else
03597 //JLFDPAD MPMOVED
03598                         if ( key == A_CURSOR_RIGHT || key == A_CURSOR_LEFT)
03599 //end JLFDPAD
03600 #endif
03601                         {
03602                                 int current = Item_Multi_FindCvarByValue(item);
03603                                 int max = Item_Multi_CountSettings(item);
03604 
03605                                 if (key == A_MOUSE2 || key == A_CURSOR_LEFT)    // Xbox uses CURSOR_LEFT
03606                                 {
03607                                         current--;
03608                                         if ( current < 0 ) 
03609                                         {
03610                                                 current = max-1;
03611                                         }
03612                                 }
03613                                 else
03614                                 {
03615                                         current++;
03616                                         if ( current >= max ) 
03617                                         {
03618                                                 current = 0;
03619                                         }
03620                                 }
03621 
03622                                 if (multiPtr->strDef) 
03623                                 {
03624                                         DC->setCVar(item->cvar, multiPtr->cvarStr[current]);
03625                                 } 
03626                                 else 
03627                                 {
03628                                         float value = multiPtr->cvarValue[current];
03629                                         if (((float)((int) value)) == value) 
03630                                         {
03631                                                 DC->setCVar(item->cvar, va("%i", (int) value ));
03632                                         }
03633                                         else 
03634                                         {
03635                                                 DC->setCVar(item->cvar, va("%f", value ));
03636                                         }
03637                                 }
03638                                 if (item->special)
03639                                 {//its a feeder?
03640                                         DC->feederSelection(item->special, current, item);
03641                                 }
03642 
03643                                 return qtrue;
03644                         }
03645                 }
03646         }
03647   return qfalse;
03648 }
03649 
03650 // Leaving an edit field so reset it so it prints from the beginning.
03651 void Leaving_EditField(itemDef_t *item)
03652 {
03653         // switching fields so reset printed text of edit field
03654         if ((g_editingField==qtrue) && (item->type==ITEM_TYPE_EDITFIELD))
03655         {
03656                 editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
03657                 if (editPtr)
03658                 {
03659                         editPtr->paintOffset = 0;
03660                 }
03661         }
03662 }
03663 
03664 qboolean Item_TextField_HandleKey(itemDef_t *item, int key) {
03665         char buff[2048];
03666         int len;
03667         itemDef_t *newItem = NULL;
03668         editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
03669 
03670         if (item->cvar) {
03671 
03672                 buff[0] = 0;
03673                 DC->getCVarString(item->cvar, buff, sizeof(buff));
03674                 len = strlen(buff);
03675                 if (editPtr->maxChars && len > editPtr->maxChars) {
03676                         len = editPtr->maxChars;
03677                 }
03678                 if ( key & K_CHAR_FLAG ) {
03679                         key &= ~K_CHAR_FLAG;
03680 
03681 
03682                         if (key == 'h' - 'a' + 1 )      {       // ctrl-h is backspace
03683                                 if ( item->cursorPos > 0 ) {
03684                                         memmove( &buff[item->cursorPos - 1], &buff[item->cursorPos], len + 1 - item->cursorPos);
03685                                         item->cursorPos--;
03686                                         if (item->cursorPos < editPtr->paintOffset) {
03687                                                 editPtr->paintOffset--;
03688                                         }
03689                                 }
03690                                 DC->setCVar(item->cvar, buff);
03691                         return qtrue;
03692                         }
03693 
03694 
03695                         //
03696                         // ignore any non printable chars
03697                         //
03698                         if ( key < 32 || !item->cvar) {
03699                             return qtrue;
03700                     }
03701 
03702                         if (item->type == ITEM_TYPE_NUMERICFIELD) {
03703                                 if (key < '0' || key > '9') {
03704                                         return qfalse;
03705                                 }
03706                         }
03707 
03708                         if (!DC->getOverstrikeMode()) {
03709                                 if (( len == MAX_EDITFIELD - 1 ) || (editPtr->maxChars && len >= editPtr->maxChars)) {
03710                                         return qtrue;
03711                                 }
03712                                 memmove( &buff[item->cursorPos + 1], &buff[item->cursorPos], len + 1 - item->cursorPos );
03713                         } else {
03714                                 if (editPtr->maxChars && item->cursorPos >= editPtr->maxChars) {
03715                                         return qtrue;
03716                                 }
03717                         }
03718 
03719                         buff[item->cursorPos] = key;
03720 
03721                         //rww - nul-terminate!
03722                         if (item->cursorPos+1 < 2048)
03723                         {
03724                                 buff[item->cursorPos+1] = 0;
03725                         }
03726                         else
03727                         {
03728                                 buff[item->cursorPos] = 0;
03729                         }
03730 
03731                         DC->setCVar(item->cvar, buff);
03732 
03733                         if (item->cursorPos < len + 1) {
03734                                 item->cursorPos++;
03735                                 if (editPtr->maxPaintChars && item->cursorPos > editPtr->maxPaintChars) {
03736                                         editPtr->paintOffset++;
03737                                 }
03738                         }
03739 
03740                 } else {
03741 
03742                         if ( key == A_DELETE || key == A_KP_PERIOD ) {
03743                                 if ( item->cursorPos < len ) {
03744                                         memmove( buff + item->cursorPos, buff + item->cursorPos + 1, len - item->cursorPos);
03745                                         DC->setCVar(item->cvar, buff);
03746                                 }
03747                                 return qtrue;
03748                         }
03749 
03750                         if ( key == A_CURSOR_RIGHT || key == A_KP_6 ) 
03751                         {
03752                                 if (editPtr->maxPaintChars && item->cursorPos >= editPtr->maxPaintChars && item->cursorPos < len) {
03753                                         item->cursorPos++;
03754                                         editPtr->paintOffset++;
03755                                         return qtrue;
03756                                 }
03757                                 if (item->cursorPos < len) {
03758                                         item->cursorPos++;
03759                                 } 
03760                                 return qtrue;
03761                         }
03762 
03763                         if ( key == A_CURSOR_LEFT || key == A_KP_4 ) 
03764                         {
03765                                 if ( item->cursorPos > 0 ) {
03766                                         item->cursorPos--;
03767                                 }
03768                                 if (item->cursorPos < editPtr->paintOffset) {
03769                                         editPtr->paintOffset--;
03770                                 }
03771                                 return qtrue;
03772                         }
03773 
03774                         if ( key == A_HOME || key == A_KP_7) {// || ( tolower(key) == 'a' && trap_Key_IsDown( K_CTRL ) ) ) {
03775                                 item->cursorPos = 0;
03776                                 editPtr->paintOffset = 0;
03777                                 return qtrue;
03778                         }
03779 
03780                         if ( key == A_END || key == A_KP_1)  {// ( tolower(key) == 'e' && trap_Key_IsDown( K_CTRL ) ) ) {
03781                                 item->cursorPos = len;
03782                                 if(item->cursorPos > editPtr->maxPaintChars) {
03783                                         editPtr->paintOffset = len - editPtr->maxPaintChars;
03784                                 }
03785                                 return qtrue;
03786                         }
03787 
03788                         if ( key == A_INSERT || key == A_KP_0 ) {
03789                                 DC->setOverstrikeMode(!DC->getOverstrikeMode());
03790                                 return qtrue;
03791                         }
03792                 }
03793 
03794                 if (key == A_TAB || key == A_CURSOR_DOWN || key == A_KP_2)
03795                 {
03796                         // switching fields so reset printed text of edit field
03797                         Leaving_EditField(item);
03798                         g_editingField = qfalse;
03799                         newItem = Menu_SetNextCursorItem((menuDef_t *) item->parent);
03800                         if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD))
03801                         {
03802                                 g_editItem = newItem;
03803                                 g_editingField = qtrue;
03804                         }
03805                 }
03806 
03807                 if (key == A_CURSOR_UP || key == A_KP_8)
03808                 {
03809                         // switching fields so reset printed text of edit field
03810                         Leaving_EditField(item);
03811 
03812                         g_editingField = qfalse;
03813                         newItem = Menu_SetPrevCursorItem((menuDef_t *) item->parent);
03814                         if (newItem && (newItem->type == ITEM_TYPE_EDITFIELD || newItem->type == ITEM_TYPE_NUMERICFIELD))
03815                         {
03816                                 g_editItem = newItem;
03817                                 g_editingField = qtrue;
03818                         }
03819                 }
03820 
03821                 if ( key == A_ENTER || key == A_KP_ENTER || key == A_ESCAPE)  {
03822                         return qfalse;
03823                 }
03824 
03825                 return qtrue;
03826         }
03827         return qfalse;
03828 
03829 }
03830 
03831 static void Scroll_TextScroll_AutoFunc (void *p) 
03832 {
03833         scrollInfo_t *si = (scrollInfo_t*)p;
03834 
03835         if (DC->realTime > si->nextScrollTime) 
03836         { 
03837                 // need to scroll which is done by simulating a click to the item
03838                 // this is done a bit sideways as the autoscroll "knows" that the item is a listbox
03839                 // so it calls it directly
03840                 Item_TextScroll_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
03841                 si->nextScrollTime = DC->realTime + si->adjustValue; 
03842         }
03843 
03844         if (DC->realTime > si->nextAdjustTime) 
03845         {
03846                 si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
03847                 if (si->adjustValue > SCROLL_TIME_FLOOR) 
03848                 {
03849                         si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
03850                 }
03851         }
03852 }
03853 
03854 static void Scroll_TextScroll_ThumbFunc(void *p) 
03855 {
03856         scrollInfo_t *si = (scrollInfo_t*)p;
03857         rectDef_t        r;
03858         int                      pos;
03859         int                      max;
03860 
03861         textScrollDef_t *scrollPtr = (textScrollDef_t*)si->item->typeData;
03862 
03863         if (DC->cursory != si->yStart) 
03864         {
03865                 r.x = si->item->window.rect.x + si->item->window.rect.w - SCROLLBAR_SIZE - 1;
03866                 r.y = si->item->window.rect.y + SCROLLBAR_SIZE + 1;
03867                 r.h = si->item->window.rect.h - (SCROLLBAR_SIZE*2) - 2;
03868                 r.w = SCROLLBAR_SIZE;
03869                 max = Item_TextScroll_MaxScroll(si->item);
03870                 //
03871                 pos = (DC->cursory - r.y - SCROLLBAR_SIZE/2) * max / (r.h - SCROLLBAR_SIZE);
03872                 if (pos < 0) 
03873                 {
03874                         pos = 0;
03875                 }
03876                 else if (pos > max) 
03877                 {
03878                         pos = max;
03879                 }
03880 
03881                 scrollPtr->startPos = pos;
03882                 si->yStart = DC->cursory;
03883         }
03884 
03885         if (DC->realTime > si->nextScrollTime) 
03886         { 
03887                 // need to scroll which is done by simulating a click to the item
03888                 // this is done a bit sideways as the autoscroll "knows" that the item is a listbox
03889                 // so it calls it directly
03890                 Item_TextScroll_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
03891                 si->nextScrollTime = DC->realTime + si->adjustValue; 
03892         }
03893 
03894         if (DC->realTime > si->nextAdjustTime) 
03895         {
03896                 si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
03897                 if (si->adjustValue > SCROLL_TIME_FLOOR) 
03898                 {
03899                         si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
03900                 }
03901         }
03902 }
03903 
03904 static void Scroll_ListBox_AutoFunc(void *p) {
03905         scrollInfo_t *si = (scrollInfo_t*)p;
03906         if (DC->realTime > si->nextScrollTime) { 
03907                 // need to scroll which is done by simulating a click to the item
03908                 // this is done a bit sideways as the autoscroll "knows" that the item is a listbox
03909                 // so it calls it directly
03910                 Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
03911                 si->nextScrollTime = DC->realTime + si->adjustValue; 
03912         }
03913 
03914         if (DC->realTime > si->nextAdjustTime) {
03915                 si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
03916                 if (si->adjustValue > SCROLL_TIME_FLOOR) {
03917                         si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
03918                 }
03919         }
03920 }
03921 
03922 static void Scroll_ListBox_ThumbFunc(void *p) {
03923         scrollInfo_t *si = (scrollInfo_t*)p;
03924         rectDef_t r;
03925         int pos, max;
03926 
03927         listBoxDef_t *listPtr = (listBoxDef_t*)si->item->typeData;
03928         if (si->item->window.flags & WINDOW_HORIZONTAL) {
03929                 if (DC->cursorx == si->xStart) {
03930                         return;
03931                 }
03932                 r.x = si->item->window.rect.x + SCROLLBAR_SIZE + 1;
03933                 r.y = si->item->window.rect.y + si->item->window.rect.h - SCROLLBAR_SIZE - 1;
03934                 r.h = SCROLLBAR_SIZE;
03935                 r.w = si->item->window.rect.w - (SCROLLBAR_SIZE*2) - 2;
03936                 max = Item_ListBox_MaxScroll(si->item);
03937                 //
03938                 pos = (DC->cursorx - r.x - SCROLLBAR_SIZE/2) * max / (r.w - SCROLLBAR_SIZE);
03939                 if (pos < 0) {
03940                         pos = 0;
03941                 }
03942                 else if (pos > max) {
03943                         pos = max;
03944                 }
03945                 listPtr->startPos = pos;
03946                 si->xStart = DC->cursorx;
03947         }
03948         else if (DC->cursory != si->yStart) {
03949 
03950                 r.x = si->item->window.rect.x + si->item->window.rect.w - SCROLLBAR_SIZE - 1;
03951                 r.y = si->item->window.rect.y + SCROLLBAR_SIZE + 1;
03952                 r.h = si->item->window.rect.h - (SCROLLBAR_SIZE*2) - 2;
03953                 r.w = SCROLLBAR_SIZE;
03954                 max = Item_ListBox_MaxScroll(si->item);
03955 
03956                 // Multiple rows and columns (since it's more than twice as wide as an element)
03957                 if (( si->item->window.rect.w > (listPtr->elementWidth*2)) &&  (listPtr->elementStyle == LISTBOX_IMAGE))
03958                 {
03959                         int rowLength, rowMax;
03960                         rowLength = si->item->window.rect.w / listPtr->elementWidth; 
03961                         rowMax = max / rowLength;
03962 
03963                         pos = (DC->cursory - r.y - SCROLLBAR_SIZE/2) * rowMax / (r.h - SCROLLBAR_SIZE);
03964                         pos *= rowLength;
03965                 }
03966                 else
03967                 {
03968                         pos = (DC->cursory - r.y - SCROLLBAR_SIZE/2) * max / (r.h - SCROLLBAR_SIZE);
03969                 }
03970 
03971                 if (pos < 0) {
03972                         pos = 0;
03973                 }
03974                 else if (pos > max) {
03975                         pos = max;
03976                 }
03977                 listPtr->startPos = pos;
03978                 si->yStart = DC->cursory;
03979         }
03980 
03981         if (DC->realTime > si->nextScrollTime) { 
03982                 // need to scroll which is done by simulating a click to the item
03983                 // this is done a bit sideways as the autoscroll "knows" that the item is a listbox
03984                 // so it calls it directly
03985                 Item_ListBox_HandleKey(si->item, si->scrollKey, qtrue, qfalse);
03986                 si->nextScrollTime = DC->realTime + si->adjustValue; 
03987         }
03988 
03989         if (DC->realTime > si->nextAdjustTime) {
03990                 si->nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
03991                 if (si->adjustValue > SCROLL_TIME_FLOOR) {
03992                         si->adjustValue -= SCROLL_TIME_ADJUSTOFFSET;
03993                 }
03994         }
03995 }
03996 
03997 static void Scroll_Slider_ThumbFunc(void *p) {
03998         float x, value, cursorx;
03999         scrollInfo_t *si = (scrollInfo_t*)p;
04000         editFieldDef_t *editDef = (editFieldDef_t *) si->item->typeData;
04001 
04002         if (si->item->text) {
04003                 x = si->item->textRect.x + si->item->textRect.w + 8;
04004         } else {
04005                 x = si->item->window.rect.x;
04006         }
04007 
04008         cursorx = DC->cursorx;
04009 
04010         if (cursorx < x) {
04011                 cursorx = x;
04012         } else if (cursorx > x + SLIDER_WIDTH) {
04013                 cursorx = x + SLIDER_WIDTH;
04014         }
04015         value = cursorx - x;
04016         value /= SLIDER_WIDTH;
04017         value *= (editDef->maxVal - editDef->minVal);
04018         value += editDef->minVal;
04019         DC->setCVar(si->item->cvar, va("%f", value));
04020 }
04021 
04022 void Item_StartCapture(itemDef_t *item, int key) 
04023 {
04024         int flags;
04025         switch (item->type) 
04026         {
04027             case ITEM_TYPE_EDITFIELD:
04028                 case ITEM_TYPE_NUMERICFIELD:
04029                 case ITEM_TYPE_LISTBOX:
04030                 {
04031                         flags = Item_ListBox_OverLB(item, DC->cursorx, DC->cursory);
04032                         if (flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW)) {
04033                                 scrollInfo.nextScrollTime = DC->realTime + SCROLL_TIME_START;
04034                                 scrollInfo.nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
04035                                 scrollInfo.adjustValue = SCROLL_TIME_START;
04036                                 scrollInfo.scrollKey = key;
04037                                 scrollInfo.scrollDir = (flags & WINDOW_LB_LEFTARROW) ? qtrue : qfalse;
04038                                 scrollInfo.item = item;
04039                                 captureData = &scrollInfo;
04040                                 captureFunc = &Scroll_ListBox_AutoFunc;
04041                                 itemCapture = item;
04042                         } else if (flags & WINDOW_LB_THUMB) {
04043                                 scrollInfo.scrollKey = key;
04044                                 scrollInfo.item = item;
04045                                 scrollInfo.xStart = DC->cursorx;
04046                                 scrollInfo.yStart = DC->cursory;
04047                                 captureData = &scrollInfo;
04048                                 captureFunc = &Scroll_ListBox_ThumbFunc;
04049                                 itemCapture = item;
04050                         }
04051                         break;
04052                 }
04053 
04054                 case ITEM_TYPE_TEXTSCROLL:
04055                         flags = Item_TextScroll_OverLB (item, DC->cursorx, DC->cursory);
04056                         if (flags & (WINDOW_LB_LEFTARROW | WINDOW_LB_RIGHTARROW)) 
04057                         {
04058                                 scrollInfo.nextScrollTime = DC->realTime + SCROLL_TIME_START;
04059                                 scrollInfo.nextAdjustTime = DC->realTime + SCROLL_TIME_ADJUST;
04060                                 scrollInfo.adjustValue = SCROLL_TIME_START;
04061                                 scrollInfo.scrollKey = key;
04062                                 scrollInfo.scrollDir = (flags & WINDOW_LB_LEFTARROW) ? qtrue : qfalse;
04063                                 scrollInfo.item = item;
04064                                 captureData = &scrollInfo;
04065                                 captureFunc = &Scroll_TextScroll_AutoFunc;
04066                                 itemCapture = item;
04067                         } 
04068                         else if (flags & WINDOW_LB_THUMB) 
04069                         {
04070                                 scrollInfo.scrollKey = key;
04071                                 scrollInfo.item = item;
04072                                 scrollInfo.xStart = DC->cursorx;
04073                                 scrollInfo.yStart = DC->cursory;
04074                                 captureData = &scrollInfo;
04075                                 captureFunc = &Scroll_TextScroll_ThumbFunc;
04076                                 itemCapture = item;
04077                         }
04078                         break;
04079 
04080                 case ITEM_TYPE_SLIDER:
04081                 {
04082                         flags = Item_Slider_OverSlider(item, DC->cursorx, DC->cursory);
04083                         if (flags & WINDOW_LB_THUMB) {
04084                                 scrollInfo.scrollKey = key;
04085                                 scrollInfo.item = item;
04086                                 scrollInfo.xStart = DC->cursorx;
04087                                 scrollInfo.yStart = DC->cursory;
04088                                 captureData = &scrollInfo;
04089                                 captureFunc = &Scroll_Slider_ThumbFunc;
04090                                 itemCapture = item;
04091                         }
04092                         break;
04093                 }
04094         }
04095 }
04096 
04097 void Item_StopCapture(itemDef_t *item) {
04098 
04099 }
04100 
04101 qboolean Item_Slider_HandleKey(itemDef_t *item, int key, qboolean down) {
04102         float x, value, width, work;
04103 
04104         //DC->Print("slider handle key\n");
04105 //JLF MPMOVED
04106 #ifndef _XBOX
04107         if (item->window.flags & WINDOW_HASFOCUS && item->cvar && Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) {
04108                 if (key == A_MOUSE1 || key == A_ENTER || key == A_MOUSE2 || key == A_MOUSE3) {
04109                         editFieldDef_t *editDef = (editFieldDef_t *) item->typeData;
04110                         if (editDef) {
04111                                 rectDef_t testRect;
04112                                 width = SLIDER_WIDTH;
04113                                 if (item->text) {
04114                                         x = item->textRect.x + item->textRect.w + 8;
04115                                 } else {
04116                                         x = item->window.rect.x;
04117                                 }
04118 
04119                                 testRect = item->window.rect;
04120                                 testRect.x = x;
04121                                 value = (float)SLIDER_THUMB_WIDTH / 2;
04122                                 testRect.x -= value;
04123                                 //DC->Print("slider x: %f\n", testRect.x);
04124                                 testRect.w = (SLIDER_WIDTH + (float)SLIDER_THUMB_WIDTH / 2);
04125                                 //DC->Print("slider w: %f\n", testRect.w);
04126                                 if (Rect_ContainsPoint(&testRect, DC->cursorx, DC->cursory)) {
04127                                         work = DC->cursorx - x;
04128                                         value = work / width;
04129                                         value *= (editDef->maxVal - editDef->minVal);
04130                                         // vm fuckage
04131                                         // value = (((float)(DC->cursorx - x)/ SLIDER_WIDTH) * (editDef->maxVal - editDef->minVal));
04132                                         value += editDef->minVal;
04133                                         DC->setCVar(item->cvar, va("%f", value));
04134                                         return qtrue;
04135                                 }
04136                         }
04137                 }
04138         }
04139 #else  //def _XBOX
04140 //JLF
04141         if (item->window.flags & WINDOW_HASFOCUS && item->cvar)
04142         {
04143                 if (key == A_CURSOR_LEFT)
04144                 {
04145                         editFieldDef_t *editDef = (editFieldDef_s *) item->typeData;
04146                         if (editDef) 
04147                         {
04148                                 value = DC->getCVarValue(item->cvar);
04149                                 value -= (editDef->maxVal-editDef->minVal)/TICK_COUNT;
04150                                 if ( value < editDef->minVal)
04151                                         value = editDef->minVal;
04152                                 DC->setCVar(item->cvar, va("%f", value));
04153                                 return qtrue;
04154                         }
04155                 }
04156                 if (key == A_CURSOR_RIGHT)
04157                 {
04158                         editFieldDef_t *editDef = (editFieldDef_s *) item->typeData;
04159                         if (editDef) 
04160                         {
04161                                 value = DC->getCVarValue(item->cvar);
04162                                 value += (editDef->maxVal-editDef->minVal)/TICK_COUNT;
04163                                 if ( value > editDef->maxVal)
04164                                         value = editDef->maxVal;
04165                                 DC->setCVar(item->cvar, va("%f", value));
04166                                 return qtrue;
04167                         }
04168                 }
04169         }
04170 #endif
04171         DC->Print("slider handle key exit\n");
04172         return qfalse;
04173 }
04174 
04175 
04176 qboolean Item_HandleKey(itemDef_t *item, int key, qboolean down) {
04177 
04178         if (itemCapture) {
04179                 Item_StopCapture(itemCapture);
04180                 itemCapture = NULL;
04181                 captureFunc = 0;
04182                 captureData = NULL;
04183         } else {
04184           // bk001206 - parentheses
04185                 if ( down && ( key == A_MOUSE1 || key == A_MOUSE2 || key == A_MOUSE3 ) ) {
04186                         Item_StartCapture(item, key);
04187                 }
04188         }
04189 
04190         if (!down) {
04191                 return qfalse;
04192         }
04193 
04194   switch (item->type) {
04195     case ITEM_TYPE_BUTTON:
04196 #ifdef _XBOX
04197                         return Item_Button_HandleKey(item, key);
04198 #else
04199                         return qfalse;
04200 #endif
04201       break;
04202     case ITEM_TYPE_RADIOBUTTON:
04203       return qfalse;
04204       break;
04205     case ITEM_TYPE_CHECKBOX:
04206       return qfalse;
04207       break;
04208     case ITEM_TYPE_EDITFIELD:
04209     case ITEM_TYPE_NUMERICFIELD:
04210                 if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_ENTER)
04211                 {
04212                         editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
04213 
04214                         if (item->cvar && editPtr)
04215                         {
04216                                 editPtr->paintOffset = 0;
04217                         }
04218 
04219       //return Item_TextField_HandleKey(item, key);
04220                 }
04221       return qfalse;
04222       break;
04223     case ITEM_TYPE_COMBO:
04224       return qfalse;
04225       break;
04226     case ITEM_TYPE_LISTBOX:
04227       return Item_ListBox_HandleKey(item, key, down, qfalse);
04228       break;
04229         case ITEM_TYPE_TEXTSCROLL:
04230       return Item_TextScroll_HandleKey(item, key, down, qfalse);
04231       break;
04232     case ITEM_TYPE_YESNO:
04233       return Item_YesNo_HandleKey(item, key);
04234       break;
04235     case ITEM_TYPE_MULTI:
04236       return Item_Multi_HandleKey(item, key);
04237       break;
04238     case ITEM_TYPE_OWNERDRAW:
04239       return Item_OwnerDraw_HandleKey(item, key);
04240       break;
04241     case ITEM_TYPE_BIND:
04242                         return Item_Bind_HandleKey(item, key, down);
04243       break;
04244     case ITEM_TYPE_SLIDER:
04245       return Item_Slider_HandleKey(item, key, down);
04246       break;
04247 #ifdef _XBOX
04248         case ITEM_TYPE_TEXT:
04249           return Item_Text_HandleKey(item, key);
04250           break;
04251 #endif
04252     //case ITEM_TYPE_IMAGE:
04253     //  Item_Image_Paint(item);
04254     //  break;
04255     default:
04256       return qfalse;
04257       break;
04258   }
04259 
04260   //return qfalse;
04261 }
04262 
04263 
04264 //JLFACCEPT MPMOVED
04265 /*
04266 -----------------------------------------
04267 Item_HandleAccept
04268         If Item has an accept script, run it.
04269 -------------------------------------------
04270 */
04271 qboolean Item_HandleAccept(itemDef_t * item)
04272 {
04273         if (item->accept)
04274         {
04275                 Item_RunScript(item, item->accept);
04276                 return qtrue;
04277         }
04278         return qfalse;
04279 }
04280 
04281 #ifdef _XBOX    // Xbox-only event handlers
04282 
04283 //JLFDPADSCRIPT MPMOVED
04284 /*
04285 -----------------------------------------
04286 Item_HandleSelectionNext
04287         If Item has an selectionNext script, run it.
04288 -------------------------------------------
04289 */
04290 qboolean Item_HandleSelectionNext(itemDef_t * item)
04291 {
04292         if (item->selectionNext)
04293         {
04294                 Item_RunScript(item, item->selectionNext);
04295                 return qtrue;
04296         }
04297         return qfalse;
04298 }
04299 
04300 //JLFDPADSCRIPT MPMOVED
04301 /*
04302 -----------------------------------------
04303 Item_HandleSelectionPrev
04304         If Item has an selectionPrev script, run it.
04305 -------------------------------------------
04306 */
04307 qboolean Item_HandleSelectionPrev(itemDef_t * item)
04308 {
04309         if (item->selectionPrev)
04310         {
04311                 Item_RunScript(item, item->selectionPrev);
04312                 return qtrue;
04313         }
04314         return qfalse;
04315 }
04316 
04317 //JLF END
04318 #endif  // _XBOX
04319 
04320 
04321 void Item_Action(itemDef_t *item) {
04322   if (item) {
04323     Item_RunScript(item, item->action);
04324   }
04325 }
04326 
04327 
04328 
04329 itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu) {
04330         qboolean wrapped = qfalse;
04331         int oldCursor = menu->cursorItem;
04332 
04333         if (menu->cursorItem < 0) {
04334                 menu->cursorItem = menu->itemCount-1;
04335                 wrapped = qtrue;
04336         } 
04337 
04338         while (menu->cursorItem > -1) 
04339         {
04340                 menu->cursorItem--;
04341                 if (menu->cursorItem < 0) {
04342                         if (wrapped)
04343                         {
04344                                 break;
04345                         }
04346                         wrapped = qtrue;
04347                         menu->cursorItem = menu->itemCount -1;
04348                 }
04349 
04350                 if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory)) {
04351                         Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
04352                         return menu->items[menu->cursorItem];
04353                 }
04354         }
04355         menu->cursorItem = oldCursor;
04356         return NULL;
04357 
04358 }
04359 
04360 itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu) {
04361 
04362   qboolean wrapped = qfalse;
04363         int oldCursor = menu->cursorItem;
04364 
04365 
04366   if (menu->cursorItem == -1) {
04367     menu->cursorItem = 0;
04368     wrapped = qtrue;
04369   }
04370 
04371   while (menu->cursorItem < menu->itemCount) {
04372 
04373     menu->cursorItem++;
04374     if (menu->cursorItem >= menu->itemCount && !wrapped) {
04375       wrapped = qtrue;
04376       menu->cursorItem = 0;
04377     }
04378                 if (Item_SetFocus(menu->items[menu->cursorItem], DC->cursorx, DC->cursory)) {
04379                         Menu_HandleMouseMove(menu, menu->items[menu->cursorItem]->window.rect.x + 1, menu->items[menu->cursorItem]->window.rect.y + 1);
04380       return menu->items[menu->cursorItem];
04381     }
04382     
04383   }
04384 
04385         menu->cursorItem = oldCursor;
04386         return NULL;
04387 }
04388 
04389 static void Window_CloseCinematic(windowDef_t *window) {
04390         if (window->style == WINDOW_STYLE_CINEMATIC && window->cinematic >= 0) {
04391                 DC->stopCinematic(window->cinematic);
04392                 window->cinematic = -1;
04393         }
04394 }
04395 
04396 static void Menu_CloseCinematics(menuDef_t *menu) {
04397         if (menu) {
04398                 int i;
04399                 Window_CloseCinematic(&menu->window);
04400           for (i = 0; i < menu->itemCount; i++) {
04401                   Window_CloseCinematic(&menu->items[i]->window);
04402                         if (menu->items[i]->type == ITEM_TYPE_OWNERDRAW) {
04403                                 DC->stopCinematic(0-menu->items[i]->window.ownerDraw);
04404                         }
04405           }
04406         }
04407 }
04408 
04409 static void Display_CloseCinematics() {
04410         int i;
04411         for (i = 0; i < menuCount; i++) {
04412                 Menu_CloseCinematics(&Menus[i]);
04413         }
04414 }
04415 
04416 void  Menus_Activate(menuDef_t *menu) {
04417 
04418 //JLFCALLOUT MPMOVED
04419 #ifdef _XBOX
04420         DC->setCVar("ui_hideAcallout" ,"0");
04421         DC->setCVar("ui_hideBcallout" ,"0");
04422         DC->setCVar("ui_hideCcallout" ,"0");
04423 #endif
04424 //JLF END
04425         menu->window.flags |= (WINDOW_HASFOCUS | WINDOW_VISIBLE);
04426         if (menu->onOpen) {
04427                 itemDef_t item;
04428                 item.parent = menu;
04429                 Item_RunScript(&item, menu->onOpen);
04430         }
04431 
04432         if (menu->soundName && *menu->soundName) {
04433 //              DC->stopBackgroundTrack();                                      // you don't want to do this since it will reset s_rawend
04434                 DC->startBackgroundTrack(menu->soundName, menu->soundName, qfalse);
04435         }
04436 
04437         menu->appearanceTime = 0;
04438         Display_CloseCinematics();
04439 
04440 }
04441 
04442 int Display_VisibleMenuCount() {
04443         int i, count;
04444         count = 0;
04445         for (i = 0; i < menuCount; i++) {
04446                 if (Menus[i].window.flags & (WINDOW_FORCED | WINDOW_VISIBLE)) {
04447                         count++;
04448                 }
04449         }
04450         return count;
04451 }
04452 
04453 void Menus_HandleOOBClick(menuDef_t *menu, int key, qboolean down) {
04454         if (menu) {
04455 //JLFMOUSE
04456 #ifdef _XBOX
04457                 Menu_HandleMouseMove(menu, DC->cursorx, DC->cursory);
04458                 Menu_HandleKey(menu, key, down);
04459                 return; 
04460 #endif
04461                 int i;
04462                 // basically the behaviour we are looking for is if there are windows in the stack.. see if 
04463                 // the cursor is within any of them.. if not close them otherwise activate them and pass the 
04464                 // key on.. force a mouse move to activate focus and script stuff 
04465                 if (down && menu->window.flags & WINDOW_OOB_CLICK) {
04466                         Menu_RunCloseScript(menu);
04467                         menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
04468                 }
04469 
04470                 for (i = 0; i < menuCount; i++) {
04471                         if (Menu_OverActiveItem(&Menus[i], DC->cursorx, DC->cursory)) {
04472                                 Menu_RunCloseScript(menu);
04473                                 menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE);
04474                                 Menus_Activate(&Menus[i]);
04475                                 Menu_HandleMouseMove(&Menus[i], DC->cursorx, DC->cursory);
04476                                 Menu_HandleKey(&Menus[i], key, down);
04477                         }
04478                 }
04479 
04480                 if (Display_VisibleMenuCount() == 0) {
04481                         if (DC->Pause) {
04482                                 DC->Pause(qfalse);
04483                         }
04484                 }
04485                 Display_CloseCinematics();
04486         }
04487 }
04488 
04489 
04490 void Menu_HandleKey(menuDef_t *menu, int key, qboolean down) {
04491         int i;
04492         itemDef_t *item = NULL;
04493         qboolean inHandler = qfalse;
04494 
04495         if (inHandler) {
04496                 return;
04497         }
04498 
04499         inHandler = qtrue;
04500         if (g_waitingForKey && down) {
04501                 Item_Bind_HandleKey(g_bindItem, key, down);
04502                 inHandler = qfalse;
04503                 return;
04504         }
04505 
04506         if (g_editingField && down) 
04507         {
04508                 if (!Item_TextField_HandleKey(g_editItem, key)) 
04509                 {
04510                         g_editingField = qfalse;
04511                         g_editItem = NULL;
04512                         inHandler = qfalse;
04513                         return;
04514                 } 
04515                 else if (key == A_MOUSE1 || key == A_MOUSE2 || key == A_MOUSE3) 
04516                 {
04517                         // switching fields so reset printed text of edit field
04518                         Leaving_EditField(g_editItem);
04519                         g_editingField = qfalse;
04520                         g_editItem = NULL;
04521                         Display_MouseMove(NULL, DC->cursorx, DC->cursory);
04522                 } 
04523                 else if (key == A_TAB || key == A_CURSOR_UP || key == A_CURSOR_DOWN) 
04524                 {
04525                         return;
04526                 }
04527         }
04528 
04529         if (menu == NULL) {
04530                 inHandler = qfalse;
04531                 return;
04532         }
04533         //JLFMOUSE  
04534                 // see if the mouse is within the window bounds and if so is this a mouse click
04535 #ifndef _XBOX
04536         if (down && !(menu->window.flags & WINDOW_POPUP) && !Rect_ContainsPoint(&menu->window.rect, DC->cursorx, DC->cursory)) 
04537 #else
04538         if (down) 
04539 #endif
04540         {
04541                 static qboolean inHandleKey = qfalse;
04542                 // bk001206 - parentheses
04543                 if (!inHandleKey && ( key == A_MOUSE1 || key == A_MOUSE2 || key == A_MOUSE3 ) ) {
04544                         inHandleKey = qtrue;
04545                         Menus_HandleOOBClick(menu, key, down);
04546                         inHandleKey = qfalse;
04547                         inHandler = qfalse;
04548                         return;
04549                 }
04550         }
04551 
04552         // get the item with focus
04553         for (i = 0; i < menu->itemCount; i++) {
04554                 if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
04555                         item = menu->items[i];
04556                 }
04557         }
04558 
04559         // Ignore if disabled
04560         if (item && item->disabled) 
04561         {
04562                 return;
04563         }
04564 
04565         if (item != NULL) {
04566                 if (Item_HandleKey(item, key, down)) 
04567                 {
04568 
04569 #ifdef _XBOX
04570                         if (key == A_MOUSE1 || key == A_MOUSE2 ||(item->type == ITEM_TYPE_MULTI && (key == A_CURSOR_RIGHT || key == A_CURSOR_LEFT)))
04571                         {
04572 #endif
04573                                 // It is possible for an item to be disable after Item_HandleKey is run (like in Voice Chat)
04574                                 if (!item->disabled) 
04575                                 {
04576                                         Item_Action(item);
04577                                 }
04578 #ifdef _XBOX
04579                         }
04580 #endif
04581                         inHandler = qfalse;
04582                         return;
04583                 }
04584         }
04585 
04586         if (!down) {
04587                 inHandler = qfalse;
04588                 return;
04589         }
04590 
04591         // default handling
04592         switch ( key ) {
04593 
04594                 case A_F11:
04595                         if (DC->getCVarValue("developer")) {
04596                                 debugMode ^= 1;
04597                         }
04598                         break;
04599 
04600                 case A_F12:
04601                         if (DC->getCVarValue("developer")) {
04602                                 DC->executeText(EXEC_APPEND, "screenshot\n");
04603                         }
04604                         break;
04605                 case A_KP_8:
04606                 case A_CURSOR_UP:
04607                         Menu_SetPrevCursorItem(menu);
04608                         break;
04609 
04610                 case A_ESCAPE:
04611                         if (!g_waitingForKey && menu->onESC) {
04612                                 itemDef_t it;
04613                     it.parent = menu;
04614                     Item_RunScript(&it, menu->onESC);
04615                         }
04616                     g_waitingForKey = qfalse;
04617                         break;
04618                 case A_TAB:
04619                 case A_KP_2:
04620                 case A_CURSOR_DOWN:
04621                         Menu_SetNextCursorItem(menu);
04622                         break;
04623 
04624                 case A_MOUSE1:
04625                 case A_MOUSE2:
04626                         if (item) {
04627                                 if (item->type == ITEM_TYPE_TEXT) {
04628 //JLFMOUSE
04629 #ifndef _XBOX
04630                                         if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory))
04631 #endif
04632                                         {
04633                                                 Item_Action(item);
04634                                         }
04635                                 } else if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
04636 //JLFMOUSE
04637 #ifndef _XBOX
04638                                         if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) 
04639 #endif                  
04640                                         {       
04641                                                 Item_Action(item);
04642                                                 item->cursorPos = 0;
04643                                                 g_editingField = qtrue;
04644                                                 g_editItem = item;
04645                                                 DC->setOverstrikeMode(qtrue);
04646                                         }
04647                                 }
04648                                 
04649         //JLFACCEPT
04650 // add new types here as needed
04651 /* Notes:
04652         Most controls will use the dpad to move through the selection possibilies.  Buttons are the only exception.
04653         Buttons will be assumed to all be on one menu together.  If the start or A button is pressed on a control focus, that
04654         means that the menu is accepted and move onto the next menu.  If the start or A button is pressed on a button focus it
04655         should just process the action and not support the accept functionality.
04656 */
04657 
04658 //JLFACCEPT MPMOVED
04659                                 else if ( item->type == ITEM_TYPE_MULTI || item->type == ITEM_TYPE_YESNO || item->type == ITEM_TYPE_SLIDER)
04660                                 {
04661                                         if (Item_HandleAccept(item))
04662                                         {
04663                                                 //Item processed it overriding the menu processing
04664                                                 return;
04665                                         }
04666                                         else if (menu->onAccept) 
04667                                         {
04668                                                 itemDef_t it;
04669                                                 it.parent = menu;
04670                                                 Item_RunScript(&it, menu->onAccept);
04671                                         }
04672                                 }
04673 //END JLFACCEPT                 
04674                                 else {
04675 //JLFMOUSE
04676 #ifndef _XBOX
04677                                         if (Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory))
04678 #endif
04679                                         {
04680 
04681                                                 Item_Action(item);
04682                                         }
04683                                 }
04684                         }
04685                         break;
04686 
04687                 case A_JOY0:
04688                 case A_JOY1:
04689                 case A_JOY2:
04690                 case A_JOY3:
04691                 case A_JOY4:
04692                 case A_AUX0:
04693                 case A_AUX1:
04694                 case A_AUX2:
04695                 case A_AUX3:
04696                 case A_AUX4:
04697                 case A_AUX5:
04698                 case A_AUX6:
04699                 case A_AUX7:
04700                 case A_AUX8:
04701                 case A_AUX9:
04702                 case A_AUX10:
04703                 case A_AUX11:
04704                 case A_AUX12:
04705                 case A_AUX13:
04706                 case A_AUX14:
04707                 case A_AUX15:
04708                 case A_AUX16:
04709                         break;
04710                 case A_KP_ENTER:
04711                 case A_ENTER:
04712                         if (item) {
04713                                 if (item->type == ITEM_TYPE_EDITFIELD || item->type == ITEM_TYPE_NUMERICFIELD) {
04714                                         item->cursorPos = 0;
04715                                         g_editingField = qtrue;
04716                                         g_editItem = item;
04717                                         DC->setOverstrikeMode(qtrue);
04718                                 } else {
04719                                                 Item_Action(item);
04720                                 }
04721                         }
04722                         break;
04723         }
04724         inHandler = qfalse;
04725 }
04726 
04727 void ToWindowCoords(float *x, float *y, windowDef_t *window) {
04728         if (window->border != 0) {
04729                 *x += window->borderSize;
04730                 *y += window->borderSize;
04731         } 
04732         *x += window->rect.x;
04733         *y += window->rect.y;
04734 }
04735 
04736 void Rect_ToWindowCoords(rectDef_t *rect, windowDef_t *window) {
04737         ToWindowCoords(&rect->x, &rect->y, window);
04738 }
04739 
04740 void Item_SetTextExtents(itemDef_t *item, int *width, int *height, const char *text) {
04741         const char *textPtr = (text) ? text : item->text;
04742 
04743         if (textPtr == NULL ) {
04744                 return;
04745         }
04746 
04747         *width = item->textRect.w;
04748         *height = item->textRect.h;
04749 
04750         // keeps us from computing the widths and heights more than once
04751         if (*width == 0 || (item->type == ITEM_TYPE_OWNERDRAW && item->textalignment == ITEM_ALIGN_CENTER)
04752 #ifndef CGAME
04753                 || (item->text && item->text[0]=='@' && item->asset != se_language.modificationCount )  //string package language changed
04754 #endif
04755                 )
04756         {
04757                 int originalWidth = DC->textWidth(textPtr, item->textscale, item->iMenuFont);
04758 
04759                 if (item->type == ITEM_TYPE_OWNERDRAW && (item->textalignment == ITEM_ALIGN_CENTER || item->textalignment == ITEM_ALIGN_RIGHT)) 
04760                 {
04761                         originalWidth += DC->ownerDrawWidth(item->window.ownerDraw, item->textscale);
04762                 } 
04763                 else if (item->type == ITEM_TYPE_EDITFIELD && item->textalignment == ITEM_ALIGN_CENTER && item->cvar) 
04764                 {
04765                         char buff[256];
04766                         DC->getCVarString(item->cvar, buff, 256);
04767                         originalWidth += DC->textWidth(buff, item->textscale, item->iMenuFont);
04768                 }
04769 
04770                 *width = DC->textWidth(textPtr, item->textscale, item->iMenuFont);
04771                 *height = DC->textHeight(textPtr, item->textscale, item->iMenuFont);
04772                 
04773                 item->textRect.w = *width;
04774                 item->textRect.h = *height;
04775                 item->textRect.x = item->textalignx;
04776                 item->textRect.y = item->textaligny;
04777                 if (item->textalignment == ITEM_ALIGN_RIGHT) {
04778                         item->textRect.x = item->textalignx - originalWidth;
04779                 } else if (item->textalignment == ITEM_ALIGN_CENTER) {
04780                         item->textRect.x = item->textalignx - originalWidth / 2;
04781                 }
04782 
04783                 ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
04784 #ifndef CGAME
04785                 if (item->text && item->text[0]=='@' )//string package
04786                 {//mark language
04787                         item->asset = se_language.modificationCount;
04788                 }
04789 #endif
04790         }
04791 }
04792 
04793 void Item_TextColor(itemDef_t *item, vec4_t *newColor) {
04794         vec4_t lowLight;
04795         menuDef_t *parent = (menuDef_t*)item->parent;
04796 
04797         Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
04798 
04799         if (item->window.flags & WINDOW_HASFOCUS) {
04800                 lowLight[0] = 0.8 * parent->focusColor[0]; 
04801                 lowLight[1] = 0.8 * parent->focusColor[1]; 
04802                 lowLight[2] = 0.8 * parent->focusColor[2]; 
04803                 lowLight[3] = 0.8 * parent->focusColor[3]; 
04804                 LerpColor(parent->focusColor,lowLight,*newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
04805         } else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1)) {
04806                 lowLight[0] = 0.8 * item->window.foreColor[0]; 
04807                 lowLight[1] = 0.8 * item->window.foreColor[1]; 
04808                 lowLight[2] = 0.8 * item->window.foreColor[2]; 
04809                 lowLight[3] = 0.8 * item->window.foreColor[3]; 
04810                 LerpColor(item->window.foreColor,lowLight,*newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
04811         } else {
04812                 memcpy(newColor, &item->window.foreColor, sizeof(vec4_t));
04813                 // items can be enabled and disabled based on cvars
04814         }
04815 
04816         if (item->disabled) 
04817         {
04818                 memcpy(newColor, &parent->disableColor, sizeof(vec4_t));
04819         }
04820 
04821         if (item->enableCvar && *item->enableCvar && item->cvarTest && *item->cvarTest) {
04822                 if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
04823                         memcpy(newColor, &parent->disableColor, sizeof(vec4_t));
04824                 }
04825         }
04826 }
04827 
04828 void Item_Text_AutoWrapped_Paint(itemDef_t *item) {
04829         char text[2048];
04830         const char *p, *textPtr, *newLinePtr;
04831         char buff[2048];
04832         int height, len, textWidth, newLine, newLineWidth;      //int width;
04833         float y;
04834         vec4_t color;
04835 
04836         textWidth = 0;
04837         newLinePtr = NULL;
04838 
04839         if (item->text == NULL) {
04840                 if (item->cvar == NULL) {
04841                         return;
04842                 }
04843                 else {
04844                         DC->getCVarString(item->cvar, text, sizeof(text));
04845                         textPtr = text;
04846                 }
04847         }
04848         else {
04849                 textPtr = item->text;
04850         }
04851         if (*textPtr == '@')    // string reference
04852         {
04853                 trap_SP_GetStringTextString( &textPtr[1], text, sizeof(text));
04854                 textPtr = text;
04855         }
04856         if (*textPtr == '\0') {
04857                 return;
04858         }
04859         Item_TextColor(item, &color);
04860         //Item_SetTextExtents(item, &width, &height, textPtr);
04861         //if (item->value == 0)
04862         //{
04863         //      item->value = (int)(0.5 + (float)DC->textWidth(textPtr, item->textscale, item->font) / item->window.rect.w);
04864         //}
04865         height = DC->textHeight(textPtr, item->textscale, item->iMenuFont);
04866 
04867         y = item->textaligny;
04868         len = 0;
04869         buff[0] = '\0';
04870         newLine = 0;
04871         newLineWidth = 0;
04872         p = textPtr;
04873         while (p) {     //findmeste (this will break widechar languages)!
04874                 if (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\0') {
04875                         newLine = len;
04876                         newLinePtr = p+1;
04877                         newLineWidth = textWidth;
04878                 }
04879                 textWidth = DC->textWidth(buff, item->textscale, 0);
04880                 if ( (newLine && textWidth > item->window.rect.w) || *p == '\n' || *p == '\0') {
04881                         if (len) {
04882                                 if (item->textalignment == ITEM_ALIGN_LEFT) {
04883                                         item->textRect.x = item->textalignx;
04884                                 } else if (item->textalignment == ITEM_ALIGN_RIGHT) {
04885                                         item->textRect.x = item->textalignx - newLineWidth;
04886                                 } else if (item->textalignment == ITEM_ALIGN_CENTER) {
04887                                         item->textRect.x = item->textalignx - newLineWidth / 2;
04888                                 }
04889                                 item->textRect.y = y;
04890                                 ToWindowCoords(&item->textRect.x, &item->textRect.y, &item->window);
04891                                 //
04892                                 buff[newLine] = '\0';
04893                                 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, buff, 0, 0, item->textStyle, item->iMenuFont);
04894                         }
04895                         if (*p == '\0') {
04896                                 break;
04897                         }
04898                         //
04899                         y += height + 5;
04900                         p = newLinePtr;
04901                         len = 0;
04902                         newLine = 0;
04903                         newLineWidth = 0;
04904                         continue;
04905                 }
04906                 buff[len++] = *p++;
04907                 buff[len] = '\0';
04908         }
04909 }
04910 
04911 void Item_Text_Wrapped_Paint(itemDef_t *item) {
04912         char text[1024];
04913         const char *p, *start, *textPtr;
04914         char buff[1024];
04915         int width, height;
04916         float x, y;
04917         vec4_t color;
04918 
04919         // now paint the text and/or any optional images
04920         // default to left
04921 
04922         if (item->text == NULL) {
04923                 if (item->cvar == NULL) {
04924                         return;
04925                 }
04926                 else {
04927                         DC->getCVarString(item->cvar, text, sizeof(text));
04928                         textPtr = text;
04929                 }
04930         }
04931         else {
04932                 textPtr = item->text;
04933         }
04934         if (*textPtr == '@')    // string reference
04935         {
04936                 trap_SP_GetStringTextString( &textPtr[1], text, sizeof(text));
04937                 textPtr = text;
04938         }
04939         if (*textPtr == '\0') {
04940                 return;
04941         }
04942 
04943         Item_TextColor(item, &color);
04944         Item_SetTextExtents(item, &width, &height, textPtr);
04945 
04946         x = item->textRect.x;
04947         y = item->textRect.y;
04948         start = textPtr;
04949         p = strchr(textPtr, '\r');
04950         while (p && *p) {
04951                 strncpy(buff, start, p-start+1);
04952                 buff[p-start] = '\0';
04953                 DC->drawText(x, y, item->textscale, color, buff, 0, 0, item->textStyle, item->iMenuFont);
04954                 y += height + 2;
04955                 start += p - start + 1;
04956                 p = strchr(p+1, '\r');
04957         }
04958         DC->drawText(x, y, item->textscale, color, start, 0, 0, item->textStyle, item->iMenuFont);
04959 }
04960 
04961 void Item_Text_Paint(itemDef_t *item) {
04962         char text[1024];
04963         const char *textPtr;
04964         int height, width;
04965         vec4_t color;
04966 
04967         if (item->window.flags & WINDOW_WRAPPED) {
04968                 Item_Text_Wrapped_Paint(item);
04969                 return;
04970         }
04971         if (item->window.flags & WINDOW_AUTOWRAPPED) {
04972                 Item_Text_AutoWrapped_Paint(item);
04973                 return;
04974         }
04975 
04976         if (item->text == NULL) {
04977                 if (item->cvar == NULL) {
04978                         return;
04979                 }
04980                 else {
04981                         DC->getCVarString(item->cvar, text, sizeof(text));
04982                         textPtr = text;
04983                 }
04984         }
04985         else {
04986                 textPtr = item->text;
04987         }
04988         if (*textPtr == '@')    // string reference
04989         {
04990                 trap_SP_GetStringTextString( &textPtr[1], text, sizeof(text));
04991                 textPtr = text;
04992         }
04993 
04994         // this needs to go here as it sets extents for cvar types as well
04995         Item_SetTextExtents(item, &width, &height, textPtr);
04996 
04997         if (*textPtr == '\0') {
04998                 return;
04999         }
05000 
05001 
05002         Item_TextColor(item, &color);
05003 
05004         DC->drawText(item->textRect.x, item->textRect.y, item->textscale, color, textPtr, 0, 0, item->textStyle, item->iMenuFont);
05005 
05006         if (item->text2)        // Is there a second line of text?
05007         {
05008                 textPtr = item->text2;
05009                 if (*textPtr == '@')    // string reference
05010                 {
05011                         trap_SP_GetStringTextString( &textPtr[1], text, sizeof(text));
05012                         textPtr = text;
05013                 }
05014                 Item_TextColor(item, &color);
05015                 DC->drawText(item->textRect.x + item->text2alignx, item->textRect.y + item->text2aligny, item->textscale, color, textPtr, 0, 0, item->textStyle,item->iMenuFont);
05016         }
05017 }
05018 
05019 
05020 
05021 //float                 trap_Cvar_VariableValue( const char *var_name );
05022 //void                  trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
05023 
05024 void Item_TextField_Paint(itemDef_t *item) {
05025         char buff[1024];
05026         vec4_t newColor, lowLight;
05027         int offset;
05028         menuDef_t *parent = (menuDef_t*)item->parent;
05029         editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
05030 
05031         Item_Text_Paint(item);
05032 
05033         buff[0] = '\0';
05034 
05035         if (item->cvar) {
05036                 DC->getCVarString(item->cvar, buff, sizeof(buff));
05037                 if (buff[0] == '@')     // string reference
05038                 {
05039                         trap_SP_GetStringTextString( &buff[1], buff, sizeof(buff));
05040                 }
05041         } 
05042 
05043         parent = (menuDef_t*)item->parent;
05044 
05045         if (item->window.flags & WINDOW_HASFOCUS) {
05046                 lowLight[0] = 0.8 * parent->focusColor[0]; 
05047                 lowLight[1] = 0.8 * parent->focusColor[1]; 
05048                 lowLight[2] = 0.8 * parent->focusColor[2]; 
05049                 lowLight[3] = 0.8 * parent->focusColor[3]; 
05050                 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
05051         } else {
05052                 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
05053         }
05054 
05055         offset = (item->text && *item->text) ? 8 : 0;
05056         if (item->window.flags & WINDOW_HASFOCUS && g_editingField) {
05057                 char cursor = DC->getOverstrikeMode() ? '_' : '|';
05058                 DC->drawTextWithCursor(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, item->cursorPos - editPtr->paintOffset , cursor, item->window.rect.w, item->textStyle, item->iMenuFont);
05059         } else {
05060                 DC->drawText(item->textRect.x + item->textRect.w + offset, item->textRect.y, item->textscale, newColor, buff + editPtr->paintOffset, 0, item->window.rect.w, item->textStyle,item->iMenuFont);
05061         }
05062 }
05063 
05064 void Item_YesNo_Paint(itemDef_t *item) {
05065         char    sYES[20];
05066         char    sNO[20];
05067         vec4_t newColor, lowLight;
05068         float value;
05069         menuDef_t *parent = (menuDef_t*)item->parent;
05070         const char *yesnovalue;
05071         
05072         value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
05073 
05074         if (item->window.flags & WINDOW_HASFOCUS) {
05075                 lowLight[0] = 0.8 * parent->focusColor[0]; 
05076                 lowLight[1] = 0.8 * parent->focusColor[1]; 
05077                 lowLight[2] = 0.8 * parent->focusColor[2]; 
05078                 lowLight[3] = 0.8 * parent->focusColor[3]; 
05079                 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
05080         } else {
05081                 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
05082         }
05083 
05084 
05085         trap_SP_GetStringTextString("MENUS_YES",sYES, sizeof(sYES));
05086         trap_SP_GetStringTextString("MENUS_NO", sNO,  sizeof(sNO));
05087 
05088 //JLFYESNO MPMOVED
05089         if (item->invertYesNo)
05090                 yesnovalue = (value == 0) ? sYES : sNO;
05091         else
05092                 yesnovalue = (value != 0) ? sYES : sNO;
05093         
05094         if (item->text) 
05095         {
05096                 Item_Text_Paint(item);
05097 //JLF MPMOVED
05098 #ifdef _XBOX
05099                 if (item->xoffset == 0)
05100                         DC->drawText(item->textRect.x + item->textRect.w + item->xoffset + 8, item->textRect.y, item->textscale, newColor, yesnovalue, 0, 0,item->textStyle, item->iMenuFont);
05101                 else
05102 #endif
05103                         DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, yesnovalue, 0, 0, item->textStyle, item->iMenuFont);
05104 
05105         } 
05106         else 
05107         {
05108 //JLF MPMOVED
05109 #ifdef _XBOX
05110                 DC->drawText(item->textRect.x + item->xoffset, item->textRect.y, item->textscale, newColor, yesnovalue , 0, 0, item->textStyle, item->iMenuFont);
05111 #else
05112                 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, yesnovalue , 0, 0, item->textStyle, item->iMenuFont);
05113 #endif
05114         }               
05115 
05116 /* JLF ORIGINAL CODE
05117         if (item->text) {
05118                 Item_Text_Paint(item);
05119 //              DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, (value != 0) ? sYES : sNO, 0, 0, item->textStyle);
05120                 DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, (value != 0) ? sYES : sNO, 0, 0, item->textStyle,item->iMenuFont);
05121         } else {
05122 //              DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? sYES : sNO, 0, 0, item->textStyle);
05123                 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? sYES : sNO, 0, 0, item->textStyle,item->iMenuFont);
05124         }
05125 */
05126 }
05127 
05128 void Item_Multi_Paint(itemDef_t *item) {
05129         vec4_t newColor, lowLight;
05130         const char *text = "";
05131         menuDef_t *parent = (menuDef_t*)item->parent;
05132         char    temp[MAX_STRING_CHARS];
05133 
05134         if (item->window.flags & WINDOW_HASFOCUS) {
05135                 lowLight[0] = 0.8 * parent->focusColor[0]; 
05136                 lowLight[1] = 0.8 * parent->focusColor[1]; 
05137                 lowLight[2] = 0.8 * parent->focusColor[2]; 
05138                 lowLight[3] = 0.8 * parent->focusColor[3]; 
05139                 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
05140         } else {
05141                 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
05142         }
05143 
05144         text = Item_Multi_Setting(item);
05145         if (*text == '@')       // string reference
05146         {
05147                 trap_SP_GetStringTextString( &text[1]  , temp, sizeof(temp));
05148                 text = temp;
05149         }
05150         // Is is specifying a cvar to get the item name from?
05151         else if (*text == '*')
05152         {
05153                 DC->getCVarString(&text[1], temp, sizeof(temp));
05154                 text = temp;
05155         }
05156 
05157         if (item->text) {
05158                 Item_Text_Paint(item);
05159 //JLF  MPMOVED
05160 #ifdef _XBOX
05161                 if ( item->xoffset)
05162                         DC->drawText(item->textRect.x + item->textRect.w + item->xoffset, item->textRect.y, item->textscale, newColor, text, 0,0, item->textStyle, item->iMenuFont);
05163                 else
05164 #endif
05165                         DC->drawText(item->textRect.x + item->textRect.w + 8, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle,item->iMenuFont);
05166         } else {
05167                 //JLF added xoffset
05168                 DC->drawText(item->textRect.x+item->xoffset, item->textRect.y, item->textscale, newColor, text, 0, 0, item->textStyle,item->iMenuFont);
05169         }
05170 }
05171 
05172 
05173 typedef struct {
05174         char    *command;
05175         int             id;
05176         int             defaultbind1;
05177         int             defaultbind2;
05178         int             bind1;
05179         int             bind2;
05180 } bind_t;
05181 
05182 typedef struct
05183 {
05184         char*   name;
05185         float   defaultvalue;
05186         float   value;  
05187 } configcvar_t;
05188 
05189 
05190 static bind_t g_bindings[] = 
05191 {
05192         {"+scores",                      A_TAB,                         -1,             -1, -1},
05193         {"+button2",             A_ENTER,                       -1,             -1, -1},
05194         {"+speed",                       A_SHIFT,                       -1,             -1,     -1},
05195         {"+forward",             A_CURSOR_UP,           -1,             -1, -1},
05196         {"+back",                        A_CURSOR_DOWN,         -1,             -1, -1},
05197         {"+moveleft",            ',',                           -1,             -1, -1},
05198         {"+moveright",           '.',                           -1,             -1, -1},
05199         {"+moveup",                      A_SPACE,                       -1,             -1, -1},
05200         {"+movedown",            'c',                           -1,             -1, -1},
05201         {"+left",                        A_CURSOR_LEFT,         -1,             -1, -1},
05202         {"+right",                       A_CURSOR_RIGHT,        -1,             -1, -1},
05203         {"+strafe",              A_ALT,                         -1,             -1, -1},
05204         {"+lookup",              A_PAGE_DOWN,           -1,             -1, -1},
05205         {"+lookdown",            A_DELETE,                      -1,             -1, -1},
05206         {"+mlook",                       '/',                           -1,             -1, -1},
05207         {"centerview",           A_END,                         -1,             -1, -1},
05208 //      {"+zoom",                        -1,                            -1,             -1, -1},
05209         {"weapon 1",             '1',                           -1,             -1, -1},
05210         {"weapon 2",             '2',                           -1,             -1, -1},
05211         {"weapon 3",             '3',                           -1,             -1, -1},
05212         {"weapon 4",             '4',                           -1,             -1, -1},
05213         {"weapon 5",             '5',                           -1,             -1, -1},
05214         {"weapon 6",             '6',                           -1,             -1, -1},
05215         {"weapon 7",             '7',                           -1,             -1, -1},
05216         {"weapon 8",             '8',                           -1,             -1, -1},
05217         {"weapon 9",             '9',                           -1,             -1, -1},
05218         {"weapon 10",            '0',                           -1,             -1, -1},
05219         {"saberAttackCycle", 'l',                               -1,             -1, -1},
05220         {"weapon 11",            -1,                            -1,             -1, -1},
05221         {"weapon 12",            -1,                            -1,             -1, -1},
05222         {"weapon 13",            -1,                            -1,             -1, -1},
05223         {"+attack",              A_CTRL,                        -1,             -1, -1},
05224         {"+altattack",          -1,                                     -1,             -1,     -1},
05225         {"+use",                        -1,                                     -1,             -1, -1},
05226         {"engage_duel",         'h',                            -1,             -1, -1},
05227         {"taunt",                       'u',                            -1,             -1, -1},
05228         {"bow",                         -1,                                     -1,             -1, -1},
05229         {"meditate",            -1,                                     -1,             -1, -1},
05230         {"flourish",            -1,                                     -1,             -1, -1},
05231         {"gloat",                       -1,                                     -1,             -1, -1},
05232         {"weapprev",             '[',                           -1,             -1, -1},
05233         {"weapnext",             ']',                           -1,             -1, -1},
05234         {"prevTeamMember",      'w',                            -1,             -1, -1},
05235         {"nextTeamMember",      'r',                            -1,             -1, -1},
05236         {"nextOrder",           't',                            -1,             -1, -1},
05237         {"confirmOrder",        'y',                            -1,             -1, -1},
05238         {"denyOrder",           'n',                            -1,             -1, -1},
05239         {"taskOffense",         'o',                            -1,             -1, -1},
05240         {"taskDefense",         'd',                            -1,             -1, -1},
05241         {"taskPatrol",          'p',                            -1,             -1, -1},
05242         {"taskCamp",            'c',                            -1,             -1, -1},
05243         {"taskFollow",          'f',                            -1,             -1, -1},
05244         {"taskRetrieve",        'v',                            -1,             -1, -1},
05245         {"taskEscort",          'e',                            -1,             -1, -1},
05246         {"taskOwnFlag",         'i',                            -1,             -1, -1},
05247         {"taskSuicide",         'k',                            -1,             -1, -1},
05248         {"tauntKillInsult", -1,                                 -1,             -1, -1},
05249         {"tauntPraise",         -1,                                     -1,             -1, -1},
05250         {"tauntTaunt",          -1,                                     -1,             -1, -1},
05251         {"tauntDeathInsult",-1,                                 -1,             -1, -1},
05252         {"tauntGauntlet",       -1,                                     -1,             -1, -1},
05253         {"scoresUp",            A_INSERT,                       -1,             -1, -1},
05254         {"scoresDown",          A_DELETE,                       -1,             -1, -1},
05255         {"messagemode",         -1,                                     -1,             -1, -1},
05256         {"messagemode2",        -1,                                     -1,             -1, -1},
05257         {"messagemode3",        -1,                                     -1,             -1, -1},
05258         {"messagemode4",        -1,                                     -1,             -1, -1},
05259         {"+use",                        -1,                                     -1,             -1,     -1},
05260         {"+force_jump",         -1,                                     -1,             -1,     -1},
05261         {"force_throw",         A_F1,                           -1,             -1,     -1},
05262         {"force_pull",          A_F2,                           -1,             -1,     -1},
05263         {"force_speed",         A_F3,                           -1,             -1,     -1},
05264         {"force_distract",      A_F4,                           -1,             -1,     -1},
05265         {"force_heal",          A_F5,                           -1,             -1,     -1},
05266         {"+force_grip",         A_F6,                           -1,             -1,     -1},
05267         {"+force_lightning",A_F7,                               -1,             -1,     -1},
05268 //mp only
05269         {"+force_drain",        -1,                                     -1,             -1,     -1},
05270         {"force_rage",          -1,                                     -1,             -1,     -1},
05271         {"force_protect",       -1,                                     -1,             -1,     -1},
05272         {"force_absorb",        -1,                                     -1,             -1,     -1},
05273         {"force_healother",     -1,                                     -1,             -1,     -1},
05274         {"force_forcepowerother",       -1,                     -1,             -1,     -1},
05275         {"force_seeing",        -1,                                     -1,             -1,     -1},
05276 
05277         {"+useforce",           -1,                                     -1,             -1,     -1},
05278         {"forcenext",           -1,                                     -1,             -1,     -1},
05279         {"forceprev",           -1,                                     -1,             -1,     -1},
05280         {"invnext",                     -1,                                     -1,             -1,     -1},
05281         {"invprev",                     -1,                                     -1,             -1,     -1},
05282         {"use_seeker",          -1,                                     -1,             -1,     -1},
05283         {"use_field",           -1,                                     -1,             -1,     -1},
05284         {"use_bacta",           -1,                                     -1,             -1,     -1},
05285         {"use_electrobinoculars",       -1,                     -1,             -1,     -1},
05286         {"use_sentry",          -1,                                     -1,             -1,     -1},
05287         {"cg_thirdperson !",-1,                                 -1,             -1,     -1},
05288         {"automap_button",      -1,                                     -1,             -1,     -1},
05289         {"automap_toggle",      -1,                                     -1,             -1,     -1},
05290         {"voicechat",           -1,                                     -1,             -1,     -1},
05291 
05292 };
05293 
05294 
05295 static const int g_bindCount = sizeof(g_bindings) / sizeof(bind_t);
05296 
05297 /*
05298 =================
05299 Controls_GetKeyAssignment
05300 =================
05301 */
05302 static void Controls_GetKeyAssignment (char *command, int *twokeys)
05303 {
05304         int             count;
05305         int             j;
05306         char    b[256];
05307 
05308         twokeys[0] = twokeys[1] = -1;
05309         count = 0;
05310 
05311         for ( j = 0; j < MAX_KEYS; j++ )
05312         {
05313                 DC->getBindingBuf( j, b, 256 );
05314                 if ( *b == 0 ) {
05315                         continue;
05316                 }
05317                 if ( !Q_stricmp( b, command ) ) {
05318                         twokeys[count] = j;
05319                         count++;
05320                         if (count == 2) {
05321                                 break;
05322                         }
05323                 }
05324         }
05325 }
05326 
05327 /*
05328 =================
05329 Controls_GetConfig
05330 =================
05331 */
05332 void Controls_GetConfig( void )
05333 {
05334         int             i;
05335         int             twokeys[2];
05336 
05337         // iterate each command, get its numeric binding
05338         for (i=0; i < g_bindCount; i++)
05339         {
05340 
05341                 Controls_GetKeyAssignment(g_bindings[i].command, twokeys);
05342 
05343                 g_bindings[i].bind1 = twokeys[0];
05344                 g_bindings[i].bind2 = twokeys[1];
05345         }
05346 
05347         //s_controls.invertmouse.curvalue  = DC->getCVarValue( "m_pitch" ) < 0;
05348         //s_controls.smoothmouse.curvalue  = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "m_filter" ) );
05349         //s_controls.alwaysrun.curvalue    = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_run" ) );
05350         //s_controls.autoswitch.curvalue   = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cg_autoswitch" ) );
05351         //s_controls.sensitivity.curvalue  = UI_ClampCvar( 2, 30, Controls_GetCvarValue( "sensitivity" ) );
05352         //s_controls.joyenable.curvalue    = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "in_joystick" ) );
05353         //s_controls.joythreshold.curvalue = UI_ClampCvar( 0.05, 0.75, Controls_GetCvarValue( "joy_threshold" ) );
05354         //s_controls.freelook.curvalue     = UI_ClampCvar( 0, 1, Controls_GetCvarValue( "cl_freelook" ) );
05355 }
05356 
05357 /*
05358 =================
05359 Controls_SetConfig
05360 =================
05361 */
05362 void Controls_SetConfig(qboolean restart)
05363 {
05364         int             i;
05365 
05366         // iterate each command, get its numeric binding
05367         for (i=0; i < g_bindCount; i++)
05368         {
05369                 if (g_bindings[i].bind1 != -1)
05370                 {       
05371                         DC->setBinding( g_bindings[i].bind1, g_bindings[i].command );
05372 
05373                         if (g_bindings[i].bind2 != -1)
05374                                 DC->setBinding( g_bindings[i].bind2, g_bindings[i].command );
05375                 }
05376         }
05377 
05378         //if ( s_controls.invertmouse.curvalue )
05379         //      DC->setCVar("m_pitch", va("%f),-fabs( DC->getCVarValue( "m_pitch" ) ) );
05380         //else
05381         //      trap_Cvar_SetValue( "m_pitch", fabs( trap_Cvar_VariableValue( "m_pitch" ) ) );
05382 
05383         //trap_Cvar_SetValue( "m_filter", s_controls.smoothmouse.curvalue );
05384         //trap_Cvar_SetValue( "cl_run", s_controls.alwaysrun.curvalue );
05385         //trap_Cvar_SetValue( "cg_autoswitch", s_controls.autoswitch.curvalue );
05386         //trap_Cvar_SetValue( "sensitivity", s_controls.sensitivity.curvalue );
05387         //trap_Cvar_SetValue( "in_joystick", s_controls.joyenable.curvalue );
05388         //trap_Cvar_SetValue( "joy_threshold", s_controls.joythreshold.curvalue );
05389         //trap_Cvar_SetValue( "cl_freelook", s_controls.freelook.curvalue );
05390 //
05391 //      DC->executeText(EXEC_APPEND, "in_restart\n");
05392 // ^--this is bad, it shows the cursor during map load, if you need to, add it as an exec cmd to use_joy or something.
05393 }
05394 
05395 
05396 int BindingIDFromName(const char *name) {
05397         int i;
05398   for (i=0; i < g_bindCount; i++)
05399         {
05400                 if (Q_stricmp(name, g_bindings[i].command) == 0) {
05401                         return i;
05402                 }
05403         }
05404         return -1;
05405 }
05406 
05407 char g_nameBind1[32];
05408 char g_nameBind2[32];
05409 
05410 void BindingFromName(const char *cvar) {
05411         int             i, b1, b2;
05412         char    sOR[32];
05413 
05414 
05415         // iterate each command, set its default binding
05416         for (i=0; i < g_bindCount; i++)
05417         {
05418                 if (Q_stricmp(cvar, g_bindings[i].command) == 0) {
05419                         b1 = g_bindings[i].bind1;
05420                         if (b1 == -1) {
05421                                 break;
05422                         }
05423                                 DC->keynumToStringBuf( b1, g_nameBind1, 32 );
05424 // do NOT do this or it corrupts asian text!!!                                  Q_strupr(g_nameBind1);
05425 
05426                                 b2 = g_bindings[i].bind2;
05427                                 if (b2 != -1)
05428                                 {
05429                                         DC->keynumToStringBuf( b2, g_nameBind2, 32 );
05430 // do NOT do this or it corrupts asian text!!!                                  Q_strupr(g_nameBind2);
05431 
05432                                         trap_SP_GetStringTextString("MENUS_KEYBIND_OR",sOR, sizeof(sOR));
05433 
05434                                         strcat( g_nameBind1, va(" %s ",sOR));
05435                                         strcat( g_nameBind1, g_nameBind2 );
05436                                 }
05437                         return;
05438                 }
05439         }
05440         strcpy(g_nameBind1, "???");
05441 }
05442 
05443 void Item_Slider_Paint(itemDef_t *item) {
05444         vec4_t newColor, lowLight;
05445         float x, y, value;
05446         menuDef_t *parent = (menuDef_t*)item->parent;
05447 
05448         value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
05449 
05450         if (item->window.flags & WINDOW_HASFOCUS) {
05451                 lowLight[0] = 0.8 * parent->focusColor[0]; 
05452                 lowLight[1] = 0.8 * parent->focusColor[1]; 
05453                 lowLight[2] = 0.8 * parent->focusColor[2]; 
05454                 lowLight[3] = 0.8 * parent->focusColor[3]; 
05455                 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
05456         } else {
05457                 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
05458         }
05459 
05460         y = item->window.rect.y;
05461         if (item->text) {
05462                 Item_Text_Paint(item);
05463                 x = item->textRect.x + item->textRect.w + 8;
05464         } else {
05465                 x = item->window.rect.x;
05466         }
05467         DC->setColor(newColor);
05468         DC->drawHandlePic( x, y, SLIDER_WIDTH, SLIDER_HEIGHT, DC->Assets.sliderBar );
05469 
05470         x = Item_Slider_ThumbPosition(item);
05471         DC->drawHandlePic( x - (SLIDER_THUMB_WIDTH / 2), y - 2, SLIDER_THUMB_WIDTH, SLIDER_THUMB_HEIGHT, DC->Assets.sliderThumb );
05472 
05473 }
05474 
05475 void Item_Bind_Paint(itemDef_t *item) 
05476 {
05477         vec4_t newColor, lowLight;
05478         float value;
05479         int maxChars = 0;
05480         float   textScale,textWidth;
05481         int             textHeight,yAdj,startingXPos;
05482 
05483 
05484         menuDef_t *parent = (menuDef_t*)item->parent;
05485         editFieldDef_t *editPtr = (editFieldDef_t*)item->typeData;
05486         if (editPtr) 
05487         {
05488                 maxChars = editPtr->maxPaintChars;
05489         }
05490 
05491         value = (item->cvar) ? DC->getCVarValue(item->cvar) : 0;
05492 
05493         if (item->window.flags & WINDOW_HASFOCUS) 
05494         {
05495                 if (g_bindItem == item) 
05496                 {
05497                         lowLight[0] = 0.8f * 1.0f;
05498                         lowLight[1] = 0.8f * 0.0f;
05499                         lowLight[2] = 0.8f * 0.0f;
05500                         lowLight[3] = 0.8f * 1.0f;
05501                 } 
05502                 else 
05503                 {
05504                         lowLight[0] = 0.8f * parent->focusColor[0]; 
05505                         lowLight[1] = 0.8f * parent->focusColor[1]; 
05506                         lowLight[2] = 0.8f * parent->focusColor[2]; 
05507                         lowLight[3] = 0.8f * parent->focusColor[3]; 
05508                 }
05509                 LerpColor(parent->focusColor,lowLight,newColor,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
05510         } 
05511         else 
05512         {
05513                 memcpy(&newColor, &item->window.foreColor, sizeof(vec4_t));
05514         }
05515 
05516         if (item->text) 
05517         {
05518                 Item_Text_Paint(item);
05519                 BindingFromName(item->cvar);
05520 
05521                 // If the text runs past the limit bring the scale down until it fits.
05522                 textScale = item->textscale;
05523                 textWidth = DC->textWidth(g_nameBind1,(float) textScale, item->iMenuFont);
05524                 startingXPos = (item->textRect.x + item->textRect.w + 8);
05525 
05526                 while ((startingXPos + textWidth) >= SCREEN_WIDTH)
05527                 {
05528                         textScale -= .05f;
05529                         textWidth = DC->textWidth(g_nameBind1,(float) textScale, item->iMenuFont);
05530                 }
05531 
05532                 // Try to adjust it's y placement if the scale has changed.
05533                 yAdj = 0;
05534                 if (textScale != item->textscale)
05535                 {
05536                         textHeight = DC->textHeight(g_nameBind1, item->textscale, item->iMenuFont);
05537                         yAdj = textHeight - DC->textHeight(g_nameBind1, textScale, item->iMenuFont);
05538                 }
05539 
05540                 DC->drawText(startingXPos, item->textRect.y + yAdj, textScale, newColor, g_nameBind1, 0, maxChars, item->textStyle,item->iMenuFont);
05541         } 
05542         else 
05543         {
05544                 DC->drawText(item->textRect.x, item->textRect.y, item->textscale, newColor, (value != 0) ? "FIXME" : "FIXME", 0, maxChars, item->textStyle,item->iMenuFont);
05545         }
05546 }
05547 
05548 qboolean Display_KeyBindPending() {
05549         return g_waitingForKey;
05550 }
05551 
05552 qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down) {
05553         int                     id;
05554         int                     i;
05555 
05556         if (key == A_MOUSE1 && Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory) && !g_waitingForKey)
05557         {
05558                 if (down) {
05559                         g_waitingForKey = qtrue;
05560                         g_bindItem = item;
05561                 }
05562                 return qtrue;
05563         }
05564         else if (key == A_ENTER && !g_waitingForKey)
05565         {
05566                 if (down) 
05567                 {
05568                         g_waitingForKey = qtrue;
05569                         g_bindItem = item;
05570                 }
05571                 return qtrue;
05572         }
05573         else
05574         {
05575                 if (!g_waitingForKey || g_bindItem == NULL) {
05576                         return qfalse;
05577                 }
05578 
05579                 if (key & K_CHAR_FLAG) {
05580                         return qtrue;
05581                 }
05582 
05583                 switch (key)
05584                 {
05585                         case A_ESCAPE:
05586                                 g_waitingForKey = qfalse;
05587                                 return qtrue;
05588         
05589                         case A_BACKSPACE:
05590                                 id = BindingIDFromName(item->cvar);
05591                                 if (id != -1) 
05592                                 {
05593                                         if ( g_bindings[id].bind1 != -1 )
05594                                         {
05595                                                 DC->setBinding ( g_bindings[id].bind1, "" );
05596                                         }
05597                                         
05598                                         if ( g_bindings[id].bind2 != -1 )
05599                                         {
05600                                                 DC->setBinding ( g_bindings[id].bind2, "" );
05601                                         }
05602                                                                 
05603                                         g_bindings[id].bind1 = -1;
05604                                         g_bindings[id].bind2 = -1;
05605                                 }
05606                                 Controls_SetConfig(qtrue);
05607                                 g_waitingForKey = qfalse;
05608                                 g_bindItem = NULL;
05609                                 return qtrue;
05610 
05611                         case '`':
05612                                 return qtrue;
05613                 }
05614         }
05615 
05616         if (key != -1)
05617         {
05618 
05619                 for (i=0; i < g_bindCount; i++)
05620                 {
05621 
05622                         if (g_bindings[i].bind2 == key) {
05623                                 g_bindings[i].bind2 = -1;
05624                         }
05625 
05626                         if (g_bindings[i].bind1 == key)
05627                         {
05628                                 g_bindings[i].bind1 = g_bindings[i].bind2;
05629                                 g_bindings[i].bind2 = -1;
05630                         }
05631                 }
05632         }
05633 
05634 
05635         id = BindingIDFromName(item->cvar);
05636 
05637         if (id != -1) {
05638                 if (key == -1) {
05639                         if( g_bindings[id].bind1 != -1 ) {
05640                                 DC->setBinding( g_bindings[id].bind1, "" );
05641                                 g_bindings[id].bind1 = -1;
05642                         }
05643                         if( g_bindings[id].bind2 != -1 ) {
05644                                 DC->setBinding( g_bindings[id].bind2, "" );
05645                                 g_bindings[id].bind2 = -1;
05646                         }
05647                 }
05648                 else if (g_bindings[id].bind1 == -1) {
05649                         g_bindings[id].bind1 = key;
05650                 }
05651                 else if (g_bindings[id].bind1 != key && g_bindings[id].bind2 == -1) {
05652                         g_bindings[id].bind2 = key;
05653                 }
05654                 else {
05655                         DC->setBinding( g_bindings[id].bind1, "" );
05656                         DC->setBinding( g_bindings[id].bind2, "" );
05657                         g_bindings[id].bind1 = key;
05658                         g_bindings[id].bind2 = -1;
05659                 }                                               
05660         }
05661 
05662         Controls_SetConfig(qtrue);      
05663         g_waitingForKey = qfalse;
05664 
05665         return qtrue;
05666 }
05667 
05668 void UI_ScaleModelAxis(refEntity_t      *ent)
05669 
05670 {               // scale the model should we need to
05671                 if (ent->modelScale[0] && ent->modelScale[0] != 1.0f)
05672                 {
05673                         VectorScale( ent->axis[0], ent->modelScale[0] , ent->axis[0] );
05674                         ent->nonNormalizedAxes = qtrue;
05675                 }
05676                 if (ent->modelScale[1] && ent->modelScale[1] != 1.0f)
05677                 {
05678                         VectorScale( ent->axis[1], ent->modelScale[1] , ent->axis[1] );
05679                         ent->nonNormalizedAxes = qtrue;
05680                 }
05681                 if (ent->modelScale[2] && ent->modelScale[2] != 1.0f)
05682                 {
05683                         VectorScale( ent->axis[2], ent->modelScale[2] , ent->axis[2] );
05684                         ent->nonNormalizedAxes = qtrue;
05685                 }
05686 }
05687 
05688 #ifndef CGAME
05689 #include "../namespace_end.h"   // Yes, these are inverted. The whole file is in the namespace.
05690 extern void UI_SaberAttachToChar( itemDef_t *item );
05691 #include "../namespace_begin.h"
05692 #endif
05693 
05694 void Item_Model_Paint(itemDef_t *item) 
05695 {
05696         float x, y, w, h;
05697         refdef_t refdef;
05698         refEntity_t             ent;
05699         vec3_t                  mins, maxs, origin;
05700         vec3_t                  angles;
05701         modelDef_t *modelPtr = (modelDef_t*)item->typeData;
05702 
05703         if (modelPtr == NULL) 
05704         {
05705                 return;
05706         }
05707 
05708         // a moves datapad anim is playing
05709 #ifndef CGAME
05710         if (uiInfo.moveAnimTime && (uiInfo.moveAnimTime < uiInfo.uiDC.realTime))
05711         {
05712                 modelDef_t *modelPtr;
05713                 modelPtr = (modelDef_t*)item->typeData;
05714                 if (modelPtr)
05715                 {
05716                         char modelPath[MAX_QPATH];
05717 
05718                         Com_sprintf( modelPath, sizeof( modelPath ), "models/players/%s/model.glm", UI_Cvar_VariableString ( "ui_char_model" ) );
05719                         //HACKHACKHACK: check for any multi-part anim sequences, and play the next anim, if needbe
05720                         switch( modelPtr->g2anim )
05721                         {
05722                         case BOTH_FORCEWALLREBOUND_FORWARD:
05723                         case BOTH_FORCEJUMP1: 
05724                                 ItemParse_model_g2anim_go( item, animTable[BOTH_FORCEINAIR1].name );
05725                                 ItemParse_asset_model_go( item, modelPath, &uiInfo.moveAnimTime );
05726                                 if ( !uiInfo.moveAnimTime )
05727                                 {
05728                                         uiInfo.moveAnimTime = 500;
05729                                 }
05730                                 uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
05731                                 break;
05732                         case BOTH_FORCEINAIR1:
05733                                 ItemParse_model_g2anim_go( item, animTable[BOTH_FORCELAND1].name );
05734                                 ItemParse_asset_model_go( item, modelPath, &uiInfo.moveAnimTime );
05735                                 uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
05736                                 break;
05737                         case BOTH_FORCEWALLRUNFLIP_START:
05738                                 ItemParse_model_g2anim_go( item, animTable[BOTH_FORCEWALLRUNFLIP_END].name );
05739                                 ItemParse_asset_model_go( item, modelPath, &uiInfo.moveAnimTime );
05740                                 uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
05741                                 break;
05742                         case BOTH_FORCELONGLEAP_START:
05743                                 ItemParse_model_g2anim_go( item, animTable[BOTH_FORCELONGLEAP_LAND].name );
05744                                 ItemParse_asset_model_go( item, modelPath, &uiInfo.moveAnimTime );
05745                                 uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
05746                                 break;
05747                         case BOTH_KNOCKDOWN3://on front - into force getup
05748                                 trap_S_StartLocalSound( uiInfo.uiDC.Assets.moveJumpSound, CHAN_LOCAL );
05749                                 ItemParse_model_g2anim_go( item, animTable[BOTH_FORCE_GETUP_F1].name );
05750                                 ItemParse_asset_model_go( item, modelPath, &uiInfo.moveAnimTime );
05751                                 uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
05752                                 break;
05753                         case BOTH_KNOCKDOWN2://on back - kick forward getup
05754                                 trap_S_StartLocalSound( uiInfo.uiDC.Assets.moveJumpSound, CHAN_LOCAL );
05755                                 ItemParse_model_g2anim_go( item, animTable[BOTH_GETUP_BROLL_F].name );
05756                                 ItemParse_asset_model_go( item, modelPath, &uiInfo.moveAnimTime );
05757                                 uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
05758                                 break;
05759                         case BOTH_KNOCKDOWN1://on back - roll-away
05760                                 trap_S_StartLocalSound( uiInfo.uiDC.Assets.moveRollSound, CHAN_LOCAL );
05761                                 ItemParse_model_g2anim_go( item, animTable[BOTH_GETUP_BROLL_R].name );
05762                                 ItemParse_asset_model_go( item, modelPath, &uiInfo.moveAnimTime );
05763                                 uiInfo.moveAnimTime += uiInfo.uiDC.realTime;
05764                                 break;
05765                         default:
05766                                 ItemParse_model_g2anim_go( item,  uiInfo.movesBaseAnim );
05767                                 ItemParse_asset_model_go( item, modelPath, &uiInfo.moveAnimTime );
05768                                 uiInfo.moveAnimTime = 0;
05769                                 break;
05770                         }
05771 
05772                         UI_UpdateCharacterSkin();
05773 
05774                         //update saber models
05775                         UI_SaberAttachToChar( item );
05776                 }
05777         }
05778 #endif
05779 
05780         // setup the refdef
05781         memset( &refdef, 0, sizeof( refdef ) );
05782 
05783         refdef.rdflags = RDF_NOWORLDMODEL;
05784         AxisClear( refdef.viewaxis );
05785         x = item->window.rect.x+1;
05786         y = item->window.rect.y+1;
05787         w = item->window.rect.w-2;
05788         h = item->window.rect.h-2;
05789 
05790         refdef.x = x * DC->xscale;
05791         refdef.y = y * DC->yscale;
05792         refdef.width = w * DC->xscale;
05793         refdef.height = h * DC->yscale;
05794 
05795         if (item->ghoul2)
05796         { //ghoul2 models don't have bounds, so we have to parse them.
05797                 VectorCopy(modelPtr->g2mins, mins);
05798                 VectorCopy(modelPtr->g2maxs, maxs);
05799 
05800                 if (!mins[0] && !mins[1] && !mins[2] &&
05801                         !maxs[0] && !maxs[1] && !maxs[2])
05802                 { //we'll use defaults then I suppose.
05803                         VectorSet(mins, -16, -16, -24);
05804                         VectorSet(maxs, 16, 16, 32);
05805                 }
05806         }
05807         else
05808         {
05809                 DC->modelBounds( item->asset, mins, maxs );
05810         }
05811 
05812         origin[2] = -0.5 * ( mins[2] + maxs[2] );
05813         origin[1] = 0.5 * ( mins[1] + maxs[1] );
05814 
05815         // calculate distance so the model nearly fills the box
05816         if (qtrue) 
05817         {
05818                 float len = 0.5 * ( maxs[2] - mins[2] );                
05819                 origin[0] = len / 0.268;        // len / tan( fov/2 )
05820                 //origin[0] = len / tan(w/2);
05821         } 
05822         else 
05823         {
05824                 origin[0] = item->textscale;
05825         }
05826         refdef.fov_x = (modelPtr->fov_x) ? modelPtr->fov_x : (int)((float)refdef.width / 640.0f * 90.0f);
05827         refdef.fov_y = (modelPtr->fov_y) ? modelPtr->fov_y : atan2( refdef.height, refdef.width / tan( refdef.fov_x / 360 * M_PI ) ) * ( 360 / M_PI );
05828         
05829         //refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f);
05830         //refdef.fov_y = atan2( refdef.height, refdef.width / tan( refdef.fov_x / 360 * M_PI ) ) * ( 360 / M_PI );
05831 
05832         DC->clearScene();
05833 
05834         refdef.time = DC->realTime;
05835 
05836         // add the model
05837 
05838         memset( &ent, 0, sizeof(ent) );
05839 
05840         // use item storage to track
05841         if ( (item->flags&ITF_ISANYSABER) && !(item->flags&ITF_ISCHARACTER) )
05842         {//hack to put saber on it's side
05843                 if (modelPtr->rotationSpeed) 
05844                 {
05845                         VectorSet( angles, modelPtr->angle+(float)refdef.time/modelPtr->rotationSpeed, 0, 90 );
05846                 }
05847                 else
05848                 {
05849                         VectorSet( angles, modelPtr->angle, 0, 90 );
05850                 }
05851         }
05852         else if (modelPtr->rotationSpeed) 
05853         {
05854                 VectorSet( angles, 0, modelPtr->angle + (float)refdef.time/modelPtr->rotationSpeed, 0 );
05855         }
05856         else 
05857         {
05858                 VectorSet( angles, 0, modelPtr->angle, 0 );
05859         }
05860 
05861         AnglesToAxis( angles, ent.axis );
05862 
05863         if (item->ghoul2)
05864         {
05865                 ent.ghoul2 = item->ghoul2;
05866                 ent.radius = 1000;
05867                 ent.customSkin = modelPtr->g2skin;
05868 
05869                 VectorCopy(modelPtr->g2scale, ent.modelScale);
05870                 UI_ScaleModelAxis(&ent);
05871 #ifndef CGAME
05872                 if ( (item->flags&ITF_ISCHARACTER) )
05873                 {
05874                         ent.shaderRGBA[0] = ui_char_color_red.integer;
05875                         ent.shaderRGBA[1] = ui_char_color_green.integer;
05876                         ent.shaderRGBA[2] = ui_char_color_blue.integer;
05877                         ent.shaderRGBA[3] = 255;
05878 //                      UI_TalkingHead(item);
05879                 }
05880                 if ( item->flags&ITF_ISANYSABER )
05881                 {//UGH, draw the saber blade!
05882                         UI_SaberDrawBlades( item, origin, angles );
05883                 }
05884 #endif
05885         }
05886         else
05887         {
05888                 ent.hModel = item->asset;
05889         }
05890         VectorCopy( origin, ent.origin );
05891         VectorCopy( ent.origin, ent.oldorigin );
05892 
05893         // Set up lighting
05894         VectorCopy( origin, ent.lightingOrigin );
05895         ent.renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;
05896 
05897         DC->addRefEntityToScene( &ent );
05898         DC->renderScene( &refdef );
05899 
05900 }
05901 
05902 
05903 void Item_Image_Paint(itemDef_t *item) {
05904         if (item == NULL) {
05905                 return;
05906         }
05907         DC->drawHandlePic(item->window.rect.x+1, item->window.rect.y+1, item->window.rect.w-2, item->window.rect.h-2, item->asset);
05908 }
05909 
05910 
05911 void Item_TextScroll_Paint(itemDef_t *item) 
05912 {
05913         char cvartext[1024];
05914         float x, y, size, count, thumb;
05915         int       i;
05916         textScrollDef_t *scrollPtr = (textScrollDef_t*)item->typeData;
05917 
05918         count = scrollPtr->iLineCount;
05919 
05920         // draw scrollbar to right side of the window
05921         x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE - 1;
05922         y = item->window.rect.y + 1;
05923         DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowUp);
05924         y += SCROLLBAR_SIZE - 1;
05925 
05926         scrollPtr->endPos = scrollPtr->startPos;
05927         size = item->window.rect.h - (SCROLLBAR_SIZE * 2);
05928         DC->drawHandlePic(x, y, SCROLLBAR_SIZE, size+1, DC->Assets.scrollBar);
05929         y += size - 1;
05930         DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowDown);
05931         
05932         // thumb
05933         thumb = Item_TextScroll_ThumbDrawPosition(item);
05934         if (thumb > y - SCROLLBAR_SIZE - 1) 
05935         {
05936                 thumb = y - SCROLLBAR_SIZE - 1;
05937         }
05938         DC->drawHandlePic(x, thumb, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
05939 
05940         if (item->cvar) 
05941         {
05942                 DC->getCVarString(item->cvar, cvartext, sizeof(cvartext));
05943                 item->text = cvartext;
05944                 Item_TextScroll_BuildLines ( item );
05945         }
05946 
05947         // adjust size for item painting
05948         size = item->window.rect.h - 2;
05949         x        = item->window.rect.x + item->textalignx + 1;
05950         y        = item->window.rect.y + item->textaligny + 1;
05951 
05952         for (i = scrollPtr->startPos; i < count; i++) 
05953         {
05954                 const char *text;
05955 
05956                 text = scrollPtr->pLines[i];
05957                 if (!text) 
05958                 {
05959                         continue;
05960                 }
05961 
05962                 DC->drawText(x + 4, y, item->textscale, item->window.foreColor, text, 0, 0, item->textStyle, item->iMenuFont);
05963 
05964                 size -= scrollPtr->lineHeight;
05965                 if (size < scrollPtr->lineHeight) 
05966                 {
05967                         scrollPtr->drawPadding = scrollPtr->lineHeight - size;
05968                         break;
05969                 }
05970 
05971                 scrollPtr->endPos++;
05972                 y += scrollPtr->lineHeight;
05973         }
05974 }
05975 
05976 #define COLOR_MAX 255.0f
05977 
05978 // Draw routine for list boxes
05979 void Item_ListBox_Paint(itemDef_t *item) {
05980         float x, y, sizeWidth, count, i, i2,sizeHeight, thumb;
05981         int startPos;
05982         qhandle_t image;
05983         qhandle_t optionalImage1, optionalImage2, optionalImage3;
05984         listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
05985 //JLF MPMOVED
05986         int numlines;
05987 
05988 
05989         // the listbox is horizontal or vertical and has a fixed size scroll bar going either direction
05990         // elements are enumerated from the DC and either text or image handles are acquired from the DC as well
05991         // textscale is used to size the text, textalignx and textaligny are used to size image elements
05992         // there is no clipping available so only the last completely visible item is painted
05993         count = DC->feederCount(item->special);
05994 
05995 //JLFLISTBOX  MPMOVED
05996 #ifdef _XBOX
05997         listPtr->startPos = listPtr->cursorPos;
05998         //item->cursorPos = listPtr->startPos;
05999 #endif
06000 //JLFLISTBOX MPMOVED
06001         if (listPtr->startPos > (count?count-1:count))
06002         {//probably changed feeders, so reset
06003                 listPtr->startPos = 0;
06004         }
06005 //JLF END
06006         if (item->cursorPos > (count?count-1:count))
06007         {//probably changed feeders, so reset
06008                 item->cursorPos = (count?count-1:count);
06009                 // NOTE : might consider moving this to any spot in here we change the cursor position
06010                 DC->feederSelection( item->special, item->cursorPos, NULL );
06011         }
06012 
06013         
06014 
06015         // default is vertical if horizontal flag is not here
06016         if (item->window.flags & WINDOW_HORIZONTAL) 
06017         {
06018 #ifdef  _DEBUG
06019                 const char *text;
06020 #endif
06021 
06022 //JLF new variable (code just indented) MPMOVED
06023                 if (!listPtr->scrollhidden)
06024                 {
06025                 // draw scrollbar in bottom of the window
06026                 // bar
06027                         if (Item_ListBox_MaxScroll(item) > 0) 
06028                         {
06029                                 x = item->window.rect.x + 1;
06030                                 y = item->window.rect.y + item->window.rect.h - SCROLLBAR_SIZE - 1;
06031                                 DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowLeft);
06032                                 x += SCROLLBAR_SIZE - 1;
06033                                 sizeWidth = item->window.rect.w - (SCROLLBAR_SIZE * 2);
06034                                 DC->drawHandlePic(x, y, sizeWidth+1, SCROLLBAR_SIZE, DC->Assets.scrollBar);
06035                                 x += sizeWidth - 1;
06036                                 DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowRight);
06037                                 // thumb
06038                                 thumb = Item_ListBox_ThumbDrawPosition(item);//Item_ListBox_ThumbPosition(item);
06039                                 if (thumb > x - SCROLLBAR_SIZE - 1) {
06040                                         thumb = x - SCROLLBAR_SIZE - 1;
06041                                 }
06042                                 DC->drawHandlePic(thumb, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
06043                         }
06044                         else if (listPtr->startPos > 0)
06045                         {
06046                                 listPtr->startPos = 0;
06047                         }
06048                 }
06049 //JLF end
06050                 //
06051                 listPtr->endPos = listPtr->startPos;
06052                 sizeWidth = item->window.rect.w - 2;
06053                 // items
06054                 // size contains max available space
06055                 if (listPtr->elementStyle == LISTBOX_IMAGE) 
06056                 {
06057                         // fit = 0;
06058                         x = item->window.rect.x + 1;
06059                         y = item->window.rect.y + 1;
06060                         for (i = listPtr->startPos; i < count; i++) 
06061                         {
06062                                 // always draw at least one
06063                                 // which may overdraw the box if it is too small for the element
06064                                 image = DC->feederItemImage(item->special, i);
06065                                 if (image) 
06066                                 {
06067 #ifndef CGAME
06068                                         if (item->window.flags & WINDOW_PLAYERCOLOR) 
06069                                         {
06070                                                 vec4_t  color;
06071 
06072                                                 color[0] = ui_char_color_red.integer/COLOR_MAX;
06073                                                 color[1] = ui_char_color_green.integer/COLOR_MAX;
06074                                                 color[2] = ui_char_color_blue.integer/COLOR_MAX;
06075                                                 color[3] = 1.0f;
06076                                                 DC->setColor(color);
06077                                         }
06078 #endif
06079                                         DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
06080                                 }
06081 
06082                                 if (i == item->cursorPos) 
06083                                 {
06084                                         DC->drawRect(x, y, listPtr->elementWidth-1, listPtr->elementHeight-1, item->window.borderSize, item->window.borderColor);
06085                                 }
06086 
06087                                 sizeWidth -= listPtr->elementWidth;
06088                                 if (sizeWidth < listPtr->elementWidth) 
06089                                 {
06090                                         listPtr->drawPadding = sizeWidth; //listPtr->elementWidth - size;
06091                                         break;
06092                                 }
06093                                 x += listPtr->elementWidth;
06094                                 listPtr->endPos++;
06095                                 // fit++;
06096                         }
06097                 } 
06098                 else 
06099                 {
06100                         //
06101                 }
06102 
06103 #ifdef  _DEBUG
06104                 // Show pic name
06105                 text = DC->feederItemText(item->special, item->cursorPos, 0, &optionalImage1, &optionalImage2, &optionalImage3);
06106                 if (text) 
06107                 {
06108                         DC->drawText(item->window.rect.x, item->window.rect.y+item->window.rect.h, item->textscale, item->window.foreColor, text, 0, 0, item->textStyle, item->iMenuFont);
06109                 }
06110 #endif
06111 
06112         } 
06113         // A vertical list box
06114         else 
06115         {
06116 //JLF MPMOVED
06117                 numlines = item->window.rect.h / listPtr->elementHeight;
06118 //JLFEND
06119                 //JLF new variable (code idented with if)
06120                 if (!listPtr->scrollhidden)
06121                 {
06122 
06123                         // draw scrollbar to right side of the window
06124                         x = item->window.rect.x + item->window.rect.w - SCROLLBAR_SIZE - 1;
06125                         y = item->window.rect.y + 1;
06126                         DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowUp);
06127                         y += SCROLLBAR_SIZE - 1;
06128 
06129                         listPtr->endPos = listPtr->startPos;
06130                         sizeHeight = item->window.rect.h - (SCROLLBAR_SIZE * 2);
06131                         DC->drawHandlePic(x, y, SCROLLBAR_SIZE, sizeHeight+1, DC->Assets.scrollBar);
06132                         y += sizeHeight - 1;
06133                         DC->drawHandlePic(x, y, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarArrowDown);
06134                         // thumb
06135                         thumb = Item_ListBox_ThumbDrawPosition(item);//Item_ListBox_ThumbPosition(item);
06136                         if (thumb > y - SCROLLBAR_SIZE - 1) {
06137                                 thumb = y - SCROLLBAR_SIZE - 1;
06138                         }
06139                         DC->drawHandlePic(x, thumb, SCROLLBAR_SIZE, SCROLLBAR_SIZE, DC->Assets.scrollBarThumb);
06140                 }
06141 //JLF end
06142 
06143                 // adjust size for item painting
06144                 sizeWidth = item->window.rect.w - 2;
06145                 sizeHeight = item->window.rect.h - 2;
06146 
06147                 if (listPtr->elementStyle == LISTBOX_IMAGE) 
06148                 {
06149                         // Multiple rows and columns (since it's more than twice as wide as an element)
06150                         if ( item->window.rect.w > (listPtr->elementWidth*2) )
06151                         {
06152                                 startPos = listPtr->startPos;
06153                                 x = item->window.rect.x + 1;
06154                                 y = item->window.rect.y + 1;
06155                                 // Next row
06156                                 for (i2 = startPos; i2 < count; i2++) 
06157                                 {
06158                                         x = item->window.rect.x + 1;
06159                                         sizeWidth = item->window.rect.w - 2;
06160                                         // print a row
06161                                         for (i = startPos; i < count; i++) 
06162                                         {
06163                                                 // always draw at least one
06164                                                 // which may overdraw the box if it is too small for the element
06165                                                 image = DC->feederItemImage(item->special, i);
06166                                                 if (image) 
06167                                                 {
06168                 #ifndef CGAME
06169                                                         if (item->window.flags & WINDOW_PLAYERCOLOR) 
06170                                                         {
06171                                                                 vec4_t  color;
06172 
06173                                                                 color[0] = ui_char_color_red.integer/COLOR_MAX;
06174                                                                 color[1] = ui_char_color_green.integer/COLOR_MAX;
06175                                                                 color[2] = ui_char_color_blue.integer/COLOR_MAX;
06176                                                                 color[3] = 1.0f;
06177                                                                 DC->setColor(color);
06178                                                         }
06179                 #endif
06180                                                         DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
06181                                                 }
06182 
06183                                                 if (i == item->cursorPos) 
06184                                                 {
06185                                                         DC->drawRect(x, y, listPtr->elementWidth-1, listPtr->elementHeight-1, item->window.borderSize, item->window.borderColor);
06186                                                 }
06187 
06188                                                 sizeWidth -= listPtr->elementWidth;
06189                                                 if (sizeWidth < listPtr->elementWidth) 
06190                                                 {
06191                                                         listPtr->drawPadding = sizeWidth; //listPtr->elementWidth - size;
06192                                                         break;
06193                                                 }
06194                                                 x += listPtr->elementWidth;
06195                                                 listPtr->endPos++;
06196                                         }
06197 
06198                                         sizeHeight -= listPtr->elementHeight;
06199                                         if (sizeHeight < listPtr->elementHeight) 
06200                                         {
06201                                                 listPtr->drawPadding = sizeHeight; //listPtr->elementWidth - size;
06202                                                 break;
06203                                         }
06204                                         // NOTE : Is endPos supposed to be valid or not? It was being used as a valid entry but I changed those
06205                                         // few spots that were causing bugs
06206                                         listPtr->endPos++;
06207                                         startPos = listPtr->endPos;
06208                                         y += listPtr->elementHeight;
06209 
06210                                 }
06211                         }
06212                         // single column
06213                         else
06214                         {
06215                                 x = item->window.rect.x + 1;
06216                                 y = item->window.rect.y + 1;
06217                                 for (i = listPtr->startPos; i < count; i++) 
06218                                 {
06219                                         // always draw at least one
06220                                         // which may overdraw the box if it is too small for the element
06221                                         image = DC->feederItemImage(item->special, i);
06222                                         if (image) 
06223                                         {
06224                                                 DC->drawHandlePic(x+1, y+1, listPtr->elementWidth - 2, listPtr->elementHeight - 2, image);
06225                                         }
06226 
06227                                         if (i == item->cursorPos) 
06228                                         {
06229                                                 DC->drawRect(x, y, listPtr->elementWidth - 1, listPtr->elementHeight - 1, item->window.borderSize, item->window.borderColor);
06230                                         }
06231 
06232                                         listPtr->endPos++;
06233                                         sizeHeight -= listPtr->elementHeight;
06234                                         if (sizeHeight < listPtr->elementHeight) 
06235                                         {
06236                                                 listPtr->drawPadding = listPtr->elementHeight - sizeHeight;
06237                                                 break;
06238                                         }
06239                                         y += listPtr->elementHeight;
06240                                         // fit++;
06241                                 }
06242                         }
06243                 } 
06244                 else 
06245                 {
06246                         x = item->window.rect.x + 1;
06247                         y = item->window.rect.y + 1;
06248 //JLF MPMOVED
06249                         y = item->window.rect.y + 1 - listPtr->elementHeight;
06250 #ifdef _XBOX
06251                         i = listPtr->startPos - (numlines/2);
06252 #else
06253                         i = listPtr->startPos;
06254 #endif
06255 
06256                         for (; i < count; i++) 
06257 //JLF END
06258                         {
06259                                 const char *text;
06260                                 // always draw at least one
06261                                 // which may overdraw the box if it is too small for the element
06262                                 if (listPtr->numColumns > 0) {
06263                                         int j;//, subX = listPtr->elementHeight;
06264 
06265                                         for (j = 0; j < listPtr->numColumns; j++) 
06266                                         {
06267                                                 char    temp[MAX_STRING_CHARS];
06268                                                 int imageStartX = listPtr->columnInfo[j].pos;
06269                                                 text = DC->feederItemText(item->special, i, j, &optionalImage1, &optionalImage2, &optionalImage3);
06270 
06271                                                 if( !text )
06272                                                 {
06273                                                         continue;
06274                                                 }
06275 
06276                                                 if (text[0]=='@')
06277                                                 {
06278                                                         trap_SP_GetStringTextString( &text[1]  , temp, sizeof(temp));
06279                                                         text = temp;
06280                                                 }
06281 
06282                                                 /*
06283                                                 if (optionalImage >= 0) {
06284                                                         DC->drawHandlePic(x + 4 + listPtr->columnInfo[j].pos, y - 1 + listPtr->elementHeight / 2, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
06285                                                 } 
06286                                                 else 
06287                                                 */
06288                                                 if ( text )
06289                                                 {
06290 //JLF MPMOVED
06291 #ifdef _XBOX
06292                                                         float fScaleA = item->textscale;
06293 #endif
06294                                                         int textyOffset;
06295 #ifdef _XBOX
06296                                                         textyOffset = DC->textHeight (text, fScaleA, item->iMenuFont);
06297                                                         textyOffset *= -1;
06298                                                         textyOffset /=2;
06299                                                         textyOffset += listPtr->elementHeight/2;
06300 #else
06301                                                         textyOffset = 0;
06302 #endif
06303 //                                                      DC->drawText(x + 4 + listPtr->columnInfo[j].pos, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, listPtr->columnInfo[j].maxChars, item->textStyle);
06304         //WAS LAST                                              DC->drawText(x + 4 + listPtr->columnInfo[j].pos, y, item->textscale, item->window.foreColor, text, 0, listPtr->columnInfo[j].maxChars, item->textStyle, item->iMenuFont);
06305                                                         DC->drawText(x + 4 + listPtr->columnInfo[j].pos, y + listPtr->elementHeight+ textyOffset + item->textaligny, item->textscale, item->window.foreColor, text, 0,listPtr->columnInfo[j].maxChars, item->textStyle, item->iMenuFont);
06306 
06307 
06308 //JLF END
06309                                                 }
06310                                                 if ( j < listPtr->numColumns - 1 )
06311                                                 {
06312                                                         imageStartX = listPtr->columnInfo[j+1].pos;
06313                                                 }
06314                                                 DC->setColor( NULL );
06315                                                 if (optionalImage3 >= 0) 
06316                                                 {
06317                                                         DC->drawHandlePic(imageStartX - listPtr->elementHeight*3, y+listPtr->elementHeight+2, listPtr->elementHeight, listPtr->elementHeight, optionalImage3);
06318                                                 } 
06319                                                 if (optionalImage2 >= 0) 
06320                                                 {
06321                                                         DC->drawHandlePic(imageStartX - listPtr->elementHeight*2, y+listPtr->elementHeight+2, listPtr->elementHeight, listPtr->elementHeight, optionalImage2);
06322                                                 } 
06323                                                 if (optionalImage1 >= 0) 
06324                                                 {
06325                                                         DC->drawHandlePic(imageStartX - listPtr->elementHeight, y+listPtr->elementHeight+2, listPtr->elementHeight, listPtr->elementHeight, optionalImage1);
06326                                                 } 
06327                                         }
06328                                 } 
06329                                 else 
06330                                 {
06331 #ifdef _XBOX
06332                                         if (i >= 0)
06333                                         {
06334 #endif
06335                                         text = DC->feederItemText(item->special, i, 0, &optionalImage1, &optionalImage2, &optionalImage3 );
06336                                         if ( optionalImage1 >= 0 || optionalImage2 >= 0 || optionalImage3 >= 0) 
06337                                         {
06338                                                 //DC->drawHandlePic(x + 4 + listPtr->elementHeight, y, listPtr->columnInfo[j].width, listPtr->columnInfo[j].width, optionalImage);
06339                                         } 
06340                                         else if (text) 
06341                                         {
06342 //                                              DC->drawText(x + 4, y + listPtr->elementHeight, item->textscale, item->window.foreColor, text, 0, 0, item->textStyle);
06343                                                 DC->drawText(x + 4, y + item->textaligny, item->textscale, item->window.foreColor, text, 0, 0, item->textStyle, item->iMenuFont);
06344                                         }
06345 #ifdef _XBOX
06346                                         }
06347 #endif
06348                                 }
06349 
06350                                 if (i == item->cursorPos) 
06351                                 {
06352                                         DC->fillRect(x + 2, y + listPtr->elementHeight + 2, item->window.rect.w - SCROLLBAR_SIZE - 4, listPtr->elementHeight, item->window.outlineColor);
06353                                 }
06354 
06355                                 sizeHeight -= listPtr->elementHeight;
06356                                 if (sizeHeight < listPtr->elementHeight) 
06357                                 {
06358                                         listPtr->drawPadding = listPtr->elementHeight - sizeHeight;
06359                                         break;
06360                                 }
06361                                 listPtr->endPos++;
06362                                 y += listPtr->elementHeight;
06363                                 // fit++;
06364                         }
06365                 }
06366         }
06367 }
06368 
06369 
06370 void Item_OwnerDraw_Paint(itemDef_t *item) {
06371   menuDef_t *parent;
06372 
06373         if (item == NULL) {
06374                 return;
06375         }
06376   parent = (menuDef_t*)item->parent;
06377 
06378         if (DC->ownerDrawItem) {
06379                 vec4_t color, lowLight;
06380                 menuDef_t *parent = (menuDef_t*)item->parent;
06381                 Fade(&item->window.flags, &item->window.foreColor[3], parent->fadeClamp, &item->window.nextTime, parent->fadeCycle, qtrue, parent->fadeAmount);
06382                 memcpy(&color, &item->window.foreColor, sizeof(color));
06383                 if (item->numColors > 0 && DC->getValue) {
06384                         // if the value is within one of the ranges then set color to that, otherwise leave at default
06385                         int i;
06386                         float f = DC->getValue(item->window.ownerDraw);
06387                         for (i = 0; i < item->numColors; i++) {
06388                                 if (f >= item->colorRanges[i].low && f <= item->colorRanges[i].high) {
06389                                         memcpy(&color, &item->colorRanges[i].color, sizeof(color));
06390                                         break;
06391                                 }
06392                         }
06393                 }
06394 
06395                 if (item->window.flags & WINDOW_HASFOCUS) {
06396                         lowLight[0] = 0.8 * parent->focusColor[0]; 
06397                         lowLight[1] = 0.8 * parent->focusColor[1]; 
06398                         lowLight[2] = 0.8 * parent->focusColor[2]; 
06399                         lowLight[3] = 0.8 * parent->focusColor[3]; 
06400                         LerpColor(parent->focusColor,lowLight,color,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
06401                 } else if (item->textStyle == ITEM_TEXTSTYLE_BLINK && !((DC->realTime/BLINK_DIVISOR) & 1)) {
06402                         lowLight[0] = 0.8 * item->window.foreColor[0]; 
06403                         lowLight[1] = 0.8 * item->window.foreColor[1]; 
06404                         lowLight[2] = 0.8 * item->window.foreColor[2]; 
06405                         lowLight[3] = 0.8 * item->window.foreColor[3]; 
06406                         LerpColor(item->window.foreColor,lowLight,color,0.5+0.5*sin((float)(DC->realTime / PULSE_DIVISOR)));
06407                 }
06408 
06409                 if (item->disabled) 
06410                 {
06411                         memcpy(color, parent->disableColor, sizeof(vec4_t)); // bk001207 - FIXME: Com_Memcpy
06412                 }
06413 
06414                 if (item->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(item, CVAR_ENABLE)) {
06415                   memcpy(color, parent->disableColor, sizeof(vec4_t)); // bk001207 - FIXME: Com_Memcpy
06416                 }
06417         
06418                 if (item->text) {
06419                         Item_Text_Paint(item);
06420                                 if (item->text[0]) {
06421                                         // +8 is an offset kludge to properly align owner draw items that have text combined with them
06422                                         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,item->iMenuFont);
06423                                 } else {
06424                                         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,item->iMenuFont);
06425                                 }
06426                         } else {
06427                         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,item->iMenuFont);
06428                 }
06429         }
06430 }
06431 
06432 
06433 void Item_Paint(itemDef_t *item) 
06434 {
06435         vec4_t          red;
06436         menuDef_t *parent = (menuDef_t*)item->parent;
06437         int                     xPos,textWidth;
06438         vec4_t          color = {1, 1, 1, 1};
06439 
06440         red[0] = red[3] = 1;
06441         red[1] = red[2] = 0;
06442 
06443         if (item == NULL) 
06444         {
06445                 return;
06446         }
06447 
06448         if (item->window.flags & WINDOW_ORBITING) 
06449         {
06450                 if (DC->realTime > item->window.nextTime) 
06451                 {
06452                         float rx, ry, a, c, s, w, h;
06453       
06454                         item->window.nextTime = DC->realTime + item->window.offsetTime;
06455                         // translate
06456                         w = item->window.rectClient.w / 2;
06457                         h = item->window.rectClient.h / 2;
06458                         rx = item->window.rectClient.x + w - item->window.rectEffects.x;
06459                         ry = item->window.rectClient.y + h - item->window.rectEffects.y;
06460                         a = 3 * M_PI / 180;
06461                         c = cos(a);
06462                         s = sin(a);
06463                         item->window.rectClient.x = (rx * c - ry * s) + item->window.rectEffects.x - w;
06464                         item->window.rectClient.y = (rx * s + ry * c) + item->window.rectEffects.y - h;
06465                         Item_UpdatePosition(item);
06466                 }
06467         }
06468 
06469 
06470         if (item->window.flags & WINDOW_INTRANSITION) 
06471         {
06472                 if (DC->realTime > item->window.nextTime) 
06473                 {
06474                         int done = 0;
06475                         item->window.nextTime = DC->realTime + item->window.offsetTime;
06476 
06477                         // transition the x,y
06478                         if (item->window.rectClient.x == item->window.rectEffects.x) 
06479                         {
06480                                 done++;
06481                         } 
06482                         else 
06483                         {
06484                                 if (item->window.rectClient.x < item->window.rectEffects.x) 
06485                                 {
06486                                         item->window.rectClient.x += item->window.rectEffects2.x;
06487                                         if (item->window.rectClient.x > item->window.rectEffects.x) 
06488                                         {
06489                                                 item->window.rectClient.x = item->window.rectEffects.x;
06490                                                 done++;
06491                                         }
06492                                 } 
06493                                 else 
06494                                 {
06495                                         item->window.rectClient.x -= item->window.rectEffects2.x;
06496                                         if (item->window.rectClient.x < item->window.rectEffects.x) 
06497                                         {
06498                                                 item->window.rectClient.x = item->window.rectEffects.x;
06499                                                 done++;
06500                                         }
06501                                 }
06502                         }
06503 
06504                         if (item->window.rectClient.y == item->window.rectEffects.y) 
06505                         {
06506                                 done++;
06507                         } 
06508                         else 
06509                         {
06510                                 if (item->window.rectClient.y < item->window.rectEffects.y) 
06511                                 {
06512                                         item->window.rectClient.y += item->window.rectEffects2.y;
06513                                         if (item->window.rectClient.y > item->window.rectEffects.y) 
06514                                         {
06515                                                 item->window.rectClient.y = item->window.rectEffects.y;
06516                                                 done++;
06517                                         }
06518                                 } 
06519                                 else 
06520                                 {
06521                                         item->window.rectClient.y -= item->window.rectEffects2.y;
06522                                         if (item->window.rectClient.y < item->window.rectEffects.y) 
06523                                         {
06524                                                 item->window.rectClient.y = item->window.rectEffects.y;
06525                                                 done++;
06526                                         }
06527                                 }
06528                         }
06529 
06530                         if (item->window.rectClient.w == item->window.rectEffects.w) 
06531                         {
06532                                 done++;
06533                         } 
06534                         else 
06535                         {
06536                                 if (item->window.rectClient.w < item->window.rectEffects.w) 
06537                                 {
06538                                         item->window.rectClient.w += item->window.rectEffects2.w;
06539                                         if (item->window.rectClient.w > item->window.rectEffects.w) 
06540                                         {
06541                                                 item->window.rectClient.w = item->window.rectEffects.w;
06542                                                 done++;
06543                                         }
06544                                 } 
06545                                 else 
06546                                 {
06547                                         item->window.rectClient.w -= item->window.rectEffects2.w;
06548                                         if (item->window.rectClient.w < item->window.rectEffects.w) 
06549                                         {
06550                                                 item->window.rectClient.w = item->window.rectEffects.w;
06551                                                 done++;
06552                                         }
06553                                 }
06554                         }
06555 
06556                         if (item->window.rectClient.h == item->window.rectEffects.h) 
06557                         {
06558                                 done++;
06559                         } 
06560                         else 
06561                         {
06562                                 if (item->window.rectClient.h < item->window.rectEffects.h) 
06563                                 {
06564                                         item->window.rectClient.h += item->window.rectEffects2.h;
06565                                         if (item->window.rectClient.h > item->window.rectEffects.h) 
06566                                         {
06567                                                 item->window.rectClient.h = item->window.rectEffects.h;
06568                                                 done++;
06569                                         }
06570                                 } 
06571                                 else 
06572                                 {
06573                                         item->window.rectClient.h -= item->window.rectEffects2.h;
06574                                         if (item->window.rectClient.h < item->window.rectEffects.h) 
06575                                         {
06576                                                 item->window.rectClient.h = item->window.rectEffects.h;
06577                                                 done++;
06578                                         }
06579                                 }
06580                         }
06581 
06582                         Item_UpdatePosition(item);
06583 
06584                         if (done == 4) 
06585                         {
06586                                 item->window.flags &= ~WINDOW_INTRANSITION;
06587                         }
06588 
06589                 }
06590         }
06591 
06592 #ifdef _TRANS3
06593         
06594 //JLF begin model transition stuff
06595         if (item->window.flags & WINDOW_INTRANSITIONMODEL) 
06596         {
06597                 if ( item->type == ITEM_TYPE_MODEL)
06598                 {
06599 //fields ing modelptr
06600 //                              vec3_t g2mins2, g2maxs2, g2minsEffect, g2maxsEffect;
06601 //      float fov_x2, fov_y2, fov_Effectx, fov_Effecty;
06602 
06603                         modelDef_t  * modelptr = (modelDef_t *)item->typeData;
06604 
06605                         if (DC->realTime > item->window.nextTime) 
06606                         {
06607                                 int done = 0;
06608                                 item->window.nextTime = DC->realTime + item->window.offsetTime;
06609 
06610 
06611 // transition the x,y,z max
06612                                 if (modelptr->g2maxs[0] == modelptr->g2maxs2[0]) 
06613                                 {
06614                                         done++;
06615                                 } 
06616                                 else 
06617                                 {
06618                                         if (modelptr->g2maxs[0] < modelptr->g2maxs2[0]) 
06619                                         {
06620                                                 modelptr->g2maxs[0] += modelptr->g2maxsEffect[0];
06621                                                 if (modelptr->g2maxs[0] > modelptr->g2maxs2[0]) 
06622                                                 {
06623                                                         modelptr->g2maxs[0] = modelptr->g2maxs2[0];
06624                                                         done++;
06625                                                 }
06626                                         } 
06627                                         else 
06628                                         {
06629                                                 modelptr->g2maxs[0] -= modelptr->g2maxsEffect[0];
06630                                                 if (modelptr->g2maxs[0] < modelptr->g2maxs2[0]) 
06631                                                 {
06632                                                         modelptr->g2maxs[0] = modelptr->g2maxs2[0];
06633                                                         done++;
06634                                                 }
06635                                         }
06636                                 }
06637 //y
06638                                 if (modelptr->g2maxs[1] == modelptr->g2maxs2[1]) 
06639                                 {
06640                                         done++;
06641                                 } 
06642                                 else 
06643                                 {
06644                                         if (modelptr->g2maxs[1] < modelptr->g2maxs2[1]) 
06645                                         {
06646                                                 modelptr->g2maxs[1] += modelptr->g2maxsEffect[1];
06647                                                 if (modelptr->g2maxs[1] > modelptr->g2maxs2[1]) 
06648                                                 {
06649                                                         modelptr->g2maxs[1] = modelptr->g2maxs2[1];
06650                                                         done++;
06651                                                 }
06652                                         } 
06653                                         else 
06654                                         {
06655                                                 modelptr->g2maxs[1] -= modelptr->g2maxsEffect[1];
06656                                                 if (modelptr->g2maxs[1] < modelptr->g2maxs2[1]) 
06657                                                 {
06658                                                         modelptr->g2maxs[1] = modelptr->g2maxs2[1];
06659                                                         done++;
06660                                                 }
06661                                         }
06662                                 }
06663 
06664 
06665 //z
06666 
06667                                 if (modelptr->g2maxs[2] == modelptr->g2maxs2[2]) 
06668                                 {
06669                                         done++;
06670                                 } 
06671                                 else 
06672                                 {
06673                                         if (modelptr->g2maxs[2] < modelptr->g2maxs2[2]) 
06674                                         {
06675                                                 modelptr->g2maxs[2] += modelptr->g2maxsEffect[2];
06676                                                 if (modelptr->g2maxs[2] > modelptr->g2maxs2[2]) 
06677                                                 {
06678                                                         modelptr->g2maxs[2] = modelptr->g2maxs2[2];
06679                                                         done++;
06680                                                 }
06681                                         } 
06682                                         else 
06683                                         {
06684                                                 modelptr->g2maxs[2] -= modelptr->g2maxsEffect[2];
06685                                                 if (modelptr->g2maxs[2] < modelptr->g2maxs2[2]) 
06686                                                 {
06687                                                         modelptr->g2maxs[2] = modelptr->g2maxs2[2];
06688                                                         done++;
06689                                                 }
06690                                         }
06691                                 }
06692 
06693 // transition the x,y,z min
06694                                 if (modelptr->g2mins[0] == modelptr->g2mins2[0]) 
06695                                 {
06696                                         done++;
06697                                 } 
06698                                 else 
06699                                 {
06700                                         if (modelptr->g2mins[0] < modelptr->g2mins2[0]) 
06701                                         {
06702                                                 modelptr->g2mins[0] += modelptr->g2minsEffect[0];
06703                                                 if (modelptr->g2mins[0] > modelptr->g2mins2[0]) 
06704                                                 {
06705                                                         modelptr->g2mins[0] = modelptr->g2mins2[0];
06706                                                         done++;
06707                                                 }
06708                                         } 
06709                                         else 
06710                                         {
06711                                                 modelptr->g2mins[0] -= modelptr->g2minsEffect[0];
06712                                                 if (modelptr->g2mins[0] < modelptr->g2mins2[0]) 
06713                                                 {
06714                                                         modelptr->g2mins[0] = modelptr->g2mins2[0];
06715                                                         done++;
06716                                                 }
06717                                         }
06718                                 }
06719 //y
06720                                 if (modelptr->g2mins[1] == modelptr->g2mins2[1]) 
06721                                 {
06722                                         done++;
06723                                 } 
06724                                 else 
06725                                 {
06726                                         if (modelptr->g2mins[1] < modelptr->g2mins2[1]) 
06727                                         {
06728                                                 modelptr->g2mins[1] += modelptr->g2minsEffect[1];
06729                                                 if (modelptr->g2mins[1] > modelptr->g2mins2[1]) 
06730                                                 {
06731                                                         modelptr->g2mins[1] = modelptr->g2mins2[1];
06732                                                         done++;
06733                                                 }
06734                                         } 
06735                                         else 
06736                                         {
06737                                                 modelptr->g2mins[1] -= modelptr->g2minsEffect[1];
06738                                                 if (modelptr->g2mins[1] < modelptr->g2mins2[1]) 
06739                                                 {
06740                                                         modelptr->g2mins[1] = modelptr->g2mins2[1];
06741                                                         done++;
06742                                                 }
06743                                         }
06744                                 }
06745 
06746 
06747 //z
06748 
06749                                 if (modelptr->g2mins[2] == modelptr->g2mins2[2]) 
06750                                 {
06751                                         done++;
06752                                 } 
06753                                 else 
06754                                 {
06755                                         if (modelptr->g2mins[2] < modelptr->g2mins2[2]) 
06756                                         {
06757                                                 modelptr->g2mins[2] += modelptr->g2minsEffect[2];
06758                                                 if (modelptr->g2mins[2] > modelptr->g2mins2[2]) 
06759                                                 {
06760                                                         modelptr->g2mins[2] = modelptr->g2mins2[2];
06761                                                         done++;
06762                                                 }
06763                                         } 
06764                                         else 
06765                                         {
06766                                                 modelptr->g2mins[2] -= modelptr->g2minsEffect[2];
06767                                                 if (modelptr->g2mins[2] < modelptr->g2mins2[2]) 
06768                                                 {
06769                                                         modelptr->g2mins[2] = modelptr->g2mins2[2];
06770                                                         done++;
06771                                                 }
06772                                         }
06773                                 }
06774 
06775 
06776 
06777 //fovx
06778                                 if (modelptr->fov_x == modelptr->fov_x2) 
06779                                 {
06780                                         done++;
06781                                 } 
06782                                 else 
06783                                 {
06784                                         if (modelptr->fov_x < modelptr->fov_x2) 
06785                                         {
06786                                                 modelptr->fov_x += modelptr->fov_Effectx;
06787                                                 if (modelptr->fov_x > modelptr->fov_x2) 
06788                                                 {
06789                                                         modelptr->fov_x = modelptr->fov_x2;
06790                                                         done++;
06791                                                 }
06792                                         } 
06793                                         else 
06794                                         {
06795                                                 modelptr->fov_x -= modelptr->fov_Effectx;
06796                                                 if (modelptr->fov_x < modelptr->fov_x2) 
06797                                                 {
06798                                                         modelptr->fov_x = modelptr->fov_x2;
06799                                                         done++;
06800                                                 }
06801                                         }
06802                                 }
06803 
06804 //fovy
06805                                 if (modelptr->fov_y == modelptr->fov_y2) 
06806                                 {
06807                                         done++;
06808                                 } 
06809                                 else 
06810                                 {
06811                                         if (modelptr->fov_y < modelptr->fov_y2) 
06812                                         {
06813                                                 modelptr->fov_y += modelptr->fov_Effecty;
06814                                                 if (modelptr->fov_y > modelptr->fov_y2) 
06815                                                 {
06816                                                         modelptr->fov_y = modelptr->fov_y2;
06817                                                         done++;
06818                                                 }
06819                                         } 
06820                                         else 
06821                                         {
06822                                                 modelptr->fov_y -= modelptr->fov_Effecty;
06823                                                 if (modelptr->fov_y < modelptr->fov_y2) 
06824                                                 {
06825                                                         modelptr->fov_y = modelptr->fov_y2;
06826                                                         done++;
06827                                                 }
06828                                         }
06829                                 }
06830 
06831                                 if (done == 5) 
06832                                 {
06833                                         item->window.flags &= ~WINDOW_INTRANSITIONMODEL;
06834                                 }
06835 
06836                         }
06837                 }
06838         }
06839 #endif
06840 //JLF end transition stuff for models
06841 
06842 
06843 
06844         if (item->window.ownerDrawFlags && DC->ownerDrawVisible) {
06845                 if (!DC->ownerDrawVisible(item->window.ownerDrawFlags)) {
06846                         item->window.flags &= ~WINDOW_VISIBLE;
06847                 } else {
06848                         item->window.flags |= WINDOW_VISIBLE;
06849                 }
06850         }
06851 
06852         if (item->cvarFlags & (CVAR_SHOW | CVAR_HIDE)) {
06853                 if (!Item_EnableShowViaCvar(item, CVAR_SHOW)) {
06854                         return;
06855                 }
06856         }
06857 
06858   if (item->window.flags & WINDOW_TIMEDVISIBLE) {
06859 
06860         }
06861 
06862         if (!(item->window.flags & WINDOW_VISIBLE)) 
06863         {
06864                 return;
06865         }
06866 
06867 
06868 //JLFMOUSE
06869 #ifndef _XBOX
06870         if (item->window.flags & WINDOW_MOUSEOVER)
06871 #else
06872         if (item->window.flags & WINDOW_HASFOCUS)
06873 #endif
06874         {
06875                 if (item->descText && !Display_KeyBindPending())
06876                 {
06877                         // Make DOUBLY sure that this item should have desctext.
06878 #ifndef _XBOX
06879                         // NOTE : we can't just check the mouse position on this, what if we TABBED
06880                         // to the current menu item -- in that case our mouse isn't over the item.
06881                         // Removing the WINDOW_MOUSEOVER flag just prevents the item's OnExit script from running
06882         //          if (!Rect_ContainsPoint(&item->window.rect, DC->cursorx, DC->cursory)) 
06883         //              {       // It isn't something that should, because it isn't live anymore.
06884         //                      item->window.flags &= ~WINDOW_MOUSEOVER;
06885         //              }
06886         //              else
06887 #endif
06888         //END JLFMOUSE
06889                         {       // Draw the desctext
06890                                 const char *textPtr = item->descText;
06891                                 if (*textPtr == '@')    // string reference
06892                                 {
06893                                         char    temp[MAX_STRING_CHARS];
06894                                         trap_SP_GetStringTextString( &textPtr[1]  , temp, sizeof(temp));
06895                                         textPtr = temp;
06896                                 }
06897 
06898                                 Item_TextColor(item, &color);
06899 
06900                                 {// stupid C language
06901                                         float fDescScale = parent->descScale ? parent->descScale : 1;
06902                                         float fDescScaleCopy = fDescScale;
06903                                         int iYadj = 0;
06904                                         while (1)
06905                                         {
06906                                                 textWidth = DC->textWidth(textPtr,fDescScale, FONT_SMALL2);
06907 
06908                                                 if (parent->descAlignment == ITEM_ALIGN_RIGHT)
06909                                                 {
06910                                                         xPos = parent->descX - textWidth;       // Right justify
06911                                                 }
06912                                                 else if (parent->descAlignment == ITEM_ALIGN_CENTER)
06913                                                 {
06914                                                         xPos = parent->descX - (textWidth/2);   // Center justify
06915                                                 }
06916                                                 else                                                                            // Left justify 
06917                                                 {
06918                                                         xPos = parent->descX;
06919                                                 }
06920 
06921                                                 if (parent->descAlignment == ITEM_ALIGN_CENTER)
06922                                                 {
06923                                                         // only this one will auto-shrink the scale until we eventually fit...
06924                                                         //
06925                                                         if (xPos + textWidth > (SCREEN_WIDTH-4)) {
06926                                                                 fDescScale -= 0.001f;
06927                                                                 continue;
06928                                                         }
06929                                                 }
06930 
06931                                                 // Try to adjust it's y placement if the scale has changed...
06932                                                 //
06933                                                 if (fDescScale != fDescScaleCopy)
06934                                                 {
06935                                                         int iOriginalTextHeight = DC->textHeight(textPtr, fDescScaleCopy, FONT_MEDIUM);
06936                                                         iYadj = iOriginalTextHeight - DC->textHeight(textPtr, fDescScale, FONT_MEDIUM);
06937                                                 }
06938 
06939                                                 DC->drawText(xPos, parent->descY + iYadj, fDescScale, parent->descColor, textPtr, 0, 0, item->textStyle, FONT_SMALL2);
06940                                                 break;
06941                                         }
06942                                 }
06943                         }
06944                 }
06945         }
06946 
06947   // paint the rect first.. 
06948   Window_Paint(&item->window, parent->fadeAmount , parent->fadeClamp, parent->fadeCycle);
06949 
06950   // Draw box to show rectangle extents, in debug mode
06951   if (debugMode) 
06952   {
06953         vec4_t color;
06954     color[1] = color[3] = 1;
06955     color[0] = color[2] = 0;
06956         DC->drawRect(
06957                 item->window.rect.x, 
06958                 item->window.rect.y, 
06959                 item->window.rect.w, 
06960                 item->window.rect.h, 
06961                 1, 
06962                 color);
06963   }
06964 
06965   //DC->drawRect(item->window.rect.x, item->window.rect.y, item->window.rect.w, item->window.rect.h, 1, red);
06966 
06967   switch (item->type) {
06968     case ITEM_TYPE_OWNERDRAW:
06969       Item_OwnerDraw_Paint(item);
06970       break;
06971     case ITEM_TYPE_TEXT:
06972     case ITEM_TYPE_BUTTON:
06973       Item_Text_Paint(item);
06974       break;
06975     case ITEM_TYPE_RADIOBUTTON:
06976       break;
06977     case ITEM_TYPE_CHECKBOX:
06978       break;
06979     case ITEM_TYPE_EDITFIELD:
06980     case ITEM_TYPE_NUMERICFIELD:
06981       Item_TextField_Paint(item);
06982       break;
06983     case ITEM_TYPE_COMBO:
06984       break;
06985     case ITEM_TYPE_LISTBOX:
06986       Item_ListBox_Paint(item);
06987       break;
06988         case ITEM_TYPE_TEXTSCROLL:
06989           Item_TextScroll_Paint ( item );
06990           break;
06991     //case ITEM_TYPE_IMAGE:
06992     //  Item_Image_Paint(item);
06993     //  break;
06994     case ITEM_TYPE_MODEL:
06995       Item_Model_Paint(item);
06996       break;
06997     case ITEM_TYPE_YESNO:
06998       Item_YesNo_Paint(item);
06999       break;
07000     case ITEM_TYPE_MULTI:
07001       Item_Multi_Paint(item);
07002       break;
07003     case ITEM_TYPE_BIND:
07004       Item_Bind_Paint(item);
07005       break;
07006     case ITEM_TYPE_SLIDER:
07007       Item_Slider_Paint(item);
07008       break;
07009     default:
07010       break;
07011   }
07012 
07013 }
07014 
07015 void Menu_Init(menuDef_t *menu) {
07016         memset(menu, 0, sizeof(menuDef_t));
07017         menu->cursorItem = -1;
07018         menu->fadeAmount = DC->Assets.fadeAmount;
07019         menu->fadeClamp = DC->Assets.fadeClamp;
07020         menu->fadeCycle = DC->Assets.fadeCycle;
07021         Window_Init(&menu->window);
07022 }
07023 
07024 itemDef_t *Menu_GetFocusedItem(menuDef_t *menu) {
07025   int i;
07026   if (menu) {
07027     for (i = 0; i < menu->itemCount; i++) {
07028       if (menu->items[i]->window.flags & WINDOW_HASFOCUS) {
07029         return menu->items[i];
07030       }
07031     }
07032   }
07033   return NULL;
07034 }
07035 
07036 menuDef_t *Menu_GetFocused() {
07037   int i;
07038   for (i = 0; i < menuCount; i++) {
07039     if (Menus[i].window.flags & WINDOW_HASFOCUS && Menus[i].window.flags & WINDOW_VISIBLE) {
07040       return &Menus[i];
07041     }
07042   }
07043   return NULL;
07044 }
07045 
07046 void Menu_ScrollFeeder(menuDef_t *menu, int feeder, qboolean down) {
07047         if (menu) {
07048                 int i;
07049     for (i = 0; i < menu->itemCount; i++) {
07050                         if (menu->items[i]->special == feeder) {
07051                                 Item_ListBox_HandleKey(menu->items[i], (down) ? A_CURSOR_DOWN : A_CURSOR_UP, qtrue, qtrue);
07052                                 return;
07053                         }
07054                 }
07055         }
07056 }
07057 
07058 
07059 
07060 void Menu_SetFeederSelection(menuDef_t *menu, int feeder, int index, const char *name) {
07061         if (menu == NULL) {
07062                 if (name == NULL) {
07063                         menu = Menu_GetFocused();
07064                 } else {
07065                         menu = Menus_FindByName(name);
07066                 }
07067         }
07068 
07069         if (menu) {
07070                 int i;
07071     for (i = 0; i < menu->itemCount; i++) {
07072                         if (menu->items[i]->special == feeder) {
07073                                 if (index == 0) {
07074                                         listBoxDef_t *listPtr = (listBoxDef_t*)menu->items[i]->typeData;
07075                                         listPtr->cursorPos = 0;
07076                                         listPtr->startPos = 0;
07077                                 }
07078                                 menu->items[i]->cursorPos = index;
07079                                 DC->feederSelection(menu->items[i]->special, menu->items[i]->cursorPos, NULL);
07080                                 return;
07081                         }
07082                 }
07083         }
07084 }
07085 
07086 qboolean Menus_AnyFullScreenVisible() {
07087   int i;
07088   for (i = 0; i < menuCount; i++) {
07089     if (Menus[i].window.flags & WINDOW_VISIBLE && Menus[i].fullScreen) {
07090                         return qtrue;
07091     }
07092   }
07093   return qfalse;
07094 }
07095 
07096 menuDef_t *Menus_ActivateByName(const char *p) {
07097   int i;
07098   menuDef_t *m = NULL;
07099         menuDef_t *focus = Menu_GetFocused();
07100   for (i = 0; i < menuCount; i++) {
07101     if (Q_stricmp(Menus[i].window.name, p) == 0) {
07102             m = &Menus[i];
07103                         Menus_Activate(m);
07104                         if (openMenuCount < MAX_OPEN_MENUS && focus != NULL) {
07105                                 menuStack[openMenuCount++] = focus;
07106                         }
07107     } else {
07108       Menus[i].window.flags &= ~WINDOW_HASFOCUS;
07109     }
07110   }
07111         Display_CloseCinematics();
07112 
07113         // Want to handle a mouse move on the new menu in case your already over an item
07114         Menu_HandleMouseMove ( m, DC->cursorx, DC->cursory );
07115 
07116         return m;
07117 }
07118 
07119 
07120 void Item_Init(itemDef_t *item) {
07121         memset(item, 0, sizeof(itemDef_t));
07122         item->textscale = 0.55f;
07123         Window_Init(&item->window);
07124 }
07125 
07126 void Menu_HandleMouseMove(menuDef_t *menu, float x, float y) {
07127 
07128         //JLFMOUSE  I THINK THIS JUST SETS THE FOCUS BASED ON THE MOUSE
07129 #ifdef _XBOX
07130         return ;
07131 #endif
07132         //END JLF
07133 
07134 
07135   int i, pass;
07136   qboolean focusSet = qfalse;
07137 
07138   itemDef_t *overItem;
07139   if (menu == NULL) {
07140     return;
07141   }
07142 
07143   if (!(menu->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
07144     return;
07145   }
07146 
07147         if (itemCapture) {
07148                 //Item_MouseMove(itemCapture, x, y);
07149                 return;
07150         }
07151 
07152         if (g_waitingForKey || g_editingField) {
07153                 return;
07154         }
07155 
07156   // FIXME: this is the whole issue of focus vs. mouse over.. 
07157   // need a better overall solution as i don't like going through everything twice
07158   for (pass = 0; pass < 2; pass++) {
07159     for (i = 0; i < menu->itemCount; i++) {
07160       // turn off focus each item
07161       // menu->items[i].window.flags &= ~WINDOW_HASFOCUS;
07162 
07163       if (!(menu->items[i]->window.flags & (WINDOW_VISIBLE | WINDOW_FORCED))) {
07164         continue;
07165       }
07166 
07167                         if (menu->items[i]->disabled) 
07168                         {
07169                                 continue;
07170                         }
07171 
07172                         // items can be enabled and disabled based on cvars
07173                         if (menu->items[i]->cvarFlags & (CVAR_ENABLE | CVAR_DISABLE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_ENABLE)) {
07174                                 continue;
07175                         }
07176 
07177                         if (menu->items[i]->cvarFlags & (CVAR_SHOW | CVAR_HIDE) && !Item_EnableShowViaCvar(menu->items[i], CVAR_SHOW)) {
07178                                 continue;
07179                         }
07180 
07181 
07182 
07183       if (Rect_ContainsPoint(&menu->items[i]->window.rect, x, y)) {
07184                                 if (pass == 1) {
07185                                         overItem = menu->items[i];
07186                                         if (overItem->type == ITEM_TYPE_TEXT && overItem->text) {
07187                                                 if (!Rect_ContainsPoint(&overItem->window.rect, x, y)) {
07188                                                         continue;
07189                                                 }
07190                                         }
07191                                         // if we are over an item
07192                                         if (IsVisible(overItem->window.flags)) {
07193                                                 // different one
07194                                                 Item_MouseEnter(overItem, x, y);
07195                                                 // Item_SetMouseOver(overItem, qtrue);
07196 
07197                                                 // if item is not a decoration see if it can take focus
07198                                                 if (!focusSet) {
07199                                                         focusSet = Item_SetFocus(overItem, x, y);
07200                                                 }
07201                                         }
07202                                 }
07203       } else if (menu->items[i]->window.flags & WINDOW_MOUSEOVER) {
07204           Item_MouseLeave(menu->items[i]);
07205           Item_SetMouseOver(menu->items[i], qfalse);
07206       }
07207     }
07208   }
07209 
07210 }
07211 
07212 void Menu_Paint(menuDef_t *menu, qboolean forcePaint) {
07213         int i;
07214 
07215         if (menu == NULL) {
07216                 return;
07217         }
07218 
07219         if (!(menu->window.flags & WINDOW_VISIBLE) &&  !forcePaint) {
07220                 return;
07221         }
07222 
07223         if (menu->window.ownerDrawFlags && DC->ownerDrawVisible && !DC->ownerDrawVisible(menu->window.ownerDrawFlags)) {
07224                 return;
07225         }
07226         
07227         if (forcePaint) {
07228                 menu->window.flags |= WINDOW_FORCED;
07229         }
07230 
07231         // draw the background if necessary
07232         if (menu->fullScreen) {
07233                 // implies a background shader
07234                 // FIXME: make sure we have a default shader if fullscreen is set with no background
07235                 DC->drawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, menu->window.background );
07236         } else if (menu->window.background) {
07237                 // this allows a background shader without being full screen
07238                 //UI_DrawHandlePic(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, menu->backgroundShader);
07239         }
07240 
07241         // paint the background and or border
07242         Window_Paint(&menu->window, menu->fadeAmount, menu->fadeClamp, menu->fadeCycle );
07243 
07244         // Loop through all items for the menu and paint them
07245         for (i = 0; i < menu->itemCount; i++) 
07246         {
07247                 if (!menu->items[i]->appearanceSlot)
07248                 {
07249                         Item_Paint(menu->items[i]);
07250                 }
07251                 else // Timed order of appearance
07252                 {
07253                         if (menu->appearanceTime < DC->realTime)        // Time to show another item
07254                         {
07255                                 menu->appearanceTime = DC->realTime + menu->appearanceIncrement;
07256                                 menu->appearanceCnt++;
07257                         }
07258 
07259                         if (menu->items[i]->appearanceSlot<=menu->appearanceCnt)
07260                         {
07261                                 Item_Paint(menu->items[i]);
07262                         }
07263                 }
07264         }
07265 
07266         if (debugMode) {
07267                 vec4_t color;
07268                 color[0] = color[2] = color[3] = 1;
07269                 color[1] = 0;
07270                 DC->drawRect(menu->window.rect.x, menu->window.rect.y, menu->window.rect.w, menu->window.rect.h, 1, color);
07271         }
07272 }
07273 
07274 /*
07275 ===============
07276 Item_ValidateTypeData
07277 ===============
07278 */
07279 void Item_ValidateTypeData(itemDef_t *item) 
07280 {
07281         if (item->typeData) 
07282         {
07283                 return;
07284         }
07285 
07286         if (item->type == ITEM_TYPE_LISTBOX) 
07287         {
07288                 item->typeData = UI_Alloc(sizeof(listBoxDef_t));
07289                 memset(item->typeData, 0, sizeof(listBoxDef_t));
07290         }
07291         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) 
07292         {
07293                 item->typeData = UI_Alloc(sizeof(editFieldDef_t));
07294                 memset(item->typeData, 0, sizeof(editFieldDef_t));
07295                 if (item->type == ITEM_TYPE_EDITFIELD) 
07296                 {
07297                         if (!((editFieldDef_t *) item->typeData)->maxPaintChars) 
07298                         {
07299                                 ((editFieldDef_t *) item->typeData)->maxPaintChars = MAX_EDITFIELD;
07300                         }
07301                 }
07302         } 
07303         else if (item->type == ITEM_TYPE_MULTI) 
07304         {
07305                 item->typeData = UI_Alloc(sizeof(multiDef_t));
07306         } 
07307         else if (item->type == ITEM_TYPE_MODEL) 
07308         {
07309                 item->typeData = UI_Alloc(sizeof(modelDef_t));
07310                 memset(item->typeData, 0, sizeof(modelDef_t));
07311         }
07312         else if (item->type == ITEM_TYPE_TEXTSCROLL )
07313         {
07314                 item->typeData = UI_Alloc(sizeof(textScrollDef_t));
07315         }
07316 }
07317 
07318 /*
07319 ===============
07320 Keyword Hash
07321 ===============
07322 */
07323 
07324 #define KEYWORDHASH_SIZE        512
07325 
07326 typedef struct keywordHash_s
07327 {
07328         char *keyword;
07329         qboolean (*func)(itemDef_t *item, int handle);
07330         struct keywordHash_s *next;
07331 } keywordHash_t;
07332 
07333 int KeywordHash_Key(char *keyword) {
07334         int register hash, i;
07335 
07336         hash = 0;
07337         for (i = 0; keyword[i] != '\0'; i++) {
07338                 if (keyword[i] >= 'A' && keyword[i] <= 'Z')
07339                         hash += (keyword[i] + ('a' - 'A')) * (119 + i);
07340                 else
07341                         hash += keyword[i] * (119 + i);
07342         }
07343         hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (KEYWORDHASH_SIZE-1);
07344         return hash;
07345 }
07346 
07347 void KeywordHash_Add(keywordHash_t *table[], keywordHash_t *key) {
07348         int hash;
07349 
07350         hash = KeywordHash_Key(key->keyword);
07351 /*
07352         if (table[hash]) {
07353                 int collision = qtrue;
07354         }
07355 */
07356         key->next = table[hash];
07357         table[hash] = key;
07358 }
07359 
07360 keywordHash_t *KeywordHash_Find(keywordHash_t *table[], char *keyword)
07361 {
07362         keywordHash_t *key;
07363         int hash;
07364 
07365         hash = KeywordHash_Key(keyword);
07366         for (key = table[hash]; key; key = key->next) {
07367                 if (!Q_stricmp(key->keyword, keyword))
07368                         return key;
07369         }
07370         return NULL;
07371 }
07372 
07373 /*
07374 ===============
07375 Item Keyword Parse functions
07376 ===============
07377 */
07378 
07379 // name <string>
07380 qboolean ItemParse_name( itemDef_t *item, int handle ) {
07381         if (!PC_String_Parse(handle, &item->window.name)) {
07382                 return qfalse;
07383         }
07384         return qtrue;
07385 }
07386 
07387 // name <string>
07388 qboolean ItemParse_focusSound( itemDef_t *item, int handle ) {
07389         pc_token_t token;
07390         if (!trap_PC_ReadToken(handle, &token)) {
07391                 return qfalse;
07392         }
07393         item->focusSound = DC->registerSound(token.string);
07394         return qtrue;
07395 }
07396 
07397 
07398 // text <string>
07399 qboolean ItemParse_text( itemDef_t *item, int handle ) {
07400         if (!PC_String_Parse(handle, &item->text)) {
07401                 return qfalse;
07402         }
07403         return qtrue;
07404 }
07405 
07406 /*
07407 ===============
07408 ItemParse_descText 
07409         text <string>
07410 ===============
07411 */
07412 qboolean ItemParse_descText( itemDef_t *item, int handle) 
07413 {
07414 
07415         if (!PC_String_Parse(handle, &item->descText))
07416         {
07417                 return qfalse;
07418         }
07419 
07420         return qtrue;
07421 
07422 }
07423 
07424 
07425 /*
07426 ===============
07427 ItemParse_text 
07428         text <string>
07429 ===============
07430 */
07431 qboolean ItemParse_text2( itemDef_t *item, int handle) 
07432 {
07433 
07434         if (!PC_String_Parse(handle, &item->text2))
07435         {
07436                 return qfalse;
07437         }
07438 
07439         return qtrue;
07440 
07441 }
07442 
07443 /*
07444 ===============
07445 ItemParse_text2alignx 
07446 ===============
07447 */
07448 qboolean ItemParse_text2alignx( itemDef_t *item, int handle) 
07449 {
07450         if (!PC_Float_Parse(handle, &item->text2alignx)) 
07451         {
07452                 return qfalse;
07453         }
07454         return qtrue;
07455 }
07456 
07457 /*
07458 ===============
07459 ItemParse_text2aligny 
07460 ===============
07461 */
07462 qboolean ItemParse_text2aligny( itemDef_t *item, int handle) 
07463 {
07464         if (!PC_Float_Parse(handle, &item->text2aligny)) 
07465         {
07466                 return qfalse;
07467         }
07468         return qtrue;
07469 }
07470 
07471 // group <string>
07472 qboolean ItemParse_group( itemDef_t *item, int handle ) {
07473         if (!PC_String_Parse(handle, &item->window.group)) {
07474                 return qfalse;
07475         }
07476         return qtrue;
07477 }
07478 
07479 typedef struct uiG2PtrTracker_s uiG2PtrTracker_t;
07480 
07481 struct uiG2PtrTracker_s
07482 {
07483         void *ghoul2;
07484         uiG2PtrTracker_t *next;
07485 };
07486 
07487 uiG2PtrTracker_t *ui_G2PtrTracker = NULL;
07488 
07489 //rww - UI G2 shared management functions.
07490 
07491 //Insert the pointer into our chain so we can keep track of it for freeing.
07492 void UI_InsertG2Pointer(void *ghoul2)
07493 {
07494         uiG2PtrTracker_t **nextFree = &ui_G2PtrTracker;
07495 
07496         while ((*nextFree) && (*nextFree)->ghoul2)
07497         { //check if it has a ghoul2, if not we can reuse it.
07498                 nextFree = &((*nextFree)->next);
07499         }
07500 
07501         if (!nextFree)
07502         { //shouldn't happen
07503                 assert(0);
07504                 return;
07505         }
07506 
07507         if (!(*nextFree))
07508         { //if we aren't reusing a chain then allocate space for it.
07509                 (*nextFree) = (uiG2PtrTracker_t *)BG_Alloc(sizeof(uiG2PtrTracker_t));
07510                 (*nextFree)->next = NULL;
07511         }
07512 
07513         (*nextFree)->ghoul2 = ghoul2;
07514 }
07515 
07516 //Remove a ghoul2 pointer from the chain if it's there.
07517 void UI_ClearG2Pointer(void *ghoul2)
07518 {
07519         uiG2PtrTracker_t *next = ui_G2PtrTracker;
07520 
07521         if (!ghoul2)
07522         {
07523                 return;
07524         }
07525 
07526         while (next)
07527         {
07528                 if (next->ghoul2 == ghoul2)
07529                 { //found it, set it to null so we can reuse this link.
07530                         next->ghoul2 = NULL;
07531                         break;
07532                 }
07533 
07534                 next = next->next;
07535         }
07536 }
07537 
07538 //Called on shutdown, cleans up all the ghoul2 instances laying around.
07539 void UI_CleanupGhoul2(void)
07540 {
07541         uiG2PtrTracker_t *next = ui_G2PtrTracker;
07542 
07543         while (next)
07544         {
07545                 if (next->ghoul2 && trap_G2_HaveWeGhoul2Models(next->ghoul2))
07546                 { //found a g2 instance, clean it.
07547                         trap_G2API_CleanGhoul2Models(&next->ghoul2);
07548                 }
07549 
07550                 next = next->next;
07551         }
07552 
07553 #ifdef _XBOX
07554         ui_G2PtrTracker = NULL;
07555 #endif
07556 }
07557 
07558 // asset_model <string>
07559 int UI_ParseAnimationFile(const char *filename, animation_t *animset, qboolean isHumanoid);
07560 
07561 /*
07562 ===============
07563 ItemParse_asset_model 
07564         asset_model <string>
07565 ===============
07566 */
07567 qboolean ItemParse_asset_model_go( itemDef_t *item, const char *name,int *runTimeLength ) 
07568 {
07569 #ifndef CGAME
07570         int g2Model;
07571         modelDef_t *modelPtr;
07572         Item_ValidateTypeData(item);
07573         modelPtr = (modelDef_t*)item->typeData;
07574         *runTimeLength =0.0f;
07575 
07576         if (!Q_stricmp(&name[strlen(name) - 4], ".glm"))
07577         { //it's a ghoul2 model then
07578                 if ( item->ghoul2 )
07579                 {
07580                         UI_ClearG2Pointer(item->ghoul2);        //remove from tracking list
07581                         trap_G2API_CleanGhoul2Models(&item->ghoul2);    //remove ghoul info
07582                         item->flags &= ~ITF_G2VALID;
07583                 }
07584 
07585                 g2Model = trap_G2API_InitGhoul2Model(&item->ghoul2, name, 0, modelPtr->g2skin, 0, 0, 0);
07586                 if (g2Model >= 0)
07587                 {
07588                         UI_InsertG2Pointer(item->ghoul2); //remember it so we can free it when the ui shuts down.
07589                         item->flags |= ITF_G2VALID;
07590 
07591                         if (modelPtr->g2anim)
07592                         { //does the menu request this model be playing an animation?
07593 //                                      DC->g2hilev_SetAnim(&item->ghoul2[0], "model_root", modelPtr->g2anim);
07594 
07595                                 char GLAName[MAX_QPATH];        
07596 
07597                                 GLAName[0] = 0;
07598                                 trap_G2API_GetGLAName(item->ghoul2, 0, GLAName);
07599 
07600                                 if (GLAName[0])
07601                                 {
07602                                         int animIndex;
07603                                         char *slash;
07604 
07605                                         slash = Q_strrchr( GLAName, '/' );
07606 
07607                                         if ( slash )
07608                                         { //If this isn't true the gla path must be messed up somehow.
07609                                                 strcpy(slash, "/animation.cfg");
07610                                         
07611                                                 animIndex = UI_ParseAnimationFile(GLAName, NULL, qfalse);
07612                                                 if (animIndex != -1)
07613                                                 { //We parsed out the animation info for whatever model this is
07614                                                         animation_t *anim = &bgAllAnims[animIndex].anims[modelPtr->g2anim];
07615 
07616                                                         int sFrame = anim->firstFrame;
07617                                                         int eFrame = anim->firstFrame + anim->numFrames;
07618                                                         int flags = BONE_ANIM_OVERRIDE_FREEZE;
07619                                                         int time = DC->realTime;
07620                                                         float animSpeed = 50.0f / anim->frameLerp;
07621                                                         int blendTime = 150;
07622 
07623                                                         if (anim->loopFrames != -1)
07624                                                         {
07625                                                                 flags |= BONE_ANIM_OVERRIDE_LOOP;
07626                                                         }
07627 
07628                                                         trap_G2API_SetBoneAnim(item->ghoul2, 0, "model_root", sFrame, eFrame, flags, animSpeed, time, -1, blendTime);
07629                                                         *runTimeLength =((anim->frameLerp * (anim->numFrames-2)));                                      
07630                                                 }
07631                                         }
07632                                 } 
07633                         }
07634 
07635                         if ( modelPtr->g2skin )
07636                         {
07637 //                                      DC->g2_SetSkin( &item->ghoul2[0], 0, modelPtr->g2skin );//this is going to set the surfs on/off matching the skin file
07638                                 //trap_G2API_InitGhoul2Model(&item->ghoul2, name, 0, modelPtr->g2skin, 0, 0, 0);
07639                                 //ahh, what are you doing?!
07640                                 trap_G2API_SetSkin(item->ghoul2, 0, modelPtr->g2skin, modelPtr->g2skin);
07641                         }
07642                 }
07643                 /*
07644                 else
07645                 {
07646                         Com_Error(ERR_FATAL, "%s does not exist.", name);
07647                 }
07648                 */
07649         }
07650         else if(!(item->asset)) 
07651         { //guess it's just an md3
07652                 item->asset = DC->registerModel(name);
07653                 item->flags &= ~ITF_G2VALID;
07654         }
07655 #endif
07656         return qtrue;
07657 }
07658 
07659 qboolean ItemParse_asset_model( itemDef_t *item, int handle ) {
07660         const char *temp;
07661         modelDef_t *modelPtr;
07662         int animRunLength;
07663         pc_token_t token;
07664 
07665         Item_ValidateTypeData(item);
07666         modelPtr = (modelDef_t*)item->typeData;
07667 
07668         if (!trap_PC_ReadToken(handle, &token)) {
07669                 return qfalse;
07670         }
07671         temp = token.string;
07672 
07673 #ifndef CGAME
07674         if (!stricmp(token.string,"ui_char_model") )
07675         {
07676                 char modelPath[MAX_QPATH];
07677                 char ui_char_model[MAX_QPATH];
07678                 trap_Cvar_VariableStringBuffer("ui_char_model", ui_char_model, sizeof(ui_char_model) );
07679                 Com_sprintf( modelPath, sizeof( modelPath ), "models/players/%s/model.glm", ui_char_model );
07680                 temp = modelPath;
07681         }
07682 #endif
07683         return (ItemParse_asset_model_go( item, temp, &animRunLength ));
07684 }
07685 
07686 // asset_shader <string>
07687 qboolean ItemParse_asset_shader( itemDef_t *item, int handle ) {
07688         pc_token_t token;
07689         if (!trap_PC_ReadToken(handle, &token)) {
07690                 return qfalse;
07691         }
07692         item->asset = DC->registerShaderNoMip(token.string);
07693         return qtrue;
07694 }
07695 
07696 // model_origin <number> <number> <number>
07697 qboolean ItemParse_model_origin( itemDef_t *item, int handle ) {
07698         modelDef_t *modelPtr;
07699         Item_ValidateTypeData(item);
07700         modelPtr = (modelDef_t*)item->typeData;
07701 
07702         if (PC_Float_Parse(handle, &modelPtr->origin[0])) {
07703                 if (PC_Float_Parse(handle, &modelPtr->origin[1])) {
07704                         if (PC_Float_Parse(handle, &modelPtr->origin[2])) {
07705                                 return qtrue;
07706                         }
07707                 }
07708         }
07709         return qfalse;
07710 }
07711 
07712 // model_fovx <number>
07713 qboolean ItemParse_model_fovx( itemDef_t *item, int handle ) {
07714         modelDef_t *modelPtr;
07715         Item_ValidateTypeData(item);
07716         modelPtr = (modelDef_t*)item->typeData;
07717 
07718         if (!PC_Float_Parse(handle, &modelPtr->fov_x)) {
07719                 return qfalse;
07720         }
07721         return qtrue;
07722 }
07723 
07724 // model_fovy <number>
07725 qboolean ItemParse_model_fovy( itemDef_t *item, int handle ) {
07726         modelDef_t *modelPtr;
07727         Item_ValidateTypeData(item);
07728         modelPtr = (modelDef_t*)item->typeData;
07729 
07730         if (!PC_Float_Parse(handle, &modelPtr->fov_y)) {
07731                 return qfalse;
07732         }
07733         return qtrue;
07734 }
07735 
07736 // model_rotation <integer>
07737 qboolean ItemParse_model_rotation( itemDef_t *item, int handle ) {
07738         modelDef_t *modelPtr;
07739         Item_ValidateTypeData(item);
07740         modelPtr = (modelDef_t*)item->typeData;
07741 
07742         if (!PC_Int_Parse(handle, &modelPtr->rotationSpeed)) {
07743                 return qfalse;
07744         }
07745         return qtrue;
07746 }
07747 
07748 // model_angle <integer>
07749 qboolean ItemParse_model_angle( itemDef_t *item, int handle ) {
07750         modelDef_t *modelPtr;
07751         Item_ValidateTypeData(item);
07752         modelPtr = (modelDef_t*)item->typeData;
07753 
07754         if (!PC_Int_Parse(handle, &modelPtr->angle)) {
07755                 return qfalse;
07756         }
07757         return qtrue;
07758 }
07759 
07760 // model_g2mins <number> <number> <number>
07761 qboolean ItemParse_model_g2mins( itemDef_t *item, int handle ) {
07762         modelDef_t *modelPtr;
07763         Item_ValidateTypeData(item);
07764         modelPtr = (modelDef_t*)item->typeData;
07765 
07766         if (PC_Float_Parse(handle, &modelPtr->g2mins[0])) {
07767                 if (PC_Float_Parse(handle, &modelPtr->g2mins[1])) {
07768                         if (PC_Float_Parse(handle, &modelPtr->g2mins[2])) {
07769                                 return qtrue;
07770                         }
07771                 }
07772         }
07773         return qfalse;
07774 }
07775 
07776 // model_g2maxs <number> <number> <number>
07777 qboolean ItemParse_model_g2maxs( itemDef_t *item, int handle ) {
07778         modelDef_t *modelPtr;
07779         Item_ValidateTypeData(item);
07780         modelPtr = (modelDef_t*)item->typeData;
07781 
07782         if (PC_Float_Parse(handle, &modelPtr->g2maxs[0])) {
07783                 if (PC_Float_Parse(handle, &modelPtr->g2maxs[1])) {
07784                         if (PC_Float_Parse(handle, &modelPtr->g2maxs[2])) {
07785                                 return qtrue;
07786                         }
07787                 }
07788         }
07789         return qfalse;
07790 }
07791 
07792 // model_g2scale <number> <number> <number>
07793 qboolean ItemParse_model_g2scale( itemDef_t *item, int handle ) {
07794         modelDef_t *modelPtr;
07795         Item_ValidateTypeData(item);
07796         modelPtr = (modelDef_t*)item->typeData;
07797 
07798         if (PC_Float_Parse(handle, &modelPtr->g2scale[0])) {
07799                 if (PC_Float_Parse(handle, &modelPtr->g2scale[1])) {
07800                         if (PC_Float_Parse(handle, &modelPtr->g2scale[2])) {
07801                                 return qtrue;
07802                         }
07803                 }
07804         }
07805         return qfalse;
07806 }
07807 
07808 // model_g2skin <string>
07809 qhandle_t trap_R_RegisterSkin( const char *name );
07810 
07811 qboolean ItemParse_model_g2skin( itemDef_t *item, int handle ) {
07812         modelDef_t *modelPtr;
07813         pc_token_t token;
07814 
07815         Item_ValidateTypeData(item);
07816         modelPtr = (modelDef_t*)item->typeData;
07817 
07818         if (!trap_PC_ReadToken(handle, &token)) {
07819                 return qfalse;
07820         }
07821 
07822         if (!token.string[0])
07823         { //it was parsed correctly so still return true.
07824                 return qtrue;
07825         }
07826 
07827         modelPtr->g2skin = trap_R_RegisterSkin(token.string);
07828 
07829         return qtrue;
07830 }
07831 
07832 // model_g2anim <number>
07833 qboolean ItemParse_model_g2anim( itemDef_t *item, int handle ) {
07834         modelDef_t *modelPtr;
07835         pc_token_t token;
07836         int i = 0;
07837 
07838         Item_ValidateTypeData(item);
07839         modelPtr = (modelDef_t*)item->typeData;
07840 
07841         if (!trap_PC_ReadToken(handle, &token)) {
07842                 return qfalse;
07843         }
07844 
07845         if ( !token.string[0])
07846         { //it was parsed correctly so still return true.
07847                 return qtrue;
07848         }
07849 
07850         while (i < MAX_ANIMATIONS)
07851         {
07852                 if (!Q_stricmp(token.string, animTable[i].name))
07853                 { //found it
07854                         modelPtr->g2anim = i;
07855                         return qtrue;
07856                 }
07857                 i++;
07858         }
07859 
07860         Com_Printf("Could not find '%s' in the anim table\n", token.string);
07861         return qtrue;
07862 }
07863 
07864 // model_g2skin <string>
07865 qboolean ItemParse_model_g2skin_go( itemDef_t *item, const char *skinName ) 
07866 {
07867 
07868         modelDef_t *modelPtr;
07869         int defSkin;
07870 
07871 
07872         Item_ValidateTypeData(item);
07873         modelPtr = (modelDef_t*)item->typeData;
07874 
07875         if (!skinName || !skinName[0])
07876         { //it was parsed correctly so still return true.
07877                 modelPtr->g2skin = 0;
07878                 trap_G2API_SetSkin(item->ghoul2, 0, 0, 0);
07879 
07880                 return qtrue;
07881         }
07882 
07883         // set skin
07884         if ( item->ghoul2 )
07885         {
07886                 defSkin = trap_R_RegisterSkin(skinName);
07887                 trap_G2API_SetSkin(item->ghoul2, 0, defSkin, defSkin);
07888         }
07889 
07890         return qtrue;
07891 }
07892 
07893 // model_g2anim <number>
07894 qboolean ItemParse_model_g2anim_go( itemDef_t *item, const char *animName ) 
07895 {
07896         modelDef_t *modelPtr;
07897         int i = 0;
07898 
07899         Item_ValidateTypeData(item);
07900         modelPtr = (modelDef_t*)item->typeData;
07901 
07902         if (!animName || !animName[0])
07903         { //it was parsed correctly so still return true.
07904                 return qtrue;
07905         }
07906 
07907         while (i < MAX_ANIMATIONS)
07908         {
07909                 if (!Q_stricmp(animName, animTable[i].name))
07910                 { //found it
07911                         modelPtr->g2anim = animTable[i].id;
07912                         return qtrue;
07913                 }
07914                 i++;
07915         }
07916 
07917         Com_Printf("Could not find '%s' in the anim table\n", animName);
07918         return qtrue;
07919 }
07920 
07921 // Get the cvar, get the values and stuff them in the rect structure.
07922 qboolean ItemParse_rectcvar( itemDef_t *item, int handle ) 
07923 {
07924         char    cvarBuf[1024];
07925         const char      *holdVal;
07926         char    *holdBuf;
07927 
07928         // get Cvar name
07929         pc_token_t token;
07930         if (!trap_PC_ReadToken(handle, &token))
07931         {
07932                 return qfalse;
07933         }
07934 
07935         // get cvar data
07936         DC->getCVarString(token.string, cvarBuf, sizeof(cvarBuf));
07937         
07938         holdBuf = cvarBuf;
07939         if (String_Parse(&holdBuf,&holdVal))
07940         {
07941                 item->window.rectClient.x = atof(holdVal);
07942                 if (String_Parse(&holdBuf,&holdVal))
07943                 {
07944                         item->window.rectClient.y = atof(holdVal);
07945                         if (String_Parse(&holdBuf,&holdVal))
07946                         {
07947                                 item->window.rectClient.w = atof(holdVal);
07948                                 if (String_Parse(&holdBuf,&holdVal))
07949                                 {
07950                                         item->window.rectClient.h = atof(holdVal);
07951                                         return qtrue;
07952                                 }
07953                         }
07954                 }
07955         }
07956 
07957         // There may be no cvar built for this, and that's okay. . . I guess.
07958         return qtrue;
07959 }
07960 
07961 // rect <rectangle>
07962 qboolean ItemParse_rect( itemDef_t *item, int handle ) {
07963         if (!PC_Rect_Parse(handle, &item->window.rectClient)) {
07964                 return qfalse;
07965         }
07966         return qtrue;
07967 }
07968 
07969 /*
07970 ===============
07971 ItemParse_flag
07972         style <integer>
07973 ===============
07974 */
07975 qboolean ItemParse_flag( itemDef_t *item, int handle) 
07976 {
07977         int             i;
07978         pc_token_t token;
07979 
07980         if (!trap_PC_ReadToken(handle, &token))
07981         {
07982                 return qfalse;
07983         }
07984 
07985         i=0;
07986         while (styles[i])
07987         {
07988                 if (Q_stricmp(token.string,itemFlags[i].string)==0)
07989                 {
07990                         item->window.flags |= itemFlags[i].value;
07991                         break;
07992                 }
07993                 i++;
07994         }
07995 
07996         if (itemFlags[i].string == NULL)
07997         {
07998                 Com_Printf(va( S_COLOR_YELLOW "Unknown item style value '%s'",token.string));
07999         }
08000 
08001         return qtrue;
08002 }
08003 
08004 /*
08005 ===============
08006 ItemParse_style 
08007         style <integer>
08008 ===============
08009 */
08010 qboolean ItemParse_style( itemDef_t *item, int handle) 
08011 {
08012         if (!PC_Int_Parse(handle, &item->window.style))
08013         {
08014                 Com_Printf(S_COLOR_YELLOW "Unknown item style value");
08015                 return qfalse;
08016         }
08017 
08018         return qtrue;
08019 }
08020 
08021 
08022 // decoration
08023 qboolean ItemParse_decoration( itemDef_t *item, int handle ) {
08024         item->window.flags |= WINDOW_DECORATION;
08025         return qtrue;
08026 }
08027 
08028 // notselectable
08029 qboolean ItemParse_notselectable( itemDef_t *item, int handle ) {
08030         listBoxDef_t *listPtr;
08031         Item_ValidateTypeData(item);
08032         listPtr = (listBoxDef_t*)item->typeData;
08033         if (item->type == ITEM_TYPE_LISTBOX && listPtr) {
08034                 listPtr->notselectable = qtrue;
08035         }
08036         return qtrue;
08037 }
08038 
08039 /*
08040 ===============
08041 ItemParse_scrollhidden
08042         scrollhidden
08043 ===============
08044 */
08045 qboolean ItemParse_scrollhidden( itemDef_t *item , int handle) 
08046 {
08047         listBoxDef_t *listPtr;
08048         Item_ValidateTypeData(item);
08049         listPtr = (listBoxDef_t*)item->typeData;
08050 
08051         if (item->type == ITEM_TYPE_LISTBOX && listPtr) 
08052         {
08053                 listPtr->scrollhidden = qtrue;
08054         }
08055         return qtrue;
08056 }
08057 
08058 
08059 
08060 
08061 
08062 // manually wrapped
08063 qboolean ItemParse_wrapped( itemDef_t *item, int handle ) {
08064         item->window.flags |= WINDOW_WRAPPED;
08065         return qtrue;
08066 }
08067 
08068 // auto wrapped
08069 qboolean ItemParse_autowrapped( itemDef_t *item, int handle ) {
08070         item->window.flags |= WINDOW_AUTOWRAPPED;
08071         return qtrue;
08072 }
08073 
08074 
08075 // horizontalscroll
08076 qboolean ItemParse_horizontalscroll( itemDef_t *item, int handle ) {
08077         item->window.flags |= WINDOW_HORIZONTAL;
08078         return qtrue;
08079 }
08080 
08081 /*
08082 ===============
08083 ItemParse_type 
08084         type <integer>
08085 ===============
08086 */
08087 qboolean ItemParse_type( itemDef_t *item, int handle  ) 
08088 {
08089 //      int             i,holdInt;
08090 
08091         if (!PC_Int_Parse(handle, &item->type)) 
08092         {
08093                 return qfalse;
08094         }
08095         Item_ValidateTypeData(item);
08096         return qtrue;
08097 }
08098 
08099 // elementwidth, used for listbox image elements
08100 // uses textalignx for storage
08101 qboolean ItemParse_elementwidth( itemDef_t *item, int handle ) {
08102         listBoxDef_t *listPtr;
08103 
08104         Item_ValidateTypeData(item);
08105         listPtr = (listBoxDef_t*)item->typeData;
08106         if (!PC_Float_Parse(handle, &listPtr->elementWidth)) {
08107                 return qfalse;
08108         }
08109         return qtrue;
08110 }
08111 
08112 // elementheight, used for listbox image elements
08113 // uses textaligny for storage
08114 qboolean ItemParse_elementheight( itemDef_t *item, int handle ) {
08115         listBoxDef_t *listPtr;
08116 
08117         Item_ValidateTypeData(item);
08118         listPtr = (listBoxDef_t*)item->typeData;
08119         if (!PC_Float_Parse(handle, &listPtr->elementHeight)) {
08120                 return qfalse;
08121         }
08122         return qtrue;
08123 }
08124 
08125 // feeder <float>
08126 qboolean ItemParse_feeder( itemDef_t *item, int handle ) {
08127         if (!PC_Float_Parse(handle, &item->special)) {
08128                 return qfalse;
08129         }
08130         return qtrue;
08131 }
08132 
08133 // elementtype, used to specify what type of elements a listbox contains
08134 // uses textstyle for storage
08135 qboolean ItemParse_elementtype( itemDef_t *item, int handle ) {
08136         listBoxDef_t *listPtr;
08137 
08138         Item_ValidateTypeData(item);
08139         if (!item->typeData)
08140                 return qfalse;
08141         listPtr = (listBoxDef_t*)item->typeData;
08142         if (!PC_Int_Parse(handle, &listPtr->elementStyle)) {
08143                 return qfalse;
08144         }
08145         return qtrue;
08146 }
08147 
08148 // columns sets a number of columns and an x pos and width per.. 
08149 qboolean ItemParse_columns( itemDef_t *item, int handle ) {
08150         int num, i;
08151         listBoxDef_t *listPtr;
08152 
08153         Item_ValidateTypeData(item);
08154         if (!item->typeData)
08155                 return qfalse;
08156         listPtr = (listBoxDef_t*)item->typeData;
08157         if (PC_Int_Parse(handle, &num)) {
08158                 if (num > MAX_LB_COLUMNS) {
08159                         num = MAX_LB_COLUMNS;
08160                 }
08161                 listPtr->numColumns = num;
08162                 for (i = 0; i < num; i++) {
08163                         int pos, width, maxChars;
08164 
08165                         if (PC_Int_Parse(handle, &pos) && PC_Int_Parse(handle, &width) && PC_Int_Parse(handle, &maxChars)) {
08166                                 listPtr->columnInfo[i].pos = pos;
08167                                 listPtr->columnInfo[i].width = width;
08168                                 listPtr->columnInfo[i].maxChars = maxChars;
08169                         } else {
08170                                 return qfalse;
08171                         }
08172                 }
08173         } else {
08174                 return qfalse;
08175         }
08176         return qtrue;
08177 }
08178 
08179 qboolean ItemParse_border( itemDef_t *item, int handle ) {
08180         if (!PC_Int_Parse(handle, &item->window.border)) {
08181                 return qfalse;
08182         }
08183         return qtrue;
08184 }
08185 
08186 qboolean ItemParse_bordersize( itemDef_t *item, int handle ) {
08187         if (!PC_Float_Parse(handle, &item->window.borderSize)) {
08188                 return qfalse;
08189         }
08190         return qtrue;
08191 }
08192 
08193 qboolean ItemParse_visible( itemDef_t *item, int handle ) {
08194         int i;
08195 
08196         if (!PC_Int_Parse(handle, &i)) {
08197                 return qfalse;
08198         }
08199         if (i) {
08200                 item->window.flags |= WINDOW_VISIBLE;
08201         }
08202         return qtrue;
08203 }
08204 
08205 qboolean ItemParse_ownerdraw( itemDef_t *item, int handle ) {
08206         if (!PC_Int_Parse(handle, &item->window.ownerDraw)) {
08207                 return qfalse;
08208         }
08209         item->type = ITEM_TYPE_OWNERDRAW;
08210         return qtrue;
08211 }
08212 
08213 qboolean ItemParse_align( itemDef_t *item, int handle ) {
08214         if (!PC_Int_Parse(handle, &item->alignment)) {
08215                 return qfalse;
08216         }
08217         return qtrue;
08218 }
08219 
08220 /*
08221 ===============
08222 ItemParse_isCharacter 
08223 
08224 Sets item flag showing this is a character
08225 ===============
08226 */
08227 qboolean ItemParse_isCharacter( itemDef_t *item, int handle  )
08228 {
08229         int flag;
08230 
08231         if (PC_Int_Parse(handle, &flag)) 
08232         {
08233                 if ( flag )
08234                 {
08235                         item->flags |= ITF_ISCHARACTER;
08236                 }
08237                 else
08238                 {
08239                         item->flags &= ~ITF_ISCHARACTER;
08240                 }
08241                 return qtrue;
08242         }
08243         return qfalse;
08244 }
08245 
08246 
08247 /*
08248 ===============
08249 ItemParse_textalign 
08250 ===============
08251 */
08252 qboolean ItemParse_textalign( itemDef_t *item, int handle ) 
08253 {
08254         if (!PC_Int_Parse(handle, &item->textalignment)) 
08255         {
08256                 Com_Printf(S_COLOR_YELLOW "Unknown text alignment value");
08257         
08258                 return qfalse;
08259         }
08260 
08261         return qtrue;
08262 }
08263 
08264 qboolean ItemParse_textalignx( itemDef_t *item, int handle ) {
08265         if (!PC_Float_Parse(handle, &item->textalignx)) {
08266                 return qfalse;
08267         }
08268         return qtrue;
08269 }
08270 
08271 qboolean ItemParse_textaligny( itemDef_t *item, int handle ) {
08272         if (!PC_Float_Parse(handle, &item->textaligny)) {
08273                 return qfalse;
08274         }
08275         return qtrue;
08276 }
08277 
08278 qboolean ItemParse_textscale( itemDef_t *item, int handle ) {
08279         if (!PC_Float_Parse(handle, &item->textscale)) {
08280                 return qfalse;
08281         }
08282         return qtrue;
08283 }
08284 
08285 qboolean ItemParse_textstyle( itemDef_t *item, int handle ) {
08286         if (!PC_Int_Parse(handle, &item->textStyle)) {
08287                 return qfalse;
08288         }
08289         return qtrue;
08290 }
08291 
08292 /*
08293 ===============
08294 ItemParse_invertyesno
08295 ===============
08296 */
08297 //JLFYESNO MPMOVED
08298 qboolean ItemParse_invertyesno( itemDef_t *item, int handle) 
08299 {
08300         if (!PC_Int_Parse(handle, &item->invertYesNo)) 
08301         {
08302                 return qfalse;
08303         }
08304         return qtrue;
08305 }
08306 
08307 /*
08308 ===============
08309 ItemParse_xoffset (used for yes/no and multi)
08310 ===============
08311 */
08312 qboolean ItemParse_xoffset( itemDef_t *item, int handle) 
08313 {
08314         if (PC_Int_Parse(handle, &item->xoffset)) 
08315         {
08316                 return qfalse;
08317         }
08318         return qtrue;
08319 }
08320 
08321 
08322 qboolean ItemParse_backcolor( itemDef_t *item, int handle ) {
08323         int i;
08324         float f;
08325 
08326         for (i = 0; i < 4; i++) {
08327                 if (!PC_Float_Parse(handle, &f)) {
08328                         return qfalse;
08329                 }
08330                 item->window.backColor[i]  = f;
08331         }
08332         return qtrue;
08333 }
08334 
08335 qboolean ItemParse_forecolor( itemDef_t *item, int handle ) {
08336         int i;
08337         float f;
08338 
08339         for (i = 0; i < 4; i++) {
08340                 if (!PC_Float_Parse(handle, &f)) {
08341                         return qfalse;
08342                 }
08343 
08344                 if (f < 0)
08345                 {       //special case for player color
08346                         item->window.flags |= WINDOW_PLAYERCOLOR;
08347                         return qtrue;
08348                 }
08349 
08350                 item->window.foreColor[i]  = f;
08351                 item->window.flags |= WINDOW_FORECOLORSET;
08352         }
08353         return qtrue;
08354 }
08355 
08356 qboolean ItemParse_bordercolor( itemDef_t *item, int handle ) {
08357         int i;
08358         float f;
08359 
08360         for (i = 0; i < 4; i++) {
08361                 if (!PC_Float_Parse(handle, &f)) {
08362                         return qfalse;
08363                 }
08364                 item->window.borderColor[i]  = f;
08365         }
08366         return qtrue;
08367 }
08368 
08369 qboolean ItemParse_outlinecolor( itemDef_t *item, int handle ) {
08370         if (!PC_Color_Parse(handle, &item->window.outlineColor)){
08371                 return qfalse;
08372         }
08373         return qtrue;
08374 }
08375 
08376 qboolean ItemParse_background( itemDef_t *item, int handle ) {
08377         pc_token_t token;
08378 
08379         if (!trap_PC_ReadToken(handle, &token)) {
08380                 return qfalse;
08381         }
08382         item->window.background = DC->registerShaderNoMip(token.string);
08383         return qtrue;
08384 }
08385 
08386 qboolean ItemParse_cinematic( itemDef_t *item, int handle ) {
08387         if (!PC_String_Parse(handle, &item->window.cinematicName)) {
08388                 return qfalse;
08389         }
08390         return qtrue;
08391 }
08392 
08393 qboolean ItemParse_doubleClick( itemDef_t *item, int handle ) {
08394         listBoxDef_t *listPtr;
08395 
08396         Item_ValidateTypeData(item);
08397         if (!item->typeData) {
08398                 return qfalse;
08399         }
08400 
08401         listPtr = (listBoxDef_t*)item->typeData;
08402 
08403         if (!PC_Script_Parse(handle, &listPtr->doubleClick)) {
08404                 return qfalse;
08405         }
08406         return qtrue;
08407 }
08408 
08409 qboolean ItemParse_onFocus( itemDef_t *item, int handle ) {
08410         if (!PC_Script_Parse(handle, &item->onFocus)) {
08411                 return qfalse;
08412         }
08413         return qtrue;
08414 }
08415 
08416 qboolean ItemParse_leaveFocus( itemDef_t *item, int handle ) {
08417         if (!PC_Script_Parse(handle, &item->leaveFocus)) {
08418                 return qfalse;
08419         }
08420         return qtrue;
08421 }
08422 
08423 qboolean ItemParse_mouseEnter( itemDef_t *item, int handle ) {
08424         if (!PC_Script_Parse(handle, &item->mouseEnter)) {
08425                 return qfalse;
08426         }
08427         return qtrue;
08428 }
08429 
08430 qboolean ItemParse_mouseExit( itemDef_t *item, int handle ) {
08431         if (!PC_Script_Parse(handle, &item->mouseExit)) {
08432                 return qfalse;
08433         }
08434         return qtrue;
08435 }
08436 
08437 qboolean ItemParse_mouseEnterText( itemDef_t *item, int handle ) {
08438         if (!PC_Script_Parse(handle, &item->mouseEnterText)) {
08439                 return qfalse;
08440         }
08441         return qtrue;
08442 }
08443 
08444 qboolean ItemParse_mouseExitText( itemDef_t *item, int handle ) {
08445         if (!PC_Script_Parse(handle, &item->mouseExitText)) {
08446                 return qfalse;
08447         }
08448         return qtrue;
08449 }
08450 
08451 qboolean ItemParse_action( itemDef_t *item, int handle ) {
08452         if (!PC_Script_Parse(handle, &item->action)) {
08453                 return qfalse;
08454         }
08455         return qtrue;
08456 }
08457 
08458 qboolean ItemParse_special( itemDef_t *item, int handle ) {
08459         if (!PC_Float_Parse(handle, &item->special)) {
08460                 return qfalse;
08461         }
08462         return qtrue;
08463 }
08464 
08465 qboolean ItemParse_cvarTest( itemDef_t *item, int handle ) {
08466         if (!PC_String_Parse(handle, &item->cvarTest)) {
08467                 return qfalse;
08468         }
08469         return qtrue;
08470 }
08471 
08472 qboolean ItemParse_cvar( itemDef_t *item, int handle ) 
08473 {
08474         Item_ValidateTypeData(item);
08475         if (!PC_String_Parse(handle, &item->cvar)) 
08476         {
08477                 return qfalse;
08478         }
08479 
08480         if ( item->typeData)
08481         {
08482                 editFieldDef_t *editPtr;
08483 
08484                 switch ( item->type )
08485                 {
08486                         case ITEM_TYPE_EDITFIELD:
08487                         case ITEM_TYPE_NUMERICFIELD:
08488                         case ITEM_TYPE_YESNO:
08489                         case ITEM_TYPE_BIND:
08490                         case ITEM_TYPE_SLIDER:
08491                         case ITEM_TYPE_TEXT:
08492                                 editPtr = (editFieldDef_t*)item->typeData;
08493                                 editPtr->minVal = -1;
08494                                 editPtr->maxVal = -1;
08495                                 editPtr->defVal = -1;
08496                                 break;
08497                 }
08498         }
08499         return qtrue;
08500 }
08501 
08502 qboolean ItemParse_font( itemDef_t *item, int handle ) 
08503 {
08504         Item_ValidateTypeData(item);
08505         if (!PC_Int_Parse(handle, &item->iMenuFont)) 
08506         {
08507                 return qfalse;
08508         }
08509         return qtrue;
08510 }
08511 
08512 
08513 qboolean ItemParse_maxChars( itemDef_t *item, int handle ) {
08514         editFieldDef_t *editPtr;
08515         int maxChars;
08516 
08517         Item_ValidateTypeData(item);
08518         if (!item->typeData)
08519                 return qfalse;
08520 
08521         if (!PC_Int_Parse(handle, &maxChars)) {
08522                 return qfalse;
08523         }
08524         editPtr = (editFieldDef_t*)item->typeData;
08525         editPtr->maxChars = maxChars;
08526         return qtrue;
08527 }
08528 
08529 qboolean ItemParse_maxPaintChars( itemDef_t *item, int handle ) {
08530         editFieldDef_t *editPtr;
08531         int maxChars;
08532 
08533         Item_ValidateTypeData(item);
08534         if (!item->typeData)
08535                 return qfalse;
08536 
08537         if (!PC_Int_Parse(handle, &maxChars)) {
08538                 return qfalse;
08539         }
08540         editPtr = (editFieldDef_t*)item->typeData;
08541         editPtr->maxPaintChars = maxChars;
08542         return qtrue;
08543 }
08544 
08545 qboolean ItemParse_maxLineChars( itemDef_t *item, int handle ) 
08546 {
08547         textScrollDef_t *scrollPtr;
08548         int                             maxChars;
08549 
08550         Item_ValidateTypeData(item);
08551         if (!item->typeData)
08552                 return qfalse;
08553 
08554         if (!PC_Int_Parse(handle, &maxChars)) 
08555         {
08556                 return qfalse;
08557         }
08558 
08559         scrollPtr = (textScrollDef_t*)item->typeData;
08560         scrollPtr->maxLineChars = maxChars;
08561 
08562         return qtrue;
08563 }
08564 
08565 qboolean ItemParse_lineHeight( itemDef_t *item, int handle ) 
08566 {
08567         textScrollDef_t *scrollPtr;
08568         int                             height;
08569 
08570         Item_ValidateTypeData(item);
08571         if (!item->typeData)
08572                 return qfalse;
08573 
08574         if (!PC_Int_Parse(handle, &height)) 
08575         {
08576                 return qfalse;
08577         }
08578 
08579         scrollPtr = (textScrollDef_t*)item->typeData;
08580         scrollPtr->lineHeight = height;
08581 
08582         return qtrue;
08583 }
08584 
08585 qboolean ItemParse_cvarFloat( itemDef_t *item, int handle ) {
08586         editFieldDef_t *editPtr;
08587 
08588         Item_ValidateTypeData(item);
08589         if (!item->typeData)
08590                 return qfalse;
08591         editPtr = (editFieldDef_t*)item->typeData;
08592         if (PC_String_Parse(handle, &item->cvar) &&
08593                 PC_Float_Parse(handle, &editPtr->defVal) &&
08594                 PC_Float_Parse(handle, &editPtr->minVal) &&
08595                 PC_Float_Parse(handle, &editPtr->maxVal)) {
08596                 return qtrue;
08597         }
08598         return qfalse;
08599 }
08600 
08601 char currLanguage[32][128];
08602 static const char languageString[32] = "@MENUS_MYLANGUAGE";
08603 
08604 qboolean ItemParse_cvarStrList( itemDef_t *item, int handle ) {
08605         pc_token_t token;
08606         multiDef_t *multiPtr;
08607         int pass;
08608         
08609         Item_ValidateTypeData(item);
08610         if (!item->typeData)
08611                 return qfalse;
08612         multiPtr = (multiDef_t*)item->typeData;
08613         multiPtr->count = 0;
08614         multiPtr->strDef = qtrue;
08615 
08616         if (!trap_PC_ReadToken(handle, &token))
08617         {
08618                 return qfalse;
08619         }
08620 
08621         if (!Q_stricmp(token.string,"feeder") && item->special == FEEDER_PLAYER_SPECIES) 
08622         {
08623 #ifndef CGAME
08624                 for (; multiPtr->count < uiInfo.playerSpeciesCount; multiPtr->count++)
08625                 {
08626                         multiPtr->cvarList[multiPtr->count] = String_Alloc(strupr(va("@MENUS_%s",uiInfo.playerSpecies[multiPtr->count].Name )));        //look up translation
08627                         multiPtr->cvarStr[multiPtr->count] = uiInfo.playerSpecies[multiPtr->count].Name;        //value
08628                 }
08629 #endif
08630                 return qtrue;
08631         }
08632         // languages
08633         if (!Q_stricmp(token.string,"feeder") && item->special == FEEDER_LANGUAGES) 
08634         {
08635 #ifndef CGAME
08636                 for (; multiPtr->count < uiInfo.languageCount; multiPtr->count++)
08637                 {
08638                         // The displayed text
08639                         trap_GetLanguageName( (const int) multiPtr->count,(char *) currLanguage[multiPtr->count]  );    // eg "English"
08640                         multiPtr->cvarList[multiPtr->count] = languageString;
08641                         // The cvar value that goes into se_language
08642                         trap_GetLanguageName( (const int) multiPtr->count,(char *) currLanguage[multiPtr->count] );
08643                         multiPtr->cvarStr[multiPtr->count] = currLanguage[multiPtr->count];
08644                 }
08645 #endif
08646                 return qtrue;
08647         }
08648 
08649         if (*token.string != '{') {
08650                 return qfalse;
08651         }
08652 
08653         pass = 0;
08654         while ( 1 ) {
08655                 char* psString;
08656 
08657 //              if (!trap_PC_ReadToken(handle, &token)) {
08658 //                      PC_SourceError(handle, "end of file inside menu item\n");
08659 //                      return qfalse;
08660 //              }                  
08661 
08662                 if (!PC_String_Parse(handle, (const char **)&psString)) 
08663                 {
08664                         PC_SourceError(handle, "end of file inside menu item\n");
08665                         return qfalse;
08666                 }
08667 
08668                 //a normal StringAlloc ptr
08669                 if ((int)psString > 0)  
08670                 {
08671                         if (*psString == '}') {
08672                                 return qtrue;
08673                         }
08674 
08675                         if (*psString == ',' || *psString == ';') {
08676                                 continue;
08677                         }
08678                 }
08679 
08680                 if (pass == 0) {
08681                         multiPtr->cvarList[multiPtr->count] = psString;
08682                         pass = 1;
08683                 } else {
08684                         multiPtr->cvarStr[multiPtr->count] = psString;
08685                         pass = 0;
08686                         multiPtr->count++;
08687                         if (multiPtr->count >= MAX_MULTI_CVARS) {
08688                                 return qfalse;
08689                         }
08690                 }
08691 
08692         }
08693         return qfalse;  // bk001205 - LCC missing return value
08694 }
08695 
08696 qboolean ItemParse_cvarFloatList( itemDef_t *item, int handle ) 
08697 {
08698         pc_token_t token;
08699         multiDef_t *multiPtr;
08700         
08701         Item_ValidateTypeData(item);
08702         if (!item->typeData)
08703         {
08704                 return qfalse;
08705         }
08706         
08707         multiPtr = (multiDef_t*)item->typeData;
08708         multiPtr->count = 0;
08709         multiPtr->strDef = qfalse;
08710 
08711         if (!trap_PC_ReadToken(handle, &token))
08712         {
08713                 return qfalse;
08714         }
08715         
08716         if (*token.string != '{') 
08717         {
08718                 return qfalse;
08719         }
08720 
08721         while ( 1 ) 
08722         {
08723                 char* string;
08724 
08725                 if ( !PC_String_Parse ( handle, (const char **)&string ) )
08726                 {
08727                         PC_SourceError(handle, "end of file inside menu item\n");
08728                         return qfalse;
08729                 }
08730                         
08731                 //a normal StringAlloc ptr
08732                 if ((int)string > 0)    
08733                 {
08734                         if (*string == '}') 
08735                         {
08736                                 return qtrue;
08737                         }
08738 
08739                         if (*string == ',' || *string == ';') 
08740                         {
08741                                 continue;
08742                         }
08743                 }
08744 
08745                 multiPtr->cvarList[multiPtr->count] = string;
08746                 if (!PC_Float_Parse(handle, &multiPtr->cvarValue[multiPtr->count])) 
08747                 {
08748                         return qfalse;
08749                 }
08750 
08751                 multiPtr->count++;
08752                 if (multiPtr->count >= MAX_MULTI_CVARS) 
08753                 {
08754                         return qfalse;
08755                 }
08756 
08757         }
08758         return qfalse;  // bk001205 - LCC missing return value
08759 }
08760 
08761 
08762 
08763 qboolean ItemParse_addColorRange( itemDef_t *item, int handle ) {
08764         colorRangeDef_t color;
08765 
08766         if (PC_Float_Parse(handle, &color.low) &&
08767                 PC_Float_Parse(handle, &color.high) &&
08768                 PC_Color_Parse(handle, &color.color) ) {
08769                 if (item->numColors < MAX_COLOR_RANGES) {
08770                         memcpy(&item->colorRanges[item->numColors], &color, sizeof(color));
08771                         item->numColors++;
08772                 }
08773                 return qtrue;
08774         }
08775         return qfalse;
08776 }
08777 
08778 qboolean ItemParse_ownerdrawFlag( itemDef_t *item, int handle ) {
08779         int i;
08780         if (!PC_Int_Parse(handle, &i)) {
08781                 return qfalse;
08782         }
08783         item->window.ownerDrawFlags |= i;
08784         return qtrue;
08785 }
08786 
08787 qboolean ItemParse_enableCvar( itemDef_t *item, int handle ) {
08788         if (PC_Script_Parse(handle, &item->enableCvar)) {
08789                 item->cvarFlags = CVAR_ENABLE;
08790                 return qtrue;
08791         }
08792         return qfalse;
08793 }
08794 
08795 qboolean ItemParse_disableCvar( itemDef_t *item, int handle ) {
08796         if (PC_Script_Parse(handle, &item->enableCvar)) {
08797                 item->cvarFlags = CVAR_DISABLE;
08798                 return qtrue;
08799         }
08800         return qfalse;
08801 }
08802 
08803 qboolean ItemParse_showCvar( itemDef_t *item, int handle ) {
08804         if (PC_Script_Parse(handle, &item->enableCvar)) {
08805                 item->cvarFlags = CVAR_SHOW;
08806                 return qtrue;
08807         }
08808         return qfalse;
08809 }
08810 
08811 qboolean ItemParse_hideCvar( itemDef_t *item, int handle ) {
08812         if (PC_Script_Parse(handle, &item->enableCvar)) {
08813                 item->cvarFlags = CVAR_HIDE;
08814                 return qtrue;
08815         }
08816         return qfalse;
08817 }
08818 
08819 /*
08820 ===============
08821 ItemParse_align 
08822 ===============
08823 */
08824 qboolean ItemParse_Appearance_slot( itemDef_t *item, int handle ) 
08825 {
08826         if (!PC_Int_Parse(handle, &item->appearanceSlot))
08827         {
08828                 return qfalse;
08829         }
08830         return qtrue;
08831 }
08832 
08833 qboolean ItemParse_isSaber( itemDef_t *item, int handle  )
08834 {
08835 #ifndef CGAME
08836 
08837         int     i;
08838 
08839         if (PC_Int_Parse(handle, &i)) 
08840         {
08841                 if ( i )
08842                 {
08843                         item->flags |= ITF_ISSABER;
08844                         UI_CacheSaberGlowGraphics();
08845                         if ( !ui_saber_parms_parsed )
08846                         {
08847                                 UI_SaberLoadParms();
08848                         }
08849                 }
08850                 else
08851                 {
08852                         item->flags &= ~ITF_ISSABER;
08853                 }
08854         
08855                 return qtrue;
08856         }
08857 #endif
08858         return qfalse;
08859 }
08860 
08861 //extern void UI_SaberLoadParms( void );
08862 //extern qboolean ui_saber_parms_parsed;
08863 //extern void UI_CacheSaberGlowGraphics( void );
08864 
08865 qboolean ItemParse_isSaber2( itemDef_t *item, int handle  )
08866 {
08867 #ifndef CGAME
08868         int     i;
08869         if (PC_Int_Parse(handle, &i)) 
08870         {
08871                 if ( i )
08872                 {
08873                         item->flags |= ITF_ISSABER2;
08874                         UI_CacheSaberGlowGraphics();
08875                         if ( !ui_saber_parms_parsed )
08876                         {
08877                                 UI_SaberLoadParms();
08878                         }
08879                 }
08880                 else
08881                 {
08882                         item->flags &= ~ITF_ISSABER2;
08883                 }
08884 
08885                 return qtrue;
08886         }
08887 #endif
08888         
08889         return qfalse;
08890 }
08891 
08892 keywordHash_t itemParseKeywords[] = {
08893         {"action",                      ItemParse_action,                       NULL    },
08894         {"addColorRange",       ItemParse_addColorRange,        NULL    },
08895         {"align",                       ItemParse_align,                        NULL    },
08896         {"autowrapped",         ItemParse_autowrapped,          NULL    },
08897         {"appearance_slot",     ItemParse_Appearance_slot,      NULL    },
08898         {"asset_model",         ItemParse_asset_model,          NULL    },
08899         {"asset_shader",        ItemParse_asset_shader,         NULL    },
08900         {"backcolor",           ItemParse_backcolor,            NULL    },
08901         {"background",          ItemParse_background,           NULL    },
08902         {"border",                      ItemParse_border,                       NULL    },
08903         {"bordercolor",         ItemParse_bordercolor,          NULL    },
08904         {"bordersize",          ItemParse_bordersize,           NULL    },
08905         {"cinematic",           ItemParse_cinematic,            NULL    },
08906         {"columns",                     ItemParse_columns,                      NULL    },
08907         {"cvar",                        ItemParse_cvar,                         NULL    },
08908         {"cvarFloat",           ItemParse_cvarFloat,            NULL    },
08909         {"cvarFloatList",       ItemParse_cvarFloatList,        NULL    },
08910         {"cvarStrList",         ItemParse_cvarStrList,          NULL    },
08911         {"cvarTest",            ItemParse_cvarTest,                     NULL    },
08912         {"desctext",            ItemParse_descText,                     NULL    },
08913         {"decoration",          ItemParse_decoration,           NULL    },
08914         {"disableCvar",         ItemParse_disableCvar,          NULL    },
08915         {"doubleclick",         ItemParse_doubleClick,          NULL    },
08916         {"elementheight",       ItemParse_elementheight,        NULL    },
08917         {"elementtype",         ItemParse_elementtype,          NULL    },
08918         {"elementwidth",        ItemParse_elementwidth,         NULL    },
08919         {"enableCvar",          ItemParse_enableCvar,           NULL    },
08920         {"feeder",                      ItemParse_feeder,                       NULL    },
08921         {"flag",                        ItemParse_flag,                         NULL    },
08922         {"focusSound",          ItemParse_focusSound,           NULL    },
08923         {"font",                        ItemParse_font,                         NULL    },
08924         {"forecolor",           ItemParse_forecolor,            NULL    },
08925         {"group",                       ItemParse_group,                        NULL    },
08926         {"hideCvar",            ItemParse_hideCvar,                     NULL    },
08927         {"horizontalscroll", ItemParse_horizontalscroll, NULL   },
08928         {"isCharacter",         ItemParse_isCharacter,          NULL    },
08929         {"isSaber",                     ItemParse_isSaber,                      NULL    },
08930         {"isSaber2",            ItemParse_isSaber2,                     NULL    },
08931         {"leaveFocus",          ItemParse_leaveFocus,           NULL    },
08932         {"maxChars",            ItemParse_maxChars,                     NULL    },
08933         {"maxPaintChars",       ItemParse_maxPaintChars,        NULL    },
08934         {"model_angle",         ItemParse_model_angle,          NULL    },
08935         {"model_fovx",          ItemParse_model_fovx,           NULL    },
08936         {"model_fovy",          ItemParse_model_fovy,           NULL    },
08937         {"model_origin",        ItemParse_model_origin,         NULL    },
08938         {"model_rotation",      ItemParse_model_rotation,       NULL    },
08939         //rww - g2 begin
08940         {"model_g2mins",        ItemParse_model_g2mins,         NULL    },
08941         {"model_g2maxs",        ItemParse_model_g2maxs,         NULL    },
08942         {"model_g2scale",       ItemParse_model_g2scale,        NULL    },
08943         {"model_g2skin",        ItemParse_model_g2skin,         NULL    },
08944         {"model_g2anim",        ItemParse_model_g2anim,         NULL    },
08945         //rww - g2 end
08946         {"mouseEnter",          ItemParse_mouseEnter,           NULL    },
08947         {"mouseEnterText",      ItemParse_mouseEnterText,       NULL    },
08948         {"mouseExit",           ItemParse_mouseExit,            NULL    },
08949         {"mouseExitText",       ItemParse_mouseExitText,        NULL    },
08950         {"name",                        ItemParse_name,                         NULL    },
08951         {"notselectable",       ItemParse_notselectable,        NULL    },
08952         {"onFocus",                     ItemParse_onFocus,                      NULL    },
08953         {"outlinecolor",        ItemParse_outlinecolor,         NULL    },
08954         {"ownerdraw",           ItemParse_ownerdraw,            NULL    },
08955         {"ownerdrawFlag",       ItemParse_ownerdrawFlag,        NULL    },
08956         {"rect",                        ItemParse_rect,                         NULL    },
08957         {"rectcvar",            ItemParse_rectcvar,                     NULL    },
08958         {"showCvar",            ItemParse_showCvar,                     NULL    },
08959         {"special",                     ItemParse_special,                      NULL    },
08960         {"style",                       ItemParse_style,                        NULL    },
08961         {"text",                        ItemParse_text,                         NULL    },
08962         {"textalign",           ItemParse_textalign,            NULL    },
08963         {"textalignx",          ItemParse_textalignx,           NULL    },
08964         {"textaligny",          ItemParse_textaligny,           NULL    },
08965         {"textscale",           ItemParse_textscale,            NULL    },
08966         {"textstyle",           ItemParse_textstyle,            NULL    },
08967         {"text2",                       ItemParse_text2,                        NULL    },
08968         {"text2alignx",         ItemParse_text2alignx,          NULL    },
08969         {"text2aligny",         ItemParse_text2aligny,          NULL    },
08970         {"type",                        ItemParse_type,                         NULL    },
08971         {"visible",                     ItemParse_visible,                      NULL    },
08972         {"wrapped",                     ItemParse_wrapped,                      NULL    },
08973 
08974         // Text scroll specific
08975         {"maxLineChars",        ItemParse_maxLineChars,         NULL    },
08976         {"lineHeight",          ItemParse_lineHeight,           NULL    },
08977         {"invertyesno",         ItemParse_invertyesno,          NULL    },
08978         //JLF MPMOVED
08979         {"scrollhidden",        ItemParse_scrollhidden,         NULL    },
08980         {"xoffset               ",      ItemParse_xoffset,                      NULL    },
08981         //JLF end
08982 
08983 
08984 
08985         {0,                                     0,                                                      0               }
08986 };
08987 
08988 keywordHash_t *itemParseKeywordHash[KEYWORDHASH_SIZE];
08989 
08990 /*
08991 ===============
08992 Item_SetupKeywordHash
08993 ===============
08994 */
08995 void Item_SetupKeywordHash(void) {
08996         int i;
08997 
08998         memset(itemParseKeywordHash, 0, sizeof(itemParseKeywordHash));
08999         for (i = 0; itemParseKeywords[i].keyword; i++) {
09000                 KeywordHash_Add(itemParseKeywordHash, &itemParseKeywords[i]);
09001         }
09002 }
09003 
09004 /*
09005 ===============
09006 Item_Parse
09007 ===============
09008 */
09009 qboolean Item_Parse(int handle, itemDef_t *item) {
09010         pc_token_t token;
09011         keywordHash_t *key;
09012 
09013 
09014         if (!trap_PC_ReadToken(handle, &token))
09015                 return qfalse;
09016         if (*token.string != '{') {
09017                 return qfalse;
09018         }
09019         while ( 1 ) {
09020                 if (!trap_PC_ReadToken(handle, &token)) {
09021                         PC_SourceError(handle, "end of file inside menu item\n");
09022                         return qfalse;
09023                 }
09024 
09025                 if (*token.string == '}') {
09026                         return qtrue;
09027                 }
09028 
09029                 key = KeywordHash_Find(itemParseKeywordHash, token.string);
09030                 if (!key) {
09031                         PC_SourceError(handle, "unknown menu item keyword %s", token.string);
09032                         continue;
09033                 }
09034                 if ( !key->func(item, handle) ) {
09035                         PC_SourceError(handle, "couldn't parse menu item keyword %s", token.string);
09036                         return qfalse;
09037                 }
09038         }
09039         return qfalse;  // bk001205 - LCC missing return value
09040 }
09041 
09042 static void Item_TextScroll_BuildLines ( itemDef_t* item )
09043 {
09044         char text[2048];
09045 
09046 #if 1
09047 
09048         // new asian-aware line breaker...  (pasted from elsewhere late @ night, hence aliasing-vars ;-)
09049         //
09050         textScrollDef_t* scrollPtr = (textScrollDef_t*) item->typeData;
09051         const char *psText = item->text;        // for copy/paste ease
09052         int iBoxWidth = item->window.rect.w - SCROLLBAR_SIZE - 10;
09053 
09054         // this could probably be simplified now, but it was converted from something else I didn't originally write, 
09055         //      and it works anyway so wtf...
09056         //
09057         const char *psCurrentTextReadPos;
09058         const char *psReadPosAtLineStart;       
09059         const char *psBestLineBreakSrcPos;
09060         const char *psLastGood_s;       // needed if we get a full screen of chars with no punctuation or space (see usage notes)
09061         qboolean bIsTrailingPunctuation;
09062         unsigned int uiLetter;
09063 
09064         if (*psText == '@')     // string reference
09065         {
09066                 trap_SP_GetStringTextString( &psText[1], text, sizeof(text));
09067                 psText = text;
09068         }
09069 
09070         psCurrentTextReadPos = psText;
09071         psReadPosAtLineStart = psCurrentTextReadPos;
09072         psBestLineBreakSrcPos = psCurrentTextReadPos;
09073 
09074         scrollPtr->iLineCount = 0;
09075         memset((char*)scrollPtr->pLines,0,sizeof(scrollPtr->pLines));
09076 
09077         while (*psCurrentTextReadPos && (scrollPtr->iLineCount < MAX_TEXTSCROLL_LINES) )
09078         {
09079                 char sLineForDisplay[2048];     // ott
09080 
09081                 // construct a line...
09082                 //
09083                 psCurrentTextReadPos = psReadPosAtLineStart;
09084                 sLineForDisplay[0] = '\0';
09085                 while ( *psCurrentTextReadPos )
09086                 {
09087                         int iAdvanceCount;
09088                         psLastGood_s = psCurrentTextReadPos;
09089 
09090                         // read letter...
09091                         //
09092                         uiLetter = trap_AnyLanguage_ReadCharFromString(psCurrentTextReadPos, &iAdvanceCount, &bIsTrailingPunctuation);
09093                         psCurrentTextReadPos += iAdvanceCount;
09094 
09095                         // concat onto string so far...
09096                         //
09097                         if (uiLetter == 32 && sLineForDisplay[0] == '\0')
09098                         {
09099                                 psReadPosAtLineStart++;
09100                                 continue;       // unless it's a space at the start of a line, in which case ignore it.
09101                         }
09102 
09103                         if (uiLetter > 255)
09104                         {
09105                                 Q_strcat(sLineForDisplay, sizeof(sLineForDisplay),va("%c%c",uiLetter >> 8, uiLetter & 0xFF));
09106                         }
09107                         else
09108                         {
09109                                 Q_strcat(sLineForDisplay, sizeof(sLineForDisplay),va("%c",uiLetter & 0xFF));
09110                         }
09111 
09112                         if (uiLetter == '\n')
09113                         {
09114                                 // explicit new line...
09115                                 //
09116                                 sLineForDisplay[ strlen(sLineForDisplay)-1 ] = '\0';    // kill the CR
09117                                 psReadPosAtLineStart = psCurrentTextReadPos;
09118                                 psBestLineBreakSrcPos = psCurrentTextReadPos;
09119 
09120                                 // hack it to fit in with this code...
09121                                 //
09122                                 scrollPtr->pLines[ scrollPtr->iLineCount ] = String_Alloc ( sLineForDisplay );
09123                                 break;  // print this line
09124                         }
09125                         else 
09126                         if ( DC->textWidth( sLineForDisplay, item->textscale, item->iMenuFont ) >= iBoxWidth )
09127                         {                                       
09128                                 // reached screen edge, so cap off string at bytepos after last good position...
09129                                 //
09130                                 if (uiLetter > 255 && bIsTrailingPunctuation && !trap_Language_UsesSpaces())
09131                                 {
09132                                         // Special case, don't consider line breaking if you're on an asian punctuation char of
09133                                         //      a language that doesn't use spaces...
09134                                         //
09135                                         uiLetter = uiLetter;    // breakpoint line only
09136                                 }
09137                                 else
09138                                 {
09139                                         if (psBestLineBreakSrcPos == psReadPosAtLineStart)
09140                                         {
09141                                                 //  aarrrggh!!!!!   we'll only get here is someone has fed in a (probably) garbage string,
09142                                                 //              since it doesn't have a single space or punctuation mark right the way across one line
09143                                                 //              of the screen.  So far, this has only happened in testing when I hardwired a taiwanese 
09144                                                 //              string into this function while the game was running in english (which should NEVER happen 
09145                                                 //              normally).  On the other hand I suppose it's entirely possible that some taiwanese string 
09146                                                 //              might have no punctuation at all, so...
09147                                                 //
09148                                                 psBestLineBreakSrcPos = psLastGood_s;   // force a break after last good letter
09149                                         }
09150 
09151                                         sLineForDisplay[ psBestLineBreakSrcPos - psReadPosAtLineStart ] = '\0';
09152                                         psReadPosAtLineStart = psCurrentTextReadPos = psBestLineBreakSrcPos;
09153 
09154                                         // hack it to fit in with this code...
09155                                         //
09156                                         scrollPtr->pLines[ scrollPtr->iLineCount ] = String_Alloc( sLineForDisplay );
09157                                         break;  // print this line
09158                                 }
09159                         }
09160 
09161                         // record last-good linebreak pos...  (ie if we've just concat'd a punctuation point (western or asian) or space)
09162                         //
09163                         if (bIsTrailingPunctuation || uiLetter == ' ' || (uiLetter > 255 && !trap_Language_UsesSpaces()))
09164                         {
09165                                 psBestLineBreakSrcPos = psCurrentTextReadPos;
09166                         }
09167                 }
09168 
09170                 //
09171                 if (scrollPtr->pLines[ scrollPtr->iLineCount ] == NULL && strlen(sLineForDisplay))
09172                 {
09173                         // then this is the last line and we've just run out of text, no CR, no overflow etc...
09174                         //
09175                         scrollPtr->pLines[ scrollPtr->iLineCount ] = String_Alloc( sLineForDisplay );
09176                 }
09177                         
09178                 scrollPtr->iLineCount++;
09179         }
09180         
09181 #else
09182         // old version...
09183         //
09184         int                              width;
09185         char*                    lineStart;
09186         char*                    lineEnd;
09187         float                    w;
09188         float                    cw;
09189 
09190         textScrollDef_t* scrollPtr = (textScrollDef_t*) item->typeData;
09191 
09192         scrollPtr->iLineCount = 0;
09193         width = scrollPtr->maxLineChars;
09194         lineStart = (char*)item->text;
09195         lineEnd   = lineStart;
09196         w                 = 0;
09197 
09198         // Keep going as long as there are more lines
09199         while ( scrollPtr->iLineCount < MAX_TEXTSCROLL_LINES )
09200         {
09201                 // End of the road
09202                 if ( *lineEnd == '\0')
09203                 {
09204                         if ( lineStart < lineEnd )
09205                         {
09206                                 scrollPtr->pLines[ scrollPtr->iLineCount++ ] = lineStart;
09207                         }
09208 
09209                         break;
09210                 }
09211 
09212                 // Force a line end if its a '\n'
09213                 else if ( *lineEnd == '\n' )
09214                 {
09215                         *lineEnd = '\0';
09216                         scrollPtr->pLines[ scrollPtr->iLineCount++ ] = lineStart;
09217                         lineStart = lineEnd + 1;
09218                         lineEnd   = lineStart;
09219                         w = 0;
09220                         continue;
09221                 }
09222 
09223                 // Get the current character width 
09224                 cw = DC->textWidth ( va("%c", *lineEnd), item->textscale, item->iMenuFont );
09225 
09226                 // Past the end of the boundary?
09227                 if ( w + cw > (item->window.rect.w - SCROLLBAR_SIZE - 10) )
09228                 {
09229                         // Past the end so backtrack to the word boundary
09230                         while ( *lineEnd != ' ' && *lineEnd != '\t' && lineEnd > lineStart )
09231                         {
09232                                 lineEnd--;
09233                         }                                       
09234 
09235                         *lineEnd = '\0';
09236                         scrollPtr->pLines[ scrollPtr->iLineCount++ ] = lineStart;
09237 
09238                         // Skip any whitespaces
09239                         lineEnd++;
09240                         while ( (*lineEnd == ' ' || *lineEnd == '\t') && *lineEnd )
09241                         {
09242                                 lineEnd++;
09243                         }
09244 
09245                         lineStart = lineEnd;
09246                         w = 0;
09247                 }
09248                 else
09249                 {
09250                         w += cw;
09251                         lineEnd++;
09252                 }
09253         }
09254 #endif
09255 }
09256 
09257 // Item_InitControls
09258 // init's special control types
09259 void Item_InitControls(itemDef_t *item) 
09260 {
09261         if (item == NULL) 
09262         {
09263                 return;
09264         }
09265 
09266         switch ( item->type )
09267         {
09268                 case ITEM_TYPE_LISTBOX:
09269                 {
09270                         listBoxDef_t *listPtr = (listBoxDef_t*)item->typeData;
09271                         item->cursorPos = 0;
09272                         if (listPtr) 
09273                         {
09274                                 listPtr->cursorPos = 0;
09275                                 listPtr->startPos = 0;
09276                                 listPtr->endPos = 0;
09277                                 listPtr->cursorPos = 0;
09278                         }
09279 
09280                         break;
09281                 }
09282         }
09283 }
09284 
09285 /*
09286 ===============
09287 Menu Keyword Parse functions
09288 ===============
09289 */
09290 
09291 qboolean MenuParse_font( itemDef_t *item, int handle ) {
09292         menuDef_t *menu = (menuDef_t*)item;
09293         if (!PC_String_Parse(handle, &menu->font)) {
09294                 return qfalse;
09295         }
09296         if (!DC->Assets.fontRegistered) {
09297                 //DC->registerFont(menu->font, 48, &DC->Assets.textFont);
09298                 DC->Assets.qhMediumFont = DC->RegisterFont(menu->font);
09299                 DC->Assets.fontRegistered = qtrue;
09300         }
09301         return qtrue;
09302 }
09303 
09304 qboolean MenuParse_name( itemDef_t *item, int handle ) {
09305         menuDef_t *menu = (menuDef_t*)item;
09306         if (!PC_String_Parse(handle, &menu->window.name)) {
09307                 return qfalse;
09308         }
09309         if (Q_stricmp(menu->window.name, "main") == 0) {
09310                 // default main as having focus
09311                 //menu->window.flags |= WINDOW_HASFOCUS;
09312         }
09313         return qtrue;
09314 }
09315 
09316 qboolean MenuParse_fullscreen( itemDef_t *item, int handle ) {
09317         menuDef_t *menu = (menuDef_t*)item;
09318         if (!PC_Int_Parse(handle, (int*) &menu->fullScreen)) { // bk001206 - cast qboolean
09319                 return qfalse;
09320         }
09321         return qtrue;
09322 }
09323 
09324 qboolean MenuParse_rect( itemDef_t *item, int handle ) {
09325         menuDef_t *menu = (menuDef_t*)item;
09326         if (!PC_Rect_Parse(handle, &menu->window.rect)) {
09327                 return qfalse;
09328         }
09329         return qtrue;
09330 }
09331 
09332 /*
09333 =================
09334 MenuParse_style
09335 =================
09336 */
09337 qboolean MenuParse_style( itemDef_t *item, int handle) 
09338 {
09339         menuDef_t *menu = (menuDef_t*)item;
09340 
09341         if (!PC_Int_Parse(handle, &menu->window.style))
09342         {
09343                 Com_Printf(S_COLOR_YELLOW "Unknown menu style value");
09344                 return qfalse;
09345         }
09346 
09347         return qtrue;
09348 }
09349 
09350 qboolean MenuParse_visible( itemDef_t *item, int handle ) {
09351         int i;
09352         menuDef_t *menu = (menuDef_t*)item;
09353 
09354         if (!PC_Int_Parse(handle, &i)) {
09355                 return qfalse;
09356         }
09357         if (i) {
09358                 menu->window.flags |= WINDOW_VISIBLE;
09359         }
09360         return qtrue;
09361 }
09362 
09363 qboolean MenuParse_onOpen( itemDef_t *item, int handle ) {
09364         menuDef_t *menu = (menuDef_t*)item;
09365         if (!PC_Script_Parse(handle, &menu->onOpen)) {
09366                 return qfalse;
09367         }
09368         return qtrue;
09369 }
09370 
09371 qboolean MenuParse_onClose( itemDef_t *item, int handle ) {
09372         menuDef_t *menu = (menuDef_t*)item;
09373         if (!PC_Script_Parse(handle, &menu->onClose)) {
09374                 return qfalse;
09375         }
09376         return qtrue;
09377 }
09378 
09379 //JLFACCEPT MPMOVED
09380 /*
09381 =================
09382 MenuParse_onAccept
09383 =================
09384 */
09385 qboolean MenuParse_onAccept( itemDef_t *item, int handle ) 
09386 {
09387         menuDef_t *menu = (menuDef_t*)item;
09388 
09389         if (!PC_Script_Parse(handle, &menu->onAccept)) 
09390         {
09391                 return qfalse;
09392         }
09393         return qtrue;
09394 }
09395 
09396 qboolean MenuParse_onESC( itemDef_t *item, int handle ) {
09397         menuDef_t *menu = (menuDef_t*)item;
09398         if (!PC_Script_Parse(handle, &menu->onESC)) {
09399                 return qfalse;
09400         }
09401         return qtrue;
09402 }
09403 
09404 
09405 
09406 qboolean MenuParse_border( itemDef_t *item, int handle ) {
09407         menuDef_t *menu = (menuDef_t*)item;
09408         if (!PC_Int_Parse(handle, &menu->window.border)) {
09409                 return qfalse;
09410         }
09411         return qtrue;
09412 }
09413 
09414 qboolean MenuParse_borderSize( itemDef_t *item, int handle ) {
09415         menuDef_t *menu = (menuDef_t*)item;
09416         if (!PC_Float_Parse(handle, &menu->window.borderSize)) {
09417                 return qfalse;
09418         }
09419         return qtrue;
09420 }
09421 
09422 qboolean MenuParse_backcolor( itemDef_t *item, int handle ) {
09423         int i;
09424         float f;
09425         menuDef_t *menu = (menuDef_t*)item;
09426 
09427         for (i = 0; i < 4; i++) {
09428                 if (!PC_Float_Parse(handle, &f)) {
09429                         return qfalse;
09430                 }
09431                 menu->window.backColor[i]  = f;
09432         }
09433         return qtrue;
09434 }
09435 
09436 /*
09437 =================
09438 MenuParse_descAlignment
09439 =================
09440 */
09441 qboolean MenuParse_descAlignment( itemDef_t *item, int handle ) 
09442 {
09443         menuDef_t *menu = (menuDef_t*)item;
09444 
09445         if (!PC_Int_Parse(handle, &menu->descAlignment)) 
09446         {
09447                 Com_Printf(S_COLOR_YELLOW "Unknown desc alignment value");
09448                 return qfalse;
09449         }
09450 
09451         return qtrue;
09452 }
09453 
09454 /*
09455 =================
09456 MenuParse_descX
09457 =================
09458 */
09459 qboolean MenuParse_descX( itemDef_t *item, int handle ) 
09460 {
09461         menuDef_t *menu = (menuDef_t*)item;
09462 
09463         if (!PC_Int_Parse(handle, &menu->descX))
09464         {
09465                 return qfalse;
09466         }
09467         return qtrue;
09468 }
09469 
09470 /*
09471 =================
09472 MenuParse_descY
09473 =================
09474 */
09475 qboolean MenuParse_descY( itemDef_t *item, int handle ) 
09476 {
09477         menuDef_t *menu = (menuDef_t*)item;
09478 
09479         if (!PC_Int_Parse(handle, &menu->descY))
09480         {
09481                 return qfalse;
09482         }
09483         return qtrue;
09484 }
09485 
09486 /*
09487 =================
09488 MenuParse_descScale
09489 =================
09490 */
09491 qboolean MenuParse_descScale( itemDef_t *item, int handle) 
09492 {
09493         menuDef_t *menu = (menuDef_t*)item;
09494 
09495         if (!PC_Float_Parse(handle, &menu->descScale)) 
09496         {
09497                 return qfalse;
09498         }
09499         return qtrue;
09500 }
09501 
09502 /*
09503 =================
09504 MenuParse_descColor
09505 =================
09506 */
09507 qboolean MenuParse_descColor( itemDef_t *item, int handle) 
09508 {
09509         int i;
09510         float f;
09511         menuDef_t *menu = (menuDef_t*)item;
09512 
09513         for (i = 0; i < 4; i++) 
09514         {
09515                 if (!PC_Float_Parse(handle, &f)) 
09516                 {
09517                         return qfalse;
09518                 }
09519                 menu->descColor[i]  = f;
09520         }
09521         return qtrue;
09522 }
09523 
09524 qboolean MenuParse_forecolor( itemDef_t *item, int handle ) {
09525         int i;
09526         float f;
09527         menuDef_t *menu = (menuDef_t*)item;
09528 
09529         for (i = 0; i < 4; i++) {
09530                 if (!PC_Float_Parse(handle, &f)) {
09531                         return qfalse;
09532                 }
09533                 if (f < 0)
09534                 {       //special case for player color
09535                         menu->window.flags |= WINDOW_PLAYERCOLOR;
09536                         return qtrue;
09537                 }
09538                 menu->window.foreColor[i]  = f;
09539                 menu->window.flags |= WINDOW_FORECOLORSET;
09540         }
09541         return qtrue;
09542 }
09543 
09544 qboolean MenuParse_bordercolor( itemDef_t *item, int handle ) {
09545         int i;
09546         float f;
09547         menuDef_t *menu = (menuDef_t*)item;
09548 
09549         for (i = 0; i < 4; i++) {
09550                 if (!PC_Float_Parse(handle, &f)) {
09551                         return qfalse;
09552                 }
09553                 menu->window.borderColor[i]  = f;
09554         }
09555         return qtrue;
09556 }
09557 
09558 qboolean MenuParse_focuscolor( itemDef_t *item, int handle ) {
09559         int i;
09560         float f;
09561         menuDef_t *menu = (menuDef_t*)item;
09562 
09563         for (i = 0; i < 4; i++) {
09564                 if (!PC_Float_Parse(handle, &f)) {
09565                         return qfalse;
09566                 }
09567                 menu->focusColor[i]  = f;
09568         }
09569         return qtrue;
09570 }
09571 
09572 qboolean MenuParse_disablecolor( itemDef_t *item, int handle ) {
09573         int i;
09574         float f;
09575         menuDef_t *menu = (menuDef_t*)item;
09576         for (i = 0; i < 4; i++) {
09577                 if (!PC_Float_Parse(handle, &f)) {
09578                         return qfalse;
09579                 }
09580                 menu->disableColor[i]  = f;
09581         }
09582         return qtrue;
09583 }
09584 
09585 
09586 qboolean MenuParse_outlinecolor( itemDef_t *item, int handle ) {
09587         menuDef_t *menu = (menuDef_t*)item;
09588         if (!PC_Color_Parse(handle, &menu->window.outlineColor)){
09589                 return qfalse;
09590         }
09591         return qtrue;
09592 }
09593 
09594 qboolean MenuParse_background( itemDef_t *item, int handle ) {
09595         pc_token_t token;
09596         menuDef_t *menu = (menuDef_t*)item;
09597 
09598         if (!trap_PC_ReadToken(handle, &token)) {
09599                 return qfalse;
09600         }
09601         menu->window.background = DC->registerShaderNoMip(token.string);
09602         return qtrue;
09603 }
09604 
09605 qboolean MenuParse_cinematic( item