tron@2186: /* $Id$ */ tron@2186: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" tron@1299: #include "debug.h" tron@2163: #include "functions.h" tron@2340: #include "gfxinit.h" tron@2162: #include "saveload.h" tron@1309: #include "strings.h" tron@1363: #include "table/sprites.h" tron@507: #include "table/strings.h" Darkvater@1784: #include "table/tree_land.h" tron@679: #include "map.h" truelight@0: #include "window.h" truelight@0: #include "gui.h" truelight@0: #include "viewport.h" truelight@0: #include "gfx.h" truelight@0: #include "station.h" truelight@0: #include "command.h" truelight@0: #include "player.h" truelight@0: #include "town.h" tron@337: #include "sound.h" truelight@543: #include "network.h" Darkvater@1390: #include "string.h" tron@2159: #include "variables.h" darkvater@1341: truelight@543: #include "hal.h" // for file list truelight@0: darkvater@1596: static bool _fios_path_changed; tron@1594: static bool _savegame_sort_dirty; tron@1594: truelight@0: truelight@0: typedef struct LandInfoData { truelight@0: Town *town; truelight@0: int32 costclear; truelight@0: AcceptedCargo ac; tron@1977: TileIndex tile; truelight@0: TileDesc td; truelight@0: } LandInfoData; truelight@0: truelight@0: static void LandInfoWndProc(Window *w, WindowEvent *e) truelight@0: { truelight@0: if (e->event == WE_PAINT) { tron@2630: const LandInfoData* lid; tron@2630: StringID str; tron@473: int i; tron@473: truelight@0: DrawWindowWidgets(w); truelight@0: truelight@0: lid = WP(w,void_d).data; truelight@0: tron@534: SetDParam(0, lid->td.dparam[0]); truelight@0: DrawStringCentered(140, 16, lid->td.str, 13); truelight@0: tron@534: SetDParam(0, STR_01A6_N_A); truelight@0: if (lid->td.owner != OWNER_NONE && lid->td.owner != OWNER_WATER) truelight@0: GetNameOfOwner(lid->td.owner, lid->tile); truelight@0: DrawStringCentered(140, 27, STR_01A7_OWNER, 0); truelight@0: truelight@0: str = STR_01A4_COST_TO_CLEAR_N_A; peter1138@2737: if (!CmdFailed(lid->costclear)) { tron@534: SetDParam(0, lid->costclear); truelight@0: str = STR_01A5_COST_TO_CLEAR; truelight@0: } truelight@0: DrawStringCentered(140, 38, str, 0); truelight@0: Darkvater@2426: snprintf(_userstring, lengthof(_userstring), "0x%.4X", lid->tile); tron@926: SetDParam(0, TileX(lid->tile)); tron@926: SetDParam(1, TileY(lid->tile)); tron@534: SetDParam(2, STR_SPEC_USERSTRING); truelight@0: DrawStringCentered(140, 49, STR_LANDINFO_COORDS, 0); truelight@0: tron@534: SetDParam(0, STR_01A9_NONE); truelight@0: if (lid->town != NULL) { ludde@2070: SetDParam(0, STR_TOWN); ludde@2070: SetDParam(1, lid->town->index); truelight@0: } truelight@0: DrawStringCentered(140,60, STR_01A8_LOCAL_AUTHORITY, 0); truelight@0: ludde@2063: { ludde@2063: char buf[512]; ludde@2063: char *p = GetString(buf, STR_01CE_CARGO_ACCEPTED); ludde@2063: bool found = false; truelight@0: ludde@2063: for (i = 0; i < NUM_CARGO; ++i) { ludde@2063: if (lid->ac[i] > 0) { ludde@2063: // Add a comma between each item. tron@2639: if (found) { tron@2639: *p++ = ','; tron@2639: *p++ = ' '; tron@2639: } ludde@2063: found = true; ludde@2063: ludde@2063: // If the accepted value is less than 8, show it in 1/8:ths ludde@2063: if (lid->ac[i] < 8) { orudge@2167: int32 argv[2]; orudge@2167: argv[0] = lid->ac[i]; orudge@2167: argv[1] = _cargoc.names_s[i]; ludde@2063: p = GetStringWithArgs(p, STR_01D1_8, argv); ludde@2063: } else { ludde@2063: p = GetString(p, _cargoc.names_s[i]); ludde@2063: } tron@473: } truelight@0: } truelight@0: tron@2639: if (found) DrawStringMultiCenter(140, 76, BindCString(buf), 276); ludde@2063: } truelight@193: truelight@71: if (lid->td.build_date != 0) { tron@534: SetDParam(0,lid->td.build_date); truelight@71: DrawStringCentered(140,71, STR_BUILD_DATE, 0); truelight@71: } truelight@0: } truelight@0: } truelight@0: truelight@0: static const Widget _land_info_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_NONE, 14, 11, 279, 0, 13, STR_01A3_LAND_AREA_INFORMATION, STR_018C_WINDOW_TITLE_DRAG_THIS}, truelight@867: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 279, 14, 92, 0x0, STR_NULL}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _land_info_desc = { truelight@0: -1, -1, 280, 93, truelight@0: WC_LAND_INFO,0, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, truelight@0: _land_info_widgets, truelight@0: LandInfoWndProc truelight@0: }; truelight@0: tron@1977: static void Place_LandInfo(TileIndex tile) truelight@0: { truelight@0: Player *p; truelight@0: static LandInfoData lid; truelight@0: Window *w; truelight@0: int64 old_money; truelight@0: truelight@0: DeleteWindowById(WC_LAND_INFO, 0); truelight@0: truelight@0: w = AllocateWindowDesc(&_land_info_desc); truelight@0: WP(w,void_d).data = &lid; truelight@193: truelight@0: lid.tile = tile; truelight@0: lid.town = ClosestTownFromTile(tile, _patches.dist_local_authority); truelight@0: tron@2631: p = GetPlayer(_local_player < MAX_PLAYERS ? _local_player : 0); darkvater@3: darkvater@3: old_money = p->money64; darkvater@3: p->money64 = p->player_money = 0x7fffffff; darkvater@3: lid.costclear = DoCommandByTile(tile, 0, 0, 0, CMD_LANDSCAPE_CLEAR); darkvater@3: p->money64 = old_money; darkvater@3: UpdatePlayerMoney32(p); truelight@193: truelight@71: // Becuase build_date is not set yet in every TileDesc, we make sure it is empty truelight@71: lid.td.build_date = 0; truelight@193: tron@473: GetAcceptedCargo(tile, lid.ac); truelight@0: GetTileDesc(tile, &lid.td); truelight@193: Darkvater@2898: #if defined(_DEBUG) Darkvater@2898: # define LANDINFOD_LEVEL 0 Darkvater@2898: #else Darkvater@2898: # define LANDINFOD_LEVEL 1 Darkvater@2898: #endif Darkvater@2898: DEBUG(misc, LANDINFOD_LEVEL) ("TILE: %#x (%i,%i)", tile, TileX(tile), TileY(tile)); Darkvater@2898: DEBUG(misc, LANDINFOD_LEVEL) ("type_height = %#x", _m[tile].type_height); Darkvater@2898: DEBUG(misc, LANDINFOD_LEVEL) ("m1 = %#x", _m[tile].m1); Darkvater@2898: DEBUG(misc, LANDINFOD_LEVEL) ("m2 = %#x", _m[tile].m2); Darkvater@2898: DEBUG(misc, LANDINFOD_LEVEL) ("m3 = %#x", _m[tile].m3); Darkvater@2898: DEBUG(misc, LANDINFOD_LEVEL) ("m4 = %#x", _m[tile].m4); Darkvater@2898: DEBUG(misc, LANDINFOD_LEVEL) ("m5 = %#x", _m[tile].m5); Darkvater@2898: DEBUG(misc, LANDINFOD_LEVEL) ("extra = %#x", _m[tile].extra); Darkvater@2898: #undef LANDINFOD_LEVEL truelight@0: } truelight@0: tron@1093: void PlaceLandBlockInfo(void) truelight@0: { Darkvater@1914: if (_cursor.sprite == SPR_CURSOR_QUERY) { truelight@0: ResetObjectToPlace(); truelight@0: } else { truelight@0: _place_proc = Place_LandInfo; Darkvater@1914: SetObjectToPlace(SPR_CURSOR_QUERY, 1, 1, 0); truelight@0: } truelight@0: } truelight@0: darkvater@859: static const char *credits[] = { darkvater@859: /************************************************************************* darkvater@859: * maximum length of string which fits in window -^*/ darkvater@859: "Original design by Chris Sawyer", darkvater@859: "Original graphics by Simon Foster", darkvater@859: "", darkvater@1124: "The OpenTTD team (in alphabetical order):", bjarni@2310: " Bjarni Corfitzen (Bjarni) - MacOSX port, coder", Darkvater@1826: " Matthijs Kooijman (blathijs) - Pathfinder-god", darkvater@1125: " Victor Fischer (Celestar) - Programming everywhere you need him to", Darkvater@2134: " Tamás Faragó (Darkvater) - Lead coder", darkvater@1124: " Kerekes Miham (MiHaMiX) - Translator system, and Nightlies host", darkvater@859: " Owen Rudge (orudge) - Forum- and masterserver host, OS/2 port", Darkvater@2748: " Peter Nelson (peter1138) - Spiritual descendant from newgrf gods", darkvater@1126: " Christoph Mallon (Tron) - Programmer, code correctness police", darkvater@1124: " Patric Stout (TrueLight) - Coder, network guru, SVN- and website host", darkvater@1125: "", darkvater@1125: "Retired Developers:", darkvater@1125: " Ludvig Strigeus (ludde) - OpenTTD author, main coder (0.1 - 0.3.3)", darkvater@859: " Serge Paquet (vurlix) - Assistant project manager, coder (0.1 - 0.3.3)", Darkvater@1826: " Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3.0 - 0.3.6)", darkvater@859: "", darkvater@859: "Special thanks go out to:", darkvater@859: " Josef Drexler - For his great work on TTDPatch", darkvater@859: " Marcin Grzegorczyk - For his documentation of TTD internals", pasky@1577: " Petr Baudis (pasky) - Many patches, newgrf support", darkvater@859: " Stefan Meißner (sign_de) - For his work on the console", Darkvater@1826: " Simon Sasburg (HackyKid) - Many bugfixes he has blessed us with (and PBS)", darkvater@1124: " Cian Duffy (MYOB) - BeOS port / manual writing", darkvater@1124: " Christian Rosentreter (tokaiz) - MorphOS / AmigaOS port", darkvater@859: "", darkvater@859: " Michael Blunck - Pre-Signals and Semaphores © 2003", darkvater@859: " George - Canal/Lock graphics © 2003-2004", darkvater@859: " Marcin Grzegorczyk - Foundations for Tracks on Slopes", darkvater@859: " All Translators - Who made OpenTTD a truly international game", darkvater@859: " Bug Reporters - Without whom OpenTTD would still be full of bugs!", darkvater@859: "", darkvater@859: "", darkvater@1124: "And last but not least:", darkvater@859: " Chris Sawyer - For an amazing game!" darkvater@859: }; truelight@0: truelight@0: static void AboutWindowProc(Window *w, WindowEvent *e) truelight@0: { tron@2639: switch (e->event) { darkvater@859: case WE_CREATE: /* Set up window counter and start position of scroller */ darkvater@998: WP(w, scroller_d).counter = 0; darkvater@998: WP(w, scroller_d).height = w->height - 40; darkvater@859: break; truelight@0: case WE_PAINT: { tron@959: uint i; darkvater@998: int y = WP(w, scroller_d).height; truelight@0: DrawWindowWidgets(w); truelight@0: darkvater@859: // Show original copyright and revision version darkvater@1125: DrawStringCentered(210, 17, STR_00B6_ORIGINAL_COPYRIGHT, 0); darkvater@1125: DrawStringCentered(210, 17 + 10, STR_00B7_VERSION, 0); darkvater@859: darkvater@859: // Show all scrolling credits darkvater@859: for (i = 0; i < lengthof(credits); i++) { darkvater@859: if (y >= 50 && y < (w->height - 40)) { Darkvater@1392: DoDrawString(credits[i], 10, y, 0x10); darkvater@859: } darkvater@859: y += 10; darkvater@859: } darkvater@859: darkvater@859: // If the last text has scrolled start anew from the start darkvater@998: if (y < 50) WP(w, scroller_d).height = w->height - 40; darkvater@859: Darkvater@2134: DoDrawStringCentered(210, w->height - 25, "Website: http://www.openttd.org", 16); Darkvater@2134: DrawStringCentered(210, w->height - 15, STR_00BA_COPYRIGHT_OPENTTD, 0); darkvater@859: } break; darkvater@859: case WE_MOUSELOOP: /* Timer to scroll the text and adjust the new top */ darkvater@998: if (WP(w, scroller_d).counter++ % 3 == 0) { darkvater@998: WP(w, scroller_d).height--; darkvater@859: SetWindowDirty(w); darkvater@859: } truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: static const Widget _about_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, darkvater@1125: { WWT_CAPTION, RESIZE_NONE, 14, 11, 419, 0, 13, STR_015B_OPENTTD, STR_NULL}, darkvater@1125: { WWT_PANEL, RESIZE_NONE, 14, 0, 419, 14, 271, 0x0, STR_NULL}, darkvater@1125: { WWT_FRAME, RESIZE_NONE, 14, 5, 414, 40, 245, STR_NULL, STR_NULL}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _about_desc = { darkvater@1125: WDP_CENTER, WDP_CENTER, 420, 272, truelight@0: WC_GAME_OPTIONS,0, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, truelight@0: _about_widgets, truelight@0: AboutWindowProc truelight@0: }; truelight@0: truelight@0: tron@1093: void ShowAboutWindow(void) truelight@0: { truelight@0: DeleteWindowById(WC_GAME_OPTIONS, 0); truelight@0: AllocateWindowDesc(&_about_desc); truelight@0: } truelight@0: truelight@0: static int _tree_to_plant; truelight@0: truelight@0: static const uint32 _tree_sprites[] = { truelight@0: 0x655,0x663,0x678,0x62B,0x647,0x639,0x64E,0x632,0x67F,0x68D,0x69B,0x6A9, truelight@0: 0x6AF,0x6D2,0x6D9,0x6C4,0x6CB,0x6B6,0x6BD,0x6E0, truelight@0: 0x72E,0x734,0x74A,0x74F,0x76B,0x78F,0x788,0x77B,0x75F,0x774,0x720,0x797, celestar@2187: 0x79E,0x7A5 | PALETTE_TO_GREEN,0x7AC | PALETTE_TO_RED,0x7B3,0x7BA,0x7C1 | PALETTE_TO_RED,0x7C8 | PALETTE_TO_PALE_GREEN,0x7CF | PALETTE_TO_YELLOW,0x7D6 | PALETTE_TO_RED truelight@0: }; truelight@0: truelight@0: static void BuildTreesWndProc(Window *w, WindowEvent *e) truelight@0: { tron@2639: switch (e->event) { truelight@0: case WE_PAINT: { truelight@0: int x,y; truelight@0: int i, count; truelight@0: truelight@0: DrawWindowWidgets(w); truelight@0: truelight@0: WP(w,tree_d).base = i = _tree_base_by_landscape[_opt.landscape]; truelight@0: WP(w,tree_d).count = count = _tree_count_by_landscape[_opt.landscape]; truelight@0: truelight@0: x = 18; truelight@0: y = 54; truelight@0: do { truelight@0: DrawSprite(_tree_sprites[i], x, y); truelight@0: x += 35; truelight@0: if (!(++i & 3)) { tron@2639: x -= 35 * 4; truelight@0: y += 47; truelight@0: } truelight@0: } while (--count); truelight@0: } break; truelight@0: truelight@0: case WE_CLICK: { tron@2639: int wid = e->click.widget; truelight@0: tron@2639: switch (wid) { truelight@0: case 0: truelight@0: ResetObjectToPlace(); tron@2639: break; tron@2639: truelight@0: case 3: case 4: case 5: case 6: truelight@0: case 7: case 8: case 9: case 10: truelight@0: case 11:case 12: case 13: case 14: tron@2639: if (wid - 3 >= WP(w,tree_d).count) break; truelight@193: Darkvater@1914: if (HandlePlacePushButton(w, wid, SPR_CURSOR_TREE, 1, NULL)) truelight@0: _tree_to_plant = WP(w,tree_d).base + wid - 3; truelight@0: break; truelight@0: truelight@0: case 15: // tree of random type. Darkvater@1914: if (HandlePlacePushButton(w, 15, SPR_CURSOR_TREE, 1, NULL)) truelight@0: _tree_to_plant = -1; truelight@0: break; truelight@0: truelight@0: case 16: /* place trees randomly over the landscape*/ truelight@0: w->click_state |= 1 << 16; truelight@0: w->flags4 |= 5 << WF_TIMEOUT_SHL; tron@541: SndPlayFx(SND_15_BEEP); truelight@0: PlaceTreesRandomly(); truelight@0: MarkWholeScreenDirty(); truelight@0: break; truelight@0: } truelight@0: } break; truelight@193: truelight@0: case WE_PLACE_OBJ: truelight@0: VpStartPlaceSizing(e->place.tile, VPM_X_AND_Y_LIMITED); truelight@0: VpSetPlaceSizingLimit(20); truelight@0: break; truelight@0: truelight@0: case WE_PLACE_DRAG: truelight@0: VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata); truelight@0: return; truelight@0: truelight@0: case WE_PLACE_MOUSEUP: truelight@0: if (e->click.pt.x != -1) { truelight@193: DoCommandP(e->place.tile, _tree_to_plant, e->place.starttile, NULL, truelight@0: CMD_PLANT_TREE | CMD_AUTO | CMD_MSG(STR_2805_CAN_T_PLANT_TREE_HERE)); truelight@0: } truelight@0: break; truelight@0: truelight@0: case WE_TIMEOUT: truelight@0: UnclickSomeWindowButtons(w, 1<<16); truelight@0: break; truelight@0: truelight@0: case WE_ABORT_PLACE_OBJ: truelight@0: w->click_state = 0; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: static const Widget _build_trees_widgets[] = { truelight@867: { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_NONE, 7, 11, 142, 0, 13, STR_2802_TREES, STR_018C_WINDOW_TITLE_DRAG_THIS}, truelight@867: { WWT_PANEL, RESIZE_NONE, 7, 0, 142, 14, 170, 0x0, STR_NULL}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 2, 35, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 37, 70, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 72, 105, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 107, 140, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 2, 35, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 37, 70, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 72, 105, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 107, 140, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 2, 35, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 37, 70, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 72, 105, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 107, 140, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, peter1138@2725: { WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _build_trees_desc = { truelight@0: 497, 22, 143, 171, dominik@606: WC_BUILD_TREES, WC_SCEN_LAND_GEN, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, truelight@0: _build_trees_widgets, truelight@0: BuildTreesWndProc truelight@0: }; truelight@0: truelight@0: static const Widget _build_trees_scen_widgets[] = { truelight@867: { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_NONE, 7, 11, 142, 0, 13, STR_2802_TREES, STR_018C_WINDOW_TITLE_DRAG_THIS}, truelight@867: { WWT_PANEL, RESIZE_NONE, 7, 0, 142, 14, 183, 0x0, STR_NULL}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 2, 35, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 37, 70, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 72, 105, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 107, 140, 16, 61, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 2, 35, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 37, 70, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 72, 105, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 107, 140, 63, 108, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 2, 35, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 37, 70, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 72, 105, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 107, 140, 110, 155, 0x0, STR_280D_SELECT_TREE_TYPE_TO_PLANT}, peter1138@2725: { WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP}, peter1138@2725: { WWT_TEXTBTN, RESIZE_NONE, 14, 2, 140, 170, 181, STR_028A_RANDOM_TREES, STR_028B_PLANT_TREES_RANDOMLY_OVER}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _build_trees_scen_desc = { truelight@0: -1, -1, 143, 184, dominik@606: WC_BUILD_TREES,0, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, truelight@0: _build_trees_scen_widgets, truelight@0: BuildTreesWndProc truelight@0: }; truelight@0: truelight@193: tron@1093: void ShowBuildTreesToolbar(void) truelight@0: { tron@1846: AllocateWindowDescFront(&_build_trees_desc, 0); truelight@0: } truelight@0: tron@1093: void ShowBuildTreesScenToolbar(void) truelight@0: { truelight@0: AllocateWindowDescFront(&_build_trees_scen_desc, 0); truelight@0: } truelight@0: truelight@674: static uint32 _errmsg_decode_params[20]; truelight@0: static StringID _errmsg_message_1, _errmsg_message_2; truelight@0: static uint _errmsg_duration; truelight@0: truelight@0: truelight@0: static const Widget _errmsg_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_NONE, 4, 11, 239, 0, 13, STR_00B2_MESSAGE, STR_NULL}, truelight@867: { WWT_PANEL, RESIZE_NONE, 4, 0, 239, 14, 45, 0x0, STR_NULL}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const Widget _errmsg_face_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_NONE, 4, 11, 333, 0, 13, STR_00B3_MESSAGE_FROM, STR_NULL}, truelight@867: { WWT_PANEL, RESIZE_NONE, 4, 0, 333, 14, 136, 0x0, STR_NULL}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static void ErrmsgWndProc(Window *w, WindowEvent *e) truelight@0: { tron@2639: switch (e->event) { truelight@0: case WE_PAINT: truelight@0: COPY_IN_DPARAM(0, _errmsg_decode_params, lengthof(_errmsg_decode_params)); truelight@0: DrawWindowWidgets(w); truelight@0: COPY_IN_DPARAM(0, _errmsg_decode_params, lengthof(_errmsg_decode_params)); truelight@867: if (!IsWindowOfPrototype(w, _errmsg_face_widgets)) { truelight@0: DrawStringMultiCenter( truelight@0: 120, truelight@193: (_errmsg_message_1 == INVALID_STRING_ID ? 25 : 15), truelight@0: _errmsg_message_2, truelight@0: 238); truelight@0: if (_errmsg_message_1 != INVALID_STRING_ID) truelight@0: DrawStringMultiCenter( truelight@0: 120, truelight@0: 30, truelight@0: _errmsg_message_1, truelight@0: 238); truelight@0: } else { tron@2475: const Player* p = GetPlayer(GetDParamX(_errmsg_decode_params,2)); truelight@0: DrawPlayerFace(p->face, p->player_color, 2, 16); truelight@0: truelight@0: DrawStringMultiCenter( truelight@0: 214, truelight@193: (_errmsg_message_1 == INVALID_STRING_ID ? 65 : 45), truelight@0: _errmsg_message_2, truelight@0: 238); truelight@0: if (_errmsg_message_1 != INVALID_STRING_ID) truelight@0: DrawStringMultiCenter( truelight@0: 214, truelight@0: 90, truelight@0: _errmsg_message_1, truelight@0: 238); truelight@0: } truelight@0: break; truelight@0: truelight@0: case WE_MOUSELOOP: tron@2639: if (_right_button_down) DeleteWindow(w); truelight@0: break; tron@2639: truelight@0: case WE_4: tron@2639: if (--_errmsg_duration == 0) DeleteWindow(w); truelight@0: break; tron@2639: tron@2639: case WE_DESTROY: tron@1860: SetRedErrorSquare(0); darkvater@172: _switch_mode_errorstr = INVALID_STRING_ID; truelight@0: break; truelight@0: truelight@0: case WE_KEYPRESS: truelight@0: if (e->keypress.keycode == WKC_SPACE) { truelight@0: // Don't continue. truelight@0: e->keypress.cont = false; truelight@0: DeleteWindow(w); truelight@0: } truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: void ShowErrorMessage(StringID msg_1, StringID msg_2, int x, int y) truelight@0: { truelight@0: Window *w; truelight@0: ViewPort *vp; truelight@0: Point pt; truelight@0: truelight@0: DeleteWindowById(WC_ERRMSG, 0); truelight@0: truelight@0: //assert(msg_2); truelight@0: if (msg_2 == 0) msg_2 = STR_EMPTY; truelight@0: truelight@0: _errmsg_message_1 = msg_1; truelight@0: _errmsg_message_2 = msg_2; truelight@0: COPY_OUT_DPARAM(_errmsg_decode_params, 0, lengthof(_errmsg_decode_params)); truelight@0: _errmsg_duration = _patches.errmsg_duration; truelight@0: if (!_errmsg_duration) truelight@0: return; truelight@193: tron@534: if (_errmsg_message_1 != STR_013B_OWNED_BY || GetDParamX(_errmsg_decode_params,2) >= 8) { truelight@0: truelight@0: if ( (x|y) != 0) { truelight@0: pt = RemapCoords2(x, y); truelight@0: for(w=_windows; w->window_class != WC_MAIN_WINDOW; w++) {} truelight@0: vp = w->viewport; truelight@0: truelight@0: // move x pos to opposite corner truelight@0: pt.x = ((pt.x - vp->virtual_left) >> vp->zoom) + vp->left; truelight@0: pt.x = (pt.x < (_screen.width >> 1)) ? _screen.width - 260 : 20; truelight@193: truelight@0: // move y pos to opposite corner truelight@0: pt.y = ((pt.y - vp->virtual_top) >> vp->zoom) + vp->top; truelight@0: pt.y = (pt.y < (_screen.height >> 1)) ? _screen.height - 80 : 100; truelight@193: truelight@0: } else { truelight@0: pt.x = (_screen.width - 240) >> 1; truelight@0: pt.y = (_screen.height - 46) >> 1; truelight@0: } truelight@0: w = AllocateWindow(pt.x, pt.y, 240, 46, ErrmsgWndProc, WC_ERRMSG, _errmsg_widgets); truelight@0: } else { truelight@0: if ( (x|y) != 0) { truelight@0: pt = RemapCoords2(x, y); truelight@0: for(w=_windows; w->window_class != WC_MAIN_WINDOW; w++) {} truelight@0: vp = w->viewport; truelight@0: pt.x = clamp(((pt.x - vp->virtual_left) >> vp->zoom) + vp->left - (334/2), 0, _screen.width - 334); truelight@0: pt.y = clamp(((pt.y - vp->virtual_top) >> vp->zoom) + vp->top - (137/2), 22, _screen.height - 137); truelight@0: } else { truelight@0: pt.x = (_screen.width - 334) >> 1; truelight@0: pt.y = (_screen.height - 137) >> 1; truelight@0: } truelight@0: w = AllocateWindow(pt.x, pt.y, 334, 137, ErrmsgWndProc, WC_ERRMSG, _errmsg_face_widgets); truelight@0: } truelight@0: truelight@0: w->desc_flags = WDF_STD_BTN | WDF_DEF_WIDGET; truelight@0: } truelight@0: truelight@0: truelight@0: void ShowEstimatedCostOrIncome(int32 cost, int x, int y) truelight@0: { tron@2498: StringID msg = STR_0805_ESTIMATED_COST; truelight@0: truelight@0: if (cost < 0) { truelight@0: cost = -cost; truelight@0: msg = STR_0807_ESTIMATED_INCOME; truelight@0: } tron@534: SetDParam(0, cost); tron@2498: ShowErrorMessage(INVALID_STRING_ID, msg, x, y); truelight@0: } truelight@0: truelight@0: void ShowCostOrIncomeAnimation(int x, int y, int z, int32 cost) truelight@0: { tron@2498: StringID msg; truelight@0: Point pt = RemapCoords(x,y,z); truelight@0: truelight@0: msg = STR_0801_COST; truelight@0: if (cost < 0) { truelight@0: cost = -cost; truelight@0: msg = STR_0803_INCOME; truelight@0: } tron@534: SetDParam(0, cost); truelight@0: AddTextEffect(msg, pt.x, pt.y, 0x250); truelight@0: } truelight@0: celestar@1935: void ShowFeederIncomeAnimation(int x, int y, int z, int32 cost) celestar@1935: { celestar@1935: Point pt = RemapCoords(x,y,z); celestar@1935: celestar@1935: SetDParam(0, cost); celestar@1935: AddTextEffect(STR_FEEDER, pt.x, pt.y, 0x250); celestar@1935: } celestar@1935: tron@2275: static const Widget _tooltips_widgets[] = { truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 0, 199, 0, 31, 0x0, STR_NULL}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: truelight@0: static void TooltipsWndProc(Window *w, WindowEvent *e) truelight@0: { tron@2639: switch (e->event) { tron@2639: case WE_PAINT: tron@2639: GfxFillRect(0, 0, w->width - 1, w->height - 1, 0); tron@2639: GfxFillRect(1, 1, w->width - 2, w->height - 2, 0x44); tron@2639: DrawStringMultiCenter((w->width >> 1), (w->height >> 1) - 5, WP(w,tooltips_d).string_id, 197); tron@2639: break; truelight@0: tron@2639: case WE_MOUSELOOP: tron@2639: if (!_right_button_down) DeleteWindow(w); tron@2639: break; truelight@0: } truelight@0: } truelight@0: truelight@0: void GuiShowTooltips(StringID string_id) truelight@0: { tron@1336: char buffer[512]; truelight@0: Window *w; truelight@0: int right,bottom; truelight@0: int x,y; truelight@193: tron@2639: if (string_id == 0) return; truelight@0: truelight@0: w = FindWindowById(WC_TOOLTIPS, 0); truelight@0: if (w != NULL) { truelight@0: if (WP(w,tooltips_d).string_id == string_id) truelight@0: return; truelight@0: DeleteWindow(w); truelight@0: } truelight@0: tron@1336: GetString(buffer, string_id); truelight@0: tron@1336: right = GetStringWidth(buffer) + 4; truelight@0: truelight@0: bottom = 14; truelight@0: if (right > 200) { truelight@0: bottom += ((right - 4) / 176) * 10; truelight@0: right = 200; truelight@0: } truelight@0: truelight@0: y = _cursor.pos.y + 30; truelight@0: if (y < 22) y = 22; truelight@0: truelight@0: if (y > (_screen.height - 44) && (y-=52) > (_screen.height - 44)) truelight@0: y = (_screen.height - 44); truelight@0: truelight@0: x = _cursor.pos.x - (right >> 1); truelight@0: if (x < 0) x = 0; truelight@0: if (x > (_screen.width - right)) x = _screen.width - right; truelight@0: truelight@0: w = AllocateWindow(x, y, right, bottom, TooltipsWndProc, WC_TOOLTIPS, _tooltips_widgets); truelight@0: WP(w,tooltips_d).string_id = string_id; truelight@0: w->flags4 &= ~WF_WHITE_BORDER_MASK; tron@2275: w->widget[0].right = right; tron@2275: w->widget[0].bottom = bottom; truelight@0: } truelight@0: truelight@0: tron@1556: static void DrawStationCoverageText(const AcceptedCargo accepts, tron@1556: int str_x, int str_y, uint mask) truelight@0: { tron@1556: char *b = _userstring; truelight@0: int i; truelight@193: tron@1553: b = InlineString(b, STR_000D_ACCEPTS); truelight@0: tron@1556: for (i = 0; i != NUM_CARGO; i++, mask >>= 1) { tron@1556: if (accepts[i] >= 8 && mask & 1) { tron@1556: b = InlineString(b, _cargoc.names_s[i]); tron@1553: *b++ = ','; tron@1553: *b++ = ' '; truelight@0: } truelight@0: } truelight@0: tron@1329: if (b == &_userstring[3]) { tron@1553: b = InlineString(b, STR_00D0_NOTHING); tron@1553: *b++ = '\0'; truelight@0: } else { tron@1556: b[-2] = '\0'; truelight@0: } truelight@0: truelight@0: DrawStringMultiLine(str_x, str_y, STR_SPEC_USERSTRING, 144); truelight@0: } truelight@0: Celestar@568: void DrawStationCoverageAreaText(int sx, int sy, uint mask, int rad) { peter1138@2873: TileIndex tile = TileVirtXY(_thd.pos.x, _thd.pos.y); tron@2498: AcceptedCargo accepts; peter1138@2873: if (tile < MapSize()) { peter1138@2873: GetAcceptanceAroundTiles(accepts, tile, _thd.size.x / 16, _thd.size.y / 16 , rad); truelight@0: DrawStationCoverageText(accepts, sx, sy, mask); truelight@0: } truelight@0: } truelight@0: tron@2549: void CheckRedrawStationCoverage(const Window* w) truelight@0: { tron@2549: if (_thd.dirty & 1) { tron@2549: _thd.dirty &= ~1; truelight@0: SetWindowDirty(w); truelight@0: } truelight@0: } truelight@0: truelight@0: truelight@0: void UnclickSomeWindowButtons(Window *w, uint32 mask) truelight@0: { truelight@0: uint32 x = w->click_state & mask; truelight@0: int i = 0; truelight@0: w->click_state ^= x; truelight@0: do { tron@2549: if (x & 1) InvalidateWidget(w, i); tron@2549: } while (i++, x >>= 1); truelight@0: } truelight@0: truelight@0: truelight@0: void UnclickWindowButtons(Window *w) truelight@0: { truelight@0: UnclickSomeWindowButtons(w, (uint32)-1); truelight@0: } truelight@0: truelight@0: truelight@0: void SetVScrollCount(Window *w, int num) truelight@0: { truelight@0: w->vscroll.count = num; truelight@0: num -= w->vscroll.cap; truelight@0: if (num < 0) num = 0; truelight@0: if (num < w->vscroll.pos) w->vscroll.pos = num; truelight@0: } truelight@0: bjarni@842: void SetVScroll2Count(Window *w, int num) truelight@867: { bjarni@842: w->vscroll2.count = num; bjarni@842: num -= w->vscroll2.cap; bjarni@842: if (num < 0) num = 0; bjarni@842: if (num < w->vscroll2.pos) w->vscroll2.pos = num; bjarni@842: } bjarni@842: truelight@0: void SetHScrollCount(Window *w, int num) truelight@0: { truelight@0: w->hscroll.count = num; truelight@0: num -= w->hscroll.cap; truelight@0: if (num < 0) num = 0; truelight@0: if (num < w->hscroll.pos) w->hscroll.pos = num; truelight@0: } truelight@0: Darkvater@1390: static void DelChar(Textbuf *tb) darkvater@911: { Darkvater@1419: tb->width -= GetCharacterWidth((byte)tb->buf[tb->caretpos]); Darkvater@1390: memmove(tb->buf + tb->caretpos, tb->buf + tb->caretpos + 1, tb->length - tb->caretpos); Darkvater@1390: tb->length--; Darkvater@1390: } darkvater@911: Darkvater@1390: /** Darkvater@1390: * Delete a character from a textbuffer, either with 'Delete' or 'Backspace' Darkvater@1390: * The character is delete from the position the caret is at Darkvater@1390: * @param tb @Textbuf type to be changed Darkvater@1390: * @param delmode Type of deletion, either @WKC_BACKSPACE or @WKC_DELETE Darkvater@1390: * @return Return true on successfull change of Textbuf, or false otherwise Darkvater@1390: */ Darkvater@1390: bool DeleteTextBufferChar(Textbuf *tb, int delmode) Darkvater@1390: { Darkvater@1390: if (delmode == WKC_BACKSPACE && tb->caretpos != 0) { Darkvater@1390: tb->caretpos--; Darkvater@1419: tb->caretxoffs -= GetCharacterWidth((byte)tb->buf[tb->caretpos]); Darkvater@1390: Darkvater@1390: DelChar(tb); Darkvater@1390: return true; Darkvater@1390: } else if (delmode == WKC_DELETE && tb->caretpos < tb->length) { Darkvater@1390: DelChar(tb); Darkvater@1390: return true; Darkvater@1390: } Darkvater@1390: Darkvater@1390: return false; Darkvater@1390: } Darkvater@1390: Darkvater@1390: /** Darkvater@1879: * Delete every character in the textbuffer Darkvater@1879: * @param tb @Textbuf buffer to be emptied Darkvater@1879: */ Darkvater@1879: void DeleteTextBufferAll(Textbuf *tb) Darkvater@1879: { Darkvater@1879: memset(tb->buf, 0, tb->maxlength); Darkvater@1879: tb->length = tb->width = 0; Darkvater@1879: tb->caretpos = tb->caretxoffs = 0; Darkvater@1879: } Darkvater@1879: Darkvater@1879: /** Darkvater@1390: * Insert a character to a textbuffer. If maxlength is zero, we don't care about Darkvater@1390: * the screenlength but only about the physical length of the string Darkvater@1390: * @param tb @Textbuf type to be changed Darkvater@1390: * @param key Character to be inserted Darkvater@1390: * @return Return true on successfull change of Textbuf, or false otherwise Darkvater@1390: */ Darkvater@1390: bool InsertTextBufferChar(Textbuf *tb, byte key) Darkvater@1390: { Darkvater@1390: const byte charwidth = GetCharacterWidth(key); Darkvater@1390: if (tb->length < tb->maxlength && (tb->maxwidth == 0 || tb->width + charwidth <= tb->maxwidth)) { Darkvater@1397: memmove(tb->buf + tb->caretpos + 1, tb->buf + tb->caretpos, (tb->length - tb->caretpos) + 1); Darkvater@1390: tb->buf[tb->caretpos] = key; Darkvater@1390: tb->length++; Darkvater@1390: tb->width += charwidth; Darkvater@1390: Darkvater@1390: tb->caretpos++; Darkvater@1390: tb->caretxoffs += charwidth; Darkvater@1390: return true; Darkvater@1390: } Darkvater@1390: return false; Darkvater@1390: } Darkvater@1390: Darkvater@1390: /** Darkvater@1390: * Handle text navigation with arrow keys left/right. Darkvater@1390: * This defines where the caret will blink and the next characer interaction will occur Darkvater@1390: * @param tb @Textbuf type where navigation occurs Darkvater@1390: * @param navmode Direction in which navigation occurs @WKC_LEFT, @WKC_RIGHT, @WKC_END, @WKC_HOME Darkvater@1390: * @return Return true on successfull change of Textbuf, or false otherwise Darkvater@1390: */ Darkvater@1390: bool MoveTextBufferPos(Textbuf *tb, int navmode) Darkvater@1390: { Darkvater@1390: switch (navmode) { Darkvater@1390: case WKC_LEFT: Darkvater@1390: if (tb->caretpos != 0) { Darkvater@1390: tb->caretpos--; Darkvater@1419: tb->caretxoffs -= GetCharacterWidth((byte)tb->buf[tb->caretpos]); Darkvater@1390: return true; Darkvater@1390: } Darkvater@1390: break; Darkvater@1390: case WKC_RIGHT: Darkvater@1390: if (tb->caretpos < tb->length) { Darkvater@1419: tb->caretxoffs += GetCharacterWidth((byte)tb->buf[tb->caretpos]); Darkvater@1390: tb->caretpos++; Darkvater@1390: return true; Darkvater@1390: } Darkvater@1390: break; Darkvater@1390: case WKC_HOME: Darkvater@1390: tb->caretpos = 0; Darkvater@1390: tb->caretxoffs = 0; Darkvater@1390: return true; Darkvater@1390: case WKC_END: Darkvater@1390: tb->caretpos = tb->length; Darkvater@1390: tb->caretxoffs = tb->width; Darkvater@1390: return true; Darkvater@1390: } Darkvater@1390: Darkvater@1390: return false; Darkvater@1390: } Darkvater@1390: Darkvater@1390: /** Darkvater@1390: * Update @Textbuf type with its actual physical character and screenlength Darkvater@1390: * Get the count of characters in the string as well as the width in pixels. Darkvater@1390: * Useful when copying in a larger amount of text at once Darkvater@1390: * @param tb @Textbuf type which length is calculated Darkvater@1390: */ Darkvater@1390: void UpdateTextBufferSize(Textbuf *tb) Darkvater@1390: { tron@2630: const char* buf; tron@2630: Darkvater@1390: tb->length = 0; Darkvater@1390: tb->width = 0; Darkvater@1390: Darkvater@1390: for (buf = tb->buf; *buf != '\0' && tb->length <= tb->maxlength; buf++) { Darkvater@1390: tb->length++; Darkvater@1390: tb->width += GetCharacterWidth((byte)*buf); Darkvater@1390: } Darkvater@1390: Darkvater@1390: tb->caretpos = tb->length; Darkvater@1390: tb->caretxoffs = tb->width; darkvater@911: } darkvater@911: Darkvater@2887: int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *we) truelight@0: { truelight@0: we->keypress.cont = false; truelight@0: Darkvater@1390: switch (we->keypress.keycode) { Darkvater@1390: case WKC_ESC: return 2; Darkvater@1390: case WKC_RETURN: case WKC_NUM_ENTER: return 1; Darkvater@1390: case (WKC_CTRL | 'V'): Darkvater@2887: if (InsertTextBufferClipboard(&string->text)) darkvater@911: InvalidateWidget(w, wid); Darkvater@1390: break; Darkvater@1879: case (WKC_CTRL | 'U'): Darkvater@2887: DeleteTextBufferAll(&string->text); Darkvater@1879: InvalidateWidget(w, wid); Darkvater@1879: break; Darkvater@1390: case WKC_BACKSPACE: case WKC_DELETE: Darkvater@2887: if (DeleteTextBufferChar(&string->text, we->keypress.keycode)) Darkvater@1390: InvalidateWidget(w, wid); Darkvater@1390: break; Darkvater@1390: case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME: Darkvater@2887: if (MoveTextBufferPos(&string->text, we->keypress.keycode)) Darkvater@1390: InvalidateWidget(w, wid); Darkvater@1390: break; Darkvater@1390: default: Darkvater@1390: if (IsValidAsciiChar(we->keypress.ascii)) { Darkvater@2887: if (InsertTextBufferChar(&string->text, we->keypress.ascii)) truelight@0: InvalidateWidget(w, wid); darkvater@911: } else // key wasn't caught truelight@0: we->keypress.cont = true; truelight@0: } truelight@0: truelight@0: return 0; truelight@0: } truelight@0: Darkvater@1390: bool HandleCaret(Textbuf *tb) Darkvater@1390: { Darkvater@1390: /* caret changed? */ Darkvater@1390: bool b = !!(_caret_timer & 0x20); Darkvater@1390: Darkvater@1390: if (b != tb->caret) { Darkvater@1390: tb->caret = b; Darkvater@1390: return true; Darkvater@1390: } Darkvater@1390: return false; Darkvater@1390: } Darkvater@1390: Darkvater@2887: void HandleEditBox(Window *w, querystr_d *string, int wid) truelight@0: { Darkvater@2887: if (HandleCaret(&string->text)) InvalidateWidget(w, wid); truelight@0: } truelight@0: Darkvater@2887: void DrawEditBox(Window *w, querystr_d *string, int wid) truelight@0: { truelight@0: const Widget *wi = w->widget + wid; Darkvater@2887: const Textbuf *tb = &string->text; truelight@0: truelight@0: GfxFillRect(wi->left+1, wi->top+1, wi->right-1, wi->bottom-1, 215); Darkvater@1390: DoDrawString(tb->buf, wi->left+2, wi->top+1, 8); Darkvater@2887: if (tb->caret) DoDrawString("_", wi->left + 2 + tb->caretxoffs, wi->top + 1, 12); truelight@0: } truelight@0: truelight@0: static void QueryStringWndProc(Window *w, WindowEvent *e) truelight@0: { truelight@543: static bool closed = false; Darkvater@1843: switch (e->event) { Darkvater@1843: case WE_CREATE: Darkvater@1843: SETBIT(_no_scroll, SCROLL_EDIT); Darkvater@1843: closed = false; Darkvater@1843: break; Darkvater@1843: Darkvater@1390: case WE_PAINT: tron@534: SetDParam(0, WP(w,querystr_d).caption); truelight@0: DrawWindowWidgets(w); truelight@0: Darkvater@2887: DrawEditBox(w, &WP(w,querystr_d), 5); Darkvater@1390: break; truelight@0: truelight@0: case WE_CLICK: truelight@0: switch(e->click.widget) { truelight@0: case 3: DeleteWindow(w); break; truelight@0: case 4: truelight@0: press_ok:; tron@1386: if (WP(w, querystr_d).orig != NULL && Darkvater@1390: strcmp(WP(w, querystr_d).text.buf, WP(w, querystr_d).orig) == 0) { truelight@0: DeleteWindow(w); truelight@0: } else { Darkvater@1390: char *buf = WP(w,querystr_d).text.buf; tron@390: WindowClass wnd_class = WP(w,querystr_d).wnd_class; tron@390: WindowNumber wnd_num = WP(w,querystr_d).wnd_num; tron@390: Window *parent; tron@390: truelight@543: // Mask the edit-box as closed, so we don't send out a CANCEL truelight@543: closed = true; truelight@543: truelight@598: DeleteWindow(w); truelight@598: tron@390: parent = FindWindowById(wnd_class, wnd_num); truelight@0: if (parent != NULL) { truelight@0: WindowEvent e; truelight@0: e.event = WE_ON_EDIT_TEXT; truelight@0: e.edittext.str = buf; truelight@0: parent->wndproc(parent, &e); truelight@0: } truelight@0: } truelight@0: break; truelight@0: } truelight@0: break; truelight@0: truelight@0: case WE_MOUSELOOP: { truelight@0: if (!FindWindowById(WP(w,querystr_d).wnd_class, WP(w,querystr_d).wnd_num)) { truelight@0: DeleteWindow(w); truelight@0: return; truelight@0: } Darkvater@2887: HandleEditBox(w, &WP(w, querystr_d), 5); truelight@0: } break; truelight@0: truelight@0: case WE_KEYPRESS: { Darkvater@2887: switch (HandleEditBoxKey(w, &WP(w, querystr_d), 5, e)) { truelight@0: case 1: // Return truelight@0: goto press_ok; truelight@0: case 2: // Escape truelight@0: DeleteWindow(w); truelight@0: break; truelight@0: } truelight@0: } break; truelight@0: truelight@0: case WE_DESTROY: truelight@543: // If the window is not closed yet, it means it still needs to send a CANCEL truelight@543: if (!closed) { truelight@543: Window *parent = FindWindowById(WP(w,querystr_d).wnd_class, WP(w,querystr_d).wnd_num); truelight@543: if (parent != NULL) { truelight@543: WindowEvent e; truelight@543: e.event = WE_ON_EDIT_TEXT_CANCEL; truelight@543: parent->wndproc(parent, &e); truelight@543: } truelight@543: } Darkvater@1397: CLRBIT(_no_scroll, SCROLL_EDIT); truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: static const Widget _query_string_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_NONE, 14, 11, 259, 0, 13, STR_012D, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 259, 14, 29, 0x0, STR_NULL}, truelight@867: { WWT_TEXTBTN, RESIZE_NONE, 14, 0, 129, 30, 41, STR_012E_CANCEL, STR_NULL}, truelight@867: { WWT_TEXTBTN, RESIZE_NONE, 14, 130, 259, 30, 41, STR_012F_OK, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_NONE, 14, 2, 257, 16, 27, 0x0, STR_NULL}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _query_string_desc = { truelight@0: 190, 219, 260, 42, truelight@0: WC_QUERY_STRING,0, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, truelight@0: _query_string_widgets, truelight@0: QueryStringWndProc truelight@0: }; truelight@0: tron@1386: static char _edit_str_buf[64]; tron@1386: static char _orig_str_buf[lengthof(_edit_str_buf)]; truelight@0: tron@1386: void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number) truelight@0: { truelight@0: Window *w; Darkvater@1390: uint realmaxlen = maxlen & ~0x1000; truelight@0: Darkvater@1390: assert(realmaxlen < lengthof(_edit_str_buf)); truelight@0: truelight@0: DeleteWindowById(WC_QUERY_STRING, 0); truelight@0: DeleteWindowById(WC_SAVELOAD, 0); truelight@0: tron@1386: w = AllocateWindowDesc(&_query_string_desc); tron@1386: tron@1386: GetString(_edit_str_buf, str); Darkvater@1390: _edit_str_buf[realmaxlen] = '\0'; truelight@596: truelight@596: if (maxlen & 0x1000) { tron@1386: WP(w, querystr_d).orig = NULL; tron@1386: } else { tron@1386: strcpy(_orig_str_buf, _edit_str_buf); tron@1386: WP(w, querystr_d).orig = _orig_str_buf; tron@1386: } truelight@0: truelight@0: w->click_state = 1 << 5; Darkvater@1390: WP(w, querystr_d).caption = caption; Darkvater@1390: WP(w, querystr_d).wnd_class = window_class; Darkvater@1390: WP(w, querystr_d).wnd_num = window_number; Darkvater@1390: WP(w, querystr_d).text.caret = false; Darkvater@1390: WP(w, querystr_d).text.maxlength = realmaxlen - 1; Darkvater@1390: WP(w, querystr_d).text.maxwidth = maxwidth; Darkvater@1390: WP(w, querystr_d).text.buf = _edit_str_buf; Darkvater@1390: UpdateTextBufferSize(&WP(w, querystr_d).text); truelight@0: } truelight@0: truelight@0: static const Widget _load_dialog_1_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 256, 0, 13, STR_4001_LOAD_GAME, STR_018C_WINDOW_TITLE_DRAG_THIS}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 128, 256, 14, 25, STR_SORT_BY_DATE, STR_SORT_ORDER_TIP}, truelight@867: { WWT_IMGBTN, RESIZE_RIGHT, 14, 0, 256, 26, 47, 0x0, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_RB, 14, 0, 256, 48, 293, 0x0, STR_NULL}, Darkvater@2750: { WWT_PUSHIMGBTN, RESIZE_LR, 14, 245, 256, 48, 59, SPR_HOUSE_ICON, STR_SAVELOAD_HOME_BUTTON}, truelight@867: { WWT_6, RESIZE_RB, 14, 2, 243, 50, 291, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, Darkvater@2559: { WWT_SCROLLBAR, RESIZE_LRB, 14, 245, 256, 60, 281, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, darkvater@893: { WWT_RESIZEBOX, RESIZE_LRTB, 14, 245, 256, 282, 293, 0x0, STR_RESIZE_BUTTON}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const Widget _load_dialog_2_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 256, 0, 13, STR_0298_LOAD_SCENARIO, STR_018C_WINDOW_TITLE_DRAG_THIS}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 128, 256, 14, 25, STR_SORT_BY_DATE, STR_SORT_ORDER_TIP}, truelight@867: { WWT_IMGBTN, RESIZE_RIGHT, 14, 0, 256, 26, 47, 0x0, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_RB, 14, 0, 256, 48, 293, 0x0, STR_NULL}, Darkvater@2750: { WWT_PUSHIMGBTN, RESIZE_LR, 14, 245, 256, 48, 59, SPR_HOUSE_ICON, STR_SAVELOAD_HOME_BUTTON}, truelight@867: { WWT_6, RESIZE_RB, 14, 2, 243, 50, 291, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, Darkvater@2559: { WWT_SCROLLBAR, RESIZE_LRB, 14, 245, 256, 60, 281, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, darkvater@893: { WWT_RESIZEBOX, RESIZE_LRTB, 14, 245, 256, 282, 293, 0x0, STR_RESIZE_BUTTON}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const Widget _save_dialog_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 256, 0, 13, STR_4000_SAVE_GAME, STR_018C_WINDOW_TITLE_DRAG_THIS}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 128, 256, 14, 25, STR_SORT_BY_DATE, STR_SORT_ORDER_TIP}, truelight@867: { WWT_IMGBTN, RESIZE_RIGHT, 14, 0, 256, 26, 47, 0x0, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_RB, 14, 0, 256, 48, 291, 0x0, STR_NULL}, Darkvater@2750: { WWT_PUSHIMGBTN, RESIZE_LR, 14, 245, 256, 48, 59, SPR_HOUSE_ICON, STR_SAVELOAD_HOME_BUTTON}, truelight@867: { WWT_6, RESIZE_RB, 14, 2, 243, 50, 290, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, Darkvater@2559: { WWT_SCROLLBAR, RESIZE_LRB, 14, 245, 256, 60, 291, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, truelight@867: { WWT_IMGBTN, RESIZE_RTB, 14, 0, 256, 292, 307, 0x0, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_RTB, 14, 2, 254, 294, 305, 0x0, STR_400B_CURRENTLY_SELECTED_NAME}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 127, 308, 319, STR_4003_DELETE, STR_400C_DELETE_THE_CURRENTLY_SELECTED}, darkvater@893: { WWT_PUSHTXTBTN, RESIZE_TB, 14, 128, 244, 308, 319, STR_4002_SAVE, STR_400D_SAVE_THE_CURRENT_GAME_USING}, darkvater@893: { WWT_RESIZEBOX, RESIZE_LRTB, 14, 245, 256, 308, 319, 0x0, STR_RESIZE_BUTTON}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const Widget _save_dialog_scen_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 256, 0, 13, STR_0299_SAVE_SCENARIO, STR_018C_WINDOW_TITLE_DRAG_THIS}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 14, 128, 256, 14, 25, STR_SORT_BY_DATE, STR_SORT_ORDER_TIP}, truelight@867: { WWT_IMGBTN, RESIZE_RIGHT, 14, 0, 256, 26, 47, 0x0, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_RB, 14, 0, 256, 48, 291, 0x0, STR_NULL}, Darkvater@2750: { WWT_PUSHIMGBTN, RESIZE_LR, 14, 245, 256, 48, 59, SPR_HOUSE_ICON, STR_SAVELOAD_HOME_BUTTON}, truelight@867: { WWT_6, RESIZE_RB, 14, 2, 243, 50, 290, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, Darkvater@2559: { WWT_SCROLLBAR, RESIZE_LRB, 14, 245, 256, 60, 291, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, truelight@867: { WWT_IMGBTN, RESIZE_RTB, 14, 0, 256, 292, 307, 0x0, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_RTB, 14, 2, 254, 294, 305, 0x0, STR_400B_CURRENTLY_SELECTED_NAME}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 127, 308, 319, STR_4003_DELETE, STR_400C_DELETE_THE_CURRENTLY_SELECTED}, darkvater@893: { WWT_PUSHTXTBTN, RESIZE_TB, 14, 128, 244, 308, 319, STR_4002_SAVE, STR_400D_SAVE_THE_CURRENT_GAME_USING}, darkvater@893: { WWT_RESIZEBOX, RESIZE_LRTB, 14, 245, 256, 308, 319, 0x0, STR_RESIZE_BUTTON}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: ludde@2261: // Colors for fios types ludde@2261: const byte _fios_colors[] = {13, 9, 9, 6, 5, 6, 5}; ludde@2261: tron@1093: void BuildFileList(void) truelight@0: { darkvater@1596: _fios_path_changed = true; truelight@0: FiosFreeSavegameList(); tron@2549: switch (_saveload_mode) { tron@2549: case SLD_NEW_GAME: tron@2549: case SLD_LOAD_SCENARIO: tron@2549: case SLD_SAVE_SCENARIO: tron@2549: _fios_list = FiosGetScenarioList(&_fios_num, _saveload_mode); tron@2549: break; tron@2549: tron@2549: default: tron@2549: _fios_list = FiosGetSavegameList(&_fios_num, _saveload_mode); tron@2549: break; tron@2549: } truelight@0: } truelight@0: Darkvater@2100: static void DrawFiosTexts(uint maxw) truelight@0: { darkvater@1596: static const char *path = NULL; darkvater@1596: static StringID str = STR_4006_UNABLE_TO_READ_DRIVE; darkvater@1596: static uint32 tot = 0; truelight@0: darkvater@1596: if (_fios_path_changed) { darkvater@1596: str = FiosGetDescText(&path, &tot); darkvater@1596: _fios_path_changed = false; darkvater@1596: } darkvater@1596: darkvater@1596: if (str != STR_4006_UNABLE_TO_READ_DRIVE) SetDParam(0, tot); darkvater@1596: DrawString(2, 37, str, 0); Darkvater@2103: DoDrawStringTruncated(path, 2, 27, 16, maxw); truelight@0: } truelight@0: tron@1093: static void MakeSortedSaveGameList(void) truelight@0: { tron@2631: uint sort_start = 0; tron@2631: uint sort_end = 0; tron@2631: uint s_amount; tron@2631: int i; tron@2631: truelight@0: /* Directories are always above the files (FIOS_TYPE_DIR) truelight@0: * Drives (A:\ (windows only) are always under the files (FIOS_TYPE_DRIVE) truelight@0: * Only sort savegames/scenarios, not directories truelight@0: */ tron@2631: for (i = 0; i < _fios_num; i++) { tron@2631: switch (_fios_list[i].type) { tron@2631: case FIOS_TYPE_DIR: sort_start++; break; tron@2631: case FIOS_TYPE_PARENT: sort_start++; break; tron@2631: case FIOS_TYPE_DRIVE: sort_end++; break; tron@2631: } truelight@0: } truelight@0: truelight@0: s_amount = _fios_num - sort_start - sort_end; tron@1105: if (s_amount > 0) truelight@0: qsort(_fios_list + sort_start, s_amount, sizeof(FiosItem), compare_FiosItems); truelight@0: } truelight@0: tron@402: static void GenerateFileName(void) tron@402: { truelight@635: /* Check if we are not a specatator who wants to generate a name.. truelight@635: Let's use the name of player #0 for now. */ tron@2631: const Player* p = GetPlayer(_local_player < MAX_PLAYERS ? _local_player : 0); truelight@635: tron@534: SetDParam(0, p->name_1); tron@534: SetDParam(1, p->name_2); tron@534: SetDParam(2, _date); tron@402: GetString(_edit_str_buf, STR_4004); tron@402: } tron@402: darkvater@1131: extern void StartupEngines(void); darkvater@1131: truelight@0: static void SaveLoadDlgWndProc(Window *w, WindowEvent *e) truelight@0: { Darkvater@2559: static FiosItem o_dir; Darkvater@2559: Darkvater@2559: switch (e->event) { Darkvater@2559: case WE_CREATE: { /* Set up OPENTTD button */ Darkvater@2559: o_dir.type = FIOS_TYPE_DIRECT; Darkvater@2559: switch (_saveload_mode) { tron@2639: case SLD_SAVE_GAME: tron@2639: case SLD_LOAD_GAME: Darkvater@2559: ttd_strlcpy(&o_dir.name[0], _path.save_dir, sizeof(o_dir.name)); Darkvater@2559: break; tron@2639: tron@2639: case SLD_SAVE_SCENARIO: tron@2639: case SLD_LOAD_SCENARIO: Darkvater@2559: ttd_strlcpy(&o_dir.name[0], _path.scenario_dir, sizeof(o_dir.name)); Darkvater@2559: break; tron@2639: Darkvater@2559: default: Darkvater@2559: ttd_strlcpy(&o_dir.name[0], _path.personal_dir, sizeof(o_dir.name)); Darkvater@2559: } Darkvater@2559: break; Darkvater@2559: } Darkvater@2559: truelight@0: case WE_PAINT: { truelight@0: int y,pos; truelight@0: const FiosItem *item; truelight@0: truelight@0: SetVScrollCount(w, _fios_num); truelight@0: DrawWindowWidgets(w); Darkvater@2100: DrawFiosTexts(w->width); truelight@0: truelight@0: if (_savegame_sort_dirty) { truelight@0: _savegame_sort_dirty = false; truelight@0: MakeSortedSaveGameList(); truelight@0: } truelight@0: Darkvater@2750: GfxFillRect(w->widget[7].left + 1, w->widget[7].top + 1, w->widget[7].right, w->widget[7].bottom, 0xD7); tron@2526: DoDrawString( tron@2526: _savegame_sort_order & SORT_DESCENDING ? DOWNARROW : UPARROW, tron@2526: _savegame_sort_order & SORT_BY_NAME ? w->widget[2].right - 9 : w->widget[3].right - 9, tron@2526: 15, 16 tron@2526: ); truelight@0: Darkvater@2750: y = w->widget[7].top + 1; truelight@0: pos = w->vscroll.pos; truelight@0: while (pos < _fios_num) { truelight@0: item = _fios_list + pos; Darkvater@2103: DoDrawStringTruncated(item->title, 4, y, _fios_colors[item->type], w->width - 18); truelight@0: pos++; tron@2549: y += 10; Darkvater@2750: if (y >= w->vscroll.cap * 10 + w->widget[7].top + 1) break; truelight@0: } truelight@0: truelight@0: if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) { Darkvater@2887: DrawEditBox(w, &WP(w,querystr_d), 10); truelight@0: } truelight@0: break; truelight@0: } truelight@0: case WE_CLICK: Darkvater@2559: switch (e->click.widget) { truelight@0: case 2: /* Sort save names by name */ tron@2526: _savegame_sort_order = (_savegame_sort_order == SORT_BY_NAME) ? tron@2526: SORT_BY_NAME | SORT_DESCENDING : SORT_BY_NAME; truelight@0: _savegame_sort_dirty = true; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: truelight@0: case 3: /* Sort save names by date */ tron@2526: _savegame_sort_order = (_savegame_sort_order == SORT_BY_DATE) ? tron@2526: SORT_BY_DATE | SORT_DESCENDING : SORT_BY_DATE; truelight@0: _savegame_sort_dirty = true; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: Darkvater@2750: case 6: /* OpenTTD 'button', jumps to OpenTTD directory */ Darkvater@2750: FiosBrowseTo(&o_dir); Darkvater@2750: SetWindowDirty(w); Darkvater@2750: BuildFileList(); Darkvater@2750: break; Darkvater@2750: Darkvater@2750: case 7: { /* Click the listbox */ Darkvater@2750: int y = (e->click.pt.y - w->widget[e->click.widget].top - 1) / 10; truelight@0: char *name; truelight@0: const FiosItem *file; truelight@0: tron@2639: if (y < 0 || (y += w->vscroll.pos) >= w->vscroll.count) return; truelight@0: truelight@0: file = _fios_list + y; truelight@193: tron@2639: name = FiosBrowseTo(file); tron@2639: if (name != NULL) { Darkvater@2100: if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) { Darkvater@2100: _switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD; Darkvater@2100: truelight@0: SetFiosType(file->type); Darkvater@2100: ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name)); Darkvater@2100: ttd_strlcpy(_file_to_saveload.title, file->title, sizeof(_file_to_saveload.title)); Darkvater@2100: truelight@0: DeleteWindow(w); truelight@0: } else { truelight@0: // SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox celestar@9948: ttd_strlcpy(WP(w, querystr_d).text.buf, file->title, WP(w, querystr_d).text.maxlength); Darkvater@1390: UpdateTextBufferSize(&WP(w, querystr_d).text); Darkvater@2559: InvalidateWidget(w, 10); truelight@0: } truelight@0: } else { truelight@0: // Changed directory, need repaint. truelight@0: SetWindowDirty(w); truelight@0: BuildFileList(); truelight@0: } truelight@0: break; truelight@0: } Darkvater@2559: Darkvater@2559: case 11: case 12: /* Delete, Save game */ truelight@0: break; truelight@0: } truelight@0: break; truelight@0: case WE_MOUSELOOP: Darkvater@2887: HandleEditBox(w, &WP(w, querystr_d), 10); truelight@0: break; truelight@0: case WE_KEYPRESS: Darkvater@2165: if (e->keypress.keycode == WKC_ESC) { Darkvater@2165: DeleteWindow(w); Darkvater@2165: return; Darkvater@2165: } Darkvater@2165: Darkvater@2165: if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) { Darkvater@2887: if (HandleEditBoxKey(w, &WP(w, querystr_d), 10, e) == 1) /* Press Enter */ Darkvater@2559: HandleButtonClick(w, 12); truelight@0: } truelight@0: break; truelight@0: case WE_TIMEOUT: Darkvater@2559: if (HASBIT(w->click_state, 11)) { /* Delete button clicked */ tron@2255: if (!FiosDelete(WP(w,querystr_d).text.buf)) { tron@2255: ShowErrorMessage(INVALID_STRING_ID, STR_4008_UNABLE_TO_DELETE_FILE, 0, 0); celestar@9948: } else { celestar@9948: BuildFileList(); celestar@9948: /* Reset file name to current date on successfull delete */ celestar@9948: if (_saveload_mode == SLD_SAVE_GAME) GenerateFileName(); tron@2255: } celestar@9948: celestar@9948: UpdateTextBufferSize(&WP(w, querystr_d).text); truelight@0: SetWindowDirty(w); Darkvater@2559: } else if (HASBIT(w->click_state, 12)) { /* Save button clicked */ truelight@0: _switch_mode = SM_SAVE; celestar@9948: FiosMakeSavegameName(_file_to_saveload.name, WP(w,querystr_d).text.buf, sizeof(_file_to_saveload.name)); darkvater@1131: darkvater@1131: /* In the editor set up the vehicle engines correctly (date might have changed) */ darkvater@1131: if (_game_mode == GM_EDITOR) StartupEngines(); truelight@0: } truelight@0: break; truelight@0: case WE_DESTROY: matthijs@1274: // pause is only used in single-player, non-editor mode, non menu mode matthijs@1274: if(!_networking && (_game_mode != GM_EDITOR) && (_game_mode != GM_MENU)) dominik@278: DoCommandP(0, 0, 0, NULL, CMD_PAUSE); truelight@0: FiosFreeSavegameList(); Darkvater@1397: CLRBIT(_no_scroll, SCROLL_SAVE); truelight@0: break; truelight@867: case WE_RESIZE: { truelight@867: /* Widget 2 and 3 have to go with halve speed, make it so obiwan */ truelight@867: uint diff = e->sizing.diff.x / 2; truelight@867: w->widget[2].right += diff; truelight@867: w->widget[3].left += diff; truelight@867: w->widget[3].right += e->sizing.diff.x; truelight@867: Darkvater@2559: /* Same for widget 11 and 12 in save-dialog */ truelight@867: if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) { Darkvater@2559: w->widget[11].right += diff; Darkvater@2559: w->widget[12].left += diff; Darkvater@2559: w->widget[12].right += e->sizing.diff.x; truelight@867: } truelight@867: truelight@867: w->vscroll.cap += e->sizing.diff.y / 10; truelight@867: } break; truelight@193: } truelight@0: } truelight@0: truelight@0: static const WindowDesc _load_dialog_desc = { truelight@0: WDP_CENTER, WDP_CENTER, 257, 294, truelight@0: WC_SAVELOAD,0, truelight@867: WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, truelight@0: _load_dialog_1_widgets, truelight@0: SaveLoadDlgWndProc, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _load_dialog_scen_desc = { truelight@0: WDP_CENTER, WDP_CENTER, 257, 294, truelight@0: WC_SAVELOAD,0, truelight@867: WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, truelight@0: _load_dialog_2_widgets, truelight@0: SaveLoadDlgWndProc, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _save_dialog_desc = { truelight@0: WDP_CENTER, WDP_CENTER, 257, 320, truelight@0: WC_SAVELOAD,0, truelight@867: WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, truelight@0: _save_dialog_widgets, truelight@0: SaveLoadDlgWndProc, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _save_dialog_scen_desc = { truelight@0: WDP_CENTER, WDP_CENTER, 257, 320, truelight@0: WC_SAVELOAD,0, truelight@867: WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, truelight@0: _save_dialog_scen_widgets, truelight@0: SaveLoadDlgWndProc, truelight@0: }; truelight@0: truelight@0: static const WindowDesc * const _saveload_dialogs[] = { truelight@0: &_load_dialog_desc, truelight@0: &_load_dialog_scen_desc, truelight@0: &_save_dialog_desc, truelight@0: &_save_dialog_scen_desc, truelight@0: }; truelight@0: truelight@0: void ShowSaveLoadDialog(int mode) truelight@0: { truelight@0: Window *w; truelight@0: Darkvater@1914: SetObjectToPlace(SPR_CURSOR_ZZZ, 0, 0, 0); truelight@0: DeleteWindowById(WC_QUERY_STRING, 0); truelight@0: DeleteWindowById(WC_SAVELOAD, 0); truelight@0: truelight@0: _saveload_mode = mode; Darkvater@1397: SETBIT(_no_scroll, SCROLL_SAVE); Darkvater@1397: Darkvater@1397: switch (mode) { tron@2631: case SLD_SAVE_GAME: GenerateFileName(); break; tron@2631: case SLD_SAVE_SCENARIO: strcpy(_edit_str_buf, "UNNAMED"); break; Darkvater@1397: } truelight@0: truelight@0: w = AllocateWindowDesc(_saveload_dialogs[mode]); truelight@0: w->vscroll.cap = 24; truelight@867: w->resize.step_width = 2; truelight@867: w->resize.step_height = 10; truelight@867: w->resize.height = w->height - 14 * 10; // Minimum of 10 items Darkvater@2750: SETBIT(w->click_state, 7); Darkvater@1390: WP(w,querystr_d).text.caret = false; Darkvater@1390: WP(w,querystr_d).text.maxlength = lengthof(_edit_str_buf) - 1; Darkvater@1390: WP(w,querystr_d).text.maxwidth = 240; Darkvater@1390: WP(w,querystr_d).text.buf = _edit_str_buf; Darkvater@1390: UpdateTextBufferSize(&WP(w, querystr_d).text); truelight@0: matthijs@1274: // pause is only used in single-player, non-editor mode, non-menu mode. It matthijs@1274: // will be unpaused in the WE_DESTROY event handler. tron@2639: if (_game_mode != GM_MENU && !_networking && _game_mode != GM_EDITOR) { dominik@278: DoCommandP(0, 1, 0, NULL, CMD_PAUSE); tron@2639: } dominik@278: truelight@0: BuildFileList(); truelight@0: truelight@0: ResetObjectToPlace(); truelight@0: } truelight@0: tron@1093: void RedrawAutosave(void) truelight@0: { truelight@0: SetWindowDirty(FindWindowById(WC_STATUS_BAR, 0)); truelight@0: } truelight@0: truelight@0: static const Widget _select_scenario_widgets[] = { peter1138@2725: { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_RIGHT, 7, 11, 256, 0, 13, STR_400E_SELECT_NEW_GAME_TYPE, STR_018C_WINDOW_TITLE_DRAG_THIS}, truelight@867: { WWT_IMGBTN, RESIZE_RIGHT, 7, 0, 256, 14, 25, 0x0, STR_NULL}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 7, 0, 127, 14, 25, STR_SORT_BY_NAME, STR_SORT_ORDER_TIP}, truelight@867: { WWT_PUSHTXTBTN, RESIZE_NONE, 7, 128, 256, 14, 25, STR_SORT_BY_DATE, STR_SORT_ORDER_TIP}, darkvater@893: { WWT_IMGBTN, RESIZE_RB, 7, 0, 244, 26, 319, 0x0, STR_NULL}, truelight@867: { WWT_6, RESIZE_RB, 7, 2, 243, 28, 317, 0x0, STR_400F_SELECT_SCENARIO_GREEN_PRE}, darkvater@893: { WWT_SCROLLBAR, RESIZE_LRB, 7, 245, 256, 26, 307, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, darkvater@893: { WWT_RESIZEBOX, RESIZE_LRTB, 7, 245, 256, 308, 319, 0x0, STR_RESIZE_BUTTON}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: tron@2639: static void SelectScenarioWndProc(Window* w, WindowEvent* e) tron@2639: { truelight@0: const int list_start = 45; tron@2639: tron@2639: switch (e->event) { truelight@0: case WE_PAINT: truelight@0: { truelight@0: int y,pos; truelight@0: const FiosItem *item; truelight@0: truelight@0: if (_savegame_sort_dirty) { truelight@0: _savegame_sort_dirty = false; truelight@0: MakeSortedSaveGameList(); truelight@0: } truelight@193: truelight@0: SetVScrollCount(w, _fios_num); truelight@0: truelight@0: DrawWindowWidgets(w); tron@2526: DoDrawString( tron@2526: _savegame_sort_order & SORT_DESCENDING ? DOWNARROW : UPARROW, tron@2526: _savegame_sort_order & SORT_BY_NAME ? w->widget[3].right - 9 : w->widget[4].right - 9, tron@2526: 15, 16 tron@2526: ); truelight@0: DrawString(4, 32, STR_4010_GENERATE_RANDOM_NEW_GAME, 9); truelight@0: truelight@0: y = list_start; truelight@0: pos = w->vscroll.pos; truelight@0: while (pos < _fios_num) { truelight@0: item = _fios_list + pos; tron@2549: DoDrawString(item->title, 4, y, _fios_colors[item->type]); truelight@0: pos++; tron@2549: y += 10; tron@2549: if (y >= w->vscroll.cap * 10 + list_start) break; truelight@0: } truelight@0: } truelight@0: break; truelight@0: truelight@0: case WE_CLICK: truelight@0: switch(e->click.widget) { truelight@867: case 3: /* Sort scenario names by name */ tron@2526: _savegame_sort_order = (_savegame_sort_order == SORT_BY_NAME) ? tron@2526: SORT_BY_NAME | SORT_DESCENDING : SORT_BY_NAME; truelight@0: _savegame_sort_dirty = true; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: truelight@867: case 4: /* Sort scenario names by date */ tron@2526: _savegame_sort_order = (_savegame_sort_order == SORT_BY_DATE) ? tron@2526: SORT_BY_DATE | SORT_DESCENDING : SORT_BY_DATE; truelight@0: _savegame_sort_dirty = true; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: truelight@867: case 6: /* Click the listbox */ Darkvater@1794: if (e->click.pt.y < list_start) Darkvater@1794: GenRandomNewGame(Random(), InteractiveRandom()); truelight@0: else { truelight@0: char *name; truelight@0: int y = (e->click.pt.y - list_start) / 10; truelight@0: const FiosItem *file; truelight@0: truelight@0: if (y < 0 || (y += w->vscroll.pos) >= w->vscroll.count) truelight@0: return; truelight@0: truelight@0: file = _fios_list + y; truelight@193: tron@2549: name = FiosBrowseTo(file); tron@2549: if (name != NULL) { truelight@0: SetFiosType(file->type); truelight@0: strcpy(_file_to_saveload.name, name); truelight@0: DeleteWindow(w); Darkvater@1796: StartScenarioEditor(Random(), InteractiveRandom()); truelight@0: } truelight@0: } truelight@0: break; truelight@0: } truelight@0: case WE_DESTROY: truelight@0: break; truelight@867: truelight@867: case WE_RESIZE: { truelight@867: /* Widget 3 and 4 have to go with halve speed, make it so obiwan */ truelight@867: uint diff = e->sizing.diff.x / 2; truelight@867: w->widget[3].right += diff; truelight@867: w->widget[4].left += diff; truelight@867: w->widget[4].right += e->sizing.diff.x; truelight@867: truelight@867: w->vscroll.cap += e->sizing.diff.y / 10; truelight@867: } break; truelight@0: } truelight@0: } truelight@0: truelight@543: void SetFiosType(const byte fiostype) truelight@0: { truelight@0: switch (fiostype) { tron@2549: case FIOS_TYPE_FILE: tron@2549: case FIOS_TYPE_SCENARIO: tron@2549: _file_to_saveload.mode = SL_LOAD; tron@2549: break; tron@2549: tron@2549: case FIOS_TYPE_OLDFILE: tron@2549: case FIOS_TYPE_OLD_SCENARIO: tron@2549: _file_to_saveload.mode = SL_OLD_LOAD; tron@2549: break; tron@2549: tron@2549: default: tron@2549: _file_to_saveload.mode = SL_INVALID; tron@2549: break; truelight@0: } truelight@0: } truelight@0: truelight@0: static const WindowDesc _select_scenario_desc = { truelight@0: WDP_CENTER, WDP_CENTER, 257, 320, truelight@0: WC_SAVELOAD,0, truelight@867: WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_STD_BTN | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE, truelight@0: _select_scenario_widgets, truelight@0: SelectScenarioWndProc truelight@0: }; truelight@0: tron@1093: void AskForNewGameToStart(void) truelight@0: { truelight@0: Window *w; truelight@0: truelight@0: DeleteWindowById(WC_QUERY_STRING, 0); truelight@0: DeleteWindowById(WC_SAVELOAD, 0); truelight@0: truelight@0: _saveload_mode = SLD_NEW_GAME; truelight@0: BuildFileList(); truelight@0: truelight@0: w = AllocateWindowDesc(&_select_scenario_desc); truelight@0: w->vscroll.cap = 27; truelight@867: w->resize.step_width = 2; truelight@867: w->resize.step_height = 10; truelight@867: w->resize.height = w->height - 10 * 17; // Minimum of 10 in the list truelight@0: } truelight@0: tron@410: static int32 ClickMoneyCheat(int32 p1, int32 p2) truelight@0: { truelight@0: DoCommandP(0, -10000000, 0, NULL, CMD_MONEY_CHEAT); truelight@0: return true; truelight@0: } truelight@0: truelight@0: // p1 player to set to, p2 is -1 or +1 (down/up) tron@410: static int32 ClickChangePlayerCheat(int32 p1, int32 p2) truelight@0: { tron@2639: while (p1 >= 0 && p1 < MAX_PLAYERS) { tron@2639: if (_players[p1].is_active) { truelight@0: _local_player = p1; dominik@138: MarkWholeScreenDirty(); truelight@0: return _local_player; truelight@0: } truelight@0: p1 += p2; truelight@0: } darkvater@155: darkvater@155: return _local_player; truelight@0: } truelight@0: dominik@100: // p1 -1 or +1 (down/up) tron@1095: static int32 ClickChangeClimateCheat(int32 p1, int32 p2) dominik@100: { tron@2639: if (p1 == -1) p1 = 3; tron@2639: if (p1 == 4) p1 = 0; dominik@100: _opt.landscape = p1; dominik@100: GfxLoadSprites(); dominik@100: MarkWholeScreenDirty(); dominik@100: return _opt.landscape; dominik@100: } dominik@100: tron@1093: extern void EnginesMonthlyLoop(void); dominik@108: dominik@108: // p2 1 (increase) or -1 (decrease) tron@1095: static int32 ClickChangeDateCheat(int32 p1, int32 p2) dominik@108: { dominik@108: YearMonthDay ymd; dominik@108: ConvertDayToYMD(&ymd, _date); dominik@108: tron@2639: if ((ymd.year == 0 && p2 == -1) || (ymd.year == 170 && p2 == 1)) return _cur_year; dominik@108: dominik@108: SetDate(ConvertYMDToDay(_cur_year + p2, ymd.month, ymd.day)); dominik@108: EnginesMonthlyLoop(); dominik@108: SetWindowDirty(FindWindowById(WC_STATUS_BAR, 0)); dominik@108: return _cur_year; dominik@108: } dominik@100: truelight@0: typedef int32 CheckButtonClick(int32, int32); truelight@0: tron@1345: typedef enum ce_type { tron@1345: CE_BOOL = 0, tron@1345: CE_UINT8 = 1, tron@1345: CE_INT16 = 2, tron@1345: CE_UINT16 = 3, tron@1345: CE_INT32 = 4, tron@1345: CE_BYTE = 5, tron@1345: CE_CLICK = 6, tron@1345: } ce_type; tron@1345: truelight@0: typedef struct CheatEntry { tron@1345: ce_type type; // type of selector truelight@0: byte flags; // selector flags truelight@0: StringID str; // string with descriptive text truelight@0: void *variable; // pointer to the variable truelight@0: bool *been_used; // has this cheat been used before? truelight@0: CheckButtonClick *click_proc; // procedure truelight@0: int16 min,max; // range for spinbox setting truelight@0: uint16 step; // step for spinbox truelight@0: } CheatEntry; truelight@0: tron@2631: static int32 ReadCE(const CheatEntry* ce) truelight@0: { tron@2631: switch (ce->type) { tron@2631: case CE_BOOL: return *(bool* )ce->variable; tron@2631: case CE_UINT8: return *(uint8* )ce->variable; tron@2631: case CE_INT16: return *(int16* )ce->variable; tron@2631: case CE_UINT16: return *(uint16*)ce->variable; tron@2631: case CE_INT32: return *(int32* )ce->variable; tron@2631: case CE_BYTE: return *(byte* )ce->variable; tron@2631: case CE_CLICK: return 0; tron@2631: default: NOT_REACHED(); truelight@0: } truelight@193: truelight@0: /* useless, but avoids compiler warning this way */ truelight@0: return 0; truelight@0: } truelight@0: truelight@0: static void WriteCE(const CheatEntry *ce, int32 val) truelight@0: { tron@2631: switch (ce->type) { tron@2631: case CE_BOOL: *(bool* )ce->variable = (bool )val; break; tron@2631: case CE_BYTE: *(byte* )ce->variable = (byte )val; break; tron@2631: case CE_UINT8: *(uint8* )ce->variable = (uint8 )val; break; tron@2631: case CE_INT16: *(int16* )ce->variable = (int16 )val; break; tron@2631: case CE_UINT16: *(uint16*)ce->variable = (uint16)val; break; tron@2631: case CE_INT32: *(int32* )ce->variable = val; break; tron@2631: case CE_CLICK: break; tron@2631: default: NOT_REACHED(); truelight@0: } truelight@0: } truelight@0: truelight@0: truelight@0: static const CheatEntry _cheats_ui[] = { darkvater@179: {CE_CLICK, 0, STR_CHEAT_MONEY, &_cheats.money.value, &_cheats.money.been_used, &ClickMoneyCheat, 0, 0, 0}, darkvater@179: {CE_UINT8, 0, STR_CHEAT_CHANGE_PLAYER, &_local_player, &_cheats.switch_player.been_used, &ClickChangePlayerCheat, 0, 11, 1}, darkvater@179: {CE_BOOL, 0, STR_CHEAT_EXTRA_DYNAMITE, &_cheats.magic_bulldozer.value, &_cheats.magic_bulldozer.been_used, NULL, 0, 0, 0}, darkvater@179: {CE_BOOL, 0, STR_CHEAT_CROSSINGTUNNELS, &_cheats.crossing_tunnels.value,&_cheats.crossing_tunnels.been_used,NULL, 0, 0, 0}, darkvater@179: {CE_BOOL, 0, STR_CHEAT_BUILD_IN_PAUSE, &_cheats.build_in_pause.value, &_cheats.build_in_pause.been_used, NULL, 0, 0, 0}, darkvater@179: {CE_BOOL, 0, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, NULL, 0, 0, 0}, miham@1176: {CE_BOOL, 0, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, NULL, 0, 0, 0}, darkvater@179: {CE_UINT8, 0, STR_CHEAT_SWITCH_CLIMATE, &_opt.landscape, &_cheats.switch_climate.been_used, &ClickChangeClimateCheat,-1, 4, 1}, darkvater@179: {CE_UINT8, 0, STR_CHEAT_CHANGE_DATE, &_cur_year, &_cheats.change_date.been_used, &ClickChangeDateCheat, -1, 1, 1}, truelight@0: }; truelight@0: truelight@0: truelight@0: static const Widget _cheat_widgets[] = { truelight@867: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, truelight@867: { WWT_CAPTION, RESIZE_NONE, 14, 11, 399, 0, 13, STR_CHEATS, STR_018C_WINDOW_TITLE_DRAG_THIS}, miham@1176: { WWT_PANEL, RESIZE_NONE, 14, 0, 399, 14, 159, 0x0, STR_NULL}, miham@1176: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 399, 14, 159, 0x0, STR_CHEATS_TIP}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: extern void DrawPlayerIcon(int p, int x, int y); truelight@0: truelight@0: static void CheatsWndProc(Window *w, WindowEvent *e) truelight@0: { tron@2639: switch (e->event) { truelight@0: case WE_PAINT: { truelight@0: int clk = WP(w,def_d).data_1; truelight@0: int x, y; truelight@0: int i; truelight@0: truelight@0: DrawWindowWidgets(w); truelight@0: truelight@0: DrawStringMultiCenter(200, 25, STR_CHEATS_WARNING, 350); truelight@0: tron@2639: x = 0; tron@2639: y = 45; truelight@0: tron@2639: for (i = 0; i != lengthof(_cheats_ui); i++) { tron@2639: const CheatEntry* ce = &_cheats_ui[i]; tron@2639: tron@2535: DrawSprite((*ce->been_used) ? SPR_BOX_CHECKED : SPR_BOX_EMPTY, x + 5, y + 2); truelight@0: truelight@0: if (ce->type == CE_BOOL) { tron@2639: DrawFrameRect(x + 20, y + 1, x + 30 + 9, y + 9, (*(bool*)ce->variable) ? 6 : 4, (*(bool*)ce->variable) ? FR_LOWERED : 0); tron@534: SetDParam(0, *(bool*)ce->variable ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF); truelight@0: } else if (ce->type == CE_CLICK) { tron@2639: DrawFrameRect(x + 20, y + 1, x + 30 + 9, y + 9, 0, (WP(w,def_d).data_1 == i * 2 + 1) ? FR_LOWERED : 0); tron@2639: if (i == 0) { tron@2639: SetDParam64(0, 10000000); tron@2639: } else { tron@534: SetDParam(0, false); tron@2639: } truelight@0: } else { tron@2639: int32 val; tron@2639: tron@2639: DrawFrameRect(x + 20, y + 1, x + 20 + 9, y + 9, 3, clk == i * 2 + 1 ? FR_LOWERED : 0); tron@2639: DrawFrameRect(x + 30, y + 1, x + 30 + 9, y + 9, 3, clk == i * 2 + 2 ? FR_LOWERED : 0); tron@2639: DrawStringCentered(x + 25, y + 1, STR_6819, 0); tron@2639: DrawStringCentered(x + 35, y + 1, STR_681A, 0); truelight@193: truelight@0: val = ReadCE(ce); dominik@100: dominik@100: // set correct string for switch climate cheat tron@2639: if (ce->str == STR_CHEAT_SWITCH_CLIMATE) val += STR_TEMPERATE_LANDSCAPE; dominik@100: tron@534: SetDParam(0, val); dominik@108: dominik@108: // display date for change date cheat tron@2639: if (ce->str == STR_CHEAT_CHANGE_DATE) SetDParam(0, _date); truelight@193: truelight@0: // draw colored flag for change player cheat tron@2639: if (ce->str == STR_CHEAT_CHANGE_PLAYER) { tron@2639: DrawPlayerIcon(_current_player, 156, y + 2); tron@2639: } truelight@0: } truelight@0: tron@2639: DrawString(50, y + 1, ce->str, 0); truelight@0: tron@2639: y += 12; truelight@0: } truelight@0: break; truelight@0: } tron@2639: truelight@0: case WE_CLICK: { truelight@0: const CheatEntry *ce; truelight@0: uint btn = (e->click.pt.y - 46) / 12; truelight@0: int32 val, oval; truelight@0: uint x = e->click.pt.x; truelight@0: truelight@0: // not clicking a button? tron@2639: if (!IS_INT_INSIDE(x, 20, 40) || btn >= lengthof(_cheats_ui)) break; truelight@0: truelight@0: ce = &_cheats_ui[btn]; truelight@0: oval = val = ReadCE(ce); truelight@0: truelight@0: *ce->been_used = true; truelight@0: tron@2639: switch (ce->type) { truelight@0: case CE_BOOL: { truelight@0: val ^= 1; tron@2639: if (ce->click_proc != NULL) ce->click_proc(val, 0); truelight@0: break; truelight@0: } truelight@0: truelight@0: case CE_CLICK: { truelight@0: ce->click_proc(val, 0); truelight@0: WP(w,def_d).data_1 = btn * 2 + 1; truelight@0: break; truelight@0: } truelight@0: truelight@0: default: { truelight@0: if (x >= 30) { truelight@0: //increase truelight@0: val += ce->step; truelight@0: if (val > ce->max) val = ce->max; truelight@0: } else { truelight@0: // decrease truelight@0: val -= ce->step; truelight@0: if (val < ce->min) val = ce->min; truelight@0: } truelight@0: truelight@0: // take whatever the function returns tron@2639: val = ce->click_proc(val, (x >= 30) ? 1 : -1); truelight@0: tron@2639: if (val != oval) { tron@2639: WP(w,def_d).data_1 = btn * 2 + 1 + ((x >= 30) ? 1 : 0); tron@2639: } truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: if (val != oval) { truelight@0: WriteCE(ce, val); truelight@0: SetWindowDirty(w); truelight@0: } truelight@0: truelight@0: w->flags4 |= 5 << WF_TIMEOUT_SHL; truelight@0: truelight@0: SetWindowDirty(w); truelight@0: } truelight@0: break; truelight@0: case WE_TIMEOUT: truelight@0: WP(w,def_d).data_1 = 0; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@193: } truelight@0: } tron@2639: truelight@0: static const WindowDesc _cheats_desc = { miham@1176: 240, 22, 400, 160, truelight@0: WC_CHEATS,0, truelight@0: WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, truelight@0: _cheat_widgets, truelight@0: CheatsWndProc truelight@0: }; truelight@0: truelight@0: tron@1093: void ShowCheatWindow(void) truelight@0: { truelight@0: Window *w; truelight@193: truelight@0: DeleteWindowById(WC_CHEATS, 0); truelight@0: w = AllocateWindowDesc(&_cheats_desc); truelight@0: tron@2549: if (w != NULL) SetWindowDirty(w); truelight@0: }