diff -wrubN quake3_1.32b/code/client/cl_console.c dfengine_1.07_src/code/client/cl_console.c
--- quake3_1.32b/code/client/cl_console.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/client/cl_console.c	2009-04-18 19:37:40.000000000 +0200
@@ -23,13 +23,14 @@
 
 #include "client.h"
 
+#include <pcre.h>	// Cgg
 
 int g_console_field_width = 78;
 
 
 #define	NUM_CON_TIMES 4
 
-#define		CON_TEXTSIZE	32768
+#define		CON_TEXTSIZE	0x10000	// Cgg - doubled
 typedef struct {
 	qboolean	initialized;
 
@@ -45,7 +46,7 @@
 
 	float	displayFrac;	// aproaches finalFrac at scr_conspeed
 	float	finalFrac;		// 0.0 to 1.0 lines of console to display
-
+	float	userFrac;		// 0.0 to 1.0 - for user Configurations. Don't want to mess with finalFrac - marky
 	int		vislines;		// in scanlines
 
 	int		times[NUM_CON_TIMES];	// cls.realtime time the line was generated
@@ -59,6 +60,15 @@
 
 cvar_t		*con_conspeed;
 cvar_t		*con_notifytime;
+// Cgg
+cvar_t		*con_useshader;
+cvar_t		*con_opacity;
+cvar_t		*con_rgb;
+
+#define MAX_CON_FILTERS 20
+cvar_t *con_filters[MAX_CON_FILTERS];
+pcre *con_filters_compiled[MAX_CON_FILTERS];
+// !Cgg
 
 #define	DEFAULT_CONSOLE_WIDTH	78
 
@@ -67,6 +77,15 @@
 
 /*
 ================
+Con_ShowPCREVersion_f (Cgg - pcre support)
+================
+*/
+static void Con_ShowPCREVersion_f(void) {
+	Com_Printf("%s\n", pcre_version());
+}
+
+/*
+================
 Con_ToggleConsole_f
 ================
 */
@@ -93,7 +112,10 @@
 	chat_playerNum = -1;
 	chat_team = qfalse;
 	Field_Clear( &chatField );
-	chatField.widthInChars = 30;
+	// Cgg
+	chatField.widthInChars = cls.glconfig.vidWidth / TINYCHAR_WIDTH -7;	// -7: "say: " + padding
+	//chatField.widthInChars = 30;
+	// !Cgg
 
 	cls.keyCatchers ^= KEYCATCH_MESSAGE;
 }
@@ -107,7 +129,10 @@
 	chat_playerNum = -1;
 	chat_team = qtrue;
 	Field_Clear( &chatField );
-	chatField.widthInChars = 25;
+	// Cgg
+	chatField.widthInChars = cls.glconfig.vidWidth / TINYCHAR_WIDTH -12; // -12: "say_team: " + padding
+//	chatField.widthInChars = 25;
+	// !Cgg
 	cls.keyCatchers ^= KEYCATCH_MESSAGE;
 }
 
@@ -124,7 +149,10 @@
 	}
 	chat_team = qfalse;
 	Field_Clear( &chatField );
-	chatField.widthInChars = 30;
+	// Cgg
+	chatField.widthInChars = cls.glconfig.vidWidth / TINYCHAR_WIDTH -7;	// -7: "say: " + padding
+//	chatField.widthInChars = 30;
+	// !Cgg
 	cls.keyCatchers ^= KEYCATCH_MESSAGE;
 }
 
@@ -141,7 +169,10 @@
 	}
 	chat_team = qfalse;
 	Field_Clear( &chatField );
-	chatField.widthInChars = 30;
+	// Cgg
+	chatField.widthInChars = cls.glconfig.vidWidth / TINYCHAR_WIDTH -7; // -7: "say: " + padding
+//	chatField.widthInChars = 30;
+	// !Cgg
 	cls.keyCatchers ^= KEYCATCH_MESSAGE;
 }
 
@@ -250,7 +281,7 @@
 	int		i, j, width, oldwidth, oldtotallines, numlines, numchars;
 	MAC_STATIC short	tbuf[CON_TEXTSIZE];
 
-	width = (SCREEN_WIDTH / SMALLCHAR_WIDTH) - 2;
+	width = (cls.glconfig.vidWidth / SMALLCHAR_WIDTH) - 2;	// Cgg - was SCREEN_WIDTH
 
 	if (width == con.linewidth)
 		return;
@@ -315,6 +346,15 @@
 	con_notifytime = Cvar_Get ("con_notifytime", "3", 0);
 	con_conspeed = Cvar_Get ("scr_conspeed", "3", 0);
 
+	// Cgg
+	con_useshader = Cvar_Get("con_useshader", "0", CVAR_ARCHIVE);
+	con_opacity = Cvar_Get("con_opacity", "0.95", CVAR_ARCHIVE);
+	con_rgb = Cvar_Get("con_rgb", ".05 .05 .1", CVAR_ARCHIVE);
+	for (i=0; i<MAX_CON_FILTERS; i++) {
+		con_filters[i] = Cvar_Get(va("con_filter%i", i), "", CVAR_ARCHIVE);
+	}
+	// !Cgg
+
 	Field_Clear( &g_consoleField );
 	g_consoleField.widthInChars = g_console_field_width;
 	for ( i = 0 ; i < COMMAND_HISTORY ; i++ ) {
@@ -329,6 +369,7 @@
 	Cmd_AddCommand ("messagemode4", Con_MessageMode4_f);
 	Cmd_AddCommand ("clear", Con_Clear_f);
 	Cmd_AddCommand ("condump", Con_Dump_f);
+	Cmd_AddCommand ("pcre_version", Con_ShowPCREVersion_f );	// Cgg
 }
 
 
@@ -340,6 +381,32 @@
 void Con_Linefeed (qboolean skipnotify)
 {
 	int		i;
+	char txt[MAXPRINTMSG];
+	pcre **re;
+	int ovector[30];
+	char ch;
+	qboolean copy;
+
+	// Cgg
+	if (con.linewidth < sizeof(txt)) {
+		for (i=con.linewidth-1,copy=qfalse; i>=0; i--) {
+			ch = con.text[(con.current%con.totallines)*con.linewidth+i] &0xff;
+			if (ch != ' ') {
+				copy = qtrue;
+			}
+			txt[i] = (copy) ? ch : 0;
+		}
+		for (re=con_filters_compiled; re-con_filters_compiled<MAX_CON_FILTERS; re++) {
+			if (*re && pcre_exec(*re, NULL, txt, strlen(txt), 0, 0, ovector, 30) > 0) {
+				con.x = 0;
+				for(i=0; i<con.linewidth; i++) {
+					con.text[(con.current%con.totallines)*con.linewidth+i] = (ColorIndex(COLOR_WHITE)<<8) | ' ';
+				}
+				return;
+			}
+		}
+	}
+	// !Cgg
 
 	// mark time for transparent overlay
 	if (con.current >= 0)
@@ -367,12 +434,14 @@
 If no console is visible, the text will appear at the top of the game window
 ================
 */
+#define Q_RAW_ESCAPE 1	// Cgg: see below
 void CL_ConsolePrint( char *txt ) {
 	int		y;
 	int		c, l;
 	int		color;
 	qboolean skipnotify = qfalse;		// NERVE - SMF
 	int prev;							// NERVE - SMF
+	char raw;	// Cgg: Q_RAW_ESCAPE char stops color sequences from being interpreted.
 
 	// TTimo - prefix for text that shows up in console but not in notify
 	// backported from RTCW
@@ -398,12 +467,20 @@
 
 	color = ColorIndex(COLOR_WHITE);
 
+	raw = 0;
 	while ( (c = *txt) != 0 ) {
+		if (!raw) {
 		if ( Q_IsColorString( txt ) ) {
 			color = ColorIndex( *(txt+1) );
 			txt += 2;
 			continue;
 		}
+			// Cgg - repeated escape codes (^^) were broken
+			if (*txt == Q_COLOR_ESCAPE && *(txt+1) == Q_COLOR_ESCAPE) {
+				txt++;
+			}
+			// !Cgg
+		}
 
 		// count word length
 		for (l=0 ; l< con.linewidth ; l++) {
@@ -423,7 +500,11 @@
 
 		switch (c)
 		{
+		case Q_RAW_ESCAPE:
+			raw = raw^1;
+			break;
 		case '\n':
+			raw = 0;
 			Con_Linefeed (skipnotify);
 			break;
 		case '\r':
@@ -532,8 +613,8 @@
 			if ( ( text[x] & 0xff ) == ' ' ) {
 				continue;
 			}
-			if ( ( (text[x]>>8)&7 ) != currentColor ) {
-				currentColor = (text[x]>>8)&7;
+			if ( ( ((text[x]>>8)&15)%10 ) != currentColor ) {
+				currentColor = ((text[x]>>8)&15)%10;
 				re.SetColor( g_color_table[currentColor] );
 			}
 			SCR_DrawSmallChar( cl_conXOffset->integer + con.xadjust + (x+1)*SMALLCHAR_WIDTH, v, text[x] & 0xff );
@@ -553,17 +634,28 @@
 	{
 		if (chat_team)
 		{
-			SCR_DrawBigString (8, v, "say_team:", 1.0f );
+			// Cgg
+			SCR_DrawSmallStringExt(8, v, "say_team:", colorWhite, qfalse, qfalse);
+			//SCR_DrawBigString (8, v, "say_team:", 1.0f );
+			// !Cgg
 			skip = 11;
 		}
 		else
 		{
-			SCR_DrawBigString (8, v, "say:", 1.0f );
-			skip = 5;
+			// Cgg
+			SCR_DrawSmallStringExt(8, v, "say:", colorWhite, qfalse, qfalse);
+			skip = 6;
+			//skip = 5;
+			//SCR_DrawBigString (8, v, "say:", 1.0f );
+			// !Cgg
 		}
 
-		Field_BigDraw( &chatField, skip * BIGCHAR_WIDTH, v,
-			SCREEN_WIDTH - ( skip + 1 ) * BIGCHAR_WIDTH, qtrue );
+		// Cgg
+		Field_Draw(&chatField,  skip * TINYCHAR_WIDTH, v,
+			SCREEN_WIDTH - ( skip + 1 ) * TINYCHAR_WIDTH, qtrue );
+		//Field_BigDraw( &chatField, skip * BIGCHAR_WIDTH, v,
+		//	SCREEN_WIDTH - ( skip + 1 ) * BIGCHAR_WIDTH, qtrue );
+		// !Cgg
 
 		v += BIGCHAR_HEIGHT;
 	}
@@ -585,7 +677,6 @@
 	int				lines;
 //	qhandle_t		conShader;
 	int				currentColor;
-	vec4_t			color;
 
 	lines = cls.glconfig.vidHeight * frac;
 	if (lines <= 0)
@@ -599,24 +690,31 @@
 	SCR_AdjustFrom640( &con.xadjust, NULL, NULL, NULL );
 
 	// draw the background
-	y = frac * SCREEN_HEIGHT - 2;
+	y = frac * SCREEN_HEIGHT - 1;	// Cgg - was 2
 	if ( y < 1 ) {
 		y = 0;
 	}
 	else {
+		// Cgg
+		if (con_useshader->integer) {
 		SCR_DrawPic( 0, 0, SCREEN_WIDTH, y, cls.consoleShader );
+		} else {
+			vec4_t color;
+			char *c = con_rgb->string;
+			color[0] = atof(COM_Parse(&c));
+			color[1] = atof(COM_Parse(&c));
+			color[2] = atof(COM_Parse(&c));
+			color[3] = con_opacity->value;
+			SCR_FillRect( 0, 0, SCREEN_WIDTH, y, color );
+		}
+		// !Cgg
 	}
 
-	color[0] = 1;
-	color[1] = 0;
-	color[2] = 0;
-	color[3] = 1;
-	SCR_FillRect( 0, y, SCREEN_WIDTH, 2, color );
-
+	SCR_FillRect( 0, y, SCREEN_WIDTH, 1, colorOrange );	// Cgg - orange & 1px instead of 2
 
 	// draw the version number
 
-	re.SetColor( g_color_table[ColorIndex(COLOR_RED)] );
+	re.SetColor( g_color_table[ColorIndex(COLOR_ORANGE)] );	// Cgg - orange
 
 	i = strlen( Q3_VERSION );
 
@@ -639,7 +737,7 @@
 	if (con.display != con.current)
 	{
 	// draw arrows to show the buffer is backscrolled
-		re.SetColor( g_color_table[ColorIndex(COLOR_RED)] );
+		re.SetColor( g_color_table[ColorIndex(COLOR_ORANGE)] );	// Cgg - orange
 		for (x=0 ; x<con.linewidth ; x+=4)
 			SCR_DrawSmallChar( con.xadjust + (x+1)*SMALLCHAR_WIDTH, y, '^' );
 		y -= SMALLCHAR_HEIGHT;
@@ -671,8 +769,8 @@
 				continue;
 			}
 
-			if ( ( (text[x]>>8)&7 ) != currentColor ) {
-				currentColor = (text[x]>>8)&7;
+			if ( ( ((text[x]>>8)&15)%10 ) != currentColor ) {
+				currentColor = ((text[x]>>8)&15)%10;
 				re.SetColor( g_color_table[currentColor] );
 			}
 			SCR_DrawSmallChar(  con.xadjust + (x+1)*SMALLCHAR_WIDTH, y, text[x] & 0xff );
@@ -724,9 +822,34 @@
 ==================
 */
 void Con_RunConsole (void) {
+	// Cgg - check for updated con_filters
+	cvar_t **cvar;
+	pcre **re;
+	const char *errptr;
+	int erroffset;
+	for (cvar=con_filters; cvar-con_filters<MAX_CON_FILTERS; cvar++) {
+		if (!*cvar || !(*cvar)->modified) {
+			continue;
+		}
+		re = con_filters_compiled+(cvar-con_filters);
+		(*cvar)->modified = qfalse;
+		if (!strlen((*cvar)->string)) {
+			*re = NULL;
+			continue;
+		}
+		*re = pcre_compile((*cvar)->string, 0, &errptr, &erroffset, NULL);
+		if (!*re) {
+			Com_Printf("Failed to compile %c%s\n", Q_RAW_ESCAPE, (*cvar)->string);
+			Com_Printf(va("%c%%%ic %%s\n", Q_RAW_ESCAPE, erroffset+19), '^', errptr);
+			Cvar_Set((*cvar)->name, "");
+			(*cvar)->modified = qfalse;
+		}
+	}
+	// !Cgg
+
 	// decide on the destination height of the console
 	if ( cls.keyCatchers & KEYCATCH_CONSOLE )
-		con.finalFrac = 0.5;		// half screen
+		con.finalFrac = con.userFrac;	// marky
 	else
 		con.finalFrac = 0;				// none visible
 	
@@ -747,6 +870,25 @@
 
 }
 
+// marky
+/*
+==================
+Con_SetFrac
+==================
+*/
+void Con_SetFrac(const float conFrac)
+{
+	// clamp the cvar value
+	if (conFrac < .1f) {	// don't let the console be hidden
+		con.userFrac = .1f;
+	} else if (conFrac > 1.0f) {
+		con.userFrac = 1.0f;
+	} else {
+		con.userFrac = conFrac;
+	}
+}
+// !marky
+
 
 void Con_PageUp( void ) {
 	con.display -= 2;
diff -wrubN quake3_1.32b/code/client/cl_download.c dfengine_1.07_src/code/client/cl_download.c
--- quake3_1.32b/code/client/cl_download.c	1970-01-01 01:00:00.000000000 +0100
+++ dfengine_1.07_src/code/client/cl_download.c	2009-05-18 13:44:57.000000000 +0200
@@ -0,0 +1,421 @@
+/*
+===========================================================================
+Copyright (C) 2009 Cyril Gantin
+
+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
+===========================================================================
+
+Integration of libcurl for requesting maps from an online repository.
+
+Usage: /download <mapname>
+
+Cvar dl_source defines the url from which to query maps, eg: http://someserver/somescript.php?q=%m
+The %m token is replaced with the actual map name in the query.
+
+The server MUST return an appropriate content-type. Accepted content-type values are either application/zip
+or application/octet-stream. Other content-type values will be treated as errors or queries that didn't
+yield results.
+
+The server MAY return a content-disposition header with the actual name of the pk3 file. In the absence
+of a content-disposition header, the client will write the pack to a default <mapname>.pk3 location. The
+filename MUST have a pk3 extension. The filename MUST NOT have directory path information - slashes (/),
+backslashes (\) and colons (:) are not accepted. Finally the filename MUST consist of us-ascii characters
+only (chars 32 to 126, included). A filename that doesn't comply to these specifications will raise an
+error and abort the transfer.
+
+The server MAY redirect the query to another url. Multiple redirections are permitted - limit depends on
+libcurl's default settings. The end query MUST return a "200 OK" http status code.
+
+It is desirable that the server returns a content-length header with the size of the pk3 file.
+
+The server MAY return a custom x-dfengine-motd header. Its value is a string that MUST NOT exceed 127
+chars. The x-dfengine-motd string will be displayed after the download is complete. This is the place
+where you take credits for setting up a server. :)
+
+Downloaded files are written to the current gamedir of the home directory - eg. C:\quake3\mymod\ in
+windows; ~/.q3a/mymod/ in linux. Name collision with an existing pk3 file will result in a failure and
+be left to the user to sort out.
+
+todo:
+	- consider the curl_multi_* interface which is non-blocking, although it's not so helpful for plain
+	console-based downloading.
+	- see if this can be integrated with the client connection code while retaining compatibility with
+	all quake3 servers.
+*/
+
+#include <curl/curl.h>
+#include "client.h"
+
+static cvar_t *dl_verbose;	// 1: show http headers; 2: http headers +curl debug info
+static cvar_t *dl_showprogress;	// show console progress
+static cvar_t *dl_showmotd;	// show server message
+static cvar_t *dl_source;	// url to query maps from; %m token will be replaced by mapname
+static cvar_t *dl_usebaseq3;	// whether to download pk3 files in baseq3 (default is off)
+
+static qboolean curl_initialized;
+static char useragent[256];
+static CURL *curl;
+static fileHandle_t f;
+static char path[MAX_OSPATH];
+static char dl_error[1024];	// if set, will be used in place of libcurl's error message.
+static char motd[128];
+
+static size_t Curl_WriteCallback_f(void *ptr, size_t size, size_t nmemb, void *stream) {
+	if (!f) {
+		char dir[MAX_OSPATH];
+		char *c;
+		// make sure Content-Type is either "application/octet-stream" or "application/zip".
+		if (curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &c) != CURLE_OK
+				|| !c
+				|| (stricmp(c, "application/octet-stream")
+					&& stricmp(c, "application/zip"))) {
+			Q_strncpyz(dl_error, "No pk3 returned - requested map is probably unknown.", sizeof(dl_error));
+			return 0;
+		}
+		// make sure the path doesn't have directory information.
+		for (c=path; *c; c++) {
+			if (*c == '\\' || *c == '/' || *c == ':') {
+				Com_sprintf(dl_error, sizeof(dl_error), "Destination filename \"%s\" is not valid.", path);
+				return 0;
+			}
+		}
+		// make sure the file has an appropriate extension.
+		c = path +strlen(path) -4;
+		if (c <= path || strcmp(c, ".pk3")) {
+			Com_sprintf(dl_error, sizeof(dl_error), "Returned file \"%s\" has wrong extension.", path);
+			return 0;
+		}
+		// make out the directory in which to place the file
+		Q_strncpyz(dir, (dl_usebaseq3->integer)?"baseq3":FS_GetGameDir(), sizeof(dir));
+		if (strlen(path) +strlen(dir) +1 >= sizeof(path)) {
+			Com_sprintf(dl_error, sizeof(dl_error), "Returned filename is too large.");
+			return 0;
+		}
+		Com_sprintf(path, sizeof(path), "%s/%s", dir, path);
+		// in case of a name collision, just fail - leave it to the user to sort out.
+		if (FS_SV_FileExists(path)) {
+			Com_sprintf(dl_error, sizeof(dl_error), "Failed to download \"%s\", a pk3 by that name exists locally.", path);
+			return 0;
+		}
+		// change the extension to .tmp - it will be changed back once the download is complete.
+		c = path +strlen(path) -4;
+		strcpy(c, ".tmp"); 
+
+		// FS should write the file in the appropriate gamedir and catch unsanitary paths.
+		f = FS_SV_FOpenFileWrite(path);
+		if (!f) {
+			Com_sprintf(dl_error, sizeof(dl_error), "Failed to open \"%s\" for writing.\n", path);
+			return 0;
+		}
+		Com_Printf("Writing to: %s\n", path);
+	}
+	return FS_Write(ptr, size*nmemb, f);
+}
+
+static size_t Curl_HeaderCallback_f(void *ptr, size_t size, size_t nmemb, void *stream) {
+	char buf[1024];
+	char *c;
+
+	// make a copy and remove the trailing crlf chars.
+	if (size*nmemb >= sizeof(buf)) {
+		Q_strncpyz(dl_error, "Curl_HeaderCallback_f() overflow.", sizeof(dl_error));
+		return (size_t)-1;
+	}
+	Q_strncpyz(buf, ptr, size*nmemb+1);
+	c = buf +strlen(buf)-1;
+	while (c>buf && (*c == '\r' || *c == '\n')) {
+		*(c--) = 0;
+	}
+
+	// make sure it's not empty.
+	if (c <= buf) {
+		return size*nmemb;
+	}
+
+	// verbose output
+	if (dl_verbose->integer > 0) {
+		Com_Printf("< %s\n", buf);
+	}
+	/**
+	 * Check whether this is a content-disposition header.
+	 * Apparently RFC2183 has precise rules for the presentation of the filename attribute.
+	 * No one seems to respect those, though.
+	 * Accepted presentations:
+	 *	filename="somefile.pk3"
+	 *	filename='somefile.pk3'
+	 *	filename=somefile.pk3
+	 * Quoted strings won't support escaping (eg. "some\"file.pk3").
+	 * Malformed quoted strings that miss the trailing quotation mark will pass.
+	 * Only us-ascii chars are accepted.
+	 * The actual filename will be validated later, when the transfer is started.
+	 */
+	if (!strncasecmp(buf, "content-disposition:", 20)) {
+		const char *c = strstr(buf, "filename=") +9;
+		if (c != (char*)9) {
+			const char *e;
+			char token=0;
+			if (*c == '"' || *c == '\'') {
+				token = *c++;
+			}
+			for (e=c; *e && *e != token; e++) {
+				if (*e<32 || *e > 126) {
+					Q_strncpyz(dl_error, "Server returned an invalid filename.", sizeof(dl_error));
+					return (size_t)-1;
+				}
+			}
+			if (e == c || e-c >= sizeof(path)) {
+				Q_strncpyz(dl_error, "Server returned an invalid filename.", sizeof(dl_error));
+				return (size_t)-1;
+			}
+			Q_strncpyz(path, c, e-c+1);	// +1 makes room for the trailing \0
+		}
+	}
+
+	// catch x-dfengine-motd headers
+	if (!strncasecmp(buf, "x-dfengine-motd: ", 17)) {
+		if (strlen(buf) >= 17+sizeof(motd)) {
+			if (dl_showmotd->integer) {
+				Com_Printf("Warning: server motd string too large.\n");
+			}
+		} else {
+			Q_strncpyz(motd, buf+17, sizeof(motd));
+		}
+	}
+	return size*nmemb;
+}
+
+static size_t Curl_VerboseCallback_f(CURL *curl, curl_infotype type, char *data, size_t size, void *userptr) {
+	char buf[1024];
+	char *c, *l;
+
+	if ((type != CURLINFO_HEADER_OUT || dl_verbose->integer < 1)
+			&& (type != CURLINFO_TEXT || dl_verbose->integer < 2)) {
+		return 0;
+	}
+	if (size >= sizeof(buf)) {
+		Com_Printf("Curl_VerboseCallback_f() warning: overflow.\n");
+		return 0;
+	}
+	Q_strncpyz(buf, data, size+1);	// +1 makes room for the trailing \0
+	if (type == CURLINFO_HEADER_OUT) {
+		for (l=c=buf; c-buf<size; c++) {
+			// header lines should have linefeeds.
+			if (*c == '\n' || *c == '\r') {
+				*c = 0;
+				if (c>l) {
+					Com_Printf("> %s\n", l);
+				}
+				l = c+1;
+			}
+		}
+		return 0;
+	}
+	// CURLINFO_TEXT (has its own linefeeds)
+	Com_Printf("%s", buf);	// Com_Printf(buf) would result in random output/segfault if buf has % chars.
+	return 0;
+}
+
+/**
+ * This callback is called on regular intervals, whether data is being transferred or not.
+ */
+static int Curl_ProgressCallback_f(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) {
+	static double stransferred = -1.0;
+
+	if (dl_showprogress->integer 
+			&& dlnow != stransferred
+			&& f) {	// don't show progress if file hasn't been initialized (might be downloading an error page).
+		double speed;
+		if (dltotal != 0.0	// content-size is known
+				&& dlnow <= dltotal) {	// and appropriate
+			if (dltotal > 1024.0 * 1024.0) {	// MB range
+				Com_Printf("%.1f/%.1fMB", dlnow/1024.0/1024.0, dltotal/1024.0/1024.0);
+			} else if (dltotal > 10240.0) {		// KB range (>10KB)
+				Com_Printf("%.1f/%.1fKB", dlnow/1024.0, dltotal/1024.0);
+			} else {							// byte range
+				Com_Printf("%.0f/%.0fB", dlnow, dltotal);
+			}
+		} else {	// unknown content-size
+			if (dlnow > 1024.0 * 1024.0) {		// MB range
+				Com_Printf("%.1fMB", dlnow/1024.0/1024.0);
+			} else if (dlnow > 10240.0) {		// KB range (>10KB)
+				Com_Printf("%.1fKB", dlnow/1024.0);
+			} else {							// byte range
+				Com_Printf("%.0fB", dlnow, dltotal);
+			}
+		}
+		if (!curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &speed)) {
+			Com_Printf(" @%.1fKB/s", speed/1024.0);
+		}
+		if (dltotal != 0.0 && dlnow <= dltotal) {
+			Com_Printf(" (%2.1f%%)", 100.0*dlnow/dltotal);
+		}
+		Com_Printf("\n");
+		stransferred = dlnow;
+	}
+
+	// pump events and refresh screen
+	Com_EventLoop();
+	SCR_UpdateScreen();
+	if (Key_IsDown(K_ESCAPE)) {
+		Q_strncpyz(dl_error, "Download aborted.", sizeof(dl_error));
+		return -1;
+	}
+	return 0;
+}
+
+static void Curl_Download_f(void) {
+	char url[1024];
+	CURLcode res;
+	char errorbuf[CURL_ERROR_SIZE];
+	char *c;
+
+	if (Cmd_Argc() < 2) {
+		Com_Printf("usage: download <mapname>\n");
+		return;
+	}
+	if (FS_FileIsInPAK(va("maps/%s.bsp", Cmd_Argv(1)), NULL) != -1) {
+		Com_Printf("Map already exists locally.\n");
+		return;
+	}
+	if (strncasecmp(dl_source->string, "http://", 7)) {
+		if (strstr(dl_source->string, "://")) {
+			Com_Printf("Invalid dl_source.\n");
+			return;
+		}
+		Cvar_Set("dl_source", va("http://%s", dl_source->string));
+	}
+	if ((c = strstr(dl_source->string, "%m")) == 0) {
+		Com_Printf("Cvar dl_source is missing a %%m token.\n");
+		return;
+	}
+	if (strlen(dl_source->string) -2 +strlen(Cmd_Argv(1)) >= sizeof(url)) {
+		Com_Printf("Cvar dl_source too large.\n");
+		return;
+	}
+
+	Q_strncpyz(url, dl_source->string, c-dl_source->string +1);	// +1 makes room for the trailing 0
+	Com_sprintf(url, sizeof(url), "%s%s%s", url, Cmd_Argv(1), c+2);
+
+	// set a default destination filename; Content-Disposition headers will override.
+	Com_sprintf(path, sizeof(path), "%s.pk3", Cmd_Argv(1));
+
+	curl = curl_easy_init();
+	if (!curl) {
+		Com_Printf("Download failed to initialize.\n");
+		return;
+	}
+	*dl_error = 0;
+	*motd = 0;
+	curl_easy_setopt(curl, CURLOPT_URL, url);
+	curl_easy_setopt(curl, CURLOPT_USERAGENT, useragent);
+	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
+	curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);	// fail if http returns an error code
+	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuf);
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Curl_WriteCallback_f);
+	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, Curl_HeaderCallback_f);
+	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+	curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, Curl_VerboseCallback_f);
+	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
+	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, Curl_ProgressCallback_f);
+	Com_Printf("Attempting download: %s\n", url);
+	SCR_UpdateScreen();
+	res = curl_easy_perform(curl);
+	if (res != CURLE_OK) {
+		Com_Printf("%s\n", (*dl_error) ? dl_error : errorbuf);
+	} else {
+		Com_Printf("Download complete, restarting filesystem.\n");
+	}
+	curl_easy_cleanup(curl);
+	curl = NULL;
+	if (f) {
+		FS_FCloseFile(f);
+		f = 0;
+		if (res == CURLE_OK) {	// download succeeded
+			char dest[MAX_OSPATH];
+			Q_strncpyz(dest, path, strlen(path)-3);	// -4 +1 for the trailing \0
+			Q_strcat(dest, sizeof(dest), ".pk3");
+			if (!FS_SV_FileExists(dest)) {
+				FS_SV_Rename(path, dest);
+				FS_Restart(clc.checksumFeed);
+				if (dl_showmotd->integer && *motd) {
+					Com_Printf("Server motd: %s\n", motd);
+				}
+			} else {
+				// normally such errors should be caught upon starting the transfer. Anyway better do
+				// it here again - the filesystem might have changed, plus this may help contain some
+				// bugs / exploitable flaws in the code.
+				Com_Printf("Failed to copy downloaded file to its location - file already exists.\n");
+				FS_SV_RemoveFile(path);
+			}
+		} else {
+			FS_SV_RemoveFile(path);
+		}
+	}
+}
+
+static void Curl_ShowVersion_f(void) {
+	Com_Printf("%s\n", curl_version());
+}
+
+
+//
+// Interface
+//
+void DL_Init() {
+	if (!curl_global_init(CURL_GLOBAL_ALL)) {
+		char *c;
+		Cmd_AddCommand("curl_version", Curl_ShowVersion_f);
+		Cmd_AddCommand("download", Curl_Download_f);
+		curl_initialized = qtrue;
+
+		// set user-agent, something along the lines of "dfengine/1.## (libcurl/#.##.# linked libs...)"
+		Q_strncpyz(useragent, Q3_VERSION, sizeof(useragent));
+		for (c=useragent; *c; c++) {
+			if (*c == ' ') *c = '/';
+		}
+		Com_sprintf(useragent, sizeof(useragent), "%s (%s) ", useragent, curl_version());
+	} else {
+		Com_Printf("Failed to initialize libcurl.\n");
+	}
+	dl_verbose = Cvar_Get("dl_verbose", "0", 0);
+	dl_source = Cvar_Get("dl_source", "http://q3a.ath.cx/getpk3bymapname.php/%m", CVAR_ARCHIVE);
+	dl_showprogress = Cvar_Get("dl_showprogress", "1", CVAR_ARCHIVE);
+	dl_showmotd = Cvar_Get("dl_showmotd", "1", CVAR_ARCHIVE);
+	dl_usebaseq3 = Cvar_Get("dl_usebaseq3", "0", CVAR_ARCHIVE);
+}
+
+qboolean DL_Active() {
+	return (f);
+}
+
+// the engine might be going dedicated, remove client commands
+void DL_Shutdown() {
+	if (curl_initialized) {
+		if (curl) {
+			curl_easy_cleanup(curl);
+			curl = NULL;
+		}
+		if (f) {
+			FS_FCloseFile(f);
+			f = 0;
+		}
+		curl_global_cleanup();
+		curl_initialized = qfalse;
+		Cmd_RemoveCommand("curl_version");
+		Cmd_RemoveCommand("download");
+	}
+}
diff -wrubN quake3_1.32b/code/client/client.h dfengine_1.07_src/code/client/client.h
--- quake3_1.32b/code/client/client.h	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/client/client.h	2009-04-18 19:37:40.000000000 +0200
@@ -449,6 +449,7 @@
 void Con_Bottom( void );
 void Con_Close( void );
 
+void Con_SetFrac( const float conFrac );	// marky
 
 //
 // cl_scrn.c
@@ -468,7 +469,7 @@
 
 void	SCR_DrawBigString( int x, int y, const char *s, float alpha );			// draws a string with embedded color control characters with fade
 void	SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color );	// ignores embedded color control characters
-void	SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor );
+void	SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor, qboolean rawmode );
 void	SCR_DrawSmallChar( int x, int y, int ch );
 
 
@@ -517,3 +518,10 @@
 void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg);	//int length, const byte *data );
 void CL_Netchan_TransmitNextFragment( netchan_t *chan );
 qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg );
+
+//
+// cl_download.c
+//
+void DL_Init();
+void DL_Shutdown();
+qboolean DL_Active();
diff -wrubN quake3_1.32b/code/client/cl_keys.c dfengine_1.07_src/code/client/cl_keys.c
--- quake3_1.32b/code/client/cl_keys.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/client/cl_keys.c	2009-05-25 11:51:16.000000000 +0200
@@ -45,6 +45,8 @@
 qboolean	anykeydown;
 qkey_t		keys[MAX_KEYS];
 
+cvar_t 		*con_height; //marky
+
 
 typedef struct {
 	char	*name;
@@ -68,6 +70,10 @@
 	{"ALT", K_ALT},
 	{"CTRL", K_CTRL},
 	{"SHIFT", K_SHIFT},
+// drakkar
+	{"WIN", K_WIN},
+	{"MENU", K_MENU},
+// !drakkar
 
 	{"COMMAND", K_COMMAND},
 
@@ -245,7 +251,7 @@
 		float	color[4];
 
 		color[0] = color[1] = color[2] = color[3] = 1.0;
-		SCR_DrawSmallStringExt( x, y, str, color, qfalse );
+		SCR_DrawSmallStringExt( x, y, str, color, qfalse, qtrue );
 	} else {
 		// draw big string with drop shadow
 		SCR_DrawBigString( x, y, str, 1.0 );
@@ -266,7 +272,7 @@
 		cursorChar = 10;
 	}
 
-	i = drawLen - ( Q_PrintStrlen( str ) + 1 );
+	i = drawLen - ( strlen( str ) + 1 );	// Cgg - was Q_PrintStrlen()
 
 	if ( size == SMALLCHAR_WIDTH ) {
 		SCR_DrawSmallChar( x + ( edit->cursor - prestep - i ) * size, y, cursorChar );
@@ -1040,37 +1046,60 @@
 		}
 	}
 
-#ifdef __linux__
-  if (key == K_ENTER)
-  {
-    if (down)
-    {
-      if (keys[K_ALT].down)
+// drakkar - swap fullscreen : same code for linux and windows
+/*
+-#ifdef __linux__
+-  if (key == K_ENTER)
+-  {
+-    if (down)
+-    {
+-      if (keys[K_ALT].down)
+-      {
+-        Key_ClearStates();
+-        if (Cvar_VariableValue("r_fullscreen") == 0)
+-        {
+-          Com_Printf("Switching to fullscreen rendering\n");
+-          Cvar_Set("r_fullscreen", "1");
+-        }
+-        else
+-        {
+-          Com_Printf("Switching to windowed rendering\n");
+-          Cvar_Set("r_fullscreen", "0");
+-        }
+-        Cbuf_ExecuteText( EXEC_APPEND, "vid_restart\n");
+-        return;
+-      }
+-    }
+-  }
+-#endif
+*/
+#if ( __linux__ || _WIN32 )
+if( keys[K_ALT].down && keys[K_ENTER].repeats == 1 )
       {
         Key_ClearStates();
-        if (Cvar_VariableValue("r_fullscreen") == 0)
-        {
-          Com_Printf("Switching to fullscreen rendering\n");
-          Cvar_Set("r_fullscreen", "1");
-        }
-        else
-        {
-          Com_Printf("Switching to windowed rendering\n");
-          Cvar_Set("r_fullscreen", "0");
-        }
-        Cbuf_ExecuteText( EXEC_APPEND, "vid_restart\n");
+	Cbuf_ExecuteText( EXEC_APPEND, "windowMode swapFullscreen\n");
         return;
       }
-    }
-  }
 #endif
+// !drakkar
 
 	// console key is hardcoded, so the user can never unbind it
 	if (key == '`' || key == '~') {
 		if (!down) {
 			return;
 		}
+		//marky
+		con_height = Cvar_Get("con_height", "0.5", CVAR_ARCHIVE);	//called early, used as default (set by user)
+		Con_SetFrac(con_height->value);				
+		if(key == '`' || key == '~') {
+			if(keys[K_ALT].down)
+				Con_SetFrac(1.0f);
+			else if (keys[K_SHIFT].down)			// We use shift because CTRL doesn't want to work...
+				Con_SetFrac(.25f);
+			}
+		// !marky
     Con_ToggleConsole_f ();
+//		Key_ClearStates();	// marky
 		return;
 	}
 
@@ -1087,6 +1116,11 @@
 
 	// escape is always handled special
 	if ( key == K_ESCAPE && down ) {
+		// Cgg
+		if (DL_Active()) {
+			return;
+		}
+		// !Cgg
 		if ( cls.keyCatchers & KEYCATCH_MESSAGE ) {
 			// clear message mode
 			Message_Key( key );
@@ -1205,7 +1239,8 @@
 */
 void CL_CharEvent( int key ) {
 	// the console key should never be used as a char
-	if ( key == '`' || key == '~' ) {
+	if ( key == '`' || key == '~' 
+		|| key == 178 ) {	// Cgg - azerty french keyboard layout
 		return;
 	}
 
diff -wrubN quake3_1.32b/code/client/cl_main.c dfengine_1.07_src/code/client/cl_main.c
--- quake3_1.32b/code/client/cl_main.c	2009-04-18 19:32:30.000000000 +0200
+++ dfengine_1.07_src/code/client/cl_main.c	2009-04-18 19:37:40.000000000 +0200
@@ -500,12 +500,13 @@
 	char		retry[MAX_OSPATH];
 
 	if (Cmd_Argc() != 2) {
-		Com_Printf ("playdemo <demoname>\n");
+		Com_Printf ("usage: demo <demoname>\n");
 		return;
 	}
 
 	// make sure a local server is killed
 	Cvar_Set( "sv_killserver", "1" );
+	SV_Frame(0);	// Cgg - kill it now
 
 	CL_Disconnect( qtrue );
 
@@ -1973,7 +1974,7 @@
 */
 void CL_CheckUserinfo( void ) {
 	// don't add reliable commands when not yet connected
-	if ( cls.state < CA_CHALLENGING ) {
+	if ( cls.state < CA_CONNECTED && cls.state != CA_CINEMATIC ) {	// Cgg - was < CA_CHALLENGING 
 		return;
 	}
 	// don't overflow the reliable command buffer when paused
@@ -2279,7 +2280,10 @@
 	// register our variables
 	//
 	cl_noprint = Cvar_Get( "cl_noprint", "0", 0 );
-	cl_motd = Cvar_Get ("cl_motd", "1", 0);
+	cl_motd = Cvar_Get ("cl_motd", "0", 0);	// Cgg - global q3 motd
+											// Id's server replies with icmp "port unreachable".
+											// Making it disabled by default - saves a dns query, 
+											// an udp packet + the resulting icmp message.
 
 	cl_timeout = Cvar_Get ("cl_timeout", "200", 0);
 
@@ -2396,6 +2400,8 @@
 
 	SCR_Init ();
 
+	DL_Init();	// Cgg - client download
+
 	Cbuf_Execute ();
 
 	Cvar_Set( "cl_running", "1" );
@@ -2448,6 +2454,8 @@
 	Cmd_RemoveCommand ("showip");
 	Cmd_RemoveCommand ("model");
 
+	DL_Shutdown();	// Cgg
+	
 	Cvar_Set( "cl_running", "0" );
 
 	recursive = qfalse;
@@ -3320,5 +3328,3 @@
 
 	return qfalse;
 }
-
-
diff -wrubN quake3_1.32b/code/client/cl_parse.c dfengine_1.07_src/code/client/cl_parse.c
--- quake3_1.32b/code/client/cl_parse.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/client/cl_parse.c	2009-04-18 19:33:06.000000000 +0200
@@ -255,6 +255,16 @@
 
 	// read areamask
 	len = MSG_ReadByte( msg );
+	// Cgg - ioquake3 rev 796
+	// Fix remotely exploitable parse download overflow reported by Luigi Auriemma.
+	// See http://lists.grok.org.uk/pipermail/full-disclosure/2006-June/046578.html
+	// for the advisory.
+	if(len > sizeof(newSnap.areamask))
+	{
+		Com_Error (ERR_DROP,"CL_ParseSnapshot: Invalid size %d for areamask.", len);
+		return;
+	}
+	// !Cgg
 	MSG_ReadData( msg, &newSnap.areamask, len);
 
 	// read playerinfo
@@ -475,6 +485,17 @@
 	unsigned char data[MAX_MSGLEN];
 	int block;
 
+	// Cgg - ioquake3 rev 796
+	// Fix remotely exploitable parse download overflow reported by Luigi Auriemma.
+	// See http://lists.grok.org.uk/pipermail/full-disclosure/2006-June/046578.html
+	// for the advisory.
+	if (!*clc.downloadTempName) {
+		Com_Printf("Server sending download, but no download was requested\n");
+		CL_AddReliableCommand( "stopdl" );
+		return;
+	}
+	// !Cgg
+
 	// read the data
 	block = MSG_ReadShort ( msg );
 
@@ -493,8 +514,17 @@
 	}
 
 	size = MSG_ReadShort ( msg );
-	if (size > 0)
+	// Cgg - ioquake3 rev 796
+	// Fix remotely exploitable parse download overflow reported by Luigi Auriemma.
+	// See http://lists.grok.org.uk/pipermail/full-disclosure/2006-June/046578.html
+	// for the advisory.
+	if (size < 0 || size > sizeof(data))
+	{
+		Com_Error(ERR_DROP, "CL_ParseDownload: Invalid size %d for download chunk.", size);
+		return;
+	}
 		MSG_ReadData( msg, data, size );
+	// !Cgg
 
 	if (clc.downloadBlock != block) {
 		Com_DPrintf( "CL_ParseDownload: Expected block %d, got %d\n", clc.downloadBlock, block);
@@ -504,11 +534,17 @@
 	// open the file if not opened yet
 	if (!clc.download)
 	{
+		// Cgg - ioquake3 rev 796
+		// Fix remotely exploitable parse download overflow reported by Luigi Auriemma.
+		// See http://lists.grok.org.uk/pipermail/full-disclosure/2006-June/046578.html
+		// for the advisory.
+	/*
 		if (!*clc.downloadTempName) {
 			Com_Printf("Server sending download, but no download was requested\n");
 			CL_AddReliableCommand( "stopdl" );
 			return;
-		}
+		}*/
+		// !Cgg
 
 		clc.download = FS_SV_FOpenFileWrite( clc.downloadTempName );
 
diff -wrubN quake3_1.32b/code/client/cl_scrn.c dfengine_1.07_src/code/client/cl_scrn.c
--- quake3_1.32b/code/client/cl_scrn.c	2009-04-18 19:32:30.000000000 +0200
+++ dfengine_1.07_src/code/client/cl_scrn.c	2009-04-18 19:35:58.000000000 +0200
@@ -30,7 +30,7 @@
 cvar_t		*cl_graphheight;
 cvar_t		*cl_graphscale;
 cvar_t		*cl_graphshift;
-cvar_t		*cl_showRecording;	// Cgg
+cvar_t		*ch_recordMessage;	// Cgg
 
 /*
 ================
@@ -213,6 +213,11 @@
 			s += 2;
 			continue;
 		}
+		// Cgg - repeated escape codes (^^) were broken
+		if (*s == Q_COLOR_ESCAPE && *(s+1) == Q_COLOR_ESCAPE) {
+			s++;
+		}
+		// !Cgg
 		SCR_DrawChar( xx+2, y+2, size, *s );
 		xx += size;
 		s++;
@@ -233,6 +238,11 @@
 			s += 2;
 			continue;
 		}
+		// Cgg - repeated escape codes (^^) were broken
+		if (*s == Q_COLOR_ESCAPE && *(s+1) == Q_COLOR_ESCAPE) {
+			s++;
+		}
+		// !Cgg
 		SCR_DrawChar( xx, y, size, *s );
 		xx += size;
 		s++;
@@ -264,7 +274,8 @@
 Coordinates are at 640 by 480 virtual resolution
 ==================
 */
-void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor ) {
+// Cgg - added rawmode: stops color sequences from being interpreted
+void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor, qboolean rawmode ) {
 	vec4_t		color;
 	const char	*s;
 	int			xx;
@@ -274,7 +285,7 @@
 	xx = x;
 	re.SetColor( setColor );
 	while ( *s ) {
-		if ( Q_IsColorString( s ) ) {
+		if ( !rawmode && Q_IsColorString( s ) ) {
 			if ( !forceColor ) {
 				Com_Memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
 				color[3] = setColor[3];
@@ -283,6 +294,11 @@
 			s += 2;
 			continue;
 		}
+		// Cgg - repeated escape codes (^^) failed
+		if (!rawmode && *s == Q_COLOR_ESCAPE && *(s+1) == Q_COLOR_ESCAPE) {
+			s++;
+		}
+		// !Cgg
 		SCR_DrawSmallChar( xx, y, *s );
 		xx += SMALLCHAR_WIDTH;
 		s++;
@@ -302,10 +318,15 @@
 	while ( *s ) {
 		if ( Q_IsColorString( s ) ) {
 			s += 2;
-		} else {
-			count++;
+			continue;
+		}
+		// Cgg - repeated escape codes (^^) were broken
+		if (*s == Q_COLOR_ESCAPE && *(s+1) == Q_COLOR_ESCAPE) {
 			s++;
 		}
+		// !Cgg
+		count++;
+		s++;
 	}
 
 	return count;
@@ -331,7 +352,7 @@
 	int		pos;
 
 	// Cgg - off by default
-	if (!cl_showRecording->integer) {
+	if (!ch_recordMessage->integer) {
 		return;
 	}
 	// !Cgg
@@ -428,7 +449,7 @@
 	cl_graphheight = Cvar_Get ("graphheight", "32", CVAR_CHEAT);
 	cl_graphscale = Cvar_Get ("graphscale", "1", CVAR_CHEAT);
 	cl_graphshift = Cvar_Get ("graphshift", "0", CVAR_CHEAT);
-	cl_showRecording = Cvar_Get ("cl_showRecording", "0", CVAR_ARCHIVE);	// Cgg
+	ch_recordMessage = Cvar_Get ("ch_recordMessage", "0", CVAR_ARCHIVE);	// Cgg
 
 	scr_initialized = qtrue;
 }
diff -wrubN quake3_1.32b/code/client/snd_dma.c dfengine_1.07_src/code/client/snd_dma.c
--- quake3_1.32b/code/client/snd_dma.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/client/snd_dma.c	2009-05-26 12:06:05.000000000 +0200
@@ -181,7 +181,9 @@
 
 		S_StopAllSounds ();
 
-		S_SoundInfo_f();
+		// Cgg - spammy
+		//S_SoundInfo_f();
+		// !Cgg
 	}
 
 }
diff -wrubN quake3_1.32b/code/game/q_math.c dfengine_1.07_src/code/game/q_math.c
--- quake3_1.32b/code/game/q_math.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/game/q_math.c	2009-04-18 19:35:58.000000000 +0200
@@ -36,11 +36,12 @@
 vec4_t		colorMagenta= {1, 0, 1, 1};
 vec4_t		colorCyan	= {0, 1, 1, 1};
 vec4_t		colorWhite	= {1, 1, 1, 1};
+vec4_t		colorOrange	= {1, 0.5, 0, 1};
 vec4_t		colorLtGrey	= {0.75, 0.75, 0.75, 1};
 vec4_t		colorMdGrey	= {0.5, 0.5, 0.5, 1};
 vec4_t		colorDkGrey	= {0.25, 0.25, 0.25, 1};
 
-vec4_t	g_color_table[8] =
+vec4_t	g_color_table[10] =
 	{
 	{0.0, 0.0, 0.0, 1.0},
 	{1.0, 0.0, 0.0, 1.0},
@@ -50,6 +51,8 @@
 	{0.0, 1.0, 1.0, 1.0},
 	{1.0, 0.0, 1.0, 1.0},
 	{1.0, 1.0, 1.0, 1.0},
+	{1.0, 0.5, 0.0, 1.0},
+	{0.5, 0.5, 0.5, 1.0}
 	};
 
 
diff -wrubN quake3_1.32b/code/game/q_shared.c dfengine_1.07_src/code/game/q_shared.c
--- quake3_1.32b/code/game/q_shared.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/game/q_shared.c	2009-04-18 19:35:58.000000000 +0200
@@ -837,6 +837,11 @@
 			p += 2;
 			continue;
 		}
+		// Cgg - repeated escape codes (^^) were broken
+		if (*p == Q_COLOR_ESCAPE && *(p+1) == Q_COLOR_ESCAPE) {
+			p++;
+		}
+		// !Cgg
 		p++;
 		len++;
 	}
@@ -848,20 +853,25 @@
 char *Q_CleanStr( char *string ) {
 	char*	d;
 	char*	s;
-	int		c;
 
 	s = string;
 	d = string;
-	while ((c = *s) != 0 ) {
+	// Cgg - repeated escape codes (^^) were broken
+	while (*s) {
 		if ( Q_IsColorString( s ) ) {
+			s += 2;
+			continue;
+		}
+		if (*s == Q_COLOR_ESCAPE && *(s+1) == Q_COLOR_ESCAPE) {
 			s++;
 		}		
-		else if ( c >= 0x20 && c <= 0x7E ) {
-			*d++ = c;
+		if (*s >= 0x20 && *s <= 0x7E) {
+			*d++ = *s;
 		}
 		s++;
 	}
 	*d = '\0';
+	// !Cgg
 
 	return string;
 }
diff -wrubN quake3_1.32b/code/game/q_shared.h dfengine_1.07_src/code/game/q_shared.h
--- quake3_1.32b/code/game/q_shared.h	2009-04-18 19:32:30.000000000 +0200
+++ dfengine_1.07_src/code/game/q_shared.h	2009-06-08 21:12:45.000000000 +0200
@@ -26,8 +26,11 @@
 // q_shared.h -- included first by ALL program modules.
 // A user mod should never modify this file
 
-#define	Q3_VERSION		"Q3 1.32b"
+// Cgg
+#define	Q3_VERSION		"dfengine 1.07"
 // 1.32 released 7-10-2002
+#define Q3_WINDOW_TITLE Q3_VERSION
+// !Cgg
 
 #define MAX_TEAMNAME 32
 
@@ -54,7 +57,13 @@
 #pragma warning(disable : 4702)		// unreachable code
 #pragma warning(disable : 4711)		// selected for automatic inline expansion
 #pragma warning(disable : 4220)		// varargs matches remaining parameters
-#define _CRT_SECURE_NO_WARNINGS 1	// Cgg - disabling deprecated warnings in crt functions with msvc 2008
+// Cgg - disable various recent msvc warnings regarding "deprecated" C library functions.
+// Complying with this would impede the code portability either way.
+// Besides quake for the most part provides its own "secure" implementation of libc functions.
+#define _CRT_SECURE_NO_WARNINGS 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#pragma warning(disable : 4996)
+// !Cgg
 #endif
 
 /**********************************************************************
@@ -160,6 +169,9 @@
 
 #define	PATH_SEP '\\'
 
+// Cgg - portability
+#define strncasecmp strnicmp
+
 #endif
 
 //======================= MAC OS X DEFINES =====================
@@ -526,6 +538,7 @@
 extern	vec4_t		colorMagenta;
 extern	vec4_t		colorCyan;
 extern	vec4_t		colorWhite;
+extern	vec4_t		colorOrange;
 extern	vec4_t		colorLtGrey;
 extern	vec4_t		colorMdGrey;
 extern	vec4_t		colorDkGrey;
@@ -541,7 +554,9 @@
 #define COLOR_CYAN		'5'
 #define COLOR_MAGENTA	'6'
 #define COLOR_WHITE		'7'
-#define ColorIndex(c)	( ( (c) - '0' ) & 7 )
+#define COLOR_ORANGE	'8'
+#define COLOR_MDGREY	'9'
+#define ColorIndex(c)	( ( ( (c) - '0' ) &15 ) %10 )
 
 #define S_COLOR_BLACK	"^0"
 #define S_COLOR_RED		"^1"
@@ -551,8 +566,10 @@
 #define S_COLOR_CYAN	"^5"
 #define S_COLOR_MAGENTA	"^6"
 #define S_COLOR_WHITE	"^7"
+#define S_COLOR_ORANGE	"^8"
+#define S_COLOR_MDGREY	"^9"
 
-extern vec4_t	g_color_table[8];
+extern vec4_t	g_color_table[10];
 
 #define	MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b
 #define	MAKERGBA( v, r, g, b, a ) v[0]=r;v[1]=g;v[2]=b;v[3]=a
diff -wrubN quake3_1.32b/code/qcommon/cmd.c dfengine_1.07_src/code/qcommon/cmd.c
--- quake3_1.32b/code/qcommon/cmd.c	2009-04-18 19:32:30.000000000 +0200
+++ dfengine_1.07_src/code/qcommon/cmd.c	2009-04-18 19:34:04.000000000 +0200
@@ -24,7 +24,10 @@
 #include "../game/q_shared.h"
 #include "qcommon.h"
 
-#define	MAX_CMD_BUFFER	16384
+// Cgg - expanding command buffer from 16k to 64k
+//#define	MAX_CMD_BUFFER	16384
+#define	MAX_CMD_BUFFER	0x10000
+// !Cgg
 #define	MAX_CMD_LINE	1024
 
 typedef struct {
@@ -240,7 +243,6 @@
 	char	*f;
 	int		len;
 	char	filename[MAX_QPATH];
-	char	*c, *lf, *s;	// Cgg
 
 	if (Cmd_Argc () != 2) {
 		Com_Printf ("exec <filename> : execute a script file\n");
@@ -256,23 +258,7 @@
 	}
 	Com_Printf ("execing %s\n",Cmd_Argv(1));
 
-	// Cgg - execute the file buffer incrementally
-	Cbuf_Execute();
-	for (c=f,s=f,lf=f; *c; c++) {
-		if (*c == '\n') {
-			lf = c;
-		}
-		if (c - s >= 0x4000 -1) {
-			*lf = 0;
-			Cbuf_InsertText(s);
-			Cbuf_Execute();
-			s = lf+1;
-		}
-	}
-	Cbuf_InsertText(s);
-	Cbuf_Execute();
-	//was: Cbuf_InsertText (f);
-	// !Cgg
+	Cbuf_InsertText (f);
 
 	FS_FreeFile (f);
 }
diff -wrubN quake3_1.32b/code/qcommon/common.c dfengine_1.07_src/code/qcommon/common.c
--- quake3_1.32b/code/qcommon/common.c	2009-04-18 19:32:30.000000000 +0200
+++ dfengine_1.07_src/code/qcommon/common.c	2009-04-18 19:35:58.000000000 +0200
@@ -45,8 +45,8 @@
 #define DEF_COMHUNKMEGS "64"
 #define DEF_COMZONEMEGS "24"
 #else
-#define DEF_COMHUNKMEGS "56"
-#define DEF_COMZONEMEGS "16"
+#define DEF_COMHUNKMEGS "64"	// Cgg: was 56
+#define DEF_COMZONEMEGS "24"	// Cgg: was 16
 #endif
 
 int		com_argc;
@@ -1387,7 +1387,8 @@
 void Com_InitZoneMemory( void ) {
 	cvar_t	*cv;
 	// allocate the random block zone
-	cv = Cvar_Get( "com_zoneMegs", DEF_COMZONEMEGS, CVAR_LATCH | CVAR_ARCHIVE );
+	Com_StartupVariable("com_zoneMegs");	// Cgg: config files and command line options haven't been taken in account yet
+	cv = Cvar_Get( "com_zoneMegs", DEF_COMZONEMEGS, CVAR_LATCH );	// Cgg: was CVAR_ARCHIVE. Does not have meaning as this cvar can only be set through the command line
 
 	if ( cv->integer < 20 ) {
 		s_zoneTotal = 1024 * 1024 * 16;
@@ -3209,11 +3210,14 @@
 	}
 
 	// cut shortestMatch to the amount common with s
-	for ( i = 0 ; s[i] ; i++ ) {
+	// Cgg - was wrong when s had fewer chars than shortestMatch
+	i = 0;
+	do {
 		if ( tolower(shortestMatch[i]) != tolower(s[i]) ) {
 			shortestMatch[i] = 0;
 		}
-	}
+	} while (s[i++]);
+	// !Cgg
 }
 
 /*
diff -wrubN quake3_1.32b/code/qcommon/files.c dfengine_1.07_src/code/qcommon/files.c
--- quake3_1.32b/code/qcommon/files.c	2009-04-18 19:32:30.000000000 +0200
+++ dfengine_1.07_src/code/qcommon/files.c	2009-04-18 19:37:40.000000000 +0200
@@ -565,8 +565,9 @@
 
 ===========
 */
-static void FS_Remove( const char *osPath ) {
-	remove( osPath );
+// Cgg - returns qboolean
+static qboolean FS_Remove( const char *osPath ) {
+	return !remove( osPath );
 }
 
 /*
@@ -2511,8 +2512,40 @@
 	}
 	FS_FreeFileList(matches);
 
-	// demos
-	matches = FS_ListFilteredFiles(searchpath, ".dm_6?", NULL, &n);
+	// .dm_68
+	matches = FS_ListFilteredFiles(searchpath, ".dm_68", NULL, &n);
+	for (i=0; i<n; i++) {
+		// filter hidden files out
+		if (matches[i][0] == '.') {
+			continue;
+		}
+		if (strlen(path)) {
+			Com_sprintf(m, sizeof(m), "%s/%s", path, matches[i]);
+			nlist = FS_AddFileToList(m, list, nlist);
+			continue;
+		}
+		nlist = FS_AddFileToList(matches[i], list, nlist);
+	}
+	FS_FreeFileList(matches);
+
+	// .dm_67
+	matches = FS_ListFilteredFiles(searchpath, ".dm_67", NULL, &n);
+	for (i=0; i<n; i++) {
+		// filter hidden files out
+		if (matches[i][0] == '.') {
+			continue;
+		}
+		if (strlen(path)) {
+			Com_sprintf(m, sizeof(m), "%s/%s", path, matches[i]);
+			nlist = FS_AddFileToList(m, list, nlist);
+			continue;
+		}
+		nlist = FS_AddFileToList(matches[i], list, nlist);
+	}
+	FS_FreeFileList(matches);
+
+	// .dm_66
+	matches = FS_ListFilteredFiles(searchpath, ".dm_66", NULL, &n);
 	for (i=0; i<n; i++) {
 		// filter hidden files out
 		if (matches[i][0] == '.') {
@@ -2627,7 +2660,8 @@
 FS_idPak
 ================
 */
-qboolean FS_idPak( char *pak, char *base ) {
+// Cgg - added const qualifier
+qboolean FS_idPak( const char *pak, const char *base ) {
 	int i;
 
 	for (i = 0; i < NUM_ID_PAKS; i++) {
@@ -2853,7 +2887,7 @@
 		homePath = fs_basepath->string;
 	}
 	fs_homepath = Cvar_Get ("fs_homepath", homePath, CVAR_INIT );
-	fs_gamedirvar = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
+	fs_gamedirvar = Cvar_Get ("fs_game", "defrag", CVAR_INIT|CVAR_SYSTEMINFO );
 	fs_restrict = Cvar_Get ("fs_restrict", "", CVAR_INIT );
 
 	// add search path elements in reverse priority order
@@ -2911,8 +2945,10 @@
 	// reorder the pure pk3 files according to server order
 	FS_ReorderPurePaks();
 	
+// Cgg - gets spammy pretty quickly
 	// print the current search paths
-	FS_Path_f();
+//	FS_Path_f();
+// !Cgg
 
 	fs_gamedirvar->modified = qfalse; // We just loaded, it's not modified
 
@@ -3517,3 +3553,54 @@
 	fflush(fsh[f].handleFiles.file.o);
 }
 
+// Cgg
+// return the current gamedir (eg. "baseq3", "mymod", ...)
+const char *FS_GetGameDir() {
+	return fs_gamedir;
+}
+
+// remove a file from the homepath (eg. C:\quake3\; ~/.q3a/).
+qboolean FS_SV_RemoveFile(const char *qpath) {
+	char stripped[MAX_OSPATH];
+	char *ospath;
+	const char *c;
+	char *ext;
+
+	// make sure the given path doesn't try to climb up the file hierarchy.
+	if (strstr(qpath, "..") || strstr(qpath, "::")) {
+		Com_Printf("Warning: attempted to remove file with invalid path.\n");
+		return qfalse;
+	}
+	// prevent files in base directory from being removed - only files in subdirs can be.
+	for (c=qpath; *c == '/' || *c == '\\'; c++)
+		;
+	if (!strchr(c, '/') && !strchr(c, '\\')) {
+		Com_Printf("Warning: attempted to remove file from base directory.\n");
+		return qfalse;
+	}
+	// prevent id's packs from being removed.
+	// FS_idPak() takes a path without the pk3 extension.
+	Q_strncpyz(stripped, qpath, sizeof(stripped));
+	ext = stripped + strlen(stripped) -4;
+	if (ext > stripped && !strcmp(ext, ".pk3")) {
+		*ext = 0;
+		if (FS_idPak(stripped, "baseq3") || FS_idPak(stripped, "missionpack")) {
+			Com_Printf("Warning: attempted to remove Id's game packs.\n");
+			return qfalse;
+		}
+	}
+	// remove
+	ospath = FS_BuildOSPath(fs_homepath->string, qpath, "");
+	ospath[strlen(ospath)-1] = 0;
+	if (!FS_Remove(ospath)) {
+		Com_Printf("Warning: failed to remove file: %s\n", ospath);
+		return qfalse;
+	}
+	return qtrue;
+}
+
+// remove a file from homepath/gamedir (eg. C:\quake3\mymod\; ~/.q3a/mymod)
+qboolean FS_RemoveFile(const char *filename) {
+	return FS_SV_RemoveFile(va("%s/%s", fs_gamedir, filename));
+}
+// !Cgg
diff -wrubN quake3_1.32b/code/qcommon/huffman.c dfengine_1.07_src/code/qcommon/huffman.c
--- quake3_1.32b/code/qcommon/huffman.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/qcommon/huffman.c	2009-05-18 13:44:57.000000000 +0200
@@ -268,25 +268,6 @@
 	return (*ch = node->symbol);
 }
 
-/* Get a symbol */
-void Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset) {
-	bloc = *offset;
-	while (node && node->symbol == INTERNAL_NODE) {
-		if (get_bit(fin)) {
-			node = node->right;
-		} else {
-			node = node->left;
-		}
-	}
-	if (!node) {
-		*ch = 0;
-		return;
-//		Com_Error(ERR_DROP, "Illegal tree!\n");
-	}
-	*ch = node->symbol;
-	*offset = bloc;
-}
-
 /* Send the prefix code for this node */
 static void send(node_t *node, node_t *child, byte *fout) {
 	if (node->parent) {
@@ -315,12 +296,6 @@
 	}
 }
 
-void Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset) {
-	bloc = *offset;
-	send(huff->loc[ch], NULL, fout);
-	*offset = bloc;
-}
-
 void Huff_Decompress(msg_t *mbuf, int offset) {
 	int			ch, cch, i, j, size;
 	byte		seq[65536];
@@ -413,25 +388,3 @@
 	mbuf->cursize = (bloc>>3) + offset;
 	Com_Memcpy(mbuf->data+offset, seq, (bloc>>3));
 }
-
-void Huff_Init(huffman_t *huff) {
-
-	Com_Memset(&huff->compressor, 0, sizeof(huff_t));
-	Com_Memset(&huff->decompressor, 0, sizeof(huff_t));
-
-	// Initialize the tree & list with the NYT node 
-	huff->decompressor.tree = huff->decompressor.lhead = huff->decompressor.ltail = huff->decompressor.loc[NYT] = &(huff->decompressor.nodeList[huff->decompressor.blocNode++]);
-	huff->decompressor.tree->symbol = NYT;
-	huff->decompressor.tree->weight = 0;
-	huff->decompressor.lhead->next = huff->decompressor.lhead->prev = NULL;
-	huff->decompressor.tree->parent = huff->decompressor.tree->left = huff->decompressor.tree->right = NULL;
-
-	// Add the NYT (not yet transmitted) node into the tree/list */
-	huff->compressor.tree = huff->compressor.lhead = huff->compressor.loc[NYT] =  &(huff->compressor.nodeList[huff->compressor.blocNode++]);
-	huff->compressor.tree->symbol = NYT;
-	huff->compressor.tree->weight = 0;
-	huff->compressor.lhead->next = huff->compressor.lhead->prev = NULL;
-	huff->compressor.tree->parent = huff->compressor.tree->left = huff->compressor.tree->right = NULL;
-	huff->compressor.loc[NYT] = huff->compressor.tree;
-}
-
diff -wrubN quake3_1.32b/code/qcommon/huffman_static.c dfengine_1.07_src/code/qcommon/huffman_static.c
--- quake3_1.32b/code/qcommon/huffman_static.c	1970-01-01 01:00:00.000000000 +0100
+++ dfengine_1.07_src/code/qcommon/huffman_static.c	2009-05-18 14:31:25.000000000 +0200
@@ -0,0 +1,347 @@
+/*
+===========================================================================
+Copyright (C) 2009 Cyril Gantin
+
+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
+===========================================================================
+
+Quake 3 uses a prerendered huffman tree to compress netchan messages.
+
+This version is more efficient - eats up less memory, initializes faster - because it uses
+a static code instead of feeding the adaptative huffman algorithm with predefined values.
+
+*/
+
+#include "../game/q_shared.h"
+#include "qcommon.h"
+
+typedef struct {
+	int code:16;
+	int nbits:16;
+} huff_code_t;
+
+static huff_code_t huff_q3code[] = {
+	{ 0x002, 2 },		// 0
+	{ 0x01b, 5 },		// 1
+	{ 0x048, 7 },		// 2
+	{ 0x06c, 7 },		// 3
+	{ 0x0a1, 8 },		// 4
+	{ 0x011, 8 },		// 5
+	{ 0x010, 7 },		// 6
+	{ 0x03f, 6 },		// 7
+	{ 0x015, 5 },		// 8
+	{ 0x034, 7 },		// 9
+	{ 0x069, 7 },		// 10
+	{ 0x00b, 7 },		// 11
+	{ 0x013, 7 },		// 12
+	{ 0x02d, 6 },		// 13
+	{ 0x039, 8 },		// 14
+	{ 0x0ac, 9 },		// 15
+	{ 0x025, 7 },		// 16
+	{ 0x058, 9 },		// 17
+	{ 0x1f0, 9 },		// 18
+	{ 0x1f8, 9 },		// 19
+	{ 0x1dd, 10 },		// 20
+	{ 0x3f3, 10 },		// 21
+	{ 0x22b, 10 },		// 22
+	{ 0x323, 10 },		// 23
+	{ 0x0f4, 9 },		// 24
+	{ 0x18d, 10 },		// 25
+	{ 0x0ab, 10 },		// 26
+	{ 0x363, 10 },		// 27
+	{ 0x1eb, 10 },		// 28
+	{ 0x043, 8 },		// 29
+	{ 0x04f, 9 },		// 30
+	{ 0x0d4, 8 },		// 31
+	{ 0x037, 6 },		// 32
+	{ 0x0d3, 10 },		// 33
+	{ 0x044, 9 },		// 34
+	{ 0x2cd, 10 },		// 35
+	{ 0x3c5, 10 },		// 36
+	{ 0x3f9, 10 },		// 37
+	{ 0x30d, 10 },		// 38
+	{ 0x3cd, 10 },		// 39
+	{ 0x094, 9 },		// 40
+	{ 0x1ac, 10 },		// 41
+	{ 0x033, 10 },		// 42
+	{ 0x014, 10 },		// 43
+	{ 0x271, 10 },		// 44
+	{ 0x2f0, 10 },		// 45
+	{ 0x1f4, 9 },		// 46
+	{ 0x078, 8 },		// 47
+	{ 0x027, 7 },		// 48
+	{ 0x0c3, 8 },		// 49
+	{ 0x0ef, 8 },		// 50
+	{ 0x197, 9 },		// 51
+	{ 0x053, 8 },		// 52
+	{ 0x0b1, 8 },		// 53
+	{ 0x00d, 9 },		// 54
+	{ 0x161, 9 },		// 55
+	{ 0x007, 9 },		// 56
+	{ 0x0f1, 9 },		// 57
+	{ 0x199, 9 },		// 58
+	{ 0x191, 10 },		// 59
+	{ 0x123, 10 },		// 60
+	{ 0x0bc, 9 },		// 61
+	{ 0x144, 9 },		// 62
+	{ 0x1f3, 10 },		// 63
+	{ 0x0cf, 8 },		// 64
+	{ 0x050, 7 },		// 65
+	{ 0x07c, 7 },		// 66
+	{ 0x004, 7 },		// 67
+	{ 0x021, 8 },		// 68
+	{ 0x051, 8 },		// 69
+	{ 0x080, 9 },		// 70
+	{ 0x070, 9 },		// 71
+	{ 0x13d, 9 },		// 72
+	{ 0x063, 10 },		// 73
+	{ 0x2d7, 10 },		// 74
+	{ 0x371, 10 },		// 75
+	{ 0x19d, 9 },		// 76
+	{ 0x2ab, 10 },		// 77
+	{ 0x1c7, 10 },		// 78
+	{ 0x333, 10 },		// 79
+	{ 0x12c, 9 },		// 80
+	{ 0x09d, 10 },		// 81
+	{ 0x16b, 10 },		// 82
+	{ 0x36b, 10 },		// 83
+	{ 0x1d3, 10 },		// 84
+	{ 0x171, 10 },		// 85
+	{ 0x1e3, 10 },		// 86
+	{ 0x233, 10 },		// 87
+	{ 0x0d7, 10 },		// 88
+	{ 0x2cb, 10 },		// 89
+	{ 0x170, 9 },		// 90
+	{ 0x0a8, 9 },		// 91
+	{ 0x0c7, 9 },		// 92
+	{ 0x105, 9 },		// 93
+	{ 0x0eb, 9 },		// 94
+	{ 0x0d8, 8 },		// 95
+	{ 0x0f3, 9 },		// 96
+	{ 0x03c, 8 },		// 97
+	{ 0x1ab, 9 },		// 98
+	{ 0x18f, 9 },		// 99
+	{ 0x097, 9 },		// 100
+	{ 0x030, 7 },		// 101
+	{ 0x041, 8 },		// 102
+	{ 0x14f, 9 },		// 103
+	{ 0x01c, 6 },		// 104
+	{ 0x028, 8 },		// 105
+	{ 0x0bd, 9 },		// 106
+	{ 0x0c4, 9 },		// 107
+	{ 0x098, 8 },		// 108
+	{ 0x08f, 9 },		// 109
+	{ 0x00c, 8 },		// 110
+	{ 0x0b3, 8 },		// 111
+	{ 0x085, 8 },		// 112
+	{ 0x08c, 8 },		// 113
+	{ 0x047, 8 },		// 114
+	{ 0x079, 8 },		// 115
+	{ 0x059, 7 },		// 116
+	{ 0x040, 7 },		// 117
+	{ 0x017, 8 },		// 118
+	{ 0x019, 8 },		// 119
+	{ 0x04b, 8 },		// 120
+	{ 0x0e1, 8 },		// 121
+	{ 0x0a3, 8 },		// 122
+	{ 0x073, 8 },		// 123
+	{ 0x06f, 8 },		// 124
+	{ 0x068, 7 },		// 125
+	{ 0x008, 7 },		// 126
+	{ 0x065, 7 },		// 127
+	{ 0x01f, 6 },		// 128
+	{ 0x029, 7 },		// 129
+	{ 0x04c, 7 },		// 130
+	{ 0x07d, 7 },		// 131
+	{ 0x00f, 8 },		// 132
+	{ 0x083, 8 },		// 133
+	{ 0x001, 8 },		// 134
+	{ 0x087, 8 },		// 135
+	{ 0x067, 8 },		// 136
+	{ 0x0e7, 8 },		// 137
+	{ 0x057, 8 },		// 138
+	{ 0x074, 8 },		// 139
+	{ 0x1cb, 9 },		// 140
+	{ 0x1c4, 9 },		// 141
+	{ 0x081, 9 },		// 142
+	{ 0x04d, 9 },		// 143
+	{ 0x131, 9 },		// 144
+	{ 0x163, 10 },		// 145
+	{ 0x180, 9 },		// 146
+	{ 0x3d7, 10 },		// 147
+	{ 0x02b, 10 },		// 148
+	{ 0x145, 10 },		// 149
+	{ 0x06b, 10 },		// 150
+	{ 0x03d, 10 },		// 151
+	{ 0x32b, 10 },		// 152
+	{ 0x0f9, 10 },		// 153
+	{ 0x0e3, 10 },		// 154
+	{ 0x245, 10 },		// 155
+	{ 0x12b, 10 },		// 156
+	{ 0x031, 10 },		// 157
+	{ 0x3eb, 10 },		// 158
+	{ 0x1b9, 10 },		// 159
+	{ 0x114, 9 },		// 160
+	{ 0x1f9, 10 },		// 161
+	{ 0x133, 10 },		// 162
+	{ 0x02c, 10 },		// 163
+	{ 0x2dd, 10 },		// 164
+	{ 0x1c1, 10 },		// 165
+	{ 0x31d, 10 },		// 166
+	{ 0x1d1, 10 },		// 167
+	{ 0x138, 9 },		// 168
+	{ 0x061, 10 },		// 169
+	{ 0x2e3, 10 },		// 170
+	{ 0x345, 10 },		// 171
+	{ 0x26b, 10 },		// 172
+	{ 0x0cd, 10 },		// 173
+	{ 0x0cb, 10 },		// 174
+	{ 0x14d, 10 },		// 175
+	{ 0x038, 9 },		// 176
+	{ 0x3c1, 10 },		// 177
+	{ 0x23d, 10 },		// 178
+	{ 0x3bc, 10 },		// 179
+	{ 0x0c5, 10 },		// 180
+	{ 0x3ac, 10 },		// 181
+	{ 0x3e3, 10 },		// 182
+	{ 0x299, 10 },		// 183
+	{ 0x3d3, 10 },		// 184
+	{ 0x214, 10 },		// 185
+	{ 0x203, 10 },		// 186
+	{ 0x1bc, 10 },		// 187
+	{ 0x29d, 10 },		// 188
+	{ 0x381, 10 },		// 189
+	{ 0x263, 10 },		// 190
+	{ 0x08d, 10 },		// 191
+	{ 0x054, 8 },		// 192
+	{ 0x103, 9 },		// 193
+	{ 0x05d, 8 },		// 194
+	{ 0x020, 6 },		// 195
+	{ 0x009, 7 },		// 196
+	{ 0x3c7, 10 },		// 197
+	{ 0x307, 10 },		// 198
+	{ 0x0b8, 8 },		// 199
+	{ 0x1f1, 9 },		// 200
+	{ 0x22c, 10 },		// 201
+	{ 0x045, 10 },		// 202
+	{ 0x003, 10 },		// 203
+	{ 0x11d, 10 },		// 204
+	{ 0x1c5, 10 },		// 205
+	{ 0x34d, 10 },		// 206
+	{ 0x01d, 10 },		// 207
+	{ 0x000, 9 },		// 208
+	{ 0x3b9, 10 },		// 209
+	{ 0x0dd, 10 },		// 210
+	{ 0x181, 10 },		// 211
+	{ 0x10d, 10 },		// 212
+	{ 0x0b9, 10 },		// 213
+	{ 0x1cd, 10 },		// 214
+	{ 0x394, 10 },		// 215
+	{ 0x1bd, 10 },		// 216
+	{ 0x194, 10 },		// 217
+	{ 0x38d, 10 },		// 218
+	{ 0x158, 10 },		// 219
+	{ 0x3bd, 10 },		// 220
+	{ 0x0c1, 10 },		// 221
+	{ 0x3dd, 10 },		// 222
+	{ 0x0f8, 10 },		// 223
+	{ 0x0d1, 9 },		// 224
+	{ 0x091, 9 },		// 225
+	{ 0x099, 10 },		// 226
+	{ 0x2f8, 10 },		// 227
+	{ 0x023, 10 },		// 228
+	{ 0x071, 10 },		// 229
+	{ 0x2d3, 10 },		// 230
+	{ 0x391, 10 },		// 231
+	{ 0x049, 7 },		// 232
+	{ 0x231, 10 },		// 233
+	{ 0x107, 10 },		// 234
+	{ 0x261, 10 },		// 235
+	{ 0x223, 10 },		// 236
+	{ 0x018, 8 },		// 237
+	{ 0x205, 10 },		// 238
+	{ 0x2c1, 10 },		// 239
+	{ 0x1d7, 10 },		// 240
+	{ 0x0f0, 10 },		// 241
+	{ 0x2c5, 10 },		// 242
+	{ 0x300, 10 },		// 243
+	{ 0x3d1, 10 },		// 244
+	{ 0x3a8, 10 },		// 245
+	{ 0x21d, 10 },		// 246
+	{ 0x500, 11 },		// 247
+	{ 0x005, 10 },		// 248
+	{ 0x358, 10 },		// 249
+	{ 0x2f9, 10 },		// 250
+	{ 0x1a8, 10 },		// 251
+	{ 0x2b9, 10 },		// 252
+	{ 0x28d, 10 },		// 253
+	{ 0x02f, 7 },		// 254
+	{ 0x024, 6 }		// 255
+};
+
+// adapted from huffman.c
+static void add_bit(char bit, byte *fout, int *offset) {
+	if ((*offset&7) == 0) {
+		fout[(*offset>>3)] = 0;
+	}
+	fout[(*offset>>3)] |= bit << (*offset&7);
+	(*offset)++;
+}
+
+// adapted from huffman.c
+static int get_bit(byte *fin, int *offset) {
+	int t;
+	t = (fin[(*offset>>3)] >> (*offset&7)) & 0x1;
+	(*offset)++;
+	return t;
+}
+
+static int getSymbolForCode(huff_code_t c) {
+	int i;
+	for (i=0; i<256; i++) {
+		if (huff_q3code[i].nbits == c.nbits && huff_q3code[i].code == c.code) {
+			return i;
+		}
+	}
+	return -1;
+}
+void Huff_offsetReceive(int *ch, byte *fin, int *offset) {
+	huff_code_t c;
+	memset(&c, 0, sizeof(c));
+	c.code |= get_bit(fin, offset) << c.nbits++;
+	c.code |= get_bit(fin, offset) << c.nbits++;
+	while ((*ch = getSymbolForCode(c)) == -1) {
+		c.code |= get_bit(fin, offset) << c.nbits++;
+		if (c.nbits	> 11) {
+			*ch = 0;
+			return;	/* code depth reached */
+		}
+	}
+}
+
+void Huff_offsetTransmit(int ch, byte *fout, int *offset) {
+	const huff_code_t *c;
+	int i;
+
+	if (ch < 0 || ch > 255) {
+		Com_Error(ERR_FATAL, "Huffman compression: invalid symbol 0x%x.", ch);
+	}
+	c = huff_q3code+ch;
+	for (i= 0; i<c->nbits; i++) {
+		add_bit((c->code>>i) &1, fout, offset);
+	}
+}
diff -wrubN quake3_1.32b/code/qcommon/msg.c dfengine_1.07_src/code/qcommon/msg.c
--- quake3_1.32b/code/qcommon/msg.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/qcommon/msg.c	2009-05-18 13:44:57.000000000 +0200
@@ -22,10 +22,6 @@
 #include "../game/q_shared.h"
 #include "qcommon.h"
 
-static huffman_t		msgHuff;
-
-static qboolean			msgInit = qfalse;
-
 int pcount[256];
 
 /*
@@ -39,21 +35,13 @@
 
 int oldsize = 0;
 
-void MSG_initHuffman();
-
 void MSG_Init( msg_t *buf, byte *data, int length ) {
-	if (!msgInit) {
-		MSG_initHuffman();
-	}
 	Com_Memset (buf, 0, sizeof(*buf));
 	buf->data = data;
 	buf->maxsize = length;
 }
 
 void MSG_InitOOB( msg_t *buf, byte *data, int length ) {
-	if (!msgInit) {
-		MSG_initHuffman();
-	}
 	Com_Memset (buf, 0, sizeof(*buf));
 	buf->data = data;
 	buf->maxsize = length;
@@ -172,7 +160,7 @@
 		if (bits) {
 			for(i=0;i<bits;i+=8) {
 //				fwrite(bp, 1, 1, fp);
-				Huff_offsetTransmit (&msgHuff.compressor, (value&0xff), msg->data, &msg->bit);
+				Huff_offsetTransmit ((value&0xff), msg->data, &msg->bit);
 				value = (value>>8);
 			}
 		}
@@ -227,7 +215,7 @@
 		if (bits) {
 //			fp = fopen("c:\\netchan.bin", "a");
 			for(i=0;i<bits;i+=8) {
-				Huff_offsetReceive (msgHuff.decompressor.tree, &get, msg->data, &msg->bit);
+				Huff_offsetReceive (&get, msg->data, &msg->bit);
 //				fwrite(&get, 1, 1, fp);
 				value |= (get<<(i+nbits));
 			}
@@ -1447,311 +1435,4 @@
 	}
 }
 
-int msg_hData[256] = {
-250315,			// 0
-41193,			// 1
-6292,			// 2
-7106,			// 3
-3730,			// 4
-3750,			// 5
-6110,			// 6
-23283,			// 7
-33317,			// 8
-6950,			// 9
-7838,			// 10
-9714,			// 11
-9257,			// 12
-17259,			// 13
-3949,			// 14
-1778,			// 15
-8288,			// 16
-1604,			// 17
-1590,			// 18
-1663,			// 19
-1100,			// 20
-1213,			// 21
-1238,			// 22
-1134,			// 23
-1749,			// 24
-1059,			// 25
-1246,			// 26
-1149,			// 27
-1273,			// 28
-4486,			// 29
-2805,			// 30
-3472,			// 31
-21819,			// 32
-1159,			// 33
-1670,			// 34
-1066,			// 35
-1043,			// 36
-1012,			// 37
-1053,			// 38
-1070,			// 39
-1726,			// 40
-888,			// 41
-1180,			// 42
-850,			// 43
-960,			// 44
-780,			// 45
-1752,			// 46
-3296,			// 47
-10630,			// 48
-4514,			// 49
-5881,			// 50
-2685,			// 51
-4650,			// 52
-3837,			// 53
-2093,			// 54
-1867,			// 55
-2584,			// 56
-1949,			// 57
-1972,			// 58
-940,			// 59
-1134,			// 60
-1788,			// 61
-1670,			// 62
-1206,			// 63
-5719,			// 64
-6128,			// 65
-7222,			// 66
-6654,			// 67
-3710,			// 68
-3795,			// 69
-1492,			// 70
-1524,			// 71
-2215,			// 72
-1140,			// 73
-1355,			// 74
-971,			// 75
-2180,			// 76
-1248,			// 77
-1328,			// 78
-1195,			// 79
-1770,			// 80
-1078,			// 81
-1264,			// 82
-1266,			// 83
-1168,			// 84
-965,			// 85
-1155,			// 86
-1186,			// 87
-1347,			// 88
-1228,			// 89
-1529,			// 90
-1600,			// 91
-2617,			// 92
-2048,			// 93
-2546,			// 94
-3275,			// 95
-2410,			// 96
-3585,			// 97
-2504,			// 98
-2800,			// 99
-2675,			// 100
-6146,			// 101
-3663,			// 102
-2840,			// 103
-14253,			// 104
-3164,			// 105
-2221,			// 106
-1687,			// 107
-3208,			// 108
-2739,			// 109
-3512,			// 110
-4796,			// 111
-4091,			// 112
-3515,			// 113
-5288,			// 114
-4016,			// 115
-7937,			// 116
-6031,			// 117
-5360,			// 118
-3924,			// 119
-4892,			// 120
-3743,			// 121
-4566,			// 122
-4807,			// 123
-5852,			// 124
-6400,			// 125
-6225,			// 126
-8291,			// 127
-23243,			// 128
-7838,			// 129
-7073,			// 130
-8935,			// 131
-5437,			// 132
-4483,			// 133
-3641,			// 134
-5256,			// 135
-5312,			// 136
-5328,			// 137
-5370,			// 138
-3492,			// 139
-2458,			// 140
-1694,			// 141
-1821,			// 142
-2121,			// 143
-1916,			// 144
-1149,			// 145
-1516,			// 146
-1367,			// 147
-1236,			// 148
-1029,			// 149
-1258,			// 150
-1104,			// 151
-1245,			// 152
-1006,			// 153
-1149,			// 154
-1025,			// 155
-1241,			// 156
-952,			// 157
-1287,			// 158
-997,			// 159
-1713,			// 160
-1009,			// 161
-1187,			// 162
-879,			// 163
-1099,			// 164
-929,			// 165
-1078,			// 166
-951,			// 167
-1656,			// 168
-930,			// 169
-1153,			// 170
-1030,			// 171
-1262,			// 172
-1062,			// 173
-1214,			// 174
-1060,			// 175
-1621,			// 176
-930,			// 177
-1106,			// 178
-912,			// 179
-1034,			// 180
-892,			// 181
-1158,			// 182
-990,			// 183
-1175,			// 184
-850,			// 185
-1121,			// 186
-903,			// 187
-1087,			// 188
-920,			// 189
-1144,			// 190
-1056,			// 191
-3462,			// 192
-2240,			// 193
-4397,			// 194
-12136,			// 195
-7758,			// 196
-1345,			// 197
-1307,			// 198
-3278,			// 199
-1950,			// 200
-886,			// 201
-1023,			// 202
-1112,			// 203
-1077,			// 204
-1042,			// 205
-1061,			// 206
-1071,			// 207
-1484,			// 208
-1001,			// 209
-1096,			// 210
-915,			// 211
-1052,			// 212
-995,			// 213
-1070,			// 214
-876,			// 215
-1111,			// 216
-851,			// 217
-1059,			// 218
-805,			// 219
-1112,			// 220
-923,			// 221
-1103,			// 222
-817,			// 223
-1899,			// 224
-1872,			// 225
-976,			// 226
-841,			// 227
-1127,			// 228
-956,			// 229
-1159,			// 230
-950,			// 231
-7791,			// 232
-954,			// 233
-1289,			// 234
-933,			// 235
-1127,			// 236
-3207,			// 237
-1020,			// 238
-927,			// 239
-1355,			// 240
-768,			// 241
-1040,			// 242
-745,			// 243
-952,			// 244
-805,			// 245
-1073,			// 246
-740,			// 247
-1013,			// 248
-805,			// 249
-1008,			// 250
-796,			// 251
-996,			// 252
-1057,			// 253
-11457,			// 254
-13504,			// 255
-};
-
-void MSG_initHuffman() {
-	int i,j;
-
-	msgInit = qtrue;
-	Huff_Init(&msgHuff);
-	for(i=0;i<256;i++) {
-		for (j=0;j<msg_hData[i];j++) {
-			Huff_addRef(&msgHuff.compressor,	(byte)i);			// Do update
-			Huff_addRef(&msgHuff.decompressor,	(byte)i);			// Do update
-		}
-	}
-}
-
-/*
-void MSG_NUinitHuffman() {
-	byte	*data;
-	int		size, i, ch;
-	int		array[256];
-
-	msgInit = qtrue;
-
-	Huff_Init(&msgHuff);
-	// load it in
-	size = FS_ReadFile( "netchan/netchan.bin", (void **)&data );
-
-	for(i=0;i<256;i++) {
-		array[i] = 0;
-	}
-	for(i=0;i<size;i++) {
-		ch = data[i];
-		Huff_addRef(&msgHuff.compressor,	ch);			// Do update
-		Huff_addRef(&msgHuff.decompressor,	ch);			// Do update
-		array[ch]++;
-	}
-	Com_Printf("msg_hData {\n");
-	for(i=0;i<256;i++) {
-		if (array[i] == 0) {
-			Huff_addRef(&msgHuff.compressor,	i);			// Do update
-			Huff_addRef(&msgHuff.decompressor,	i);			// Do update
-		}
-		Com_Printf("%d,			// %d\n", array[i], i);
-	}
-	Com_Printf("};\n");
-	FS_FreeFile( data );
-	Cbuf_AddText( "condump dump.txt\n" );
-}
-*/
-
 //===========================================================================
diff -wrubN quake3_1.32b/code/qcommon/qcommon.h dfengine_1.07_src/code/qcommon/qcommon.h
--- quake3_1.32b/code/qcommon/qcommon.h	2009-04-18 19:32:30.000000000 +0200
+++ dfengine_1.07_src/code/qcommon/qcommon.h	2009-05-18 13:44:57.000000000 +0200
@@ -543,6 +543,7 @@
 // will properly create any needed paths and deal with seperater character issues
 
 int		FS_filelength( fileHandle_t f );
+qboolean FS_SV_FileExists( const char *file );	// Cgg - was missing
 fileHandle_t FS_SV_FOpenFileWrite( const char *filename );
 int		FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp );
 void	FS_SV_Rename( const char *from, const char *to );
@@ -627,12 +628,19 @@
 // separated checksums will be checked for files, with the
 // sole exception of .cfg files.
 
-qboolean FS_idPak( char *pak, char *base );
+qboolean FS_idPak( const char *pak, const char *base );
 qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring );
 
 void FS_Rename( const char *from, const char *to );
 
-// Cgg - autocompletion on map & demo names
+// Cgg
+// return the current gamedir (eg. "baseq3", "mymod"...)
+const char *FS_GetGameDir();
+// remove a file from the homepath (eg. C:\quake3\; ~/.q3a/)
+qboolean FS_SV_RemoveFile(const char *filepath);
+// remove a file from homepath/gamedir (eg. C:\quake3\mymod\; ~/.q3a/mymod)
+qboolean FS_RemoveFile(const char *filename);
+// autocompletion on map & demo names
 void Maps_CommandCompletion(void (*callback) (const char *s));
 void Demos_CommandCompletion(void (*callback) (const char *s));
 // !Cgg
@@ -1042,28 +1050,21 @@
 	node_t*		loc[HMAX+1];
 	node_t**	freelist;
 
-	node_t		nodeList[768];
-	node_t*		nodePtrs[768];
+	// Cgg - had 768 nodes; while actual max is (256 values + NYT) *2 -1 => 513
+	node_t		nodeList[513];
+	node_t*		nodePtrs[513];
 } huff_t;
 
-typedef struct {
-	huff_t		compressor;
-	huff_t		decompressor;
-} huffman_t;
-
 void	Huff_Compress(msg_t *buf, int offset);
 void	Huff_Decompress(msg_t *buf, int offset);
-void	Huff_Init(huffman_t *huff);
 void	Huff_addRef(huff_t* huff, byte ch);
 int		Huff_Receive (node_t *node, int *ch, byte *fin);
 void	Huff_transmit (huff_t *huff, int ch, byte *fout);
-void	Huff_offsetReceive (node_t *node, int *ch, byte *fin, int *offset);
-void	Huff_offsetTransmit (huff_t *huff, int ch, byte *fout, int *offset);
+void	Huff_offsetReceive (int *ch, byte *fin, int *offset);	// Cgg (changed prototype)
+void	Huff_offsetTransmit (int ch, byte *fout, int *offset);	// Cgg (changed prototype)
 void	Huff_putBit( int bit, byte *fout, int *offset);
 int		Huff_getBit( byte *fout, int *offset);
 
-extern huffman_t clientHuffTables;
-
 #define	SV_ENCODE_START		4
 #define SV_DECODE_START		12
 #define	CL_ENCODE_START		12
diff -wrubN quake3_1.32b/code/renderer/qgl.h dfengine_1.07_src/code/renderer/qgl.h
--- quake3_1.32b/code/renderer/qgl.h	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/renderer/qgl.h	2009-04-18 19:37:40.000000000 +0200
@@ -90,6 +90,12 @@
 #define GL_TEXTURE2_ARB                     0x84C2
 #define GL_TEXTURE3_ARB                     0x84C3
 
+// marky
+#ifndef GL_EXT_texture_edge_clamp
+#define GL_EXT_CLAMP_TO_EDGE                 0x812F
+#endif
+// !marky
+
 // NOTE: some Linux platforms would need those prototypes
 #if defined(MACOS_X)
 typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
diff -wrubN quake3_1.32b/code/renderer/tr_init.c dfengine_1.07_src/code/renderer/tr_init.c
--- quake3_1.32b/code/renderer/tr_init.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/renderer/tr_init.c	2009-05-26 12:06:05.000000000 +0200
@@ -226,8 +226,10 @@
 	// init command buffers and SMP
 	R_InitCommandBuffers();
 
+	// Cgg - spammy
 	// print info
-	GfxInfo_f();
+	//GfxInfo_f();
+	// !Cgg
 
 	// set default state
 	GL_SetDefaultState();
@@ -384,6 +386,7 @@
 	buffer[15] = height >> 8;
 	buffer[16] = 24;	// pixel size
 
+	qglPixelStorei(GL_PACK_ALIGNMENT, 1); //marky: fixes nonstandard res'
 	qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); 
 
 	// swap rgb to bgr
@@ -847,6 +850,43 @@
 	}
 }
 
+
+// drakkar
+/*
+================
+R_WindowMode_f
+================
+*/
+void R_WindowMode_f( void ) 
+{
+	char *str = NULL;
+
+	str = ri.Cmd_Argv(1);
+	
+	if     ( !strncasecmp( str, "restart",        7 ) )  GLimp_WindowMode( WMODE_RESTART );
+	else if( !strncasecmp( str, "minimized",      3 ) )  GLimp_WindowMode( WMODE_SET_MINIMIZED );
+	else if( !strncasecmp( str, "windowed",       3 ) )  GLimp_WindowMode( WMODE_SET_WINDOWED );
+	else if( !strncasecmp( str, "fullscreen",     4 ) )  GLimp_WindowMode( WMODE_SET_FULLSCREEN );
+	else if( !strncasecmp( str, "swapFullscreen", 8 ) )  GLimp_WindowMode( WMODE_SWAP_FULLSCREEN );
+	else if( !strncasecmp( str, "swapMinimized",  7 ) )  GLimp_WindowMode( WMODE_SWAP_MINIMIZED );
+	else
+	{
+		str = ri.Cmd_Argv(0);
+		ri.Printf( PRINT_ALL,
+			"How to use:\n"
+			"\\%s restart\n"
+			"\\%s minimized\n"
+			"\\%s windowed\n"
+			"\\%s fullscreen\n"
+			"\\%s swapFullscreen\n"
+			"\\%s swapMinimized\n"
+			, str, str, str, str, str, str
+		);
+	}
+}
+// !drakkar
+
+
 /*
 ===============
 R_Register
@@ -1003,6 +1043,9 @@
 	ri.Cmd_AddCommand( "screenshot", R_ScreenShot_f );
 	ri.Cmd_AddCommand( "screenshotJPEG", R_ScreenShotJPEG_f );
 	ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
+	// drakkar
+	ri.Cmd_AddCommand( "windowMode", R_WindowMode_f );
+	// !drakkar
 }
 
 /*
@@ -1122,6 +1165,9 @@
 	ri.Cmd_RemoveCommand ("gfxinfo");
 	ri.Cmd_RemoveCommand( "modelist" );
 	ri.Cmd_RemoveCommand( "shaderstate" );
+	// drakkar
+	ri.Cmd_RemoveCommand( "windowMode" );
+	// !drakkar
 
 
 	if ( tr.registered ) {
diff -wrubN quake3_1.32b/code/renderer/tr_local.h dfengine_1.07_src/code/renderer/tr_local.h
--- quake3_1.32b/code/renderer/tr_local.h	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/renderer/tr_local.h	2009-05-21 14:53:03.000000000 +0200
@@ -1247,6 +1247,18 @@
 						    unsigned char green[256],
 							unsigned char blue[256] );
 
+// drakkar
+typedef enum {
+	WMODE_RESTART = 0,
+	WMODE_SET_MINIMIZED,
+	WMODE_SET_WINDOWED,
+	WMODE_SET_FULLSCREEN,
+	WMODE_SWAP_FULLSCREEN,
+	WMODE_SWAP_MINIMIZED
+} windowMode_t;
+void GLimp_WindowMode( windowMode_t wmode );
+// !drakkar
+
 
 /*
 ====================================================================
diff -wrubN quake3_1.32b/code/renderer/tr_shader.c dfengine_1.07_src/code/renderer/tr_shader.c
--- quake3_1.32b/code/renderer/tr_shader.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/renderer/tr_shader.c	2009-05-26 12:06:05.000000000 +0200
@@ -1227,7 +1227,7 @@
 		for (i=0 ; i<6 ; i++) {
 			Com_sprintf( pathname, sizeof(pathname), "%s_%s.tga"
 				, token, suf[i] );
-			shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_CLAMP );
+			shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_EXT_CLAMP_TO_EDGE );	// marky: GL_CLAMP to GL_CLAMP_TO_EDGE
 			if ( !shader.sky.outerbox[i] ) {
 				shader.sky.outerbox[i] = tr.defaultImage;
 			}
@@ -2872,7 +2872,9 @@
 		char filename[MAX_QPATH];
 
 		Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] );
-		ri.Printf( PRINT_ALL, "...loading '%s'\n", filename );
+// Cgg - spammy and rather pointless - made it PRINT_DEV
+		ri.Printf( PRINT_DEVELOPER, "...loading '%s'\n", filename );
+// !Cgg
 		sum += ri.FS_ReadFile( filename, (void **)&buffers[i] );
 		if ( !buffers[i] ) {
 			ri.Error( ERR_DROP, "Couldn't load %s", filename );
diff -wrubN quake3_1.32b/code/ui/keycodes.h dfengine_1.07_src/code/ui/keycodes.h
--- quake3_1.32b/code/ui/keycodes.h	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/ui/keycodes.h	2009-05-25 11:51:16.000000000 +0200
@@ -151,6 +151,11 @@
 	K_AUX15,
 	K_AUX16,
 
+// drakkar
+	K_WIN,
+	K_MENU,
+// !drakkar
+
 	K_LAST_KEY		// this had better be <256!
 } keyNum_t;
 
diff -wrubN quake3_1.32b/code/unix/linux_glimp.c dfengine_1.07_src/code/unix/linux_glimp.c
--- quake3_1.32b/code/unix/linux_glimp.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/unix/linux_glimp.c	2009-06-08 21:11:39.000000000 +0200
@@ -69,7 +69,9 @@
 #include <X11/extensions/xf86dga.h>
 #include <X11/extensions/xf86vmode.h>
 
-#define	WINDOW_CLASS_NAME	"Quake III: Arena"
+// Cgg
+#define	WINDOW_CLASS_NAME Q3_WINDOW_TITLE
+//"Quake III: Arena"
 
 typedef enum
 {
@@ -87,14 +89,18 @@
 static int scrnum;
 static Window win = 0;
 static GLXContext ctx = NULL;
+static XVisualInfo *visinfo = NULL; // drakkar - create once and reuse
 
 // bk001206 - not needed anymore
 // static qboolean autorepeaton = qtrue;
 
 #define KEY_MASK (KeyPressMask | KeyReleaseMask)
-#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
-		    PointerMotionMask | ButtonMotionMask )
-#define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask )
+#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask )
+// drakkar
+//- #define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask )
+#define WINDOW_MASK ( VisibilityChangeMask | StructureNotifyMask | FocusChangeMask )
+#define X_MASK ( KEY_MASK | MOUSE_MASK | WINDOW_MASK )
+// /drakkar
 
 static qboolean mouse_avail;
 static qboolean mouse_active = qfalse;
@@ -122,11 +128,20 @@
 static int vidmode_MajorVersion = 0, vidmode_MinorVersion = 0; // major and minor of XF86VidExtensions
 
 // gamma value of the X display before we start playing with it
-static XF86VidModeGamma vidmode_InitialGamma;
+static XF86VidModeGamma vidmode_InitialGamma = { -1,-1,-1 };  // drakkar - initialized to nonvalid values
 
-static int win_x, win_y;
+static int win_x = 50, win_y = 50;  // drakkar - initialize window position
 
-static XF86VidModeModeInfo **vidmodes;
+// drakkar
+qboolean win_active = qtrue;
+static qboolean win_minimized = qfalse;
+static qboolean windowModeLock = qtrue;
+static unsigned long int ignoreFocus = 0;
+static XF86VidModeModeInfo desktopVideoModeInfo = { 0,0,0,0,0,0,0,0,0,0,0,0 };
+static int desktopVideoMode = -1;
+// !drakkar
+
+static XF86VidModeModeInfo **vidmodes = NULL;  // drakkar - initialized to NULL
 //static int default_dotclock_vidmode; // bk001204 - unused
 static int num_vidmodes;
 static qboolean vidmode_active = qfalse;
@@ -282,6 +297,13 @@
   case XK_Alt_R:  
   case XK_Meta_R: *key = K_ALT;     break;
 
+  // drakkar
+  case XK_Super_L:
+  case XK_Super_R:  *key = K_WIN;     break;
+  
+  case XK_Menu:  *key = K_MENU;     break;
+  // !drakkar
+
   case XK_KP_Begin: *key = K_KP_5;  break;
 
   case XK_Insert:   *key = K_INS; break;
@@ -446,6 +468,19 @@
   XUndefineCursor(dpy, win);
 }
 
+
+// drakkar
+// Sys_MilliSeconds returns CPU usage time,
+// this fuction returns real time millisecons
+unsigned long int realMilliSeconds() 
+{
+	struct timeval tv;
+	gettimeofday( &tv, NULL );
+	return (unsigned long int)tv.tv_sec*1000 + (unsigned long int)tv.tv_usec/1000;
+}
+// !drakakr
+
+
 // bk001206 - from Ryan's Fakk2
 /**
  * XPending() actually performs a blocking read 
@@ -688,9 +723,26 @@
       break;
 
     case ConfigureNotify :
+		// drakkar - only user actions
+		if( glConfig.isFullscreen ) break;
+		if( win_active ) break;
+		if( event.xcreatewindow.x < 1 ) break;
+		if( event.xcreatewindow.y < 1 ) break;
+		// !drakkar
       win_x = event.xconfigure.x;
       win_y = event.xconfigure.y;
       break;
+	
+	// drakkar
+	case FocusIn:
+		if( ignoreFocus < realMilliSeconds() )
+			GLW_WindowFocus( qtrue );
+	break;
+	case FocusOut:
+		if( ignoreFocus < realMilliSeconds() )
+			GLW_WindowFocus( qfalse );
+	break;
+	// !drakkar
     }
   }
 
@@ -779,12 +831,14 @@
   // autorepeaton = qfalse; // bk001130 - from cvs1.17 (mkv)
   if (dpy)
   {
+	if( visinfo ) // drakkar
+	  XFree( visinfo );
     if (ctx)
       qglXDestroyContext(dpy, ctx);
     if (win)
       XDestroyWindow(dpy, win);
     if (vidmode_active)
-      XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]);
+      XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[desktopVideoMode]); // drakkar - replace 0 by desktopVideoMode
     if (glConfig.deviceSupportsGamma)
     {
       XF86VidModeSetGamma(dpy, scrnum, &vidmode_InitialGamma);
@@ -799,6 +853,11 @@
   dpy = NULL;
   win = 0;
   ctx = NULL;
+  // drakkar  
+  visinfo = NULL;
+  if( vidmodes ) XFree( vidmodes );
+  vidmodes = NULL;  
+  // !drakkar  
 
   memset( &glConfig, 0, sizeof( glConfig ) );
   memset( &glState, 0, sizeof( glState ) );
@@ -862,143 +921,63 @@
   return qtrue;
 }
 
-/*
-** GLW_SetMode
-*/
-int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen )
-{
-  int attrib[] = {
-    GLX_RGBA,         // 0
-    GLX_RED_SIZE, 4,      // 1, 2
-    GLX_GREEN_SIZE, 4,      // 3, 4
-    GLX_BLUE_SIZE, 4,     // 5, 6
-    GLX_DOUBLEBUFFER,     // 7
-    GLX_DEPTH_SIZE, 1,      // 8, 9
-    GLX_STENCIL_SIZE, 1,    // 10, 11
-    None
-  };
-  // these match in the array
-#define ATTR_RED_IDX 2
-#define ATTR_GREEN_IDX 4
-#define ATTR_BLUE_IDX 6
-#define ATTR_DEPTH_IDX 9
-#define ATTR_STENCIL_IDX 11
-  Window root;
-  XVisualInfo *visinfo;
-  XSetWindowAttributes attr;
-  XSizeHints sizehints;
-  unsigned long mask;
-  int colorbits, depthbits, stencilbits;
-  int tcolorbits, tdepthbits, tstencilbits;
-  int dga_MajorVersion, dga_MinorVersion;
-  int actualWidth, actualHeight;
-  int i;
-  const char*   glstring; // bk001130 - from cvs1.17 (mkv)
-
-  ri.Printf( PRINT_ALL, "Initializing OpenGL display\n");
 
-  ri.Printf (PRINT_ALL, "...setting mode %d:", mode );
 
-  if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) )
+// drakkar
+void GLW_WindowFocus(qboolean focus)
   {
-    ri.Printf( PRINT_ALL, " invalid mode\n" );
-    return RSERR_INVALID_MODE;
-  }
-  ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight);
+	if( !dpy || !win ) return;
 
-  if (!(dpy = XOpenDisplay(NULL)))
-  {
-    fprintf(stderr, "Error couldn't open the X display\n");
-    return RSERR_INVALID_MODE;
-  }
+	//Key_ClearStates();
   
-  scrnum = DefaultScreen(dpy);
-  root = RootWindow(dpy, scrnum);
+	R_SetColorMappings();
 
-  actualWidth = glConfig.vidWidth;
-  actualHeight = glConfig.vidHeight;
-
-  // Get video mode list
-  if (!XF86VidModeQueryVersion(dpy, &vidmode_MajorVersion, &vidmode_MinorVersion))
+	if( focus )
   {
-    vidmode_ext = qfalse;
-  } else
-  {
-    ri.Printf(PRINT_ALL, "Using XFree86-VidModeExtension Version %d.%d\n",
-              vidmode_MajorVersion, vidmode_MinorVersion);
-    vidmode_ext = qtrue;
+		if( win_minimized )
+			GLimp_WindowMode( WMODE_SWAP_MINIMIZED );
   }
-
-  // Check for DGA	
-  dga_MajorVersion = 0, dga_MinorVersion = 0;
-  if (in_dgamouse->value)
-  {
-    if (!XF86DGAQueryVersion(dpy, &dga_MajorVersion, &dga_MinorVersion))
-    {
-      // unable to query, probalby not supported
-      ri.Printf( PRINT_ALL, "Failed to detect XF86DGA Mouse\n" );
-      ri.Cvar_Set( "in_dgamouse", "0" );
-    } else
+	else
     {
-      ri.Printf( PRINT_ALL, "XF86DGA Mouse (Version %d.%d) initialized\n",
-                 dga_MajorVersion, dga_MinorVersion);
+		if( glConfig.deviceSupportsGamma )
+			XF86VidModeSetGamma( dpy, scrnum, &vidmode_InitialGamma );
+		if( glConfig.isFullscreen )
+			GLimp_WindowMode( WMODE_SWAP_MINIMIZED );
     }
+
+	win_active = ( focus && !win_minimized );
   }
+// !drakkar
 
-  if (vidmode_ext)
-  {
-    int best_fit, best_dist, dist, x, y;
 
-    XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
 
-    // Are we going fullscreen?  If so, let's change video mode
-    if (fullscreen)
-    {
-      best_dist = 9999999;
-      best_fit = -1;
 
-      for (i = 0; i < num_vidmodes; i++)
-      {
-        if (glConfig.vidWidth > vidmodes[i]->hdisplay ||
-            glConfig.vidHeight > vidmodes[i]->vdisplay)
-          continue;
-
-        x = glConfig.vidWidth - vidmodes[i]->hdisplay;
-        y = glConfig.vidHeight - vidmodes[i]->vdisplay;
-        dist = (x * x) + (y * y);
-        if (dist < best_dist)
-        {
-          best_dist = dist;
-          best_fit = i;
-        }
-      }
 
-      if (best_fit != -1)
-      {
-        actualWidth = vidmodes[best_fit]->hdisplay;
-        actualHeight = vidmodes[best_fit]->vdisplay;
 
-        // change to the mode
-        XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
-        vidmode_active = qtrue;
 
-        // Move the viewport to top left
-        XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
-
-        ri.Printf(PRINT_ALL, "XFree86-VidModeExtension Activated at %dx%d\n",
-                  actualWidth, actualHeight);
+#define ATTR_RED_IDX		2
+#define ATTR_GREEN_IDX		4
+#define ATTR_BLUE_IDX		6
+#define ATTR_DEPTH_IDX		9
+#define ATTR_STENCIL_IDX	11
 
-      } else
+XVisualInfo * createVisualInfo(Display *dpy, int scrnum)
       {
-        fullscreen = 0;
-        ri.Printf(PRINT_ALL, "XFree86-VidModeExtension: No acceptable modes found\n");
-      }
-    } else
-    {
-      ri.Printf(PRINT_ALL, "XFree86-VidModeExtension:  Ignored on non-fullscreen/Voodoo\n");
-    }
-  }
+  XVisualInfo *visinfo = NULL;
+  int colorbits, depthbits, stencilbits;
+  int tcolorbits, tdepthbits, tstencilbits;
+  int i;
 
+  int attrib[] = {
+    GLX_RGBA,			// 0
+    GLX_RED_SIZE, 4,	// 1, 2
+    GLX_GREEN_SIZE, 4,	// 3, 4
+    GLX_BLUE_SIZE, 4,	// 5, 6
+    GLX_DOUBLEBUFFER,	// 7
+    GLX_DEPTH_SIZE, 1,	// 8, 9
+    GLX_STENCIL_SIZE, 1,// 10, 11
+    None
+  };
 
   if (!r_colorbits->value)
     colorbits = 24;
@@ -1102,53 +1081,254 @@
     break;
   }
 
-  if (!visinfo)
-  {
-    ri.Printf( PRINT_ALL, "Couldn't get a visual\n" );
-    return RSERR_INVALID_MODE;
+  return visinfo;
   }
 
-  /* window attributes */
+
+
+Window createWindow(Display *dpy, int scrnum, Window root, XVisualInfo *visinfo, qboolean fullscreen, int x, int y)
+{
+	XSetWindowAttributes attr;
+	XSizeHints sizehints;
+	unsigned long mask;
+	Window win;
+	
   attr.background_pixel = BlackPixel(dpy, scrnum);
   attr.border_pixel = 0;
   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+	attr.backing_store = NotUseful;
+	attr.save_under = False;
   attr.event_mask = X_MASK;
-  if (vidmode_active)
+	mask = CWEventMask | CWBackPixel | CWBorderPixel | CWColormap | CWBackingStore | CWSaveUnder;
+
+  	if( fullscreen )
   {
-    mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | 
-           CWEventMask | CWOverrideRedirect;
+		mask |= CWOverrideRedirect;
     attr.override_redirect = True;
-    attr.backing_store = NotUseful;
-    attr.save_under = False;
-  } else
-    mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+		x = 0;
+		y = 0;
+	}
 
-  win = XCreateWindow(dpy, root, 0, 0, 
-                      actualWidth, actualHeight, 
+	win = XCreateWindow( dpy, root,
+						 x, y,  glConfig.vidWidth, glConfig.vidHeight, 
                       0, visinfo->depth, InputOutput,
                       visinfo->visual, mask, &attr);
-
+	if( !win ) return 0;
   XStoreName( dpy, win, WINDOW_CLASS_NAME );
 
-  /* GH: Don't let the window be resized */
-  sizehints.flags = PMinSize | PMaxSize;
-  sizehints.min_width = sizehints.max_width = actualWidth;
-  sizehints.min_height = sizehints.max_height = actualHeight;
+	XMapWindow( dpy, win );	
+	XFlush(dpy);
+
+	XMoveWindow( dpy, win, x, y );
 
+	// GH: Don't let the window be resized
+	sizehints.flags = PMinSize | PMaxSize;
+	sizehints.min_width = sizehints.max_width = glConfig.vidWidth;
+	sizehints.min_height = sizehints.max_height = glConfig.vidHeight;
   XSetWMNormalHints( dpy, win, &sizehints );
 
-  XMapWindow( dpy, win );
+	XFlush(dpy);
 
-  if (vidmode_active)
-    XMoveWindow(dpy, win, 0, 0);
+	return win;
+}
 
-  XFlush(dpy);
+
+qboolean switchToMode(Display *dpy, int scrnum, qboolean fullscreen)
+{
+  if (!XF86VidModeQueryVersion(dpy, &vidmode_MajorVersion, &vidmode_MinorVersion))
+  {
+    vidmode_ext = qfalse;
+	// drakkar
+	fullscreen = qfalse;
+	vidmode_active = qfalse;
+	// !drakkar
+  } else
+  {
+    ri.Printf(PRINT_ALL, "Using XFree86-VidModeExtension Version %d.%d\n",
+              vidmode_MajorVersion, vidmode_MinorVersion);
+    vidmode_ext = qtrue;
+  }
+  
+  if (vidmode_ext)
+  {
+    int best_fit, best_dist, dist, x, y, i;
+
+	if( vidmodes ) XFree( vidmodes ); // drakkar
+	XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
+
+	// drakkar
+	// search desktop video mode:
+	// first time vidmodes[0] is always the desktop video mode ( we come from desktop )
+	// but vidmodes[0] is not always the desktop video mode in some graphic card drivers
+	if( desktopVideoModeInfo.hdisplay == 0 ) // first time, desktop mode = vidmodes[0]
+	{
+		desktopVideoModeInfo = *vidmodes[0];
+		desktopVideoMode = 0;
+	}
+	else // desktop mode = one in vidmodes array, normally vidmodes[0]
+	{
+		desktopVideoMode = 0;
+		for( i = 0; i < num_vidmodes; i++ )
+		{
+			dist = memcmp( vidmodes[i], &desktopVideoModeInfo, sizeof(*vidmodes[i])-sizeof(vidmodes[i]->private) );
+			if( !dist )
+			{
+				desktopVideoMode = i;
+				break;
+			}
+		}
+	}
+	// !drakkar
+
+    // Are we going fullscreen?  If so, let's change video mode
+    if (fullscreen)
+    {
+      best_dist = 9999999;
+      best_fit = -1;
+
+      for (i = 0; i < num_vidmodes; i++)
+      {
+        if (glConfig.vidWidth  > vidmodes[i]->hdisplay || glConfig.vidHeight > vidmodes[i]->vdisplay)
+          continue;
+
+        x = glConfig.vidWidth  - vidmodes[i]->hdisplay;
+        y = glConfig.vidHeight - vidmodes[i]->vdisplay;
+        dist = (x * x) + (y * y);
+        if (dist < best_dist)
+        {
+          best_dist = dist;
+          best_fit = i;
+        }
+      }
+
+      if (best_fit != -1)
+      {
+        glConfig.vidWidth  = vidmodes[best_fit]->hdisplay;
+        glConfig.vidHeight = vidmodes[best_fit]->vdisplay;
+
+        // change to the mode
+        XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
+		XFlush( dpy );  // drakkar - man 3 XF86VidModeSwitchToMode 
+        vidmode_active = qtrue;
+        // Move the viewport to top left
+		if( win ) XMoveWindow( dpy, win, 0, 0 ); // drakkar - XF86VidModeSetViewPort problems if windows is placed out of screen
+        XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
+
+        ri.Printf(PRINT_ALL, "XFree86-VidModeExtension Activated at %dx%d\n", glConfig.vidWidth, glConfig.vidHeight);
+
+      } else
+      {
+        fullscreen = 0;
+        ri.Printf(PRINT_ALL, "XFree86-VidModeExtension: No acceptable modes found\n");
+      }
+    }
+	// drakkar	
+//- else
+//- {
+//-   ri.Printf(PRINT_ALL, "XFree86-VidModeExtension:  Ignored on non-fullscreen/Voodoo\n");
+//- }
+	
+	if( !fullscreen )
+    {
+		vidmode_active = qfalse;
+		XF86VidModeSwitchToMode( dpy, scrnum, vidmodes[desktopVideoMode] );
+		ri.Printf(PRINT_ALL, "XFree86-VidModeExtension:  No fullscreen\n");
+    }
+	// !drakkar
+  }
+	
+	glConfig.isFullscreen = fullscreen;
+
+	return fullscreen;
+}
+
+
+/*
+** GLW_SetMode
+*/
+int GLW_SetMode( const char *drivername, int mode, qboolean fullscreen )
+{  
+  int dga_MajorVersion, dga_MinorVersion;
+  const char*   glstring; // bk001130 - from cvs1.17 (mkv)
+  Window root = 0;
+
+
+  ri.Printf( PRINT_ALL, "Initializing OpenGL display\n");
+
+  ri.Printf (PRINT_ALL, "...setting mode %d:", mode );
+
+  if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) )
+  {
+    ri.Printf( PRINT_ALL, " invalid mode\n" );
+    return RSERR_INVALID_MODE;
+  }
+  ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight);
+
+	if( !dpy ) // drakkar - skip if display already opened
+	{
+		dpy = XOpenDisplay( NULL );
+		if( !dpy )
+		{
+			fprintf(stderr, "Error couldn't open the X display\n");
+			return RSERR_INVALID_MODE;
+		}
+	}  
+  
+  scrnum = DefaultScreen(dpy);
+  root = RootWindow(dpy, scrnum);
+
+  // Check for DGA	
+  dga_MajorVersion = 0, dga_MinorVersion = 0;
+  if (in_dgamouse->value)
+  {
+    if (!XF86DGAQueryVersion(dpy, &dga_MajorVersion, &dga_MinorVersion))
+    {
+      // unable to query, probalby not supported
+      ri.Printf( PRINT_ALL, "Failed to detect XF86DGA Mouse\n" );
+      ri.Cvar_Set( "in_dgamouse", "0" );
+    } else
+    {
+      ri.Printf( PRINT_ALL, "XF86DGA Mouse (Version %d.%d) initialized\n",
+                 dga_MajorVersion, dga_MinorVersion);
+    }
+  }
+
+	// drakkar
+	// moved some code to switchToMode function
+	fullscreen = switchToMode( dpy, scrnum, fullscreen );
+	win_minimized = qfalse;
+
+	// moved visual info code to createVisualInfo function
+	if( !visinfo )
+	{
+		visinfo = createVisualInfo( dpy, scrnum );
+		if( !visinfo )
+		{
+			ri.Printf( PRINT_ALL, "Couldn't get a visual\n" );
+			return RSERR_INVALID_MODE;
+		}
+	}
+	
+	// moved window code to createWindow function
+	IN_DeactivateMouse();
+	ignoreFocus = 10000 + realMilliSeconds();
+	if( win ) XDestroyWindow( dpy, win );
+	win = createWindow( dpy, scrnum, root, visinfo, fullscreen, win_x, win_y );
+	if( !win )
+	{
+		ri.Printf( PRINT_ALL, "Couldn't create the window\n" );
+		return RSERR_INVALID_MODE;
+	}
+	IN_ActivateMouse();
+	ignoreFocus = 500 + realMilliSeconds();
+	// !drakkar
+
+	if( !ctx )  // drakkar - skip if context already created
+	{
   XSync(dpy,False); // bk001130 - from cvs1.17 (mkv)
   ctx = qglXCreateContext(dpy, visinfo, NULL, True);
   XSync(dpy,False); // bk001130 - from cvs1.17 (mkv)
-
-  /* GH: Free the visinfo after we're done with it */
-  XFree( visinfo );
+	}
 
   qglXMakeCurrent(dpy, win, ctx);
 
@@ -1180,6 +1360,7 @@
   return RSERR_OK;
 }
 
+
 /*
 ** GLW_InitExtensions
 */
@@ -1303,6 +1484,7 @@
       ri.Printf( PRINT_ALL, "XF86 Gamma extension not supported in this version\n");
       return;
     }
+	if( vidmode_InitialGamma.red < 0 ) // drakkar - get initial gamma only one time
     XF86VidModeGetGamma(dpy, scrnum, &vidmode_InitialGamma);
     ri.Printf( PRINT_ALL, "XF86 Gamma extension initialized\n");
     glConfig.deviceSupportsGamma = qtrue;
@@ -1334,6 +1516,10 @@
   {
     fullscreen = r_fullscreen->integer;
 
+	// drakkar
+	windowModeLock = qfalse;
+	// !drakkar
+	  
     // create the window and set up the context
     if ( !GLW_StartDriverAndSetMode( name, r_mode->integer, fullscreen ) )
     {
@@ -1347,6 +1533,10 @@
         goto fail;
     }
 
+	// drakkar
+	windowModeLock = qtrue;
+	// !drakkar
+
     return qtrue;
   } else
   {
@@ -1377,6 +1567,81 @@
   return 0;
 }
 
+
+// drakkar
+/*
+** GLimp_WindowMode
+**
+** Changes window mode ( minimized, windowed, fullscreen ) without vid_restart.
+*/
+void GLimp_WindowMode( windowMode_t wmode )
+{
+	if( !windowModeLock ) return;
+
+	switch( wmode )
+	{
+		case WMODE_SET_MINIMIZED:
+			windowModeLock = qfalse;
+			GLW_StartDriverAndSetMode( r_glDriver->string, r_mode->integer, qfalse );
+			XIconifyWindow( dpy, win, scrnum );
+			win_minimized = qtrue;
+			GLW_WindowFocus( qfalse );
+			windowModeLock = qtrue;
+		break;
+		
+		case WMODE_SET_WINDOWED:
+			windowModeLock = qfalse;
+			GLW_StartDriverAndSetMode( r_glDriver->string, r_mode->integer, qfalse );
+			win_minimized = qfalse;
+			GLW_WindowFocus( qtrue );
+			uninstall_grabs();
+			install_grabs();
+			windowModeLock = qtrue;
+			ri.Cvar_Set( "r_fullscreen", "0" );
+			if( glConfig.isFullscreen )
+				Cbuf_AddText( "vid_restart\n" );
+		break;
+		
+		case WMODE_SET_FULLSCREEN:
+			windowModeLock = qfalse;
+			GLW_StartDriverAndSetMode( r_glDriver->string, r_mode->integer, qtrue );
+			win_minimized = qfalse;
+			GLW_WindowFocus( qtrue );
+			windowModeLock = qtrue;
+			ri.Cvar_Set( "r_fullscreen", "1" );
+			if( !glConfig.isFullscreen )
+				Cbuf_AddText( "vid_restart\n" );
+		break;
+		
+		case WMODE_RESTART:
+			if( r_fullscreen->modified && r_fullscreen->latchedString )
+			{
+				if( !Q_strncmp( r_fullscreen->latchedString, "0", 1 ) )
+					GLimp_WindowMode( WMODE_SET_WINDOWED );
+				else
+					GLimp_WindowMode( WMODE_SET_FULLSCREEN );
+			}
+			else
+			{
+				GLimp_WindowMode( r_fullscreen->integer ? WMODE_SET_FULLSCREEN : WMODE_SET_WINDOWED );
+			}
+		break;
+		
+		case WMODE_SWAP_FULLSCREEN:
+			GLimp_WindowMode( glConfig.isFullscreen ? WMODE_SET_WINDOWED : WMODE_SET_FULLSCREEN );
+		break;		
+		
+		case WMODE_SWAP_MINIMIZED:
+			GLimp_WindowMode( win_minimized ? WMODE_RESTART : WMODE_SET_MINIMIZED );
+		break;
+		
+		default:
+			Com_Printf( "Invalid Window Mode\n" );
+	}
+}
+// !drakkar
+
+
 /*
 ** GLimp_Init
 **
@@ -1753,7 +2018,13 @@
     }
   }
 
+	// drakkar
+//-  IN_ActivateMouse();
+	if( win_active )
   IN_ActivateMouse();
+	else
+		IN_DeactivateMouse();
+	// !drakkar
 }
 
 void IN_Activate(void)
diff -wrubN quake3_1.32b/code/unix/linux_local.h dfengine_1.07_src/code/unix/linux_local.h
--- quake3_1.32b/code/unix/linux_local.h	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/unix/linux_local.h	2009-05-21 14:53:03.000000000 +0200
@@ -47,3 +47,13 @@
 
 // signals.c
 void InitSig(void);
+
+
+// drakkar
+void GLW_WindowFocus(qboolean focus);
+// !drakkar
+
+// drakkar - main need this to do sleep() if window not active
+extern qboolean win_active;
+// !drakkar
+
diff -wrubN quake3_1.32b/code/unix/unix_main.c dfengine_1.07_src/code/unix/unix_main.c
--- quake3_1.32b/code/unix/unix_main.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/unix/unix_main.c	2009-05-27 12:44:05.000000000 +0200
@@ -1219,6 +1219,11 @@
 
 #include "../client/client.h"
 extern clientStatic_t cls;
+#ifdef __linux__
+#ifndef DEDICATED
+extern qboolean win_active;	// drakkar
+#endif
+#endif
 
 int main ( int argc, char* argv[] )
 {
@@ -1267,7 +1272,15 @@
   {
 #ifdef __linux__
     Sys_ConfigureFPU();
-#endif
+#ifndef DEDICATED
+	// drakkar
+	if( !win_active )
+	{
+		usleep( 100000 );  // 10 fps, free CPU
+	}
+	// !drakkar
+#endif	// !DEDICATED
+#endif	// __linux__
     Com_Frame ();
   }
 }
diff -wrubN quake3_1.32b/code/win32/win_glimp.c dfengine_1.07_src/code/win32/win_glimp.c
--- quake3_1.32b/code/win32/win_glimp.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/win32/win_glimp.c	2009-05-22 21:11:14.000000000 +0200
@@ -67,6 +67,10 @@
 
 static qboolean s_classRegistered = qfalse;
 
+// drakkar
+static qboolean windowModeLock = qtrue;
+// !drakkar
+
 //
 // function declaration
 //
@@ -568,11 +572,147 @@
 	return qtrue;
 }
 
+
 /*
 ** GLW_CreateWindow
 **
 ** Responsible for creating the Win32 window and initializing the OpenGL driver.
 */
+// drakkar - some changes to allow swap between fullscreen and windowed
+#define	WINDOW_STYLE	        (WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE)
+#define WINDOW_STYLE_NORMAL     (WINDOW_STYLE|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX)
+#define WINDOW_STYLE_FULLSCREEN (WS_POPUP|WS_VISIBLE|WS_SYSMENU|WS_MAXIMIZE)
+static qboolean GLW_CreateWindow( const char *drivername, int width, int height, int colorbits, qboolean cdsFullscreen )
+{
+	RECT			r;
+	cvar_t			*vid_xpos, *vid_ypos;
+	int				stylebits;
+	int				x, y, w, h;
+	int				exstyle;
+
+	// register the window class if necessary
+	if ( !s_classRegistered )
+	{
+		WNDCLASS wc;
+
+		memset( &wc, 0, sizeof( wc ) );
+
+		wc.style         = 0;
+		wc.lpfnWndProc   = (WNDPROC) glw_state.wndproc;
+		wc.cbClsExtra    = 0;
+		wc.cbWndExtra    = 0;
+		wc.hInstance     = g_wv.hInstance;
+		wc.hIcon         = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
+		wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
+		wc.hbrBackground = (void *)COLOR_GRAYTEXT;
+		wc.lpszMenuName  = 0;
+		wc.lpszClassName = WINDOW_CLASS_NAME;
+
+		if ( !RegisterClass( &wc ) )
+		{
+			ri.Error( ERR_FATAL, "GLW_CreateWindow: could not register window class" );
+		}
+		s_classRegistered = qtrue;
+		ri.Printf( PRINT_ALL, "...registered window class\n" );
+	}
+
+	cdsFullscreen = ( cdsFullscreen || !Q_stricmp( _3DFX_DRIVER_NAME, drivername ) );
+	g_wv.isMinimized = qfalse;
+
+	if( cdsFullscreen )
+	{
+		exstyle = WS_EX_TOPMOST;
+		stylebits = WINDOW_STYLE_FULLSCREEN;
+	}
+	else
+	{
+		exstyle = 0;
+		stylebits = WINDOW_STYLE_NORMAL;
+	}
+
+	r.left = 0;
+	r.top = 0;
+	r.right  = width;
+	r.bottom = height;
+
+	AdjustWindowRect( &r, stylebits, FALSE );
+
+	w = r.right - r.left;
+	h = r.bottom - r.top;
+
+	if ( cdsFullscreen )
+	{
+		x = 0;
+		y = 0;
+	}
+	else
+	{
+		vid_xpos = ri.Cvar_Get ("vid_xpos", "", 0);
+		vid_ypos = ri.Cvar_Get ("vid_ypos", "", 0);
+		x = vid_xpos->integer;
+		y = vid_ypos->integer;
+
+		// adjust window coordinates if necessary 
+		// so that the window is completely on screen
+		if ( x < 0 ) x = 0;
+		if ( y < 0 ) y = 0;
+
+		if ( w < glw_state.desktopWidth && h < glw_state.desktopHeight )
+		{
+			if ( x + w > glw_state.desktopWidth )
+				x = ( glw_state.desktopWidth - w );
+			if ( y + h > glw_state.desktopHeight )
+				y = ( glw_state.desktopHeight - h );
+		}
+	}
+
+	// create the HWND if one does not already exist
+	if ( !g_wv.hWnd )
+	{
+		g_wv.hWnd = CreateWindowEx (
+			 exstyle, 
+			 WINDOW_CLASS_NAME,
+			 Q3_WINDOW_TITLE,
+			 stylebits,
+			 x, y, w, h,
+			 NULL,
+			 NULL,
+			 g_wv.hInstance,
+			 NULL);
+
+		if ( !g_wv.hWnd )
+		{
+			ri.Error (ERR_FATAL, "GLW_CreateWindow() - Couldn't create window");
+		}
+	
+		ri.Printf( PRINT_ALL, "...created window@%d,%d (%dx%d)\n", x, y, w, h );
+	}
+	else
+	{
+		ri.Printf( PRINT_ALL, "...window already present, CreateWindowEx skipped\n" );
+		SetWindowLong( g_wv.hWnd, GWL_STYLE, stylebits );
+		SetWindowLong( g_wv.hWnd, GWL_EXSTYLE, exstyle );
+		SetWindowPos( g_wv.hWnd, cdsFullscreen?HWND_TOPMOST:HWND_NOTOPMOST, x,y, w,h, SWP_SHOWWINDOW );
+	}
+
+	ShowWindow( g_wv.hWnd, SW_SHOW );
+	UpdateWindow( g_wv.hWnd );
+
+	if ( !GLW_InitDriver( drivername, colorbits ) )
+	{
+		ShowWindow( g_wv.hWnd, SW_HIDE );
+		DestroyWindow( g_wv.hWnd );
+		g_wv.hWnd = NULL;
+
+		return qfalse;
+	}
+
+	SetForegroundWindow( g_wv.hWnd );
+	SetFocus( g_wv.hWnd );
+
+	return qtrue;
+}
+/* // original version
 #define	WINDOW_STYLE	(WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_VISIBLE)
 static qboolean GLW_CreateWindow( const char *drivername, int width, int height, int colorbits, qboolean cdsFullscreen )
 {
@@ -670,7 +810,7 @@
 		g_wv.hWnd = CreateWindowEx (
 			 exstyle, 
 			 WINDOW_CLASS_NAME,
-			 "Quake 3: Arena",
+			 Q3_WINDOW_TITLE,	// Cgg
 			 stylebits,
 			 x, y, w, h,
 			 NULL,
@@ -706,6 +846,36 @@
 
 	return qtrue;
 }
+*/  // !original version
+// !drakkar
+
+
+// drakkar
+void GLW_WindowFocus(qboolean focus)
+{
+	if( !g_wv.hWnd ) return;
+
+	R_SetColorMappings();
+
+	if( focus )
+	{
+		//Key_ClearStates();
+		if( g_wv.isMinimized )
+			GLimp_WindowMode( WMODE_SWAP_MINIMIZED );
+	}
+	else
+	{
+		WG_RestoreGamma();
+		if( glConfig.isFullscreen )
+			GLimp_WindowMode( WMODE_SWAP_MINIMIZED );
+	}
+
+	g_wv.activeApp = ( focus && !g_wv.isMinimized );
+	IN_Activate( g_wv.activeApp );
+	SNDDMA_Activate();
+}
+// !drakkar
+
 
 static void PrintCDSError( int value )
 {
@@ -1201,6 +1371,10 @@
 	{
 		cdsFullscreen = r_fullscreen->integer;
 
+		// drakkar
+		windowModeLock = qfalse;
+		// !drakkar
+
 		// create the window and set up the context
 		if ( !GLW_StartDriverAndSetMode( drivername, r_mode->integer, r_colorbits->integer, cdsFullscreen ) )
 		{
@@ -1229,6 +1403,10 @@
 			glConfig.isFullscreen = qtrue;
 		}
 
+		// drakkar
+		windowModeLock = qtrue;
+		// !drakkar
+
 		return qtrue;
 	}
 fail:
@@ -1337,6 +1515,82 @@
 	}
 }
 
+
+// drakkar
+/*
+** GLimp_WindowMode
+**
+** Changes window mode ( minimized, windowed, fullscreen ) without vid_restart.
+*/
+void GLimp_WindowMode( windowMode_t wmode )
+{
+	if( !windowModeLock )	return;	
+
+	switch( wmode )
+	{
+		case WMODE_SET_MINIMIZED:
+			windowModeLock = qfalse;
+			glw_state.cdsFullscreen = qfalse;
+			ChangeDisplaySettings( 0, 0 );
+			ShowWindow( g_wv.hWnd, SW_SHOWMINIMIZED );			
+			g_wv.isMinimized = qtrue;
+			GLW_WindowFocus( qfalse );
+			windowModeLock = qtrue;
+		break;
+		
+		case WMODE_SET_WINDOWED:
+			windowModeLock = qfalse;
+			GLW_StartDriverAndSetMode( r_glDriver->string, r_mode->integer, r_colorbits->integer, qfalse );
+			ShowWindow( g_wv.hWnd, SW_SHOWNORMAL );
+			g_wv.isMinimized = qfalse;
+			GLW_WindowFocus( qtrue );
+			windowModeLock = qtrue;
+			ri.Cvar_Set( "r_fullscreen", "0" );
+			if( glConfig.isFullscreen )
+				Cbuf_AddText( "vid_restart\n" );
+		break;
+		
+		case WMODE_SET_FULLSCREEN:
+			windowModeLock = qfalse;
+			GLW_StartDriverAndSetMode( r_glDriver->string, r_mode->integer, r_colorbits->integer, qtrue );
+			ShowWindow( g_wv.hWnd, SW_SHOWMAXIMIZED );				
+			g_wv.isMinimized = qfalse;
+			GLW_WindowFocus( qtrue );
+			windowModeLock = qtrue;
+			ri.Cvar_Set( "r_fullscreen", "1" );
+			if( !glConfig.isFullscreen )
+				Cbuf_AddText( "vid_restart\n" );
+		break;
+		
+		case WMODE_RESTART:
+			if( r_fullscreen->modified && r_fullscreen->latchedString )
+			{
+				if( !Q_strncmp( r_fullscreen->latchedString, "0", 1 ) )
+					GLimp_WindowMode( WMODE_SET_WINDOWED );
+				else
+					GLimp_WindowMode( WMODE_SET_FULLSCREEN );
+			}
+			else
+			{
+				GLimp_WindowMode( r_fullscreen->integer ? WMODE_SET_FULLSCREEN : WMODE_SET_WINDOWED );
+			}
+		break;
+		
+		case WMODE_SWAP_FULLSCREEN:
+			GLimp_WindowMode( glConfig.isFullscreen ? WMODE_SET_WINDOWED : WMODE_SET_FULLSCREEN );
+		break;		
+		
+		case WMODE_SWAP_MINIMIZED:
+			GLimp_WindowMode( g_wv.isMinimized ? WMODE_RESTART : WMODE_SET_MINIMIZED );
+		break;
+		
+		default:
+			Com_Printf( "Invalid Window Mode\n" );
+	}
+}
+// !drakkar
+
+
 /*
 ** GLimp_Init
 **
diff -wrubN quake3_1.32b/code/win32/win_input.c dfengine_1.07_src/code/win32/win_input.c
--- quake3_1.32b/code/win32/win_input.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/win32/win_input.c	2009-05-19 14:03:24.000000000 +0200
@@ -32,6 +32,7 @@
 	qboolean	mouseActive;
 	qboolean	mouseInitialized;
   qboolean  mouseStartupDelayed; // delay mouse init to try DI again when we have a window
+	qboolean	mouseRaw;	// Cgg - raw input
 } WinMouseVars_t;
 
 static WinMouseVars_t s_wmv;
@@ -187,6 +188,48 @@
 /*
 ============================================================
 
+RAW INPUT MOUSE
+(Cgg)
+
+============================================================
+*/
+qboolean IN_InitRawMouse() {
+	// http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
+	RAWINPUTDEVICE dev = {
+		1,	// usUsagePage - generic desktop controls
+		2,	// usUsage - mouse
+		0,	// dwFlags
+		0	// hwndTarget
+	};
+	if (!RegisterRawInputDevices(&dev, 1, sizeof(dev))) {
+		Com_Printf("Raw input registration failed. (0x%x)\n", GetLastError());
+		return qfalse;
+	}
+	Com_Printf("Registered for raw input.\n");
+	s_wmv.mouseRaw = qtrue;
+	return qtrue;
+}
+
+void IN_ShutdownRawMouse() {
+	RAWINPUTDEVICE dev = {
+		1,	// usUsagePage - generic desktop controls
+		2,	// usUsage - mouse
+		RIDEV_REMOVE,	// dwFlags
+		0	// hwndTarget
+	};
+	s_wmv.mouseRaw = qfalse;
+	if (!RegisterRawInputDevices(&dev, 1, sizeof(dev))) {
+		Com_Printf("Mouse release failed. (0x%x)\n", GetLastError());
+	}
+}
+
+qboolean IN_RawMouseActive() {
+	return s_wmv.mouseActive && s_wmv.mouseRaw;
+}
+
+/*
+============================================================
+
 DIRECT INPUT MOUSE CONTROL
 
 ============================================================
@@ -571,10 +614,15 @@
 	}
 
 	if ( in_mouse->integer == -1 ) {
-		Com_Printf ("Skipping check for DirectInput\n");
+		Com_Printf ("Skipping check for DirectInput and Raw Input\n");
+	} else if (in_mouse->integer == 3) {	// Cgg - raw input
+		if (IN_InitRawMouse()) {
+			s_wmv.mouseInitialized = qtrue;
+			return;
+		}
+		Com_Printf ("Falling back to Win32 mouse support...\n");
 	} else {
-    if (!g_wv.hWnd)
-    {
+		if (!g_wv.hWnd) {
       Com_Printf ("No window for DirectInput mouse init, delaying\n");
       s_wmv.mouseStartupDelayed = qtrue;
       return;
@@ -629,6 +677,13 @@
 void IN_MouseMove ( void ) {
 	int		mx, my;
 
+	// Cgg - raw input is based on wndproc events - not frames.
+	if ( s_wmv.mouseRaw ) {
+		// keep the windows cursor centered
+		SetCursorPos(window_center_x, window_center_y);
+		return;
+	}
+	// !Cgg
 	if ( g_pMouse ) {
 		IN_DIMouse( &mx, &my );
 	} else {
@@ -673,6 +728,7 @@
 void IN_Shutdown( void ) {
 	IN_DeactivateMouse();
 	IN_ShutdownDIMouse();
+	IN_ShutdownRawMouse();
 	IN_ShutdownMIDI();
 	Cmd_RemoveCommand("midiinfo" );
 }
diff -wrubN quake3_1.32b/code/win32/win_local.h dfengine_1.07_src/code/win32/win_local.h
--- quake3_1.32b/code/win32/win_local.h	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/win32/win_local.h	2009-05-21 14:53:03.000000000 +0200
@@ -63,6 +63,8 @@
 void	IN_Activate (qboolean active);
 void	IN_Frame (void);
 
+qboolean IN_RawMouseActive(); // Cgg
+
 // window procedure
 LONG WINAPI MainWndProc (
     HWND    hWnd,
@@ -75,6 +77,10 @@
 void SNDDMA_Activate( void );
 int  SNDDMA_InitDS ();
 
+// drakkar
+void GLW_WindowFocus(qboolean focus);
+// !drakkar
+
 typedef struct
 {
 	
diff -wrubN quake3_1.32b/code/win32/win_main.c dfengine_1.07_src/code/win32/win_main.c
--- quake3_1.32b/code/win32/win_main.c	2009-04-18 19:32:30.000000000 +0200
+++ dfengine_1.07_src/code/win32/win_main.c	2009-05-21 14:53:03.000000000 +0200
@@ -1227,10 +1227,22 @@
 
     // main game loop
 	while( 1 ) {
-		// if not running as a game client, sleep a bit
-		if ( g_wv.isMinimized || ( com_dedicated && com_dedicated->integer ) ) {
-			Sleep( 5 );
+// drakkar - free CPU if window not active
+/*
+-		// if not running as a game client, sleep a bit
+-		if ( g_wv.isMinimized || ( com_dedicated && com_dedicated->integer ) ) {
+-			Sleep( 5 );
+-		}
+*/
+		if( com_dedicated && com_dedicated->integer )
+		{
+			// Sleep( 5 );  // why? linux version dont sleep
 		}
+		else if( !g_wv.activeApp )
+		{
+			Sleep( 100 );  // 10 fps, free CPU
+		}
+// !drakkar
 
 		// set low precision every frame, because some system calls
 		// reset it arbitrarily
diff -wrubN quake3_1.32b/code/win32/win_syscon.c dfengine_1.07_src/code/win32/win_syscon.c
--- quake3_1.32b/code/win32/win_syscon.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/win32/win_syscon.c	2009-04-19 20:02:08.000000000 +0200
@@ -334,7 +334,7 @@
 
 	s_wcd.hWnd = CreateWindowEx( 0,
 							   DEDCLASS,
-							   "Quake 3 Console",
+							   Q3_WINDOW_TITLE,	// Cgg
 							   DEDSTYLE,
 							   ( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
 							   NULL,
diff -wrubN quake3_1.32b/code/win32/win_wndproc.c dfengine_1.07_src/code/win32/win_wndproc.c
--- quake3_1.32b/code/win32/win_wndproc.c	2009-04-18 19:29:36.000000000 +0200
+++ dfengine_1.07_src/code/win32/win_wndproc.c	2009-05-25 11:51:16.000000000 +0200
@@ -130,7 +130,7 @@
 	K_F6, K_F7, K_F8, K_F9, K_F10,  K_PAUSE,    0  , K_HOME, 
 	K_UPARROW,K_PGUP,K_KP_MINUS,K_LEFTARROW,K_KP_5,K_RIGHTARROW, K_KP_PLUS,K_END, //4 
 	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11, 
-	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
+	K_F12,0  ,    0  ,    0  ,    0  ,    K_MENU  ,    0  ,    0,        // 5
 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6 
 	0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0, 
@@ -214,6 +214,80 @@
 }
 
 
+// drakkar
+// http://support.microsoft.com/kb/226359
+LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+	int vkCode, isDown;
+
+	if( nCode == HC_ACTION )
+	{
+		vkCode = ((KBDLLHOOKSTRUCT *)lParam)->vkCode;
+		isDown = ( wParam == WM_SYSKEYDOWN || wParam == WM_KEYDOWN );
+
+		switch( vkCode )
+		{
+			// Disable Windows key
+			case VK_LWIN:
+			case VK_RWIN:
+				Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_WIN, isDown, 0, NULL );
+				return 1;
+			break;
+
+            // Disable XXX+TAB : ALT+TAB, SHIFT+TAB
+			case VK_TAB:
+				Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_TAB, isDown, 0, NULL );
+				return 1;
+			break;
+
+			// Disable ALT+XXX : ALT+F4, ALT+TAB
+			case VK_LMENU:
+				Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_ALT, isDown, 0, NULL );
+				return 1;
+			break;
+
+			// Disable XXX+ESC : CTRL+ESC, ALT+ESC, SHIFT+ESC
+			case VK_ESCAPE:
+				Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, K_ESCAPE, isDown, 0, NULL );
+				return 1;
+			break;
+		}
+	}
+
+    return CallNextHookEx( 0, nCode, wParam, lParam );
+}
+// !drakkar
+
+
+// drakkar
+static HHOOK hHook = NULL;
+void EnableLowLevelKeyboard(qboolean enable)
+{
+	if( enable )
+	{
+		if( !hHook )
+		{
+			// WH_KEYBOARD_LL -> Windows NT/2000/XP
+			hHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, g_wv.hInstance, 0 );
+			if( !hHook )
+			{
+				Com_Printf("Could not create key hook ( LowLevelKeyboard )\n");
+			}
+		}
+	}
+	else
+	{
+		if( hHook )
+		{
+			UnhookWindowsHookEx( hHook );
+			hHook = NULL;
+		}
+	}
+}
+// !drakkar
+
+
+
 /*
 ====================
 MainWndProc
@@ -314,15 +388,20 @@
 		r_fullscreen = Cvar_Get ("r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH );
 
 		MSH_MOUSEWHEEL = RegisterWindowMessage("MSWHEEL_ROLLMSG"); 
-		if ( r_fullscreen->integer )
-		{
+		// drakkar - never use low level ALT+TAB
+/*
+-		if ( r_fullscreen->integer )
+-		{
+-			WIN_DisableAltTab();
+-		}
+-		else
+-		{
+-			WIN_EnableAltTab();
+-		}
+*/
+		EnableLowLevelKeyboard( qtrue );
 			WIN_DisableAltTab();
-		}
-		else
-		{
-			WIN_EnableAltTab();
-		}
-
+		// !drakkar
 		break;
 #if 0
 	case WM_DISPLAYCHANGE:
@@ -341,27 +420,58 @@
 	case WM_DESTROY:
 		// let sound and input know about this?
 		g_wv.hWnd = NULL;
-		if ( r_fullscreen->integer )
-		{
+		// drakkar
+/*
+-		if ( r_fullscreen->integer )
+-		{
+-			WIN_EnableAltTab();
+-		}
+*/
+		EnableLowLevelKeyboard( qfalse );
 			WIN_EnableAltTab();
-		}
+		// !drakkar
 		break;
 
 	case WM_CLOSE:
 		Cbuf_ExecuteText( EXEC_APPEND, "quit" );
 		break;
 
-	case WM_ACTIVATE:
-		{
-			int	fActive, fMinimized;
+	// drakkar - use WM_SETFOCUS and WM_KILLFOCUS messages
+/*
+-	case WM_ACTIVATE:
+-		{
+-			int	fActive, fMinimized;
+-
+-			fActive = LOWORD(wParam);
+-			fMinimized = (BOOL) HIWORD(wParam);
+-
+-			VID_AppActivate( fActive != WA_INACTIVE, fMinimized);
+-			SNDDMA_Activate();
+-		}
+-		break;
+*/
+	// !drakkar
 
-			fActive = LOWORD(wParam);
-			fMinimized = (BOOL) HIWORD(wParam);
+	// drakkar
+	case WM_SETFOCUS:
+		EnableLowLevelKeyboard( qtrue );
+		WIN_DisableAltTab();
+		GLW_WindowFocus( qtrue );
+	break;
+	case WM_KILLFOCUS:
+		EnableLowLevelKeyboard( qfalse );
+		WIN_EnableAltTab();
+		GLW_WindowFocus( qfalse );
+	break;
+	// !drakkar
 
-			VID_AppActivate( fActive != WA_INACTIVE, fMinimized);
-			SNDDMA_Activate();
-		}
+	// drakkar - dynamically set window size
+	case WM_SIZE:
+		if( wParam == SIZE_MINIMIZED ) Cmd_ExecuteString( "windowMode minimized\n" );
+		if( wParam == SIZE_MAXIMIZED ) Cmd_ExecuteString( "windowMode fullscreen\n" );
+		if( wParam == SIZE_RESTORED  ) Cmd_ExecuteString( "windowMode windowed\n" );		
 		break;
+	// !drakkar
 
 	case WM_MOVE:
 		{
@@ -406,6 +516,11 @@
 		{
 			int	temp;
 
+			// Cgg: ignore legacy messages when raw input is on
+			if (IN_RawMouseActive()) {
+				return 0;
+			}
+
 			temp = 0;
 
 			if (wParam & MK_LBUTTON)
@@ -421,21 +536,47 @@
 		}
 		break;
 
+	// Cgg - raw input
+	case WM_INPUT: {
+		RAWINPUT ri;
+		unsigned int i = sizeof(ri);
+		if (!IN_RawMouseActive()) {
+			return 0;
+		}
+		GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &ri, &i, sizeof(RAWINPUTHEADER));
+		for (i=0; i<5; i++) {
+			if (ri.data.mouse.ulButtons & (1<<(i*2))) {
+				Sys_QueEvent(g_wv.sysMsgTime, SE_KEY, K_MOUSE1+i, qtrue, 0, NULL);
+			} else if (ri.data.mouse.ulButtons & (1<<(i*2+1))) {
+				Sys_QueEvent(g_wv.sysMsgTime, SE_KEY, K_MOUSE1+i, qfalse, 0, NULL);
+			}
+		}
+		if (ri.data.mouse.lLastX || ri.data.mouse.lLastY) {
+			Sys_QueEvent(0, SE_MOUSE, ri.data.mouse.lLastX, ri.data.mouse.lLastY, 0, NULL);
+		}
+		break;
+	}	
+	// !Cgg
+
 	case WM_SYSCOMMAND:
 		if ( wParam == SC_SCREENSAVE )
 			return 0;
 		break;
 
 	case WM_SYSKEYDOWN:
-		if ( wParam == 13 )
-		{
-			if ( r_fullscreen )
-			{
-				Cvar_SetValue( "r_fullscreen", !r_fullscreen->integer );
-				Cbuf_AddText( "vid_restart\n" );
-			}
-			return 0;
-		}
+// drakkar - dont swap fullscreen here, better in cl_keys.c
+/*
+-		if ( wParam == 13 )
+-		{
+-			if ( r_fullscreen )
+-			{
+-				Cvar_SetValue( "r_fullscreen", !r_fullscreen->integer );
+-				Cbuf_AddText( "vid_restart\n" );
+-			}
+-			return 0;
+-		}
+*/
+// !drakkar
 		// fall through
 	case WM_KEYDOWN:
 		Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, MapKey( lParam ), qtrue, 0, NULL );
