217 SetDirtyBlocks(w->left, w->top - diff, w->left + w->width, w->top + w->height); |
217 SetDirtyBlocks(w->left, w->top - diff, w->left + w->width, w->top + w->height); |
218 } break; |
218 } break; |
219 } |
219 } |
220 } |
220 } |
221 |
221 |
222 // returns the correct index in the array |
222 /** Return the correct index in the pseudo-fifo |
223 // (to deal with overflows) |
223 * queue and deals with overflows when increasing the index */ |
224 static byte increaseIndex(byte i) |
224 static inline byte increaseIndex(byte i) |
225 { |
225 { |
226 if (i == INVALID_NEWS) return 0; |
226 if (i == INVALID_NEWS) return 0; |
227 i++; |
227 return (i + 1) % MAX_NEWS; |
228 if (i >= MAX_NEWS) i = i % MAX_NEWS; |
228 } |
229 return i; |
229 |
|
230 /** Return the correct index in the pseudo-fifo |
|
231 * queue and deals with overflows when decreasing the index */ |
|
232 static inline byte decreaseIndex(byte i) |
|
233 { |
|
234 assert(i != INVALID_NEWS); |
|
235 return (i + MAX_NEWS - 1) % MAX_NEWS; |
230 } |
236 } |
231 |
237 |
232 /** Add a new newsitem to be shown. |
238 /** Add a new newsitem to be shown. |
233 * @param string String to display, can have special values based on parameter 'flags' |
239 * @param string String to display, can have special values based on parameter 'flags' |
234 * @param flags various control bits that will show various news-types. See macro NEWS_FLAGS() |
240 * @param flags various control bits that will show various news-types. See macro NEWS_FLAGS() |
249 * @see NewsFlags |
255 * @see NewsFlags |
250 * @see NewsType |
256 * @see NewsType |
251 * @see NewsCallback */ |
257 * @see NewsCallback */ |
252 void AddNewsItem(StringID string, uint32 flags, uint data_a, uint data_b) |
258 void AddNewsItem(StringID string, uint32 flags, uint data_a, uint data_b) |
253 { |
259 { |
254 NewsItem *ni; |
|
255 Window *w; |
|
256 byte l_news; |
260 byte l_news; |
257 |
261 |
258 if (_game_mode == GM_MENU) return; |
262 if (_game_mode == GM_MENU) return; |
259 |
263 |
260 // check the rare case that the oldest (to be overwritten) news item is open |
264 // check the rare case that the oldest (to be overwritten) news item is open |
261 if (_total_news==MAX_NEWS && (_oldest_news == _current_news || _oldest_news == _forced_news)) |
265 if (_total_news == MAX_NEWS && (_oldest_news == _current_news || _oldest_news == _forced_news)) |
262 MoveToNexItem(); |
266 MoveToNexItem(); |
263 |
267 |
264 _forced_news = INVALID_NEWS; |
268 _forced_news = INVALID_NEWS; |
265 if (_total_news < MAX_NEWS) _total_news++; |
269 if (_total_news < MAX_NEWS) _total_news++; |
266 |
270 |
267 // make sure our pointer isn't overflowing |
271 // make sure our pointer isn't overflowing |
268 l_news = _latest_news; |
272 l_news = _latest_news; |
269 _latest_news = increaseIndex(_latest_news); |
273 _latest_news = increaseIndex(_latest_news); |
270 |
274 |
271 /* If the fifo-buffer is full, overwrite the oldest entry */ |
275 /* If the fifo-buffer is full, overwrite the oldest entry */ |
272 if (l_news != INVALID_NEWS && _latest_news == _oldest_news) |
276 if (l_news != INVALID_NEWS && _latest_news == _oldest_news) { |
273 _oldest_news = increaseIndex(_oldest_news); // but make sure we're not overflowing here |
277 assert(_total_news == MAX_NEWS); |
274 |
278 _oldest_news = increaseIndex(_oldest_news); |
275 // add news to _latest_news |
279 } |
276 ni = &_news_items[_latest_news]; |
280 |
277 memset(ni, 0, sizeof(*ni)); |
281 { /* Add news to _latest_news */ |
278 |
282 Window *w; |
279 ni->string_id = string; |
283 NewsItem *ni = &_news_items[_latest_news]; |
280 ni->display_mode = (byte)flags; |
284 memset(ni, 0, sizeof(*ni)); |
281 ni->flags = (byte)(flags >> 8); |
285 |
282 |
286 ni->string_id = string; |
283 // show this news message in color? |
287 ni->display_mode = (byte)flags; |
284 if (_cur_year >= _patches.colored_news_year) |
288 ni->flags = (byte)(flags >> 8); |
285 ni->flags |= NF_INCOLOR; |
289 |
286 |
290 // show this news message in color? |
287 ni->type = (byte)(flags >> 16); |
291 if (_cur_year >= _patches.colored_news_year) ni->flags |= NF_INCOLOR; |
288 ni->callback = (byte)(flags >> 24); |
292 |
289 ni->data_a = data_a; |
293 ni->type = (byte)(flags >> 16); |
290 ni->data_b = data_b; |
294 ni->callback = (byte)(flags >> 24); |
291 ni->date = _date; |
295 ni->data_a = data_a; |
292 COPY_OUT_DPARAM(ni->params, 0, lengthof(ni->params)); |
296 ni->data_b = data_b; |
293 |
297 ni->date = _date; |
294 w = FindWindowById(WC_MESSAGE_HISTORY, 0); |
298 COPY_OUT_DPARAM(ni->params, 0, lengthof(ni->params)); |
295 if (w == NULL) return; |
299 |
296 SetWindowDirty(w); |
300 w = FindWindowById(WC_MESSAGE_HISTORY, 0); |
297 w->vscroll.count = _total_news; |
301 if (w == NULL) return; |
|
302 SetWindowDirty(w); |
|
303 w->vscroll.count = _total_news; |
|
304 } |
298 } |
305 } |
299 |
306 |
300 |
307 |
301 // don't show item if it's older than x days |
308 // don't show item if it's older than x days |
302 static const byte _news_items_age[] = {60, 60, 90, 60, 90, 30, 150, 30, 90, 180}; |
309 static const byte _news_items_age[] = {60, 60, 90, 60, 90, 30, 150, 30, 90, 180}; |
469 static void MoveToNexItem(void) |
476 static void MoveToNexItem(void) |
470 { |
477 { |
471 DeleteWindowById(WC_NEWS_WINDOW, 0); |
478 DeleteWindowById(WC_NEWS_WINDOW, 0); |
472 _forced_news = INVALID_NEWS; |
479 _forced_news = INVALID_NEWS; |
473 |
480 |
474 // if we're not at the last item, than move on |
481 // if we're not at the last item, then move on |
475 if (_current_news != _latest_news) { |
482 if (_current_news != _latest_news) { |
476 NewsItem *ni; |
483 NewsItem *ni; |
477 |
484 |
478 _current_news = increaseIndex(_current_news); |
485 _current_news = increaseIndex(_current_news); |
479 ni = &_news_items[_current_news]; |
486 ni = &_news_items[_current_news]; |
534 } |
541 } |
535 } |
542 } |
536 |
543 |
537 void ShowLastNewsMessage(void) |
544 void ShowLastNewsMessage(void) |
538 { |
545 { |
539 if (_forced_news == INVALID_NEWS) { |
546 switch (_forced_news) { |
540 ShowNewsMessage(_current_news); |
547 case INVALID_NEWS: // Not forced any news yet, show the current one |
541 } else if (_forced_news != 0) { |
548 ShowNewsMessage(_current_news); |
542 ShowNewsMessage(_forced_news - 1); |
549 break; |
543 } else { |
550 case 0: // |
544 ShowNewsMessage(_total_news != MAX_NEWS ? _latest_news : MAX_NEWS - 1); |
551 ShowNewsMessage(_total_news != MAX_NEWS ? _latest_news : MAX_NEWS - 1); |
|
552 break; |
|
553 default: // 'Scrolling' through news history show each one in turn |
|
554 ShowNewsMessage(_forced_news - 1); |
|
555 break; |
545 } |
556 } |
546 } |
557 } |
547 |
558 |
548 |
559 |
549 /* return news by number, with 0 being the most |
560 /* return news by number, with 0 being the most |
874 |
885 |
875 void DeleteVehicleNews(VehicleID vid, StringID news) |
886 void DeleteVehicleNews(VehicleID vid, StringID news) |
876 { |
887 { |
877 byte n; |
888 byte n; |
878 |
889 |
879 for (n = _oldest_news; _latest_news != INVALID_NEWS && n != (_latest_news + 1) % MAX_NEWS; n = (n + 1) % MAX_NEWS) { |
890 for (n = _oldest_news; _latest_news != INVALID_NEWS && n != increaseIndex(_latest_news); n = increaseIndex(n)) { |
880 const NewsItem* ni = &_news_items[n]; |
891 const NewsItem *ni = &_news_items[n]; |
881 |
892 |
882 if (ni->flags & NF_VEHICLE && |
893 if (ni->flags & NF_VEHICLE && |
883 ni->data_a == vid && |
894 ni->data_a == vid && |
884 (news == INVALID_STRING_ID || ni->string_id == news)) { |
895 (news == INVALID_STRING_ID || ni->string_id == news)) { |
885 Window *w; |
896 Window *w; |
886 byte i; |
897 byte i; |
887 |
898 |
888 if (_forced_news == n) MoveToNexItem(); |
899 if (_forced_news == n || _current_news == n) MoveToNexItem(); |
889 if (_current_news == n) MoveToNexItem(); |
|
890 |
900 |
891 // If this is the last news item, invalidate _latest_news |
901 // If this is the last news item, invalidate _latest_news |
892 if (_latest_news == _oldest_news) _latest_news = INVALID_NEWS; |
902 if (_latest_news == _oldest_news) _latest_news = INVALID_NEWS; |
893 |
903 |
894 if (n != _oldest_news) { |
904 if (n != _oldest_news) { |