Changeset - r11464:d0a348843230
[Not reviewed]
master
0 3 0
smatz - 15 years ago 2009-03-23 11:48:05
smatz@openttd.org
(svn r15830) -Codechange: don't use fixed size of array in news_gui.cpp and news_func.h
2 files changed with 7 insertions and 3 deletions:
0 comments (0 inline, 0 general)
src/news_func.h
Show inline comments
 
/* $Id$ */
 

	
 
/** @file news_func.h Functions related to news. */
 

	
 
#ifndef NEWS_FUNC_H
 
#define NEWS_FUNC_H
 

	
 
#include "news_type.h"
 
#include "vehicle_type.h"
 
#include "station_type.h"
 

	
 
void AddNewsItem(StringID string, NewsSubtype subtype, uint data_a, uint data_b, void *free_data = NULL);
 
void NewsLoop();
 
void InitNewsItemStructs();
 

	
 
extern NewsItem _statusbar_news_item;
 
extern bool _news_ticker_sound;
 

	
 
extern NewsTypeData _news_type_data[NT_END];
 
extern NewsTypeData _news_type_data[];
 

	
 
/**
 
 * Delete a news item type about a vehicle
 
 * if the news item type is INVALID_STRING_ID all news about the vehicle get
 
 * deleted
 
 */
 
void DeleteVehicleNews(VehicleID, StringID news);
 

	
 
/** Delete news associated with given station */
 
void DeleteStationNews(StationID);
 

	
 
#endif /* NEWS_FUNC_H */
src/news_gui.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/** @file news_gui.cpp GUI functions related to news messages. */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "gui.h"
 
#include "window_gui.h"
 
#include "viewport_func.h"
 
#include "news_type.h"
 
#include "settings_type.h"
 
#include "transparency.h"
 
#include "strings_func.h"
 
#include "window_func.h"
 
#include "date_func.h"
 
#include "vehicle_base.h"
 
#include "sound_func.h"
 
#include "string_func.h"
 
#include "widgets/dropdown_func.h"
 
#include "statusbar_gui.h"
 
#include "company_manager_face.h"
 

	
 
#include "table/strings.h"
 

	
 
#define NB_WIDG_PER_SETTING 4
 

	
 
NewsItem _statusbar_news_item;
 
bool _news_ticker_sound;
 

	
 
static uint MIN_NEWS_AMOUNT = 30;           ///< prefered minimum amount of news messages
 
static uint _total_news = 0;                ///< current number of news items
 
static NewsItem *_oldest_news = NULL;       ///< head of news items queue
 
static NewsItem *_latest_news = NULL;       ///< tail of news items queue
 

	
 
/** 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 NULL. */
 
static NewsItem *_forced_news = NULL;       ///< item the user has asked for
 

	
 
/** Current news item (last item shown regularly). */
 
static NewsItem *_current_news = NULL;
 

	
 

	
 
typedef void DrawNewsCallbackProc(struct Window *w, const NewsItem *ni);
 
void DrawNewsNewVehicleAvail(Window *w, const NewsItem *ni);
 

	
 
static void DrawNewsBankrupcy(Window *w, const NewsItem *ni)
 
{
 
	const CompanyNewsInformation *cni = (const CompanyNewsInformation*)ni->free_data;
 

	
 
	DrawCompanyManagerFace(cni->face, cni->colour, 2, 23);
 
	GfxFillRect(3, 23, 3 + 91, 23 + 118, PALETTE_TO_STRUCT_GREY, FILLRECT_RECOLOUR);
 

	
 
	SetDParamStr(0, cni->president_name);
 
	DrawStringMultiLine(49 - MAX_LENGTH_PRESIDENT_NAME_PIXELS / 2, 49 + MAX_LENGTH_PRESIDENT_NAME_PIXELS / 2, 141, 169, STR_JUST_RAW_STRING, SA_CENTER);
 

	
 
	switch (ni->subtype) {
 
		case NS_COMPANY_TROUBLE:
 
			DrawString(0, w->width, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, TC_FROMSTRING, SA_CENTER);
 

	
 
			SetDParam(0, ni->params[2]);
 

	
 
			DrawStringMultiLine(100, w->width - 2, 20, 169, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED, SA_CENTER);
 
			break;
 

	
 
		case NS_COMPANY_MERGER:
 
			DrawString(0, w->width, 1, STR_7059_TRANSPORT_COMPANY_MERGER, TC_FROMSTRING, SA_CENTER);
 
			SetDParam(0, ni->params[2]);
 
			SetDParam(1, ni->params[3]);
 
			SetDParam(2, ni->params[4]);
 
			DrawStringMultiLine(100, w->width - 2, 20, 169, ni->params[4] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR, SA_CENTER);
 
			break;
 

	
 
		case NS_COMPANY_BANKRUPT:
 
			DrawString(0, w->width, 1, STR_705C_BANKRUPT, TC_FROMSTRING, SA_CENTER);
 
			SetDParam(0, ni->params[2]);
 
			DrawStringMultiLine(100, w->width - 2, 20, 169, STR_705D_HAS_BEEN_CLOSED_DOWN_BY, SA_CENTER);
 
			break;
 

	
 
		case NS_COMPANY_NEW:
 
			DrawString(0, w->width, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, TC_FROMSTRING, SA_CENTER);
 
			SetDParam(0, ni->params[2]);
 
			SetDParam(1, ni->params[3]);
 
			DrawStringMultiLine(100, w->width - 2, 20, 169, STR_705F_STARTS_CONSTRUCTION_NEAR, SA_CENTER);
 
			break;
 

	
 
		default:
 
			NOT_REACHED();
 
	}
 
}
 

	
 

	
 
/**
 
 * Data common to all news items of a given subtype (structure)
 
 */
 
struct NewsSubtypeData {
 
	NewsType type;         ///< News category @see NewsType
 
	NewsMode display_mode; ///< Display mode value @see NewsMode
 
	NewsFlag flags;        ///< Initial NewsFlags bits @see NewsFlag
 
	DrawNewsCallbackProc *callback; ///< Call-back function
 
};
 

	
 
/**
 
 * Data common to all news items of a given subtype (actual data)
 
 */
 
static const struct NewsSubtypeData _news_subtype_data[NS_END] = {
 
static const NewsSubtypeData _news_subtype_data[] = {
 
	/* type,               display_mode, flags,                  callback */
 
	{ NT_ARRIVAL_COMPANY,  NM_THIN,     NF_VIEWPORT|NF_VEHICLE, NULL                    }, ///< NS_ARRIVAL_COMPANY
 
	{ NT_ARRIVAL_OTHER,    NM_THIN,     NF_VIEWPORT|NF_VEHICLE, NULL                    }, ///< NS_ARRIVAL_OTHER
 
	{ NT_ACCIDENT,         NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_ACCIDENT_TILE
 
	{ NT_ACCIDENT,         NM_THIN,     NF_VIEWPORT|NF_VEHICLE, NULL                    }, ///< NS_ACCIDENT_VEHICLE
 
	{ NT_COMPANY_INFO,     NM_NORMAL,   NF_NONE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_TROUBLE
 
	{ NT_COMPANY_INFO,     NM_NORMAL,   NF_NONE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_MERGER
 
	{ NT_COMPANY_INFO,     NM_NORMAL,   NF_NONE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_BANKRUPT
 
	{ NT_COMPANY_INFO,     NM_NORMAL,   NF_TILE,                DrawNewsBankrupcy       }, ///< NS_COMPANY_NEW
 
	{ NT_INDUSTRY_OPEN,    NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_OPEN
 
	{ NT_INDUSTRY_CLOSE,   NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_CLOSE
 
	{ NT_ECONOMY,          NM_NORMAL,   NF_NONE,                NULL                    }, ///< NS_ECONOMY
 
	{ NT_INDUSTRY_COMPANY, NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_COMPANY
 
	{ NT_INDUSTRY_OTHER,   NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_OTHER
 
	{ NT_INDUSTRY_NOBODY,  NM_THIN,     NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_INDUSTRY_NOBODY
 
	{ NT_ADVICE,           NM_SMALL,    NF_VIEWPORT|NF_VEHICLE, NULL                    }, ///< NS_ADVICE
 
	{ NT_NEW_VEHICLES,     NM_NORMAL,   NF_NONE,                DrawNewsNewVehicleAvail }, ///< NS_NEW_VEHICLES
 
	{ NT_ACCEPTANCE,       NM_SMALL,    NF_VIEWPORT|NF_TILE,    NULL                    }, ///< NS_ACCEPTANCE
 
	{ NT_SUBSIDIES,        NM_NORMAL,   NF_TILE|NF_TILE2,       NULL                    }, ///< NS_SUBSIDIES
 
	{ NT_GENERAL,          NM_NORMAL,   NF_TILE,                NULL                    }, ///< NS_GENERAL
 
};
 

	
 
assert_compile(lengthof(_news_subtype_data) == NS_END);
 

	
 
/**
 
 * Per-NewsType data
 
 */
 
NewsTypeData _news_type_data[NT_END] = {
 
NewsTypeData _news_type_data[] = {
 
	/* name,              age, sound,           display */
 
	{ "arrival_player",    60, SND_1D_APPLAUSE, ND_FULL },  ///< NT_ARRIVAL_COMPANY
 
	{ "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
 
	{ "open",              90, SND_BEGIN,       ND_FULL },  ///< NT_INDUSTRY_OPEN
 
	{ "close",             90, SND_BEGIN,       ND_FULL },  ///< NT_INDUSTRY_CLOSE
 
	{ "economy",           30, SND_BEGIN,       ND_FULL },  ///< NT_ECONOMY
 
	{ "production_player", 30, SND_BEGIN,       ND_FULL },  ///< NT_INDUSTRY_COMPANY
 
	{ "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
 
};
 

	
 
assert_compile(lengthof(_news_type_data) == NT_END);
 

	
 
struct NewsWindow : Window {
 
	uint16 chat_height;
 
	NewsItem *ni;
 
	static uint duration;
 

	
 
	NewsWindow(const WindowDesc *desc, NewsItem *ni) : Window(desc), ni(ni)
 
	{
 
		NewsWindow::duration = 555;
 
		const Window *w = FindWindowById(WC_SEND_NETWORK_MSG, 0);
 
		this->chat_height = (w != NULL) ? w->height : 0;
 

	
 
		this->ni = _forced_news == NULL ? _current_news : _forced_news;
 
		this->flags4 |= WF_DISABLE_VP_SCROLL;
 

	
 
		this->FindWindowPlacementAndResize(desc);
 
	}
 

	
 
	void DrawNewsBorder()
 
	{
 
		int left = 0;
 
		int right = this->width - 1;
 
		int top = 0;
 
		int bottom = this->height - 1;
 

	
 
		GfxFillRect(left,  top,    right, bottom, 0xF);
 

	
 
		GfxFillRect(left,  top,    left,  bottom, 0xD7);
 
		GfxFillRect(right, top,    right, bottom, 0xD7);
 
		GfxFillRect(left,  top,    right, top,    0xD7);
 
		GfxFillRect(left,  bottom, right, bottom, 0xD7);
 

	
 
		DrawString(left + 2, right - 2, top + 1, STR_00C6, TC_FROMSTRING);
 
	}
 

	
 
	virtual void OnPaint()
 
	{
 
		const NewsMode display_mode = _news_subtype_data[this->ni->subtype].display_mode;
 

	
 
		switch (display_mode) {
 
			case NM_NORMAL:
 
			case NM_THIN: {
 
				this->DrawNewsBorder();
 

	
 
				if (_news_subtype_data[this->ni->subtype].callback != NULL) {
 
					(_news_subtype_data[this->ni->subtype].callback)(this, ni);
 
					break;
 
				}
 

	
 
				DrawString(2, this->width - 1, 1, STR_00C6, TC_FROMSTRING);
 

	
 
				SetDParam(0, this->ni->date);
 
				DrawString(2, this->width - 1, 1, STR_01FF, TC_FROMSTRING, SA_RIGHT);
 

	
 
				if (!(this->ni->flags & NF_VIEWPORT)) {
 
					CopyInDParam(0, this->ni->params, lengthof(this->ni->params));
 
					DrawStringMultiLine(2, this->width - 2, 20, this->height, this->ni->string_id, SA_CENTER);
 
				} else {
 
					/* Back up transparency options to draw news view */
 
					TransparencyOptionBits to_backup = _transparency_opt;
 
					_transparency_opt = 0;
 
					this->DrawViewport();
 
					_transparency_opt = to_backup;
 

	
 
					/* Shade the viewport into gray, or colour*/
 
					ViewPort *vp = this->viewport;
 
					GfxFillRect(vp->left - this->left, vp->top - this->top,
 
						vp->left - this->left + vp->width - 1, vp->top - this->top + vp->height - 1,
 
						(this->ni->flags & NF_INCOLOUR ? PALETTE_TO_TRANSPARENT : PALETTE_TO_STRUCT_GREY), FILLRECT_RECOLOUR
 
					);
 

	
 
					CopyInDParam(0, this->ni->params, lengthof(this->ni->params));
 
					DrawStringMultiLine(2, this->width - 2, 0, 58, this->ni->string_id, SA_CENTER);
 
				}
 
				break;
 
			}
 

	
 
			default:
 
				this->DrawWidgets();
 
				if (!(this->ni->flags & NF_VIEWPORT)) {
 
					CopyInDParam(0, this->ni->params, lengthof(this->ni->params));
 
					DrawStringMultiLine(2, 278, 38, this->ni->string_id, SA_CENTER);
 
				} else {
 
					this->DrawViewport();
 
					CopyInDParam(0, this->ni->params, lengthof(this->ni->params));
 
					DrawStringMultiLine(2, this->width - 2, 64, this->height, this->ni->string_id, SA_CENTER);
 
				}
 
				break;
 
		}
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case 1:
 
				NewsWindow::duration = 0;
 
				delete this;
 
				_forced_news = NULL;
 
				break;
 

	
 
			case 0:
 
				if (this->ni->flags & NF_VEHICLE) {
 
					const Vehicle *v = GetVehicle(this->ni->data_a);
 
					ScrollMainWindowTo(v->x_pos, v->y_pos, v->z_pos);
 
				} else if (this->ni->flags & NF_TILE) {
 
					if (_ctrl_pressed) {
 
						ShowExtraViewPortWindow(this->ni->data_a);
 
						if (this->ni->flags & NF_TILE2) {
 
							ShowExtraViewPortWindow(this->ni->data_b);
 
						}
 
					} else {
 
						if (!ScrollMainWindowToTile(this->ni->data_a) && this->ni->flags & NF_TILE2) {
 
							ScrollMainWindowToTile(this->ni->data_b);
 
						}
 
					}
 
				}
 
				break;
 
		}
 
	}
 

	
 
	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
 
	{
 
		if (keycode == WKC_SPACE) {
 
			/* Don't continue. */
 
			delete this;
 
			return ES_HANDLED;
 
		}
 
		return ES_NOT_HANDLED;
 
	}
 

	
 
	virtual void OnInvalidateData(int data)
 
	{
 
		/* The chatbar has notified us that is was either created or closed */
 
		this->chat_height = data;
 
	}
 

	
 
	virtual void OnTick()
 
	{
 
		/* Scroll up newsmessages from the bottom in steps of 4 pixels */
 
		int y = max(this->top - 4, _screen.height - this->height - 12 - this->chat_height);
 
		if (y == this->top) return;
 

	
 
		if (this->viewport != NULL) this->viewport->top += y - this->top;
 

	
 
		int diff = Delta(this->top, y);
 
		this->top = y;
 

	
 
		SetDirtyBlocks(this->left, this->top - diff, this->left + this->width, this->top + this->height);
 
	}
 
};
 

	
 
/* static */ uint NewsWindow::duration; ///< Remaining time for showing current news message
 

	
 

	
 
static const Widget _news_type13_widgets[] = {
 
{      WWT_PANEL,   RESIZE_NONE,  COLOUR_WHITE,     0,   429,     0,   169, 0x0, STR_NULL},
 
{      WWT_PANEL,   RESIZE_NONE,  COLOUR_WHITE,     0,    10,     0,    11, 0x0, STR_NULL},
 
{   WIDGETS_END},
 
};
 

	
 
static WindowDesc _news_type13_desc(
 
	WDP_CENTER, 476, 430, 170, 430, 170,
 
	WC_NEWS_WINDOW, WC_NONE,
 
	WDF_DEF_WIDGET,
 
	_news_type13_widgets
 
);
 

	
 
static const Widget _news_type2_widgets[] = {
 
{      WWT_PANEL,   RESIZE_NONE,  COLOUR_WHITE,     0,   429,     0,   129, 0x0, STR_NULL},
 
{      WWT_PANEL,   RESIZE_NONE,  COLOUR_WHITE,     0,    10,     0,    11, 0x0, STR_NULL},
 
{   WIDGETS_END},
 
};
 

	
 
static WindowDesc _news_type2_desc(
 
	WDP_CENTER, 476, 430, 130, 430, 130,
 
	WC_NEWS_WINDOW, WC_NONE,
 
	WDF_DEF_WIDGET,
 
	_news_type2_widgets
 
);
 

	
 
static const Widget _news_type0_widgets[] = {
 
{      WWT_PANEL,   RESIZE_NONE,  COLOUR_LIGHT_BLUE,     0,   279,    14,    86, 0x0,              STR_NULL},
 
{   WWT_CLOSEBOX,   RESIZE_NONE,  COLOUR_LIGHT_BLUE,     0,    10,     0,    13, STR_00C5,         STR_018B_CLOSE_WINDOW},
 
{    WWT_CAPTION,   RESIZE_NONE,  COLOUR_LIGHT_BLUE,    11,   279,     0,    13, STR_012C_MESSAGE, STR_NULL},
 
{      WWT_INSET,   RESIZE_NONE,  COLOUR_LIGHT_BLUE,     2,   277,    16,    64, 0x0,              STR_NULL},
 
{   WIDGETS_END},
 
};
 

	
 
static NWidgetPart _nested_news_type0_widgets[] = {
 
	/* Caption + close box */
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE, 1), SetMinimalSize(11, 14), SetDataTip(STR_00C5, STR_018B_CLOSE_WINDOW),
 
		NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, 2), SetMinimalSize(269, 14), SetDataTip(STR_012C_MESSAGE, STR_NULL),
0 comments (0 inline, 0 general)