コード例 #1
0
ファイル: stats_grid.c プロジェクト: jite/jquake
void StatsGrid_Remove(stats_weight_grid_t **grid)
{
	int row;

	// Nothing to remove.
	if((*grid) == NULL)
	{
		return;
	}

	// Free all the rows.
	if((*grid)->cells != NULL)
	{
		for(row = 0; row < (*grid)->row_count; row++)
		{
			// Make sure it hasn't already been freed.
			if((*grid)->cells[row] != NULL)
			{
				Q_free((*grid)->cells[row]);
			}
		}
	}

	// Free all columns.
	Q_free((*grid)->cells);

	// Free the grid itself.
	Q_free((*grid));
}
コード例 #2
0
ファイル: xsd.c プロジェクト: AAS/ezquake-source
// strip spaces multiple spaces from in-between words
char *XSD_StripSpaces (char *str)
{
    char *buf, *ret;
    unsigned int p = 0, q = 0;

    if (str == NULL)
        return str;

    buf = (char *) Q_malloc(strlen(str)+1);
    for (p=0; p < strlen(str); p++)
    {
        if (XSD_IsSpace(str[p]))
        {
            if (q == 0  ||  XSD_IsSpace(buf[q-1]))
                ;
            else
                buf[q++] = ' ';
        }
        else
            buf[q++] = str[p];
    }

    // strip spaces from the end
    while (q > 0  &&  XSD_IsSpace(buf[q-1]))
        q--;
    buf[q] = 0;

    ret = (char *) Q_strdup(buf);
    Q_free(buf);
    Q_free(str);
    return ret;
}
コード例 #3
0
mvd_clock_t *MVD_ClockList_Remove(mvd_clock_t *item)
{
	mvd_clock_t *ret = NULL;

	if (item == mvd_clocklist) {
		mvd_clocklist = item->next;
		if (mvd_clocklist) {
			mvd_clocklist->prev = NULL;
		}
		Q_free(item);
		return mvd_clocklist;
	}

	ret = item->next;
	// item->prev is not null
	if (item->next) {
		item->next->prev = item->prev;
		item->prev->next = item->next;
	}
	else {
		item->prev->next = NULL;
	}
	Q_free(item);
	return ret;
}
コード例 #4
0
ファイル: utils.c プロジェクト: AAS/ezquake-source
// compares two fun strings
int funcmp(const char *s1, const char *s2)
{
    char *t1, *t2;
    int ret;

    if (s1 == NULL  &&  s2 == NULL)
        return 0;

    if (s1 == NULL)
        return -1;

    if (s2 == NULL)
        return 1;

    t1 = Q_strdup(s1);
    t2 = Q_strdup(s2);

    FunToSort(t1);
    FunToSort(t2);

    ret = strcmp(t1, t2);

    Q_free(t1);
    Q_free(t2);

    return ret;
}
コード例 #5
0
static char *VX_RemovePrefix(int player)
{
	size_t skip;
	char *prefixes, *prefix, *name;

	if (amf_tracker_name_remove_prefixes.string[0] == 0)
		return cl.players[player].name;

	skip = 0;
	prefixes = Q_normalizetext(Q_strdup(amf_tracker_name_remove_prefixes.string));
	prefix = strtok(prefixes, " ");
	name = Q_normalizetext(Q_strdup(cl.players[player].name));

	while (prefix != NULL) {
		if (strlen(prefix) > skip && strlen(name) > strlen(prefix) && strncasecmp(prefix, name, strlen(prefix)) == 0) {
			skip = strlen(prefix);
			// remove spaces from the new start of the name
			while (name[skip] == ' ')
				skip++;
			// if it would skip the whole name, just use the whole name
			if (name[skip] == 0) {
				skip = 0;
				break;
			}
		}
		prefix = strtok(NULL, " ");
	}

	Q_free(prefixes);
	Q_free(name);

	return cl.players[player].name + skip;
}
コード例 #6
0
ファイル: mp3_winamp.c プロジェクト: jogi1/camquake
static void MP3_WINAMP_CachePlaylistFlush(void) {
	int i;
	for (i = 0; i < WINAMP_Playlist_nelms; i++)
		Q_free(WINAMP_Playlist[i]);

	Q_free(WINAMP_Playlist);
}
コード例 #7
0
ファイル: utils.c プロジェクト: AAS/ezquake-source
qbool Util_F_Match (const char *_msg, char *f_request) {
	int offset, i, status, flags;
	char *s, *msg;

	msg = Q_strdup(_msg);
	flags = TP_CategorizeMessage(msg, &offset);

	if (flags != 1 && flags != 4)
		return false;

	for (i = 0, s = msg + offset; i < strlen(s); i++)
		s[i] = s[i] & ~128;		

	if (strstr(s, f_request) != s) {
		Q_free(msg);
		return false;
	}
	status = 0;
	for (s += strlen(f_request); *s; s++) {
		if (isdigit(*s) && status <= 1) {
			status = 1;
		} else if (isspace(*s)) {
			status = (status == 1) ? 2 : status;
		} else {
			Q_free(msg);			
			return false;
		}
	}
	Q_free(msg);
	return true;
}
コード例 #8
0
ファイル: gl_bloom.c プロジェクト: jogi1/camquake
void R_Bloom_InitTextures( void )
{
	unsigned char *data;
	int maxtexsize;
	size_t size;

	// Find closer power of 2 to screen size.
	for (screen_texture_width = 1;  screen_texture_width  < glwidth;  screen_texture_width *= 2);
	for (screen_texture_height = 1; screen_texture_height < glheight; screen_texture_height *= 2);

    // Disable blooms if we can't handle a texture of that size.
	glGetIntegerv (GL_MAX_TEXTURE_SIZE, &maxtexsize);
	if (screen_texture_width > maxtexsize || screen_texture_height > maxtexsize)
	{
		screen_texture_width = screen_texture_height = 0;
		Cvar_SetValue (&r_bloom, 0);
		Com_Printf ("WARNING: 'R_InitBloomScreenTexture' too high resolution for Light Bloom. Effect disabled\n");
		return;
	}

	// Init the screen texture.
	size = screen_texture_width * screen_texture_height * sizeof (int);
	data = Q_malloc (size);
	memset (data, 255, size);
	//r_bloomscreentexture = GL_LoadTexture ( "***r_screenbackuptexture***", screen_texture_width, screen_texture_height, data, 0, 4); // false, false, 4);
	
	if (!r_bloomscreentexture)
		r_bloomscreentexture = texture_extension_number++;

	GL_Bind (r_bloomscreentexture);
	glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, screen_texture_width, screen_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	Q_free (data);

	// Validate bloom size and init the bloom effect texture.
	R_Bloom_InitEffectTexture();

	// If screensize is more than 2x the bloom effect texture, set up for stepped downsampling.
	r_bloomdownsamplingtexture = 0;
	r_screendownsamplingtexture_size = 0;
	if( glwidth > (BLOOM_SIZE * 2) && !r_bloom_fast_sample.value )
	{
		r_screendownsamplingtexture_size = (int)(BLOOM_SIZE * 2);
		data = Q_calloc (r_screendownsamplingtexture_size * r_screendownsamplingtexture_size, sizeof (int));
		r_bloomdownsamplingtexture = GL_LoadTexture ( "***r_bloomdownsamplingtexture***", r_screendownsamplingtexture_size, r_screendownsamplingtexture_size, data, 0, 4);
		Q_free (data);
	}

	// Init the screen backup texture.
	if (r_screendownsamplingtexture_size)
		R_Bloom_InitBackUpTexture (r_screendownsamplingtexture_size, r_screendownsamplingtexture_size);
	else
		R_Bloom_InitBackUpTexture (BLOOM_SIZE, BLOOM_SIZE);
}
コード例 #9
0
ファイル: polylib.c プロジェクト: atphalix/eviltoys
/*
=================
ChopWinding

Returns the fragment of in that is on the front side
of the cliping plane.  The original is freed.
=================
*/
winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
{
	winding_t	*f, *b;

	ClipWinding (in, normal, dist, &f, &b);
	Q_free (in);
	if (b)
		Q_free (b);
	return f;
}
コード例 #10
0
void QTVList_Entry_Destroy(sb_qtventry_t *entry)
{
	while (entry->players) {
		sb_qtvplayer_t *next = entry->players->next;
		Q_free(entry->players);
		entry->players = next;
	}

	Q_free(entry);
}
コード例 #11
0
ファイル: Ctrl_PageViewer.c プロジェクト: AAS/ezquake-source
static void FreePage(CPageViewer_page_t *page)
{
    FreePageRendered(page);
    if (page->url)
        Q_free(page->url);
    if (page->doc)
        XSD_FreeDocument((xml_t *)page->doc);
    Q_free(page);
    return;
}
コード例 #12
0
ファイル: cl_slist.c プロジェクト: DavidWiberg/ezquake-source
void SList_Set (int i, char *addr, char *desc) {
	if (i >= MAX_SERVER_LIST || i < 0)
		Sys_Error("SList_Switch: Bad index %d", i);

	if (slist[i].server)
		Q_free(slist[i].server);
	if (slist[i].description)
		Q_free(slist[i].description);

	slist[i].server = Q_strdup (addr);
	slist[i].description = Q_strdup (desc);
}
コード例 #13
0
ファイル: main.c プロジェクト: JoakimSoderberg/mvdparser
void CmdArgs_Clear(void)
{
	int i;

	for (i = 0; i < cmdargs.mvd_files_count; i++)
	{
		Q_free(cmdargs.mvd_files[i]);
	}

	Q_free(cmdargs.template_file);
	Q_free(cmdargs.frag_file);
}
コード例 #14
0
ファイル: in_win.c プロジェクト: jite/jquake
void IN_RawInput_DeInit(void)
{
	if (rawmicecount < 1)
		return;

	IN_RawInput_DeRegister();
	Q_free(rawmice);
	Q_free(raw);

	// dealloc mouse structure
	rawmicecount = 0;
}
コード例 #15
0
ファイル: cmd.c プロジェクト: QuakePhil/mvdsv
/*
===============
Cmd_StuffCmds_f

Adds command line parameters as script statements
Commands lead with a +, and continue until a - or another +
quake +prog jctest.qp +cmd amlev1
quake -nosound +cmd amlev1
===============
*/
void Cmd_StuffCmds_f (void)
{
	int i, j;
	int s;
	char *text, *build, c;

	// build the combined string to parse from
	s = 0;
	for (i = 1; i < com_argc; i++)
		s += strlen (com_argv[i]) + 1;

	if (!s)
		return;

	text = (char *) Q_malloc (s+1);
	text[0] = 0;
	for (i = 1; i < com_argc; i++)
	{
		strlcat (text, com_argv[i], s + 1);
		if (i != com_argc-1)
			strlcat (text, " ", s + 1);
	}

	// pull out the commands
	build = (char *) Q_malloc (s+1);
	build[0] = 0;

	for (i=0 ; i<s-1 ; i++)
	{
		if (text[i] == '+')
		{
			i++;

			for (j=i ; (text[j] != '+') && (text[j] != '-') && (text[j] != 0) ; j++)
				;

			c = text[j];
			text[j] = 0;

			strlcat (build, text + i, s + 1);
			strlcat (build, "\n", s + 1);
			text[j] = c;
			i = j-1;
		}
	}

	if (build[0])
		Cbuf_AddText (build);

	Q_free (text);
	Q_free (build);
}
コード例 #16
0
void Reset_Source(source_data *s)
{
    int i;
    if (s->servers != NULL)
    {
        for (i=0; i < s->serversn; i++)
            Q_free(s->servers[i]);
        Q_free(s->servers);
    }
    s->serversn = 0;
    s->last_update.wYear = 0;
    //s->name[0] = 0;
}
コード例 #17
0
ファイル: vfs_pak.c プロジェクト: jite/jquake
static void FSPAK_ClosePath(void *handle)
{
	pack_t *pak = handle;

	pak->references--;
	if (pak->references > 0)
		return;	//not free yet

	VFS_CLOSE (pak->handle);
	if (pak->files)
		Q_free(pak->files);
	Q_free(pak);
}
コード例 #18
0
ファイル: vx_tracker.c プロジェクト: se-sss/ezquake-source
static char *VX_SkipCommonPrefix(int player)
{
	size_t skip;
	char *prefixes, *prefix, *name;

	skip = 0;
	prefixes = Q_normalizetext(Q_strdup(amf_tracker_name_prefixes.string));
	prefix = strtok(prefixes, " ");
	name = Q_normalizetext(Q_strdup(cl.players[player].name));

	if (prefix == NULL)  {
		// no prefixes defined by the user, search all players and remove the commont prefix
		size_t i;
		int j;
		unsigned players_left;

		players_left = 0xFFFF;
		players_left &= ~(1 << player);

		for (i = 0; i < strlen(cl.players[player].name); i++) {
			for (j = 0; j < MAX_CLIENTS; j++) {
				if ((players_left & (1 << j)) == 0)
					continue;
				if (cl.players[j].spectator)
					players_left &= ~(1 << j);
				if (strlen(cl.players[j].name) < i + 1 || cl.players[j].name[i] != cl.players[player].name[i])
					players_left &= ~(1 << j);
			}
			if (players_left == 0)
				break;
		}

		skip = i;

		if (skip == strlen(cl.players[player].name))
			skip = 0;
	} else {
		while (prefix != NULL) {
			if (strlen(name) > strlen(prefix) && strncasecmp(prefix, name, strlen(prefix)) == 0) {
				if (strlen(prefix) > skip)
					skip = strlen(prefix);
			}
			prefix = strtok(NULL, " ");
		}
	}

	Q_free(prefixes);
	Q_free(name);

	return cl.players[player].name + skip;
}
コード例 #19
0
static void DeleteReTrigger (pcre_trigger_t *t)
{
	if (t->regexp)
		(pcre_free)(t->regexp);

	if (t->regexp_extra)
		(pcre_free)(t->regexp_extra);

	if (t->regexpstr)
		Q_free(t->regexpstr);

	Q_free(t->name);
	Q_free(t);
}
コード例 #20
0
ファイル: cl_slist.c プロジェクト: DavidWiberg/ezquake-source
void SList_Reset (int i) {
	if (i >= MAX_SERVER_LIST || i < 0)
		Sys_Error("SList_Switch: Bad index %d", i);

	if (slist[i].server) {
		Q_free(slist[i].server);
		slist[i].server = NULL;
	}

	if (slist[i].description) {
		Q_free(slist[i].description);
		slist[i].description = NULL;
	}
}
コード例 #21
0
ファイル: cmd.c プロジェクト: matatk/agrip
/*
===============
Cmd_Alias_f

Creates a new command that executes a command string (possibly ; separated)
===============
*/
void Cmd_Alias_f (void)
{
	cmd_alias_t	*a;
	int			key;
	char		*name;

	if (Cmd_Argc() == 1)
	{
		Com_Printf ("alias <name> <command> : create or modify an alias\n");
		Com_Printf ("aliaslist : list all aliases\n");
		return;
	}

	name = Cmd_Argv(1);

	// see if there's already an alias by that name
	a = Cmd_FindAlias(name);

	if (a) {
		// reuse it
		Q_free (a->name);
		Q_free (a->value);
	}
	else {
		// allocate a new one
		a = Q_malloc (sizeof(cmd_alias_t));
		a->flags = 0;

		// link it in
		a->next = cmd_alias;
		cmd_alias = a;
		key = Com_HashKey(name);
		a->hash_next = cmd_alias_hash[key];
		cmd_alias_hash[key] = a;
	}

	a->name = Q_strdup(name);
	a->value = Q_strdup(Cmd_MakeArgs(2));	// copy the rest of the command line

#ifndef SERVERONLY
	if (cbuf_current == &cbuf_svc)
		a->flags |= ALIAS_STUFFED;
	else
		a->flags &= ALIAS_STUFFED;
#endif

	if (!Q_stricmp(Cmd_Argv(0), "aliasa"))
		a->flags |= ALIAS_ARCHIVE;

}
コード例 #22
0
ファイル: utils.c プロジェクト: AAS/ezquake-source
qbool Utils_RegExpGetGroup(char *regexp, char *matchstring, const char **resultstring, int *resultlength, int group)
{
	int offsets[HUD_REGEXP_OFFSET_COUNT];
	pcre *re = NULL;
	const char *error;
	int erroffset = 0;
	int match = 0;

	re = pcre_compile(
			regexp,				// The pattern.
			PCRE_CASELESS,		// Case insensitive.
			&error,				// Error message.
			&erroffset,			// Error offset.
			NULL);				// use default character tables.

	if(error)
	{
		if(re)
		{
			Q_free(re);
		}

		return false;
	}

	if(re && (match = pcre_exec(re, NULL, matchstring, strlen(matchstring), 0, 0, offsets, HUD_REGEXP_OFFSET_COUNT)) >= 0)
	{
		int substring_length = 0;
		substring_length = pcre_get_substring (matchstring, offsets, match, group, resultstring);
		
		if (resultlength != NULL)
		{
			(*resultlength) = substring_length;
		}

		if(re)
		{
			Q_free(re);
		}

		return (substring_length != PCRE_ERROR_NOSUBSTRING && substring_length != PCRE_ERROR_NOMEMORY);
	}

	if(re)
	{
		Q_free(re);
	}

	return false;
}
コード例 #23
0
ファイル: document_rendering.c プロジェクト: jogi1/camquake
// strip spaces from inline text, making links working
char * StripInlineSpaces(char *str, document_rendered_link_t *links)
{
    int cut = 0;

    char *buf, *ret;
    int p=0, q=0;

    if (str == NULL)
        return str;

    buf = (char *) Q_malloc(strlen(str)+1);
    for (p=0; p < strlen(str); p++)
    {
        // offset links
        document_rendered_link_t *l = links;
        while (l)
        {
            if (l->start == p)
                l->start -= cut;
            if (l->end == p)
                l->end -= cut;

            l = l->next;
        }

        if (XSD_IsSpace(str[p]))
        {
            if (q == 0  ||  XSD_IsSpace(buf[q-1]))
                cut++;
            else
            {
                // add this char, but replace with pure space
                buf[q++] = ' ';
            }
        }
        else
            buf[q++] = str[p];
    }

    // strip spaces from the end
    while (q > 0  &&  XSD_IsSpace(buf[q-1]))
        q--;
    buf[q] = 0;

	ret = (char *) Q_strdup(buf);
    Q_free(buf);
    Q_free(str);
    return ret;
}
コード例 #24
0
ファイル: cmd.c プロジェクト: matatk/agrip
qbool Cmd_DeleteAlias (char *name)
{
	cmd_alias_t	*a, *prev;
	int			key;

	key = Com_HashKey (name);

	prev = NULL;
	for (a = cmd_alias_hash[key] ; a ; a = a->hash_next)
	{
		if (!Q_stricmp(a->name, name))
		{
			// unlink from hash
			if (prev)
				prev->hash_next = a->hash_next;
			else
				cmd_alias_hash[key] = a->hash_next;
			break;
		}
		prev = a;
	}

	if (!a)
		return false;	// not found

	prev = NULL;
	for (a = cmd_alias ; a ; a = a->next)
	{
		if (!Q_stricmp(a->name, name))
		{
			// unlink from alias list
			if (prev)
				prev->next = a->next;
			else
				cmd_alias = a->next;

			// free
			Q_free (a->name);
			Q_free (a->value);
			Q_free (a);
			return true;
		}
		prev = a;
	}

	assert(!"Cmd_DeleteAlias: alias list broken");
	return false;	// shut up compiler
}
コード例 #25
0
ファイル: vfs_gzip.c プロジェクト: DavidWiberg/ezquake-source
static void *FSGZIP_LoadGZipFile(vfsfile_t *gziphandle, const char *desc)
{
	gzipfile_t *gzip;
	const char *base;
	char *ext;
	int fd;

	gzip = Q_calloc(1, sizeof(*gzip));
	strlcpy(gzip->filename, desc, sizeof(gzip->filename));
	if (gziphandle == NULL) goto fail;
	gzip->raw = gziphandle;

	fd = fileno(((vfsosfile_t *)gziphandle)->handle); // <-- ASSUMPTION! that file is OS
	gzip->handle = (vfsfile_t *)gzdopen(dup(fd), "r");
	gzip->references = 1;

	/* Remove the .gz from the file.name */
	base = COM_SkipPath(desc);
	ext = COM_FileExtension(desc);
	if (strcmp(ext, "gz") == 0) {
		COM_StripExtension(base, gzip->file.name, sizeof(gzip->file.name));
	} else {
		strlcpy(gzip->file.name, base, sizeof(gzip->file.name));
	}

	return gzip;

fail:
	// Q_free is safe to call on NULL pointers
	Q_free(gzip);
	return NULL;
}
コード例 #26
0
void SaveConfig(const char *cfgname)
{
	char filename[MAX_PATH] = {0}, *filename_ext, *backupname_ext;
	size_t len;
	FILE *f;

	snprintf(filename, sizeof(filename) - 4, "%s", cfgname[0] ? cfgname : MAIN_CONFIG_FILENAME); // use config.cfg if no params was specified

	COM_ForceExtensionEx (filename, ".cfg", sizeof (filename));

	if (cfg_backup.integer) {
		if (cfg_use_home.integer)	// homedir
			filename_ext = va("%s/%s/%s", com_homedir, (strcmp(com_gamedirfile, "qw") == 0 || !cfg_use_gamedir.integer) ? "" : com_gamedirfile, filename);
		else	// basedir
			filename_ext = va("%s/%s/configs/%s", com_basedir, (strcmp(com_gamedirfile, "qw") == 0 || !cfg_use_gamedir.integer) ? "ezquake" : com_gamedirfile, filename);

		if ((f = fopen(filename_ext, "r"))) {
			fclose(f);
			len = strlen(filename_ext) + 5;
			backupname_ext = (char *) Q_malloc(len);
			snprintf (backupname_ext, len, "%s.bak", filename_ext);

			if ((f = fopen(backupname_ext, "r"))) {
				fclose(f);
				remove(backupname_ext);
			}

			rename(filename_ext, backupname_ext);
			Q_free(backupname_ext);
		}
	}

	DumpConfig(filename);
	filesystemchanged = true; // fix bug 2359900
}
コード例 #27
0
ファイル: qtv.c プロジェクト: DavidWiberg/ezquake-source
// free data, perform unlink if requested
static void QTV_FreeUser(qtvuser_t *user, qbool unlink)
{
	if (!user)
		return;

	if (unlink)
	{
		qtvuser_t *next, *prev, *current;

		prev = NULL;
		current = qtvuserlist;

		for ( ; current; )
		{
			next = current->next;

			if (user == current)
			{
				if (prev)
					prev->next = next;
				else
					qtvuserlist = next;

				break;
			}

			prev = current;
			current = next;
		}
	}

	Q_free(user);
}
コード例 #28
0
ファイル: mp3_winamp.c プロジェクト: jogi1/camquake
int MP3_WINAMP_CachePlaylist(void) {
	char *playlist_buf;
	unsigned int length;
	int current;

	if ((length = WINAMP_GetPlaylist(&playlist_buf)) == -1) 
	{
		Com_Printf("%s is not running\n", mp3_player->PlayerName_LeadingCaps);
		return -1;
	}

	MP3_WINAMP_GetPlaylistInfo(&current, &WINAMP_Playlist_nelms);

	/* Free the list before we cache a new one */
	if (WINAMP_Playlist) {
		MP3_WINAMP_CachePlaylistFlush();
	}

	WINAMP_Playlist = (char **) Q_malloc(sizeof(*WINAMP_Playlist)*WINAMP_Playlist_nelms);

	WINAMP_Playlist_nelms = WINAMP_ParsePlaylist_EXTM3U(playlist_buf, length, 
									WINAMP_Playlist, WINAMP_Playlist_nelms);

	Q_free(playlist_buf);

	return 0;
}
コード例 #29
0
void SB_Source_Remove(int i)
{
    source_data *s;

	if (i < 0 || i >= MAX_SOURCES) {
		return;
	}

	s = sources[i];
    if (s->type == type_dummy)
        return;

	Q_free(sources[i]);

    // remove from SB
    if (i < sourcesn - 1)
    {
		memmove(sources+i,
                sources+i + 1,
                (sourcesn-i-1)*sizeof(*sources));
    }
    sourcesn--;

	SB_Sources_Dump();
}
コード例 #30
0
void AddToFileSource(source_data *source, server_data *serv)
{
	if (IsInSource(source, serv))
		return;

	SB_ServerList_Lock();

    // reallocate buffer if we've run out of space
	if (source->serversn >= source->servers_allocated) {
		int new_size = source->servers_allocated + 4;
		server_data** newlist = Q_malloc(new_size * sizeof(server_data*));

		memcpy(newlist, source->servers, sizeof(server_data*) * source->servers_allocated);
		Q_free(source->servers);
		source->servers = newlist;
		source->servers_allocated = new_size;
	}

	source->servers[source->serversn++] = Clone_Server(serv);
	rebuild_servers_list = true;

	SB_ServerList_Unlock();

	DumpSource(source);
	Mark_Source(sources[0]);
}