X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=common.c;h=efea48511f9f20c4e4951563c91cabd8fe37159e;hp=f568a828ea60f9812b2170a0a2d51f0dd389701f;hb=7d08a8ba9d7925d79b903a087b97357968e011de;hpb=182f5dd46097dc11b3643dc2376b4dd6a4fa42c7 diff --git a/common.c b/common.c index f568a828..efea4851 100644 --- a/common.c +++ b/common.c @@ -27,18 +27,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -cvar_t registered = {0, "registered","0"}; -cvar_t cmdline = {0, "cmdline","0"}; +cvar_t registered = {0, "registered","0", "indicates if this is running registered quake (whether gfx/qpop.lmp was found)"}; +cvar_t cmdline = {0, "cmdline","0", "contains commandline the engine was launched with"}; extern qboolean fs_modified; // set true if using non-id files -char com_token[1024]; +char com_token[MAX_INPUTLINE]; int com_argc; const char **com_argv; -// LordHavoc: made commandline 1024 characters instead of 256 -#define CMDLINE_LENGTH 1024 -char com_cmdline[CMDLINE_LENGTH]; +char com_cmdline[MAX_INPUTLINE]; gamemode_t gamemode; const char *gamename; @@ -59,7 +57,7 @@ char com_modname[MAX_OSPATH] = ""; short ShortSwap (short l) { - qbyte b1,b2; + unsigned char b1,b2; b1 = l&255; b2 = (l>>8)&255; @@ -69,7 +67,7 @@ short ShortSwap (short l) int LongSwap (int l) { - qbyte b1,b2,b3,b4; + unsigned char b1,b2,b3,b4; b1 = l&255; b2 = (l>>8)&255; @@ -84,7 +82,7 @@ float FloatSwap (float f) union { float f; - qbyte b[4]; + unsigned char b[4]; } dat1, dat2; @@ -99,22 +97,22 @@ float FloatSwap (float f) // Extract integers from buffers -unsigned int BuffBigLong (const qbyte *buffer) +unsigned int BuffBigLong (const unsigned char *buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } -unsigned short BuffBigShort (const qbyte *buffer) +unsigned short BuffBigShort (const unsigned char *buffer) { return (buffer[0] << 8) | buffer[1]; } -unsigned int BuffLittleLong (const qbyte *buffer) +unsigned int BuffLittleLong (const unsigned char *buffer) { return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0]; } -unsigned short BuffLittleShort (const qbyte *buffer) +unsigned short BuffLittleShort (const unsigned char *buffer) { return (buffer[1] << 8) | buffer[0]; } @@ -171,7 +169,7 @@ static unsigned short crctable[256] = 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; -unsigned short CRC_Block(qbyte *data, int size) +unsigned short CRC_Block(const unsigned char *data, size_t size) { unsigned short crc = CRC_INIT_VALUE; while (size--) @@ -179,6 +177,65 @@ unsigned short CRC_Block(qbyte *data, int size) return crc ^ CRC_XOR_VALUE; } +// QuakeWorld +static unsigned char chktbl[1024 + 4] = +{ + 0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01, + 0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a, + 0x64,0xed,0x5c,0x99,0x29,0x87,0xa8,0x78,0x59,0x0d,0xaa,0x0f,0x25,0x0a,0x5c,0x58, + 0xfb,0x00,0xa7,0xa8,0x8a,0x1d,0x86,0x80,0xc5,0x1f,0xd2,0x28,0x69,0x71,0x58,0xc3, + 0x51,0x90,0xe1,0xf8,0x6a,0xf3,0x8f,0xb0,0x68,0xdf,0x95,0x40,0x5c,0xe4,0x24,0x6b, + 0x29,0x19,0x71,0x3f,0x42,0x63,0x6c,0x48,0xe7,0xad,0xa8,0x4b,0x91,0x8f,0x42,0x36, + 0x34,0xe7,0x32,0x55,0x59,0x2d,0x36,0x38,0x38,0x59,0x9b,0x08,0x16,0x4d,0x8d,0xf8, + 0x0a,0xa4,0x52,0x01,0xbb,0x52,0xa9,0xfd,0x40,0x18,0x97,0x37,0xff,0xc9,0x82,0x27, + 0xb2,0x64,0x60,0xce,0x00,0xd9,0x04,0xf0,0x9e,0x99,0xbd,0xce,0x8f,0x90,0x4a,0xdd, + 0xe1,0xec,0x19,0x14,0xb1,0xfb,0xca,0x1e,0x98,0x0f,0xd4,0xcb,0x80,0xd6,0x05,0x63, + 0xfd,0xa0,0x74,0xa6,0x86,0xf6,0x19,0x98,0x76,0x27,0x68,0xf7,0xe9,0x09,0x9a,0xf2, + 0x2e,0x42,0xe1,0xbe,0x64,0x48,0x2a,0x74,0x30,0xbb,0x07,0xcc,0x1f,0xd4,0x91,0x9d, + 0xac,0x55,0x53,0x25,0xb9,0x64,0xf7,0x58,0x4c,0x34,0x16,0xbc,0xf6,0x12,0x2b,0x65, + 0x68,0x25,0x2e,0x29,0x1f,0xbb,0xb9,0xee,0x6d,0x0c,0x8e,0xbb,0xd2,0x5f,0x1d,0x8f, + 0xc1,0x39,0xf9,0x8d,0xc0,0x39,0x75,0xcf,0x25,0x17,0xbe,0x96,0xaf,0x98,0x9f,0x5f, + 0x65,0x15,0xc4,0x62,0xf8,0x55,0xfc,0xab,0x54,0xcf,0xdc,0x14,0x06,0xc8,0xfc,0x42, + 0xd3,0xf0,0xad,0x10,0x08,0xcd,0xd4,0x11,0xbb,0xca,0x67,0xc6,0x48,0x5f,0x9d,0x59, + 0xe3,0xe8,0x53,0x67,0x27,0x2d,0x34,0x9e,0x9e,0x24,0x29,0xdb,0x69,0x99,0x86,0xf9, + 0x20,0xb5,0xbb,0x5b,0xb0,0xf9,0xc3,0x67,0xad,0x1c,0x9c,0xf7,0xcc,0xef,0xce,0x69, + 0xe0,0x26,0x8f,0x79,0xbd,0xca,0x10,0x17,0xda,0xa9,0x88,0x57,0x9b,0x15,0x24,0xba, + 0x84,0xd0,0xeb,0x4d,0x14,0xf5,0xfc,0xe6,0x51,0x6c,0x6f,0x64,0x6b,0x73,0xec,0x85, + 0xf1,0x6f,0xe1,0x67,0x25,0x10,0x77,0x32,0x9e,0x85,0x6e,0x69,0xb1,0x83,0x00,0xe4, + 0x13,0xa4,0x45,0x34,0x3b,0x40,0xff,0x41,0x82,0x89,0x79,0x57,0xfd,0xd2,0x8e,0xe8, + 0xfc,0x1d,0x19,0x21,0x12,0x00,0xd7,0x66,0xe5,0xc7,0x10,0x1d,0xcb,0x75,0xe8,0xfa, + 0xb6,0xee,0x7b,0x2f,0x1a,0x25,0x24,0xb9,0x9f,0x1d,0x78,0xfb,0x84,0xd0,0x17,0x05, + 0x71,0xb3,0xc8,0x18,0xff,0x62,0xee,0xed,0x53,0xab,0x78,0xd3,0x65,0x2d,0xbb,0xc7, + 0xc1,0xe7,0x70,0xa2,0x43,0x2c,0x7c,0xc7,0x16,0x04,0xd2,0x45,0xd5,0x6b,0x6c,0x7a, + 0x5e,0xa1,0x50,0x2e,0x31,0x5b,0xcc,0xe8,0x65,0x8b,0x16,0x85,0xbf,0x82,0x83,0xfb, + 0xde,0x9f,0x36,0x48,0x32,0x79,0xd6,0x9b,0xfb,0x52,0x45,0xbf,0x43,0xf7,0x0b,0x0b, + 0x19,0x19,0x31,0xc3,0x85,0xec,0x1d,0x8c,0x20,0xf0,0x3a,0xfa,0x80,0x4d,0x2c,0x7d, + 0xac,0x60,0x09,0xc0,0x40,0xee,0xb9,0xeb,0x13,0x5b,0xe8,0x2b,0xb1,0x20,0xf0,0xce, + 0x4c,0xbd,0xc6,0x04,0x86,0x70,0xc6,0x33,0xc3,0x15,0x0f,0x65,0x19,0xfd,0xc2,0xd3, + + // map checksum goes here + 0x00,0x00,0x00,0x00 +}; + +// QuakeWorld +unsigned char COM_BlockSequenceCRCByteQW(unsigned char *base, int length, int sequence) +{ + unsigned char *p; + unsigned char chkb[60 + 4]; + + p = chktbl + (sequence % (sizeof(chktbl) - 8)); + + if (length > 60) + length = 60; + memcpy(chkb, base, length); + + chkb[length] = (sequence & 0xff) ^ p[0]; + chkb[length+1] = p[1]; + chkb[length+2] = ((sequence>>8) & 0xff) ^ p[2]; + chkb[length+3] = p[3]; + + return CRC_Block(chkb, length + 4) & 0xff; +} /* ============================================================================== @@ -195,7 +252,7 @@ Handles byte ordering and avoids alignment errors void MSG_WriteChar (sizebuf_t *sb, int c) { - qbyte *buf; + unsigned char *buf; buf = SZ_GetSpace (sb, 1); buf[0] = c; @@ -203,7 +260,7 @@ void MSG_WriteChar (sizebuf_t *sb, int c) void MSG_WriteByte (sizebuf_t *sb, int c) { - qbyte *buf; + unsigned char *buf; buf = SZ_GetSpace (sb, 1); buf[0] = c; @@ -211,7 +268,7 @@ void MSG_WriteByte (sizebuf_t *sb, int c) void MSG_WriteShort (sizebuf_t *sb, int c) { - qbyte *buf; + unsigned char *buf; buf = SZ_GetSpace (sb, 2); buf[0] = c&0xff; @@ -220,7 +277,7 @@ void MSG_WriteShort (sizebuf_t *sb, int c) void MSG_WriteLong (sizebuf_t *sb, int c) { - qbyte *buf; + unsigned char *buf; buf = SZ_GetSpace (sb, 4); buf[0] = c&0xff; @@ -241,15 +298,21 @@ void MSG_WriteFloat (sizebuf_t *sb, float f) dat.f = f; dat.l = LittleLong (dat.l); - SZ_Write (sb, &dat.l, 4); + SZ_Write (sb, (unsigned char *)&dat.l, 4); } void MSG_WriteString (sizebuf_t *sb, const char *s) { if (!s) - SZ_Write (sb, "", 1); + SZ_Write (sb, (unsigned char *)"", 1); else - SZ_Write (sb, s, strlen(s)+1); + SZ_Write (sb, (unsigned char *)s, (int)strlen(s)+1); +} + +void MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s) +{ + if (s) + SZ_Write (sb, (unsigned char *)s, (int)strlen(s)); } void MSG_WriteCoord13i (sizebuf_t *sb, float f) @@ -273,19 +336,19 @@ void MSG_WriteCoord32f (sizebuf_t *sb, float f) MSG_WriteFloat (sb, f); } -void MSG_WriteCoord (sizebuf_t *sb, float f, int protocol) +void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol) { - if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_NEHAHRAMOVIE) + if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_QUAKEWORLD) MSG_WriteCoord13i (sb, f); - else if (protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6) + else if (protocol == PROTOCOL_DARKPLACES1) MSG_WriteCoord32f (sb, f); else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4) MSG_WriteCoord16i (sb, f); else - Host_Error("MSG_WriteCoord: unknown protocol\n"); + MSG_WriteCoord32f (sb, f); } -void MSG_WriteVector (sizebuf_t *sb, float *v, int protocol) +void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol) { MSG_WriteCoord (sb, v[0], protocol); MSG_WriteCoord (sb, v[1], protocol); @@ -314,12 +377,12 @@ void MSG_WriteAngle32f (sizebuf_t *sb, float f) MSG_WriteFloat (sb, f); } -void MSG_WriteAngle (sizebuf_t *sb, float f, int protocol) +void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol) { - if (protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6) - MSG_WriteAngle16i (sb, f); - else + if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD) MSG_WriteAngle8i (sb, f); + else + MSG_WriteAngle16i (sb, f); } // @@ -414,9 +477,9 @@ float MSG_ReadBigFloat (void) char *MSG_ReadString (void) { - static char string[2048]; + static char string[MAX_INPUTLINE]; int l,c; - for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadChar()) != -1 && c != 0;l++) + for (l = 0;l < (int) sizeof(string) - 1 && (c = MSG_ReadByte()) != -1 && c != 0;l++) string[l] = c; string[l] = 0; return string; @@ -425,7 +488,7 @@ char *MSG_ReadString (void) int MSG_ReadBytes (int numbytes, unsigned char *out) { int l, c; - for (l = 0;l < numbytes && (c = MSG_ReadChar()) != -1;l++) + for (l = 0;l < numbytes && (c = MSG_ReadByte()) != -1;l++) out[l] = c; return l; } @@ -445,19 +508,19 @@ float MSG_ReadCoord32f (void) return MSG_ReadLittleFloat(); } -float MSG_ReadCoord (int protocol) +float MSG_ReadCoord (protocolversion_t protocol) { - if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_NEHAHRAMOVIE) + if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_QUAKEWORLD) return MSG_ReadCoord13i(); - else if (protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6) + else if (protocol == PROTOCOL_DARKPLACES1) return MSG_ReadCoord32f(); else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4) return MSG_ReadCoord16i(); - Host_Error("MSG_ReadCoord: unknown protocol\n"); - return 0; + else + return MSG_ReadCoord32f(); } -void MSG_ReadVector (float *v, int protocol) +void MSG_ReadVector (float *v, protocolversion_t protocol) { v[0] = MSG_ReadCoord(protocol); v[1] = MSG_ReadCoord(protocol); @@ -480,12 +543,12 @@ float MSG_ReadAngle32f (void) return MSG_ReadFloat (); } -float MSG_ReadAngle (int protocol) +float MSG_ReadAngle (protocolversion_t protocol) { - if (protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6) - return MSG_ReadAngle16i (); - else + if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD) return MSG_ReadAngle8i (); + else + return MSG_ReadAngle16i (); } @@ -496,17 +559,17 @@ void SZ_Clear (sizebuf_t *buf) buf->cursize = 0; } -void *SZ_GetSpace (sizebuf_t *buf, int length) +unsigned char *SZ_GetSpace (sizebuf_t *buf, int length) { - void *data; + unsigned char *data; if (buf->cursize + length > buf->maxsize) { if (!buf->allowoverflow) - Host_Error ("SZ_GetSpace: overflow without allowoverflow set\n"); + Host_Error ("SZ_GetSpace: overflow without allowoverflow set"); if (length > buf->maxsize) - Host_Error ("SZ_GetSpace: %i is > full buffer size\n", length); + Host_Error ("SZ_GetSpace: %i is > full buffer size", length); buf->overflowed = true; Con_Print("SZ_GetSpace: overflow\n"); @@ -519,7 +582,7 @@ void *SZ_GetSpace (sizebuf_t *buf, int length) return data; } -void SZ_Write (sizebuf_t *buf, const void *data, int length) +void SZ_Write (sizebuf_t *buf, const unsigned char *data, int length) { memcpy (SZ_GetSpace(buf,length),data,length); } @@ -529,12 +592,12 @@ void SZ_Write (sizebuf_t *buf, const void *data, int length) // all of darkplaces. static char *hexchar = "0123456789ABCDEF"; -void Com_HexDumpToConsole(const qbyte *data, int size) +void Com_HexDumpToConsole(const unsigned char *data, int size) { int i, j, n; char text[1024]; char *cur, *flushpointer; - const qbyte *d; + const unsigned char *d; cur = text; flushpointer = text + 512; for (i = 0;i < size;) @@ -783,7 +846,6 @@ skipwhite: } com_token[len] = 0; *datapointer = data+1; - return true; } else { @@ -800,8 +862,9 @@ skipwhite: } com_token[len] = 0; *datapointer = data; - return true; } + + return true; } @@ -842,7 +905,7 @@ void COM_CheckRegistered (void) { Cvar_Set ("cmdline", com_cmdline); - if (!FS_FileExists("gfx/pop.lmp")) + if (gamemode == GAME_NORMAL && !FS_FileExists("gfx/pop.lmp")) { if (fs_modified) Con_Print("Playing shareware version, with modification.\nwarning: most mods require full quake data.\n"); @@ -873,16 +936,16 @@ void COM_InitArgv (void) { // arg contains whitespace, store quotes around it com_cmdline[n++] = '\"'; - while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i]) + while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i]) com_cmdline[n++] = com_argv[j][i++]; com_cmdline[n++] = '\"'; } else { - while ((n < (CMDLINE_LENGTH - 1)) && com_argv[j][i]) + while ((n < ((int)sizeof(com_cmdline) - 1)) && com_argv[j][i]) com_cmdline[n++] = com_argv[j][i++]; } - if (n < (CMDLINE_LENGTH - 1)) + if (n < ((int)sizeof(com_cmdline) - 1)) com_cmdline[n++] = ' '; else break; @@ -895,7 +958,7 @@ void COM_InitArgv (void) // Game mods -typedef struct +typedef struct gamemode_info_s { const char* prog_name; const char* cmdline; @@ -938,7 +1001,7 @@ static const gamemode_info_t gamemode_info [] = { "battlemech", "-battlemech", "Battlemech", "base", NULL, "battlemech", "battlemech" }, // GAME_ZYMOTIC // COMMANDLINEOPTION: Game: -zymotic runs the singleplayer game Zymotic -{ "zymotic", "-zymotic", "Zymotic", "data", NULL, "zymotic", "zymotic" }, +{ "zymotic", "-zymotic", "Zymotic", "basezym", NULL, "zymotic", "zymotic" }, // GAME_FNIGGIUM // COMMANDLINEOPTION: Game: -fniggium runs the post apocalyptic melee RPG Fniggium { "fniggium", "-fniggium", "Fniggium", "data", NULL, "fniggium", "fniggium" }, @@ -956,16 +1019,19 @@ static const gamemode_info_t gamemode_info [] = { "neoteric", "-neoteric", "Neoteric", "id1", "neobase", "neo", "darkplaces" }, // GAME_OPENQUARTZ // COMMANDLINEOPTION: Game: -openquartz runs the game OpenQuartz, a standalone GPL replacement of the quake content -{ "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces"}, +{ "openquartz", "-openquartz", "OpenQuartz", "id1", NULL, "openquartz", "darkplaces" }, // GAME_PRYDON // COMMANDLINEOPTION: Game: -prydon runs the topdown point and click action-RPG Prydon Gate -{ "prydon", "-prydon", "PrydonGate", "id1", "prydon", "prydon", "darkplaces"}, +{ "prydon", "-prydon", "PrydonGate", "id1", "prydon", "prydon", "darkplaces" }, // GAME_NETHERWORLD -// COMMANDLINEOPTION: Game: -netherworld runs the game Netherworld: Dark Masters -{ "netherworld", "-netherworld", "Dark Masters", "id1", "netherworld", "nw", "darkplaces"}, +// COMMANDLINEOPTION: Game: -netherworld runs the game Netherworld: Dark Master +{ "netherworld", "-netherworld", "Netherworld: Dark Master", "id1", "netherworld", "nw", "darkplaces" }, // GAME_THEHUNTED -// COMMANDLINEOPTION: Game: -netherworld runs the game The Hunted -{ "thehunted", "-thehunted", "The Hunted", "thdata", NULL, "th", "thehunted"}, +// COMMANDLINEOPTION: Game: -thehunted runs the game The Hunted +{ "thehunted", "-thehunted", "The Hunted", "thdata", NULL, "th", "thehunted" }, +// GAME_DEFEATINDETAIL2 +// COMMANDLINEOPTION: Game: -did2 runs the game Defeat In Detail 2 +{ "did2", "-did2", "Defeat In Detail 2", "data", NULL, "did2_", "did2" }, }; void COM_InitGameType (void) @@ -981,7 +1047,7 @@ void COM_InitGameType (void) for (i = 1; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++) if (strstr (name, gamemode_info[i].prog_name)) { - gamemode = i; + gamemode = (gamemode_t)i; break; } @@ -989,7 +1055,7 @@ void COM_InitGameType (void) for (i = 0; i < sizeof (gamemode_info) / sizeof (gamemode_info[0]); i++) if (COM_CheckParm (gamemode_info[i].cmdline)) { - gamemode = i; + gamemode = (gamemode_t)i; break; } @@ -1131,7 +1197,7 @@ int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *t l = *text; commentprefixlength = 0; if (commentprefix) - commentprefixlength = strlen(commentprefix); + commentprefixlength = (int)strlen(commentprefix); while (*l && *l != '\n' && *l != '\r') { if (*l > ' ') @@ -1188,8 +1254,8 @@ int COM_ReadAndTokenizeLine(const char **text, char **argv, int maxargc, char *t // written by Elric, thanks Elric! char *SearchInfostring(const char *infostring, const char *key) { - static char value [256]; - char crt_key [256]; + static char value [MAX_INPUTLINE]; + char crt_key [MAX_INPUTLINE]; size_t value_ind, key_ind; char c; @@ -1247,6 +1313,139 @@ char *SearchInfostring(const char *infostring, const char *key) } } +void InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuelength) +{ + int pos = 0, j; + size_t keylength; + if (!key) + key = ""; + if (!value) + value = ""; + keylength = strlen(key); + if (valuelength < 1 || !value) + { + Con_Printf("InfoString_GetValue: no room in value\n"); + return; + } + value[0] = 0; + if (strchr(key, '\\')) + { + Con_Printf("InfoString_GetValue: key name \"%s\" contains \\ which is not possible in an infostring\n", key); + return; + } + if (strchr(key, '\"')) + { + Con_Printf("InfoString_SetValue: key name \"%s\" contains \" which is not allowed in an infostring\n", key); + return; + } + if (!key[0]) + { + Con_Printf("InfoString_GetValue: can not look up a key with no name\n"); + return; + } + while (buffer[pos] == '\\') + { + if (!memcmp(buffer + pos+1, key, keylength)) + { + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + pos++; + for (j = 0;buffer[pos+j] && buffer[pos+j] != '\\' && j < (int)valuelength - 1;j++) + value[j] = buffer[pos+j]; + value[j] = 0; + return; + } + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + } + // if we reach this point the key was not found +} + +void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value) +{ + int pos = 0, pos2; + size_t keylength; + if (!key) + key = ""; + if (!value) + value = ""; + keylength = strlen(key); + if (strchr(key, '\\') || strchr(value, '\\')) + { + Con_Printf("InfoString_SetValue: \"%s\" \"%s\" contains \\ which is not possible to store in an infostring\n", key, value); + return; + } + if (strchr(key, '\"') || strchr(value, '\"')) + { + Con_Printf("InfoString_SetValue: \"%s\" \"%s\" contains \" which is not allowed in an infostring\n", key, value); + return; + } + if (!key[0]) + { + Con_Printf("InfoString_SetValue: can not set a key with no name\n"); + return; + } + while (buffer[pos] == '\\') + { + if (!memcmp(buffer + pos+1, key, keylength)) + break; + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + for (pos++;buffer[pos] && buffer[pos] != '\\';pos++); + } + // if we found the key, find the end of it because we will be replacing it + pos2 = pos; + if (buffer[pos] == '\\') + { + for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos2++); + for (pos2++;buffer[pos2] && buffer[pos2] != '\\';pos2++); + } + if (bufferlength <= 1 + strlen(key) + 1 + strlen(value) + strlen(buffer + pos2)) + { + Con_Printf("InfoString_SetValue: no room for \"%s\" \"%s\" in infostring\n", key, value); + return; + } + if (value && value[0]) + { + // set the key/value and append the remaining text + char tempbuffer[4096]; + strlcpy(tempbuffer, buffer + pos2, sizeof(tempbuffer)); + sprintf(buffer + pos, "\\%s\\%s%s", key, value, tempbuffer); + } + else + { + // just remove the key from the text + strcpy(buffer + pos, buffer + pos2); + } +} + +void InfoString_Print(char *buffer) +{ + int i; + char key[2048]; + char value[2048]; + while (*buffer) + { + if (*buffer != '\\') + { + Con_Printf("InfoString_Print: corrupt string\n"); + return; + } + for (buffer++, i = 0;*buffer && *buffer != '\\';buffer++) + if (i < (int)sizeof(key)-1) + key[i++] = *buffer; + key[i] = 0; + if (*buffer != '\\') + { + Con_Printf("InfoString_Print: corrupt string\n"); + return; + } + for (buffer++, i = 0;*buffer && *buffer != '\\';buffer++) + if (i < (int)sizeof(value)-1) + value[i++] = *buffer; + value[i] = 0; + // empty value is an error case + Con_Printf("%20s %s\n", key, value[0] ? value : "NO VALUE"); + } +} //======================================================== // strlcat and strlcpy, from OpenBSD