truelight@0: #include "stdafx.h" truelight@0: #include "ttd.h" tron@507: #include "table/strings.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" truelight@0: truelight@543: #include "hal.h" // for file list truelight@0: truelight@0: bool _query_string_active; truelight@0: truelight@596: /* Now this is what I call dirty.. the edit-box needs to be rewritten! */ truelight@596: static bool _do_edit_on_text_even_when_no_change_to_edit_box; truelight@596: truelight@0: typedef struct LandInfoData { truelight@0: Town *town; truelight@0: int32 costclear; truelight@0: AcceptedCargo ac; truelight@0: uint tile; truelight@0: TileDesc td; truelight@0: } LandInfoData; truelight@0: truelight@0: static void LandInfoWndProc(Window *w, WindowEvent *e) truelight@0: { truelight@0: LandInfoData *lid; truelight@0: StringID str; truelight@0: truelight@0: if (e->event == WE_PAINT) { tron@534: int idx = 0; 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; truelight@0: if (lid->costclear != CMD_ERROR) { 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: pasky@485: snprintf(_userstring, USERSTRING_LEN, "%.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) { tron@534: SetDParam(0, lid->town->townnametype); tron@534: SetDParam(1, lid->town->townnameparts); truelight@0: } truelight@0: DrawStringCentered(140,60, STR_01A8_LOCAL_AUTHORITY, 0); truelight@0: truelight@0: str = STR_01CE_CARGO_ACCEPTED - 1; truelight@0: tron@473: /* XXX if a tile accepts more cargo types than there are template strings tron@473: * this breaks */ tron@473: for (i = 0; i < NUM_CARGO; ++i) { tron@473: if (lid->ac[i] > 0) { tron@473: if (lid->ac[i] < 8) { tron@534: SetDParam(idx++, STR_01D1_8); tron@534: SetDParam(idx++, lid->ac[i]); tron@473: } tron@534: SetDParam(idx++, _cargoc.names_s[i]); tron@473: str++; truelight@0: } truelight@0: } truelight@0: truelight@0: if (str != (STR_01CE_CARGO_ACCEPTED - 1)) truelight@0: DrawStringMultiCenter(140, 76, str, 276); 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[] = { truelight@867: { WWT_TEXTBTN, 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: truelight@0: static void Place_LandInfo(uint 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: darkvater@3: if (_local_player >= MAX_PLAYERS) darkvater@3: p = DEREF_PLAYER(0); darkvater@3: else truelight@0: p = DEREF_PLAYER(_local_player); 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@65: #if defined(_DEBUG) tron@926: DEBUG(misc, 0) ("TILE: %#x (%i,%i)", tile, TileX(tile), TileY(tile)); darkvater@147: DEBUG(misc, 0) ("TILE: %d ", tile); darkvater@65: DEBUG(misc, 0) ("_map_type_and_height=%#x", _map_type_and_height[tile]); darkvater@65: DEBUG(misc, 0) ("_map2=%#x", _map2[tile]); darkvater@65: DEBUG(misc, 0) ("_map3_lo=%#x", _map3_lo[tile]); darkvater@65: DEBUG(misc, 0) ("_map3_hi=%#x", _map3_hi[tile]); darkvater@65: DEBUG(misc, 0) ("_map5=%#x", _map5[tile]); darkvater@65: DEBUG(misc, 0) ("_map_owner=%#x", _map_owner[tile]); darkvater@65: #endif truelight@0: } truelight@0: tron@1093: void PlaceLandBlockInfo(void) truelight@0: { truelight@0: if (_cursor.sprite == 0x2CF) { truelight@0: ResetObjectToPlace(); truelight@0: } else { truelight@0: _place_proc = Place_LandInfo; truelight@0: SetObjectToPlace(0x2CF, 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@859: "The OpenTTD team:", darkvater@859: " Dominik Scherer (dominik81) - Lead coder", darkvater@859: " Tamas Farago (Darkvater) - Lead coder", darkvater@859: " Patric Stout (TrueLight) - Coder, network guru, SVN- and website host", darkvater@859: " Owen Rudge (orudge) - Forum- and masterserver host, OS/2 port", darkvater@859: " Bjarni Corfitzen (Bjarni) - MacOS port", darkvater@859: " Kerekes Miham (MiHaMiX) - Translator system, and Nightlies host", darkvater@859: " Cian Duffy (MYOB) - BeOS port / manual writing", darkvater@859: " Christian Rosentreter (tokaiz) - MorphOS / AmigaOS port", darkvater@859: " 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@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", darkvater@859: " Tron - Many patches, suggestions and relentless correcting of the code", darkvater@859: " Celestar - For his many patches, suggestions and fixes", darkvater@859: " blathijs - For his many patches, suggestions and code documentation", darkvater@859: " pasky - Many patches, newgrf support", darkvater@859: " Stefan Meißner (sign_de) - For his work on the console", 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: NULL, darkvater@859: "", darkvater@859: "", darkvater@859: "And finally:", darkvater@859: " Chris Sawyer - For an amazing game!" darkvater@859: }; truelight@0: truelight@0: static void AboutWindowProc(Window *w, WindowEvent *e) truelight@0: { truelight@0: 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: { darkvater@859: const char *str; darkvater@859: char buffer[100]; 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@859: DrawStringCentered(200, 17, STR_00B6_ORIGINAL_COPYRIGHT, 0); darkvater@859: DrawStringCentered(200, 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@859: str = credits[i]; darkvater@859: /* Hack-Alert: Translated by is a dynamic string as it changes darkvater@859: * with the language chosen. So the special value of NULL is used darkvater@859: * to identify this for the moment */ darkvater@859: if (str == NULL) { darkvater@859: GetString(buffer, STR_TRANSLATED_BY); darkvater@859: str = buffer; darkvater@859: } darkvater@859: darkvater@859: DoDrawString(str, 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@859: DrawStringMultiCenter(200, w->height - 15, STR_00BA_COPYRIGHT_OPENTTD, 398); 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[] = { truelight@867: { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_NULL}, truelight@867: { WWT_CAPTION, RESIZE_NONE, 14, 11, 399, 0, 13, STR_015B_OPENTTD, STR_NULL}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 0, 399, 14, 271, 0x0, STR_NULL}, tron@910: { WWT_FRAME, RESIZE_NONE, 14, 5, 394, 40, 245, STR_NULL, STR_NULL}, darkvater@176: { WIDGETS_END}, truelight@0: }; truelight@0: truelight@0: static const WindowDesc _about_desc = { truelight@0: WDP_CENTER, WDP_CENTER, 400, 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 byte _tree_base_by_landscape[4] = {0, 12, 20, 32}; truelight@0: static const byte _tree_count_by_landscape[4] = {12, 8, 12, 9}; 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, truelight@0: 0x79E,0x30D87A5,0x30B87AC,0x7B3,0x7BA,0x30B87C1,0x30887C8,0x30A87CF,0x30B87D6 truelight@0: }; truelight@0: truelight@0: static void BuildTreesWndProc(Window *w, WindowEvent *e) truelight@0: { truelight@0: 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)) { truelight@0: x -= 35*4; truelight@0: y += 47; truelight@0: } truelight@0: } while (--count); truelight@0: } break; truelight@0: truelight@0: case WE_CLICK: { truelight@0: int wid; truelight@0: truelight@0: switch(wid=e->click.widget) { truelight@0: case 0: truelight@0: ResetObjectToPlace(); truelight@0: return; 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: truelight@0: if ( (uint)(wid-3) >= (uint)WP(w,tree_d).count) truelight@0: return; truelight@193: truelight@0: if (HandlePlacePushButton(w, wid, 0x7DA, 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. truelight@0: if (HandlePlacePushButton(w, 15, 0x7DA, 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}, truelight@867: { WWT_CLOSEBOX, 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}, truelight@867: { WWT_CLOSEBOX, RESIZE_NONE, 14, 2, 140, 157, 168, STR_TREES_RANDOM_TYPE, STR_TREES_RANDOM_TYPE_TIP}, truelight@867: { WWT_CLOSEBOX, 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: { truelight@0: AllocateWindowDesc(&_build_trees_desc); 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[] = { truelight@867: { WWT_CLOSEBOX, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL}, 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[] = { truelight@867: { WWT_CLOSEBOX, RESIZE_NONE, 4, 0, 10, 0, 13, STR_00C5, STR_NULL}, 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: { truelight@0: 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@534: Player *p = DEREF_PLAYER(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: truelight@0: if (_right_button_down) truelight@0: DeleteWindow(w); truelight@0: break; truelight@0: case WE_4: truelight@0: if (!--_errmsg_duration) truelight@0: DeleteWindow(w); truelight@0: break; truelight@0: case WE_DESTROY: { truelight@0: TileHighlightData *thd = _thd_ptr; truelight@0: TileIndex tile = thd->redsq; truelight@0: thd->redsq = 0; darkvater@172: _switch_mode_errorstr = INVALID_STRING_ID; truelight@0: if (tile != 0) truelight@0: MarkTileDirtyByTile(tile); truelight@0: break; truelight@0: } 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: { truelight@0: int 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); truelight@0: ShowErrorMessage(-1, msg, x, y); truelight@0: } truelight@0: truelight@0: void ShowCostOrIncomeAnimation(int x, int y, int z, int32 cost) truelight@0: { truelight@0: int 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: truelight@0: static 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: { truelight@0: truelight@0: switch(e->event) { truelight@0: case WE_PAINT: { truelight@193: GfxFillRect(0, 0, w->width - 1, w->height - 1, 0); truelight@0: GfxFillRect(1, 1, w->width - 2, w->height - 2, 0x44); truelight@0: DrawStringMultiCenter((w->width>>1), (w->height>>1)-5, WP(w,tooltips_d).string_id, 197); truelight@0: break; truelight@0: } truelight@0: case WE_MOUSELOOP: truelight@0: if (!_right_button_down) truelight@0: DeleteWindow(w); truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: void GuiShowTooltips(StringID string_id) truelight@0: { truelight@0: Window *w; truelight@0: int right,bottom; truelight@0: int x,y; truelight@193: truelight@0: if (string_id == 0) truelight@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: truelight@0: GetString(str_buffr, string_id); truelight@0: assert(strlen(str_buffr) < sizeof(str_buffr) - 1); truelight@0: truelight@0: right = GetStringWidth(str_buffr) + 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: _tooltips_widgets[0].right = right; truelight@0: _tooltips_widgets[0].bottom = bottom; 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; truelight@0: } truelight@0: truelight@0: truelight@0: static void DrawStationCoverageText(const uint *accepts, int str_x, int str_y, uint mask) truelight@0: { truelight@0: int i; truelight@0: byte *b; truelight@193: truelight@0: b = _userstring; truelight@0: b[0] = 0x81; truelight@0: b[1] = STR_000D_ACCEPTS; truelight@0: b[2] = STR_000D_ACCEPTS >> 8; truelight@0: b += 3; truelight@0: truelight@0: for(i=0; i!=NUM_CARGO; i++,mask>>=1) { truelight@0: if (accepts[i] >= 8 && (mask&1) ) { truelight@0: StringID id = _cargoc.names_s[i]; truelight@0: b[0] = 0x81; truelight@0: b[1] = (byte)(id & 255); truelight@0: b[2] = (byte)(id >> 8); truelight@0: b[3] = ','; truelight@0: b[4] = ' '; truelight@0: b += 5; truelight@0: } truelight@0: } truelight@0: truelight@0: if (b == (byte*)&_userstring[3]) { truelight@0: b[0] = 0x81; truelight@0: b[1] = STR_00D0_NOTHING; truelight@0: b[2] = STR_00D0_NOTHING >> 8; truelight@0: b[3] = 0; truelight@0: } else { truelight@0: 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) { truelight@0: int x = _thd.pos.x; truelight@0: int y = _thd.pos.y; truelight@0: uint accepts[NUM_CARGO]; truelight@0: if (x != -1) { darkvater@980: GetAcceptanceAroundTiles(accepts, TILE_FROM_XY(x, y), _thd.size.x /16, _thd.size.y /16 , rad); truelight@0: DrawStationCoverageText(accepts, sx, sy, mask); truelight@0: } truelight@0: } truelight@0: truelight@0: void CheckRedrawStationCoverage(Window *w) truelight@0: { truelight@0: if (_thd.dirty&1) { truelight@0: _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 { truelight@0: if (x&1) InvalidateWidget(w,i); truelight@0: } while(i++,x>>=1); truelight@0: } truelight@0: truelight@0: truelight@0: void UnclickWindowButtons(Window *w) truelight@0: { darkvater@755: bool sticky = false; darkvater@755: if (w->desc_flags & WDF_STICKY_BUTTON && HASBIT(w->click_state, 2)) sticky = true; darkvater@755: truelight@0: UnclickSomeWindowButtons(w, (uint32)-1); darkvater@755: darkvater@755: if (sticky) SETBIT(w->click_state, 2); 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@911: /* Get the count of characters in the string as well as the width in pixels darkvater@911: * [IN]buf: string to be checked darkvater@911: * [OUT]count: gets set to the count of characters darkvater@911: * [OUT]width: gets set to the pixels width */ darkvater@911: static void GetCurrentStringSize(const byte *buf, int *count, int *width) darkvater@911: { darkvater@911: *count = 0; darkvater@911: *width = -1; darkvater@911: darkvater@911: do { darkvater@911: if (*++buf == 0) darkvater@911: break; darkvater@911: (*count)++; darkvater@911: (*width) += _stringwidth_table[*buf - 32]; darkvater@911: } while (1); darkvater@911: } darkvater@911: truelight@0: int HandleEditBoxKey(Window *w, int wid, WindowEvent *we) truelight@0: { truelight@0: int width,count; truelight@0: int key = we->keypress.ascii; truelight@0: truelight@0: we->keypress.cont = false; truelight@0: truelight@0: if (we->keypress.keycode == WKC_ESC) { truelight@0: return 2; truelight@0: } else if (we->keypress.keycode == WKC_RETURN) { truelight@0: return 1; darkvater@911: #ifdef WIN32 darkvater@911: } else if (we->keypress.keycode == (WKC_CTRL | 'V')) { darkvater@911: if (IsClipboardFormatAvailable(CF_TEXT)) { darkvater@911: const byte* data; darkvater@911: HGLOBAL cbuf; darkvater@911: darkvater@911: OpenClipboard(NULL); darkvater@911: cbuf = GetClipboardData(CF_TEXT); darkvater@911: data = GlobalLock(cbuf); // clipboard data darkvater@911: darkvater@911: GetCurrentStringSize(WP(w,querystr_d).buf - 1, &count, &width); darkvater@911: darkvater@911: /* IS_INT_INSIDE = filter for ascii-function codes like BELL and so on [we need an special filter here later] */ darkvater@911: for (; (IS_INT_INSIDE(*data, ' ', 256)) && // valid ASCII char darkvater@911: (count < WP(w,querystr_d).maxlen - 1 && // max charcount; always allow for terminating '\0' darkvater@911: width + _stringwidth_table[(int)(*data) - 32] <= WP(w,querystr_d).maxwidth); ++data) { // max screensize darkvater@911: darkvater@911: // append data and update size parameters darkvater@911: WP(w,querystr_d).buf[count] = *data; darkvater@911: count++; darkvater@911: width += _stringwidth_table[*data - 32]; darkvater@911: } darkvater@911: WP(w,querystr_d).buf[count + 1] = '\0'; darkvater@911: darkvater@911: GlobalUnlock(cbuf); darkvater@911: CloseClipboard(); darkvater@911: InvalidateWidget(w, wid); darkvater@911: } darkvater@911: #endif truelight@0: } else { darkvater@911: GetCurrentStringSize(WP(w,querystr_d).buf - 1, &count, &width); truelight@193: truelight@0: if (we->keypress.keycode == WKC_BACKSPACE) { truelight@0: if (count != 0) { truelight@0: WP(w,querystr_d).buf[count-1] = 0; truelight@0: InvalidateWidget(w, wid); truelight@0: } truelight@0: } else if (IS_INT_INSIDE((key = we->keypress.ascii), 32, 256)) { darkvater@911: if (count < WP(w,querystr_d).maxlen && width + _stringwidth_table[key - 32] <= WP(w,querystr_d).maxwidth) { truelight@0: WP(w,querystr_d).buf[count] = key; darkvater@911: WP(w,querystr_d).buf[count + 1] = '\0'; truelight@0: InvalidateWidget(w, wid); truelight@0: } 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: truelight@0: void HandleEditBox(Window *w, int wid) truelight@0: { truelight@0: bool b; truelight@0: truelight@0: /* caret changed? */ truelight@0: b = !!(_caret_timer & 0x20); truelight@0: if (b != WP(w,querystr_d).caret) { truelight@0: WP(w,querystr_d).caret = b; truelight@0: InvalidateWidget(w, wid); truelight@0: } truelight@0: } truelight@0: truelight@0: void DrawEditBox(Window *w, int wid) truelight@0: { truelight@0: const Widget *wi = w->widget + wid; truelight@0: int x; truelight@0: truelight@0: GfxFillRect(wi->left+1, wi->top+1, wi->right-1, wi->bottom-1, 215); truelight@0: x = DoDrawString(WP(w,querystr_d).buf, wi->left+2, wi->top+1, 8); truelight@0: if (WP(w,querystr_d).caret) truelight@0: DoDrawString("_", x, wi->top+1, 12); truelight@0: } truelight@0: truelight@0: truelight@0: #define MAX_QUERYSTR_LEN 64 truelight@0: truelight@0: static void QueryStringWndProc(Window *w, WindowEvent *e) truelight@0: { truelight@543: static bool closed = false; truelight@0: switch(e->event) { truelight@0: case WE_PAINT: { truelight@0: // int x; truelight@0: tron@534: SetDParam(0, WP(w,querystr_d).caption); truelight@0: DrawWindowWidgets(w); truelight@0: truelight@0: DrawEditBox(w, 5); truelight@0: } 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:; truelight@596: if (str_eq(WP(w,querystr_d).buf, WP(w,querystr_d).buf + MAX_QUERYSTR_LEN) && !_do_edit_on_text_even_when_no_change_to_edit_box) { truelight@0: DeleteWindow(w); truelight@0: } else { truelight@0: byte *buf = WP(w,querystr_d).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: } truelight@0: HandleEditBox(w, 5); truelight@0: } break; truelight@0: truelight@0: case WE_KEYPRESS: { truelight@0: switch(HandleEditBoxKey(w, 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@543: case WE_CREATE: truelight@543: closed = false; truelight@543: break; truelight@543: 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: } truelight@0: _query_string_active = false; truelight@0: break; truelight@0: } truelight@0: } truelight@0: truelight@0: static const Widget _query_string_widgets[] = { truelight@867: { WWT_TEXTBTN, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_NULL}, 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: truelight@0: static byte _edit_str_buf[MAX_QUERYSTR_LEN*2]; truelight@0: truelight@0: void ShowQueryString(StringID str, StringID caption, int maxlen, int maxwidth, byte window_class, uint16 window_number) truelight@0: { truelight@0: Window *w; truelight@0: truelight@0: #define _orig_edit_str_buf (_edit_str_buf+MAX_QUERYSTR_LEN) truelight@0: truelight@0: DeleteWindowById(WC_QUERY_STRING, 0); truelight@0: DeleteWindowById(WC_SAVELOAD, 0); truelight@0: truelight@0: if (str == 0xFFFF) { truelight@0: memcpy(_orig_edit_str_buf, str_buffr, MAX_QUERYSTR_LEN); truelight@0: } else { truelight@0: GetString(_orig_edit_str_buf, str); truelight@0: } truelight@596: truelight@596: if (maxlen & 0x1000) { truelight@596: _do_edit_on_text_even_when_no_change_to_edit_box = true; truelight@596: maxlen &= ~0x1000; truelight@596: } else truelight@596: _do_edit_on_text_even_when_no_change_to_edit_box = false; truelight@596: truelight@0: _orig_edit_str_buf[maxlen] = 0; truelight@0: truelight@0: memcpy(_edit_str_buf, _orig_edit_str_buf, MAX_QUERYSTR_LEN); truelight@0: truelight@0: w = AllocateWindowDesc(&_query_string_desc); truelight@0: truelight@0: w->click_state = 1 << 5; truelight@0: WP(w,querystr_d).caption = caption; truelight@0: WP(w,querystr_d).wnd_class = window_class; truelight@0: WP(w,querystr_d).wnd_num = window_number; truelight@0: WP(w,querystr_d).caret = 0; truelight@0: WP(w,querystr_d).maxlen = maxlen; truelight@0: WP(w,querystr_d).maxwidth = maxwidth; truelight@0: WP(w,querystr_d).buf = _edit_str_buf; truelight@0: truelight@0: _query_string_active = true; truelight@0: } truelight@0: truelight@0: static const Widget _load_dialog_1_widgets[] = { truelight@867: { WWT_TEXTBTN, 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}, truelight@867: { WWT_6, RESIZE_RB, 14, 2, 243, 50, 291, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, darkvater@893: { WWT_SCROLLBAR, RESIZE_LRB, 14, 245, 256, 48, 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[] = { truelight@867: { WWT_TEXTBTN, 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}, truelight@867: { WWT_6, RESIZE_RB, 14, 2, 243, 50, 291, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, darkvater@893: { WWT_SCROLLBAR, RESIZE_LRB, 14, 245, 256, 48, 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[] = { truelight@867: { WWT_TEXTBTN, 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}, truelight@867: { WWT_6, RESIZE_RB, 14, 2, 243, 50, 290, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, darkvater@893: { WWT_SCROLLBAR, RESIZE_LRB, 14, 245, 256, 48, 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[] = { truelight@867: { WWT_TEXTBTN, 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}, truelight@867: { WWT_6, RESIZE_RB, 14, 2, 243, 50, 290, 0x0, STR_400A_LIST_OF_DRIVES_DIRECTORIES}, darkvater@893: { WWT_SCROLLBAR, RESIZE_LRB, 14, 245, 256, 48, 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: tron@1093: void BuildFileList(void) truelight@0: { truelight@0: FiosFreeSavegameList(); truelight@0: if(_saveload_mode==SLD_NEW_GAME || _saveload_mode==SLD_LOAD_SCENARIO || _saveload_mode==SLD_SAVE_SCENARIO) truelight@0: _fios_list = FiosGetScenarioList(&_fios_num, _saveload_mode); truelight@0: else truelight@0: _fios_list = FiosGetSavegameList(&_fios_num, _saveload_mode); truelight@0: } truelight@0: tron@1093: static void DrawFiosTexts(void) truelight@0: { darkvater@222: const char *path; truelight@0: StringID str; truelight@0: truelight@0: str = FiosGetDescText(&path); truelight@0: if (str != 0) truelight@0: DrawString(2, 37, str, 0); truelight@0: DoDrawString(path, 2, 27, 16); truelight@0: } truelight@0: truelight@0: #if defined(_WIN32) truelight@0: extern int CDECL compare_FiosItems (const void *a, const void *b); truelight@0: #else truelight@0: extern int compare_FiosItems (const void *a, const void *b); truelight@0: #endif truelight@0: truelight@0: tron@1093: static void MakeSortedSaveGameList(void) truelight@0: { 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: */ truelight@0: truelight@0: int i, sort_start, sort_end, s_amount; truelight@0: i = sort_start = sort_end = 0; truelight@0: truelight@0: while (i < _fios_num) { truelight@0: if (_fios_list[i].type == FIOS_TYPE_DIR || _fios_list[i].type == FIOS_TYPE_PARENT) truelight@0: sort_start++; truelight@0: truelight@0: if (_fios_list[i].type == FIOS_TYPE_DRIVE) truelight@0: sort_end++; truelight@0: truelight@0: i++; 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: const Player *p; 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. */ truelight@635: if (_local_player < MAX_PLAYERS) truelight@635: p = DEREF_PLAYER(_local_player); truelight@635: else truelight@635: p = DEREF_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: truelight@0: static void SaveLoadDlgWndProc(Window *w, WindowEvent *e) truelight@0: { truelight@0: switch(e->event) { 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); truelight@0: DrawFiosTexts(); truelight@0: truelight@0: if (_savegame_sort_dirty) { truelight@0: _savegame_sort_dirty = false; truelight@0: MakeSortedSaveGameList(); truelight@0: } truelight@0: truelight@867: GfxFillRect(w->widget[6].left + 1, w->widget[6].top + 1, w->widget[6].right, w->widget[6].bottom, 0xD7); truelight@867: DoDrawString(_savegame_sort_order & 1 ? "\xAA" : "\xA0", _savegame_sort_order <= 1 ? w->widget[3].right - 9 : w->widget[2].right - 9, 15, 0x10); truelight@0: truelight@867: y = w->widget[6].top + 1; truelight@0: pos = w->vscroll.pos; truelight@0: while (pos < _fios_num) { truelight@0: item = _fios_list + pos; truelight@0: DoDrawString(item->title[0] ? item->title : item->name, 4, y, _fios_colors[item->type] ); truelight@0: pos++; truelight@0: y+=10; truelight@867: if (y >= w->vscroll.cap*10+w->widget[6].top+1) truelight@0: break; truelight@0: } truelight@0: truelight@0: if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) { truelight@0: DrawEditBox(w, 9); truelight@0: } truelight@0: break; truelight@0: } truelight@0: case WE_CLICK: truelight@0: switch(e->click.widget) { truelight@0: case 2: /* Sort save names by name */ truelight@0: _savegame_sort_order = (_savegame_sort_order == 2) ? 3 : 2; truelight@0: _savegame_sort_dirty = true; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: truelight@0: case 3: /* Sort save names by date */ truelight@0: _savegame_sort_order = (_savegame_sort_order == 0) ? 1 : 0; truelight@0: _savegame_sort_dirty = true; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: truelight@0: case 6: { /* Click the listbox */ truelight@867: int y = (e->click.pt.y - w->widget[6].top - 1) / 10; truelight@0: char *name; 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: truelight@0: if ((name = FiosBrowseTo(file)) != NULL) { truelight@0: if (_saveload_mode == SLD_LOAD_GAME) { truelight@0: _switch_mode = SM_LOAD; truelight@0: SetFiosType(file->type); truelight@0: strcpy(_file_to_saveload.name, name); truelight@0: DeleteWindow(w); truelight@0: } else if (_saveload_mode == SLD_LOAD_SCENARIO) { truelight@0: _switch_mode = SM_LOAD_SCENARIO; truelight@0: SetFiosType(file->type); truelight@0: strcpy(_file_to_saveload.name, name); truelight@0: DeleteWindow(w); truelight@0: } else { truelight@0: // SLD_SAVE_GAME, SLD_SAVE_SCENARIO copy clicked name to editbox truelight@0: strcpy(WP(w,querystr_d).buf, file->title[0] ? file->title : file->name); truelight@0: InvalidateWidget(w, 9); 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: } truelight@0: case 10: case 11: /* Delete, Save game */ truelight@0: break; truelight@0: } truelight@0: break; truelight@0: case WE_MOUSELOOP: truelight@0: HandleEditBox(w, 9); truelight@0: break; truelight@0: case WE_KEYPRESS: truelight@0: switch (HandleEditBoxKey(w, 9, e)) { truelight@0: case 1: truelight@0: HandleButtonClick(w, 11); truelight@0: break; truelight@0: } truelight@0: break; truelight@0: case WE_TIMEOUT: truelight@0: if (HASBIT(w->click_state, 10)) { /* Delete button clicked */ truelight@0: FiosDelete(WP(w,querystr_d).buf); truelight@0: SetWindowDirty(w); truelight@0: BuildFileList(); tron@402: if (_saveload_mode == SLD_SAVE_GAME) tron@402: GenerateFileName(); /* Reset file name to current date */ truelight@0: } else if (HASBIT(w->click_state, 11)) { /* Save button clicked */ truelight@0: _switch_mode = SM_SAVE; truelight@0: FiosMakeSavegameName(_file_to_saveload.name, WP(w,querystr_d).buf); truelight@0: } truelight@0: break; truelight@0: case WE_DESTROY: dominik@278: // pause is only used in single-player, non-editor mode dominik@278: if(!_networking && (_game_mode != GM_EDITOR)) dominik@278: DoCommandP(0, 0, 0, NULL, CMD_PAUSE); truelight@0: _query_string_active = false; truelight@0: FiosFreeSavegameList(); 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: truelight@867: /* Same for widget 10 and 11 in save-dialog */ truelight@867: if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) { truelight@867: w->widget[10].right += diff; truelight@867: w->widget[11].left += diff; truelight@867: w->widget[11].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: truelight@0: SetObjectToPlace(1, 0, 0, 0); truelight@0: DeleteWindowById(WC_QUERY_STRING, 0); truelight@0: DeleteWindowById(WC_SAVELOAD, 0); truelight@0: truelight@0: _saveload_mode = mode; 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 truelight@0: w->click_state |= (1 << 6); truelight@0: WP(w,querystr_d).caret = 0; truelight@0: WP(w,querystr_d).maxlen = MAX_QUERYSTR_LEN; truelight@0: WP(w,querystr_d).maxwidth = 240; truelight@0: WP(w,querystr_d).buf = _edit_str_buf; truelight@0: truelight@0: if (mode == SLD_SAVE_GAME) { tron@402: GenerateFileName(); truelight@0: } else if (mode == SLD_SAVE_SCENARIO) { truelight@0: strcpy(_edit_str_buf, "UNNAMED"); truelight@0: } truelight@0: dominik@278: // pause is only used in single-player, non-editor mode truelight@543: if(_game_mode != GM_MENU && !_networking && _game_mode != GM_EDITOR) dominik@278: DoCommandP(0, 1, 0, NULL, CMD_PAUSE); 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[] = { truelight@867: { WWT_TEXTBTN, 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: truelight@0: static void SelectScenarioWndProc(Window *w, WindowEvent *e) { truelight@0: const int list_start = 45; truelight@0: 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); truelight@867: DoDrawString(_savegame_sort_order & 1 ? "\xAA" : "\xA0", _savegame_sort_order <= 1 ? w->widget[4].right - 9 : w->widget[3].right - 9, 15, 0x10); 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; truelight@0: DoDrawString(item->title[0] ? item->title : item->name, 4, y, _fios_colors[item->type] ); truelight@0: pos++; truelight@0: y+=10; truelight@0: if (y >= w->vscroll.cap*10+list_start) truelight@0: 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 */ truelight@0: _savegame_sort_order = (_savegame_sort_order == 2) ? 3 : 2; truelight@0: _savegame_sort_dirty = true; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: truelight@867: case 4: /* Sort scenario names by date */ truelight@0: _savegame_sort_order = (_savegame_sort_order == 0) ? 1 : 0; truelight@0: _savegame_sort_dirty = true; truelight@0: SetWindowDirty(w); truelight@0: break; truelight@0: truelight@867: case 6: /* Click the listbox */ truelight@0: if(e->click.pt.y < list_start) truelight@0: DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_GEN_RANDOM_NEW_GAME); 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: truelight@0: if ((name = FiosBrowseTo(file)) != NULL) { truelight@0: SetFiosType(file->type); truelight@0: strcpy(_file_to_saveload.name, name); truelight@0: DeleteWindow(w); truelight@0: DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_START_SCENARIO); 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) { truelight@0: case FIOS_TYPE_FILE: case FIOS_TYPE_SCENARIO: truelight@0: _file_to_saveload.mode = SL_LOAD; truelight@0: break; truelight@0: case FIOS_TYPE_OLDFILE: case FIOS_TYPE_OLD_SCENARIO: truelight@0: _file_to_saveload.mode = SL_OLD_LOAD; truelight@0: break; truelight@0: default: truelight@0: _file_to_saveload.mode = SL_INVALID; 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: { darkvater@155: while(p1 >= 0 && p1 < MAX_PLAYERS) { darkvater@155: 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: { dominik@104: if(p1==-1) p1 = 3; dominik@104: 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: dominik@108: 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: truelight@0: typedef struct CheatEntry { truelight@0: byte 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: truelight@0: enum { truelight@0: CE_BOOL = 0, truelight@0: CE_UINT8 = 1, truelight@0: CE_INT16 = 2, truelight@0: CE_UINT16 = 3, truelight@0: CE_INT32 = 4, truelight@0: CE_BYTE = 5, truelight@0: CE_CLICK = 6, truelight@0: truelight@0: CF_0ISDIS = 1, truelight@0: CF_NOCOMMA = 2, truelight@0: }; truelight@0: truelight@0: static int32 ReadCE(const CheatEntry*ce) truelight@0: { truelight@0: switch(ce->type) { truelight@0: case CE_BOOL: return *(bool*)ce->variable; truelight@0: case CE_UINT8: return *(uint8*)ce->variable; truelight@0: case CE_INT16: return *(int16*)ce->variable; truelight@0: case CE_UINT16: return *(uint16*)ce->variable; truelight@0: case CE_INT32: return *(int32*)ce->variable; truelight@0: case CE_BYTE: return *(byte*)ce->variable; truelight@0: case CE_CLICK: return 0; truelight@0: default: truelight@0: 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: { truelight@0: switch(ce->type) { truelight@0: case CE_BOOL: *(bool*)ce->variable = (bool)val; break; truelight@0: case CE_BYTE: *(byte*)ce->variable = (byte)val; break; truelight@0: case CE_UINT8: *(uint8*)ce->variable = (uint8)val; break; truelight@0: case CE_INT16: *(int16*)ce->variable = (int16)val; break; truelight@0: case CE_UINT16: *(uint16*)ce->variable = (uint16)val; break; truelight@0: case CE_INT32: *(int32*)ce->variable = val; break; truelight@0: case CE_CLICK: break; truelight@0: default: truelight@0: 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}, 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}, truelight@867: { WWT_PANEL, RESIZE_NONE, 14, 0, 399, 14, 147, 0x0, STR_NULL}, truelight@867: { WWT_IMGBTN, RESIZE_NONE, 14, 0, 399, 14, 147, 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: { truelight@0: switch(e->event) { truelight@0: case WE_PAINT: { truelight@0: int clk = WP(w,def_d).data_1; truelight@0: const CheatEntry *ce = &_cheats_ui[0]; truelight@0: int32 val; 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: truelight@0: x=0; truelight@0: y=45; truelight@0: truelight@0: for(i=0; i!=lengthof(_cheats_ui); i++,ce++) { truelight@0: truelight@0: DrawSprite((SPR_OPENTTD_BASE + ((*ce->been_used)?67:66)), x+5, y+2); truelight@0: truelight@0: if (ce->type == CE_BOOL) { truelight@0: DrawFrameRect(x+20, y+1, x+30+9, y+9, (*(bool*)ce->variable)?6:4, (*(bool*)ce->variable)?0x20:0); tron@534: SetDParam(0, *(bool*)ce->variable ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF); truelight@0: truelight@0: } else if (ce->type == CE_CLICK) { truelight@0: DrawFrameRect(x+20, y+1, x+30+9, y+9, 0, (WP(w,def_d).data_1==i*2+1)?0x20:0x00); truelight@0: if(i==0) tron@534: SetDParam64(0, (int64) 10000000); truelight@0: else tron@534: SetDParam(0, false); truelight@0: truelight@0: } else { truelight@0: DrawFrameRect(x+20, y+1, x+20+9, y+9, 3, clk == i*2+1 ? 0x20 : 0); truelight@0: DrawFrameRect(x+30, y+1, x+30+9, y+9, 3, clk == i*2+2 ? 0x20 : 0); truelight@0: DrawStringCentered(x+25, y+1, STR_6819, 0); truelight@0: 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 dominik@100: if(ce->str==STR_CHEAT_SWITCH_CLIMATE) dominik@100: val += STR_TEMPERATE_LANDSCAPE; dominik@100: tron@534: SetDParam(0, val); dominik@108: dominik@108: // display date for change date cheat dominik@108: if(ce->str==STR_CHEAT_CHANGE_DATE) tron@534: SetDParam(0, _date); truelight@193: truelight@0: // draw colored flag for change player cheat truelight@0: if(ce->str==STR_CHEAT_CHANGE_PLAYER) truelight@0: DrawPlayerIcon(_current_player, 156, y+2); truelight@0: truelight@0: } truelight@0: truelight@0: DrawString(50, y+1, ce->str, 0); truelight@0: truelight@0: y+=12; truelight@0: } truelight@0: break; truelight@0: } 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? truelight@0: if(!IS_INT_INSIDE(x, 20, 40) || btn>=lengthof(_cheats_ui)) truelight@0: 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: truelight@0: switch(ce->type) { truelight@0: case CE_BOOL: { truelight@0: val ^= 1; truelight@0: if (ce->click_proc != NULL) truelight@0: 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 truelight@0: val = ce->click_proc(val, (x>=30) ? 1 : -1); truelight@0: truelight@0: if (val != oval) truelight@0: WP(w,def_d).data_1 = btn * 2 + 1 + ((x>=30) ? 1 : 0); truelight@0: 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: } truelight@0: static const WindowDesc _cheats_desc = { truelight@0: 240, 22, 400, 148, 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: truelight@0: if (w) truelight@0: SetWindowDirty(w); truelight@0: }