Index: src/settings.cpp
===================================================================
--- src/settings.cpp	(Revision 13681)
+++ src/settings.cpp	(Arbeitskopie)
@@ -65,6 +65,8 @@
 
 #include "table/strings.h"
 
+#include "core/smallvec_type.hpp"
+
 ClientSettings _settings_client;
 GameSettings _settings_game;
 GameSettings _settings_newgame;
@@ -2101,6 +2103,54 @@
 	ini_free(ini);
 }
 
+typedef SmallVector<char *, 8> PresetList;
+PresetList _grf_preset_list;
+
+void GetGRFPresetList()
+{
+	/* Clear out the list of old entries */
+	for (uint i = 0; i < _grf_preset_list.Length(); i++) {
+		free(_grf_preset_list[i]);
+	}
+
+	_grf_preset_list.Clear();
+
+	IniFile *ini = ini_load(_config_file);
+	IniGroup *group;
+	for (group = ini->group; group != NULL; group = group->next) {
+		if (strncmp(group->name, "preset-", 7) == 0) {
+			*_grf_preset_list.Append() = strdup(group->name + 7);
+		}
+	}
+
+	_grf_preset_list.Compact();
+
+	ini_free(ini);
+}
+
+GRFConfig *LoadGRFPresetFromConfig(const char *config_name)
+{
+	char section[MAX_PATH];
+	snprintf(section, lengthof(section), "preset-%s", config_name);
+
+	IniFile *ini = ini_load(_config_file);
+	GRFConfig *config = GRFLoadConfig(ini, section, false);
+	ini_free(ini);
+
+	return config;
+}
+
+void SaveGRFPresetToConfig(const char *config_name, GRFConfig *config)
+{
+	char section[MAX_PATH];
+	snprintf(section, lengthof(section), "preset-%s", config_name);
+
+	IniFile *ini = ini_load(_config_file);
+	GRFSaveConfig(ini, section, config);
+	ini_save(_config_file, ini);
+	ini_free(ini);
+}
+
 static const SettingDesc *GetSettingDescription(uint index)
 {
 	if (index >= lengthof(_patch_settings)) return NULL;
Index: src/lang/english.txt
===================================================================
--- src/lang/english.txt	(Revision 13681)
+++ src/lang/english.txt	(Arbeitskopie)
@@ -3168,6 +3168,10 @@
 STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED                        :Too many NewGRFs are loaded.
 STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC                       :Loading {STRING} as static NewGRF with {STRING} could cause desyncs.
 
+STR_NEWGRF_PRESET_LIST_TIP                                      :{BLACK}Load the selected preset
+STR_NEWGRF_PRESET_SAVE                                          :{BLACK}Save preset
+STR_NEWGRF_PRESET_SAVE_TIP                                      :{BLACK}Save the current list as a preset
+STR_NEWGRF_PRESET_SAVE_QUERY                                    :{BLACK}Enter name for preset
 STR_NEWGRF_ADD                                                  :{BLACK}Add
 STR_NEWGRF_ADD_TIP                                              :{BLACK}Add a NewGRF file to the list
 STR_NEWGRF_REMOVE                                               :{BLACK}Remove
Index: src/newgrf_gui.cpp
===================================================================
--- src/newgrf_gui.cpp	(Revision 13681)
+++ src/newgrf_gui.cpp	(Arbeitskopie)
@@ -15,11 +15,16 @@
 #include "core/alloc_func.hpp"
 #include "string_func.h"
 #include "gfx_func.h"
+#include "settings_func.h"
+#include "widgets/dropdown_type.h"
 #include "gamelog.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
 
+#include "core/smallvec_type.hpp"
+
+
 /** Parse an integerlist string and set each found value
  * @param p the string to be parsed. Each element in the list is seperated by a
  * comma or a space character
@@ -253,7 +258,27 @@
 	_newgrf_add_dlg_widgets,
 };
 
+/* YUM WE LIKE GLOBALS OH YES */             
+typedef SmallVector<char *, 8> PresetList;
+extern PresetList _grf_preset_list;
 
+class DropDownListPresetItem : public DropDownListItem {
+public:
+	DropDownListPresetItem(int result) : DropDownListItem(result, false) {}
+
+	virtual ~DropDownListPresetItem() {}
+
+	virtual StringID String() const
+	{
+		return STR_EMPTY;
+	}
+
+	virtual void Draw(int x, int y, uint width, uint height, bool sel) const
+	{
+		DoDrawStringTruncated(_grf_preset_list[this->result], x + 2, y, sel ? TC_WHITE : TC_BLACK, x + width);
+	}
+};
+
 static void NewGRFConfirmationCallback(Window *w, bool confirmed);
 
 /**
@@ -264,7 +289,10 @@
 	enum ShowNewGRFStateWidgets {
 		SNGRFS_CLOSEBOX = 0,
 		SNGRFS_CAPTION,
-		SNGRFS_BACKGROUND,
+		SNGRFS_BACKGROUND1,
+		SNGRFS_PRESET_LIST,
+		SNGRFS_PRESET_SAVE,
+		SNGRFS_BACKGROUND2,
 		SNGRFS_ADD,
 		SNGRFS_REMOVE,
 		SNGRFS_MOVE_UP,
@@ -283,6 +311,8 @@
 	bool editable;         ///< is the window editable
 	bool show_params;      ///< are the grf-parameters shown in the info-panel
 	bool execute;          ///< on pressing 'apply changes' are grf changes applied immediately, or only list is updated
+	int query_widget;      ///< widget that opened a query
+	int preset;            ///< selected preset
 
 	NewGRFWindow(const WindowDesc *desc, bool editable, bool show_params, bool exec_changes, GRFConfig **config) : Window(desc, 0)
 	{
@@ -293,6 +323,7 @@
 		this->editable    = editable;
 		this->execute     = exec_changes;
 		this->show_params = show_params;
+		this->preset      = -1;
 
 		CopyGRFConfigList(&this->list, *config, false);
 
@@ -322,8 +353,12 @@
 		this->vscroll.cap = (this->widget[SNGRFS_FILE_LIST].bottom - this->widget[SNGRFS_FILE_LIST].top) / 14 + 1;
 		SetVScrollCount(this, i);
 
-		this->SetWidgetDisabledState(SNGRFS_ADD, !this->editable);
-		this->SetWidgetDisabledState(SNGRFS_APPLY_CHANGES, !this->editable);
+		this->SetWidgetsDisabledState(!this->editable,
+			SNGRFS_PRESET_LIST,
+			SNGRFS_ADD,
+			SNGRFS_APPLY_CHANGES,
+			WIDGET_LIST_END
+		);
 	}
 
 	virtual void OnPaint()
@@ -345,6 +380,12 @@
 			if (this->sel->IsOpenTTDBaseGRF()) this->DisableWidget(SNGRFS_REMOVE);
 		}
 
+		if (this->preset == -1) {
+			this->widget[SNGRFS_PRESET_LIST].data = STR_02BF_CUSTOM;
+		} else {
+			this->widget[SNGRFS_PRESET_LIST].data = BindCString(_grf_preset_list[this->preset]);
+		}
+
 		this->DrawWidgets();
 
 		/* Draw NewGRF list */
@@ -397,6 +438,27 @@
 	virtual void OnClick(Point pt, int widget)
 	{
 		switch (widget) {
+			case SNGRFS_PRESET_LIST: {
+				GetGRFPresetList();
+
+				DropDownList *list = new DropDownList();
+
+				/* Add 'None' option for clearing list */
+				list->push_back(new DropDownListStringItem(STR_NONE, -1, false));
+
+				for (uint i = 0; i < _grf_preset_list.Length(); i++) {
+					list->push_back(new DropDownListPresetItem(i));
+				}
+
+				ShowDropDownList(this, list, -1, SNGRFS_PRESET_LIST);
+				break;
+			}
+
+			case SNGRFS_PRESET_SAVE:
+				this->query_widget = widget;
+				ShowQueryString(STR_EMPTY, STR_NEWGRF_PRESET_SAVE_QUERY, 32, 100, this, CS_ALPHANUMERAL);
+				break;
+
 			case SNGRFS_ADD: // Add GRF
 				DeleteWindowByClass(WC_SAVELOAD);
 				new NewGRFAddWindow(&_newgrf_add_dlg_desc, &this->list);
@@ -421,6 +483,7 @@
 				}
 
 				this->sel = newsel;
+				this->preset = -1;
 				this->SetupNewGRFWindow();
 				this->SetDirty();
 				break;
@@ -438,6 +501,7 @@
 						break;
 					}
 				}
+				this->preset = -1;
 				this->SetDirty();
 				break;
 			}
@@ -454,6 +518,7 @@
 						break;
 					}
 				}
+				this->preset = -1;
 				this->SetDirty();
 				break;
 			}
@@ -487,6 +552,8 @@
 			case SNGRFS_SET_PARAMETERS: { // Edit parameters
 				if (this->sel == NULL) break;
 
+				this->query_widget = widget;
+
 				char buff[512];
 				GRFBuildParamList(buff, this->sel, lastof(buff));
 				ShowQueryString(BindCString(buff), STR_NEWGRF_PARAMETER_QUERY, 63, 250, this, CS_ALPHANUMERAL);
@@ -495,18 +562,48 @@
 		}
 	}
 
+	virtual void OnDropdownSelect(int widget, int index)
+	{
+		if (index == -1) {
+			ClearGRFConfigList(&this->list);
+			this->preset = -1;
+		} else {
+			GRFConfig *c = LoadGRFPresetFromConfig(_grf_preset_list[index]);
+
+			if (c != NULL) {
+				this->sel = NULL;
+				ClearGRFConfigList(&this->list);
+				this->list = c;
+				this->preset = index;
+			}
+		}
+
+		this->SetupNewGRFWindow();
+		this->SetDirty();
+	}
+
 	virtual void OnQueryTextFinished(char *str)
 	{
 		if (str == NULL) return;
 
-		/* Parse our new "int list" */
-		GRFConfig *c = this->sel;
-		c->num_params = parse_intlist(str, (int*)c->param, lengthof(c->param));
+		switch (this->query_widget) {
+			case SNGRFS_PRESET_SAVE:
+				SaveGRFPresetToConfig(str, this->list);
+				break;
 
-		/* parse_intlist returns -1 on error */
-		if (c->num_params == (byte)-1) c->num_params = 0;
+			case SNGRFS_SET_PARAMETERS: {
+				/* Parse our new "int list" */
+				GRFConfig *c = this->sel;
+				c->num_params = parse_intlist(str, (int*)c->param, lengthof(c->param));
 
-		this->SetDirty();
+				/* parse_intlist returns -1 on error */
+				if (c->num_params == (byte)-1) c->num_params = 0;
+
+				this->preset = -1;
+				this->SetDirty();
+				break;
+			}
+		}
 	}
 
 	virtual void OnResize(Point new_size, Point delta)
@@ -524,6 +621,7 @@
 
 	virtual void OnInvalidateData(int data = 0)
 	{
+		this->preset = -1;
 		this->SetupNewGRFWindow();
 	}
 };
@@ -532,23 +630,26 @@
 static const Widget _newgrf_widgets[] = {
 {   WWT_CLOSEBOX,  RESIZE_NONE, 10,   0,  10,   0,  13, STR_00C5,                    STR_018B_CLOSE_WINDOW },            // SNGRFS_CLOSEBOX
 {    WWT_CAPTION, RESIZE_RIGHT, 10,  11, 299,   0,  13, STR_NEWGRF_SETTINGS_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS },  // SNGRFS_CAPTION
-{      WWT_PANEL, RESIZE_RIGHT, 10,   0, 299,  14,  29, STR_NULL,                    STR_NULL },                         // SNGRFS_BACKGROUND
-{ WWT_PUSHTXTBTN,  RESIZE_NONE,  3,  10,  79,  16,  27, STR_NEWGRF_ADD,              STR_NEWGRF_ADD_TIP },               // SNGRFS_ADD
-{ WWT_PUSHTXTBTN,  RESIZE_NONE,  3,  80, 149,  16,  27, STR_NEWGRF_REMOVE,           STR_NEWGRF_REMOVE_TIP },            // SNGRFS_REMOVE
-{ WWT_PUSHTXTBTN,  RESIZE_NONE,  3, 150, 219,  16,  27, STR_NEWGRF_MOVEUP,           STR_NEWGRF_MOVEUP_TIP },            // SNGRFS_MOVE_UP
-{ WWT_PUSHTXTBTN, RESIZE_RIGHT,  3, 220, 289,  16,  27, STR_NEWGRF_MOVEDOWN,         STR_NEWGRF_MOVEDOWN_TIP },          // SNGRFS_MOVE_DOWN
-{     WWT_MATRIX,    RESIZE_RB, 10,   0, 287,  30,  99, 0x501,                       STR_NEWGRF_FILE_TIP },              // SNGRFS_FILE_LIST
-{  WWT_SCROLLBAR,   RESIZE_LRB, 10, 288, 299,  30,  99, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST }, // SNGRFS_SCROLLBAR
-{      WWT_PANEL,   RESIZE_RTB, 10,   0, 299, 100, 212, STR_NULL,                    STR_NULL },                         // SNGRFS_NEWGRF_INFO
-{ WWT_PUSHTXTBTN,    RESIZE_TB, 10,   0, 143, 213, 224, STR_NEWGRF_SET_PARAMETERS,   STR_NULL },                         // SNGRFS_SET_PARAMETERS
-{ WWT_PUSHTXTBTN,   RESIZE_RTB, 10, 144, 287, 213, 224, STR_NEWGRF_APPLY_CHANGES,    STR_NULL },                         // SNGRFS_APPLY_CHANGES
-{  WWT_RESIZEBOX,  RESIZE_LRTB, 10, 288, 299, 213, 224, 0x0,                         STR_RESIZE_BUTTON },                // SNGRFS_RESIZE
+{      WWT_PANEL, RESIZE_RIGHT, 10,   0, 299,  14,  41, STR_NULL,                    STR_NULL },                         // SNGRFS_BACKGROUND1
+{   WWT_DROPDOWN, RESIZE_RIGHT,  3,  10, 219,  16,  27, STR_EMPTY,                   STR_NEWGRF_PRESET_LIST_TIP },       // SNGRFS_PRESET_LIST
+{ WWT_PUSHTXTBTN,    RESIZE_LR,  3, 220, 289,  16,  27, STR_NEWGRF_PRESET_SAVE,      STR_NEWGRF_PRESET_SAVE_TIP },       // SNGRFS_PRESET_SAVE
+{      WWT_PANEL, RESIZE_RIGHT, 10,   0, 299,  30,  45, STR_NULL,                    STR_NULL },                         // SNGRFS_BACKGROUND
+{ WWT_PUSHTXTBTN,  RESIZE_NONE,  3,  10,  79,  32,  43, STR_NEWGRF_ADD,              STR_NEWGRF_ADD_TIP },               // SNGRFS_ADD
+{ WWT_PUSHTXTBTN,  RESIZE_NONE,  3,  80, 149,  32,  43, STR_NEWGRF_REMOVE,           STR_NEWGRF_REMOVE_TIP },            // SNGRFS_REMOVE
+{ WWT_PUSHTXTBTN,  RESIZE_NONE,  3, 150, 219,  32,  43, STR_NEWGRF_MOVEUP,           STR_NEWGRF_MOVEUP_TIP },            // SNGRFS_MOVE_UP
+{ WWT_PUSHTXTBTN, RESIZE_RIGHT,  3, 220, 289,  32,  43, STR_NEWGRF_MOVEDOWN,         STR_NEWGRF_MOVEDOWN_TIP },          // SNGRFS_MOVE_DOWN
+{     WWT_MATRIX,    RESIZE_RB, 10,   0, 287,  46, 115, 0x501,                       STR_NEWGRF_FILE_TIP },              // SNGRFS_FILE_LIST
+{  WWT_SCROLLBAR,   RESIZE_LRB, 10, 288, 299,  46, 115, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST }, // SNGRFS_SCROLLBAR
+{      WWT_PANEL,   RESIZE_RTB, 10,   0, 299, 116, 228, STR_NULL,                    STR_NULL },                         // SNGRFS_NEWGRF_INFO
+{ WWT_PUSHTXTBTN,    RESIZE_TB, 10,   0, 143, 229, 240, STR_NEWGRF_SET_PARAMETERS,   STR_NULL },                         // SNGRFS_SET_PARAMETERS
+{ WWT_PUSHTXTBTN,   RESIZE_RTB, 10, 144, 287, 229, 240, STR_NEWGRF_APPLY_CHANGES,    STR_NULL },                         // SNGRFS_APPLY_CHANGES
+{  WWT_RESIZEBOX,  RESIZE_LRTB, 10, 288, 299, 229, 240, 0x0,                         STR_RESIZE_BUTTON },                // SNGRFS_RESIZE
 { WIDGETS_END },
 };
 
 /* Window definition of the manage newgrfs window */
 static const WindowDesc _newgrf_desc = {
-	WDP_CENTER, WDP_CENTER, 300, 225, 300, 225,
+	WDP_CENTER, WDP_CENTER, 300, 241, 300, 241,
 	WC_GAME_OPTIONS, WC_NONE,
 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 	_newgrf_widgets,
Index: src/settings_func.h
===================================================================
--- src/settings_func.h	(Revision 13681)
+++ src/settings_func.h	(Arbeitskopie)
@@ -14,4 +14,10 @@
 void SaveToConfig();
 void CheckConfig();
 
+/* Functions to load and save NewGRF settings to a separate
+ * configuration file, used for presets. */
+void GetGRFPresetList();
+struct GRFConfig *LoadGRFPresetFromConfig(const char *config_name);
+void SaveGRFPresetToConfig(const char *config_name, struct GRFConfig *config);
+
 #endif /* SETTINGS_FUNC_H */
