src/newgrf_gui.cpp
branchcustombridgeheads
changeset 5649 55c8267c933f
parent 5643 3778051e8095
child 5650 aefc131bf5ce
equal deleted inserted replaced
5648:1608018c5ff2 5649:55c8267c933f
       
     1 /* $Id$ */
       
     2 
       
     3 #include "stdafx.h"
       
     4 #include "openttd.h"
       
     5 #include "functions.h"
       
     6 #include "variables.h"
       
     7 #include "gfx.h"
       
     8 #include "gui.h"
       
     9 #include "window.h"
       
    10 #include "table/strings.h"
       
    11 #include "table/sprites.h"
       
    12 #include "newgrf.h"
       
    13 #include "newgrf_config.h"
       
    14 
       
    15 
       
    16 /** Parse an integerlist string and set each found value
       
    17  * @param p the string to be parsed. Each element in the list is seperated by a
       
    18  * comma or a space character
       
    19  * @param items pointer to the integerlist-array that will be filled with values
       
    20  * @param maxitems the maximum number of elements the integerlist-array has
       
    21  * @return returns the number of items found, or -1 on an error */
       
    22 static int parse_intlist(const char *p, int *items, int maxitems)
       
    23 {
       
    24 	int n = 0, v;
       
    25 	char *end;
       
    26 
       
    27 	for (;;) {
       
    28 		v = strtol(p, &end, 0);
       
    29 		if (p == end || n == maxitems) return -1;
       
    30 		p = end;
       
    31 		items[n++] = v;
       
    32 		if (*p == '\0') break;
       
    33 		if (*p != ',' && *p != ' ') return -1;
       
    34 		p++;
       
    35 	}
       
    36 
       
    37 	return n;
       
    38 }
       
    39 
       
    40 
       
    41 static void ShowNewGRFInfo(const GRFConfig *c, uint x, uint y, uint w, bool show_params)
       
    42 {
       
    43 	char buff[512];
       
    44 	char *s;
       
    45 	uint i;
       
    46 
       
    47 	/* Draw filename or not if it is not known (GRF sent over internet) */
       
    48 	if (c->filename != NULL) {
       
    49 		SetDParamStr(0, c->filename);
       
    50 		y += DrawStringMultiLine(x, y, STR_NEWGRF_FILENAME, w);
       
    51 	}
       
    52 
       
    53 	/* Prepare and draw GRF ID */
       
    54 	snprintf(buff, lengthof(buff), "%08X", (uint32)BSWAP32(c->grfid));
       
    55 	SetDParamStr(0, buff);
       
    56 	y += DrawStringMultiLine(x, y, STR_NEWGRF_GRF_ID, w);
       
    57 
       
    58 	/* Prepare and draw MD5 sum */
       
    59 	s = buff;
       
    60 	for (i = 0; i < lengthof(c->md5sum); i++) {
       
    61 		s += snprintf(s, lastof(buff) - s, "%02X", c->md5sum[i]);
       
    62 	}
       
    63 	SetDParamStr(0, buff);
       
    64 	y += DrawStringMultiLine(x, y, STR_NEWGRF_MD5SUM, w);
       
    65 
       
    66 	/* Show GRF parameter list */
       
    67 	if (show_params) {
       
    68 		if (c->num_params > 0) {
       
    69 			GRFBuildParamList(buff, c, lastof(buff));
       
    70 			SetDParamStr(0, buff);
       
    71 		} else {
       
    72 			SetDParam(0, STR_01A9_NONE);
       
    73 		}
       
    74 		y += DrawStringMultiLine(x, y, STR_NEWGRF_PARAMETER, w);
       
    75 	}
       
    76 
       
    77 	/* Show flags */
       
    78 	if (HASBIT(c->flags, GCF_NOT_FOUND)) y += DrawStringMultiLine(x, y, STR_NEWGRF_NOT_FOUND, w);
       
    79 	if (HASBIT(c->flags, GCF_DISABLED))  y += DrawStringMultiLine(x, y, STR_NEWGRF_DISABLED, w);
       
    80 
       
    81 	/* Draw GRF info if it exists */
       
    82 	if (c->info != NULL && strlen(c->info) != 0) {
       
    83 		SetDParamStr(0, c->info);
       
    84 		y += DrawStringMultiLine(x, y, STR_02BD, w);
       
    85 	} else {
       
    86 		y += DrawStringMultiLine(x, y, STR_NEWGRF_NO_INFO, w);
       
    87 	}
       
    88 }
       
    89 
       
    90 
       
    91 /* Dialogue for adding NewGRF files to the selection */
       
    92 typedef struct newgrf_add_d {
       
    93 	GRFConfig **list;
       
    94 	const GRFConfig *sel;
       
    95 } newgrf_add_d;
       
    96 
       
    97 
       
    98 static void NewGRFAddDlgWndProc(Window *w, WindowEvent *e)
       
    99 {
       
   100 	switch (e->event) {
       
   101 		case WE_PAINT: {
       
   102 			const GRFConfig *c;
       
   103 			int y;
       
   104 			int n = 0;
       
   105 
       
   106 			/* Count the number of GRFs */
       
   107 			for (c = _all_grfs; c != NULL; c = c->next) n++;
       
   108 
       
   109 			w->vscroll.cap = (w->widget[3].bottom - w->widget[3].top) / 10;
       
   110 			SetVScrollCount(w, n);
       
   111 
       
   112 			SetWindowWidgetDisabledState(w, 6, WP(w, newgrf_add_d).sel == NULL);
       
   113 			DrawWindowWidgets(w);
       
   114 
       
   115 			GfxFillRect(w->widget[3].left + 1, w->widget[3].top + 1, w->widget[3].right, w->widget[3].bottom, 0xD7);
       
   116 
       
   117 			n = 0;
       
   118 			y = w->widget[3].top + 1;
       
   119 
       
   120 			for (c = _all_grfs; c != NULL; c = c->next) {
       
   121 				if (n >= w->vscroll.pos && n < w->vscroll.pos + w->vscroll.cap) {
       
   122 					bool h = c == WP(w, newgrf_add_d).sel;
       
   123 					const char *text = (c->name != NULL && strlen(c->name) != 0) ? c->name : c->filename;
       
   124 
       
   125 					/* Draw selection background */
       
   126 					if (h) GfxFillRect(3, y, w->width - 15, y + 9, 156);
       
   127 					DoDrawStringTruncated(text, 4, y, h ? 0xC : 0x6, w->width - 18);
       
   128 					y += 10;
       
   129 				}
       
   130 				n++;
       
   131 			}
       
   132 
       
   133 			if (WP(w, newgrf_add_d).sel != NULL) {
       
   134 				const Widget *wi = &w->widget[5];
       
   135 				ShowNewGRFInfo(WP(w, newgrf_add_d).sel, wi->left + 2, wi->top + 2, wi->right - wi->left - 2, false);
       
   136 			}
       
   137 			break;
       
   138 		}
       
   139 
       
   140 		case WE_CLICK:
       
   141 			switch (e->we.click.widget) {
       
   142 				case 3: {
       
   143 					// Get row...
       
   144 					const GRFConfig *c;
       
   145 					uint i = (e->we.click.pt.y - w->widget[3].top) / 10 + w->vscroll.pos;
       
   146 
       
   147 					for (c = _all_grfs; c != NULL && i > 0; c = c->next, i--);
       
   148 					WP(w, newgrf_add_d).sel = c;
       
   149 					SetWindowDirty(w);
       
   150 					break;
       
   151 				}
       
   152 
       
   153 				case 6: /* Add selection to list */
       
   154 					if (WP(w, newgrf_add_d).sel != NULL) {
       
   155 						const GRFConfig *src = WP(w, newgrf_add_d).sel;
       
   156 						GRFConfig **list, *c;
       
   157 
       
   158 						/* Find last entry in the list, checking for duplicate grfid on the way */
       
   159 						for (list = WP(w, newgrf_add_d).list; *list != NULL; list = &(*list)->next) {
       
   160 							if ((*list)->grfid == src->grfid) {
       
   161 								ShowErrorMessage(INVALID_STRING_ID, STR_NEWGRF_DUPLICATE_GRFID, 0, 0);
       
   162 								return;
       
   163 							}
       
   164 						}
       
   165 
       
   166 						/* Copy GRF details from scanned list */
       
   167 						c = calloc(1, sizeof(*c));
       
   168 						*c = *src;
       
   169 						c->filename = strdup(src->filename);
       
   170 						if (src->name != NULL) c->name = strdup(src->name);
       
   171 						if (src->info != NULL) c->info = strdup(src->info);
       
   172 						c->next = NULL;
       
   173 
       
   174 						/* Append GRF config to configuration list */
       
   175 						*list = c;
       
   176 
       
   177 						DeleteWindowByClass(WC_SAVELOAD);
       
   178 						InvalidateWindowData(WC_GAME_OPTIONS, 0);
       
   179 					}
       
   180 					break;
       
   181 
       
   182 				case 7: /* Rescan list */
       
   183 					WP(w, newgrf_add_d).sel = NULL;
       
   184 					ScanNewGRFFiles();
       
   185 					SetWindowDirty(w);
       
   186 					break;
       
   187 			}
       
   188 			break;
       
   189 	}
       
   190 }
       
   191 
       
   192 
       
   193 static const Widget _newgrf_add_dlg_widgets[] = {
       
   194 {   WWT_CLOSEBOX,    RESIZE_NONE, 14,   0,  10,   0,  13, STR_00C5,                STR_018B_CLOSE_WINDOW },
       
   195 {    WWT_CAPTION,   RESIZE_RIGHT, 14,  11, 306,   0,  13, STR_NEWGRF_ADD_CAPTION,  STR_018C_WINDOW_TITLE_DRAG_THIS },
       
   196 
       
   197 /* List of files */
       
   198 {      WWT_PANEL,      RESIZE_RB, 14,   0, 294,  14, 221, 0x0,                     STR_NULL },
       
   199 {      WWT_INSET,      RESIZE_RB, 14,   2, 292,  16, 219, 0x0,                     STR_NULL },
       
   200 {  WWT_SCROLLBAR,     RESIZE_LRB, 14, 295, 306,  14, 221, 0x0,                     STR_NULL },
       
   201 
       
   202 /* NewGRF file info */
       
   203 {      WWT_PANEL,     RESIZE_RTB, 14,   0, 306, 222, 324, 0x0,                     STR_NULL },
       
   204 
       
   205 { WWT_PUSHTXTBTN,     RESIZE_RTB, 14,   0, 146, 325, 336, STR_NEWGRF_ADD_FILE,     STR_NEWGRF_ADD_FILE_TIP },
       
   206 { WWT_PUSHTXTBTN,    RESIZE_LRTB, 14, 147, 294, 325, 336, STR_NEWGRF_RESCAN_FILES, STR_NEWGRF_RESCAN_FILES_TIP },
       
   207 {  WWT_RESIZEBOX,    RESIZE_LRTB, 14, 295, 306, 325, 336, 0x0,                     STR_RESIZE_BUTTON },
       
   208 {   WIDGETS_END },
       
   209 };
       
   210 
       
   211 
       
   212 static const WindowDesc _newgrf_add_dlg_desc = {
       
   213 	WDP_CENTER, WDP_CENTER, 307, 337,
       
   214 	WC_SAVELOAD, 0,
       
   215 	WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
       
   216 	_newgrf_add_dlg_widgets,
       
   217 	NewGRFAddDlgWndProc,
       
   218 };
       
   219 
       
   220 
       
   221 /* 'NewGRF Settings' dialogue */
       
   222 typedef struct newgrf_d {
       
   223 	GRFConfig **orig_list; ///< grf list the window is shown with
       
   224 	GRFConfig **list;      ///< temporary grf list to which changes are made
       
   225 	GRFConfig *sel;        ///< selected grf item
       
   226 	bool editable;         ///< is the window editable
       
   227 	bool show_params;      ///< are the grf-parameters shown in the info-panel
       
   228 	bool execute;          ///< on pressing 'apply changes' are grf changes applied immediately, or only list is updated
       
   229 } newgrf_d;
       
   230 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(newgrf_d));
       
   231 
       
   232 
       
   233 enum ShowNewGRFStateWidgets {
       
   234 	SNGRFS_ADD = 3,
       
   235 	SNGRFS_REMOVE,
       
   236 	SNGRFS_MOVE_UP,
       
   237 	SNGRFS_MOVE_DOWN,
       
   238 	SNGRFS_FILE_LIST = 7,
       
   239 	SNGRFS_NEWGRF_INFO = 9,
       
   240 	SNGRFS_SET_PARAMETERS,
       
   241 	SNGRFS_APPLY_CHANGES,
       
   242 };
       
   243 
       
   244 
       
   245 static void SetupNewGRFState(Window *w)
       
   246 {
       
   247 	bool disable_all = WP(w, newgrf_d).sel == NULL || !WP(w, newgrf_d).editable;
       
   248 
       
   249 	SetWindowWidgetDisabledState(w, 3, !WP(w, newgrf_d).editable);
       
   250 	SetWindowWidgetsDisabledState(w, disable_all,
       
   251 		SNGRFS_REMOVE,
       
   252 		SNGRFS_MOVE_UP,
       
   253 		SNGRFS_MOVE_DOWN,
       
   254 		WIDGET_LIST_END
       
   255 	);
       
   256 	SetWindowWidgetDisabledState(w, SNGRFS_SET_PARAMETERS, !WP(w, newgrf_d).show_params || disable_all);
       
   257 
       
   258 	if (!disable_all) {
       
   259 		/* All widgets are now enabled, so disable widgets we can't use */
       
   260 		if (WP(w, newgrf_d).sel == *WP(w, newgrf_d).list) DisableWindowWidget(w, SNGRFS_MOVE_UP);
       
   261 		if (WP(w, newgrf_d).sel->next == NULL) DisableWindowWidget(w, SNGRFS_MOVE_DOWN);
       
   262 	}
       
   263 }
       
   264 
       
   265 
       
   266 static void SetupNewGRFWindow(Window *w)
       
   267 {
       
   268 	const GRFConfig *c;
       
   269 	int i;
       
   270 
       
   271 	for (c = *WP(w, newgrf_d).list, i = 0; c != NULL; c = c->next, i++);
       
   272 
       
   273 	w->vscroll.cap = (w->widget[SNGRFS_FILE_LIST].bottom - w->widget[SNGRFS_FILE_LIST].top) / 14 + 1;
       
   274 	SetVScrollCount(w, i);
       
   275 	SetWindowWidgetDisabledState(w, SNGRFS_APPLY_CHANGES, !WP(w, newgrf_d).editable);
       
   276 }
       
   277 
       
   278 
       
   279 /** Callback function for the newgrf 'apply changes' confirmation window
       
   280  * @param yes_clicked boolean value, true when yes was clicked, false otherwise */
       
   281 static void NewGRFConfirmationCallback(Window *w, bool confirmed)
       
   282 {
       
   283 	if (confirmed) {
       
   284 		newgrf_d *nd = &WP(w, newgrf_d);
       
   285 
       
   286 		CopyGRFConfigList(nd->orig_list, *nd->list);
       
   287 		ReloadNewGRFData();
       
   288 	}
       
   289 }
       
   290 
       
   291 
       
   292 static void NewGRFWndProc(Window *w, WindowEvent *e)
       
   293 {
       
   294 	switch (e->event) {
       
   295 		case WE_PAINT: {
       
   296 			const GRFConfig *c;
       
   297 			int i, y;
       
   298 
       
   299 			SetupNewGRFState(w);
       
   300 
       
   301 			DrawWindowWidgets(w);
       
   302 
       
   303 			/* Draw NewGRF list */
       
   304 			y = w->widget[SNGRFS_FILE_LIST].top;
       
   305 			for (c = *WP(w, newgrf_d).list, i = 0; c != NULL; c = c->next, i++) {
       
   306 				if (i >= w->vscroll.pos && i < w->vscroll.pos + w->vscroll.cap) {
       
   307 					const char *text = (c->name != NULL && strlen(c->name) != 0) ? c->name : c->filename;
       
   308 					PalSpriteID pal;
       
   309 
       
   310 					/* Pick a colour */
       
   311 					if (HASBIT(c->flags, GCF_NOT_FOUND) || HASBIT(c->flags, GCF_DISABLED)) {
       
   312 						pal = PALETTE_TO_RED;
       
   313 					} else if (HASBIT(c->flags, GCF_STATIC)) {
       
   314 						pal = PALETTE_TO_YELLOW;
       
   315 					} else if (HASBIT(c->flags, GCF_ACTIVATED)) {
       
   316 						pal = PALETTE_TO_GREEN;
       
   317 					} else {
       
   318 						pal = PALETTE_TO_BLUE;
       
   319 					}
       
   320 
       
   321 					DrawSprite(SPRITE_PALETTE(SPR_SQUARE | pal), 5, y + 2);
       
   322 					DoDrawString(text, 25, y + 3, WP(w, newgrf_d).sel == c ? 0xC : 0x10);
       
   323 					y += 14;
       
   324 				}
       
   325 			}
       
   326 
       
   327 			if (WP(w, newgrf_d).sel != NULL) {
       
   328 				/* Draw NewGRF file info */
       
   329 				const Widget *wi = &w->widget[SNGRFS_NEWGRF_INFO];
       
   330 				ShowNewGRFInfo(WP(w, newgrf_d).sel, wi->left + 2, wi->top + 2, wi->right - wi->left - 2, WP(w, newgrf_d).show_params);
       
   331 			}
       
   332 
       
   333 			break;
       
   334 		}
       
   335 
       
   336 		case WE_INVALIDATE_DATA:
       
   337 			SetupNewGRFWindow(w);
       
   338 			break;
       
   339 
       
   340 		case WE_CLICK:
       
   341 			switch (e->we.click.widget) {
       
   342 				case SNGRFS_ADD: { /* Add GRF */
       
   343 					GRFConfig **list = WP(w, newgrf_d).list;
       
   344 					Window *w;
       
   345 
       
   346 					DeleteWindowByClass(WC_SAVELOAD);
       
   347 					w = AllocateWindowDesc(&_newgrf_add_dlg_desc);
       
   348 					w->resize.step_height = 10;
       
   349 
       
   350 					WP(w, newgrf_add_d).list = list;
       
   351 					break;
       
   352 				}
       
   353 
       
   354 				case SNGRFS_REMOVE: { /* Remove GRF */
       
   355 					GRFConfig **pc, *c, *newsel;
       
   356 
       
   357 					/* Choose the next GRF file to be the selected file */
       
   358 					newsel = WP(w, newgrf_d).sel->next;
       
   359 
       
   360 					for (pc = WP(w, newgrf_d).list; (c = *pc) != NULL; pc = &c->next) {
       
   361 						/* If the new selection is empty (i.e. we're deleting the last item
       
   362 						 * in the list, pick the file just before the selected file */
       
   363 						if (newsel == NULL && c->next == WP(w, newgrf_d).sel) newsel = c;
       
   364 
       
   365 						if (c == WP(w, newgrf_d).sel) {
       
   366 							*pc = c->next;
       
   367 							free(c);
       
   368 							break;
       
   369 						}
       
   370 					}
       
   371 
       
   372 					WP(w, newgrf_d).sel = newsel;
       
   373 					SetupNewGRFWindow(w);
       
   374 					SetWindowDirty(w);
       
   375 					break;
       
   376 				}
       
   377 
       
   378 				case SNGRFS_MOVE_UP: { /* Move GRF up */
       
   379 					GRFConfig **pc, *c;
       
   380 					if (WP(w, newgrf_d).sel == NULL) break;
       
   381 
       
   382 					for (pc = WP(w, newgrf_d).list; (c = *pc) != NULL; pc = &c->next) {
       
   383 						if (c->next == WP(w, newgrf_d).sel) {
       
   384 							c->next = WP(w, newgrf_d).sel->next;
       
   385 							WP(w, newgrf_d).sel->next = c;
       
   386 							*pc = WP(w, newgrf_d).sel;
       
   387 							break;
       
   388 						}
       
   389 					}
       
   390 					SetWindowDirty(w);
       
   391 					break;
       
   392 				}
       
   393 
       
   394 				case SNGRFS_MOVE_DOWN: { /* Move GRF down */
       
   395 					GRFConfig **pc, *c;
       
   396 					if (WP(w, newgrf_d).sel == NULL) break;
       
   397 
       
   398 					for (pc = WP(w, newgrf_d).list; (c = *pc) != NULL; pc = &c->next) {
       
   399 						if (c == WP(w, newgrf_d).sel) {
       
   400 							*pc = c->next;
       
   401 							c->next = c->next->next;
       
   402 							(*pc)->next = c;
       
   403 							break;
       
   404 						}
       
   405 					}
       
   406 					SetWindowDirty(w);
       
   407 					break;
       
   408 				}
       
   409 
       
   410 				case SNGRFS_FILE_LIST: { /* Select a GRF */
       
   411 					GRFConfig *c;
       
   412 					uint i = (e->we.click.pt.y - w->widget[SNGRFS_FILE_LIST].top) / 14 + w->vscroll.pos;
       
   413 
       
   414 					for (c = *WP(w, newgrf_d).list; c != NULL && i > 0; c = c->next, i--);
       
   415 					WP(w, newgrf_d).sel = c;
       
   416 
       
   417 					SetWindowDirty(w);
       
   418 					break;
       
   419 				}
       
   420 
       
   421 				case SNGRFS_APPLY_CHANGES: /* Apply changes made to GRF list */
       
   422 					if (WP(w, newgrf_d).execute) {
       
   423 						ShowQuery(
       
   424 							STR_POPUP_CAUTION_CAPTION,
       
   425 							STR_NEWGRF_CONFIRMATION_TEXT,
       
   426 							w,
       
   427 							NewGRFConfirmationCallback
       
   428 						);
       
   429 					} else {
       
   430 						CopyGRFConfigList(WP(w, newgrf_d).orig_list, *WP(w, newgrf_d).list);
       
   431 					}
       
   432 					break;
       
   433 
       
   434 				case SNGRFS_SET_PARAMETERS: { /* Edit parameters */
       
   435 					char buff[512];
       
   436 					if (WP(w, newgrf_d).sel == NULL) break;
       
   437 
       
   438 					GRFBuildParamList(buff, WP(w, newgrf_d).sel, lastof(buff));
       
   439 					ShowQueryString(BindCString(buff), STR_NEWGRF_PARAMETER_QUERY, 63, 250, w, CS_ALPHANUMERAL);
       
   440 					break;
       
   441 				}
       
   442 			}
       
   443 			break;
       
   444 
       
   445 		case WE_ON_EDIT_TEXT:
       
   446 			if (e->we.edittext.str != NULL) {
       
   447 				/* Parse our new "int list" */
       
   448 				GRFConfig *c = WP(w, newgrf_d).sel;
       
   449 				c->num_params = parse_intlist(e->we.edittext.str, (int*)c->param, lengthof(c->param));
       
   450 
       
   451 				/* parse_intlist returns -1 on error */
       
   452 				if (c->num_params == (byte)-1) c->num_params = 0;
       
   453 			}
       
   454 			SetWindowDirty(w);
       
   455 			break;
       
   456 
       
   457 		case WE_DESTROY:
       
   458 			/* Remove the temporary copy of grf-list used in window */
       
   459 			ClearGRFConfigList(WP(w, newgrf_d).list);
       
   460 			break;
       
   461 
       
   462 		case WE_RESIZE:
       
   463 			w->vscroll.cap += e->we.sizing.diff.y / 14;
       
   464 			w->widget[SNGRFS_FILE_LIST].data = (w->vscroll.cap << 8) + 1;
       
   465 			break;
       
   466 	}
       
   467 }
       
   468 
       
   469 
       
   470 static const Widget _newgrf_widgets[] = {
       
   471 {   WWT_CLOSEBOX,  RESIZE_NONE, 10,   0,  10,   0,  13, STR_00C5,                    STR_018B_CLOSE_WINDOW },
       
   472 {    WWT_CAPTION, RESIZE_RIGHT, 10,  11, 299,   0,  13, STR_NEWGRF_SETTINGS_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS },
       
   473 
       
   474 /* NewGRF file Add, Remove, Move up, Move down */
       
   475 {      WWT_PANEL, RESIZE_RIGHT, 10,   0, 299,  14,  29, STR_NULL,                    STR_NULL },
       
   476 { WWT_PUSHTXTBTN,  RESIZE_NONE,  3,  10,  79,  16,  27, STR_NEWGRF_ADD,              STR_NEWGRF_ADD_TIP },
       
   477 { WWT_PUSHTXTBTN,  RESIZE_NONE,  3,  80, 149,  16,  27, STR_NEWGRF_REMOVE,           STR_NEWGRF_REMOVE_TIP },
       
   478 { WWT_PUSHTXTBTN,  RESIZE_NONE,  3, 150, 219,  16,  27, STR_NEWGRF_MOVEUP,           STR_NEWGRF_MOVEUP_TIP },
       
   479 { WWT_PUSHTXTBTN,  RESIZE_NONE,  3, 220, 289,  16,  27, STR_NEWGRF_MOVEDOWN,         STR_NEWGRF_MOVEDOWN_TIP },
       
   480 
       
   481 /* NewGRF file list */
       
   482 {     WWT_MATRIX,    RESIZE_RB, 10,   0, 287,  30,  99, 0x501,                       STR_NEWGRF_FILE_TIP },
       
   483 {  WWT_SCROLLBAR,   RESIZE_LRB, 10, 288, 299,  30,  99, 0x0,                         STR_0190_SCROLL_BAR_SCROLLS_LIST },
       
   484 
       
   485 /* NewGRF file info */
       
   486 {      WWT_PANEL,   RESIZE_RTB, 10,   0, 299, 100, 212, STR_NULL,                    STR_NULL },
       
   487 
       
   488 /* Edit parameter and apply changes button... */
       
   489 { WWT_PUSHTXTBTN,    RESIZE_TB, 10,   0, 143, 213, 224, STR_NEWGRF_SET_PARAMETERS,   STR_NULL },
       
   490 { WWT_PUSHTXTBTN,   RESIZE_RTB, 10, 144, 287, 213, 224, STR_NEWGRF_APPLY_CHANGES,    STR_NULL },
       
   491 
       
   492 {  WWT_RESIZEBOX,  RESIZE_LRTB, 10, 288, 299, 213, 224, 0x0,                         STR_RESIZE_BUTTON },
       
   493 
       
   494 { WIDGETS_END },
       
   495 };
       
   496 
       
   497 
       
   498 static const WindowDesc _newgrf_desc = {
       
   499 	WDP_CENTER, WDP_CENTER, 300, 225,
       
   500 	WC_GAME_OPTIONS, 0,
       
   501 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
       
   502 	_newgrf_widgets,
       
   503 	NewGRFWndProc,
       
   504 };
       
   505 
       
   506 
       
   507 /** Setup the NewGRF gui
       
   508  * @param editable allow the user to make changes to the grfconfig in the window
       
   509  * @param show_params show information about what parameters are set for the grf files
       
   510  * @param exec_changes if changes are made to the list (editable is true), apply these
       
   511  *        changes immediately or only update the list
       
   512  * @param config pointer to a linked-list of grfconfig's that will be shown */
       
   513 void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config)
       
   514 {
       
   515 	static GRFConfig *local = NULL;
       
   516 	Window *w;
       
   517 
       
   518 	DeleteWindowByClass(WC_GAME_OPTIONS);
       
   519 	w = AllocateWindowDesc(&_newgrf_desc);
       
   520 	if (w == NULL) return;
       
   521 
       
   522 	w->resize.step_height = 14;
       
   523 	CopyGRFConfigList(&local, *config);
       
   524 
       
   525 	/* Clear selections */
       
   526 	WP(w, newgrf_d).sel         = NULL;
       
   527 	WP(w, newgrf_d).list        = &local;
       
   528 	WP(w, newgrf_d).orig_list   = config;
       
   529 	WP(w, newgrf_d).editable    = editable;
       
   530 	WP(w, newgrf_d).execute     = exec_changes;
       
   531 	WP(w, newgrf_d).show_params = show_params;
       
   532 
       
   533 	SetupNewGRFWindow(w);
       
   534 }