diff options
-rw-r--r-- | src/news_gui.cpp | 345 |
1 files changed, 171 insertions, 174 deletions
diff --git a/src/news_gui.cpp b/src/news_gui.cpp index eaa9dca77..1b5efb8b5 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -172,18 +172,26 @@ static const struct NewsSubtypeData _news_subtype_data[NS_END] = { { NT_GENERAL, NM_NORMAL, NF_TILE, NULL }, ///< NS_GENERAL }; -/** Initialize the news-items data structures */ -void InitNewsItemStructs() -{ - free(_news_items); - _max_news_items = max(ScaleByMapSize(30), 30U); - _news_items = CallocT<NewsItem>(_max_news_items); - _current_news = INVALID_NEWS; - _oldest_news = 0; - _latest_news = INVALID_NEWS; - _forced_news = INVALID_NEWS; - _total_news = 0; -} +/** + * Per-NewsType data + */ +NewsTypeData _news_type_data[NT_END] = { + /* name, age, sound, display */ + { "arrival_player", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_PLAYER + { "arrival_other", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_OTHER + { "accident", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCIDENT + { "company_info", 60, SND_BEGIN, ND_FULL }, ///< NT_COMPANY_INFO + { "openclose", 90, SND_BEGIN, ND_FULL }, ///< NT_OPENCLOSE + { "economy", 30, SND_BEGIN, ND_FULL }, ///< NT_ECONOMY + { "production_player", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_PLAYER + { "production_other", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_OTHER + { "production_nobody", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_NOBODY + { "advice", 150, SND_BEGIN, ND_FULL }, ///< NT_ADVICE + { "new_vehicles", 30, SND_1E_OOOOH, ND_FULL }, ///< NT_NEW_VEHICLES + { "acceptance", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCEPTANCE + { "subsidies", 180, SND_BEGIN, ND_FULL }, ///< NT_SUBSIDIES + { "general", 60, SND_BEGIN, ND_FULL }, ///< NT_GENERAL +}; struct NewsWindow : Window { uint16 chat_height; @@ -334,105 +342,6 @@ struct NewsWindow : Window { } }; -/** - * Return the correct index in the pseudo-fifo - * queue and deals with overflows when increasing the index - */ -static inline NewsID IncreaseIndex(NewsID i) -{ - assert(i != INVALID_NEWS); - return (i + 1) % _max_news_items; -} - -/** - * Return the correct index in the pseudo-fifo - * queue and deals with overflows when decreasing the index - */ -static inline NewsID DecreaseIndex(NewsID i) -{ - assert(i != INVALID_NEWS); - return (i + _max_news_items - 1) % _max_news_items; -} - -/** - * Add a new newsitem to be shown. - * @param string String to display - * @param subtype news category, any of the NewsSubtype enums (NS_) - * @param data_a news-specific value based on news type - * @param data_b news-specific value based on news type - * - * @see NewsSubype - */ -void AddNewsItem(StringID string, NewsSubtype subtype, uint data_a, uint data_b) -{ - if (_game_mode == GM_MENU) return; - - /* check the rare case that the oldest (to be overwritten) news item is open */ - if (_total_news == _max_news_items && (_oldest_news == _current_news || _oldest_news == _forced_news)) { - MoveToNextItem(); - } - - if (_total_news < _max_news_items) _total_news++; - - /* Increase _latest_news. If we have no news yet, use _oldest news as an - * index. We cannot use 0 as _oldest_news can jump around due to - * DeleteVehicleNews */ - NewsID l_news = _latest_news; - _latest_news = (_latest_news == INVALID_NEWS) ? _oldest_news : IncreaseIndex(_latest_news); - - /* If the fifo-buffer is full, overwrite the oldest entry */ - if (l_news != INVALID_NEWS && _latest_news == _oldest_news) { - assert(_total_news == _max_news_items); - _oldest_news = IncreaseIndex(_oldest_news); - } - - /*DEBUG(misc, 0, "+cur %3d, old %2d, lat %3d, for %3d, tot %2d", - _current_news, _oldest_news, _latest_news, _forced_news, _total_news);*/ - - /* Add news to _latest_news */ - NewsItem *ni = &_news_items[_latest_news]; - memset(ni, 0, sizeof(*ni)); - - ni->string_id = string; - ni->subtype = subtype; - ni->flags = _news_subtype_data[subtype].flags; - - /* show this news message in color? */ - if (_cur_year >= _settings.gui.colored_news_year) ni->flags |= NF_INCOLOR; - - ni->data_a = data_a; - ni->data_b = data_b; - ni->date = _date; - CopyOutDParam(ni->params, 0, lengthof(ni->params)); - - Window *w = FindWindowById(WC_MESSAGE_HISTORY, 0); - if (w == NULL) return; - w->SetDirty(); - w->vscroll.count = _total_news; -} - - -/** - * Per-NewsType data - */ -NewsTypeData _news_type_data[NT_END] = { - /* name, age, sound, display */ - { "arrival_player", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_PLAYER - { "arrival_other", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_OTHER - { "accident", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCIDENT - { "company_info", 60, SND_BEGIN, ND_FULL }, ///< NT_COMPANY_INFO - { "openclose", 90, SND_BEGIN, ND_FULL }, ///< NT_OPENCLOSE - { "economy", 30, SND_BEGIN, ND_FULL }, ///< NT_ECONOMY - { "production_player", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_PLAYER - { "production_other", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_OTHER - { "production_nobody", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_NOBODY - { "advice", 150, SND_BEGIN, ND_FULL }, ///< NT_ADVICE - { "new_vehicles", 30, SND_1E_OOOOH, ND_FULL }, ///< NT_NEW_VEHICLES - { "acceptance", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCEPTANCE - { "subsidies", 180, SND_BEGIN, ND_FULL }, ///< NT_SUBSIDIES - { "general", 60, SND_BEGIN, ND_FULL }, ///< NT_GENERAL -}; - static const Widget _news_type13_widgets[] = { { WWT_PANEL, RESIZE_NONE, 15, 0, 429, 0, 169, 0x0, STR_NULL}, @@ -530,6 +439,157 @@ static void ShowTicker(const NewsItem *ni) InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SHOW_TICKER); } +/** Initialize the news-items data structures */ +void InitNewsItemStructs() +{ + free(_news_items); + _max_news_items = max(ScaleByMapSize(30), 30U); + _news_items = CallocT<NewsItem>(_max_news_items); + _current_news = INVALID_NEWS; + _oldest_news = 0; + _latest_news = INVALID_NEWS; + _forced_news = INVALID_NEWS; + _total_news = 0; +} + +/** + * Return the correct index in the pseudo-fifo + * queue and deals with overflows when increasing the index + */ +static inline NewsID IncreaseIndex(NewsID i) +{ + assert(i != INVALID_NEWS); + return (i + 1) % _max_news_items; +} + +/** + * Return the correct index in the pseudo-fifo + * queue and deals with overflows when decreasing the index + */ +static inline NewsID DecreaseIndex(NewsID i) +{ + assert(i != INVALID_NEWS); + return (i + _max_news_items - 1) % _max_news_items; +} + +/** + * Add a new newsitem to be shown. + * @param string String to display + * @param subtype news category, any of the NewsSubtype enums (NS_) + * @param data_a news-specific value based on news type + * @param data_b news-specific value based on news type + * + * @see NewsSubype + */ +void AddNewsItem(StringID string, NewsSubtype subtype, uint data_a, uint data_b) +{ + if (_game_mode == GM_MENU) return; + + /* check the rare case that the oldest (to be overwritten) news item is open */ + if (_total_news == _max_news_items && (_oldest_news == _current_news || _oldest_news == _forced_news)) { + MoveToNextItem(); + } + + if (_total_news < _max_news_items) _total_news++; + + /* Increase _latest_news. If we have no news yet, use _oldest news as an + * index. We cannot use 0 as _oldest_news can jump around due to + * DeleteVehicleNews */ + NewsID l_news = _latest_news; + _latest_news = (_latest_news == INVALID_NEWS) ? _oldest_news : IncreaseIndex(_latest_news); + + /* If the fifo-buffer is full, overwrite the oldest entry */ + if (l_news != INVALID_NEWS && _latest_news == _oldest_news) { + assert(_total_news == _max_news_items); + _oldest_news = IncreaseIndex(_oldest_news); + } + + /*DEBUG(misc, 0, "+cur %3d, old %2d, lat %3d, for %3d, tot %2d", + _current_news, _oldest_news, _latest_news, _forced_news, _total_news);*/ + + /* Add news to _latest_news */ + NewsItem *ni = &_news_items[_latest_news]; + memset(ni, 0, sizeof(*ni)); + + ni->string_id = string; + ni->subtype = subtype; + ni->flags = _news_subtype_data[subtype].flags; + + /* show this news message in color? */ + if (_cur_year >= _settings.gui.colored_news_year) ni->flags |= NF_INCOLOR; + + ni->data_a = data_a; + ni->data_b = data_b; + ni->date = _date; + CopyOutDParam(ni->params, 0, lengthof(ni->params)); + + Window *w = FindWindowById(WC_MESSAGE_HISTORY, 0); + if (w == NULL) return; + w->SetDirty(); + w->vscroll.count = _total_news; +} + +void DeleteVehicleNews(VehicleID vid, StringID news) +{ + for (NewsID n = _oldest_news; _latest_news != INVALID_NEWS; n = IncreaseIndex(n)) { + const NewsItem *ni = &_news_items[n]; + + if (ni->flags & NF_VEHICLE && + ni->data_a == vid && + (news == INVALID_STRING_ID || ni->string_id == news)) { + /* If we delete a forced news and it is just before the current news + * then we need to advance to the next news (if any) */ + if (_forced_news == n) MoveToNextItem(); + if (_forced_news == INVALID_NEWS && _current_news == n) MoveToNextItem(); + _total_news--; + + /* If this is the last news item, invalidate _latest_news */ + if (_total_news == 0) { + assert(_latest_news == _oldest_news); + _latest_news = INVALID_NEWS; + _current_news = INVALID_NEWS; + } + + /* Since we only imitate a FIFO removing an arbitrary element does need + * some magic. Remove the item by shifting head towards the tail. eg + * oldest remove last + * | | | + * [------O--------n-----L--] + * will become (change dramatized to make clear) + * [---------O-----------L--] + * We also need an update of the current, forced and visible (open window) + * news's as this shifting could change the items they were pointing to */ + if (_total_news != 0) { + NewsWindow *w = dynamic_cast<NewsWindow*>(FindWindowById(WC_NEWS_WINDOW, 0)); + NewsID visible_news = (w != NULL) ? (NewsID)(w->ni - _news_items) : INVALID_NEWS; + + for (NewsID i = n;; i = DecreaseIndex(i)) { + _news_items[i] = _news_items[DecreaseIndex(i)]; + + if (i != _latest_news) { + if (i == _current_news) _current_news = IncreaseIndex(_current_news); + if (i == _forced_news) _forced_news = IncreaseIndex(_forced_news); + if (i == visible_news) w->ni = &_news_items[IncreaseIndex(visible_news)]; + } + + if (i == _oldest_news) break; + } + _oldest_news = IncreaseIndex(_oldest_news); + } + + /*DEBUG(misc, 0, "-cur %3d, old %2d, lat %3d, for %3d, tot %2d", + _current_news, _oldest_news, _latest_news, _forced_news, _total_news);*/ + + Window *w = FindWindowById(WC_MESSAGE_HISTORY, 0); + if (w != NULL) { + w->SetDirty(); + w->vscroll.count = _total_news; + } + } + + if (n == _latest_news) break; + } +} /** * Are we ready to show another news item? @@ -976,66 +1036,3 @@ void ShowMessageOptions() DeleteWindowById(WC_GAME_OPTIONS, 0); new MessageOptionsWindow(&_message_options_desc); } - - -void DeleteVehicleNews(VehicleID vid, StringID news) -{ - for (NewsID n = _oldest_news; _latest_news != INVALID_NEWS; n = IncreaseIndex(n)) { - const NewsItem *ni = &_news_items[n]; - - if (ni->flags & NF_VEHICLE && - ni->data_a == vid && - (news == INVALID_STRING_ID || ni->string_id == news)) { - /* If we delete a forced news and it is just before the current news - * then we need to advance to the next news (if any) */ - if (_forced_news == n) MoveToNextItem(); - if (_forced_news == INVALID_NEWS && _current_news == n) MoveToNextItem(); - _total_news--; - - /* If this is the last news item, invalidate _latest_news */ - if (_total_news == 0) { - assert(_latest_news == _oldest_news); - _latest_news = INVALID_NEWS; - _current_news = INVALID_NEWS; - } - - /* Since we only imitate a FIFO removing an arbitrary element does need - * some magic. Remove the item by shifting head towards the tail. eg - * oldest remove last - * | | | - * [------O--------n-----L--] - * will become (change dramatized to make clear) - * [---------O-----------L--] - * We also need an update of the current, forced and visible (open window) - * news's as this shifting could change the items they were pointing to */ - if (_total_news != 0) { - NewsWindow *w = dynamic_cast<NewsWindow*>(FindWindowById(WC_NEWS_WINDOW, 0)); - NewsID visible_news = (w != NULL) ? (NewsID)(w->ni - _news_items) : INVALID_NEWS; - - for (NewsID i = n;; i = DecreaseIndex(i)) { - _news_items[i] = _news_items[DecreaseIndex(i)]; - - if (i != _latest_news) { - if (i == _current_news) _current_news = IncreaseIndex(_current_news); - if (i == _forced_news) _forced_news = IncreaseIndex(_forced_news); - if (i == visible_news) w->ni = &_news_items[IncreaseIndex(visible_news)]; - } - - if (i == _oldest_news) break; - } - _oldest_news = IncreaseIndex(_oldest_news); - } - - /*DEBUG(misc, 0, "-cur %3d, old %2d, lat %3d, for %3d, tot %2d", - _current_news, _oldest_news, _latest_news, _forced_news, _total_news);*/ - - Window *w = FindWindowById(WC_MESSAGE_HISTORY, 0); - if (w != NULL) { - w->SetDirty(); - w->vscroll.count = _total_news; - } - } - - if (n == _latest_news) break; - } -} |