21 [O------------F-------------C---------L ] |
21 [O------------F-------------C---------L ] |
22 | |
22 | |
23 forced |
23 forced |
24 */ |
24 */ |
25 |
25 |
26 # define MAX_NEWS 30 |
26 #define MAX_NEWS 30 |
|
27 |
|
28 #define INVALID_NEWS 255 |
27 |
29 |
28 static NewsItem _news_items[MAX_NEWS]; |
30 static NewsItem _news_items[MAX_NEWS]; |
29 static byte _current_news = 255; // points to news item that should be shown next |
31 static byte _current_news = INVALID_NEWS; // points to news item that should be shown next |
30 static byte _oldest_news = 0; // points to first item in fifo queue |
32 static byte _oldest_news = 0; // points to first item in fifo queue |
31 static byte _latest_news = 255; // points to last item in fifo queue |
33 static byte _latest_news = INVALID_NEWS; // points to last item in fifo queue |
32 static byte _forced_news = 255; // if the message being shown was forced by the user, its index is stored in _forced_news. |
34 /* if the message being shown was forced by the user, its index is stored in |
33 //forced_news is 255 otherwise. (Users can force messages through history or "last message") |
35 * _forced_news. forced_news is INVALID_NEWS otherwise. |
|
36 * (Users can force messages through history or "last message") */ |
|
37 static byte _forced_news = INVALID_NEWS; |
34 |
38 |
35 static byte _total_news = 0; // total news count |
39 static byte _total_news = 0; // total news count |
36 |
40 |
37 void DrawNewsNewTrainAvail(Window *w); |
41 void DrawNewsNewTrainAvail(Window *w); |
38 void DrawNewsNewRoadVehAvail(Window *w); |
42 void DrawNewsNewRoadVehAvail(Window *w); |
39 void DrawNewsNewShipAvail(Window *w); |
43 void DrawNewsNewShipAvail(Window *w); |
40 void DrawNewsNewAircraftAvail(Window *w); |
44 void DrawNewsNewAircraftAvail(Window *w); |
41 void DrawNewsBankrupcy(Window *w); |
45 void DrawNewsBankrupcy(Window *w); |
42 static void MoveToNexItem(); |
46 static void MoveToNexItem(void); |
43 |
47 |
44 StringID GetNewsStringNewTrainAvail(NewsItem *ni); |
48 StringID GetNewsStringNewTrainAvail(NewsItem *ni); |
45 StringID GetNewsStringNewRoadVehAvail(NewsItem *ni); |
49 StringID GetNewsStringNewRoadVehAvail(NewsItem *ni); |
46 StringID GetNewsStringNewShipAvail(NewsItem *ni); |
50 StringID GetNewsStringNewShipAvail(NewsItem *ni); |
47 StringID GetNewsStringNewAircraftAvail(NewsItem *ni); |
51 StringID GetNewsStringNewAircraftAvail(NewsItem *ni); |
48 StringID GetNewsStringBankrupcy(NewsItem *ni); |
52 StringID GetNewsStringBankrupcy(NewsItem *ni); |
49 |
53 |
50 static DrawNewsCallbackProc * const _draw_news_callback[] = { |
54 static DrawNewsCallbackProc * const _draw_news_callback[] = { |
51 DrawNewsNewTrainAvail, /* DNC_TRAINAVAIL */ |
55 DrawNewsNewTrainAvail, /* DNC_TRAINAVAIL */ |
52 DrawNewsNewRoadVehAvail, /* DNC_ROADAVAIL */ |
56 DrawNewsNewRoadVehAvail, /* DNC_ROADAVAIL */ |
53 DrawNewsNewShipAvail, /* DNC_SHIPAVAIL */ |
57 DrawNewsNewShipAvail, /* DNC_SHIPAVAIL */ |
54 DrawNewsNewAircraftAvail, /* DNC_AIRCRAFTAVAIL */ |
58 DrawNewsNewAircraftAvail, /* DNC_AIRCRAFTAVAIL */ |
55 DrawNewsBankrupcy, /* DNC_BANKRUPCY */ |
59 DrawNewsBankrupcy, /* DNC_BANKRUPCY */ |
56 }; |
60 }; |
57 |
61 |
58 GetNewsStringCallbackProc * const _get_news_string_callback[] = { |
62 GetNewsStringCallbackProc * const _get_news_string_callback[] = { |
59 GetNewsStringNewTrainAvail, /* DNC_TRAINAVAIL */ |
63 GetNewsStringNewTrainAvail, /* DNC_TRAINAVAIL */ |
60 GetNewsStringNewRoadVehAvail, /* DNC_ROADAVAIL */ |
64 GetNewsStringNewRoadVehAvail, /* DNC_ROADAVAIL */ |
61 GetNewsStringNewShipAvail, /* DNC_SHIPAVAIL */ |
65 GetNewsStringNewShipAvail, /* DNC_SHIPAVAIL */ |
62 GetNewsStringNewAircraftAvail, /* DNC_AIRCRAFTAVAIL */ |
66 GetNewsStringNewAircraftAvail, /* DNC_AIRCRAFTAVAIL */ |
63 GetNewsStringBankrupcy, /* DNC_BANKRUPCY */ |
67 GetNewsStringBankrupcy, /* DNC_BANKRUPCY */ |
64 }; |
68 }; |
65 |
69 |
66 void InitNewsItemStructs() |
70 void InitNewsItemStructs(void) |
67 { |
71 { |
68 memset(_news_items, 0, sizeof(NewsItem)*MAX_NEWS); |
72 memset(_news_items, 0, sizeof(_news_items)); |
69 _current_news = 255; |
73 _current_news = INVALID_NEWS; |
70 _oldest_news = 0; |
74 _oldest_news = 0; |
71 _latest_news = 255; |
75 _latest_news = INVALID_NEWS; |
72 _forced_news = 255; |
76 _forced_news = INVALID_NEWS; |
73 _total_news = 0; |
77 _total_news = 0; |
74 } |
78 } |
75 |
79 |
76 void DrawNewsBorder(Window *w) |
80 void DrawNewsBorder(const Window *w) |
77 { |
81 { |
78 int left = 0; |
82 int left = 0; |
79 int right = w->width - 1; |
83 int right = w->width - 1; |
80 int top = 0; |
84 int top = 0; |
81 int bottom = w->height - 1; |
85 int bottom = w->height - 1; |
90 DrawString(left + 2, top + 1, STR_00C6, 0); |
94 DrawString(left + 2, top + 1, STR_00C6, 0); |
91 } |
95 } |
92 |
96 |
93 static void NewsWindowProc(Window *w, WindowEvent *e) |
97 static void NewsWindowProc(Window *w, WindowEvent *e) |
94 { |
98 { |
95 switch(e->event) { |
99 switch (e->event) { |
96 case WE_PAINT: { |
100 case WE_PAINT: { |
97 NewsItem *ni = WP(w,news_d).ni; |
101 const NewsItem *ni = WP(w, news_d).ni; |
98 ViewPort *vp; |
102 ViewPort *vp; |
99 |
103 |
100 if (ni->display_mode == NM_NORMAL || ni->display_mode == NM_THIN) { |
104 switch (ni->display_mode) { |
101 DrawNewsBorder(w); |
105 case NM_NORMAL: |
102 |
106 case NM_THIN: { |
103 DrawString(2, 1, STR_00C6, 0); |
107 DrawNewsBorder(w); |
104 |
108 |
105 SET_DPARAM16(0, ni->date); |
109 DrawString(2, 1, STR_00C6, 0); |
106 DrawStringRightAligned(428, 1, STR_01FF, 0); |
110 |
107 |
111 SET_DPARAM16(0, ni->date); |
108 if (!(ni->flags & NF_VIEWPORT)) { |
112 DrawStringRightAligned(428, 1, STR_01FF, 0); |
109 COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); |
113 |
110 DrawStringMultiCenter(215, ni->display_mode == NM_NORMAL ? 76 : 56, ni->string_id, 426); |
114 if (!(ni->flags & NF_VIEWPORT)) { |
111 } else { |
115 COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); |
112 byte bk = _display_opt; |
116 DrawStringMultiCenter(215, ni->display_mode == NM_NORMAL ? 76 : 56, |
113 _display_opt |= DO_TRANS_BUILDINGS; |
117 ni->string_id, 426); |
114 DrawWindowViewport(w); |
118 } else { |
115 _display_opt = bk; |
119 byte bk = _display_opt; |
116 |
120 _display_opt |= DO_TRANS_BUILDINGS; |
117 /* Shade the viewport into gray, or color*/ |
121 DrawWindowViewport(w); |
118 vp = w->viewport; |
122 _display_opt = bk; |
119 GfxFillRect(vp->left - w->left, vp->top - w->top, vp->left - w->left + vp->width - 1, vp->top - w->top + vp->height - 1, |
123 |
120 ni->flags & NF_INCOLOR ? 0x4322:0x4323 |
124 /* Shade the viewport into gray, or color*/ |
121 ); |
125 vp = w->viewport; |
122 |
126 GfxFillRect(vp->left - w->left, vp->top - w->top, |
123 COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); |
127 vp->left - w->left + vp->width - 1, vp->top - w->top + vp->height - 1, |
124 DrawStringMultiCenter((w->width>>1), 20, ni->string_id, 428); |
128 ni->flags & NF_INCOLOR ? 0x4322 : 0x4323 |
|
129 ); |
|
130 |
|
131 COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); |
|
132 DrawStringMultiCenter(w->width / 2, 20, ni->string_id, 428); |
|
133 } |
|
134 break; |
125 } |
135 } |
126 } else if (ni->display_mode == NM_CALLBACK) { |
136 |
127 _draw_news_callback[ni->callback](w); |
137 case NM_CALLBACK: { |
128 } else { |
138 _draw_news_callback[ni->callback](w); |
129 DrawWindowWidgets(w); |
139 break; |
130 if (!(ni->flags & NF_VIEWPORT)) { |
|
131 COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); |
|
132 DrawStringMultiCenter(140,38, ni->string_id, 276); |
|
133 } else { |
|
134 DrawWindowViewport(w); |
|
135 COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); |
|
136 DrawStringMultiCenter((w->width>>1), w->height - 16, ni->string_id, 276); |
|
137 } |
140 } |
|
141 |
|
142 default: { |
|
143 DrawWindowWidgets(w); |
|
144 if (!(ni->flags & NF_VIEWPORT)) { |
|
145 COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); |
|
146 DrawStringMultiCenter(140, 38, ni->string_id, 276); |
|
147 } else { |
|
148 DrawWindowViewport(w); |
|
149 COPY_IN_DPARAM(0, ni->params, lengthof(ni->params)); |
|
150 DrawStringMultiCenter(w->width / 2, w->height - 16, ni->string_id, 276); |
|
151 } |
|
152 break; |
|
153 } |
138 } |
154 } |
139 } break; |
155 } break; |
140 |
156 |
141 case WE_CLICK: { |
157 case WE_CLICK: { |
142 switch(e->click.widget) { |
158 switch (e->click.widget) { |
143 case 1: { |
159 case 1: { |
144 NewsItem *ni = WP(w,news_d).ni; |
160 NewsItem *ni = WP(w, news_d).ni; |
145 DeleteWindow(w); |
161 DeleteWindow(w); |
146 ni->duration = 0; |
162 ni->duration = 0; |
147 if(_forced_news!=255) _forced_news = 255; |
163 _forced_news = INVALID_NEWS; |
148 } break; |
164 } break; |
149 case 0: { |
165 case 0: { |
150 NewsItem *ni = WP(w,news_d).ni; |
166 NewsItem *ni = WP(w, news_d).ni; |
151 if (ni->flags & NF_VEHICLE) { |
167 if (ni->flags & NF_VEHICLE) { |
152 Vehicle *v = &_vehicles[ni->data_a]; |
168 Vehicle *v = &_vehicles[ni->data_a]; |
153 ScrollMainWindowTo(v->x_pos, v->y_pos); |
169 ScrollMainWindowTo(v->x_pos, v->y_pos); |
154 } else if (ni->flags & NF_TILE) { |
170 } else if (ni->flags & NF_TILE) { |
155 if (!ScrollMainWindowToTile(ni->data_a) && ni->data_b != 0) |
171 if (!ScrollMainWindowToTile(ni->data_a) && ni->data_b != 0) |
202 |
218 |
203 if (_game_mode == GM_MENU) |
219 if (_game_mode == GM_MENU) |
204 return; |
220 return; |
205 |
221 |
206 // check the rare case that the oldest (to be overwritten) news item is open |
222 // check the rare case that the oldest (to be overwritten) news item is open |
207 if(_oldest_news == _current_news || _oldest_news == _forced_news) |
223 if (_oldest_news == _current_news || _oldest_news == _forced_news) |
208 MoveToNexItem(); |
224 MoveToNexItem(); |
209 |
225 |
210 _forced_news = 255; |
226 _forced_news = INVALID_NEWS; |
211 if(_total_news < MAX_NEWS) _total_news++; |
227 if (_total_news < MAX_NEWS) _total_news++; |
212 |
228 |
213 // make sure our pointer isn't overflowing |
229 // make sure our pointer isn't overflowing |
214 _latest_news = increaseIndex(_latest_news); |
230 _latest_news = increaseIndex(_latest_news); |
215 |
231 |
216 // overwrite oldest news entry |
232 // overwrite oldest news entry |
217 if( _oldest_news == _latest_news && _news_items[_oldest_news].string_id != 0) |
233 if (_oldest_news == _latest_news && _news_items[_oldest_news].string_id != 0) |
218 _oldest_news = increaseIndex(_oldest_news); // but make sure we're not overflowing here |
234 _oldest_news = increaseIndex(_oldest_news); // but make sure we're not overflowing here |
219 |
235 |
220 // add news to _latest_news |
236 // add news to _latest_news |
221 ni = &_news_items[_latest_news]; |
237 ni = &_news_items[_latest_news]; |
222 |
238 |
234 ni->data_b = data_b; |
250 ni->data_b = data_b; |
235 ni->date = _date; |
251 ni->date = _date; |
236 COPY_OUT_DPARAM(ni->params, 0, lengthof(ni->params)); |
252 COPY_OUT_DPARAM(ni->params, 0, lengthof(ni->params)); |
237 |
253 |
238 w = FindWindowById(WC_MESSAGE_HISTORY, 0); |
254 w = FindWindowById(WC_MESSAGE_HISTORY, 0); |
239 if(w==NULL) return; |
255 if (w == NULL) return; |
240 SetWindowDirty(w); |
256 SetWindowDirty(w); |
241 w->vscroll.count = _total_news; |
257 w->vscroll.count = _total_news; |
242 } |
258 } |
243 |
259 |
244 // don't show item if it's older than x days |
260 // don't show item if it's older than x days |
245 static const byte _news_items_age[] = {60, 60, 90, 60, 90, 30, 150, 30, 90, 180}; |
261 static const byte _news_items_age[] = {60, 60, 90, 60, 90, 30, 150, 30, 90, 180}; |
246 |
262 |
247 static const Widget _news_type13_widgets[] = { |
263 static const Widget _news_type13_widgets[] = { |
248 { WWT_PANEL, 15, 0, 429, 0, 169, 0x0, STR_NULL}, |
264 { WWT_PANEL, 15, 0, 429, 0, 169, 0x0, STR_NULL}, |
249 { WWT_PANEL, 15, 0, 10, 0, 11, 0x0, STR_NULL}, |
265 { WWT_PANEL, 15, 0, 10, 0, 11, 0x0, STR_NULL}, |
250 { WIDGETS_END}, |
266 { WIDGETS_END}, |
251 }; |
267 }; |
252 |
268 |
253 static WindowDesc _news_type13_desc = { |
269 static WindowDesc _news_type13_desc = { |
254 WDP_CENTER, 476, 430, 170, |
270 WDP_CENTER, 476, 430, 170, |
255 WC_NEWS_WINDOW,0, |
271 WC_NEWS_WINDOW, 0, |
256 WDF_DEF_WIDGET, |
272 WDF_DEF_WIDGET, |
257 _news_type13_widgets, |
273 _news_type13_widgets, |
258 NewsWindowProc |
274 NewsWindowProc |
259 }; |
275 }; |
260 |
276 |
261 static const Widget _news_type2_widgets[] = { |
277 static const Widget _news_type2_widgets[] = { |
262 { WWT_PANEL, 15, 0, 429, 0, 129, 0x0, STR_NULL}, |
278 { WWT_PANEL, 15, 0, 429, 0, 129, 0x0, STR_NULL}, |
263 { WWT_PANEL, 15, 0, 10, 0, 11, 0x0, STR_NULL}, |
279 { WWT_PANEL, 15, 0, 10, 0, 11, 0x0, STR_NULL}, |
264 { WIDGETS_END}, |
280 { WIDGETS_END}, |
265 }; |
281 }; |
266 |
282 |
267 static WindowDesc _news_type2_desc = { |
283 static WindowDesc _news_type2_desc = { |
268 WDP_CENTER, 476, 430, 130, |
284 WDP_CENTER, 476, 430, 130, |
269 WC_NEWS_WINDOW,0, |
285 WC_NEWS_WINDOW, 0, |
270 WDF_DEF_WIDGET, |
286 WDF_DEF_WIDGET, |
271 _news_type2_widgets, |
287 _news_type2_widgets, |
272 NewsWindowProc |
288 NewsWindowProc |
273 }; |
289 }; |
274 |
290 |
280 { WIDGETS_END}, |
296 { WIDGETS_END}, |
281 }; |
297 }; |
282 |
298 |
283 static WindowDesc _news_type0_desc = { |
299 static WindowDesc _news_type0_desc = { |
284 WDP_CENTER, 476, 280, 87, |
300 WDP_CENTER, 476, 280, 87, |
285 WC_NEWS_WINDOW,0, |
301 WC_NEWS_WINDOW, 0, |
286 WDF_DEF_WIDGET, |
302 WDF_DEF_WIDGET, |
287 _news_type0_widgets, |
303 _news_type0_widgets, |
288 NewsWindowProc |
304 NewsWindowProc |
289 }; |
305 }; |
290 |
306 |
291 static byte _news_sounds[] = { 27, 27, 0, 0, 0, 0, 28, 0, 0, 0 }; |
307 static const SoundFx _news_sounds[] = { |
|
308 SND_1D_APPLAUSE, |
|
309 SND_1D_APPLAUSE, |
|
310 0, |
|
311 0, |
|
312 0, |
|
313 0, |
|
314 SND_1E_OOOOH, |
|
315 0, |
|
316 0, |
|
317 0 |
|
318 }; |
292 |
319 |
293 // open up an own newspaper window for the news item |
320 // open up an own newspaper window for the news item |
294 static void ShowNewspaper(NewsItem *ni) |
321 static void ShowNewspaper(NewsItem *ni) |
295 { |
322 { |
296 Window *w; |
323 Window *w; |
297 int sound; |
324 int sound; |
298 int top; |
325 int top; |
299 ni->flags &= ~(NF_NOEXPIRE|NF_FORCE_BIG); |
326 ni->flags &= ~(NF_NOEXPIRE | NF_FORCE_BIG); |
300 ni->duration = 555; |
327 ni->duration = 555; |
301 |
328 |
302 sound = _news_sounds[ni->type]; |
329 sound = _news_sounds[ni->type]; |
303 if (sound != 0) |
330 if (sound != 0) |
304 SndPlayFx(sound); |
331 SndPlayFx(sound); |
305 |
332 |
306 top = _screen.height - 4; |
333 top = _screen.height - 4; |
307 if (ni->display_mode == NM_NORMAL || ni->display_mode == NM_CALLBACK) { |
334 switch (ni->display_mode) { |
308 _news_type13_desc.top = top; |
335 case NM_NORMAL: |
309 w = AllocateWindowDesc(&_news_type13_desc); |
336 case NM_CALLBACK: { |
310 if (ni->flags & NF_VIEWPORT) { |
337 _news_type13_desc.top = top; |
311 AssignWindowViewport(w, 2, 58, 0x1AA, 0x6E, ni->data_a | ((ni->flags&NF_VEHICLE) ? 0x80000000 : 0), 0); |
338 w = AllocateWindowDesc(&_news_type13_desc); |
312 } |
339 if (ni->flags & NF_VIEWPORT) |
313 } else if (ni->display_mode == NM_THIN) { |
340 AssignWindowViewport(w, 2, 58, 0x1AA, 0x6E, |
314 _news_type2_desc.top = top; |
341 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), 0); |
315 w = AllocateWindowDesc(&_news_type2_desc); |
342 break; |
316 if (ni->flags & NF_VIEWPORT) { |
343 } |
317 AssignWindowViewport(w, 2, 58, 0x1AA, 0x46, ni->data_a | ((ni->flags&NF_VEHICLE) ? 0x80000000 : 0), 0); |
344 |
318 } |
345 case NM_THIN: { |
319 } else { |
346 _news_type2_desc.top = top; |
320 _news_type0_desc.top = top; |
347 w = AllocateWindowDesc(&_news_type2_desc); |
321 w = AllocateWindowDesc(&_news_type0_desc); |
348 if (ni->flags & NF_VIEWPORT) |
322 if (ni->flags & NF_VIEWPORT) { |
349 AssignWindowViewport(w, 2, 58, 0x1AA, 0x46, |
323 AssignWindowViewport(w, 3, 17, 0x112, 0x2F, ni->data_a | ((ni->flags&NF_VEHICLE) ? 0x80000000 : 0), 0); |
350 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), 0); |
324 } |
351 break; |
325 } |
352 } |
326 WP(w,news_d).ni = &_news_items[(_forced_news==255)?_current_news:_forced_news]; |
353 |
|
354 default: { |
|
355 _news_type0_desc.top = top; |
|
356 w = AllocateWindowDesc(&_news_type0_desc); |
|
357 if (ni->flags & NF_VIEWPORT) |
|
358 AssignWindowViewport(w, 3, 17, 0x112, 0x2F, |
|
359 ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), 0); |
|
360 break; |
|
361 } |
|
362 } |
|
363 WP(w, news_d).ni = &_news_items[_forced_news == INVALID_NEWS ? _current_news : _forced_news]; |
327 w->flags4 |= WF_DISABLE_VP_SCROLL; |
364 w->flags4 |= WF_DISABLE_VP_SCROLL; |
328 } |
365 } |
329 |
366 |
330 // show news item in the ticker |
367 // show news item in the ticker |
331 static void ShowTicker(NewsItem *ni) |
368 static void ShowTicker(const NewsItem *ni) |
332 { |
369 { |
333 Window *w; |
370 Window *w; |
334 |
371 |
335 SndPlayFx(20); |
372 SndPlayFx(20); |
336 _statusbar_news_item = *ni; |
373 _statusbar_news_item = *ni; |
337 w = FindWindowById(WC_STATUS_BAR, 0); |
374 w = FindWindowById(WC_STATUS_BAR, 0); |
338 if (w != 0) |
375 if (w != NULL) |
339 WP(w,def_d).data_1 = 360; |
376 WP(w, def_d).data_1 = 360; |
340 } |
377 } |
341 |
378 |
342 |
379 |
343 // Are we ready to show another news item? |
380 // Are we ready to show another news item? |
344 // Only if nothing is in the newsticker and no newspaper is displayed |
381 // Only if nothing is in the newsticker and no newspaper is displayed |
345 static bool ReadyForNextItem() |
382 static bool ReadyForNextItem(void) |
346 { |
383 { |
347 Window *w; |
384 const Window *w; |
348 byte item = (_forced_news==255)?_current_news:_forced_news; |
385 byte item = _forced_news == INVALID_NEWS ? _current_news : _forced_news; |
349 NewsItem *ni; |
386 NewsItem *ni; |
350 |
387 |
351 if(item>=MAX_NEWS) return true; |
388 if (item >= MAX_NEWS) return true; |
352 ni = &_news_items[item]; |
389 ni = &_news_items[item]; |
353 |
390 |
354 // Ticker message |
391 // Ticker message |
355 // Check if the status bar message is still being displayed? |
392 // Check if the status bar message is still being displayed? |
356 w = FindWindowById(WC_STATUS_BAR, 0); |
393 w = FindWindowById(WC_STATUS_BAR, 0); |
357 if (w != NULL && WP(w,def_d).data_1 > -1280) |
394 if (w != NULL && WP(w, def_d).data_1 > -1280) |
358 { |
|
359 return false; |
395 return false; |
360 } |
|
361 |
396 |
362 // Newspaper message |
397 // Newspaper message |
363 // Wait until duration reaches 0 |
398 // Wait until duration reaches 0 |
364 if (ni->duration != 0) { |
399 if (ni->duration != 0) { |
365 ni->duration--; |
400 ni->duration--; |
368 |
403 |
369 // neither newsticker nor newspaper are running |
404 // neither newsticker nor newspaper are running |
370 return true; |
405 return true; |
371 } |
406 } |
372 |
407 |
373 static void MoveToNexItem() |
408 static void MoveToNexItem(void) |
374 { |
409 { |
375 DeleteWindowById(WC_NEWS_WINDOW, 0); |
410 DeleteWindowById(WC_NEWS_WINDOW, 0); |
376 _forced_news = 255; |
411 _forced_news = INVALID_NEWS; |
377 |
412 |
378 // if we're not at the last item, than move on |
413 // if we're not at the last item, than move on |
379 if(_current_news != _latest_news) |
414 if (_current_news != _latest_news) { |
380 { |
|
381 NewsItem *ni; |
415 NewsItem *ni; |
382 |
416 |
383 _current_news = increaseIndex(_current_news); |
417 _current_news = increaseIndex(_current_news); |
384 ni = &_news_items[_current_news]; |
418 ni = &_news_items[_current_news]; |
385 |
419 |
386 // check the date, don't show too old items |
420 // check the date, don't show too old items |
387 if(_date - _news_items_age[ni->type] > ni->date) |
421 if (_date - _news_items_age[ni->type] > ni->date) |
388 return; |
422 return; |
389 |
423 |
390 // show newspaper or send to ticker? |
424 // show newspaper or send to ticker? |
391 if(!HASBIT(_news_display_opt, ni->type) && !(ni->flags&NF_FORCE_BIG)) |
425 if (!HASBIT(_news_display_opt, ni->type) && !(ni->flags & NF_FORCE_BIG)) |
392 ShowTicker(ni); |
426 ShowTicker(ni); |
393 else |
427 else |
394 ShowNewspaper(ni); |
428 ShowNewspaper(ni); |
395 } |
429 } |
396 } |
430 } |
397 |
431 |
398 void NewsLoop() |
432 void NewsLoop(void) |
399 { |
433 { |
400 // no news item yet |
434 // no news item yet |
401 if(_total_news==0) return; |
435 if (_total_news == 0) return; |
402 |
436 |
403 if( ReadyForNextItem() ) |
437 if (ReadyForNextItem()) |
404 MoveToNexItem(); |
438 MoveToNexItem(); |
405 } |
439 } |
406 |
440 |
407 /* Do a forced show of a specific message */ |
441 /* Do a forced show of a specific message */ |
408 void ShowNewsMessage(byte i) |
442 void ShowNewsMessage(byte i) |
409 { |
443 { |
410 if(_total_news==0) return; |
444 if (_total_news == 0) return; |
411 |
445 |
412 // Delete the news window |
446 // Delete the news window |
413 DeleteWindowById(WC_NEWS_WINDOW, 0); |
447 DeleteWindowById(WC_NEWS_WINDOW, 0); |
414 |
448 |
415 // setup forced news item |
449 // setup forced news item |
416 _forced_news = i; |
450 _forced_news = i; |
417 |
451 |
418 if(_forced_news!=255) |
452 if (_forced_news != INVALID_NEWS) { |
419 { |
|
420 NewsItem *ni = &_news_items[_forced_news]; |
453 NewsItem *ni = &_news_items[_forced_news]; |
421 ni->duration = 555; |
454 ni->duration = 555; |
422 ni->flags |= NF_NOEXPIRE | NF_FORCE_BIG; |
455 ni->flags |= NF_NOEXPIRE | NF_FORCE_BIG; |
423 DeleteWindowById(WC_NEWS_WINDOW, 0); |
456 DeleteWindowById(WC_NEWS_WINDOW, 0); |
424 ShowNewspaper(ni); |
457 ShowNewspaper(ni); |
425 } |
458 } |
426 } |
459 } |
427 |
460 |
428 void ShowLastNewsMessage() |
461 void ShowLastNewsMessage(void) |
429 { |
462 { |
430 if(_forced_news==255) |
463 if (_forced_news == INVALID_NEWS) |
431 ShowNewsMessage(_current_news); |
464 ShowNewsMessage(_current_news); |
432 else if(_forced_news!=0) |
465 else if (_forced_news != 0) |
433 ShowNewsMessage(_forced_news-1); |
466 ShowNewsMessage(_forced_news - 1); |
434 else { |
467 else { |
435 if(_total_news != MAX_NEWS) |
468 if (_total_news != MAX_NEWS) |
436 ShowNewsMessage(_latest_news); |
469 ShowNewsMessage(_latest_news); |
437 else |
470 else |
438 ShowNewsMessage(MAX_NEWS-1); |
471 ShowNewsMessage(MAX_NEWS - 1); |
439 } |
472 } |
440 } |
473 } |
441 |
474 |
442 |
475 |
443 /* return news by number, with 0 being the most |
476 /* return news by number, with 0 being the most |
444 recent news. Returns 255 if end of queue reached. */ |
477 recent news. Returns INVALID_NEWS if end of queue reached. */ |
445 static byte getNews(byte i) |
478 static byte getNews(byte i) |
446 { |
479 { |
447 if(i>=_total_news) |
480 if (i >= _total_news) |
448 return 255; |
481 return INVALID_NEWS; |
449 |
482 |
450 if(_latest_news < i) |
483 if (_latest_news < i) |
451 i = _latest_news + MAX_NEWS - i; |
484 i = _latest_news + MAX_NEWS - i; |
452 else |
485 else |
453 i = _latest_news - i; |
486 i = _latest_news - i; |
454 |
487 |
455 i = i % MAX_NEWS; |
488 i %= MAX_NEWS; |
456 return i; |
489 return i; |
457 } |
490 } |
458 |
491 |
459 static void GetNewsString(NewsItem *ni, byte *buffer) |
492 static void GetNewsString(NewsItem *ni, byte *buffer) |
460 { |
493 { |
472 assert(strlen(str_buffr) < sizeof(str_buffr) - 1); |
505 assert(strlen(str_buffr) < sizeof(str_buffr) - 1); |
473 |
506 |
474 s = str_buffr; |
507 s = str_buffr; |
475 d = buffer; |
508 d = buffer; |
476 |
509 |
477 for(;;s++) { |
510 for (;; s++) { |
478 // cut strings that are too long |
511 // cut strings that are too long |
479 if(s >= str_buffr + 55) { |
512 if (s >= str_buffr + 55) { |
480 d[0] = d[1] = d[2] = '.'; |
513 d[0] = d[1] = d[2] = '.'; |
481 d+=3; |
514 d += 3; |
482 *d = 0; |
515 *d = '\0'; |
483 break; |
516 break; |
484 } |
517 } |
485 |
518 |
486 if (*s == 0) { |
519 if (*s == '\0') { |
487 *d = 0; |
520 *d = '\0'; |
488 break; |
521 break; |
489 } else if (*s == 13) { |
522 } else if (*s == '\r') { |
490 d[0] = d[1] = d[2] = d[3] = ' '; |
523 d[0] = d[1] = d[2] = d[3] = ' '; |
491 d+=4; |
524 d += 4; |
492 } else if (*s >= ' ' && (*s < 0x88 || *s >= 0x99)) { |
525 } else if (*s >= ' ' && (*s < 0x88 || *s >= 0x99)) { |
493 *d++ = *s; |
526 *d++ = *s; |
494 } |
527 } |
495 } |
528 } |
496 } |
529 } |
497 |
530 |
498 |
531 |
499 static void MessageHistoryWndProc(Window *w, WindowEvent *e) |
532 static void MessageHistoryWndProc(Window *w, WindowEvent *e) |
500 { |
533 { |
501 switch(e->event) { |
534 switch (e->event) { |
502 case WE_PAINT: { |
535 case WE_PAINT: { |
503 byte buffer[256]; |
536 byte buffer[256]; |
504 int y=19; |
537 int y = 19; |
505 byte p, show; |
538 byte p, show; |
506 NewsItem *ni; |
539 NewsItem *ni; |
507 |
540 |
508 DrawWindowWidgets(w); |
541 DrawWindowWidgets(w); |
509 |
542 |
510 if(_total_news==0) break; |
543 if (_total_news == 0) break; |
511 show = min(_total_news, 10); |
544 show = min(_total_news, 10); |
512 |
545 |
513 for(p=w->vscroll.pos; p<w->vscroll.pos+show; p++) |
546 for (p = w->vscroll.pos; p < w->vscroll.pos + show; p++) { |
514 { |
|
515 // get news in correct order |
547 // get news in correct order |
516 ni = &_news_items[ getNews(p) ]; |
548 ni = &_news_items[getNews(p)]; |
517 |
549 |
518 SET_DPARAM16(0, ni->date); |
550 SET_DPARAM16(0, ni->date); |
519 DrawString(4, y, STR_00AF, 16); |
551 DrawString(4, y, STR_00AF, 16); |
520 |
552 |
521 GetNewsString(ni, buffer); |
553 GetNewsString(ni, buffer); |
525 |
557 |
526 break; |
558 break; |
527 } |
559 } |
528 |
560 |
529 case WE_CLICK: |
561 case WE_CLICK: |
530 switch(e->click.widget) { |
562 switch (e->click.widget) { |
531 case 2: { |
563 case 2: { |
532 int y = (e->click.pt.y - 19) / 12; |
564 int y = (e->click.pt.y - 19) / 12; |
533 byte p, q; |
565 byte p, q; |
534 |
566 |
535 /* // === DEBUG code only |
567 #if 0 // === DEBUG code only |
536 for(p=0; p<_total_news; p++) |
568 for (p = 0; p < _total_news; p++) |
537 { |
569 { |
538 NewsItem *ni; |
570 NewsItem *ni; |
539 byte buffer[256]; |
571 byte buffer[256]; |
540 ni=&_news_items[p]; |
572 ni = &_news_items[p]; |
541 GetNewsString(ni, buffer); |
573 GetNewsString(ni, buffer); |
542 printf("%i\t%i\t%s\n", p, ni->date, buffer); |
574 printf("%i\t%i\t%s\n", p, ni->date, buffer); |
543 } |
575 } |
544 printf("=========================\n"); |
576 printf("=========================\n"); |
545 // === END OF DEBUG CODE */ |
577 #endif |
546 |
578 |
547 p = y + w->vscroll.pos; |
579 p = y + w->vscroll.pos; |
548 if( p > _total_news-1 ) break; |
580 if (p > _total_news - 1) break; |
549 |
581 |
550 if(_latest_news >= p) q=_latest_news - p; |
582 if (_latest_news >= p) |
551 else q=_latest_news + MAX_NEWS - p; |
583 q = _latest_news - p; |
|
584 else |
|
585 q = _latest_news + MAX_NEWS - p; |
552 ShowNewsMessage(q); |
586 ShowNewsMessage(q); |
553 |
587 |
554 break; |
588 break; |
555 } |
589 } |
556 } |
590 } |
566 { WIDGETS_END}, |
600 { WIDGETS_END}, |
567 }; |
601 }; |
568 |
602 |
569 static const WindowDesc _message_history_desc = { |
603 static const WindowDesc _message_history_desc = { |
570 240, 22, 400, 140, |
604 240, 22, 400, 140, |
571 WC_MESSAGE_HISTORY,0, |
605 WC_MESSAGE_HISTORY, 0, |
572 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
606 WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, |
573 _message_history_widgets, |
607 _message_history_widgets, |
574 MessageHistoryWndProc |
608 MessageHistoryWndProc |
575 }; |
609 }; |
576 |
610 |
577 void ShowMessageHistory() |
611 void ShowMessageHistory(void) |
578 { |
612 { |
579 Window *w; |
613 Window *w; |
580 |
614 |
581 DeleteWindowById(WC_MESSAGE_HISTORY, 0); |
615 DeleteWindowById(WC_MESSAGE_HISTORY, 0); |
582 w = AllocateWindowDesc(&_message_history_desc); |
616 w = AllocateWindowDesc(&_message_history_desc); |
583 |
617 |
584 if (w) { |
618 if (w != NULL) { |
585 w->vscroll.cap = 10; |
619 w->vscroll.cap = 10; |
586 w->vscroll.count = _total_news; |
620 w->vscroll.count = _total_news; |
587 SetWindowDirty(w); |
621 SetWindowDirty(w); |
588 } |
622 } |
589 } |
623 } |
590 |
624 |
591 |
625 |
592 static void MessageOptionsWndProc(Window *w, WindowEvent *e) |
626 static void MessageOptionsWndProc(Window *w, WindowEvent *e) |
593 { |
627 { |
594 switch(e->event) { |
628 switch (e->event) { |
595 case WE_PAINT: { |
629 case WE_PAINT: { |
596 uint16 x = _news_display_opt; |
630 uint16 x = _news_display_opt; |
597 uint32 cs = 0; |
631 uint32 cs = 0; |
598 int i, y; |
632 int i, y; |
599 |
633 |
600 for(i=3; i!=23; i+=2) { |
634 for (i = 3; i != 23; i += 2) { |
601 cs |= 1 << (i + (x&1)); |
635 cs |= 1 << (i + (x & 1)); |
602 x >>= 1; |
636 x >>= 1; |
603 } |
637 } |
604 cs |= (w->click_state >> 23) << 23; |
638 cs |= (w->click_state >> 23) << 23; |
605 |
639 |
606 w->click_state = cs; |
640 w->click_state = cs; |
607 DrawWindowWidgets(w); |
641 DrawWindowWidgets(w); |
608 |
642 |
609 DrawStringCentered(185, 15, STR_0205_MESSAGE_TYPES, 0); |
643 DrawStringCentered(185, 15, STR_0205_MESSAGE_TYPES, 0); |
610 |
644 |
611 y = 27; |
645 y = 27; |
612 for(i=STR_0206_ARRIVAL_OF_FIRST_VEHICLE; i <= STR_020F_GENERAL_INFORMATION; i++) { |
646 for (i = STR_0206_ARRIVAL_OF_FIRST_VEHICLE; i <= STR_020F_GENERAL_INFORMATION; i++) { |
613 DrawString(124, y, i, 0); |
647 DrawString(124, y, i, 0); |
614 y += 12; |
648 y += 12; |
615 } |
649 } |
616 |
650 |
617 break; |
651 break; |
618 } |
652 } |
619 |
653 |
620 case WE_CLICK: { |
654 case WE_CLICK: { |
621 int wid; |
655 int wid; |
622 if ( (uint)(wid=e->click.widget - 3) < 20) { |
656 if ((uint)(wid = e->click.widget - 3) < 20) { |
623 if (!(wid & 1)) { |
657 if (!(wid & 1)) |
624 _news_display_opt &= ~(1 << (wid>>1)); |
658 _news_display_opt &= ~(1 << (wid / 2)); |
625 } else { |
659 else |
626 _news_display_opt |= (1 << (wid>>1)); |
660 _news_display_opt |= (1 << (wid / 2)); |
627 } |
|
628 SetWindowDirty(w); |
661 SetWindowDirty(w); |
629 // XXX: write settings |
662 // XXX: write settings |
630 } |
663 } |
631 if( e->click.widget == 23) { |
664 if (e->click.widget == 23) { |
632 _news_display_opt = 0; |
665 _news_display_opt = 0; |
633 HandleButtonClick(w, 23); |
666 HandleButtonClick(w, 23); |
634 SetWindowDirty(w); |
667 SetWindowDirty(w); |
635 } |
668 } |
636 if( e->click.widget == 24) { |
669 if (e->click.widget == 24) { |
637 _news_display_opt = ~0; |
670 _news_display_opt = ~0; |
638 HandleButtonClick(w, 24); |
671 HandleButtonClick(w, 24); |
639 SetWindowDirty(w); |
672 SetWindowDirty(w); |
640 } |
673 } |
641 } break; |
674 } break; |