00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "variables.h"
00008 #include "gui.h"
00009 #include "window_gui.h"
00010 #include "textbuf_gui.h"
00011 #include "newgrf.h"
00012 #include "newgrf_config.h"
00013 #include "strings_func.h"
00014 #include "window_func.h"
00015 #include "core/alloc_func.hpp"
00016 #include "string_func.h"
00017 #include "gfx_func.h"
00018
00019 #include "table/strings.h"
00020 #include "table/sprites.h"
00021
00028 static int parse_intlist(const char *p, int *items, int maxitems)
00029 {
00030 int n = 0, v;
00031 char *end;
00032
00033 for (;;) {
00034 v = strtol(p, &end, 0);
00035 if (p == end || n == maxitems) return -1;
00036 p = end;
00037 items[n++] = v;
00038 if (*p == '\0') break;
00039 if (*p != ',' && *p != ' ') return -1;
00040 p++;
00041 }
00042
00043 return n;
00044 }
00045
00046
00047 static void ShowNewGRFInfo(const GRFConfig *c, uint x, uint y, uint w, uint bottom, bool show_params)
00048 {
00049 char buff[256];
00050
00051 if (c->error != NULL) {
00052 SetDParamStr(0, c->filename);
00053 SetDParamStr(1, c->error->data);
00054 for (uint i = 0; i < c->error->num_params; i++) {
00055 uint32 param = 0;
00056 byte param_number = c->error->param_number[i];
00057
00058 if (param_number < c->num_params) param = c->param[param_number];
00059
00060 SetDParam(2 + i, param);
00061 }
00062
00063 char message[512];
00064 GetString(message, c->error->custom_message != NULL ? BindCString(c->error->custom_message) : c->error->message, lastof(message));
00065
00066 SetDParamStr(0, message);
00067 y += DrawStringMultiLine(x, y, c->error->severity, w, bottom - y);
00068 }
00069
00070
00071 if (c->filename != NULL) {
00072 SetDParamStr(0, c->filename);
00073 y += DrawStringMultiLine(x, y, STR_NEWGRF_FILENAME, w, bottom - y);
00074 }
00075
00076
00077 snprintf(buff, lengthof(buff), "%08X", BSWAP32(c->grfid));
00078 SetDParamStr(0, buff);
00079 y += DrawStringMultiLine(x, y, STR_NEWGRF_GRF_ID, w, bottom - y);
00080
00081
00082 md5sumToString(buff, lastof(buff), c->md5sum);
00083 SetDParamStr(0, buff);
00084 y += DrawStringMultiLine(x, y, STR_NEWGRF_MD5SUM, w, bottom - y);
00085
00086
00087 if (show_params) {
00088 if (c->num_params > 0) {
00089 GRFBuildParamList(buff, c, lastof(buff));
00090 SetDParamStr(0, buff);
00091 } else {
00092 SetDParam(0, STR_01A9_NONE);
00093 }
00094 y += DrawStringMultiLine(x, y, STR_NEWGRF_PARAMETER, w, bottom - y);
00095 }
00096
00097
00098 if (c->status == GCS_NOT_FOUND) y += DrawStringMultiLine(x, y, STR_NEWGRF_NOT_FOUND, w, bottom - y);
00099 if (c->status == GCS_DISABLED) y += DrawStringMultiLine(x, y, STR_NEWGRF_DISABLED, w, bottom - y);
00100 if (HasBit(c->flags, GCF_COMPATIBLE)) y += DrawStringMultiLine(x, y, STR_NEWGRF_COMPATIBLE_LOADED, w, bottom - y);
00101
00102
00103 if (c->info != NULL && !StrEmpty(c->info)) {
00104 SetDParamStr(0, c->info);
00105 y += DrawStringMultiLine(x, y, STR_02BD, w, bottom - y);
00106 } else {
00107 y += DrawStringMultiLine(x, y, STR_NEWGRF_NO_INFO, w, bottom - y);
00108 }
00109 }
00110
00111
00112
00113 struct newgrf_add_d {
00114 GRFConfig **list;
00115 const GRFConfig *sel;
00116 };
00117
00118
00119 enum AddNewGRFWindowWidgets {
00120 ANGRFW_CLOSEBOX = 0,
00121 ANGRFW_CAPTION,
00122 ANGRFW_BACKGROUND,
00123 ANGRFW_GRF_LIST,
00124 ANGRFW_SCROLLBAR,
00125 ANGRFW_GRF_INFO,
00126 ANGRFW_ADD,
00127 ANGRFW_RESCAN,
00128 ANGRFW_RESIZE,
00129 };
00130
00131 static void NewGRFAddDlgWndProc(Window *w, WindowEvent *e)
00132 {
00133 switch (e->event) {
00134 case WE_PAINT: {
00135 const GRFConfig *c;
00136 const Widget *wl = &w->widget[ANGRFW_GRF_LIST];
00137 int n = 0;
00138
00139
00140 for (c = _all_grfs; c != NULL; c = c->next) n++;
00141
00142 w->vscroll.cap = (wl->bottom - wl->top) / 10;
00143 SetVScrollCount(w, n);
00144
00145 w->SetWidgetDisabledState(ANGRFW_ADD, WP(w, newgrf_add_d).sel == NULL || WP(w, newgrf_add_d).sel->IsOpenTTDBaseGRF());
00146 DrawWindowWidgets(w);
00147
00148 GfxFillRect(wl->left + 1, wl->top + 1, wl->right, wl->bottom, 0xD7);
00149
00150 uint y = wl->top + 1;
00151 for (c = _all_grfs, n = 0; c != NULL && n < (w->vscroll.pos + w->vscroll.cap); c = c->next, n++) {
00152 if (n >= w->vscroll.pos) {
00153 bool h = c == WP(w, newgrf_add_d).sel;
00154 const char *text = (c->name != NULL && !StrEmpty(c->name)) ? c->name : c->filename;
00155
00156
00157 if (h) GfxFillRect(3, y, w->width - 15, y + 9, 156);
00158 DoDrawStringTruncated(text, 4, y, h ? TC_WHITE : TC_ORANGE, w->width - 18);
00159 y += 10;
00160 }
00161 }
00162
00163 if (WP(w, newgrf_add_d).sel != NULL) {
00164 const Widget *wi = &w->widget[ANGRFW_GRF_INFO];
00165 ShowNewGRFInfo(WP(w, newgrf_add_d).sel, wi->left + 2, wi->top + 2, wi->right - wi->left - 2, wi->bottom, false);
00166 }
00167 break;
00168 }
00169
00170 case WE_DOUBLE_CLICK:
00171 if (e->we.click.widget != ANGRFW_GRF_LIST) break;
00172 e->we.click.widget = ANGRFW_ADD;
00173
00174
00175 case WE_CLICK:
00176 switch (e->we.click.widget) {
00177 case ANGRFW_GRF_LIST: {
00178
00179 const GRFConfig *c;
00180 uint i = (e->we.click.pt.y - w->widget[ANGRFW_GRF_LIST].top) / 10 + w->vscroll.pos;
00181
00182 for (c = _all_grfs; c != NULL && i > 0; c = c->next, i--) {}
00183 WP(w, newgrf_add_d).sel = c;
00184 SetWindowDirty(w);
00185 break;
00186 }
00187
00188 case ANGRFW_ADD:
00189 if (WP(w, newgrf_add_d).sel != NULL) {
00190 const GRFConfig *src = WP(w, newgrf_add_d).sel;
00191 GRFConfig **list;
00192
00193
00194 for (list = WP(w, newgrf_add_d).list; *list != NULL; list = &(*list)->next) {
00195 if ((*list)->grfid == src->grfid) {
00196 ShowErrorMessage(INVALID_STRING_ID, STR_NEWGRF_DUPLICATE_GRFID, 0, 0);
00197 return;
00198 }
00199 }
00200
00201
00202 GRFConfig *c = CallocT<GRFConfig>(1);
00203 *c = *src;
00204 c->filename = strdup(src->filename);
00205 if (src->name != NULL) c->name = strdup(src->name);
00206 if (src->info != NULL) c->info = strdup(src->info);
00207 c->next = NULL;
00208
00209
00210 *list = c;
00211
00212 DeleteWindowByClass(WC_SAVELOAD);
00213 InvalidateWindowData(WC_GAME_OPTIONS, 0);
00214 }
00215 break;
00216
00217 case ANGRFW_RESCAN:
00218 WP(w, newgrf_add_d).sel = NULL;
00219 ScanNewGRFFiles();
00220 SetWindowDirty(w);
00221 break;
00222 }
00223 break;
00224 }
00225 }
00226
00227
00228 static const Widget _newgrf_add_dlg_widgets[] = {
00229 { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
00230 { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 306, 0, 13, STR_NEWGRF_ADD_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS },
00231 { WWT_PANEL, RESIZE_RB, 14, 0, 294, 14, 121, 0x0, STR_NULL },
00232 { WWT_INSET, RESIZE_RB, 14, 2, 292, 16, 119, 0x0, STR_NULL },
00233 { WWT_SCROLLBAR, RESIZE_LRB, 14, 295, 306, 14, 121, 0x0, STR_NULL },
00234 { WWT_PANEL, RESIZE_RTB, 14, 0, 306, 122, 224, 0x0, STR_NULL },
00235 { WWT_PUSHTXTBTN, RESIZE_RTB, 14, 0, 146, 225, 236, STR_NEWGRF_ADD_FILE, STR_NEWGRF_ADD_FILE_TIP },
00236 { WWT_PUSHTXTBTN, RESIZE_LRTB, 14, 147, 294, 225, 236, STR_NEWGRF_RESCAN_FILES, STR_NEWGRF_RESCAN_FILES_TIP },
00237 { WWT_RESIZEBOX, RESIZE_LRTB, 14, 295, 306, 225, 236, 0x0, STR_RESIZE_BUTTON },
00238 { WIDGETS_END },
00239 };
00240
00241
00242 static const WindowDesc _newgrf_add_dlg_desc = {
00243 WDP_CENTER, WDP_CENTER, 307, 237, 307, 337,
00244 WC_SAVELOAD, WC_NONE,
00245 WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
00246 _newgrf_add_dlg_widgets,
00247 NewGRFAddDlgWndProc,
00248 };
00249
00250
00251
00252 struct newgrf_d {
00253 GRFConfig **orig_list;
00254 GRFConfig **list;
00255 GRFConfig *sel;
00256 bool editable;
00257 bool show_params;
00258 bool execute;
00259 };
00260 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(newgrf_d));
00261
00262
00263
00264 enum ShowNewGRFStateWidgets {
00265 SNGRFS_CLOSEBOX = 0,
00266 SNGRFS_CAPTION,
00267 SNGRFS_BACKGROUND,
00268 SNGRFS_ADD,
00269 SNGRFS_REMOVE,
00270 SNGRFS_MOVE_UP,
00271 SNGRFS_MOVE_DOWN,
00272 SNGRFS_FILE_LIST,
00273 SNGRFS_SCROLLBAR,
00274 SNGRFS_NEWGRF_INFO,
00275 SNGRFS_SET_PARAMETERS,
00276 SNGRFS_APPLY_CHANGES,
00277 SNGRFS_RESIZE,
00278 };
00279
00280 static void SetupNewGRFState(Window *w)
00281 {
00282 bool disable_all = WP(w, newgrf_d).sel == NULL || !WP(w, newgrf_d).editable;
00283
00284 w->SetWidgetDisabledState(SNGRFS_ADD, !WP(w, newgrf_d).editable);
00285 w->SetWidgetsDisabledState(disable_all,
00286 SNGRFS_REMOVE,
00287 SNGRFS_MOVE_UP,
00288 SNGRFS_MOVE_DOWN,
00289 WIDGET_LIST_END
00290 );
00291 w->SetWidgetDisabledState(SNGRFS_SET_PARAMETERS, !WP(w, newgrf_d).show_params || disable_all);
00292
00293 if (!disable_all) {
00294
00295 if (WP(w, newgrf_d).sel == *WP(w, newgrf_d).list) w->DisableWidget(SNGRFS_MOVE_UP);
00296 if (WP(w, newgrf_d).sel->next == NULL) w->DisableWidget(SNGRFS_MOVE_DOWN);
00297 if (WP(w, newgrf_d).sel->IsOpenTTDBaseGRF()) w->DisableWidget(SNGRFS_REMOVE);
00298 }
00299 }
00300
00301
00302 static void SetupNewGRFWindow(Window *w)
00303 {
00304 const GRFConfig *c;
00305 int i;
00306
00307 for (c = *WP(w, newgrf_d).list, i = 0; c != NULL; c = c->next, i++) {}
00308
00309 w->vscroll.cap = (w->widget[SNGRFS_FILE_LIST].bottom - w->widget[SNGRFS_FILE_LIST].top) / 14 + 1;
00310 SetVScrollCount(w, i);
00311 w->SetWidgetDisabledState(SNGRFS_APPLY_CHANGES, !WP(w, newgrf_d).editable);
00312 }
00313
00314
00319 static void NewGRFConfirmationCallback(Window *w, bool confirmed)
00320 {
00321 if (confirmed) {
00322 newgrf_d *nd = &WP(w, newgrf_d);
00323 GRFConfig *c;
00324 int i = 0;
00325
00326 CopyGRFConfigList(nd->orig_list, *nd->list, false);
00327 ReloadNewGRFData();
00328
00329
00330 for (c = *nd->list; c != NULL && c != nd->sel; c = c->next, i++) {}
00331 CopyGRFConfigList(nd->list, *nd->orig_list, false);
00332 for (c = *nd->list; c != NULL && i > 0; c = c->next, i--) {}
00333 nd->sel = c;
00334
00335 SetWindowDirty(w);
00336 }
00337 }
00338
00339
00340 static void NewGRFWndProc(Window *w, WindowEvent *e)
00341 {
00342 switch (e->event) {
00343 case WE_PAINT: {
00344 const GRFConfig *c;
00345 int i, y;
00346
00347 SetupNewGRFState(w);
00348
00349 DrawWindowWidgets(w);
00350
00351
00352 y = w->widget[SNGRFS_FILE_LIST].top;
00353 for (c = *WP(w, newgrf_d).list, i = 0; c != NULL; c = c->next, i++) {
00354 if (i >= w->vscroll.pos && i < w->vscroll.pos + w->vscroll.cap) {
00355 const char *text = (c->name != NULL && !StrEmpty(c->name)) ? c->name : c->filename;
00356 SpriteID pal;
00357 byte txtoffset;
00358
00359
00360 switch (c->status) {
00361 case GCS_NOT_FOUND:
00362 case GCS_DISABLED:
00363 pal = PALETTE_TO_RED;
00364 break;
00365 case GCS_ACTIVATED:
00366 pal = PALETTE_TO_GREEN;
00367 break;
00368 default:
00369 pal = PALETTE_TO_BLUE;
00370 break;
00371 }
00372
00373
00374 if (pal != PALETTE_TO_RED) {
00375 if (HasBit(c->flags, GCF_STATIC)) {
00376 pal = PALETTE_TO_GREY;
00377 } else if (HasBit(c->flags, GCF_COMPATIBLE)) {
00378 pal = PALETTE_TO_ORANGE;
00379 }
00380 }
00381
00382 DrawSprite(SPR_SQUARE, pal, 5, y + 2);
00383 if (c->error != NULL) DrawSprite(SPR_WARNING_SIGN, 0, 20, y + 2);
00384 txtoffset = c->error != NULL ? 35 : 25;
00385 DoDrawStringTruncated(text, txtoffset, y + 3, WP(w, newgrf_d).sel == c ? TC_WHITE : TC_BLACK, w->width - txtoffset - 10);
00386 y += 14;
00387 }
00388 }
00389
00390 if (WP(w, newgrf_d).sel != NULL) {
00391
00392 const Widget *wi = &w->widget[SNGRFS_NEWGRF_INFO];
00393 ShowNewGRFInfo(WP(w, newgrf_d).sel, wi->left + 2, wi->top + 2, wi->right - wi->left - 2, wi->bottom, WP(w, newgrf_d).show_params);
00394 }
00395
00396 break;
00397 }
00398
00399 case WE_INVALIDATE_DATA:
00400 SetupNewGRFWindow(w);
00401 break;
00402
00403 case WE_CLICK:
00404 switch (e->we.click.widget) {
00405 case SNGRFS_ADD: {
00406 GRFConfig **list = WP(w, newgrf_d).list;
00407 Window *w;
00408
00409 DeleteWindowByClass(WC_SAVELOAD);
00410 w = AllocateWindowDesc(&_newgrf_add_dlg_desc);
00411 w->resize.step_height = 10;
00412
00413 WP(w, newgrf_add_d).list = list;
00414 break;
00415 }
00416
00417 case SNGRFS_REMOVE: {
00418 GRFConfig **pc, *c, *newsel;
00419
00420
00421 newsel = WP(w, newgrf_d).sel->next;
00422
00423 for (pc = WP(w, newgrf_d).list; (c = *pc) != NULL; pc = &c->next) {
00424
00425
00426 if (newsel == NULL && c->next == WP(w, newgrf_d).sel) newsel = c;
00427
00428 if (c == WP(w, newgrf_d).sel) {
00429 *pc = c->next;
00430 free(c);
00431 break;
00432 }
00433 }
00434
00435 WP(w, newgrf_d).sel = newsel;
00436 SetupNewGRFWindow(w);
00437 SetWindowDirty(w);
00438 break;
00439 }
00440
00441 case SNGRFS_MOVE_UP: {
00442 GRFConfig **pc, *c;
00443 if (WP(w, newgrf_d).sel == NULL) break;
00444
00445 for (pc = WP(w, newgrf_d).list; (c = *pc) != NULL; pc = &c->next) {
00446 if (c->next == WP(w, newgrf_d).sel) {
00447 c->next = WP(w, newgrf_d).sel->next;
00448 WP(w, newgrf_d).sel->next = c;
00449 *pc = WP(w, newgrf_d).sel;
00450 break;
00451 }
00452 }
00453 SetWindowDirty(w);
00454 break;
00455 }
00456
00457 case SNGRFS_MOVE_DOWN: {
00458 GRFConfig **pc, *c;
00459 if (WP(w, newgrf_d).sel == NULL) break;
00460
00461 for (pc = WP(w, newgrf_d).list; (c = *pc) != NULL; pc = &c->next) {
00462 if (c == WP(w, newgrf_d).sel) {
00463 *pc = c->next;
00464 c->next = c->next->next;
00465 (*pc)->next = c;
00466 break;
00467 }
00468 }
00469 SetWindowDirty(w);
00470 break;
00471 }
00472
00473 case SNGRFS_FILE_LIST: {
00474 GRFConfig *c;
00475 uint i = (e->we.click.pt.y - w->widget[SNGRFS_FILE_LIST].top) / 14 + w->vscroll.pos;
00476
00477 for (c = *WP(w, newgrf_d).list; c != NULL && i > 0; c = c->next, i--) {}
00478 WP(w, newgrf_d).sel = c;
00479
00480 SetWindowDirty(w);
00481 break;
00482 }
00483
00484 case SNGRFS_APPLY_CHANGES:
00485 if (WP(w, newgrf_d).execute) {
00486 ShowQuery(
00487 STR_POPUP_CAUTION_CAPTION,
00488 STR_NEWGRF_CONFIRMATION_TEXT,
00489 w,
00490 NewGRFConfirmationCallback
00491 );
00492 } else {
00493 CopyGRFConfigList(WP(w, newgrf_d).orig_list, *WP(w, newgrf_d).list, true);
00494 ResetGRFConfig(false);
00495 ReloadNewGRFData();
00496 }
00497 break;
00498
00499 case SNGRFS_SET_PARAMETERS: {
00500 char buff[512];
00501 if (WP(w, newgrf_d).sel == NULL) break;
00502
00503 GRFBuildParamList(buff, WP(w, newgrf_d).sel, lastof(buff));
00504 ShowQueryString(BindCString(buff), STR_NEWGRF_PARAMETER_QUERY, 63, 250, w, CS_ALPHANUMERAL);
00505 break;
00506 }
00507 }
00508 break;
00509
00510 case WE_ON_EDIT_TEXT:
00511 if (e->we.edittext.str != NULL) {
00512
00513 GRFConfig *c = WP(w, newgrf_d).sel;
00514 c->num_params = parse_intlist(e->we.edittext.str, (int*)c->param, lengthof(c->param));
00515
00516
00517 if (c->num_params == (byte)-1) c->num_params = 0;
00518 }
00519 SetWindowDirty(w);
00520 break;
00521
00522 case WE_DESTROY:
00523 if (!WP(w, newgrf_d).execute) {
00524 CopyGRFConfigList(WP(w, newgrf_d).orig_list, *WP(w, newgrf_d).list, true);
00525 ResetGRFConfig(false);
00526 ReloadNewGRFData();
00527 }
00528
00529 ClearGRFConfigList(WP(w, newgrf_d).list);
00530 break;
00531
00532 case WE_RESIZE:
00533 if (e->we.sizing.diff.x != 0) {
00534 ResizeButtons(w, SNGRFS_ADD, SNGRFS_MOVE_DOWN);
00535 ResizeButtons(w, SNGRFS_SET_PARAMETERS, SNGRFS_APPLY_CHANGES);
00536 }
00537 w->vscroll.cap += e->we.sizing.diff.y / 14;
00538 w->widget[SNGRFS_FILE_LIST].data = (w->vscroll.cap << 8) + 1;
00539 SetupNewGRFWindow(w);
00540 break;
00541 }
00542 }
00543
00544
00545 static const Widget _newgrf_widgets[] = {
00546 { WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
00547 { WWT_CAPTION, RESIZE_RIGHT, 10, 11, 299, 0, 13, STR_NEWGRF_SETTINGS_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS },
00548 { WWT_PANEL, RESIZE_RIGHT, 10, 0, 299, 14, 29, STR_NULL, STR_NULL },
00549 { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 10, 79, 16, 27, STR_NEWGRF_ADD, STR_NEWGRF_ADD_TIP },
00550 { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 80, 149, 16, 27, STR_NEWGRF_REMOVE, STR_NEWGRF_REMOVE_TIP },
00551 { WWT_PUSHTXTBTN, RESIZE_NONE, 3, 150, 219, 16, 27, STR_NEWGRF_MOVEUP, STR_NEWGRF_MOVEUP_TIP },
00552 { WWT_PUSHTXTBTN, RESIZE_RIGHT, 3, 220, 289, 16, 27, STR_NEWGRF_MOVEDOWN, STR_NEWGRF_MOVEDOWN_TIP },
00553 { WWT_MATRIX, RESIZE_RB, 10, 0, 287, 30, 99, 0x501, STR_NEWGRF_FILE_TIP },
00554 { WWT_SCROLLBAR, RESIZE_LRB, 10, 288, 299, 30, 99, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST },
00555 { WWT_PANEL, RESIZE_RTB, 10, 0, 299, 100, 212, STR_NULL, STR_NULL },
00556 { WWT_PUSHTXTBTN, RESIZE_TB, 10, 0, 143, 213, 224, STR_NEWGRF_SET_PARAMETERS, STR_NULL },
00557 { WWT_PUSHTXTBTN, RESIZE_RTB, 10, 144, 287, 213, 224, STR_NEWGRF_APPLY_CHANGES, STR_NULL },
00558 { WWT_RESIZEBOX, RESIZE_LRTB, 10, 288, 299, 213, 224, 0x0, STR_RESIZE_BUTTON },
00559 { WIDGETS_END },
00560 };
00561
00562
00563 static const WindowDesc _newgrf_desc = {
00564 WDP_CENTER, WDP_CENTER, 300, 225, 300, 225,
00565 WC_GAME_OPTIONS, WC_NONE,
00566 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
00567 _newgrf_widgets,
00568 NewGRFWndProc,
00569 };
00570
00571
00578 void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFConfig **config)
00579 {
00580 static GRFConfig *local = NULL;
00581 Window *w;
00582
00583 DeleteWindowByClass(WC_GAME_OPTIONS);
00584 w = AllocateWindowDesc(&_newgrf_desc);
00585 if (w == NULL) return;
00586
00587 w->resize.step_height = 14;
00588 CopyGRFConfigList(&local, *config, false);
00589
00590
00591 WP(w, newgrf_d).sel = NULL;
00592 WP(w, newgrf_d).list = &local;
00593 WP(w, newgrf_d).orig_list = config;
00594 WP(w, newgrf_d).editable = editable;
00595 WP(w, newgrf_d).execute = exec_changes;
00596 WP(w, newgrf_d).show_params = show_params;
00597
00598 SetupNewGRFWindow(w);
00599 }