Changes in refs/remotes/origin/master
	Modified   qcsrc/dpdefs/csprogsdefs.qc
diff --git a/qcsrc/dpdefs/csprogsdefs.qc b/qcsrc/dpdefs/csprogsdefs.qc
index 7b0644e..e4968f0 100644
--- a/qcsrc/dpdefs/csprogsdefs.qc
+++ b/qcsrc/dpdefs/csprogsdefs.qc
@@ -435,6 +435,9 @@ vector(string) stov = #117;
 string(string s) strzone = #118;
 void(string s) strunzone = #119;
 
+// Colin
+float(string from, string to) rename = #642;
+
 // FTEQW range #200-#299
 
 float(float number, float quantity) bitshift = #218;
	Modified   qcsrc/dpdefs/dpextensions.qc
diff --git a/qcsrc/dpdefs/dpextensions.qc b/qcsrc/dpdefs/dpextensions.qc
index 0a55043..7887e1e 100644
--- a/qcsrc/dpdefs/dpextensions.qc
+++ b/qcsrc/dpdefs/dpextensions.qc
@@ -2115,6 +2115,10 @@ string(string s, float start, float length) substring = #116; // returns a secti
 vector(string s) stov = #117; // returns vector value from a string
 string(string s, ...) strzone = #118; // makes a copy of a string into the string zone and returns it, this is often used to keep around a tempstring for longer periods of time (tempstrings are replaced often)
 void(string s) strunzone = #119; // removes a copy of a string from the string zone (you can not use that string again or it may crash!!!)
+
+// Colin
+float(string from, string to) rename = #642;
+
 //constants:
 float FILE_READ = 0;
 float FILE_APPEND = 1;
	Modified   qcsrc/dpdefs/menudefs.qc
diff --git a/qcsrc/dpdefs/menudefs.qc b/qcsrc/dpdefs/menudefs.qc
index ad8666e..932de8c 100644
--- a/qcsrc/dpdefs/menudefs.qc
+++ b/qcsrc/dpdefs/menudefs.qc
@@ -244,6 +244,9 @@ void	fclose(float fhandle)  = #49;
 string	fgets(float fhandle)  = #50;
 void	fputs(float fhandle, string s)  = #51;
 
+// Colin
+float rename(string from, string to) = #642;
+
 float	strlen(string s)  = #52;
 string	strcat(string s1,string s2,...)  = #53;
 string	substring(string s, float start, float length)  = #54;
	Modified   qcsrc/menu/classes.c
diff --git a/qcsrc/menu/classes.c b/qcsrc/menu/classes.c
index f838257..817266d 100644
--- a/qcsrc/menu/classes.c
+++ b/qcsrc/menu/classes.c
@@ -86,6 +86,8 @@
 #include "xonotic/dialog_multiplayer_playersetup_view.c"
 #include "xonotic/dialog_multiplayer_playersetup_weapons.c"
 #include "xonotic/weaponslist.c"
+// Added by Colin
+#include "xonotic/dialog_multiplayer_demo_demoinfo.c"
 #include "xonotic/dialog_multiplayer_demo.c"
 #include "xonotic/demolist.c"
 #include "xonotic/colorpicker.c"
	Modified   qcsrc/menu/xonotic/demolist.c
diff --git a/qcsrc/menu/xonotic/demolist.c b/qcsrc/menu/xonotic/demolist.c
index 2daed8b..5d9fa48 100644
--- a/qcsrc/menu/xonotic/demolist.c
+++ b/qcsrc/menu/xonotic/demolist.c
@@ -22,12 +22,14 @@ CLASS(XonoticDemoList) EXTENDS(XonoticListBox)
 	
 	ATTRIB(XonoticDemoList, lastClickedDemo, float, -1)
 	ATTRIB(XonoticDemoList, lastClickedTime, float, 0)
-	ATTRIB(XonoticDemoList, filterString, string, string_null)	
+	ATTRIB(XonoticDemoList, filterString, string, string_null)
 ENDCLASS(XonoticDemoList)
 
 entity makeXonoticDemoList();
 void StartDemo_Click(entity btn, entity me);
 void TimeDemo_Click(entity btn, entity me);
+void InfoDemo_Click(entity btn, entity dlist);
+
 void DemoList_Filter_Change(entity box, entity me);
 #endif
 
@@ -44,7 +46,7 @@ entity makeXonoticDemoList()
 void XonoticDemoList_configureXonoticDemoList(entity me)
 {
 	me.configureXonoticListBox(me);
-	me.getDemos(me);	
+	me.getDemos(me);
 }
 
 string XonoticDemoList_demoName(entity me, float i )
@@ -62,7 +64,7 @@ void XonoticDemoList_getDemos(entity me)
 	
 	if(me.filterString)
 		//subdirectory in filterString allowed	
-		s=strcat("demos/*", me.filterString, "*.dem");		
+		s=strcat("demos/*", me.filterString, "*.dem");
 	else
 		s="demos/*.dem";
 	
@@ -128,7 +130,7 @@ void DemoList_Filter_Change(entity box, entity me)
 void XonoticDemoList_startDemo(entity me)
 {
 	string s;
-	s = me.demoName(me,me.selectedItem);
+	s = me.demoName(me, me.selectedItem);
 	localcmd("playdemo \"demos/", s, ".dem\" \nwait \ntogglemenu\n");	
 }
 
@@ -144,6 +146,14 @@ void TimeDemo_Click(entity btn, entity me)
 	localcmd("timedemo \"demos/", s, ".dem\" \nwait \ntogglemenu\n");	
 }
 
+// Opens up a dialog for additional information about the selected
+// demo file
+void InfoDemo_Click(entity btn, entity dlist)
+{
+	main.demoInfoDialog.loadDemoInfo(main.demoInfoDialog, dlist);
+	DialogOpenButton_Click(dlist, main.demoInfoDialog);
+}
+
 void XonoticDemoList_clickListBoxItem(entity me, float i, vector where)
 {
 	if(i == me.lastClickedDemo)
@@ -166,5 +176,5 @@ float XonoticDemoList_keyDown(entity me, float scan, float ascii, float shift)
 	else
 		return SUPER(XonoticDemoList).keyDown(me, scan, ascii, shift);
 }
-#endif
 
+#endif
	Modified   qcsrc/menu/xonotic/dialog_multiplayer_demo.c
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_demo.c b/qcsrc/menu/xonotic/dialog_multiplayer_demo.c
index bb4b969..a5f8c90 100644
--- a/qcsrc/menu/xonotic/dialog_multiplayer_demo.c
+++ b/qcsrc/menu/xonotic/dialog_multiplayer_demo.c
@@ -42,11 +42,14 @@ void XonoticDemoBrowserTab_fill(entity me)
 		me.TD(me, me.rows - 4, me.columns, dlist);
 		
 	me.gotoRC(me, me.rows - 1, 0);
-		me.TD(me, 1, me.columns / 2, e = makeXonoticButton(_("Timedemo"), '0 0 0'));
+		me.TD(me, 1, me.columns / 3, e = makeXonoticButton(_("Timedemo"), '0 0 0'));
 			e.onClick = TimeDemo_Click;
 			e.onClickEntity = dlist;
-		me.TD(me, 1, me.columns / 2, e = makeXonoticButton(ZCTX(_("DEMO^Play")), '0 0 0'));
+		me.TD(me, 1, me.columns / 3, e = makeXonoticButton(ZCTX(_("Play")), '0 0 0'));
 			e.onClick = StartDemo_Click;
-			e.onClickEntity = dlist;
+			e.onClickEntity = dlist;			
+		me.TD(me, 1, me.columns / 3, e = makeXonoticButton(_("Info..."), '0 0 0'));
+			e.onClick = InfoDemo_Click;
+			e.onClickEntity = dlist;			
 }
 #endif
	New        qcsrc/menu/xonotic/dialog_multiplayer_demo_demoinfo.c
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_demo_demoinfo.c b/qcsrc/menu/xonotic/dialog_multiplayer_demo_demoinfo.c
new file mode 100644
index 0000000..b214a2e
--- /dev/null
+++ b/qcsrc/menu/xonotic/dialog_multiplayer_demo_demoinfo.c
@@ -0,0 +1,128 @@
+// NOTE: When user presses "Save" dont close the Dialog. Instead, update!
+#ifdef INTERFACE
+CLASS(XonoticDemoInfoDialog) EXTENDS(XonoticDialog)
+        METHOD(XonoticDemoInfoDialog, fill, void(entity))
+	METHOD(XonoticDemoInfoDialog, loadDemoInfo, void(entity, entity))
+	ATTRIB(XonoticDemoInfoDialog, title, string, _("Demo Information"))
+	// ATTRIB(XonoticDemoInfoDialog, color, vector, SKINCOLOR_DIALOG_DEMOINFO)
+	ATTRIB(XonoticDemoInfoDialog, intendedWidth, float, 0.8)
+	ATTRIB(XonoticDemoInfoDialog, rows, float, 18)
+	ATTRIB(XonoticDemoInfoDialog, columns, float, 6.2)
+	
+	ATTRIB(XonoticDemoInfoDialog, currentDemoName, string, string_null)
+
+	ATTRIB(XonoticDemoInfoDialog, demoNameLabel, entity, NULL)
+	ATTRIB(XonoticDemoInfoDialog, demolist, entity, NULL)
+
+	// Used to change the demo name.
+	ATTRIB(XonoticDemoInfoDialog, newDemoName, string, string_null)
+	ATTRIB(XonoticDemoInfoDialog, demoNameBox, entity, NULL)	
+ENDCLASS(XonoticDemoInfoDialog)
+
+void PlayDemo_Click(entity btn, entity me);
+#endif
+
+#ifdef IMPLEMENTATION
+void XonoticDemoInfoDialog_loadDemoInfo(entity me, entity dlist)
+{
+	// ====================================
+	//  First clear and unzone the strings
+	// ====================================	
+	if(me.currentDemoName)
+		strunzone(me.currentDemoName);
+	me.currentDemoName = string_null;
+
+	
+	// ==========================
+	//  Now, fill in the strings
+	// ==========================
+	me.currentDemoName = strzone(dlist.demoName(dlist, dlist.selectedItem));	
+	me.demoNameLabel.setText(me.demoNameLabel, me.currentDemoName);
+	me.demoNameBox.setText(me.demoNameBox, me.currentDemoName);
+	
+	dprint("Current demo: ", me.currentDemoName, "\n");
+	
+	// Save the demo list for updating
+	me.demolist = dlist;
+}
+
+void XonoticDemoInfoDialog_Clear(entity me)
+{
+	// ====================================
+	//  First clear and unzone the strings
+	// ====================================
+	if(me.newDemoName)
+		strunzone(me.newDemoName);
+	me.newDemoName = string_null;
+}
+
+void PlayDemo_Click(entity btn, entity me)
+{
+	localcmd("playdemo \"demos/", me.currentDemoName, ".dem\" \nwait \ntogglemenu\n");	
+}
+
+void XonoticDemoInfoDialog_Save(entity btn, entity me)
+{
+	float rename_error;
+	string oldname;
+	string newname;
+	// Colin: when the user clicks OK the newDemoName has to be
+	// applied before strun and closeDialog can be run.
+	
+	// 1. Change/Save the new demo name
+	
+	oldname = strcat("demos/", me.currentDemoName, ".dem");
+	newname = strcat("demos/", me.demoNameBox.text, ".dem");
+		
+	rename_error = rename(oldname, newname);
+	if(rename_error < 0.0) {
+		dprint("Save: could not save the new name.");
+		return;		
+	}
+	
+	// 2. Update the demolist
+	me.demolist.getDemos(me.demolist);
+	
+	// 3. Close the dialog
+	DialogCloseButton_Click(me, main.demoInfoDialog);
+}
+
+void XonoticDemoInfoDialog_Cancel(entity btn, entity me)
+{
+	// Colin: when the user closes the demo info dialog, the
+	// newDemoName string has to be cleared before closing
+	
+	// 1. Clear the newDemoName string
+	XonoticDemoInfoDialog_Clear(me);
+	
+	// 2. Close the demoInfoDialog
+	DialogCloseButton_Click(me, main.demoInfoDialog);
+}
+
+
+void XonoticDemoInfoDialog_fill(entity me)
+{
+	entity e, box, btn;
+
+	me.TR(me);
+	me.TR(me);
+		me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Name:")));
+		me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0, ""));
+		e.allowCut = 1;
+		me.demoNameLabel = e;
+		
+	me.TR(me);
+		me.TD(me, 1, me.columns - 0.6 * 4 - 0.4, me.demoNameBox = makeXonoticInputBox(0, string_null));
+		
+	me.gotoRC(me, me.rows - 1, 0);
+	        me.TD(me, 1, me.columns/3, e = makeXonoticButton(_("Play"), '0 0 0'));
+			e.onClick = PlayDemo_Click;
+			e.onClickEntity = me;
+		me.TD(me, 1, me.columns/3, e = makeXonoticButton(_("Cancel"), '0 0 0'));
+			e.onClick = XonoticDemoInfoDialog_Cancel;
+			e.onClickEntity = me;
+		me.TD(me, 1, me.columns/3, e = makeXonoticButton(_("Save"), '0 0 0'));
+			e.onClick = XonoticDemoInfoDialog_Save;
+			e.onClickEntity = me;
+}
+#endif
	Modified   qcsrc/menu/xonotic/mainwindow.c
diff --git a/qcsrc/menu/xonotic/mainwindow.c b/qcsrc/menu/xonotic/mainwindow.c
index f9d86c2..a411626 100644
--- a/qcsrc/menu/xonotic/mainwindow.c
+++ b/qcsrc/menu/xonotic/mainwindow.c
@@ -16,6 +16,7 @@ CLASS(MainWindow) EXTENDS(ModalController)
 	ATTRIB(MainWindow, crosshairDialog, entity, NULL)
 	ATTRIB(MainWindow, hudDialog, entity, NULL)
 	ATTRIB(MainWindow, hudconfirmDialog, entity, NULL)
+	ATTRIB(MainWindow, demoInfoDialog, entity, NULL)
 	ATTRIB(MainWindow, mainNexposee, entity, NULL)
 	ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND)
 	ATTRIB(MainWindow, dialogToShow, entity, NULL)
@@ -188,6 +189,12 @@ void MainWindow_configureMainWindow(entity me)
 	me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
 	
 
+	// dialog used by multiplayer/demo
+	me.demoInfoDialog = i = spawnXonoticDemoInfoDialog();
+	i.configureDialog(i);
+	me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+	
+	
 	// mutator dialogs
 	i = spawnXonoticSandboxToolsDialog();
 	i.configureDialog(i);

