summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--graph_gui.c149
-rw-r--r--gui.h1
-rw-r--r--lang/english.txt2
-rw-r--r--main_gui.c3
-rw-r--r--signs.c24
-rw-r--r--signs.h3
-rw-r--r--ttd.h1
7 files changed, 178 insertions, 5 deletions
diff --git a/graph_gui.c b/graph_gui.c
index fdd6a1ee5..d27c140b9 100644
--- a/graph_gui.c
+++ b/graph_gui.c
@@ -6,6 +6,9 @@
#include "gfx.h"
#include "player.h"
#include "economy.h"
+#include "signs.h"
+#include "strings.h"
+#include "debug.h"
static uint _legend_excludebits;
static uint _legend_cargobits;
@@ -1098,3 +1101,149 @@ void ShowPerformanceRatingDetail(void)
{
AllocateWindowDescFront(&_performance_rating_detail_desc, 0);
}
+
+
+static uint16 _num_sign_sort;
+
+static char _bufcache[64];
+static uint16 _last_sign_idx;
+
+static int CDECL SignNameSorter(const void *a, const void *b)
+{
+ char buf1[64];
+ SignStruct *ss;
+ const uint16 cmp1 = *(const uint16 *)a;
+ const uint16 cmp2 = *(const uint16 *)b;
+
+ ss = GetSign(cmp1);
+ GetString(buf1, ss->str);
+
+ if (cmp2 != _last_sign_idx) {
+ _last_sign_idx = cmp2;
+ ss = GetSign(cmp2);
+ GetString(_bufcache, ss->str);
+ }
+
+ return strcmp(buf1, _bufcache); // sort by name
+}
+
+static void GlobalSortSignList(void)
+{
+ const SignStruct *ss;
+ uint32 n = 0;
+
+ _num_sign_sort = 0;
+
+ /* Create array for sorting */
+ _sign_sort = realloc(_sign_sort, GetSignPoolSize() * sizeof(_sign_sort[0]));
+ if (_sign_sort == NULL)
+ error("Could not allocate memory for the sign-sorting-list");
+
+ FOR_ALL_SIGNS(ss) {
+ if(ss->str != STR_NULL) {
+ _sign_sort[n++] = ss->index;
+ _num_sign_sort++;
+ }
+ }
+
+ qsort(_sign_sort, n, sizeof(_sign_sort[0]), SignNameSorter);
+
+ _sign_sort_dirty = false;
+
+ DEBUG(misc, 1) ("Resorting global sign list...");
+}
+
+static void SignListWndProc(Window *w, WindowEvent *e)
+{
+ switch (e->event) {
+ case WE_PAINT: {
+ uint32 i;
+ int y = 16; // offset from top of widget
+
+ if (_sign_sort_dirty)
+ GlobalSortSignList();
+
+ SetVScrollCount(w, _num_sign_sort);
+
+ SetDParam(0, w->vscroll.count);
+ DrawWindowWidgets(w);
+
+ /* No signs? */
+ if (w->vscroll.count == 0) {
+ DrawString(2, y, STR_304A_NONE, 0);
+ return;
+ }
+
+ {
+ SignStruct *ss;
+
+ /* Start drawing the signs */
+ i = 0;
+ for (i = w->vscroll.pos; i < (uint)w->vscroll.cap + w->vscroll.pos && i < w->vscroll.count; i++) {
+ ss = GetSign(_sign_sort[i]);
+
+ if (ss->owner != OWNER_NONE)
+ DrawPlayerIcon(ss->owner, 4, y + 1);
+
+ DrawString(22, y, ss->str, 8);
+ y += 10;
+ }
+ }
+ } break;
+
+ case WE_CLICK: {
+ switch (e->click.widget) {
+ case 3: {
+ uint32 id_v = (e->click.pt.y - 15) / 10;
+ SignStruct *ss;
+
+ if (id_v >= w->vscroll.cap)
+ return;
+
+ id_v += w->vscroll.pos;
+
+ if (id_v >= w->vscroll.count)
+ return;
+
+ ss = GetSign(_sign_sort[id_v]);
+ ScrollMainWindowToTile(TILE_FROM_XY(ss->x, ss->y));
+ } break;
+ }
+ } break;
+
+ case WE_RESIZE:
+ w->vscroll.cap += e->sizing.diff.y / 10;
+ break;
+ }
+}
+
+static const Widget _sign_list_widget[] = {
+{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 345, 0, 13, STR_SIGN_LIST_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
+{ WWT_STICKYBOX, RESIZE_LR, 14, 346, 357, 0, 13, 0x0, STR_STICKY_BUTTON},
+{ WWT_PANEL, RESIZE_RB, 14, 0, 345, 14, 137, 0x0, STR_NULL},
+{ WWT_SCROLLBAR, RESIZE_LRB, 14, 346, 357, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+{ WWT_RESIZEBOX, RESIZE_LRTB, 14, 346, 357, 126, 137, 0x0, STR_RESIZE_BUTTON},
+{ WIDGETS_END},
+};
+
+static const WindowDesc _sign_list_desc = {
+ -1, -1, 358, 138,
+ WC_SIGN_LIST,0,
+ WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON | WDF_RESIZABLE,
+ _sign_list_widget,
+ SignListWndProc
+};
+
+
+void ShowSignList(void)
+{
+ Window *w;
+
+ w = AllocateWindowDescFront(&_sign_list_desc, 0);
+ if (w != NULL) {
+ w->vscroll.cap = 12;
+ w->resize.step_height = 10;
+ w->resize.height = w->height - 10 * 7; // minimum if 5 in the list
+ }
+}
diff --git a/gui.h b/gui.h
index eb2a2b3af..868662144 100644
--- a/gui.h
+++ b/gui.h
@@ -75,6 +75,7 @@ void ShowSubsidiesList(void);
void ShowPlayerStations(int player);
void ShowPlayerFinances(int player);
void ShowPlayerCompany(int player);
+void ShowSignList(void);
void ShowEstimatedCostOrIncome(int32 cost, int x, int y);
void ShowErrorMessage(StringID msg_1, StringID msg_2, int x, int y);
diff --git a/lang/english.txt b/lang/english.txt
index 4f5011547..729c81a13 100644
--- a/lang/english.txt
+++ b/lang/english.txt
@@ -772,6 +772,7 @@ STR_02DC_DISPLAY_SUBSIDIES :{BLACK}Display subsidies
STR_02DD_SUBSIDIES :Subsidies
STR_02DE_MAP_OF_WORLD :Map of world
STR_EXTRA_VIEW_PORT :Extra viewport
+STR_SIGN_LIST :Sign list
STR_02DF_TOWN_DIRECTORY :Town directory
STR_TOWN_POPULATION :{BLACK}World population: {COMMA32}
STR_EXTRA_VIEW_PORT_TITLE :{WHITE}Viewport {COMMA16}
@@ -2796,6 +2797,7 @@ STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Displays which engine the left sele
STR_REPLACE_HELP :{BLACK}This allows you to replace one engine type with another type, when trains of the original type enter a depot
STR_SHORT_DATE :{WHITE}{DATE_TINY}
+STR_SIGN_LIST_CAPTION :{WHITE}Sign List - {COMMA16} Signs
############ Lists rail types
diff --git a/main_gui.c b/main_gui.c
index bac3509f7..633b970b7 100644
--- a/main_gui.c
+++ b/main_gui.c
@@ -233,6 +233,7 @@ static void MenuClickMap(int index)
switch(index) {
case 0: ShowSmallMap(); break;
case 1: ShowExtraViewPortWindow(); break;
+ case 2: ShowSignList(); break;
}
}
@@ -778,7 +779,7 @@ static void ToolbarSaveClick(Window *w)
static void ToolbarMapClick(Window *w)
{
- PopupMainToolbMenu(w, 96, 4, STR_02DE_MAP_OF_WORLD, 2);
+ PopupMainToolbMenu(w, 96, 4, STR_02DE_MAP_OF_WORLD, 3);
}
static void ToolbarTownClick(Window *w)
diff --git a/signs.c b/signs.c
index c686dc1eb..74856cc2b 100644
--- a/signs.c
+++ b/signs.c
@@ -4,6 +4,7 @@
#include "signs.h"
#include "saveload.h"
#include "command.h"
+#include "strings.h"
enum {
/* Max signs: 64000 (4 * 16000) */
@@ -75,10 +76,17 @@ static void MarkSignDirty(SignStruct *ss)
*/
static SignStruct *AllocateSign(void)
{
- SignStruct *s;
- FOR_ALL_SIGNS(s)
- if (s->str == 0)
- return s;
+ SignStruct *ss;
+ FOR_ALL_SIGNS(ss) {
+ if (ss->str == 0) {
+ uint index = ss->index;
+
+ memset(ss, 0, sizeof(SignStruct));
+ ss->index = index;
+
+ return ss;
+ }
+ }
/* Check if we can add a block to the pool */
if (AddBlockToPool(&_sign_pool))
@@ -112,6 +120,8 @@ int32 CmdPlaceSign(int x, int y, uint32 flags, uint32 p1, uint32 p2)
ss->z = GetSlopeZ(x,y);
UpdateSignVirtCoords(ss);
MarkSignDirty(ss);
+ InvalidateWindow(WC_SIGN_LIST, 0);
+ _sign_sort_dirty = true;
_new_sign_struct = ss;
}
@@ -151,6 +161,8 @@ int32 CmdRenameSign(int x, int y, uint32 flags, uint32 sign_id, uint32 owner)
/* Update */
UpdateSignVirtCoords(ss);
MarkSignDirty(ss);
+ InvalidateWindow(WC_SIGN_LIST, 0);
+ _sign_sort_dirty = true;
} else {
/* Free the name, because we did not assign it yet */
DeleteName(str);
@@ -165,6 +177,8 @@ int32 CmdRenameSign(int x, int y, uint32 flags, uint32 sign_id, uint32 owner)
ss->str = 0;
MarkSignDirty(ss);
+ InvalidateWindow(WC_SIGN_LIST, 0);
+ _sign_sort_dirty = true;
}
}
@@ -252,6 +266,8 @@ static void Load_SIGN(void)
ss = GetSign(index);
SlObject(ss, _sign_desc);
}
+
+ _sign_sort_dirty = true;
}
const ChunkHandler _sign_chunk_handlers[] = {
diff --git a/signs.h b/signs.h
index dc8c65785..2cc417ca0 100644
--- a/signs.h
+++ b/signs.h
@@ -46,6 +46,9 @@ static inline uint16 GetSignPoolSize(void)
VARDEF SignStruct *_new_sign_struct;
+VARDEF bool _sign_sort_dirty;
+VARDEF uint16 *_sign_sort;
+
void UpdateAllSignVirtCoords(void);
void PlaceProc_Sign(uint tile);
diff --git a/ttd.h b/ttd.h
index 24b193b0c..33cc3c13d 100644
--- a/ttd.h
+++ b/ttd.h
@@ -425,6 +425,7 @@ enum {
WC_CUSTOM_CURRENCY = 0x4B,
WC_REPLACE_VEHICLE = 0x4C,
WC_HIGHSCORE_ENDSCREEN = 0x4D,
+ WC_SIGN_LIST = 0x4E,
};