Index: binaries/data/config/default.cfg
===================================================================
--- binaries/data/config/default.cfg	(Revision 15816)
+++ binaries/data/config/default.cfg	(Arbeitskopie)
@@ -240,6 +240,7 @@
 ; > ENTITY SELECTION
 hotkey.selection.add = Shift                ; Add units to selection
 hotkey.selection.milonly = Alt              ; Add only military units to selection
+hotkey.selection.idleonly = "I"             ; Select only idle units
 hotkey.selection.remove = Ctrl              ; Remove units from selection
 hotkey.selection.cancel = Esc               ; Un-select all units and cancel building placement 
 hotkey.selection.idleworker = Period        ; Select next idle worker
Index: binaries/data/mods/public/gui/session/input.js
===================================================================
--- binaries/data/mods/public/gui/session/input.js	(Revision 15816)
+++ binaries/data/mods/public/gui/session/input.js	(Arbeitskopie)
@@ -437,44 +437,89 @@
 	return true;
 }
 
-// Limits bandboxed selections to certain types of entities based on priority
-function getPreferredEntities(ents)
+// Run all filters, until one returns at least on element.
+// A filter must acept an entity as parameter and return a boolean value.
+function iteratedEntityFilter(ents, filters)
 {
-	var entStateList = [];
 	var preferredEnts = [];
-
-	// Check if there are units in the selection and get a list of entity states
-	for each (var ent in ents)
+	for (var i = 0; i < filters.length; i++)
 	{
-		var entState = GetEntityState(ent);
-		if (!entState)
-			continue;
-		if (hasClass(entState, "Unit"))
-			preferredEnts.push(ent);
-
-		entStateList.push(entState);
+		preferredEnts = ents.filter(filters[i]);
+		if (preferredEnts.length > 0) // filter was sucessfull
+		{
+			return preferredEnts;
+		}
 	}
+	return [];
+}
 
-	// If there are no units, check if there are defensive entities in the selection
-	if (!preferredEnts.length)
-		for (var i = 0; i < ents.length; i++)
-			if (hasClass(entStateList[i], "Defensive"))
-				preferredEnts.push(ents[i]);
+// Updates the bandbox object with new positions and visibility.
+// The coordinates [x0, y0, x1, y1] are returned for further use.
+function updateBandbox(bandbox, ev, hidden)
+{
+	var x0 = dragStart[0];
+	var y0 = dragStart[1];
+	var x1 = ev.x;
+	var y1 = ev.y;
+	// normalize the orientation of the rectangle
+	if (x0 > x1) { var t = x0; x0 = x1; x1 = t; }
+	if (y0 > y1) { var t = y0; y0 = y1; y1 = t; }
 
-	return preferredEnts;
+	bandbox.size = [x0, y0, x1, y1].join(" ");
+	bandbox.hidden = hidden;
+	
+	return [x0, y0, x1, y1];
 }
 
-// Removes any support units from the passed list of entities
-function getMilitaryEntities(ents)
+// returns a list of filters to be used with the iterated entity filter
+// the list is based of the hotkeys held down.
+// TODO: This can easily handle "control all units".
+function unitFilterConfiguration()
 {
-	var militaryEnts = [];
-	for each (var ent in ents)
-	{
-		var entState = GetEntityState(ent);
-		if (!hasClass(entState, "Support"))
-			militaryEnts.push(ent);
+	// check if the filter functions have already been created
+	// the functions are cached to avoid recreating them each time (as static variables)
+	// NOTE: That may be premature optimization
+	if (typeof unitFilterConfiguration.filters == 'undefined') {
+		unitFilterConfiguration.filters = {
+			"isUnit" : function (entity)
+			{
+				var entState = GetEntityState(entity);
+				if (!entState)
+					return false;
+				return hasClass(entState, "Unit");
+			},
+			"isDefensive" : function (entity)
+			{
+				var entState = GetEntityState(entity);
+				if (!entState)
+					return false;
+				return hasClass(entState, "Defensive");
+			},
+			"isNotSupport" : function (entity)
+			{
+				var entState = GetEntityState(entity);
+				if (!entState)
+					return false;
+				return hasClass(entState, "Unit") && !hasClass(entState, "Support");
+			},
+			"isIdle" : function (entity)
+			{
+				var entState = GetEntityState(entity);
+				if (!entState)
+					return false;
+				return hasClass(entState, "Unit") && entState.unitAI.isIdle;
+			},
+			"everything" : function (entity) {return true;}
+		}
 	}
-	return militaryEnts;
+	
+	var filters = unitFilterConfiguration.filters
+	
+	if (Engine.HotkeyIsPressed("selection.milonly"))
+		return [filters["isNotSupport"]];
+	if (Engine.HotkeyIsPressed("selection.idleonly"))
+		return [filters["isIdle"]];
+	return [filters["isUnit"], filters["isDefensive"], filters["everything"]];
 }
 
 function handleInputBeforeGui(ev, hoveredObject)
@@ -511,56 +556,27 @@
 	switch (inputState)
 	{
 	case INPUT_BANDBOXING:
+		var bandbox = Engine.GetGUIObjectByName("bandbox");
 		switch (ev.type)
 		{
 		case "mousemotion":
-			var x0 = dragStart[0];
-			var y0 = dragStart[1];
-			var x1 = ev.x;
-			var y1 = ev.y;
-			if (x0 > x1) { var t = x0; x0 = x1; x1 = t; }
-			if (y0 > y1) { var t = y0; y0 = y1; y1 = t; }
+			var rect = updateBandbox(bandbox, ev, false);
 
-			var bandbox = Engine.GetGUIObjectByName("bandbox");
-			bandbox.size = [x0, y0, x1, y1].join(" ");
-			bandbox.hidden = false;
+			var ents = Engine.PickFriendlyEntitiesInRect(rect[0], rect[1], rect[2], rect[3], Engine.GetPlayerID());
+			var preferredEntities = iteratedEntityFilter(ents, unitFilterConfiguration());
+			g_Selection.setHighlightList(preferredEntities);
 
-			// TODO: Should we handle "control all units" here as well?
-			var ents = Engine.PickFriendlyEntitiesInRect(x0, y0, x1, y1, Engine.GetPlayerID());
-			g_Selection.setHighlightList(ents);
-
 			return false;
 
 		case "mousebuttonup":
 			if (ev.button == SDL_BUTTON_LEFT)
 			{
-				var x0 = dragStart[0];
-				var y0 = dragStart[1];
-				var x1 = ev.x;
-				var y1 = ev.y;
-				if (x0 > x1) { var t = x0; x0 = x1; x1 = t; }
-				if (y0 > y1) { var t = y0; y0 = y1; y1 = t; }
+				var rect = updateBandbox(bandbox, ev, true);
 
-				var bandbox = Engine.GetGUIObjectByName("bandbox");
-				bandbox.hidden = true;
-
 				// Get list of entities limited to preferred entities
-				// TODO: Should we handle "control all units" here as well?
-				var ents = Engine.PickFriendlyEntitiesInRect(x0, y0, x1, y1, Engine.GetPlayerID());
-				var preferredEntities = getPreferredEntities(ents)
+				var ents = Engine.PickFriendlyEntitiesInRect(rect[0], rect[1], rect[2], rect[3], Engine.GetPlayerID());
+				ents = iteratedEntityFilter(ents, unitFilterConfiguration());
 
-				if (preferredEntities.length)
-				{
- 					ents = preferredEntities;
-
-					if (Engine.HotkeyIsPressed("selection.milonly"))
-					{
-						var militaryEntities = getMilitaryEntities(ents);
-						if (militaryEntities.length)
-							ents = militaryEntities;
-					}
-				}
-
 				// Remove the bandbox hover highlighting
 				g_Selection.setHighlightList([]);
 
@@ -585,7 +601,6 @@
 			else if (ev.button == SDL_BUTTON_RIGHT)
 			{
 				// Cancel selection
-				var bandbox = Engine.GetGUIObjectByName("bandbox");
 				bandbox.hidden = true;
 
 				g_Selection.setHighlightList([]);
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js	(Revision 15816)
+++ binaries/data/mods/public/simulation/components/GuiInterface.js	(Arbeitskopie)
@@ -331,6 +331,7 @@
 			"canGuard": cmpUnitAI.CanGuard(),
 			"isGuarding": cmpUnitAI.IsGuardOf(),
 			"possibleStances": cmpUnitAI.GetPossibleStances(),
+			"isIdle":cmpUnitAI.IsIdle(),
 		};
 		// Add some information needed for ungarrisoning
 		if (cmpUnitAI.IsGarrisoned() && ret.player !== undefined)
