📄 ui_shared.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
// string allocation/managment
#include "ui_shared.h"
#define SCROLL_TIME_START 500
#define SCROLL_TIME_ADJUST 150
#define SCROLL_TIME_ADJUSTOFFSET 40
#define SCROLL_TIME_FLOOR 20
typedef struct scrollInfo_s {
int nextScrollTime;
int nextAdjustTime;
int adjustValue;
int scrollKey;
float xStart;
float yStart;
itemDef_t *item;
qboolean scrollDir;
} scrollInfo_t;
static scrollInfo_t scrollInfo;
static void (*captureFunc) (void *p) = NULL;
static void *captureData = NULL;
static itemDef_t *itemCapture = NULL; // item that has the mouse captured ( if any )
displayContextDef_t *DC = NULL;
static qboolean g_waitingForKey = qfalse;
static qboolean g_editingField = qfalse;
static itemDef_t *g_bindItem = NULL;
static itemDef_t *g_editItem = NULL;
menuDef_t Menus[MAX_MENUS]; // defined menus
int menuCount = 0; // how many
menuDef_t *menuStack[MAX_OPEN_MENUS];
int openMenuCount = 0;
static qboolean debugMode = qfalse;
#define DOUBLE_CLICK_DELAY 300
static int lastListBoxClickTime = 0;
void Item_RunScript(itemDef_t *item, const char *s);
void Item_SetupKeywordHash(void);
void Menu_SetupKeywordHash(void);
int BindingIDFromName(const char *name);
qboolean Item_Bind_HandleKey(itemDef_t *item, int key, qboolean down);
itemDef_t *Menu_SetPrevCursorItem(menuDef_t *menu);
itemDef_t *Menu_SetNextCursorItem(menuDef_t *menu);
static qboolean Menu_OverActiveItem(menuDef_t *menu, float x, float y);
#ifdef CGAME
#define MEM_POOL_SIZE 128 * 1024
#else
#define MEM_POOL_SIZE 1024 * 1024
#endif
static char memoryPool[MEM_POOL_SIZE];
static int allocPoint, outOfMemory;
/*
===============
UI_Alloc
===============
*/
void *UI_Alloc( int size ) {
char *p;
if ( allocPoint + size > MEM_POOL_SIZE ) {
outOfMemory = qtrue;
if (DC->Print) {
DC->Print("UI_Alloc: Failure. Out of memory!\n");
}
//DC->trap_Print(S_COLOR_YELLOW"WARNING: UI Out of Memory!\n");
return NULL;
}
p = &memoryPool[allocPoint];
allocPoint += ( size + 15 ) & ~15;
return p;
}
/*
===============
UI_InitMemory
===============
*/
void UI_InitMemory( void ) {
allocPoint = 0;
outOfMemory = qfalse;
}
qboolean UI_OutOfMemory() {
return outOfMemory;
}
#define HASH_TABLE_SIZE 2048
/*
================
return a hash value for the string
================
*/
static long hashForString(const char *str) {
int i;
long hash;
char letter;
hash = 0;
i = 0;
while (str[i] != '\0') {
letter = tolower(str[i]);
hash+=(long)(letter)*(i+119);
i++;
}
hash &= (HASH_TABLE_SIZE-1);
return hash;
}
typedef struct stringDef_s {
struct stringDef_s *next;
const char *str;
} stringDef_t;
static int strPoolIndex = 0;
static char strPool[STRING_POOL_SIZE];
static int strHandleCount = 0;
static stringDef_t *strHandle[HASH_TABLE_SIZE];
const char *String_Alloc(const char *p) {
int len;
long hash;
stringDef_t *str, *last;
static const char *staticNULL = "";
if (p == NULL) {
return NULL;
}
if (*p == 0) {
return staticNULL;
}
hash = hashForString(p);
str = strHandle[hash];
while (str) {
if (strcmp(p, str->str) == 0) {
return str->str;
}
str = str->next;
}
len = strlen(p);
if (len + strPoolIndex + 1 < STRING_POOL_SIZE) {
int ph = strPoolIndex;
strcpy(&strPool[strPoolIndex], p);
strPoolIndex += len + 1;
str = strHandle[hash];
last = str;
while (str && str->next) {
last = str;
str = str->next;
}
str = UI_Alloc(sizeof(stringDef_t));
str->next = NULL;
str->str = &strPool[ph];
if (last) {
last->next = str;
} else {
strHandle[hash] = str;
}
return &strPool[ph];
}
return NULL;
}
void String_Report() {
float f;
Com_Printf("Memory/String Pool Info\n");
Com_Printf("----------------\n");
f = strPoolIndex;
f /= STRING_POOL_SIZE;
f *= 100;
Com_Printf("String Pool is %.1f%% full, %i bytes out of %i used.\n", f, strPoolIndex, STRING_POOL_SIZE);
f = allocPoint;
f /= MEM_POOL_SIZE;
f *= 100;
Com_Printf("Memory Pool is %.1f%% full, %i bytes out of %i used.\n", f, allocPoint, MEM_POOL_SIZE);
}
/*
=================
String_Init
=================
*/
void String_Init() {
int i;
for (i = 0; i < HASH_TABLE_SIZE; i++) {
strHandle[i] = 0;
}
strHandleCount = 0;
strPoolIndex = 0;
menuCount = 0;
openMenuCount = 0;
UI_InitMemory();
Item_SetupKeywordHash();
Menu_SetupKeywordHash();
if (DC && DC->getBindingBuf) {
Controls_GetConfig();
}
}
/*
=================
PC_SourceWarning
=================
*/
void PC_SourceWarning(int handle, char *format, ...) {
int line;
char filename[128];
va_list argptr;
static char string[4096];
va_start (argptr, format);
vsprintf (string, format, argptr);
va_end (argptr);
filename[0] = '\0';
line = 0;
trap_PC_SourceFileAndLine(handle, filename, &line);
Com_Printf(S_COLOR_YELLOW "WARNING: %s, line %d: %s\n", filename, line, string);
}
/*
=================
PC_SourceError
=================
*/
void PC_SourceError(int handle, char *format, ...) {
int line;
char filename[128];
va_list argptr;
static char string[4096];
va_start (argptr, format);
vsprintf (string, format, argptr);
va_end (argptr);
filename[0] = '\0';
line = 0;
trap_PC_SourceFileAndLine(handle, filename, &line);
Com_Printf(S_COLOR_RED "ERROR: %s, line %d: %s\n", filename, line, string);
}
/*
=================
LerpColor
=================
*/
void LerpColor(vec4_t a, vec4_t b, vec4_t c, float t)
{
int i;
// lerp and clamp each component
for (i=0; i<4; i++)
{
c[i] = a[i] + t*(b[i]-a[i]);
if (c[i] < 0)
c[i] = 0;
else if (c[i] > 1.0)
c[i] = 1.0;
}
}
/*
=================
Float_Parse
=================
*/
qboolean Float_Parse(char **p, float *f) {
char *token;
token = COM_ParseExt(p, qfalse);
if (token && token[0] != 0) {
*f = atof(token);
return qtrue;
} else {
return qfalse;
}
}
/*
=================
PC_Float_Parse
=================
*/
qboolean PC_Float_Parse(int handle, float *f) {
pc_token_t token;
int negative = qfalse;
if (!trap_PC_ReadToken(handle, &token))
return qfalse;
if (token.string[0] == '-') {
if (!trap_PC_ReadToken(handle, &token))
return qfalse;
negative = qtrue;
}
if (token.type != TT_NUMBER) {
PC_SourceError(handle, "expected float but found %s\n", token.string);
return qfalse;
}
if (negative)
*f = -token.floatvalue;
else
*f = token.floatvalue;
return qtrue;
}
/*
=================
Color_Parse
=================
*/
qboolean Color_Parse(char **p, vec4_t *c) {
int i;
float f;
for (i = 0; i < 4; i++) {
if (!Float_Parse(p, &f)) {
return qfalse;
}
(*c)[i] = f;
}
return qtrue;
}
/*
=================
PC_Color_Parse
=================
*/
qboolean PC_Color_Parse(int handle, vec4_t *c) {
int i;
float f;
for (i = 0; i < 4; i++) {
if (!PC_Float_Parse(handle, &f)) {
return qfalse;
}
(*c)[i] = f;
}
return qtrue;
}
/*
=================
Int_Parse
=================
*/
qboolean Int_Parse(char **p, int *i) {
char *token;
token = COM_ParseExt(p, qfalse);
if (token && token[0] != 0) {
*i = atoi(token);
return qtrue;
} else {
return qfalse;
}
}
/*
=================
PC_Int_Parse
=================
*/
qboolean PC_Int_Parse(int handle, int *i) {
pc_token_t token;
int negative = qfalse;
if (!trap_PC_ReadToken(handle, &token))
return qfalse;
if (token.string[0] == '-') {
if (!trap_PC_ReadToken(handle, &token))
return qfalse;
negative = qtrue;
}
if (token.type != TT_NUMBER) {
PC_SourceError(handle, "expected integer but found %s\n", token.string);
return qfalse;
}
*i = token.intvalue;
if (negative)
*i = - *i;
return qtrue;
}
/*
=================
Rect_Parse
=================
*/
qboolean Rect_Parse(char **p, rectDef_t *r) {
if (Float_Parse(p, &r->x)) {
if (Float_Parse(p, &r->y)) {
if (Float_Parse(p, &r->w)) {
if (Float_Parse(p, &r->h)) {
return qtrue;
}
}
}
}
return qfalse;
}
/*
=================
PC_Rect_Parse
=================
*/
qboolean PC_Rect_Parse(int handle, rectDef_t *r) {
if (PC_Float_Parse(handle, &r->x)) {
if (PC_Float_Parse(handle, &r->y)) {
if (PC_Float_Parse(handle, &r->w)) {
if (PC_Float_Parse(handle, &r->h)) {
return qtrue;
}
}
}
}
return qfalse;
}
/*
=================
String_Parse
=================
*/
qboolean String_Parse(char **p, const char **out) {
char *token;
token = COM_ParseExt(p, qfalse);
if (token && token[0] != 0) {
*(out) = String_Alloc(token);
return qtrue;
}
return qfalse;
}
/*
=================
PC_String_Parse
=================
*/
qboolean PC_String_Parse(int handle, const char **out) {
pc_token_t token;
if (!trap_PC_ReadToken(handle, &token))
return qfalse;
*(out) = String_Alloc(token.string);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -