From f6a88e40a4540dbf58f664d0c322b39f6a929169 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 4 Apr 2024 07:53:14 +0100 Subject: [PATCH] Codechange: Use std::list for News Items. (#12338) --- src/crashlog.cpp | 9 +- src/news_func.h | 2 +- src/news_gui.cpp | 329 ++++++++++++++++++------------------------ src/news_gui.h | 2 +- src/news_type.h | 5 +- src/statusbar_gui.cpp | 4 +- 6 files changed, 155 insertions(+), 196 deletions(-) diff --git a/src/crashlog.cpp b/src/crashlog.cpp index dfa029ca44..b728406fd8 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -56,11 +56,12 @@ static void SurveyRecentNews(nlohmann::json &json) json = nlohmann::json::array(); int i = 0; - for (NewsItem *news = _latest_news; i < 32 && news != nullptr; news = news->prev, i++) { - TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(news->date); + for (const auto &news : GetNews()) { + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(news.date); json.push_back(fmt::format("({}-{:02}-{:02}) StringID: {}, Type: {}, Ref1: {}, {}, Ref2: {}, {}", - ymd.year, ymd.month + 1, ymd.day, news->string_id, news->type, - news->reftype1, news->ref1, news->reftype2, news->ref2)); + ymd.year, ymd.month + 1, ymd.day, news.string_id, news.type, + news.reftype1, news.ref1, news.reftype2, news.ref2)); + if (++i > 32) break; } } diff --git a/src/news_func.h b/src/news_func.h index 614f29cf7e..e24b115258 100644 --- a/src/news_func.h +++ b/src/news_func.h @@ -55,7 +55,7 @@ inline void AddIndustryNewsItem(StringID string, NewsType type, IndustryID indus void NewsLoop(); void InitNewsItemStructs(); -extern const NewsItem *_statusbar_news_item; +const NewsItem *GetStatusbarNews(); void DeleteInvalidEngineNews(); void DeleteVehicleNews(VehicleID vid, StringID news); diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 36200d003d..fe7710ca8d 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -21,7 +21,6 @@ #include "town.h" #include "sound_func.h" #include "string_func.h" -#include "dropdown_func.h" #include "statusbar_gui.h" #include "company_manager_face.h" #include "company_func.h" @@ -44,25 +43,42 @@ #include "safeguards.h" -const NewsItem *_statusbar_news_item = nullptr; +static const uint MIN_NEWS_AMOUNT = 30; ///< preferred minimum amount of news messages. +static const uint MAX_NEWS_AMOUNT = 1U << 10; ///< Do not exceed this number of news messages. -static uint MIN_NEWS_AMOUNT = 30; ///< preferred minimum amount of news messages -static uint MAX_NEWS_AMOUNT = 1 << 10; ///< Do not exceed this number of news messages -static uint _total_news = 0; ///< current number of news items -static NewsItem *_oldest_news = nullptr; ///< head of news items queue -NewsItem *_latest_news = nullptr; ///< tail of news items queue +static NewsContainer _news; ///< List of news, with newest items at the start. /** * Forced news item. * Users can force an item by accessing the history or "last message". - * If the message being shown was forced by the user, a pointer is stored - * in _forced_news. Otherwise, \a _forced_news variable is nullptr. + * If the message being shown was forced by the user, an iterater is stored + * in _forced_news. Otherwise, \a _forced_news variable is the end of \a _news. */ -static const NewsItem *_forced_news = nullptr; +static NewsIterator _forced_news = std::end(_news); /** Current news item (last item shown regularly). */ -static const NewsItem *_current_news = nullptr; +static NewsIterator _current_news = std::end(_news); +/** Current status bar news item. */ +static NewsIterator _statusbar_news = std::end(_news); + +/** + * Get pointer to the current status bar news item. + * @return Pointer to the current status bar news item, or nullptr if there is none. + */ +const NewsItem *GetStatusbarNews() +{ + return (_statusbar_news == std::end(_news)) ? nullptr : &*_statusbar_news; +} + +/** + * Get read-only reference to all news items. + * @return Read-only reference to all news items. + */ +const NewsContainer &GetNews() +{ + return _news; +} /** * Get the position a news-reference is referencing. @@ -484,7 +500,7 @@ struct NewsWindow : Window { case WID_N_CLOSEBOX: NewsWindow::duration = 0; this->Close(); - _forced_news = nullptr; + _forced_news = std::end(_news); break; case WID_N_CAPTION: @@ -622,29 +638,21 @@ static void ShowNewspaper(const NewsItem *ni) } /** Show news item in the ticker */ -static void ShowTicker(const NewsItem *ni) +static void ShowTicker(NewsIterator ni) { if (_settings_client.sound.news_ticker) SndPlayFx(SND_16_NEWS_TICKER); - _statusbar_news_item = ni; + _statusbar_news = ni; InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SHOW_TICKER); } /** Initialize the news-items data structures */ void InitNewsItemStructs() { - for (NewsItem *ni = _oldest_news; ni != nullptr; ) { - NewsItem *next = ni->next; - delete ni; - ni = next; - } - - _total_news = 0; - _oldest_news = nullptr; - _latest_news = nullptr; - _forced_news = nullptr; - _current_news = nullptr; - _statusbar_news_item = nullptr; + _news.clear(); + _forced_news = std::end(_news); + _current_news = std::end(_news); + _statusbar_news = std::end(_news); NewsWindow::duration = 0; } @@ -654,7 +662,7 @@ void InitNewsItemStructs() */ static bool ReadyForNextTickerItem() { - const NewsItem *ni = _statusbar_news_item; + const NewsItem *ni = GetStatusbarNews(); if (ni == nullptr) return true; /* Ticker message @@ -668,8 +676,7 @@ static bool ReadyForNextTickerItem() */ static bool ReadyForNextNewsItem() { - const NewsItem *ni = _forced_news == nullptr ? _current_news : _forced_news; - if (ni == nullptr) return true; + if (_forced_news == std::end(_news) && _current_news == std::end(_news)) return true; /* neither newsticker nor newspaper are running */ return (NewsWindow::duration <= 0 || FindWindowById(WC_NEWS_WINDOW, 0) == nullptr); @@ -678,116 +685,98 @@ static bool ReadyForNextNewsItem() /** Move to the next ticker item */ static void MoveToNextTickerItem() { + assert(!std::empty(_news)); + /* There is no status bar, so no reason to show news; * especially important with the end game screen when * there is no status bar but possible news. */ if (FindWindowById(WC_STATUS_BAR, 0) == nullptr) return; - /* if we're not at the last item, then move on */ - while (_statusbar_news_item != _latest_news) { - _statusbar_news_item = (_statusbar_news_item == nullptr) ? _oldest_news : _statusbar_news_item->next; - const NewsItem *ni = _statusbar_news_item; - const NewsType type = ni->type; + /* if we're not at the latest item, then move on */ + while (_statusbar_news != std::begin(_news)) { + --_statusbar_news; + const NewsType type = _statusbar_news->type; /* check the date, don't show too old items */ - if (TimerGameEconomy::date - _news_type_data[type].age > ni->economy_date) continue; + if (TimerGameEconomy::date - _news_type_data[type].age > _statusbar_news->economy_date) continue; switch (_news_type_data[type].GetDisplay()) { default: NOT_REACHED(); case ND_OFF: // Off - show nothing only a small reminder in the status bar InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SHOW_REMINDER); - break; + return; case ND_SUMMARY: // Summary - show ticker - ShowTicker(ni); - break; + ShowTicker(_statusbar_news); + return; case ND_FULL: // Full - show newspaper, skipped here - continue; + break;; } - return; } } /** Move to the next news item */ static void MoveToNextNewsItem() { + assert(!std::empty(_news)); + /* There is no status bar, so no reason to show news; * especially important with the end game screen when * there is no status bar but possible news. */ if (FindWindowById(WC_STATUS_BAR, 0) == nullptr) return; CloseWindowById(WC_NEWS_WINDOW, 0); // close the newspapers window if shown - _forced_news = nullptr; + _forced_news = std::end(_news); - /* if we're not at the last item, then move on */ - while (_current_news != _latest_news) { - _current_news = (_current_news == nullptr) ? _oldest_news : _current_news->next; - const NewsItem *ni = _current_news; - const NewsType type = ni->type; + /* if we're not at the latest item, then move on */ + while (_current_news != std::begin(_news)) { + --_current_news; + const NewsType type = _current_news->type; /* check the date, don't show too old items */ - if (TimerGameEconomy::date - _news_type_data[type].age > ni->economy_date) continue; + if (TimerGameEconomy::date - _news_type_data[type].age > _current_news->economy_date) continue; switch (_news_type_data[type].GetDisplay()) { default: NOT_REACHED(); case ND_OFF: // Off - show nothing only a small reminder in the status bar, skipped here - continue; + break; case ND_SUMMARY: // Summary - show ticker, skipped here - continue; + break;; case ND_FULL: // Full - show newspaper - ShowNewspaper(ni); - break; + ShowNewspaper(&*_current_news); + return; } - return; } } /** Delete a news item from the queue */ -static void DeleteNewsItem(NewsItem *ni) +static std::list::iterator DeleteNewsItem(std::list::iterator ni) { - /* Delete the news from the news queue. */ - if (ni->prev != nullptr) { - ni->prev->next = ni->next; - } else { - assert(_oldest_news == ni); - _oldest_news = ni->next; - } - - if (ni->next != nullptr) { - ni->next->prev = ni->prev; - } else { - assert(_latest_news == ni); - _latest_news = ni->prev; - } - - _total_news--; - if (_forced_news == ni || _current_news == ni) { /* When we're the current news, go to the previous item first; * we just possibly made that the last news item. */ - if (_current_news == ni) _current_news = ni->prev; + if (_current_news == ni) _current_news = (_current_news == std::begin(_news)) ? std::end(_news) : std::prev(_current_news); /* About to remove the currently forced item (shown as newspapers) || * about to remove the currently displayed item (newspapers) */ MoveToNextNewsItem(); } - if (_statusbar_news_item == ni) { + if (_statusbar_news == ni) { /* When we're the current news, go to the previous item first; * we just possibly made that the last news item. */ - _statusbar_news_item = ni->prev; + if (_statusbar_news == ni) _statusbar_news = (_statusbar_news == std::begin(_news)) ? std::end(_news) : std::prev(_statusbar_news); /* About to remove the currently displayed item (ticker, or just a reminder) */ InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED); // invalidate the statusbar MoveToNextTickerItem(); } - delete ni; - - SetWindowDirty(WC_MESSAGE_HISTORY, 0); + /* Delete the news from the news queue. */ + return _news.erase(ni); } /** @@ -829,27 +818,14 @@ void AddNewsItem(StringID string, NewsType type, NewsFlag flags, NewsReferenceTy if (_game_mode == GM_MENU) return; /* Create new news item node */ - NewsItem *ni = new NewsItem(string, type, flags, reftype1, ref1, reftype2, ref2, data); - - if (_total_news++ == 0) { - assert(_oldest_news == nullptr); - _oldest_news = ni; - ni->prev = nullptr; - } else { - assert(_latest_news->next == nullptr); - _latest_news->next = ni; - ni->prev = _latest_news; - } - - ni->next = nullptr; - _latest_news = ni; + _news.emplace_front(string, type, flags, reftype1, ref1, reftype2, ref2, data); /* Keep the number of stored news items to a managable number */ - if (_total_news > MAX_NEWS_AMOUNT) { - DeleteNewsItem(_oldest_news); + if (std::size(_news) > MAX_NEWS_AMOUNT) { + DeleteNewsItem(std::prev(std::end(_news))); } - SetWindowDirty(WC_MESSAGE_HISTORY, 0); + InvalidateWindowData(WC_MESSAGE_HISTORY, 0); } /** @@ -910,6 +886,29 @@ CommandCost CmdCustomNewsItem(DoCommandFlag flags, NewsType type, NewsReferenceT return CommandCost(); } +/** + * Delete news items by predicate, and invalidate the message history if necessary. + * @tparam Tmin Stop if the number of news items remaining reaches \a min items. + * @tparam Tpredicate Condition for a news item to be deleted. + */ +template +void DeleteNews(Tpredicate predicate) +{ + bool dirty = false; + for (auto it = std::rbegin(_news); it != std::rend(_news); /* nothing */) { + if constexpr (Tmin > 0) { + if (std::size(_news) <= Tmin) break; + } + if (predicate(*it)) { + it = std::make_reverse_iterator(DeleteNewsItem(std::prev(it.base()))); + dirty = true; + } else { + ++it; + } + } + if (dirty) InvalidateWindowData(WC_MESSAGE_HISTORY, 0); +} + /** * Delete a news item type about a vehicle. * When the news item type is INVALID_STRING_ID all news about the vehicle gets deleted. @@ -918,16 +917,9 @@ CommandCost CmdCustomNewsItem(DoCommandFlag flags, NewsType type, NewsReferenceT */ void DeleteVehicleNews(VehicleID vid, StringID news) { - NewsItem *ni = _oldest_news; - - while (ni != nullptr) { - NewsItem *next = ni->next; - if (((ni->reftype1 == NR_VEHICLE && ni->ref1 == vid) || (ni->reftype2 == NR_VEHICLE && ni->ref2 == vid)) && - (news == INVALID_STRING_ID || ni->string_id == news)) { - DeleteNewsItem(ni); - } - ni = next; - } + DeleteNews([&](const auto &ni) { + return ((ni.reftype1 == NR_VEHICLE && ni.ref1 == vid) || (ni.reftype2 == NR_VEHICLE && ni.ref2 == vid)) && (news == INVALID_STRING_ID || ni.string_id == news); + }); } /** @@ -937,15 +929,9 @@ void DeleteVehicleNews(VehicleID vid, StringID news) */ void DeleteStationNews(StationID sid) { - NewsItem *ni = _oldest_news; - - while (ni != nullptr) { - NewsItem *next = ni->next; - if ((ni->reftype1 == NR_STATION && ni->ref1 == sid) || (ni->reftype2 == NR_STATION && ni->ref2 == sid)) { - DeleteNewsItem(ni); - } - ni = next; - } + DeleteNews([&](const auto &ni) { + return (ni.reftype1 == NR_STATION && ni.ref1 == sid) || (ni.reftype2 == NR_STATION && ni.ref2 == sid); + }); } /** @@ -954,15 +940,9 @@ void DeleteStationNews(StationID sid) */ void DeleteIndustryNews(IndustryID iid) { - NewsItem *ni = _oldest_news; - - while (ni != nullptr) { - NewsItem *next = ni->next; - if ((ni->reftype1 == NR_INDUSTRY && ni->ref1 == iid) || (ni->reftype2 == NR_INDUSTRY && ni->ref2 == iid)) { - DeleteNewsItem(ni); - } - ni = next; - } + DeleteNews([&](const auto &ni) { + return (ni.reftype1 == NR_INDUSTRY && ni.ref1 == iid) || (ni.reftype2 == NR_INDUSTRY && ni.ref2 == iid); + }); } /** @@ -970,25 +950,17 @@ void DeleteIndustryNews(IndustryID iid) */ void DeleteInvalidEngineNews() { - NewsItem *ni = _oldest_news; - - while (ni != nullptr) { - NewsItem *next = ni->next; - if ((ni->reftype1 == NR_ENGINE && (!Engine::IsValidID(ni->ref1) || !Engine::Get(ni->ref1)->IsEnabled())) || - (ni->reftype2 == NR_ENGINE && (!Engine::IsValidID(ni->ref2) || !Engine::Get(ni->ref2)->IsEnabled()))) { - DeleteNewsItem(ni); - } - ni = next; - } + DeleteNews([](const auto &ni) { + return (ni.reftype1 == NR_ENGINE && (!Engine::IsValidID(ni.ref1) || !Engine::Get(ni.ref1)->IsEnabled())) || + (ni.reftype2 == NR_ENGINE && (!Engine::IsValidID(ni.ref2) || !Engine::Get(ni.ref2)->IsEnabled())); + }); } static void RemoveOldNewsItems() { - NewsItem *next; - for (NewsItem *cur = _oldest_news; _total_news > MIN_NEWS_AMOUNT && cur != nullptr; cur = next) { - next = cur->next; - if (TimerGameEconomy::date - _news_type_data[cur->type].age * _settings_client.gui.news_message_timeout > cur->economy_date) DeleteNewsItem(cur); - } + DeleteNews([](const auto &ni) { + return TimerGameEconomy::date - _news_type_data[ni.type].age * _settings_client.gui.news_message_timeout > ni.economy_date; + }); } /** @@ -999,17 +971,17 @@ static void RemoveOldNewsItems() */ void ChangeVehicleNews(VehicleID from_index, VehicleID to_index) { - for (NewsItem *ni = _oldest_news; ni != nullptr; ni = ni->next) { - if (ni->reftype1 == NR_VEHICLE && ni->ref1 == from_index) ni->ref1 = to_index; - if (ni->reftype2 == NR_VEHICLE && ni->ref2 == from_index) ni->ref2 = to_index; - if (ni->flags & NF_VEHICLE_PARAM0 && ni->params[0].data == from_index) ni->params[0] = to_index; + for (auto &ni : _news) { + if (ni.reftype1 == NR_VEHICLE && ni.ref1 == from_index) ni.ref1 = to_index; + if (ni.reftype2 == NR_VEHICLE && ni.ref2 == from_index) ni.ref2 = to_index; + if (ni.flags & NF_VEHICLE_PARAM0 && ni.params[0].data == from_index) ni.params[0] = to_index; } } void NewsLoop() { /* no news item yet */ - if (_total_news == 0) return; + if (std::empty(_news)) return; static TimerGameEconomy::Month _last_clean_month = 0; @@ -1023,9 +995,9 @@ void NewsLoop() } /** Do a forced show of a specific message */ -static void ShowNewsMessage(const NewsItem *ni) +static void ShowNewsMessage(NewsIterator ni) { - assert(_total_news != 0); + assert(!std::empty(_news)); /* Delete the news window */ CloseWindowById(WC_NEWS_WINDOW, 0); @@ -1033,9 +1005,9 @@ static void ShowNewsMessage(const NewsItem *ni) /* setup forced news item */ _forced_news = ni; - if (_forced_news != nullptr) { + if (_forced_news != std::end(_news)) { CloseWindowById(WC_NEWS_WINDOW, 0); - ShowNewspaper(ni); + ShowNewspaper(&*ni); } } @@ -1054,26 +1026,26 @@ bool HideActiveNewsMessage() /** Show previous news item */ void ShowLastNewsMessage() { - const NewsItem *ni = nullptr; - if (_total_news == 0) { - return; - } else if (_forced_news == nullptr) { + if (std::empty(_news)) return; + + NewsIterator ni; + if (_forced_news == std::end(_news)) { /* Not forced any news yet, show the current one, unless a news window is * open (which can only be the current one), then show the previous item */ - if (_current_news == nullptr) { + if (_current_news == std::end(_news)) { /* No news were shown yet resp. the last shown one was already deleted. - * Threat this as if _forced_news reached _oldest_news; so, wrap around and start anew with the latest. */ - ni = _latest_news; + * Treat this as if _forced_news reached the oldest news; so, wrap around and start anew with the latest. */ + ni = std::begin(_news); } else { const Window *w = FindWindowById(WC_NEWS_WINDOW, 0); - ni = (w == nullptr || (_current_news == _oldest_news)) ? _current_news : _current_news->prev; + ni = (w == nullptr || (std::next(_current_news) == std::end(_news))) ? _current_news : std::next(_current_news); } - } else if (_forced_news == _oldest_news) { + } else if (std::next(_forced_news) == std::end(_news)) { /* We have reached the oldest news, start anew with the latest */ - ni = _latest_news; + ni = std::begin(_news); } else { /* 'Scrolling' through news history show each one in turn */ - ni = _forced_news->prev; + ni = std::next(_forced_news); } bool wrap = false; for (;;) { @@ -1082,11 +1054,11 @@ void ShowLastNewsMessage() break; } - ni = ni->prev; - if (ni == nullptr) { + ++ni; + if (ni == std::end(_news)) { if (wrap) break; /* We have reached the oldest news, start anew with the latest */ - ni = _latest_news; + ni = std::begin(_news); wrap = true; } } @@ -1143,37 +1115,23 @@ struct MessageHistoryWindow : Window { } } - void OnPaint() override - { - this->OnInvalidateData(0); - this->DrawWidgets(); - } - void DrawWidget(const Rect &r, WidgetID widget) const override { - if (widget != WID_MH_BACKGROUND || _total_news == 0) return; - - /* Find the first news item to display. */ - NewsItem *ni = _latest_news; - for (int n = this->vscroll->GetPosition(); n > 0; n--) { - ni = ni->prev; - if (ni == nullptr) return; - } + if (widget != WID_MH_BACKGROUND || std::empty(_news)) return; /* Fill the widget with news items. */ bool rtl = _current_text_dir == TD_RTL; Rect news = r.Shrink(WidgetDimensions::scaled.framerect).Indent(this->date_width + WidgetDimensions::scaled.hsep_wide, rtl); Rect date = r.Shrink(WidgetDimensions::scaled.framerect).WithWidth(this->date_width, rtl); int y = news.top; - for (int n = this->vscroll->GetCapacity(); n > 0; n--) { + + auto [first, last] = this->vscroll->GetVisibleRangeIterators(_news); + for (auto ni = first; ni != last; ++ni) { SetDParam(0, ni->date); DrawString(date.left, date.right, y, STR_JUST_DATE_TINY, TC_WHITE); - DrawNewsString(news.left, news.right, y, TC_WHITE, ni); + DrawNewsString(news.left, news.right, y, TC_WHITE, &*ni); y += this->line_height; - - ni = ni->prev; - if (ni == nullptr) return; } } @@ -1185,19 +1143,18 @@ struct MessageHistoryWindow : Window { void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override { if (!gui_scope) return; - this->vscroll->SetCount(_total_news); + this->vscroll->SetCount(std::size(_news)); } void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override { if (widget == WID_MH_BACKGROUND) { - NewsItem *ni = _latest_news; - if (ni == nullptr) return; - - for (int n = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_MH_BACKGROUND, WidgetDimensions::scaled.framerect.top); n > 0; n--) { - ni = ni->prev; - if (ni == nullptr) return; - } + /* Scheduled window invalidations currently occur after the input loop, which means the scrollbar count + * could be invalid, so ensure it's correct now. Potentially this means that item clicked on might be + * different as well. */ + this->vscroll->SetCount(std::size(_news)); + auto ni = this->vscroll->GetScrolledItemFromWidget(_news, pt.y, this, widget); + if (ni == std::end(_news)) return; ShowNewsMessage(ni); } diff --git a/src/news_gui.h b/src/news_gui.h index 059d51ad32..c7fea6cebd 100644 --- a/src/news_gui.h +++ b/src/news_gui.h @@ -16,6 +16,6 @@ void ShowLastNewsMessage(); void ShowMessageHistory(); bool HideActiveNewsMessage(); -extern NewsItem *_latest_news; +const NewsContainer &GetNews(); #endif /* NEWS_GUI_H */ diff --git a/src/news_type.h b/src/news_type.h index ffe63b6a8e..cbafbef1ce 100644 --- a/src/news_type.h +++ b/src/news_type.h @@ -126,8 +126,6 @@ struct NewsAllocatedData { /** Information about a single item of news. */ struct NewsItem { - NewsItem *prev; ///< Previous news item - NewsItem *next; ///< Next news item StringID string_id; ///< Message text TimerGameCalendar::Date date; ///< Calendar date to show for the news TimerGameEconomy::Date economy_date; ///< Economy date of the news item, never shown but used to calculate age @@ -169,4 +167,7 @@ struct CompanyNewsInformation : NewsAllocatedData { CompanyNewsInformation(const struct Company *c, const struct Company *other = nullptr); }; +using NewsContainer = std::list; ///< Container type for storing news items. +using NewsIterator = NewsContainer::const_iterator; ///< Iterator type for news items. + #endif /* NEWS_TYPE_H */ diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp index 7229ffd803..69f12dbfdd 100644 --- a/src/statusbar_gui.cpp +++ b/src/statusbar_gui.cpp @@ -145,9 +145,9 @@ struct StatusBarWindow : Window { } else if (_pause_mode != PM_UNPAUSED) { StringID msg = (_pause_mode & PM_PAUSED_LINK_GRAPH) ? STR_STATUSBAR_PAUSED_LINK_GRAPH : STR_STATUSBAR_PAUSED; DrawString(tr, msg, TC_FROMSTRING, SA_HOR_CENTER); - } else if (this->ticker_scroll < TICKER_STOP && _statusbar_news_item != nullptr && _statusbar_news_item->string_id != 0) { + } else if (this->ticker_scroll < TICKER_STOP && GetStatusbarNews() != nullptr && GetStatusbarNews()->string_id != 0) { /* Draw the scrolling news text */ - if (!DrawScrollingStatusText(_statusbar_news_item, ScaleGUITrad(this->ticker_scroll), tr.left, tr.right, tr.top, tr.bottom)) { + if (!DrawScrollingStatusText(GetStatusbarNews(), ScaleGUITrad(this->ticker_scroll), tr.left, tr.right, tr.top, tr.bottom)) { InvalidateWindowData(WC_STATUS_BAR, 0, SBI_NEWS_DELETED); if (Company::IsValidID(_local_company)) { /* This is the default text */