1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”).
8 
9 RTCW MP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 RTCW MP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with RTCW MP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 // Copyright (C) 1999-2000 Id Software, Inc.
30 //
31 /**********************************************************************
32 	UI_ATOMS.C
33 
34 	User interface building blocks and support functions.
35 **********************************************************************/
36 #include "ui_local.h"
37 
38 uiStatic_t uis;
39 qboolean m_entersound;              // after a frame, so caching won't disrupt the sound
40 
41 void QDECL Com_DPrintf( const char *fmt, ... ) __attribute__ ( ( format ( printf, 1, 2 ) ) );
42 
43 
44 // JPW NERVE added Com_DPrintf
45 #define MAXPRINTMSG 4096
Com_DPrintf(const char * fmt,...)46 void QDECL Com_DPrintf( const char *fmt, ... ) {
47 	va_list argptr;
48 	char msg[MAXPRINTMSG];
49 	int developer;
50 
51 	developer = trap_Cvar_VariableValue( "developer" );
52 	if ( !developer ) {
53 		return;
54 	}
55 
56 	va_start( argptr,fmt );
57 	Q_vsnprintf( msg, sizeof( msg ), fmt, argptr );
58 	va_end( argptr );
59 
60 	Com_Printf( "%s", msg );
61 }
62 // jpw
63 
Com_Error(int level,const char * error,...)64 void QDECL Com_Error( int level, const char *error, ... ) {
65 	va_list argptr;
66 	char text[1024];
67 
68 	va_start( argptr, error );
69 	Q_vsnprintf( text, sizeof( text ), error, argptr );
70 	va_end( argptr );
71 
72 	trap_Error( text );
73 }
74 
Com_Printf(const char * msg,...)75 void QDECL Com_Printf( const char *msg, ... ) {
76 	va_list argptr;
77 	char text[1024];
78 
79 	va_start( argptr, msg );
80 	Q_vsnprintf( text, sizeof( text ), msg, argptr );
81 	va_end( argptr );
82 
83 	trap_Print( text );
84 }
85 
86 /*
87 =================
88 UI_ClampCvar
89 =================
90 */
UI_ClampCvar(float min,float max,float value)91 float UI_ClampCvar( float min, float max, float value ) {
92 	if ( value < min ) {
93 		return min;
94 	}
95 	if ( value > max ) {
96 		return max;
97 	}
98 	return value;
99 }
100 
101 /*
102 =================
103 UI_StartDemoLoop
104 =================
105 */
UI_StartDemoLoop(void)106 void UI_StartDemoLoop( void ) {
107 	trap_Cmd_ExecuteText( EXEC_APPEND, "d1\n" );
108 }
109 
110 /*
111 // TTimo: unused
112 static void NeedCDAction( qboolean result ) {
113 	if ( !result ) {
114 		trap_Cmd_ExecuteText( EXEC_APPEND, "quit\n" );
115 	}
116 }
117 
118 static void NeedCDKeyAction( qboolean result ) {
119 	if ( !result ) {
120 		trap_Cmd_ExecuteText( EXEC_APPEND, "quit\n" );
121 	}
122 }
123 */
124 
UI_Argv(int arg)125 char *UI_Argv( int arg ) {
126 	static char buffer[MAX_STRING_CHARS];
127 
128 	trap_Argv( arg, buffer, sizeof( buffer ) );
129 
130 	return buffer;
131 }
132 
133 
UI_Cvar_VariableString(const char * var_name)134 char *UI_Cvar_VariableString( const char *var_name ) {
135 	static char buffer[2][MAX_STRING_CHARS];
136 	static int toggle;
137 
138 	toggle ^= 1;        // flip-flop to allow two returns without clash
139 
140 	trap_Cvar_VariableStringBuffer( var_name, buffer[toggle], sizeof( buffer[0] ) );
141 
142 	return buffer[toggle];
143 }
144 
145 
146 #ifdef MISSIONPACK
UI_SetBestScores(postGameInfo_t * newInfo,qboolean postGame)147 void UI_SetBestScores( postGameInfo_t *newInfo, qboolean postGame ) {
148 	trap_Cvar_Set( "ui_scoreAccuracy",     va( "%i%%", newInfo->accuracy ) );
149 	trap_Cvar_Set( "ui_scoreImpressives", va( "%i", newInfo->impressives ) );
150 	trap_Cvar_Set( "ui_scoreExcellents",  va( "%i", newInfo->excellents ) );
151 	trap_Cvar_Set( "ui_scoreDefends",             va( "%i", newInfo->defends ) );
152 	trap_Cvar_Set( "ui_scoreAssists",             va( "%i", newInfo->assists ) );
153 	trap_Cvar_Set( "ui_scoreGauntlets",       va( "%i", newInfo->gauntlets ) );
154 	trap_Cvar_Set( "ui_scoreScore",               va( "%i", newInfo->score ) );
155 	trap_Cvar_Set( "ui_scorePerfect",         va( "%i", newInfo->perfects ) );
156 	trap_Cvar_Set( "ui_scoreTeam",                    va( "%i to %i", newInfo->redScore, newInfo->blueScore ) );
157 	trap_Cvar_Set( "ui_scoreBase",                    va( "%i", newInfo->baseScore ) );
158 	trap_Cvar_Set( "ui_scoreTimeBonus",       va( "%i", newInfo->timeBonus ) );
159 	trap_Cvar_Set( "ui_scoreSkillBonus",      va( "%i", newInfo->skillBonus ) );
160 	trap_Cvar_Set( "ui_scoreShutoutBonus",    va( "%i", newInfo->shutoutBonus ) );
161 	trap_Cvar_Set( "ui_scoreTime",                    va( "%02i:%02i", newInfo->time / 60, newInfo->time % 60 ) );
162 	trap_Cvar_Set( "ui_scoreCaptures",        va( "%i", newInfo->captures ) );
163 	if ( postGame ) {
164 		trap_Cvar_Set( "ui_scoreAccuracy2",     va( "%i%%", newInfo->accuracy ) );
165 		trap_Cvar_Set( "ui_scoreImpressives2",    va( "%i", newInfo->impressives ) );
166 		trap_Cvar_Set( "ui_scoreExcellents2",     va( "%i", newInfo->excellents ) );
167 		trap_Cvar_Set( "ui_scoreDefends2",            va( "%i", newInfo->defends ) );
168 		trap_Cvar_Set( "ui_scoreAssists2",            va( "%i", newInfo->assists ) );
169 		trap_Cvar_Set( "ui_scoreGauntlets2",      va( "%i", newInfo->gauntlets ) );
170 		trap_Cvar_Set( "ui_scoreScore2",              va( "%i", newInfo->score ) );
171 		trap_Cvar_Set( "ui_scorePerfect2",            va( "%i", newInfo->perfects ) );
172 		trap_Cvar_Set( "ui_scoreTeam2",                   va( "%i to %i", newInfo->redScore, newInfo->blueScore ) );
173 		trap_Cvar_Set( "ui_scoreBase2",                   va( "%i", newInfo->baseScore ) );
174 		trap_Cvar_Set( "ui_scoreTimeBonus2",      va( "%i", newInfo->timeBonus ) );
175 		trap_Cvar_Set( "ui_scoreSkillBonus2",     va( "%i", newInfo->skillBonus ) );
176 		trap_Cvar_Set( "ui_scoreShutoutBonus2",   va( "%i", newInfo->shutoutBonus ) );
177 		trap_Cvar_Set( "ui_scoreTime2",                   va( "%02i:%02i", newInfo->time / 60, newInfo->time % 60 ) );
178 		trap_Cvar_Set( "ui_scoreCaptures2",       va( "%i", newInfo->captures ) );
179 	}
180 }
181 #endif  // #ifdef MISSIONPACK
182 
UI_LoadBestScores(const char * map,int game)183 void UI_LoadBestScores( const char *map, int game ) {
184 #ifdef MISSIONPACK
185 	char fileName[MAX_QPATH];
186 	fileHandle_t f;
187 	postGameInfo_t newInfo;
188 	int protocol, protocolLegacy;
189 
190 	memset( &newInfo, 0, sizeof( postGameInfo_t ) );
191 	Com_sprintf( fileName, MAX_QPATH, "games/%s_%i.game", map, game );
192 	if ( trap_FS_FOpenFile( fileName, &f, FS_READ ) >= 0 ) {
193 		int size = 0;
194 		trap_FS_Read( &size, sizeof( int ), f );
195 		if ( size == sizeof( postGameInfo_t ) ) {
196 			trap_FS_Read( &newInfo, sizeof( postGameInfo_t ), f );
197 		}
198 		trap_FS_FCloseFile( f );
199 	}
200 	UI_SetBestScores( &newInfo, qfalse );
201 
202 	uiInfo.demoAvailable = qfalse;
203 
204 	protocolLegacy = trap_Cvar_VariableValue("com_legacyprotocol");
205 	protocol = trap_Cvar_VariableValue("com_protocol");
206 
207 	if(!protocol)
208 		protocol = trap_Cvar_VariableValue("protocol");
209 	if(protocolLegacy == protocol)
210 		protocolLegacy = 0;
211 
212 	Com_sprintf(fileName, MAX_QPATH, "demos/%s_%d.%s%d", map, game, DEMOEXT, protocol);
213 	if(trap_FS_FOpenFile(fileName, &f, FS_READ) >= 0)
214 	{
215 		uiInfo.demoAvailable = qtrue;
216 		trap_FS_FCloseFile( f );
217 	}
218 	else if(protocolLegacy > 0)
219 	{
220 		Com_sprintf(fileName, MAX_QPATH, "demos/%s_%d.%s%d", map, game, DEMOEXT, protocolLegacy);
221 		if (trap_FS_FOpenFile(fileName, &f, FS_READ) >= 0)
222 		{
223 			uiInfo.demoAvailable = qtrue;
224 			trap_FS_FCloseFile(f);
225 		}
226 	}
227 #endif  // #ifdef MISSIONPACK
228 }
229 
230 /*
231 ===============
232 UI_ClearScores
233 ===============
234 */
UI_ClearScores(void)235 void UI_ClearScores(void) {
236 #ifdef MISSIONPACK
237 	char gameList[4096];
238 	char *gameFile;
239 	int i, len, count, size;
240 	fileHandle_t f;
241 	postGameInfo_t newInfo;
242 
243 	count = trap_FS_GetFileList( "games", "game", gameList, sizeof( gameList ) );
244 
245 	size = sizeof( postGameInfo_t );
246 	memset( &newInfo, 0, size );
247 
248 	if ( count > 0 ) {
249 		gameFile = gameList;
250 		for ( i = 0; i < count; i++ ) {
251 			len = strlen( gameFile );
252 			if ( trap_FS_FOpenFile( va( "games/%s",gameFile ), &f, FS_WRITE ) >= 0 ) {
253 				trap_FS_Write( &size, sizeof( int ), f );
254 				trap_FS_Write( &newInfo, size, f );
255 				trap_FS_FCloseFile( f );
256 			}
257 			gameFile += len + 1;
258 		}
259 	}
260 
261 	UI_SetBestScores( &newInfo, qfalse );
262 #endif  // #ifdef MISSIONPACK
263 
264 }
265 
266 
267 
UI_Cache_f(void)268 static void UI_Cache_f(void) {
269 	Display_CacheAll();
270 }
271 
272 /*
273 =======================
274 UI_CalcPostGameStats
275 =======================
276 */
UI_CalcPostGameStats(void)277 static void UI_CalcPostGameStats(void) {
278 #ifdef MISSIONPACK
279 	char map[MAX_QPATH];
280 	char fileName[MAX_QPATH];
281 	char info[MAX_INFO_STRING];
282 	fileHandle_t f;
283 	int size, game, time, adjustedTime;
284 	postGameInfo_t oldInfo;
285 	postGameInfo_t newInfo;
286 	qboolean newHigh = qfalse;
287 
288 	trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) );
289 	Q_strncpyz( map, Info_ValueForKey( info, "mapname" ), sizeof( map ) );
290 	game = atoi( Info_ValueForKey( info, "g_gametype" ) );
291 
292 	// compose file name
293 	Com_sprintf( fileName, MAX_QPATH, "games/%s_%i.game", map, game );
294 	// see if we have one already
295 	memset( &oldInfo, 0, sizeof( postGameInfo_t ) );
296 	if ( trap_FS_FOpenFile( fileName, &f, FS_READ ) >= 0 ) {
297 		// if so load it
298 		size = 0;
299 		trap_FS_Read( &size, sizeof( int ), f );
300 		if ( size == sizeof( postGameInfo_t ) ) {
301 			trap_FS_Read( &oldInfo, sizeof( postGameInfo_t ), f );
302 		}
303 		trap_FS_FCloseFile( f );
304 	}
305 
306 	newInfo.accuracy = atoi( UI_Argv( 3 ) );
307 	newInfo.impressives = atoi( UI_Argv( 4 ) );
308 	newInfo.excellents = atoi( UI_Argv( 5 ) );
309 	newInfo.defends = atoi( UI_Argv( 6 ) );
310 	newInfo.assists = atoi( UI_Argv( 7 ) );
311 	newInfo.gauntlets = atoi( UI_Argv( 8 ) );
312 	newInfo.baseScore = atoi( UI_Argv( 9 ) );
313 	newInfo.perfects = atoi( UI_Argv( 10 ) );
314 	newInfo.redScore = atoi( UI_Argv( 11 ) );
315 	newInfo.blueScore = atoi( UI_Argv( 12 ) );
316 	time = atoi( UI_Argv( 13 ) );
317 	newInfo.captures = atoi( UI_Argv( 14 ) );
318 
319 	newInfo.time = ( time - trap_Cvar_VariableValue( "ui_matchStartTime" ) ) / 1000;
320 	adjustedTime = uiInfo.mapList[ui_currentMap.integer].timeToBeat[game];
321 	if ( newInfo.time < adjustedTime ) {
322 		newInfo.timeBonus = ( adjustedTime - newInfo.time ) * 10;
323 	} else {
324 		newInfo.timeBonus = 0;
325 	}
326 
327 	if ( newInfo.redScore > newInfo.blueScore && newInfo.blueScore <= 0 ) {
328 		newInfo.shutoutBonus = 100;
329 	} else {
330 		newInfo.shutoutBonus = 0;
331 	}
332 
333 	newInfo.skillBonus = trap_Cvar_VariableValue( "g_spSkill" );
334 	if ( newInfo.skillBonus <= 0 ) {
335 		newInfo.skillBonus = 1;
336 	}
337 	newInfo.score = newInfo.baseScore + newInfo.shutoutBonus + newInfo.timeBonus;
338 	newInfo.score *= newInfo.skillBonus;
339 
340 	// see if the score is higher for this one
341 	newHigh = ( newInfo.redScore > newInfo.blueScore && newInfo.score > oldInfo.score );
342 
343 	if  ( newHigh ) {
344 		// if so write out the new one
345 		uiInfo.newHighScoreTime = uiInfo.uiDC.realTime + 20000;
346 		if ( trap_FS_FOpenFile( fileName, &f, FS_WRITE ) >= 0 ) {
347 			size = sizeof( postGameInfo_t );
348 			trap_FS_Write( &size, sizeof( int ), f );
349 			trap_FS_Write( &newInfo, sizeof( postGameInfo_t ), f );
350 			trap_FS_FCloseFile( f );
351 		}
352 	}
353 
354 	if ( newInfo.time < oldInfo.time ) {
355 		uiInfo.newBestTime = uiInfo.uiDC.realTime + 20000;
356 	}
357 
358 	// put back all the ui overrides
359 	trap_Cvar_Set( "capturelimit", UI_Cvar_VariableString( "ui_saveCaptureLimit" ) );
360 	trap_Cvar_Set( "fraglimit", UI_Cvar_VariableString( "ui_saveFragLimit" ) );
361 	trap_Cvar_Set( "cg_drawTimer", UI_Cvar_VariableString( "ui_drawTimer" ) );
362 	trap_Cvar_Set( "g_doWarmup", UI_Cvar_VariableString( "ui_doWarmup" ) );
363 	trap_Cvar_Set( "g_Warmup", UI_Cvar_VariableString( "ui_Warmup" ) );
364 	trap_Cvar_Set( "sv_pure", UI_Cvar_VariableString( "ui_pure" ) );
365 	trap_Cvar_Set( "g_friendlyFire", UI_Cvar_VariableString( "ui_friendlyFire" ) );
366 
367 	UI_SetBestScores( &newInfo, qtrue );
368 	UI_ShowPostGame( newHigh );
369 
370 #endif  // #ifdef MISSIONPACK
371 
372 }
373 
374 
375 /*
376 =================
377 UI_ConsoleCommand
378 =================
379 */
UI_ConsoleCommand(int realTime)380 qboolean UI_ConsoleCommand( int realTime ) {
381 	char    *cmd;
382 
383 	uiInfo.uiDC.frameTime = realTime - uiInfo.uiDC.realTime;
384 	uiInfo.uiDC.realTime = realTime;
385 
386 	cmd = UI_Argv( 0 );
387 
388 	// ensure minimum menu data is available
389 	//Menu_Cache();
390 
391 	if ( Q_stricmp( cmd, "ui_test" ) == 0 ) {
392 		UI_ShowPostGame( qtrue );
393 		return qtrue;
394 	}
395 
396 	if ( Q_stricmp( cmd, "ui_report" ) == 0 ) {
397 		UI_Report();
398 		return qtrue;
399 	}
400 
401 	if ( Q_stricmp( cmd, "ui_load" ) == 0 ) {
402 		UI_Load();
403 		return qtrue;
404 	}
405 
406 	if ( Q_stricmp( cmd, "remapShader" ) == 0 ) {
407 		if ( trap_Argc() == 4 ) {
408 			char shader1[MAX_QPATH];
409 			char shader2[MAX_QPATH];
410 			char shader3[MAX_QPATH];
411 			Q_strncpyz( shader1, UI_Argv( 1 ), sizeof( shader1 ) );
412 			Q_strncpyz( shader2, UI_Argv( 2 ), sizeof( shader2 ) );
413 			Q_strncpyz(shader3, UI_Argv(3), sizeof(shader3));
414 
415 			trap_R_RemapShader(shader1, shader2, shader3);
416 			return qtrue;
417 		}
418 	}
419 
420 	if ( Q_stricmp( cmd, "postgame" ) == 0 ) {
421 		UI_CalcPostGameStats();
422 		return qtrue;
423 	}
424 
425 	if ( Q_stricmp( cmd, "ui_cache" ) == 0 ) {
426 		UI_Cache_f();
427 		return qtrue;
428 	}
429 
430 	if ( Q_stricmp( cmd, "ui_teamOrders" ) == 0 ) {
431 		//UI_TeamOrdersMenu_f();
432 		return qtrue;
433 	}
434 
435 
436 	if ( Q_stricmp( cmd, "ui_cdkey" ) == 0 ) {
437 		//UI_CDKeyMenu_f();
438 		return qtrue;
439 	}
440 
441 	return qfalse;
442 }
443 
444 /*
445 =================
446 UI_Shutdown
447 =================
448 */
UI_Shutdown(void)449 void UI_Shutdown( void ) {
450 }
451 
UI_DrawNamedPic(float x,float y,float width,float height,const char * picname)452 void UI_DrawNamedPic( float x, float y, float width, float height, const char *picname ) {
453 	qhandle_t hShader;
454 
455 	hShader = trap_R_RegisterShaderNoMip( picname );
456 	UI_AdjustFrom640( &x, &y, &width, &height );
457 	trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
458 }
459 
UI_DrawHandlePic(float x,float y,float w,float h,qhandle_t hShader)460 void UI_DrawHandlePic( float x, float y, float w, float h, qhandle_t hShader ) {
461 	float s0;
462 	float s1;
463 	float t0;
464 	float t1;
465 
466 	if ( w < 0 ) {   // flip about vertical
467 		w  = -w;
468 		s0 = 1;
469 		s1 = 0;
470 	} else {
471 		s0 = 0;
472 		s1 = 1;
473 	}
474 
475 	if ( h < 0 ) {   // flip about horizontal
476 		h  = -h;
477 		t0 = 1;
478 		t1 = 0;
479 	} else {
480 		t0 = 0;
481 		t1 = 1;
482 	}
483 
484 	UI_AdjustFrom640( &x, &y, &w, &h );
485 	trap_R_DrawStretchPic( x, y, w, h, s0, t0, s1, t1, hShader );
486 }
487 
488 /*
489 ================
490 UI_FillRect
491 
492 Coordinates are 640*480 virtual values
493 =================
494 */
UI_FillRect(float x,float y,float width,float height,const float * color)495 void UI_FillRect( float x, float y, float width, float height, const float *color ) {
496 	trap_R_SetColor( color );
497 
498 	UI_AdjustFrom640( &x, &y, &width, &height );
499 	trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
500 
501 	trap_R_SetColor( NULL );
502 }
503 
UI_DrawSides(float x,float y,float w,float h)504 void UI_DrawSides( float x, float y, float w, float h ) {
505 	UI_AdjustFrom640( &x, &y, &w, &h );
506 	trap_R_DrawStretchPic( x, y, 1, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
507 	trap_R_DrawStretchPic( x + w - 1, y, 1, h, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
508 }
509 
UI_DrawTopBottom(float x,float y,float w,float h)510 void UI_DrawTopBottom( float x, float y, float w, float h ) {
511 	UI_AdjustFrom640( &x, &y, &w, &h );
512 	trap_R_DrawStretchPic( x, y, w, 1, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
513 	trap_R_DrawStretchPic( x, y + h - 1, w, 1, 0, 0, 0, 0, uiInfo.uiDC.whiteShader );
514 }
515 /*
516 ================
517 UI_DrawRect
518 
519 Coordinates are 640*480 virtual values
520 =================
521 */
UI_DrawRect(float x,float y,float width,float height,const float * color)522 void UI_DrawRect( float x, float y, float width, float height, const float *color ) {
523 	trap_R_SetColor( color );
524 
525 	UI_DrawTopBottom( x, y, width, height );
526 	UI_DrawSides( x, y, width, height );
527 
528 	trap_R_SetColor( NULL );
529 }
530 
UI_SetColor(const float * rgba)531 void UI_SetColor( const float *rgba ) {
532 	trap_R_SetColor( rgba );
533 }
534 
UI_UpdateScreen(void)535 void UI_UpdateScreen( void ) {
536 	trap_UpdateScreen();
537 }
538 
539 
UI_DrawTextBox(int x,int y,int width,int lines)540 void UI_DrawTextBox( int x, int y, int width, int lines ) {
541 	UI_FillRect( x + BIGCHAR_WIDTH / 2, y + BIGCHAR_HEIGHT / 2, ( width + 1 ) * BIGCHAR_WIDTH, ( lines + 1 ) * BIGCHAR_HEIGHT, colorBlack );
542 	UI_DrawRect( x + BIGCHAR_WIDTH / 2, y + BIGCHAR_HEIGHT / 2, ( width + 1 ) * BIGCHAR_WIDTH, ( lines + 1 ) * BIGCHAR_HEIGHT, colorWhite );
543 }
544 
UI_CursorInRect(int x,int y,int width,int height)545 qboolean UI_CursorInRect( int x, int y, int width, int height ) {
546 	if ( uiInfo.uiDC.cursorx < x ||
547 		 uiInfo.uiDC.cursory < y ||
548 		 uiInfo.uiDC.cursorx > x + width ||
549 		 uiInfo.uiDC.cursory > y + height ) {
550 		return qfalse;
551 	}
552 
553 	return qtrue;
554 }
555