Changeset - r15175:66e0817dc450
[Not reviewed]
master
0 30 0
rubidium - 14 years ago 2010-05-13 10:14:29
rubidium@openttd.org
(svn r19814) -Codechange: give some more unnamed enums a name, in case they consisted of unrelated values use static const (u)int
30 files changed with 82 insertions and 125 deletions:
0 comments (0 inline, 0 general)
src/ai/ai_instance.cpp
Show inline comments
 
@@ -415,99 +415,97 @@ void AIInstance::CollectGarbage() const
 
	instance->engine->InsertResult(AIObject::GetNewGroupID());
 
}
 

	
 
/* static */ AIStorage *AIInstance::GetStorage()
 
{
 
	assert(Company::IsValidAiID(_current_company));
 
	return Company::Get(_current_company)->ai_instance->storage;
 
}
 

	
 
/*
 
 * All data is stored in the following format:
 
 * First 1 byte indicating if there is a data blob at all.
 
 * 1 byte indicating the type of data.
 
 * The data itself, this differs per type:
 
 *  - integer: a binary representation of the integer (int32).
 
 *  - string:  First one byte with the string length, then a 0-terminated char
 
 *             array. The string can't be longer than 255 bytes (including
 
 *             terminating '\0').
 
 *  - array:   All data-elements of the array are saved recursive in this
 
 *             format, and ended with an element of the type
 
 *             SQSL_ARRAY_TABLE_END.
 
 *  - table:   All key/value pairs are saved in this format (first key 1, then
 
 *             value 1, then key 2, etc.). All keys and values can have an
 
 *             arbitrary type (as long as it is supported by the save function
 
 *             of course). The table is ended with an element of the type
 
 *             SQSL_ARRAY_TABLE_END.
 
 *  - bool:    A single byte with value 1 representing true and 0 false.
 
 *  - null:    No data.
 
 */
 

	
 
/** The type of the data that follows in the savegame. */
 
enum SQSaveLoadType {
 
	SQSL_INT             = 0x00, ///< The following data is an integer.
 
	SQSL_STRING          = 0x01, ///< The following data is an string.
 
	SQSL_ARRAY           = 0x02, ///< The following data is an array.
 
	SQSL_TABLE           = 0x03, ///< The following data is an table.
 
	SQSL_BOOL            = 0x04, ///< The following data is a boolean.
 
	SQSL_NULL            = 0x05, ///< A null variable.
 
	SQSL_ARRAY_TABLE_END = 0xFF, ///< Marks the end of an array or table, no data follows.
 
};
 

	
 
static byte _ai_sl_byte;
 

	
 
static const SaveLoad _ai_byte[] = {
 
	SLEG_VAR(_ai_sl_byte, SLE_UINT8),
 
	SLE_END()
 
};
 

	
 
enum {
 
	AISAVE_MAX_DEPTH = 25, ///< The maximum recursive depth for items stored in the savegame.
 
};
 
static const uint AISAVE_MAX_DEPTH = 25; ///< The maximum recursive depth for items stored in the savegame.
 

	
 
/* static */ bool AIInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test)
 
{
 
	if (max_depth == 0) {
 
		AILog::Error("Savedata can only be nested to 25 deep. No data saved.");
 
		return false;
 
	}
 

	
 
	switch (sq_gettype(vm, index)) {
 
		case OT_INTEGER: {
 
			if (!test) {
 
				_ai_sl_byte = SQSL_INT;
 
				SlObject(NULL, _ai_byte);
 
			}
 
			SQInteger res;
 
			sq_getinteger(vm, index, &res);
 
			if (!test) {
 
				int value = (int)res;
 
				SlArray(&value, 1, SLE_INT32);
 
			}
 
			return true;
 
		}
 

	
 
		case OT_STRING: {
 
			if (!test) {
 
				_ai_sl_byte = SQSL_STRING;
 
				SlObject(NULL, _ai_byte);
 
			}
 
			const SQChar *res;
 
			sq_getstring(vm, index, &res);
 
			/* @bug if a string longer than 512 characters is given to SQ2OTTD, the
 
			 *  internal buffer overflows. */
 
			const char *buf = SQ2OTTD(res);
 
			size_t len = strlen(buf) + 1;
 
			if (len >= 255) {
 
				AILog::Error("Maximum string length is 254 chars. No data saved.");
 
				return false;
 
			}
 
			if (!test) {
 
				_ai_sl_byte = (byte)len;
 
				SlObject(NULL, _ai_byte);
 
				SlArray((void*)buf, len, SLE_CHAR);
 
			}
 
			return true;
 
		}
 

	
 
		case OT_ARRAY: {
 
			if (!test) {
src/airport.h
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file airport.h Various declarations for airports */
 

	
 
#ifndef AIRPORT_H
 
#define AIRPORT_H
 

	
 
#include "direction_type.h"
 
#include "tile_type.h"
 

	
 
/** Some airport-related constants */
 
enum {
 
	MAX_TERMINALS =  10,                    ///< maximum number of terminals per airport
 
	MAX_HELIPADS  =   4,                    ///< maximum number of helipads per airport
 
	MAX_ELEMENTS  = 255,                    ///< maximum number of aircraft positions at airport
 
	NUM_AIRPORTTILES = 256,                 ///< total number of airport tiles
 
	NEW_AIRPORTTILE_OFFSET = 74,            ///< offset of first newgrf airport tile
 
	INVALID_AIRPORTTILE = NUM_AIRPORTTILES, ///< id for an invalid airport tile
 
};
 
static const uint MAX_TERMINALS =  10;                       ///< maximum number of terminals per airport
 
static const uint MAX_HELIPADS  =   4;                       ///< maximum number of helipads per airport
 
static const uint MAX_ELEMENTS  = 255;                       ///< maximum number of aircraft positions at airport
 

	
 
static const uint NUM_AIRPORTTILES       = 256;              ///< total number of airport tiles
 
static const uint NEW_AIRPORTTILE_OFFSET = 74;               ///< offset of first newgrf airport tile
 
static const uint INVALID_AIRPORTTILE    = NUM_AIRPORTTILES; ///< id for an invalid airport tile
 

	
 
/** Airport types */
 
enum AirportTypes {
 
	AT_SMALL         =   0,
 
	AT_LARGE         =   1,
 
	AT_HELIPORT      =   2,
 
	AT_METROPOLITAN  =   3,
 
	AT_INTERNATIONAL =   4,
 
	AT_COMMUTER      =   5,
 
	AT_HELIDEPOT     =   6,
 
	AT_INTERCON      =   7,
 
	AT_HELISTATION   =   8,
 
	AT_OILRIG        =   9,
 
	NEW_AIRPORT_OFFSET = 10,
 
	NUM_AIRPORTS     =  128,
 
	AT_INVALID       = 254,
 
	AT_DUMMY         = 255
 
};
 

	
 
enum AirportMovingDataFlags {
 
	AMED_NOSPDCLAMP = 1 << 0,
 
	AMED_TAKEOFF    = 1 << 1,
 
	AMED_SLOWTURN   = 1 << 2,
 
	AMED_LAND       = 1 << 3,
 
	AMED_EXACTPOS   = 1 << 4,
 
	AMED_BRAKE      = 1 << 5,
 
	AMED_HELI_RAISE = 1 << 6,
 
	AMED_HELI_LOWER = 1 << 7,
 
	AMED_HOLD       = 1 << 8
 
};
 

	
 
/* Movement States on Airports (headings target) */
 
enum AirportMovementStates {
 
	TO_ALL         =  0,
 
	HANGAR         =  1,
 
	TERM1          =  2,
 
	TERM2          =  3,
 
	TERM3          =  4,
 
	TERM4          =  5,
 
	TERM5          =  6,
 
	TERM6          =  7,
 
	HELIPAD1       =  8,
 
	HELIPAD2       =  9,
 
	TAKEOFF        = 10,
 
	STARTTAKEOFF   = 11,
 
	ENDTAKEOFF     = 12,
 
	HELITAKEOFF    = 13,
 
	FLYING         = 14,
src/airport_gui.cpp
Show inline comments
 
@@ -11,97 +11,97 @@
 

	
 
#include "stdafx.h"
 
#include "window_gui.h"
 
#include "station_gui.h"
 
#include "terraform_gui.h"
 
#include "airport.h"
 
#include "sound_func.h"
 
#include "window_func.h"
 
#include "strings_func.h"
 
#include "viewport_func.h"
 
#include "gfx_func.h"
 
#include "company_func.h"
 
#include "tilehighlight_func.h"
 
#include "company_base.h"
 
#include "station_type.h"
 
#include "newgrf_airport.h"
 
#include "widgets/dropdown_type.h"
 
#include "core/geometry_func.hpp"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
 

	
 
static AirportClassID _selected_airport_class; ///< the currently visible airport class
 
static int _selected_airport_index;            ///< the index of the selected airport in the current class or -1
 

	
 
static void ShowBuildAirportPicker(Window *parent);
 

	
 

	
 
void CcBuildAirport(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
 
{
 
	if (result.Failed()) return;
 

	
 
	SndPlayTileFx(SND_1F_SPLAT, tile);
 
	if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
 
}
 

	
 
static void PlaceAirport(TileIndex tile)
 
{
 
	if (_selected_airport_index == -1) return;
 
	uint32 p2 = _ctrl_pressed;
 
	SB(p2, 16, 16, INVALID_STATION); // no station to join
 

	
 
	uint32 p1 = GetAirportSpecFromClass(_selected_airport_class, _selected_airport_index)->GetIndex();
 
	CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_AIRPORT | CMD_MSG(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE), CcBuildAirport, "" };
 
	ShowSelectStationIfNeeded(cmdcont, TileArea(tile, _thd.size.x / TILE_SIZE, _thd.size.y / TILE_SIZE));
 
}
 

	
 
/** Widget number of the airport build window. */
 
enum {
 
enum AirportToolbarWidgets {
 
	ATW_AIRPORT,
 
	ATW_DEMOLISH,
 
};
 

	
 

	
 
static void BuildAirClick_Airport(Window *w)
 
{
 
	if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, HT_RECT, PlaceAirport)) ShowBuildAirportPicker(w);
 
}
 

	
 
static void BuildAirClick_Demolish(Window *w)
 
{
 
	HandlePlacePushButton(w, ATW_DEMOLISH, ANIMCURSOR_DEMOLISH, HT_RECT, PlaceProc_DemolishArea);
 
}
 

	
 

	
 
typedef void OnButtonClick(Window *w);
 
static OnButtonClick * const _build_air_button_proc[] = {
 
	BuildAirClick_Airport,
 
	BuildAirClick_Demolish,
 
};
 

	
 
struct BuildAirToolbarWindow : Window {
 
	BuildAirToolbarWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
 
	{
 
		this->InitNested(desc, window_number);
 
		if (_settings_client.gui.link_terraform_toolbar) ShowTerraformToolbar(this);
 
	}
 

	
 
	~BuildAirToolbarWindow()
 
	{
 
		if (_settings_client.gui.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0, false);
 
	}
 

	
 
	virtual void OnPaint()
 
	{
 
		this->DrawWidgets();
 
	}
 

	
 
	virtual void OnClick(Point pt, int widget, int click_count)
 
	{
 
		if (!IsInsideBS(widget, ATW_AIRPORT, lengthof(_build_air_button_proc))) return;
 

	
 
		_build_air_button_proc[widget - ATW_AIRPORT](this);
 
	}
 

	
 

	
 
	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
src/company_gui.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file company_gui.cpp Company related GUIs. */
 

	
 
#include "stdafx.h"
 
#include "gui.h"
 
#include "window_gui.h"
 
#include "textbuf_gui.h"
 
#include "viewport_func.h"
 
#include "company_func.h"
 
#include "command_func.h"
 
#include "network/network.h"
 
#include "network/network_gui.h"
 
#include "network/network_func.h"
 
#include "economy_func.h"
 
#include "vehicle_base.h"
 
#include "newgrf.h"
 
#include "company_manager_face.h"
 
#include "strings_func.h"
 
#include "date_func.h"
 
#include "widgets/dropdown_type.h"
 
#include "tilehighlight_func.h"
 
#include "sprite.h"
 
#include "company_base.h"
 
#include "core/geometry_func.hpp"
 

	
 
#include "table/strings.h"
 

	
 
/** Company GUI constants. */
 
enum {
 
	FIRST_GUI_CALL = INT_MAX,  ///< default value to specify this is the first call of the resizable gui
 
static const int FIRST_GUI_CALL = INT_MAX; ///< default value to specify this is the first call of the resizable gui
 

	
 
	EXP_LINESPACE  = 2,        ///< Amount of vertical space for a horizontal (sub-)total line.
 
	EXP_BLOCKSPACE = 10,       ///< Amount of vertical space between two blocks of numbers.
 
};
 
static const uint EXP_LINESPACE  = 2;      ///< Amount of vertical space for a horizontal (sub-)total line.
 
static const uint EXP_BLOCKSPACE = 10;     ///< Amount of vertical space between two blocks of numbers.
 

	
 
static void DoSelectCompanyManagerFace(Window *parent);
 

	
 
/** Standard unsorted list of expenses. */
 
static ExpensesType _expenses_list_1[] = {
 
	EXPENSES_CONSTRUCTION,
 
	EXPENSES_NEW_VEHICLES,
 
	EXPENSES_TRAIN_RUN,
 
	EXPENSES_ROADVEH_RUN,
 
	EXPENSES_AIRCRAFT_RUN,
 
	EXPENSES_SHIP_RUN,
 
	EXPENSES_PROPERTY,
 
	EXPENSES_TRAIN_INC,
 
	EXPENSES_ROADVEH_INC,
 
	EXPENSES_AIRCRAFT_INC,
 
	EXPENSES_SHIP_INC,
 
	EXPENSES_LOAN_INT,
 
	EXPENSES_OTHER,
 
};
 

	
 
/** Grouped list of expenses. */
 
static ExpensesType _expenses_list_2[] = {
 
	EXPENSES_TRAIN_INC,
 
	EXPENSES_ROADVEH_INC,
 
	EXPENSES_AIRCRAFT_INC,
 
	EXPENSES_SHIP_INC,
 
	INVALID_EXPENSES,
 
	EXPENSES_TRAIN_RUN,
 
	EXPENSES_ROADVEH_RUN,
 
	EXPENSES_AIRCRAFT_RUN,
 
	EXPENSES_SHIP_RUN,
 
	EXPENSES_PROPERTY,
 
	EXPENSES_LOAN_INT,
 
	INVALID_EXPENSES,
 
	EXPENSES_CONSTRUCTION,
 
	EXPENSES_NEW_VEHICLES,
 
	EXPENSES_OTHER,
 
	INVALID_EXPENSES,
 
};
 

	
 
/** Expense list container. */
 
struct ExpensesList {
 
	const ExpensesType *et;   ///< Expenses items.
 
	const uint length;        ///< Number of items in list.
 
	const uint num_subtotals; ///< Number of sub-totals in the list.
 

	
 
	ExpensesList(ExpensesType *et, int length, int num_subtotals) : et(et), length(length), num_subtotals(num_subtotals)
 
	{
src/console_gui.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file console_gui.cpp Handling the GUI of the in-game console. */
 

	
 
#include "stdafx.h"
 
#include "textbuf_gui.h"
 
#include "window_gui.h"
 
#include "console_gui.h"
 
#include "console_internal.h"
 
#include "window_func.h"
 
#include "string_func.h"
 
#include "gfx_func.h"
 
#include "settings_type.h"
 
#include "console_func.h"
 
#include "rev.h"
 

	
 

	
 
enum {
 
	ICON_HISTORY_SIZE       = 20,
 
	ICON_LINE_SPACING       =  2,
 
	ICON_RIGHT_BORDERWIDTH  = 10,
 
	ICON_BOTTOM_BORDERWIDTH = 12,
 
};
 
static const uint ICON_HISTORY_SIZE       = 20;
 
static const uint ICON_LINE_SPACING       =  2;
 
static const uint ICON_RIGHT_BORDERWIDTH  = 10;
 
static const uint ICON_BOTTOM_BORDERWIDTH = 12;
 

	
 
/**
 
 * Container for a single line of console output
 
 */
 
struct IConsoleLine {
 
	static IConsoleLine *front; ///< The front of the console backlog buffer
 
	static int size;            ///< The amount of items in the backlog
 

	
 
	IConsoleLine *previous; ///< The previous console message.
 
	char *buffer;           ///< The data to store.
 
	TextColour colour;      ///< The colour of the line.
 
	uint16 time;            ///< The amount of time the line is in the backlog.
 

	
 
	/**
 
	 * Initialize the console line.
 
	 * @param buffer the data to print.
 
	 * @param colour the colour of the line.
 
	 */
 
	IConsoleLine(char *buffer, TextColour colour) :
 
			previous(IConsoleLine::front),
 
			buffer(buffer),
 
			colour(colour),
 
			time(0)
 
	{
 
		IConsoleLine::front = this;
 
		IConsoleLine::size++;
 
	}
 

	
 
	/**
 
	 * Clear this console line and any further ones.
 
	 */
 
	~IConsoleLine()
 
	{
 
		IConsoleLine::size--;
 
		free(buffer);
 

	
 
		delete previous;
 
	}
 

	
 
	/**
 
	 * Get the index-ed item in the list.
 
	 */
 
	static const IConsoleLine *Get(uint index)
 
	{
 
		const IConsoleLine *item = IConsoleLine::front;
 
		while (index != 0 && item != NULL) {
 
			index--;
 
			item = item->previous;
 
@@ -401,80 +398,80 @@ void IConsoleSwitch()
 

	
 
		case ICONSOLE_OPENED: case ICONSOLE_FULL:
 
			DeleteWindowById(WC_CONSOLE, 0);
 
			break;
 
	}
 

	
 
	MarkWholeScreenDirty();
 
}
 

	
 
void IConsoleClose() {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
 

	
 
/**
 
 * Add the entered line into the history so you can look it back
 
 * scroll, etc. Put it to the beginning as it is the latest text
 
 * @param cmd Text to be entered into the 'history'
 
 * @return the command to execute
 
 */
 
static const char *IConsoleHistoryAdd(const char *cmd)
 
{
 
	/* Strip all spaces at the begin */
 
	while (IsWhitespace(*cmd)) cmd++;
 

	
 
	/* Do not put empty command in history */
 
	if (StrEmpty(cmd)) return NULL;
 

	
 
	/* Do not put in history if command is same as previous */
 
	if (_iconsole_history[0] == NULL || strcmp(_iconsole_history[0], cmd) != 0) {
 
		free(_iconsole_history[ICON_HISTORY_SIZE - 1]);
 
		memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1));
 
		_iconsole_history[0] = strdup(cmd);
 
	}
 

	
 
	/* Reset the history position */
 
	IConsoleResetHistoryPos();
 
	return _iconsole_history[0];
 
}
 

	
 
/**
 
 * Navigate Up/Down in the history of typed commands
 
 * @param direction Go further back in history (+1), go to recently typed commands (-1)
 
 */
 
static void IConsoleHistoryNavigate(int direction)
 
{
 
	if (_iconsole_history[0] == NULL) return; // Empty history
 
	int i = _iconsole_historypos + direction;
 

	
 
	/* watch out for overflows, just wrap around */
 
	if (i < 0) i = ICON_HISTORY_SIZE - 1;
 
	if (i >= ICON_HISTORY_SIZE) i = 0;
 
	if ((uint)i >= ICON_HISTORY_SIZE) i = 0;
 

	
 
	if (direction > 0) {
 
		if (_iconsole_history[i] == NULL) i = 0;
 
	}
 

	
 
	if (direction < 0) {
 
		while (i > 0 && _iconsole_history[i] == NULL) i--;
 
	}
 

	
 
	_iconsole_historypos = i;
 
	IConsoleClearCommand();
 
	/* copy history to 'command prompt / bash' */
 
	assert(_iconsole_history[i] != NULL && IsInsideMM(i, 0, ICON_HISTORY_SIZE));
 
	ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxsize);
 
	UpdateTextBufferSize(&_iconsole_cmdline);
 
}
 

	
 
/**
 
 * Handle the printing of text entered into the console or redirected there
 
 * by any other means. Text can be redirected to other clients in a network game
 
 * as well as to a logfile. If the network server is a dedicated server, all activities
 
 * are also logged. All lines to print are added to a temporary buffer which can be
 
 * used as a history to print them onscreen
 
 * @param colour_code the colour of the command. Red in case of errors, etc.
 
 * @param str the message entered or output on the console (notice, error, etc.)
 
 */
 
void IConsoleGUIPrint(ConsoleColour colour_code, char *str)
 
{
 
	new IConsoleLine(str, (TextColour)colour_code);
 
	SetWindowDirty(WC_CONSOLE, 0);
 
}
src/currency.cpp
Show inline comments
 
@@ -17,97 +17,97 @@
 

	
 
#include "table/strings.h"
 

	
 
	/*   exchange rate    prefix                      symbol_pos
 
	 *   |  separator        |           postfix          |
 
	 *   |   |   Euro year   |              |             | name
 
	 *   |   |    |          |              |             |  | */
 
static const CurrencySpec origin_currency_specs[NUM_CURRENCY] = {
 
	{    1, "", CF_NOEURO, "\xC2\xA3",     "",           0, STR_GAME_OPTIONS_CURRENCY_GBP    }, ///< british pounds
 
	{    2, "", CF_NOEURO, "$",            "",           0, STR_GAME_OPTIONS_CURRENCY_USD    }, ///< us dollars
 
	{    2, "", CF_ISEURO, "\xE2\x82\xAC", "",           0, STR_GAME_OPTIONS_CURRENCY_EUR    }, ///< Euro
 
	{  220, "", CF_NOEURO, "\xC2\xA5",     "",           0, STR_GAME_OPTIONS_CURRENCY_YEN    }, ///< yen
 
	{   20, "", 2002,      "",             " S.",        1, STR_GAME_OPTIONS_CURRENCY_ATS    }, ///< austrian schilling
 
	{   59, "", 2002,      "BEF ",         "",           0, STR_GAME_OPTIONS_CURRENCY_BEF    }, ///< belgian franc
 
	{    2, "", CF_NOEURO, "CHF ",         "",           0, STR_GAME_OPTIONS_CURRENCY_CHF    }, ///< swiss franc
 
	{   41, "", CF_NOEURO, "",             " K\xC4\x8D", 1, STR_GAME_OPTIONS_CURRENCY_CZK    }, ///< czech koruna
 
	{    3, "", 2002,      "DM ",          "",           0, STR_GAME_OPTIONS_CURRENCY_DEM    }, ///< deutsche mark
 
	{   11, "", CF_NOEURO, "",             " kr",        1, STR_GAME_OPTIONS_CURRENCY_DKK    }, ///< danish krone
 
	{  245, "", 2002,      "Pts ",         "",           0, STR_GAME_OPTIONS_CURRENCY_ESP    }, ///< spanish pesetas
 
	{    9, "", 2002,      "",             " mk",        1, STR_GAME_OPTIONS_CURRENCY_FIM    }, ///< finnish markka
 
	{   10, "", 2002,      "FF ",          "",           0, STR_GAME_OPTIONS_CURRENCY_FRF    }, ///< french francs
 
	{  500, "", 2002,      "",             "Dr.",        1, STR_GAME_OPTIONS_CURRENCY_GRD    }, ///< greek drachma
 
	{  378, "", CF_NOEURO, "",             " Ft",        1, STR_GAME_OPTIONS_CURRENCY_HUF    }, ///< hungarian forint
 
	{  130, "", CF_NOEURO, "",             " Kr",        1, STR_GAME_OPTIONS_CURRENCY_ISK    }, ///< icelandic krona
 
	{ 2850, "", 2002,      "",             " L.",        1, STR_GAME_OPTIONS_CURRENCY_ITL    }, ///< italian lira
 
	{    3, "", 2002,      "NLG ",         "",           0, STR_GAME_OPTIONS_CURRENCY_NLG    }, ///< dutch gulden
 
	{   12, "", CF_NOEURO, "",             " Kr",        1, STR_GAME_OPTIONS_CURRENCY_NOK    }, ///< norwegian krone
 
	{    6, "", CF_NOEURO, "",             " z\xC5\x82", 1, STR_GAME_OPTIONS_CURRENCY_PLN    }, ///< polish zloty
 
	{    5, "", CF_NOEURO, "",             " Lei",       1, STR_GAME_OPTIONS_CURRENCY_RON    }, ///< romanian Lei
 
	{   50, "", CF_NOEURO, "",             " p",         1, STR_GAME_OPTIONS_CURRENCY_RUR    }, ///< russian rouble
 
	{  352, "", 2007,      "",             " SIT",       1, STR_GAME_OPTIONS_CURRENCY_SIT    }, ///< slovenian tolar
 
	{   13, "", CF_NOEURO, "",             " Kr",        1, STR_GAME_OPTIONS_CURRENCY_SEK    }, ///< swedish krona
 
	{    3, "", CF_NOEURO, "",             " TL",        1, STR_GAME_OPTIONS_CURRENCY_TRY    }, ///< turkish lira
 
	{   52, "", 2009,      "",             " Sk",        1, STR_GAME_OPTIONS_CURRENCY_SKK    }, ///< slovak koruna
 
	{    4, "", CF_NOEURO, "R$ ",          "",           0, STR_GAME_OPTIONS_CURRENCY_BRL    }, ///< brazil real
 
	{   20, "", CF_NOEURO, "",             " EEK",       1, STR_GAME_OPTIONS_CURRENCY_EEK    }, ///< estonian krooni
 
	{    1, "", CF_NOEURO, "",             "",           2, STR_GAME_OPTIONS_CURRENCY_CUSTOM }, ///< custom currency
 
};
 

	
 
/* Array of currencies used by the system */
 
CurrencySpec _currency_specs[NUM_CURRENCY];
 

	
 
/**
 
 * These enums are only declared in order to make sens
 
 * out of the TTDPatch_To_OTTDIndex array that will follow
 
 * Every currency used by Ottd is there, just in case TTDPatch will
 
 * add those missing in its code
 
 **/
 
enum {
 
enum Currencies {
 
	CURR_GBP,
 
	CURR_USD,
 
	CURR_EUR,
 
	CURR_YEN,
 
	CURR_ATS,
 
	CURR_BEF,
 
	CURR_CHF,
 
	CURR_CZK,
 
	CURR_DEM,
 
	CURR_DKK,
 
	CURR_ESP,
 
	CURR_FIM,
 
	CURR_FRF,
 
	CURR_GRD,
 
	CURR_HUF,
 
	CURR_ISK,
 
	CURR_ITL,
 
	CURR_NLG,
 
	CURR_NOK,
 
	CURR_PLN,
 
	CURR_RON,
 
	CURR_RUR,
 
	CURR_SIT,
 
	CURR_SEK,
 
	CURR_YTL,
 
	CURR_SKK,
 
	CURR_BRL,
 
	CURR_EEK,
 
};
 

	
 
/**
 
 * This array represent the position of OpenTTD's currencies,
 
 * compared to TTDPatch's ones.
 
 * When a grf sends currencies, they are based on the order defined by TTDPatch.
 
 * So, we must reindex them to our own order.
 
 **/
 
const byte TTDPatch_To_OTTDIndex[] =
 
{
 
	CURR_GBP,
 
	CURR_USD,
 
	CURR_FRF,
 
	CURR_DEM,
 
	CURR_YEN,
 
	CURR_ESP,
 
	CURR_HUF,
 
	CURR_PLN,
 
	CURR_ATS,
 
	CURR_BEF,
src/date.cpp
Show inline comments
 
@@ -10,97 +10,97 @@
 
/** @file date.cpp Handling of dates in our native format and transforming them to something human readable. */
 

	
 
#include "stdafx.h"
 
#include "variables.h"
 
#include "network/network.h"
 
#include "network/network_func.h"
 
#include "currency.h"
 
#include "window_func.h"
 
#include "functions.h"
 
#include "date_func.h"
 
#include "vehicle_base.h"
 
#include "debug.h"
 
#include "rail_gui.h"
 
#include "saveload/saveload.h"
 

	
 
Year      _cur_year;   ///< Current year, starting at 0
 
Month     _cur_month;  ///< Current month (0..11)
 
Date      _date;       ///< Current date in days (day counter)
 
DateFract _date_fract;
 

	
 

	
 
void SetDate(Date date)
 
{
 
	YearMonthDay ymd;
 

	
 
	_date = date;
 
	ConvertDateToYMD(date, &ymd);
 
	_cur_year = ymd.year;
 
	_cur_month = ymd.month;
 
}
 

	
 
#define M(a, b) ((a << 5) | b)
 
static const uint16 _month_date_from_year_day[] = {
 
	M( 0, 1), M( 0, 2), M( 0, 3), M( 0, 4), M( 0, 5), M( 0, 6), M( 0, 7), M( 0, 8), M( 0, 9), M( 0, 10), M( 0, 11), M( 0, 12), M( 0, 13), M( 0, 14), M( 0, 15), M( 0, 16), M( 0, 17), M( 0, 18), M( 0, 19), M( 0, 20), M( 0, 21), M( 0, 22), M( 0, 23), M( 0, 24), M( 0, 25), M( 0, 26), M( 0, 27), M( 0, 28), M( 0, 29), M( 0, 30), M( 0, 31),
 
	M( 1, 1), M( 1, 2), M( 1, 3), M( 1, 4), M( 1, 5), M( 1, 6), M( 1, 7), M( 1, 8), M( 1, 9), M( 1, 10), M( 1, 11), M( 1, 12), M( 1, 13), M( 1, 14), M( 1, 15), M( 1, 16), M( 1, 17), M( 1, 18), M( 1, 19), M( 1, 20), M( 1, 21), M( 1, 22), M( 1, 23), M( 1, 24), M( 1, 25), M( 1, 26), M( 1, 27), M( 1, 28), M( 1, 29),
 
	M( 2, 1), M( 2, 2), M( 2, 3), M( 2, 4), M( 2, 5), M( 2, 6), M( 2, 7), M( 2, 8), M( 2, 9), M( 2, 10), M( 2, 11), M( 2, 12), M( 2, 13), M( 2, 14), M( 2, 15), M( 2, 16), M( 2, 17), M( 2, 18), M( 2, 19), M( 2, 20), M( 2, 21), M( 2, 22), M( 2, 23), M( 2, 24), M( 2, 25), M( 2, 26), M( 2, 27), M( 2, 28), M( 2, 29), M( 2, 30), M( 2, 31),
 
	M( 3, 1), M( 3, 2), M( 3, 3), M( 3, 4), M( 3, 5), M( 3, 6), M( 3, 7), M( 3, 8), M( 3, 9), M( 3, 10), M( 3, 11), M( 3, 12), M( 3, 13), M( 3, 14), M( 3, 15), M( 3, 16), M( 3, 17), M( 3, 18), M( 3, 19), M( 3, 20), M( 3, 21), M( 3, 22), M( 3, 23), M( 3, 24), M( 3, 25), M( 3, 26), M( 3, 27), M( 3, 28), M( 3, 29), M( 3, 30),
 
	M( 4, 1), M( 4, 2), M( 4, 3), M( 4, 4), M( 4, 5), M( 4, 6), M( 4, 7), M( 4, 8), M( 4, 9), M( 4, 10), M( 4, 11), M( 4, 12), M( 4, 13), M( 4, 14), M( 4, 15), M( 4, 16), M( 4, 17), M( 4, 18), M( 4, 19), M( 4, 20), M( 4, 21), M( 4, 22), M( 4, 23), M( 4, 24), M( 4, 25), M( 4, 26), M( 4, 27), M( 4, 28), M( 4, 29), M( 4, 30), M( 4, 31),
 
	M( 5, 1), M( 5, 2), M( 5, 3), M( 5, 4), M( 5, 5), M( 5, 6), M( 5, 7), M( 5, 8), M( 5, 9), M( 5, 10), M( 5, 11), M( 5, 12), M( 5, 13), M( 5, 14), M( 5, 15), M( 5, 16), M( 5, 17), M( 5, 18), M( 5, 19), M( 5, 20), M( 5, 21), M( 5, 22), M( 5, 23), M( 5, 24), M( 5, 25), M( 5, 26), M( 5, 27), M( 5, 28), M( 5, 29), M( 5, 30),
 
	M( 6, 1), M( 6, 2), M( 6, 3), M( 6, 4), M( 6, 5), M( 6, 6), M( 6, 7), M( 6, 8), M( 6, 9), M( 6, 10), M( 6, 11), M( 6, 12), M( 6, 13), M( 6, 14), M( 6, 15), M( 6, 16), M( 6, 17), M( 6, 18), M( 6, 19), M( 6, 20), M( 6, 21), M( 6, 22), M( 6, 23), M( 6, 24), M( 6, 25), M( 6, 26), M( 6, 27), M( 6, 28), M( 6, 29), M( 6, 30), M( 6, 31),
 
	M( 7, 1), M( 7, 2), M( 7, 3), M( 7, 4), M( 7, 5), M( 7, 6), M( 7, 7), M( 7, 8), M( 7, 9), M( 7, 10), M( 7, 11), M( 7, 12), M( 7, 13), M( 7, 14), M( 7, 15), M( 7, 16), M( 7, 17), M( 7, 18), M( 7, 19), M( 7, 20), M( 7, 21), M( 7, 22), M( 7, 23), M( 7, 24), M( 7, 25), M( 7, 26), M( 7, 27), M( 7, 28), M( 7, 29), M( 7, 30), M( 7, 31),
 
	M( 8, 1), M( 8, 2), M( 8, 3), M( 8, 4), M( 8, 5), M( 8, 6), M( 8, 7), M( 8, 8), M( 8, 9), M( 8, 10), M( 8, 11), M( 8, 12), M( 8, 13), M( 8, 14), M( 8, 15), M( 8, 16), M( 8, 17), M( 8, 18), M( 8, 19), M( 8, 20), M( 8, 21), M( 8, 22), M( 8, 23), M( 8, 24), M( 8, 25), M( 8, 26), M( 8, 27), M( 8, 28), M( 8, 29), M( 8, 30),
 
	M( 9, 1), M( 9, 2), M( 9, 3), M( 9, 4), M( 9, 5), M( 9, 6), M( 9, 7), M( 9, 8), M( 9, 9), M( 9, 10), M( 9, 11), M( 9, 12), M( 9, 13), M( 9, 14), M( 9, 15), M( 9, 16), M( 9, 17), M( 9, 18), M( 9, 19), M( 9, 20), M( 9, 21), M( 9, 22), M( 9, 23), M( 9, 24), M( 9, 25), M( 9, 26), M( 9, 27), M( 9, 28), M( 9, 29), M( 9, 30), M( 9, 31),
 
	M(10, 1), M(10, 2), M(10, 3), M(10, 4), M(10, 5), M(10, 6), M(10, 7), M(10, 8), M(10, 9), M(10, 10), M(10, 11), M(10, 12), M(10, 13), M(10, 14), M(10, 15), M(10, 16), M(10, 17), M(10, 18), M(10, 19), M(10, 20), M(10, 21), M(10, 22), M(10, 23), M(10, 24), M(10, 25), M(10, 26), M(10, 27), M(10, 28), M(10, 29), M(10, 30),
 
	M(11, 1), M(11, 2), M(11, 3), M(11, 4), M(11, 5), M(11, 6), M(11, 7), M(11, 8), M(11, 9), M(11, 10), M(11, 11), M(11, 12), M(11, 13), M(11, 14), M(11, 15), M(11, 16), M(11, 17), M(11, 18), M(11, 19), M(11, 20), M(11, 21), M(11, 22), M(11, 23), M(11, 24), M(11, 25), M(11, 26), M(11, 27), M(11, 28), M(11, 29), M(11, 30), M(11, 31),
 
};
 
#undef M
 

	
 
enum {
 
enum DaysTillMonth {
 
	ACCUM_JAN = 0,
 
	ACCUM_FEB = ACCUM_JAN + 31,
 
	ACCUM_MAR = ACCUM_FEB + 29,
 
	ACCUM_APR = ACCUM_MAR + 31,
 
	ACCUM_MAY = ACCUM_APR + 30,
 
	ACCUM_JUN = ACCUM_MAY + 31,
 
	ACCUM_JUL = ACCUM_JUN + 30,
 
	ACCUM_AUG = ACCUM_JUL + 31,
 
	ACCUM_SEP = ACCUM_AUG + 31,
 
	ACCUM_OCT = ACCUM_SEP + 30,
 
	ACCUM_NOV = ACCUM_OCT + 31,
 
	ACCUM_DEC = ACCUM_NOV + 30,
 
};
 

	
 
static const uint16 _accum_days_for_month[] = {
 
	ACCUM_JAN, ACCUM_FEB, ACCUM_MAR, ACCUM_APR,
 
	ACCUM_MAY, ACCUM_JUN, ACCUM_JUL, ACCUM_AUG,
 
	ACCUM_SEP, ACCUM_OCT, ACCUM_NOV, ACCUM_DEC,
 
};
 

	
 
/**
 
 * Converts a Date to a Year, Month & Day.
 
 * @param date the date to convert from
 
 * @param ymd  the year, month and day to write to
 
 */
 
void ConvertDateToYMD(Date date, YearMonthDay *ymd)
 
{
 
	/*
 
	 * Year determination in multiple steps to account for leap
 
	 * years. First do the large steps, then the smaller ones.
 
	 */
 

	
 
	/* There are 97 leap years in 400 years */
 
	Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97));
 
	int rem = date % (DAYS_IN_YEAR * 400 + 97);
 
	uint16 x;
 

	
 
	if (rem >= DAYS_IN_YEAR * 100 + 25) {
 
		/* There are 25 leap years in the first 100 years after
 
		 * every 400th year, as every 400th year is a leap year */
 
		yr  += 100;
 
		rem -= DAYS_IN_YEAR * 100 + 25;
 

	
 
		/* There are 24 leap years in the next couple of 100 years */
 
		yr += 100 * (rem / (DAYS_IN_YEAR * 100 + 24));
 
		rem = (rem % (DAYS_IN_YEAR * 100 + 24));
 
	}
 

	
src/fontcache.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file fontcache.cpp Cache for characters from fonts. */
 

	
 
#include "stdafx.h"
 
#include "fontcache.h"
 
#include "blitter/factory.hpp"
 
#include "core/math_func.hpp"
 

	
 
#include "table/sprites.h"
 
#include "table/control_codes.h"
 

	
 
static const int ASCII_LETTERSTART = 32; ///< First printable ASCII letter.
 

	
 
/** Semi-constant for the height of the different sizes of fonts. */
 
int _font_height[FS_END];
 

	
 
#ifdef WITH_FREETYPE
 
#include <ft2build.h>
 
#include FT_FREETYPE_H
 
#include FT_GLYPH_H
 

	
 
#ifdef WITH_FONTCONFIG
 
#include <fontconfig/fontconfig.h>
 
#endif
 

	
 
static FT_Library _library = NULL;
 
static FT_Face _face_small = NULL;
 
static FT_Face _face_medium = NULL;
 
static FT_Face _face_large = NULL;
 
static int _ascender[FS_END];
 

	
 
FreeTypeSettings _freetype;
 

	
 
enum {
 
	FACE_COLOUR = 1,
 
	SHADOW_COLOUR = 2,
 
};
 
static const byte FACE_COLOUR   = 1;
 
static const byte SHADOW_COLOUR = 2;
 

	
 
/** Get the font loaded into a Freetype face by using a font-name.
 
 * If no appropiate font is found, the function returns an error */
 
#ifdef WIN32
 
#include <windows.h>
 
#include <shlobj.h> /* SHGetFolderPath */
 
#include "os/windows/win32.h"
 

	
 
/**
 
 * Get the short DOS 8.3 format for paths.
 
 * FreeType doesn't support Unicode filenames and Windows' fopen (as used
 
 * by FreeType) doesn't support UTF-8 filenames. So we have to convert the
 
 * filename into something that isn't UTF-8 but represents the Unicode file
 
 * name. This is the short DOS 8.3 format. This does not contain any
 
 * characters that fopen doesn't support.
 
 * @param long_path the path in UTF-8.
 
 * @return the short path in ANSI (ASCII).
 
 */
 
char *GetShortPath(const char *long_path)
 
{
 
	static char short_path[MAX_PATH];
 
#ifdef UNICODE
 
	/* The non-unicode GetShortPath doesn't support UTF-8...,
 
	 * so convert the path to wide chars, then get the short
 
	 * path and convert it back again. */
 
	wchar_t long_path_w[MAX_PATH];
 
	MultiByteToWideChar(CP_UTF8, 0, long_path, -1, long_path_w, MAX_PATH);
 

	
 
	wchar_t short_path_w[MAX_PATH];
 
	GetShortPathNameW(long_path_w, short_path_w, MAX_PATH);
 

	
 
	WideCharToMultiByte(CP_ACP, 0, short_path_w, -1, short_path, MAX_PATH, NULL, NULL);
 
#else
 
	/* Technically not needed, but do it for consistency. */
 
	GetShortPathNameA(long_path, short_path, MAX_PATH);
 
#endif
 
	return short_path;
 
}
 

	
 
/* Get the font file to be loaded into Freetype by looping the registry
 
 * location where windows lists all installed fonts. Not very nice, will
 
 * surely break if the registry path changes, but it works. Much better
 
 * solution would be to use CreateFont, and extract the font data from it
 
 * by GetFontData. The problem with this is that the font file needs to be
 
 * kept in memory then until the font is no longer needed. This could mean
 
 * an additional memory usage of 30MB (just for fonts!) when using an eastern
 
 * font for all font sizes */
 
#define FONT_DIR_NT "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
src/gamelog.cpp
Show inline comments
 
@@ -40,101 +40,99 @@ static LoggedAction *_current_action = N
 

	
 

	
 
/** Stores information about new action, but doesn't allocate it
 
 * Action is allocated only when there is at least one change
 
 * @param at type of action
 
 */
 
void GamelogStartAction(GamelogActionType at)
 
{
 
	assert(_gamelog_action_type == GLAT_NONE); // do not allow starting new action without stopping the previous first
 
	_gamelog_action_type = at;
 
}
 

	
 
/** Stops logging of any changes
 
 */
 
void GamelogStopAction()
 
{
 
	assert(_gamelog_action_type != GLAT_NONE); // nobody should try to stop if there is no action in progress
 

	
 
	bool print = _current_action != NULL;
 

	
 
	_current_action = NULL;
 
	_gamelog_action_type = GLAT_NONE;
 

	
 
	if (print) GamelogPrintDebug(5);
 
}
 

	
 
/** Resets and frees all memory allocated - used before loading or starting a new game
 
 */
 
void GamelogReset()
 
{
 
	assert(_gamelog_action_type == GLAT_NONE);
 

	
 
	for (uint i = 0; i < _gamelog_actions; i++) {
 
		const LoggedAction *la = &_gamelog_action[i];
 
		for (uint j = 0; j < la->changes; j++) {
 
			const LoggedChange *lc = &la->change[j];
 
			if (lc->ct == GLCT_SETTING) free(lc->setting.name);
 
		}
 
		free(la->change);
 
	}
 

	
 
	free(_gamelog_action);
 

	
 
	_gamelog_action  = NULL;
 
	_gamelog_actions = 0;
 
	_current_action  = NULL;
 
}
 

	
 
enum {
 
	GAMELOG_BUF_LEN = 1024 ///< length of buffer for one line of text
 
};
 
static const uint GAMELOG_BUF_LEN = 1024; ///< length of buffer for one line of text
 

	
 
static int _dbgofs = 0; ///< offset in current output buffer
 
static uint _dbgofs = 0; ///< offset in current output buffer
 

	
 
static void AddDebugText(char *buf, const char *s, ...) WARN_FORMAT(2, 3);
 

	
 
static void AddDebugText(char *buf, const char *s, ...)
 
{
 
	if (GAMELOG_BUF_LEN <= _dbgofs) return;
 

	
 
	va_list va;
 

	
 
	va_start(va, s);
 
	_dbgofs += vsnprintf(buf + _dbgofs, GAMELOG_BUF_LEN - _dbgofs, s, va);
 
	va_end(va);
 
}
 

	
 

	
 
/** Prints GRF filename if found
 
 * @param buf The location in the _dbgofs buffer to draw
 
 * @param grfid GRF which filename to print
 
 */
 
static void PrintGrfFilename(char *buf, uint grfid)
 
{
 
	const GRFConfig *gc = FindGRFConfig(grfid);
 

	
 
	if (gc == NULL) return;
 

	
 
	AddDebugText(buf, ", filename: %s", gc->filename);
 
}
 

	
 
/** Prints GRF ID, checksum and filename if found
 
 * @param buf The location in the _dbgofs buffer to draw
 
 * @param grfid GRF ID
 
 * @param md5sum array of md5sum to print
 
 */
 
static void PrintGrfInfo(char *buf, uint grfid, const uint8 *md5sum)
 
{
 
	char txt[40];
 

	
 
	md5sumToString(txt, lastof(txt), md5sum);
 

	
 
	AddDebugText(buf, "GRF ID %08X, checksum %s", BSWAP32(grfid), txt);
 

	
 
	PrintGrfFilename(buf, grfid);
 

	
 
	return;
 
}
 

	
 

	
 
/** Text messages for various logged actions */
src/gfx.cpp
Show inline comments
 
@@ -29,100 +29,99 @@
 
#include "table/palettes.h"
 
#include "table/sprites.h"
 
#include "table/control_codes.h"
 

	
 
byte _dirkeys;        ///< 1 = left, 2 = up, 4 = right, 8 = down
 
bool _fullscreen;
 
CursorVars _cursor;
 
bool _ctrl_pressed;   ///< Is Ctrl pressed?
 
bool _shift_pressed;  ///< Is Shift pressed?
 
byte _fast_forward;
 
bool _left_button_down;     ///< Is left mouse button pressed?
 
bool _left_button_clicked;  ///< Is left mouse button clicked?
 
bool _right_button_down;    ///< Is right mouse button pressed?
 
bool _right_button_clicked; ///< Is right mouse button clicked?
 
DrawPixelInfo _screen;
 
bool _screen_disable_anim = false;   ///< Disable palette animation (important for 32bpp-anim blitter during giant screenshot)
 
bool _exit_game;
 
GameMode _game_mode;
 
SwitchMode _switch_mode;  ///< The next mainloop command.
 
PauseModeByte _pause_mode;
 
int _pal_first_dirty;
 
int _pal_count_dirty;
 

	
 
Colour _cur_palette[256];
 

	
 
static int _max_char_height; ///< Cache of the height of the largest font
 
static int _max_char_width;  ///< Cache of the width of the largest font
 
static byte _stringwidth_table[FS_END][224]; ///< Cache containing width of often used characters. @see GetCharacterWidth()
 
DrawPixelInfo *_cur_dpi;
 
byte _colour_gradient[COLOUR_END][8];
 

	
 
static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = NULL, SpriteID sprite_id = SPR_CURSOR_MOUSE);
 

	
 
FontSize _cur_fontsize;
 
static FontSize _last_fontsize;
 
static ReusableBuffer<uint8> _cursor_backup;
 

	
 
/**
 
 * The rect for repaint.
 
 *
 
 * This rectangle defines the area which should be repaint by the video driver.
 
 *
 
 * @ingroup dirty
 
 */
 
static Rect _invalid_rect;
 
static const byte *_colour_remap_ptr;
 
static byte _string_colourremap[3]; ///< Recoloursprite for stringdrawing. The grf loader ensures, that ST_FONT sprites only use colours 0 to 2.
 

	
 
enum {
 
	DIRTY_BLOCK_HEIGHT   = 8,
 
	DIRTY_BLOCK_WIDTH    = 64,
 
};
 
static const uint DIRTY_BLOCK_HEIGHT   = 8;
 
static const uint DIRTY_BLOCK_WIDTH    = 64;
 

	
 
static uint _dirty_bytes_per_line = 0;
 
static byte *_dirty_blocks = NULL;
 

	
 
void GfxScroll(int left, int top, int width, int height, int xo, int yo)
 
{
 
	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
 

	
 
	if (xo == 0 && yo == 0) return;
 

	
 
	if (_cursor.visible) UndrawMouseCursor();
 

	
 
#ifdef ENABLE_NETWORK
 
	if (_networking) NetworkUndrawChatMessage();
 
#endif /* ENABLE_NETWORK */
 

	
 
	blitter->ScrollBuffer(_screen.dst_ptr, left, top, width, height, xo, yo);
 
	/* This part of the screen is now dirty. */
 
	_video_driver->MakeDirty(left, top, width, height);
 
}
 

	
 

	
 
/**
 
 * Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
 
 *
 
 * @pre dpi->zoom == ZOOM_LVL_NORMAL, right >= left, bottom >= top
 
 * @param left Minimum X (inclusive)
 
 * @param top Minimum Y (inclusive)
 
 * @param right Maximum X (inclusive)
 
 * @param bottom Maximum Y (inclusive)
 
 * @param colour A 8 bit palette index (FILLRECT_OPAQUE and FILLRECT_CHECKER) or a recolour spritenumber (FILLRECT_RECOLOUR)
 
 * @param mode
 
 *         FILLRECT_OPAQUE:   Fill the rectangle with the specified colour
 
 *         FILLRECT_CHECKER:  Like FILLRECT_OPAQUE, but only draw every second pixel (used to grey out things)
 
 *         FILLRECT_RECOLOUR:  Apply a recolour sprite to every pixel in the rectangle currently on screen
 
 */
 
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
 
{
 
	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
 
	const DrawPixelInfo *dpi = _cur_dpi;
 
	void *dst;
 
	const int otop = top;
 
	const int oleft = left;
 

	
 
	if (dpi->zoom != ZOOM_LVL_NORMAL) return;
 
	if (left > right || top > bottom) return;
 
	if (right < dpi->left || left >= dpi->left + dpi->width) return;
 
	if (bottom < dpi->top || top >= dpi->top + dpi->height) return;
 

	
src/industry_cmd.cpp
Show inline comments
 
@@ -2142,100 +2142,98 @@ static int WhoCanServiceIndustry(Industr
 
		 */
 
		const Order *o;
 
		FOR_VEHICLE_ORDERS(v, o) {
 
			if (o->IsType(OT_GOTO_STATION) && !(o->GetUnloadType() & OUFB_TRANSFER)) {
 
				/* Vehicle visits a station to load or unload */
 
				Station *st = Station::Get(o->GetDestination());
 
				assert(st != NULL);
 

	
 
				/* Same cargo produced by industry is dropped here => not serviced by vehicle v */
 
				if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;
 

	
 
				if (stations.Contains(st)) {
 
					if (v->owner == _local_company) return 2; // Company services industry
 
					result = 1; // Competitor services industry
 
				}
 
			}
 
		}
 
	}
 
	return result;
 
}
 

	
 
/**
 
 * Report news that industry production has changed significantly
 
 *
 
 * @param ind: Industry with changed production
 
 * @param type: Cargo type that has changed
 
 * @param percent: Percentage of change (>0 means increase, <0 means decrease)
 
 */
 
static void ReportNewsProductionChangeIndustry(Industry *ind, CargoID type, int percent)
 
{
 
	NewsSubtype ns;
 

	
 
	switch (WhoCanServiceIndustry(ind)) {
 
		case 0: ns = NS_INDUSTRY_NOBODY;  break;
 
		case 1: ns = NS_INDUSTRY_OTHER;   break;
 
		case 2: ns = NS_INDUSTRY_COMPANY; break;
 
		default: NOT_REACHED();
 
	}
 
	SetDParam(2, abs(percent));
 
	SetDParam(0, CargoSpec::Get(type)->name);
 
	SetDParam(1, ind->index);
 
	AddIndustryNewsItem(
 
		percent >= 0 ? STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_SMOOTH : STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_SMOOTH,
 
		ns,
 
		ind->index
 
	);
 
}
 

	
 
enum {
 
	PERCENT_TRANSPORTED_60 = 153,
 
	PERCENT_TRANSPORTED_80 = 204,
 
};
 
static const uint PERCENT_TRANSPORTED_60 = 153;
 
static const uint PERCENT_TRANSPORTED_80 = 204;
 

	
 
/** Change industry production or do closure
 
 * @param i Industry for which changes are performed
 
 * @param monthly true if it's the monthly call, false if it's the random call
 
 */
 
static void ChangeIndustryProduction(Industry *i, bool monthly)
 
{
 
	StringID str = STR_NULL;
 
	bool closeit = false;
 
	const IndustrySpec *indspec = GetIndustrySpec(i->type);
 
	bool standard = false;
 
	bool suppress_message = false;
 
	bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
 
	/* don't use smooth economy for industries using production related callbacks */
 
	bool smooth_economy = _settings_game.economy.smooth_economy &&
 
	                      !(HasBit(indspec->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(indspec->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
 
	                      !(HasBit(indspec->callback_mask, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(indspec->callback_mask, CBM_IND_PRODUCTION_CHANGE));            // production change callbacks
 
	byte div = 0;
 
	byte mul = 0;
 
	int8 increment = 0;
 

	
 
	bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
 
	if (callback_enabled) {
 
		uint16 res = GetIndustryCallback(monthly ? CBID_INDUSTRY_MONTHLYPROD_CHANGE : CBID_INDUSTRY_PRODUCTION_CHANGE, 0, Random(), i, i->type, i->location.tile);
 
		if (res != CALLBACK_FAILED) { // failed callback means "do nothing"
 
			suppress_message = HasBit(res, 7);
 
			/* Get the custom message if any */
 
			if (HasBit(res, 8)) str = MapGRFStringID(indspec->grf_prop.grffile->grfid, GB(GetRegister(0x100), 0, 16));
 
			res = GB(res, 0, 4);
 
			switch (res) {
 
				default: NOT_REACHED();
 
				case 0x0: break;                  // Do nothing, but show the custom message if any
 
				case 0x1: div = 1; break;         // Halve industry production. If production reaches the quarter of the default, the industry is closed instead.
 
				case 0x2: mul = 1; break;         // Double industry production if it hasn't reached eight times of the original yet.
 
				case 0x3: closeit = true; break;  // The industry announces imminent closure, and is physically removed from the map next month.
 
				case 0x4: standard = true; break; // Do the standard random production change as if this industry was a primary one.
 
				case 0x5: case 0x6: case 0x7:     // Divide production by 4, 8, 16
 
				case 0x8: div = res - 0x3; break; // Divide production by 32
 
				case 0x9: case 0xA: case 0xB:     // Multiply production by 4, 8, 16
 
				case 0xC: mul = res - 0x7; break; // Multiply production by 32
 
				case 0xD:                         // decrement production
 
				case 0xE:                         // increment production
 
					increment = res == 0x0D ? -1 : 1;
 
					break;
 
				case 0xF:                         // Set production to third byte of register 0x100
 
					i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
 
					recalculate_multipliers = true;
 
					break;
src/misc_gui.cpp
Show inline comments
 
@@ -34,103 +34,103 @@
 
#include "tilehighlight_func.h"
 
#include "querystring_gui.h"
 
#include "console_func.h"
 
#include "core/geometry_func.hpp"
 
#include "newgrf_debug.h"
 

	
 
#include "table/strings.h"
 

	
 

	
 
/**
 
 * Try to retrive the current clipboard contents.
 
 *
 
 * @note OS-specific funtion.
 
 * @return True if some text could be retrived.
 
 */
 
bool GetClipboardContents(char *buffer, size_t buff_len);
 

	
 

	
 
/* Variables to display file lists */
 
SaveLoadDialogMode _saveload_mode;
 

	
 

	
 
static bool _fios_path_changed;
 
static bool _savegame_sort_dirty;
 
int _caret_timer;
 

	
 
/** Widgets for the land info window. */
 
enum LandInfoWidgets {
 
	LIW_BACKGROUND, ///< Background to draw on
 
};
 

	
 
static const NWidgetPart _nested_land_info_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
 
		NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_LAND_AREA_INFORMATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
 
		NWidget(WWT_DEBUGBOX, COLOUR_GREY),
 
	EndContainer(),
 
	NWidget(WWT_PANEL, COLOUR_GREY, LIW_BACKGROUND), EndContainer(),
 
};
 

	
 
static const WindowDesc _land_info_desc(
 
	WDP_AUTO, 0, 0,
 
	WC_LAND_INFO, WC_NONE,
 
	0,
 
	_nested_land_info_widgets, lengthof(_nested_land_info_widgets)
 
);
 

	
 
class LandInfoWindow : public Window {
 
	enum {
 
	enum LandInfoLines {
 
		LAND_INFO_CENTERED_LINES   = 12,                       ///< Up to 12 centered lines
 
		LAND_INFO_MULTICENTER_LINE = LAND_INFO_CENTERED_LINES, ///< One multicenter line
 
		LAND_INFO_LINE_END,
 
	};
 

	
 
		LAND_INFO_LINE_BUFF_SIZE = 512,
 
	};
 
	static const uint LAND_INFO_LINE_BUFF_SIZE = 512;
 

	
 
public:
 
	char landinfo_data[LAND_INFO_LINE_END][LAND_INFO_LINE_BUFF_SIZE];
 
	TileIndex tile;
 

	
 
	virtual void OnPaint()
 
	{
 
		this->DrawWidgets();
 
	}
 

	
 
	virtual void DrawWidget(const Rect &r, int widget) const
 
	{
 
		if (widget != LIW_BACKGROUND) return;
 

	
 
		uint y = r.top + WD_TEXTPANEL_TOP;
 
		for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) {
 
			if (StrEmpty(this->landinfo_data[i])) break;
 

	
 
			DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING, SA_CENTER);
 
			y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
 
			if (i == 0) y += 4;
 
		}
 

	
 
		if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) {
 
			SetDParamStr(0, this->landinfo_data[LAND_INFO_MULTICENTER_LINE]);
 
			DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, r.bottom - WD_TEXTPANEL_BOTTOM, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER);
 
		}
 
	}
 

	
 
	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
 
	{
 
		if (widget != LIW_BACKGROUND) return;
 

	
 
		size->height = WD_TEXTPANEL_TOP + WD_TEXTPANEL_BOTTOM;
 
		for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) {
 
			if (StrEmpty(this->landinfo_data[i])) break;
 

	
 
			uint width = GetStringBoundingBox(this->landinfo_data[i]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
 
			size->width = max(size->width, width);
 

	
 
			size->height += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
 
			if (i == 0) size->height += 4;
 
		}
 

	
 
		if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) {
 
			uint width = GetStringBoundingBox(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
 
			size->width = max(size->width, min(300u, width));
 
			SetDParamStr(0, this->landinfo_data[LAND_INFO_MULTICENTER_LINE]);
src/music/qtmidi.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/**
 
 * @file qtmidi.cpp
 
 * @brief MIDI music player for MacOS X using QuickTime.
 
 *
 
 * This music player should work in all MacOS X releases starting from 10.0,
 
 * as QuickTime is an integral part of the system since the old days of the
 
 * Motorola 68k-based Macintoshes. The only extra dependency apart from
 
 * QuickTime itself is Carbon, which is included since 10.0 as well.
 
 *
 
 * QuickTime gets fooled with the MIDI files from Transport Tycoon Deluxe
 
 * because of the @c .gm suffix. To force QuickTime to load the MIDI files
 
 * without the need of dealing with the individual QuickTime components
 
 * needed to play music (data source, MIDI parser, note allocators,
 
 * synthesizers and the like) some Carbon functions are used to set the file
 
 * type as seen by QuickTime, using @c FSpSetFInfo() (which modifies the
 
 * file's resource fork).
 
 */
 

	
 

	
 
#ifndef NO_QUICKTIME
 

	
 
#include "../stdafx.h"
 
#include "qtmidi.h"
 
#include "../debug.h"
 

	
 
#define Rect  OTTDRect
 
#define Point OTTDPoint
 
#include <QuickTime/QuickTime.h>
 
#undef Rect
 
#undef Point
 

	
 
static FMusicDriver_QtMidi iFMusicDriver_QtMidi;
 

	
 

	
 
enum {
 
	midiType = 'Midi' ///< OSType code for MIDI songs.
 
};
 
static const uint MIDI_TYPE = 'Midi' ///< OSType code for MIDI songs.
 

	
 

	
 
/**
 
 * Sets the @c OSType of a given file to @c 'Midi', but only if it's not
 
 * already set.
 
 *
 
 * @param *ref A @c FSSpec structure referencing a file.
 
 */
 
static void SetMIDITypeIfNeeded(const FSRef *ref)
 
{
 
	FSCatalogInfo catalogInfo;
 

	
 
	assert(ref);
 

	
 
	if (noErr != FSGetCatalogInfo(ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, NULL)) return;
 
	if (!(catalogInfo.nodeFlags & kFSNodeIsDirectoryMask)) {
 
		FileInfo * const info = (FileInfo *) catalogInfo.finderInfo;
 
		if (info->fileType != midiType && !(info->finderFlags & kIsAlias)) {
 
		if (info->fileType != MIDI_TYPE && !(info->finderFlags & kIsAlias)) {
 
			OSErr e;
 
			info->fileType = midiType;
 
			info->fileType = MIDI_TYPE;
 
			e = FSSetCatalogInfo(ref, kFSCatInfoFinderInfo, &catalogInfo);
 
			if (e == noErr) {
 
				DEBUG(driver, 3, "qtmidi: changed filetype to 'Midi'");
 
			} else {
 
				DEBUG(driver, 0, "qtmidi: changing filetype to 'Midi' failed - error %d", e);
 
			}
 
		}
 
	}
 
}
 

	
 

	
 
/**
 
 * Loads a MIDI file and returns it as a QuickTime Movie structure.
 
 *
 
 * @param *path String with the path of an existing MIDI file.
 
 * @param *moov Pointer to a @c Movie where the result will be stored.
 
 * @return Wether the file was loaded and the @c Movie successfully created.
 
 */
 
static bool LoadMovieForMIDIFile(const char *path, Movie *moov)
 
{
 
	int fd;
 
	int ret;
 
	char magic[4];
 
	FSRef fsref;
 
	FSSpec fsspec;
 
	short refnum = 0;
 
	short resid  = 0;
 

	
 
	assert(path != NULL);
 
	assert(moov != NULL);
 

	
 
	DEBUG(driver, 2, "qtmidi: start loading '%s'...", path);
 

	
 
	/*
 
	 * XXX Manual check for MIDI header ('MThd'), as I don't know how to make
 
	 * QuickTime load MIDI files without a .mid suffix without knowing it's
 
	 * a MIDI file and setting the OSType of the file to the 'Midi' value.
 
	 * Perhahaps ugly, but it seems that it does the Right Thing(tm).
 
	 */
 
	fd = open(path, O_RDONLY, 0);
 
	if (fd == -1) return false;
 
	ret = read(fd, magic, 4);
 
	close(fd);
 
	if (ret < 4) return false;
 

	
 
	DEBUG(driver, 3, "qtmidi: header is '%.4s'", magic);
 
	if (magic[0] != 'M' || magic[1] != 'T' || magic[2] != 'h' || magic[3] != 'd') {
 
		return false;
 
@@ -116,97 +114,97 @@ static bool LoadMovieForMIDIFile(const c
 

	
 
	if (noErr != FSPathMakeRef((const UInt8 *) path, &fsref, NULL)) return false;
 
	SetMIDITypeIfNeeded(&fsref);
 

	
 
	if (noErr != FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fsspec, NULL)) return false;
 
	if (OpenMovieFile(&fsspec, &refnum, fsRdPerm) != noErr) return false;
 
	DEBUG(driver, 3, "qtmidi: '%s' successfully opened", path);
 

	
 
	if (noErr != NewMovieFromFile(moov, refnum, &resid, NULL,
 
				newMovieActive | newMovieDontAskUnresolvedDataRefs, NULL)) {
 
		CloseMovieFile(refnum);
 
		return false;
 
	}
 
	DEBUG(driver, 3, "qtmidi: movie container created");
 

	
 
	CloseMovieFile(refnum);
 
	return true;
 
}
 

	
 

	
 
/**
 
 * Flag which has the @c true value when QuickTime is available and
 
 * initialized.
 
 */
 
static bool _quicktime_started = false;
 

	
 

	
 
/**
 
 * Initialize QuickTime if needed. This function sets the
 
 * #_quicktime_started flag to @c true if QuickTime is present in the system
 
 * and it was initialized properly.
 
 */
 
static void InitQuickTimeIfNeeded()
 
{
 
	OSStatus dummy;
 

	
 
	if (_quicktime_started) return;
 

	
 
	DEBUG(driver, 2, "qtmidi: initializing Quicktime");
 
	/* Be polite: check wether QuickTime is available and initialize it. */
 
	_quicktime_started =
 
		(noErr == Gestalt(gestaltQuickTime, &dummy)) &&
 
		(noErr == EnterMovies());
 
	if (!_quicktime_started) DEBUG(driver, 0, "qtmidi: Quicktime initialization failed!");
 
}
 

	
 

	
 
/** Possible states of the QuickTime music driver. */
 
enum {
 
enum QTStates {
 
	QT_STATE_IDLE, ///< No file loaded.
 
	QT_STATE_PLAY, ///< File loaded, playing.
 
	QT_STATE_STOP, ///< File loaded, stopped.
 
};
 

	
 

	
 
static Movie _quicktime_movie;                  ///< Current QuickTime @c Movie.
 
static byte  _quicktime_volume = 127;           ///< Current volume.
 
static int   _quicktime_state  = QT_STATE_IDLE; ///< Current player state.
 

	
 

	
 
/**
 
 * Maps OpenTTD volume to QuickTime notion of volume.
 
 */
 
#define VOLUME  ((short)((0x00FF & _quicktime_volume) << 1))
 

	
 

	
 
/**
 
 * Initialized the MIDI player, including QuickTime initialization.
 
 *
 
 * @todo Give better error messages by inspecting error codes returned by
 
 * @c Gestalt() and @c EnterMovies(). Needs changes in
 
 * #InitQuickTimeIfNeeded.
 
 */
 
const char *MusicDriver_QtMidi::Start(const char * const *parm)
 
{
 
	InitQuickTimeIfNeeded();
 
	return (_quicktime_started) ? NULL : "can't initialize QuickTime";
 
}
 

	
 

	
 
/**
 
 * Checks wether the player is active.
 
 *
 
 * This function is called at regular intervals from OpenTTD's main loop, so
 
 * we call @c MoviesTask() from here to let QuickTime do its work.
 
 */
 
bool MusicDriver_QtMidi::IsSongPlaying()
 
{
 
	if (!_quicktime_started) return true;
 

	
 
	switch (_quicktime_state) {
 
		case QT_STATE_IDLE:
 
		case QT_STATE_STOP:
 
			/* Do nothing. */
 
			break;
 

	
 
		case QT_STATE_PLAY:
src/network/network_chat_gui.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file network_chat_gui.cpp GUI for handling chat messages. */
 

	
 
#include <stdarg.h> /* va_list */
 

	
 
#ifdef ENABLE_NETWORK
 

	
 
#include "../stdafx.h"
 
#include "../date_func.h"
 
#include "../gfx_func.h"
 
#include "../strings_func.h"
 
#include "../blitter/factory.hpp"
 
#include "../console_func.h"
 
#include "../video/video_driver.hpp"
 
#include "../table/sprites.h"
 
#include "../querystring_gui.h"
 
#include "../town.h"
 
#include "../window_func.h"
 
#include "../core/geometry_func.hpp"
 
#include "network.h"
 
#include "network_client.h"
 
#include "network_base.h"
 

	
 
#include "table/strings.h"
 

	
 
/* The draw buffer must be able to contain the chat message, client name and the "[All]" message,
 
 * some spaces and possible translations of [All] to other languages. */
 
assert_compile((int)DRAW_STRING_BUFFER >= (int)NETWORK_CHAT_LENGTH + NETWORK_NAME_LENGTH + 40);
 

	
 
enum {
 
	NETWORK_CHAT_LINE_SPACING = 3,
 
};
 
static const uint NETWORK_CHAT_LINE_SPACING = 3;
 

	
 
struct ChatMessage {
 
	char message[DRAW_STRING_BUFFER];
 
	TextColour colour;
 
	Date end_date;
 
};
 

	
 
/* used for chat window */
 
static ChatMessage *_chatmsg_list = NULL;
 
static bool _chatmessage_dirty = false;
 
static bool _chatmessage_visible = false;
 
static bool _chat_tab_completion_active;
 
static uint MAX_CHAT_MESSAGES = 0;
 

	
 
/* The chatbox grows from the bottom so the coordinates are pixels from
 
 * the left and pixels from the bottom. The height is the maximum height */
 
static PointDimension _chatmsg_box;
 
static uint8 *_chatmessage_backup = NULL;
 

	
 
static inline uint GetChatMessageCount()
 
{
 
	uint i = 0;
 
	for (; i < MAX_CHAT_MESSAGES; i++) {
 
		if (_chatmsg_list[i].message[0] == '\0') break;
 
	}
 

	
 
	return i;
 
}
 

	
 
/**
 
 * Add a text message to the 'chat window' to be shown
 
 * @param colour The colour this message is to be shown in
 
 * @param duration The duration of the chat message in game-days
 
 * @param message message itself in printf() style
 
 */
 
void CDECL NetworkAddChatMessage(TextColour colour, uint8 duration, const char *message, ...)
 
{
 
	char buf[DRAW_STRING_BUFFER];
 
	const char *bufp;
 
	va_list va;
 
	uint msg_count;
 
	uint16 lines;
 

	
 
	va_start(va, message);
 
	vsnprintf(buf, lengthof(buf), message, va);
 
	va_end(va);
 

	
 
	Utf8TrimString(buf, DRAW_STRING_BUFFER);
src/network/network_content_gui.cpp
Show inline comments
 
@@ -180,100 +180,98 @@ public:
 
	virtual void OnDownloadProgress(const ContentInfo *ci, uint bytes)
 
	{
 
		if (ci->id != this->cur_id) {
 
			strecpy(this->name, ci->filename, lastof(this->name));
 
			this->cur_id = ci->id;
 
			this->downloaded_files++;
 
			this->receivedTypes.Include(ci->type);
 
		}
 
		this->downloaded_bytes += bytes;
 

	
 
		/* When downloading is finished change cancel in ok */
 
		if (this->downloaded_bytes == this->total_bytes) {
 
			this->GetWidget<NWidgetCore>(NCDSWW_CANCELOK)->widget_data = STR_BUTTON_OK;
 
		}
 

	
 
		this->SetDirty();
 
	}
 
};
 

	
 
/** Widgets of the content list window. */
 
enum NetworkContentListWindowWidgets {
 
	NCLWW_BACKGROUND,    ///< Resize button
 

	
 
	NCLWW_FILTER_CAPT,   ///< Caption for the filter editbox
 
	NCLWW_FILTER,        ///< Filter editbox
 

	
 
	NCLWW_CHECKBOX,      ///< Button above checkboxes
 
	NCLWW_TYPE,          ///< 'Type' button
 
	NCLWW_NAME,          ///< 'Name' button
 

	
 
	NCLWW_MATRIX,        ///< Panel with list of content
 
	NCLWW_SCROLLBAR,     ///< Scrollbar of matrix
 

	
 
	NCLWW_DETAILS,       ///< Panel with content details
 

	
 
	NCLWW_SELECT_ALL,    ///< 'Select all' button
 
	NCLWW_SELECT_UPDATE, ///< 'Select updates' button
 
	NCLWW_UNSELECT,      ///< 'Unselect all' button
 
	NCLWW_CANCEL,        ///< 'Cancel' button
 
	NCLWW_DOWNLOAD,      ///< 'Download' button
 

	
 
	NCLWW_SEL_ALL_UPDATE, ///< #NWID_SELECTION widget for select all/update buttons.
 
};
 

	
 
/** Window that lists the content that's at the content server */
 
class NetworkContentListWindow : public QueryStringBaseWindow, ContentCallback {
 
	typedef GUIList<const ContentInfo*> GUIContentList;
 

	
 
	enum {
 
		EDITBOX_MAX_SIZE = 50,
 
		EDITBOX_MAX_LENGTH = 300,
 
	};
 
	static const uint EDITBOX_MAX_SIZE   =  50;
 
	static const uint EDITBOX_MAX_LENGTH = 300;
 

	
 
	/** Runtime saved values */
 
	static Listing last_sorting;
 
	static Filtering last_filtering;
 
	/** The sorter functions */
 
	static GUIContentList::SortFunction * const sorter_funcs[];
 
	static GUIContentList::FilterFunction * const filter_funcs[];
 
	GUIContentList content;      ///< List with content
 

	
 
	const ContentInfo *selected; ///< The selected content info
 
	int list_pos;                ///< Our position in the list
 
	uint filesize_sum;           ///< The sum of all selected file sizes
 

	
 
	/**
 
	 * (Re)build the network game list as its amount has changed because
 
	 * an item has been added or deleted for example
 
	 */
 
	void BuildContentList()
 
	{
 
		if (!this->content.NeedRebuild()) return;
 

	
 
		/* Create temporary array of games to use for listing */
 
		this->content.Clear();
 

	
 
		for (ConstContentIterator iter = _network_content_client.Begin(); iter != _network_content_client.End(); iter++) {
 
			*this->content.Append() = *iter;
 
		}
 

	
 
		this->FilterContentList();
 
		this->content.Compact();
 
		this->content.RebuildDone();
 
		this->SortContentList();
 

	
 
		this->vscroll.SetCount(this->content.Length()); // Update the scrollbar
 
		this->ScrollToSelected();
 
	}
 

	
 
	/** Sort content by name. */
 
	static int CDECL NameSorter(const ContentInfo * const *a, const ContentInfo * const *b)
 
	{
 
		return strcasecmp((*a)->name, (*b)->name);
 
	}
 

	
 
	/** Sort content by type. */
 
	static int CDECL TypeSorter(const ContentInfo * const *a, const ContentInfo * const *b)
 
	{
 
		int r = 0;
 
		if ((*a)->type != (*b)->type) {
src/network/network_gamelist.cpp
Show inline comments
 
@@ -87,101 +87,99 @@ NetworkGameList *NetworkGameListAddItem(
 
	for (item = _network_game_list; item != NULL; item = item->next) {
 
		if (item->address == address) return item;
 
		prev_item = item;
 
	}
 

	
 
	item = CallocT<NetworkGameList>(1);
 
	item->next = NULL;
 
	item->address = address;
 

	
 
	if (prev_item == NULL) {
 
		_network_game_list = item;
 
	} else {
 
		prev_item->next = item;
 
	}
 
	DEBUG(net, 4, "[gamelist] added server to list");
 

	
 
	UpdateNetworkGameWindow(false);
 

	
 
	return item;
 
}
 

	
 
/** Remove an item from the gamelist linked list
 
 * @param remove pointer to the item to be removed */
 
void NetworkGameListRemoveItem(NetworkGameList *remove)
 
{
 
	NetworkGameList *prev_item = NULL;
 
	for (NetworkGameList *item = _network_game_list; item != NULL; item = item->next) {
 
		if (remove == item) {
 
			if (prev_item == NULL) {
 
				_network_game_list = remove->next;
 
			} else {
 
				prev_item->next = remove->next;
 
			}
 

	
 
			/* Remove GRFConfig information */
 
			ClearGRFConfigList(&remove->info.grfconfig);
 
			free(remove);
 
			remove = NULL;
 

	
 
			DEBUG(net, 4, "[gamelist] removed server from list");
 
			NetworkRebuildHostList();
 
			UpdateNetworkGameWindow(false);
 
			return;
 
		}
 
		prev_item = item;
 
	}
 
}
 

	
 
enum {
 
	MAX_GAME_LIST_REQUERY_COUNT  = 10, ///< How often do we requery in number of times per server?
 
	REQUERY_EVERY_X_GAMELOOPS    = 60, ///< How often do we requery in time?
 
	REFRESH_GAMEINFO_X_REQUERIES = 50, ///< Refresh the game info itself after REFRESH_GAMEINFO_X_REQUERIES * REQUERY_EVERY_X_GAMELOOPS game loops
 
};
 
static const uint MAX_GAME_LIST_REQUERY_COUNT  = 10; ///< How often do we requery in number of times per server?
 
static const uint REQUERY_EVERY_X_GAMELOOPS    = 60; ///< How often do we requery in time?
 
static const uint REFRESH_GAMEINFO_X_REQUERIES = 50; ///< Refresh the game info itself after REFRESH_GAMEINFO_X_REQUERIES * REQUERY_EVERY_X_GAMELOOPS game loops
 

	
 
/** Requeries the (game) servers we have not gotten a reply from */
 
void NetworkGameListRequery()
 
{
 
	NetworkGameListHandleDelayedInsert();
 

	
 
	static uint8 requery_cnt = 0;
 

	
 
	if (++requery_cnt < REQUERY_EVERY_X_GAMELOOPS) return;
 
	requery_cnt = 0;
 

	
 
	for (NetworkGameList *item = _network_game_list; item != NULL; item = item->next) {
 
		item->retries++;
 
		if (item->retries < REFRESH_GAMEINFO_X_REQUERIES && (item->online || item->retries >= MAX_GAME_LIST_REQUERY_COUNT)) continue;
 

	
 
		/* item gets mostly zeroed by NetworkUDPQueryServer */
 
		uint8 retries = item->retries;
 
		NetworkUDPQueryServer(NetworkAddress(item->address));
 
		item->retries = (retries >= REFRESH_GAMEINFO_X_REQUERIES) ? 0 : retries;
 
	}
 
}
 

	
 
/**
 
 * Rebuild the GRFConfig's of the servers in the game list as we did
 
 * a rescan and might have found new NewGRFs.
 
 */
 
void NetworkAfterNewGRFScan()
 
{
 
	for (NetworkGameList *item = _network_game_list; item != NULL; item = item->next) {
 
		/* Reset compatability state */
 
		item->info.compatible = item->info.version_compatible;
 

	
 
		for (GRFConfig *c = item->info.grfconfig; c != NULL; c = c->next) {
 
			assert(HasBit(c->flags, GCF_COPY));
 

	
 
			const GRFConfig *f = FindGRFConfig(c->ident.grfid, c->ident.md5sum);
 
			if (f == NULL) {
 
				/* Don't know the GRF, so mark game incompatible and the (possibly)
 
				 * already resolved name for this GRF (another server has sent the
 
				 * name of the GRF already */
 
				c->name   = FindUnknownGRFName(c->ident.grfid, c->ident.md5sum, true);
 
				c->status = GCS_NOT_FOUND;
 

	
 
				/* If we miss a file, we're obviously incompatible */
 
				item->info.compatible = false;
 
			} else {
 
				c->filename  = f->filename;
 
				c->name      = f->name;
src/network/network_udp.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/**
 
 * @file network_udp.cpp This file handles the UDP related communication.
 
 *
 
 * This is the GameServer <-> MasterServer and GameServer <-> GameClient
 
 * communication before the game is being joined.
 
 */
 

	
 
#ifdef ENABLE_NETWORK
 

	
 
#include "../stdafx.h"
 
#include "../date_func.h"
 
#include "../map_func.h"
 
#include "../debug.h"
 
#include "network_gamelist.h"
 
#include "network_internal.h"
 
#include "network_udp.h"
 
#include "network.h"
 
#include "../core/endian_func.hpp"
 
#include "../company_base.h"
 
#include "../thread/thread.h"
 
#include "../rev.h"
 

	
 
#include "core/udp.h"
 

	
 
static ThreadMutex *_network_udp_mutex = ThreadMutex::New();
 

	
 
/** Session key to register ourselves to the master server */
 
static uint64 _session_key = 0;
 

	
 
enum {
 
	ADVERTISE_NORMAL_INTERVAL = 30000, // interval between advertising in ticks (15 minutes)
 
	ADVERTISE_RETRY_INTERVAL  =   300, // readvertise when no response after this many ticks (9 seconds)
 
	ADVERTISE_RETRY_TIMES     =     3  // give up readvertising after this much failed retries
 
};
 
static const uint ADVERTISE_NORMAL_INTERVAL = 30000; ///< interval between advertising in ticks (15 minutes)
 
static const uint ADVERTISE_RETRY_INTERVAL  =   300; ///< readvertise when no response after this many ticks (9 seconds)
 
static const uint ADVERTISE_RETRY_TIMES     =     3; ///< give up readvertising after this much failed retries
 

	
 
NetworkUDPSocketHandler *_udp_client_socket = NULL; ///< udp client socket
 
NetworkUDPSocketHandler *_udp_server_socket = NULL; ///< udp server socket
 
NetworkUDPSocketHandler *_udp_master_socket = NULL; ///< udp master socket
 

	
 
///*** Communication with the masterserver ***/
 

	
 
class MasterNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
 
protected:
 
	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER);
 
	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_SESSION_KEY);
 
public:
 
	MasterNetworkUDPSocketHandler(NetworkAddressList *addresses) : NetworkUDPSocketHandler(addresses) {}
 
	virtual ~MasterNetworkUDPSocketHandler() {}
 
};
 

	
 
DEF_UDP_RECEIVE_COMMAND(Master, PACKET_UDP_MASTER_ACK_REGISTER)
 
{
 
	_network_advertise_retries = 0;
 
	DEBUG(net, 2, "[udp] advertising on master server successful (%s)", NetworkAddress::AddressFamilyAsString(client_addr->GetAddress()->ss_family));
 

	
 
	/* We are advertised, but we don't want to! */
 
	if (!_settings_client.network.server_advertise) NetworkUDPRemoveAdvertise(false);
 
}
 

	
 
DEF_UDP_RECEIVE_COMMAND(Master, PACKET_UDP_MASTER_SESSION_KEY)
 
{
 
	_session_key = p->Recv_uint64();
 
	DEBUG(net, 2, "[udp] received new session key from master server (%s)", NetworkAddress::AddressFamilyAsString(client_addr->GetAddress()->ss_family));
 
}
 

	
 
///*** Communication with clients (we are server) ***/
 

	
 
class ServerNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
 
protected:
 
	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER);
 
	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO);
 
	DECLARE_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS);
 
public:
 
	ServerNetworkUDPSocketHandler(NetworkAddressList *addresses) : NetworkUDPSocketHandler(addresses) {}
 
	virtual ~ServerNetworkUDPSocketHandler() {}
 
};
 

	
 
DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_FIND_SERVER)
 
{
 
	/* Just a fail-safe.. should never happen */
 
	if (!_network_udp_server) {
 
		return;
src/newgrf.cpp
Show inline comments
 
@@ -135,99 +135,97 @@ public:
 
				return 0;
 
		}
 
	}
 

	
 
	const char *ReadString()
 
	{
 
		char *string = reinterpret_cast<char *>(data);
 
		size_t string_length = ttd_strnlen(string, Remaining());
 

	
 
		if (string_length == Remaining()) {
 
			/* String was not NUL terminated, so make sure it is now. */
 
			string[string_length - 1] = '\0';
 
			grfmsg(7, "String was not terminated with a zero byte.");
 
		} else {
 
			/* Increase the string length to include the NUL byte. */
 
			string_length++;
 
		}
 
		Skip(string_length);
 

	
 
		return string;
 
	}
 

	
 
	FORCEINLINE size_t Remaining() const
 
	{
 
		return end - data;
 
	}
 

	
 
	FORCEINLINE bool HasData() const
 
	{
 
		return data < end;
 
	}
 

	
 
	FORCEINLINE byte *Data()
 
	{
 
		return data;
 
	}
 

	
 
	FORCEINLINE void Skip(size_t len)
 
	{
 
		data += len;
 
		/* It is valid to move the buffer to exactly the end of the data,
 
		 * as there may not be any more data read. */
 
		if (data > end) throw OTTDByteReaderSignal();
 
	}
 
};
 

	
 
typedef void (*SpecialSpriteHandler)(ByteReader *buf);
 

	
 
enum {
 
	MAX_STATIONS = 256,
 
};
 
static const uint MAX_STATIONS = 256;
 

	
 
/* Temporary data used when loading only */
 
struct GRFTempEngineData {
 
	uint16 cargo_allowed;
 
	uint16 cargo_disallowed;
 
	RailTypeLabel railtypelabel;
 
	bool refitmask_valid;    ///< Did the newgrf set any refittability property? If not, default refittability will be applied.
 
	uint8 rv_max_speed;      ///< Temporary storage of RV prop 15, maximum speed in mph/0.8
 
};
 

	
 
static GRFTempEngineData *_gted;
 

	
 
/* Contains the GRF ID of the owner of a vehicle if it has been reserved.
 
 * GRM for vehicles is only used if dynamic engine allocation is disabled,
 
 * so 256 is the number of original engines. */
 
static uint32 _grm_engines[256];
 

	
 
/* Contains the GRF ID of the owner of a cargo if it has been reserved */
 
static uint32 _grm_cargos[NUM_CARGO * 2];
 

	
 
struct GRFLocation {
 
	uint32 grfid;
 
	uint32 nfoline;
 

	
 
	GRFLocation(uint32 grfid, uint32 nfoline) : grfid(grfid), nfoline(nfoline) { }
 

	
 
	bool operator<(const GRFLocation &other) const
 
	{
 
		return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
 
	}
 

	
 
	bool operator == (const GRFLocation &other) const
 
	{
 
		return this->grfid == other.grfid && this->nfoline == other.nfoline;
 
	}
 
};
 

	
 
static std::map<GRFLocation, SpriteID> _grm_sprites;
 
typedef std::map<GRFLocation, byte*> GRFLineToSpriteOverride;
 
static GRFLineToSpriteOverride _grf_line_to_action6_sprite_override;
 

	
 
/** DEBUG() function dedicated to newGRF debugging messages
 
 * Function is essentialy the same as DEBUG(grf, severity, ...) with the
 
 * addition of file:line information when parsing grf files.
 
 * NOTE: for the above reason(s) grfmsg() should ONLY be used for
 
 * loading/parsing grf files, not for runtime debug messages as there
 
 * is no file information available during that time.
 
 * @param severity debugging severity level, see debug.h
 
@@ -6564,97 +6562,97 @@ static void FinaliseIndustriesArray()
 
					}
 

	
 
					_industry_mngr.SetEntitySpec(indsp);
 
					_loaded_newgrf_features.has_newindustries = true;
 
				}
 
			}
 
		}
 

	
 
		if (indtspec != NULL) {
 
			for (int i = 0; i < NUM_INDUSTRYTILES; i++) {
 
				IndustryTileSpec *indtsp = indtspec[i];
 
				if (indtsp != NULL) {
 
					_industile_mngr.SetEntitySpec(indtsp);
 
				}
 
			}
 
		}
 
	}
 

	
 
	for (uint j = 0; j < NUM_INDUSTRYTYPES; j++) {
 
		IndustrySpec *indsp = &_industry_specs[j];
 
		if (indsp->enabled && indsp->grf_prop.grffile != NULL) {
 
			for (uint i = 0; i < 3; i++) {
 
				indsp->conflicting[i] = MapNewGRFIndustryType(indsp->conflicting[i], indsp->grf_prop.grffile->grfid);
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 * Add all new airports to the airport array. Airport properties can be set at any
 
 * time in the GRF file, so we can only add a airport spec to the airport array
 
 * after the file has finished loading.
 
 */
 
static void FinaliseAirportsArray()
 
{
 
	const GRFFile * const *end = _grf_files.End();
 
	for (GRFFile **file = _grf_files.Begin(); file != end; file++) {
 
		AirportSpec **&airportspec = (*file)->airportspec;
 
		if (airportspec != NULL) {
 
			for (int i = 0; i < NUM_AIRPORTS; i++) {
 
				if (airportspec[i] != NULL && airportspec[i]->enabled) {
 
					_airport_mngr.SetEntitySpec(airportspec[i]);
 
				}
 
			}
 
		}
 

	
 
		AirportTileSpec **&airporttilespec = (*file)->airtspec;
 
		if (airporttilespec != NULL) {
 
			for (int i = 0; i < NUM_AIRPORTTILES; i++) {
 
			for (uint i = 0; i < NUM_AIRPORTTILES; i++) {
 
				if (airporttilespec[i] != NULL && airporttilespec[i]->enabled) {
 
					_airporttile_mngr.SetEntitySpec(airporttilespec[i]);
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
/* Here we perform initial decoding of some special sprites (as are they
 
 * described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very
 
 * partial implementation yet).
 
 * XXX: We consider GRF files trusted. It would be trivial to exploit OTTD by
 
 * a crafted invalid GRF file. We should tell that to the user somehow, or
 
 * better make this more robust in the future. */
 
static void DecodeSpecialSprite(byte *buf, uint num, GrfLoadingStage stage)
 
{
 
	/* XXX: There is a difference between staged loading in TTDPatch and
 
	 * here.  In TTDPatch, for some reason actions 1 and 2 are carried out
 
	 * during stage 1, whilst action 3 is carried out during stage 2 (to
 
	 * "resolve" cargo IDs... wtf). This is a little problem, because cargo
 
	 * IDs are valid only within a given set (action 1) block, and may be
 
	 * overwritten after action 3 associates them. But overwriting happens
 
	 * in an earlier stage than associating, so...  We just process actions
 
	 * 1 and 2 in stage 2 now, let's hope that won't get us into problems.
 
	 * --pasky
 
	 * We need a pre-stage to set up GOTO labels of Action 0x10 because the grf
 
	 * is not in memory and scanning the file every time would be too expensive.
 
	 * In other stages we skip action 0x10 since it's already dealt with. */
 
	static const SpecialSpriteHandler handlers[][GLS_END] = {
 
		/* 0x00 */ { NULL,     SafeChangeInfo, NULL,       NULL,           ReserveChangeInfo, FeatureChangeInfo, },
 
		/* 0x01 */ { SkipAct1, SkipAct1,  SkipAct1,        SkipAct1,       SkipAct1,          NewSpriteSet, },
 
		/* 0x02 */ { NULL,     NULL,      NULL,            NULL,           NULL,              NewSpriteGroup, },
 
		/* 0x03 */ { NULL,     GRFUnsafe, NULL,            NULL,           NULL,              FeatureMapSpriteGroup, },
 
		/* 0x04 */ { NULL,     NULL,      NULL,            NULL,           NULL,              FeatureNewName, },
 
		/* 0x05 */ { SkipAct5, SkipAct5,  SkipAct5,        SkipAct5,       SkipAct5,          GraphicsNew, },
 
		/* 0x06 */ { NULL,     NULL,      NULL,            CfgApply,       CfgApply,          CfgApply, },
 
		/* 0x07 */ { NULL,     NULL,      NULL,            NULL,           SkipIf,            SkipIf, },
 
		/* 0x08 */ { ScanInfo, NULL,      NULL,            GRFInfo,        GRFInfo,           GRFInfo, },
 
		/* 0x09 */ { NULL,     NULL,      NULL,            SkipIf,         SkipIf,            SkipIf, },
 
		/* 0x0A */ { SkipActA, SkipActA,  SkipActA,        SkipActA,       SkipActA,          SpriteReplace, },
 
		/* 0x0B */ { NULL,     NULL,      NULL,            GRFLoadError,   GRFLoadError,      GRFLoadError, },
 
		/* 0x0C */ { NULL,     NULL,      NULL,            GRFComment,     NULL,              GRFComment, },
 
		/* 0x0D */ { NULL,     SafeParamSet, NULL,         ParamSet,       ParamSet,          ParamSet, },
 
		/* 0x0E */ { NULL,     SafeGRFInhibit, NULL,       GRFInhibit,     GRFInhibit,        GRFInhibit, },
 
		/* 0x0F */ { NULL,     GRFUnsafe, NULL,            FeatureTownName, NULL,             NULL, },
 
		/* 0x10 */ { NULL,     NULL,      DefineGotoLabel, NULL,           NULL,              NULL, },
 
		/* 0x11 */ { SkipAct11,GRFUnsafe, SkipAct11,       SkipAct11,      SkipAct11,         GRFSound, },
 
		/* 0x12 */ { SkipAct12, SkipAct12, SkipAct12,      SkipAct12,      SkipAct12,         LoadFontGlyph, },
src/newgrf_engine.cpp
Show inline comments
 
@@ -109,97 +109,97 @@ void SetCustomEngineSprites(EngineID eng
 
void SetEngineGRF(EngineID engine, const GRFFile *file)
 
{
 
	Engine *e = Engine::Get(engine);
 
	e->grffile = file;
 
}
 

	
 

	
 
/**
 
 * Retrieve the GRFFile tied to an engine
 
 * @param engine Engine ID to retrieve.
 
 * @return Pointer to GRFFile.
 
 */
 
const GRFFile *GetEngineGRF(EngineID engine)
 
{
 
	return Engine::Get(engine)->grffile;
 
}
 

	
 

	
 
/**
 
 * Retrieve the GRF ID of the GRFFile tied to an engine
 
 * @param engine Engine ID to retrieve.
 
 * @return 32 bit GRFID value.
 
 */
 
uint32 GetEngineGRFID(EngineID engine)
 
{
 
	const GRFFile *file = GetEngineGRF(engine);
 
	return file == NULL ? 0 : file->grfid;
 
}
 

	
 

	
 
static int MapOldSubType(const Vehicle *v)
 
{
 
	switch (v->type) {
 
		case VEH_TRAIN:
 
			if (Train::From(v)->IsEngine()) return 0;
 
			if (Train::From(v)->IsFreeWagon()) return 4;
 
			return 2;
 
		case VEH_ROAD:
 
		case VEH_SHIP:     return 0;
 
		case VEH_AIRCRAFT:
 
		case VEH_DISASTER: return v->subtype;
 
		case VEH_EFFECT:   return v->subtype << 1;
 
		default: NOT_REACHED();
 
	}
 
}
 

	
 

	
 
/* TTDP style aircraft movement states for GRF Action 2 Var 0xE2 */
 
enum {
 
enum TTDPAircraftMovementStates {
 
	AMS_TTDP_HANGAR,
 
	AMS_TTDP_TO_HANGAR,
 
	AMS_TTDP_TO_PAD1,
 
	AMS_TTDP_TO_PAD2,
 
	AMS_TTDP_TO_PAD3,
 
	AMS_TTDP_TO_ENTRY_2_AND_3,
 
	AMS_TTDP_TO_ENTRY_2_AND_3_AND_H,
 
	AMS_TTDP_TO_JUNCTION,
 
	AMS_TTDP_LEAVE_RUNWAY,
 
	AMS_TTDP_TO_INWAY,
 
	AMS_TTDP_TO_RUNWAY,
 
	AMS_TTDP_TO_OUTWAY,
 
	AMS_TTDP_WAITING,
 
	AMS_TTDP_TAKEOFF,
 
	AMS_TTDP_TO_TAKEOFF,
 
	AMS_TTDP_CLIMBING,
 
	AMS_TTDP_FLIGHT_APPROACH,
 
	AMS_TTDP_UNUSED_0x11,
 
	AMS_TTDP_FLIGHT_TO_TOWER,
 
	AMS_TTDP_UNUSED_0x13,
 
	AMS_TTDP_FLIGHT_FINAL,
 
	AMS_TTDP_FLIGHT_DESCENT,
 
	AMS_TTDP_BRAKING,
 
	AMS_TTDP_HELI_TAKEOFF_AIRPORT,
 
	AMS_TTDP_HELI_TO_TAKEOFF_AIRPORT,
 
	AMS_TTDP_HELI_LAND_AIRPORT,
 
	AMS_TTDP_HELI_TAKEOFF_HELIPORT,
 
	AMS_TTDP_HELI_TO_TAKEOFF_HELIPORT,
 
	AMS_TTDP_HELI_LAND_HELIPORT,
 
};
 

	
 

	
 
/**
 
 * Map OTTD aircraft movement states to TTDPatch style movement states
 
 * (VarAction 2 Variable 0xE2)
 
 */
 
static byte MapAircraftMovementState(const Aircraft *v)
 
{
 
	const Station *st = GetTargetAirportIfValid(v);
 
	if (st == NULL) return AMS_TTDP_FLIGHT_TO_TOWER;
 

	
 
	const AirportFTAClass *afc = st->airport.GetFTA();
 
	uint16 amdflag = afc->MovingData(v->pos)->flag;
 

	
 
	switch (v->state) {
 
		case HANGAR:
 
			/* The international airport is a special case as helicopters can land in
 
			 * front of the hanger. Helicopters also change their air.state to
 
@@ -245,97 +245,97 @@ static byte MapAircraftMovementState(con
 
			if (amdflag & AMED_HELI_LOWER) return AMS_TTDP_HELI_LAND_AIRPORT; // Descending.
 
			if (amdflag & AMED_SLOWTURN)   return AMS_TTDP_FLIGHT_TO_TOWER;   // Still hasn't started descent.
 
			return AMS_TTDP_TO_JUNCTION; // On the ground.
 

	
 
		case TAKEOFF: // Moving to takeoff position.
 
			return AMS_TTDP_TO_OUTWAY;
 

	
 
		case STARTTAKEOFF: // Accelerating down runway.
 
			return AMS_TTDP_TAKEOFF;
 

	
 
		case ENDTAKEOFF: // Ascent
 
			return AMS_TTDP_CLIMBING;
 

	
 
		case HELITAKEOFF: // Helicopter is moving to take off position.
 
			if (afc->delta_z == 0) {
 
				return amdflag & AMED_HELI_RAISE ?
 
					AMS_TTDP_HELI_TAKEOFF_AIRPORT : AMS_TTDP_TO_JUNCTION;
 
			} else {
 
				return AMS_TTDP_HELI_TAKEOFF_HELIPORT;
 
			}
 

	
 
		case FLYING:
 
			return amdflag & AMED_HOLD ? AMS_TTDP_FLIGHT_APPROACH : AMS_TTDP_FLIGHT_TO_TOWER;
 

	
 
		case LANDING: // Descent
 
			return AMS_TTDP_FLIGHT_DESCENT;
 

	
 
		case ENDLANDING: // On the runway braking
 
			if (amdflag & AMED_BRAKE) return AMS_TTDP_BRAKING;
 
			/* Landed - moving off runway */
 
			return AMS_TTDP_TO_INWAY;
 

	
 
		case HELILANDING:
 
		case HELIENDLANDING: // Helicoptor is decending.
 
			if (amdflag & AMED_HELI_LOWER) {
 
				return afc->delta_z == 0 ?
 
					AMS_TTDP_HELI_LAND_AIRPORT : AMS_TTDP_HELI_LAND_HELIPORT;
 
			} else {
 
				return AMS_TTDP_FLIGHT_TO_TOWER;
 
			}
 

	
 
		default:
 
			return AMS_TTDP_HANGAR;
 
	}
 
}
 

	
 

	
 
/* TTDP style aircraft movement action for GRF Action 2 Var 0xE6 */
 
enum {
 
enum TTDPAircraftMovementActions {
 
	AMA_TTDP_IN_HANGAR,
 
	AMA_TTDP_ON_PAD1,
 
	AMA_TTDP_ON_PAD2,
 
	AMA_TTDP_ON_PAD3,
 
	AMA_TTDP_HANGAR_TO_PAD1,
 
	AMA_TTDP_HANGAR_TO_PAD2,
 
	AMA_TTDP_HANGAR_TO_PAD3,
 
	AMA_TTDP_LANDING_TO_PAD1,
 
	AMA_TTDP_LANDING_TO_PAD2,
 
	AMA_TTDP_LANDING_TO_PAD3,
 
	AMA_TTDP_PAD1_TO_HANGAR,
 
	AMA_TTDP_PAD2_TO_HANGAR,
 
	AMA_TTDP_PAD3_TO_HANGAR,
 
	AMA_TTDP_PAD1_TO_TAKEOFF,
 
	AMA_TTDP_PAD2_TO_TAKEOFF,
 
	AMA_TTDP_PAD3_TO_TAKEOFF,
 
	AMA_TTDP_HANGAR_TO_TAKOFF,
 
	AMA_TTDP_LANDING_TO_HANGAR,
 
	AMA_TTDP_IN_FLIGHT,
 
};
 

	
 

	
 
/**
 
 * Map OTTD aircraft movement states to TTDPatch style movement actions
 
 * (VarAction 2 Variable 0xE6)
 
 * This is not fully supported yet but it's enough for Planeset.
 
 */
 
static byte MapAircraftMovementAction(const Aircraft *v)
 
{
 
	switch (v->state) {
 
		case HANGAR:
 
			return (v->cur_speed > 0) ? AMA_TTDP_LANDING_TO_HANGAR : AMA_TTDP_IN_HANGAR;
 

	
 
		case TERM1:
 
		case HELIPAD1:
 
			return (v->current_order.IsType(OT_LOADING)) ? AMA_TTDP_ON_PAD1 : AMA_TTDP_LANDING_TO_PAD1;
 

	
 
		case TERM2:
 
		case HELIPAD2:
 
			return (v->current_order.IsType(OT_LOADING)) ? AMA_TTDP_ON_PAD2 : AMA_TTDP_LANDING_TO_PAD2;
 

	
 
		case TERM3:
 
		case TERM4:
 
		case TERM5:
 
		case TERM6:
 
		case TERM7:
 
		case TERM8:
 
		case HELIPAD3:
src/newgrf_gui.cpp
Show inline comments
 
@@ -102,100 +102,98 @@ static void ShowNewGRFInfo(const GRFConf
 
	}
 

	
 
	/* Show flags */
 
	if (c->status == GCS_NOT_FOUND)       y = DrawStringMultiLine(x, right, y, bottom, STR_NEWGRF_SETTINGS_NOT_FOUND);
 
	if (c->status == GCS_DISABLED)        y = DrawStringMultiLine(x, right, y, bottom, STR_NEWGRF_SETTINGS_DISABLED);
 
	if (HasBit(c->flags, GCF_COMPATIBLE)) y = DrawStringMultiLine(x, right, y, bottom, STR_NEWGRF_COMPATIBLE_LOADED);
 

	
 
	/* Draw GRF info if it exists */
 
	if (!StrEmpty(c->GetDescription())) {
 
		SetDParam(0, STR_JUST_RAW_STRING);
 
		SetDParamStr(1, c->GetDescription());
 
		y = DrawStringMultiLine(x, right, y, bottom, STR_BLACK_STRING);
 
	} else {
 
		y = DrawStringMultiLine(x, right, y, bottom, STR_NEWGRF_SETTINGS_NO_INFO);
 
	}
 
}
 

	
 

	
 
/** Names of the add a newgrf window widgets. */
 
enum AddNewGRFWindowWidgets {
 
	ANGRFW_FILTER,
 
	ANGRFW_GRF_LIST,
 
	ANGRFW_SCROLLBAR,
 
	ANGRFW_GRF_INFO,
 
	ANGRFW_ADD,
 
	ANGRFW_RESCAN,
 
};
 

	
 
/**
 
 * Window for adding NewGRF files
 
 */
 
struct NewGRFAddWindow : public QueryStringBaseWindow {
 
private:
 
	typedef GUIList<const GRFConfig *> GUIGRFConfigList;
 

	
 
	GRFConfig **list;
 

	
 
	/** Runtime saved values */
 
	static Listing last_sorting;
 
	static Filtering last_filtering;
 

	
 
	static GUIGRFConfigList::SortFunction * const sorter_funcs[];
 
	static GUIGRFConfigList::FilterFunction * const filter_funcs[];
 
	GUIGRFConfigList grfs;
 

	
 
	const GRFConfig *sel;
 
	int sel_pos;
 

	
 
	enum {
 
		EDITBOX_MAX_SIZE = 50,
 
		EDITBOX_MAX_LENGTH = 300,
 
	};
 
	static const uint EDITBOX_MAX_SIZE   =  50;
 
	static const uint EDITBOX_MAX_LENGTH = 300;
 

	
 
	/**
 
	 * (Re)build the grf as its amount has changed because
 
	 * an item has been added or deleted for example
 
	 */
 
	void BuildGrfList()
 
	{
 
		if (!this->grfs.NeedRebuild()) return;
 

	
 
		/* Create temporary array of grfs to use for listing */
 
		this->grfs.Clear();
 

	
 
		for (const GRFConfig *c = _all_grfs; c != NULL; c = c->next) {
 
			*this->grfs.Append() = c;
 
		}
 

	
 
		this->FilterGrfList();
 
		this->grfs.Compact();
 
		this->grfs.RebuildDone();
 
		this->SortGrfList();
 

	
 
		this->vscroll.SetCount(this->grfs.Length()); // Update the scrollbar
 
		this->ScrollToSelected();
 
	}
 

	
 
	/** Sort grfs by name. */
 
	static int CDECL NameSorter(const GRFConfig * const *a, const GRFConfig * const *b)
 
	{
 
		return strcasecmp((*a)->GetName(), (*b)->GetName());
 
	}
 

	
 
	/** Sort the grf list */
 
	void SortGrfList()
 
	{
 
		if (!this->grfs.Sort()) return;
 
		this->UpdateListPosition();
 
	}
 

	
 
	/** Update selection position. */
 
	void UpdateListPosition()
 
	{
 
		/* update list position */
 
		if (this->sel != NULL) {
 
			this->sel_pos = this->grfs.FindIndex(this->sel);
 
			if (this->sel_pos < 0) {
 
				this->sel = NULL;
 
			}
 
		}
src/newgrf_station.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file newgrf_station.cpp Functions for dealing with station classes and custom stations. */
 

	
 
#include "stdafx.h"
 
#include "variables.h"
 
#include "debug.h"
 
#include "station_base.h"
 
#include "waypoint_base.h"
 
#include "roadstop_base.h"
 
#include "newgrf_cargo.h"
 
#include "newgrf_commons.h"
 
#include "newgrf_station.h"
 
#include "newgrf_spritegroup.h"
 
#include "newgrf_sound.h"
 
#include "newgrf_railtype.h"
 
#include "town.h"
 
#include "newgrf_town.h"
 
#include "date_func.h"
 
#include "company_func.h"
 
#include "animated_tile_func.h"
 
#include "functions.h"
 
#include "tunnelbridge_map.h"
 
#include "newgrf.h"
 
#include "core/random_func.hpp"
 

	
 
#include "table/strings.h"
 

	
 
static StationClass _station_classes[STAT_CLASS_MAX];
 

	
 
enum {
 
	MAX_SPECLIST = 255,
 
};
 
static const uint MAX_SPECLIST = 255;
 

	
 
enum TriggerArea {
 
	TA_TILE,
 
	TA_PLATFORM,
 
	TA_WHOLE,
 
};
 

	
 
struct ETileArea : TileArea {
 
	ETileArea(const BaseStation *st, TileIndex tile, TriggerArea ta)
 
	{
 
		switch (ta) {
 
			default: NOT_REACHED();
 

	
 
			case TA_TILE:
 
				this->tile = tile;
 
				this->w    = 1;
 
				this->h    = 1;
 
				break;
 

	
 
			case TA_PLATFORM: {
 
				TileIndex start, end;
 
				Axis axis = GetRailStationAxis(tile);
 
				TileIndexDiff delta = TileOffsByDiagDir(AxisToDiagDir(axis));
 

	
 
				for (end = tile; IsRailStationTile(end + delta) && IsCompatibleTrainStationTile(tile, end + delta); end += delta) { /* Nothing */ }
 
				for (start = tile; IsRailStationTile(start - delta) && IsCompatibleTrainStationTile(tile, start - delta); start -= delta) { /* Nothing */ }
 

	
 
				this->tile = start;
 
				this->w = TileX(end) - TileX(start) + 1;
 
				this->h = TileY(end) - TileY(start) + 1;
 
				break;
 
			}
 

	
 
			case TA_WHOLE:
 
				st->GetTileArea(this, Station::IsExpected(st) ? STATION_RAIL : STATION_WAYPOINT);
 
				break;
 
		}
 
	}
 
};
 

	
 

	
 
/**
 
 * Reset station classes to their default state.
 
 * This includes initialising the Default and Waypoint classes with an empty
 
 * entry, for standard stations and waypoints.
 
 */
 
void ResetStationClasses()
 
{
src/osk_gui.cpp
Show inline comments
 
@@ -6,97 +6,97 @@
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file osk_gui.cpp The On Screen Keyboard GUI */
 

	
 
#include "stdafx.h"
 
#include "string_func.h"
 
#include "strings_func.h"
 
#include "debug.h"
 
#include "window_func.h"
 
#include "gfx_func.h"
 
#include "querystring_gui.h"
 

	
 
#include "table/sprites.h"
 
#include "table/strings.h"
 

	
 
/** Widget numbers of the on-screen keyboard (OSK) window. */
 
enum OskWidgets {
 
	OSK_WIDGET_CAPTION,         ///< Title bar.
 
	OSK_WIDGET_TEXT,            ///< Edit box.
 
	OSK_WIDGET_CANCEL,          ///< Cancel key.
 
	OSK_WIDGET_OK,              ///< Ok key.
 
	OSK_WIDGET_BACKSPACE,       ///< Backspace key.
 
	OSK_WIDGET_SPECIAL,         ///< Special key (at keyborads often used for tab key).
 
	OSK_WIDGET_CAPS,            ///< Capslock key.
 
	OSK_WIDGET_SHIFT,           ///< Shift(lock) key.
 
	OSK_WIDGET_SPACE,           ///< Space bar.
 
	OSK_WIDGET_LEFT,            ///< Cursor left key.
 
	OSK_WIDGET_RIGHT,           ///< Cursor right key.
 
	OSK_WIDGET_LETTERS,         ///< First widget of the 'normal' keys.
 

	
 
	OSK_WIDGET_NUMBERS_FIRST = OSK_WIDGET_LETTERS,           ///< First widget of the numbers row.
 
	OSK_WIDGET_NUMBERS_LAST = OSK_WIDGET_NUMBERS_FIRST + 13, ///< Last widget of the numbers row.
 

	
 
	OSK_WIDGET_QWERTY_FIRST,                                 ///< First widget of the qwerty row.
 
	OSK_WIDGET_QWERTY_LAST = OSK_WIDGET_QWERTY_FIRST + 11,   ///< Last widget of the qwerty row.
 

	
 
	OSK_WIDGET_ASDFG_FIRST,                                  ///< First widget of the asdfg row.
 
	OSK_WIDGET_ASDFG_LAST = OSK_WIDGET_ASDFG_FIRST + 11,     ///< Last widget of the asdfg row.
 

	
 
	OSK_WIDGET_ZXCVB_FIRST,                                  ///< First widget of the zxcvb row.
 
	OSK_WIDGET_ZXCVB_LAST = OSK_WIDGET_ZXCVB_FIRST + 11,     ///< Last widget of the zxcvb row.
 
};
 

	
 
char _keyboard_opt[2][OSK_KEYBOARD_ENTRIES * 4 + 1];
 
static WChar _keyboard[2][OSK_KEYBOARD_ENTRIES];
 

	
 
enum {
 
enum KeyStateBits {
 
	KEYS_NONE,
 
	KEYS_SHIFT,
 
	KEYS_CAPS
 
};
 
static byte _keystate = KEYS_NONE;
 

	
 
struct OskWindow : public Window {
 
	StringID caption;      ///< the caption for this window.
 
	QueryString *qs;       ///< text-input
 
	int text_btn;          ///< widget number of parent's text field
 
	int ok_btn;            ///< widget number of parent's ok button (=0 when ok shouldn't be passed on)
 
	int cancel_btn;        ///< widget number of parent's cancel button (=0 when cancel shouldn't be passed on; text will be reverted to original)
 
	Textbuf *text;         ///< pointer to parent's textbuffer (to update caret position)
 
	char *orig_str_buf;    ///< Original string.
 
	bool shift;            ///< Is the shift effectively pressed?
 

	
 
	OskWindow(const WindowDesc *desc, QueryStringBaseWindow *parent, int button, int cancel, int ok) : Window()
 
	{
 
		this->parent = parent;
 
		assert(parent != NULL);
 

	
 
		NWidgetCore *par_wid = parent->GetWidget<NWidgetCore>(button);
 
		assert(par_wid != NULL);
 
		this->caption = (par_wid->widget_data != STR_NULL) ? par_wid->widget_data : parent->caption;
 

	
 
		this->qs         = parent;
 
		this->text_btn   = button;
 
		this->cancel_btn = cancel;
 
		this->ok_btn     = ok;
 
		this->text       = &parent->text;
 

	
 
		/* make a copy in case we need to reset later */
 
		this->orig_str_buf = strdup(this->qs->text.buf);
 

	
 
		this->InitNested(desc, 0);
 

	
 
		/* Not needed by default. */
 
		this->DisableWidget(OSK_WIDGET_SPECIAL);
 

	
 
		this->UpdateOskState();
 
	}
 

	
 
	~OskWindow()
 
	{
 
		free(this->orig_str_buf);
 
	}
 

	
 
	/**
src/pathfinder/npf/npf.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file npf.cpp Implementation of the NPF pathfinder. */
 

	
 
#include "../../stdafx.h"
 
#include "../../debug.h"
 
#include "../../landscape.h"
 
#include "../../network/network.h"
 
#include "../../functions.h"
 
#include "../../ship.h"
 
#include "../../roadstop_base.h"
 
#include "../pathfinder_func.h"
 
#include "../pathfinder_type.h"
 
#include "../follow_track.hpp"
 
#include "aystar.h"
 

	
 
enum {
 
	NPF_HASH_BITS = 12, ///< The size of the hash used in pathfinding. Just changing this value should be sufficient to change the hash size. Should be an even value.
 
	/* Do no change below values */
 
	NPF_HASH_SIZE = 1 << NPF_HASH_BITS,
 
	NPF_HASH_HALFBITS = NPF_HASH_BITS / 2,
 
	NPF_HASH_HALFMASK = (1 << NPF_HASH_HALFBITS) - 1
 
};
 
static const uint NPF_HASH_BITS = 12; ///< The size of the hash used in pathfinding. Just changing this value should be sufficient to change the hash size. Should be an even value.
 
/* Do no change below values */
 
static const uint NPF_HASH_SIZE = 1 << NPF_HASH_BITS;
 
static const uint NPF_HASH_HALFBITS = NPF_HASH_BITS / 2;
 
static const uint NPF_HASH_HALFMASK = (1 << NPF_HASH_HALFBITS) - 1;
 

	
 
/* Meant to be stored in AyStar.targetdata */
 
/** Meant to be stored in AyStar.targetdata */
 
struct NPFFindStationOrTileData {
 
	TileIndex dest_coords;    ///< An indication of where the station is, for heuristic purposes, or the target tile
 
	StationID station_index;  ///< station index we're heading for, or INVALID_STATION when we're heading for a tile
 
	bool reserve_path;        ///< Indicates whether the found path should be reserved
 
	StationType station_type; ///< The type of station we're heading for
 
	bool not_articulated;     ///< The (road) vehicle is not articulated
 
	const Vehicle *v;         ///< The vehicle we are pathfinding for
 
};
 

	
 
/* Indices into AyStar.userdata[] */
 
enum {
 
/** Indices into AyStar.userdata[] */
 
enum AyStarUserDataType {
 
	NPF_TYPE = 0,  ///< Contains a TransportTypes value
 
	NPF_SUB_TYPE,  ///< Contains the sub transport type
 
	NPF_OWNER,     ///< Contains an Owner value
 
	NPF_RAILTYPES, ///< Contains a bitmask the compatible RailTypes of the engine when NPF_TYPE == TRANSPORT_RAIL. Unused otherwise.
 
};
 

	
 
/* Indices into AyStarNode.userdata[] */
 
enum {
 
/** Indices into AyStarNode.userdata[] */
 
enum AyStarNodeUserDataType {
 
	NPF_TRACKDIR_CHOICE = 0, ///< The trackdir chosen to get here
 
	NPF_NODE_FLAGS,
 
};
 

	
 
/* Flags for AyStarNode.userdata[NPF_NODE_FLAGS]. Use NPFSetFlag() and NPFGetFlag() to use them. */
 
/** Flags for AyStarNode.userdata[NPF_NODE_FLAGS]. Use NPFSetFlag() and NPFGetFlag() to use them. */
 
enum NPFNodeFlag {
 
	NPF_FLAG_SEEN_SIGNAL,       ///< Used to mark that a signal was seen on the way, for rail only
 
	NPF_FLAG_2ND_SIGNAL,        ///< Used to mark that two signals were seen, rail only
 
	NPF_FLAG_3RD_SIGNAL,        ///< Used to mark that three signals were seen, rail only
 
	NPF_FLAG_REVERSE,           ///< Used to mark that this node was reached from the second start node, if applicable
 
	NPF_FLAG_LAST_SIGNAL_RED,   ///< Used to mark that the last signal on this path was red
 
	NPF_FLAG_LAST_SIGNAL_BLOCK, ///< Used to mark that the last signal on this path was a block signal
 
	NPF_FLAG_IGNORE_START_TILE, ///< Used to mark that the start tile is invalid, and searching should start from the second tile on
 
	NPF_FLAG_TARGET_RESERVED,   ///< Used to mark that the possible reservation target is already reserved
 
	NPF_FLAG_IGNORE_RESERVED,   ///< Used to mark that reserved tiles should be considered impassable
 
};
 

	
 
/* Meant to be stored in AyStar.userpath */
 
/** Meant to be stored in AyStar.userpath */
 
struct NPFFoundTargetData {
 
	uint best_bird_dist;    ///< The best heuristic found. Is 0 if the target was found
 
	uint best_path_dist;    ///< The shortest path. Is UINT_MAX if no path is found
 
	Trackdir best_trackdir; ///< The trackdir that leads to the shortest path/closest birds dist
 
	AyStarNode node;        ///< The node within the target the search led us to
 
	bool res_okay;          ///< True if a path reservation could be made
 
};
 

	
 
static AyStar _npf_aystar;
 

	
 
/* The cost of each trackdir. A diagonal piece is the full NPF_TILE_LENGTH,
 
 * the shorter piece is sqrt(2)/2*NPF_TILE_LENGTH =~ 0.7071
 
 */
 
#define NPF_STRAIGHT_LENGTH (uint)(NPF_TILE_LENGTH * STRAIGHT_TRACK_LENGTH)
 
static const uint _trackdir_length[TRACKDIR_END] = {
 
	NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH,
 
	0, 0,
 
	NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH
 
};
 

	
 
/**
 
 * Returns the current value of the given flag on the given AyStarNode.
 
 */
 
static inline bool NPFGetFlag(const AyStarNode *node, NPFNodeFlag flag)
 
{
 
	return HasBit(node->user_data[NPF_NODE_FLAGS], flag);
 
}
 

	
 
/**
 
 * Sets the given flag on the given AyStarNode to the given value.
 
 */
 
static inline void NPFSetFlag(AyStarNode *node, NPFNodeFlag flag, bool value)
 
{
 
	SB(node->user_data[NPF_NODE_FLAGS], flag, 1, value);
 
}
 

	
 
/**
 
 * Calculates the minimum distance traveled to get from t0 to t1 when only
 
 * using tracks (ie, only making 45 degree turns). Returns the distance in the
 
 * NPF scale, ie the number of full tiles multiplied by NPF_TILE_LENGTH to
 
 * prevent rounding.
 
 */
 
static uint NPFDistanceTrack(TileIndex t0, TileIndex t1)
 
{
 
	const uint dx = Delta(TileX(t0), TileX(t1));
 
	const uint dy = Delta(TileY(t0), TileY(t1));
 

	
 
	const uint straightTracks = 2 * min(dx, dy); // The number of straight (not full length) tracks
src/rail_cmd.cpp
Show inline comments
 
@@ -2084,97 +2084,97 @@ static void DrawTrackBits(TileInfo *ti, 
 
		TrackBits pbs = GetRailReservationTrackBits(ti->tile) & track;
 
		if (pbs & TRACK_BIT_X) {
 
			if (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED) {
 
				DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH);
 
			} else {
 
				DrawGroundSprite(_track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.single_sloped - 20, PALETTE_CRASH);
 
			}
 
		}
 
		if (pbs & TRACK_BIT_Y) {
 
			if (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED) {
 
				DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH);
 
			} else {
 
				DrawGroundSprite(_track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.single_sloped - 20, PALETTE_CRASH);
 
			}
 
		}
 
		if (pbs & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PALETTE_CRASH, NULL, 0, ti->tileh & SLOPE_N ? -TILE_HEIGHT : 0);
 
		if (pbs & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PALETTE_CRASH, NULL, 0, ti->tileh & SLOPE_S ? -TILE_HEIGHT : 0);
 
		if (pbs & TRACK_BIT_LEFT)  DrawGroundSprite(rti->base_sprites.single_w, PALETTE_CRASH, NULL, 0, ti->tileh & SLOPE_W ? -TILE_HEIGHT : 0);
 
		if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PALETTE_CRASH, NULL, 0, ti->tileh & SLOPE_E ? -TILE_HEIGHT : 0);
 
	}
 

	
 
	if (IsValidCorner(halftile_corner)) {
 
		DrawFoundation(ti, HalftileFoundation(halftile_corner));
 

	
 
		/* Draw higher halftile-overlay: Use the sloped sprites with three corners raised. They probably best fit the lightning. */
 
		Slope fake_slope = SlopeWithThreeCornersRaised(OppositeCorner(halftile_corner));
 
		image = _track_sloped_sprites[fake_slope - 1] + rti->base_sprites.track_y;
 
		pal = PAL_NONE;
 
		switch (rgt) {
 
			case RAIL_GROUND_BARREN:     pal = PALETTE_TO_BARE_LAND; break;
 
			case RAIL_GROUND_ICE_DESERT:
 
			case RAIL_GROUND_HALF_SNOW:  image += rti->snow_offset;  break; // higher part has snow in this case too
 
			default: break;
 
		}
 
		DrawGroundSprite(image, pal, &(_halftile_sub_sprite[halftile_corner]));
 

	
 
		if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasReservedTracks(ti->tile, CornerToTrackBits(halftile_corner))) {
 
			static const byte _corner_to_track_sprite[] = {3, 1, 2, 0};
 
			DrawGroundSprite(_corner_to_track_sprite[halftile_corner] + rti->base_sprites.single_n, PALETTE_CRASH, NULL, 0, -TILE_HEIGHT);
 
		}
 
	}
 
}
 

	
 
/** Enums holding the offsets from base signal sprite,
 
 * according to the side it is representing.
 
 * The addtion of 2 per enum is necessary in order to "jump" over the
 
 * green state sprite, all signal sprites being in pair,
 
 * starting with the off-red state */
 
enum {
 
enum SignalOffsets {
 
	SIGNAL_TO_SOUTHWEST =  0,
 
	SIGNAL_TO_NORTHEAST =  2,
 
	SIGNAL_TO_SOUTHEAST =  4,
 
	SIGNAL_TO_NORTHWEST =  6,
 
	SIGNAL_TO_EAST      =  8,
 
	SIGNAL_TO_WEST      = 10,
 
	SIGNAL_TO_SOUTH     = 12,
 
	SIGNAL_TO_NORTH     = 14,
 
};
 

	
 
static void DrawSignals(TileIndex tile, TrackBits rails)
 
{
 
#define MAYBE_DRAW_SIGNAL(x, y, z, t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y, z)
 

	
 
	if (!(rails & TRACK_BIT_Y)) {
 
		if (!(rails & TRACK_BIT_X)) {
 
			if (rails & TRACK_BIT_LEFT) {
 
				MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTH, 0, TRACK_LEFT);
 
				MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTH, 1, TRACK_LEFT);
 
			}
 
			if (rails & TRACK_BIT_RIGHT) {
 
				MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_NORTH, 2, TRACK_RIGHT);
 
				MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_SOUTH, 3, TRACK_RIGHT);
 
			}
 
			if (rails & TRACK_BIT_UPPER) {
 
				MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_WEST, 4, TRACK_UPPER);
 
				MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_EAST, 5, TRACK_UPPER);
 
			}
 
			if (rails & TRACK_BIT_LOWER) {
 
				MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_WEST, 6, TRACK_LOWER);
 
				MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_EAST, 7, TRACK_LOWER);
 
			}
 
		} else {
 
			MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHWEST, 8, TRACK_X);
 
			MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHEAST, 9, TRACK_X);
 
		}
 
	} else {
 
		MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHEAST, 10, TRACK_Y);
 
		MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHWEST, 11, TRACK_Y);
 
	}
 
}
 

	
 
static void DrawTile_Track(TileInfo *ti)
 
{
 
	const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
 

	
 
	_drawtile_track_palette = COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile));
 

	
src/signal.cpp
Show inline comments
 
/* $Id$ */
 

	
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file signal.cpp functions related to rail signals updating */
 

	
 
#include "stdafx.h"
 
#include "debug.h"
 
#include "station_map.h"
 
#include "tunnelbridge_map.h"
 
#include "vehicle_func.h"
 
#include "functions.h"
 
#include "train.h"
 
#include "company_base.h"
 

	
 

	
 
/** these are the maximums used for updating signal blocks */
 
enum {
 
	SIG_TBU_SIZE    =  64, ///< number of signals entering to block
 
	SIG_TBD_SIZE    = 256, ///< number of intersections - open nodes in current block
 
	SIG_GLOB_SIZE   = 128, ///< number of open blocks (block can be opened more times until detected)
 
	SIG_GLOB_UPDATE =  64, ///< how many items need to be in _globset to force update
 
};
 
static const uint SIG_TBU_SIZE    =  64; ///< number of signals entering to block
 
static const uint SIG_TBD_SIZE    = 256; ///< number of intersections - open nodes in current block
 
static const uint SIG_GLOB_SIZE   = 128; ///< number of open blocks (block can be opened more times until detected)
 
static const uint SIG_GLOB_UPDATE =  64; ///< how many items need to be in _globset to force update
 

	
 
assert_compile(SIG_GLOB_UPDATE <= SIG_GLOB_SIZE);
 

	
 
/** incidating trackbits with given enterdir */
 
static const TrackBits _enterdir_to_trackbits[DIAGDIR_END] = {
 
	TRACK_BIT_3WAY_NE,
 
	TRACK_BIT_3WAY_SE,
 
	TRACK_BIT_3WAY_SW,
 
	TRACK_BIT_3WAY_NW
 
};
 

	
 
/** incidating trackdirbits with given enterdir */
 
static const TrackdirBits _enterdir_to_trackdirbits[DIAGDIR_END] = {
 
	TRACKDIR_BIT_X_SW | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_RIGHT_S,
 
	TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_RIGHT_N,
 
	TRACKDIR_BIT_X_NE | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LEFT_N,
 
	TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LEFT_S
 
};
 

	
 
/**
 
 * Set containing 'items' items of 'tile and Tdir'
 
 * No tree structure is used because it would cause
 
 * slowdowns in most usual cases
 
 */
 
template <typename Tdir, uint items>
 
struct SmallSet {
 
private:
 
	uint n;           // actual number of units
 
	bool overflowed;  // did we try to oveflow the set?
 
	const char *name; // name, used for debugging purposes...
 

	
 
	/** Element of set */
 
	struct SSdata {
 
		TileIndex tile;
 
		Tdir dir;
 
	} data[items];
 

	
 
public:
 
	/** Constructor - just set default values and 'name' */
 
	SmallSet(const char *name) : n(0), overflowed(false), name(name) { }
 

	
 
	/** Reset variables to default values */
 
	void Reset()
 
	{
 
		this->n = 0;
 
		this->overflowed = false;
 
	}
 

	
src/statusbar_gui.cpp
Show inline comments
 
@@ -38,102 +38,100 @@ static bool DrawScrollingStatusText(cons
 
	char buf[512];
 
	GetString(buf, str, lastof(buf));
 
	const char *s = buf;
 

	
 
	char buffer[256];
 
	char *d = buffer;
 
	const char *last = lastof(buffer);
 

	
 
	for (;;) {
 
		WChar c = Utf8Consume(&s);
 
		if (c == 0) {
 
			break;
 
		} else if (c == '\n') {
 
			if (d + 4 >= last) break;
 
			d[0] = d[1] = d[2] = d[3] = ' ';
 
			d += 4;
 
		} else if (IsPrintable(c)) {
 
			if (d + Utf8CharLen(c) >= last) break;
 
			d += Utf8Encode(d, c);
 
		}
 
	}
 
	*d = '\0';
 

	
 
	DrawPixelInfo tmp_dpi;
 
	if (!FillDrawPixelInfo(&tmp_dpi, left, top, right - left, bottom)) return true;
 

	
 
	int width = GetStringBoundingBox(buffer).width;
 
	int pos = (_dynlang.text_dir == TD_RTL) ? (scroll_pos - width) : (right - scroll_pos - left);
 

	
 
	DrawPixelInfo *old_dpi = _cur_dpi;
 
	_cur_dpi = &tmp_dpi;
 
	DrawString(pos, INT16_MAX, 0, buffer, TC_LIGHT_BLUE, SA_LEFT | SA_FORCE);
 
	_cur_dpi = old_dpi;
 

	
 
	return (_dynlang.text_dir == TD_RTL) ? (pos < right - left) : (pos + width > 0);
 
}
 

	
 
enum StatusbarWidget {
 
	SBW_LEFT,   ///< left part of the statusbar; date is shown there
 
	SBW_MIDDLE, ///< middle part; current news or company name or *** SAVING *** or *** PAUSED ***
 
	SBW_RIGHT,  ///< right part; bank balance
 
};
 

	
 
struct StatusBarWindow : Window {
 
	bool saving;
 
	int ticker_scroll;
 
	int reminder_timeout;
 

	
 
	enum {
 
		TICKER_STOP    = 1640, ///< scrolling is finished when counter reaches this value
 
		REMINDER_START =   91, ///< initial value of the reminder counter (right dot on the right)
 
		REMINDER_STOP  =    0, ///< reminder disappears when counter reaches this value
 
		COUNTER_STEP   =    2, ///< this is subtracted from active counters every tick
 
	};
 
	static const int TICKER_STOP    = 1640; ///< scrolling is finished when counter reaches this value
 
	static const int REMINDER_START =   91; ///< initial value of the reminder counter (right dot on the right)
 
	static const int REMINDER_STOP  =    0; ///< reminder disappears when counter reaches this value
 
	static const int COUNTER_STEP   =    2; ///< this is subtracted from active counters every tick
 

	
 
	StatusBarWindow(const WindowDesc *desc) : Window()
 
	{
 
		CLRBITS(this->flags4, WF_WHITE_BORDER_MASK);
 
		this->ticker_scroll    =   TICKER_STOP;
 
		this->reminder_timeout = REMINDER_STOP;
 

	
 
		this->InitNested(desc);
 
	}
 

	
 
	virtual Point OnInitialPosition(const WindowDesc *desc, int16 sm_width, int16 sm_height, int window_number)
 
	{
 
		Point pt = { (_screen.width - max(sm_width, desc->default_width)) / 2, _screen.height - sm_height };
 
		return pt;
 
	}
 

	
 
	virtual void OnPaint()
 
	{
 
		this->DrawWidgets();
 
	}
 

	
 
	virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
 
	{
 
		Dimension d;
 
		switch (widget) {
 
			case SBW_LEFT:
 
				SetDParam(0, MAX_YEAR * DAYS_IN_YEAR);
 
				d = GetStringBoundingBox(STR_WHITE_DATE_LONG);
 
				break;
 

	
 
			case SBW_RIGHT: {
 
				int64 max_money = UINT32_MAX;
 
				const Company *c;
 
				FOR_ALL_COMPANIES(c) max_money = max<int64>(c->money, max_money);
 
				SetDParam(0, 100LL * max_money);
 
				d = GetStringBoundingBox(STR_COMPANY_MONEY);
 
			} break;
 

	
 
			default:
 
				return;
 
		}
 

	
 
		d.width += padding.width;
 
		d.height += padding.height;
 
		*size = maxdim(d, *size);
 
	}
 

	
 
	virtual void DrawWidget(const Rect &r, int widget) const
src/toolbar_gui.cpp
Show inline comments
 
@@ -166,101 +166,99 @@ public:
 
	{
 
		return true;
 
	}
 

	
 
	uint Width() const
 
	{
 
		CompanyID company = (CompanyID)this->result;
 
		SetDParam(0, company);
 
		SetDParam(1, company);
 
		return GetStringBoundingBox(STR_COMPANY_NAME_COMPANY_NUM).width + this->icon_width + 3;
 
	}
 

	
 
	void Draw(int left, int right, int top, int bottom, bool sel, int bg_colour) const
 
	{
 
		CompanyID company = (CompanyID)this->result;
 
		bool rtl = _dynlang.text_dir == TD_RTL;
 

	
 
		/* It's possible the company is deleted while the dropdown is open */
 
		if (!Company::IsValidID(company)) return;
 

	
 
		DrawCompanyIcon(company, rtl ? right - this->icon_width - WD_FRAMERECT_RIGHT : left + WD_FRAMERECT_LEFT, top + 1 + (FONT_HEIGHT_NORMAL - 10) / 2);
 

	
 
		SetDParam(0, company);
 
		SetDParam(1, company);
 
		TextColour col;
 
		if (this->greyed) {
 
			col = TC_GREY;
 
		} else {
 
			col = sel ? TC_WHITE : TC_BLACK;
 
		}
 
		DrawString(left + WD_FRAMERECT_LEFT + (rtl ? 0 : 3 + this->icon_width), right - WD_FRAMERECT_RIGHT - (rtl ? 3 + this->icon_width : 0), top, STR_COMPANY_NAME_COMPANY_NUM, col);
 
	}
 
};
 

	
 
/**
 
 * Pop up a generic text only menu.
 
 */
 
static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count)
 
{
 
	DropDownList *list = new DropDownList();
 
	for (int i = 0; i < count; i++) {
 
		list->push_back(new DropDownListStringItem(string + i, i, false));
 
	}
 
	ShowDropDownList(w, list, 0, widget, 140, true, true);
 
	SndPlayFx(SND_15_BEEP);
 
}
 

	
 
/** Enum for the Company Toolbar's network related buttons */
 
enum {
 
	CTMN_CLIENT_LIST = -1, ///< Show the client list
 
	CTMN_NEW_COMPANY = -2, ///< Create a new company
 
	CTMN_SPECTATE    = -3, ///< Become spectator
 
};
 
static const int CTMN_CLIENT_LIST = -1; ///< Show the client list
 
static const int CTMN_NEW_COMPANY = -2; ///< Create a new company
 
static const int CTMN_SPECTATE    = -3; ///< Become spectator
 

	
 
/**
 
 * Pop up a generic company list menu.
 
 */
 
static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0)
 
{
 
	DropDownList *list = new DropDownList();
 

	
 
#ifdef ENABLE_NETWORK
 
	if (widget == TBN_COMPANIES && _networking) {
 
		/* Add the client list button for the companies menu */
 
		list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false));
 

	
 
		if (_local_company == COMPANY_SPECTATOR) {
 
			list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_NEW_COMPANY, CTMN_NEW_COMPANY, NetworkMaxCompaniesReached()));
 
		} else {
 
			list->push_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, NetworkMaxSpectatorsReached()));
 
		}
 
	}
 
#endif /* ENABLE_NETWORK */
 

	
 
	for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
 
		if (!Company::IsValidID(c)) continue;
 
		list->push_back(new DropDownListCompanyItem(c, false, HasBit(grey, c)));
 
	}
 

	
 
	ShowDropDownList(w, list, _local_company == COMPANY_SPECTATOR ? CTMN_CLIENT_LIST : (int)_local_company, widget, 240, true, true);
 
	SndPlayFx(SND_15_BEEP);
 
}
 

	
 

	
 
static ToolbarMode _toolbar_mode;
 

	
 
static void SelectSignTool()
 
{
 
	if (_cursor.sprite == SPR_CURSOR_SIGN) {
 
		ResetObjectToPlace();
 
	} else {
 
		SetObjectToPlace(SPR_CURSOR_SIGN, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0);
 
		_place_proc = PlaceProc_Sign;
 
	}
 
}
 

	
 
/* --- Pausing --- */
 

	
 
static void ToolbarPauseClick(Window *w)
 
{
 
	if (_networking && !_network_server) return; // only server can pause the game
src/train_gui.cpp
Show inline comments
 
@@ -81,100 +81,98 @@ void DrawTrainImage(const Train *v, int 
 

	
 
		if (rtl ? px + width > 0 : px - width < max_width) {
 
			PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
 
			DrawSprite(v->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), 7 + offset.y);
 
		}
 

	
 
		if (!v->IsArticulatedPart()) sel_articulated = false;
 

	
 
		if (v->index == selection) {
 
			/* Set the highlight position */
 
			highlight_l = rtl ? px - width : px;
 
			highlight_r = rtl ? px - 1 : px + width - 1;
 
			sel_articulated = true;
 
		} else if ((_cursor.vehchain && highlight_r != 0) || sel_articulated) {
 
			if (rtl) {
 
				highlight_l -= width;
 
			} else {
 
				highlight_r += width;
 
			}
 
		}
 

	
 
		px += rtl ? -width : width;
 
	}
 

	
 
	if (highlight_l != highlight_r) {
 
		/* Draw the highlight. Now done after drawing all the engines, as
 
		 * the next engine after the highlight could overlap it. */
 
		DrawFrameRect(highlight_l, 0, highlight_r, 13, COLOUR_WHITE, FR_BORDERONLY);
 
	}
 

	
 
	_cur_dpi = old_dpi;
 
}
 

	
 
/** Helper struct for the cargo details information */
 
struct CargoSummaryItem {
 
	CargoID cargo;    ///< The cargo that is carried
 
	StringID subtype; ///< STR_EMPTY if none
 
	uint capacity;    ///< Amount that can be carried
 
	uint amount;      ///< Amount that is carried
 
	StationID source; ///< One of the source stations
 

	
 
	/** Used by CargoSummary::Find() and similiar functions */
 
	FORCEINLINE bool operator != (const CargoSummaryItem &other) const
 
	{
 
		return this->cargo != other.cargo || this->subtype != other.subtype;
 
	}
 
};
 

	
 
enum {
 
	TRAIN_DETAILS_MIN_INDENT = 32, ///< Minimum indent level in the train details window
 
	TRAIN_DETAILS_MAX_INDENT = 72, ///< Maximum indent level in the train details window; wider than this and we start on a new line
 
};
 
static const uint TRAIN_DETAILS_MIN_INDENT = 32; ///< Minimum indent level in the train details window
 
static const uint TRAIN_DETAILS_MAX_INDENT = 72; ///< Maximum indent level in the train details window; wider than this and we start on a new line
 

	
 
/** Container for the cargo summary information. */
 
typedef SmallVector<CargoSummaryItem, 2> CargoSummary;
 
/** Reused container of cargo details */
 
static CargoSummary _cargo_summary;
 

	
 
/**
 
 * Draw the details cargo tab for the given vehicle at the given position
 
 *
 
 * @param item  Data to draw
 
 * @param left  The left most coordinate to draw
 
 * @param right The right most coordinate to draw
 
 * @param y     The y coordinate
 
 */
 
static void TrainDetailsCargoTab(const CargoSummaryItem *item, int left, int right, int y)
 
{
 
	StringID str = STR_VEHICLE_DETAILS_CARGO_EMPTY;
 

	
 
	if (item->amount > 0) {
 
		SetDParam(0, item->cargo);
 
		SetDParam(1, item->amount);
 
		SetDParam(2, item->source);
 
		SetDParam(3, _settings_game.vehicle.freight_trains);
 
		str = FreightWagonMult(item->cargo) > 1 ? STR_VEHICLE_DETAILS_CARGO_FROM_MULT : STR_VEHICLE_DETAILS_CARGO_FROM;
 
	}
 

	
 
	DrawString(left, right, y, str);
 
}
 

	
 
/**
 
 * Draw the details info tab for the given vehicle at the given position
 
 *
 
 * @param v     current vehicle
 
 * @param left  The left most coordinate to draw
 
 * @param right The right most coordinate to draw
 
 * @param y     The y coordinate
 
 */
 
static void TrainDetailsInfoTab(const Vehicle *v, int left, int right, int y)
 
{
 
	if (RailVehInfo(v->engine_type)->railveh_type == RAILVEH_WAGON) {
 
		SetDParam(0, v->engine_type);
 
		SetDParam(1, v->value);
 
		DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE, TC_FROMSTRING, SA_LEFT | SA_STRIP);
 
	} else {
 
		SetDParam(0, v->engine_type);
 
		SetDParam(1, v->build_year);
 
		SetDParam(2, v->value);
 
		DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE, TC_FROMSTRING, SA_LEFT | SA_STRIP);
 
@@ -262,97 +260,97 @@ int GetTrainDetailsWndVScroll(VehicleID 
 
			act_cargo[v->cargo_type] += v->cargo.Count();
 
			max_cargo[v->cargo_type] += v->cargo_cap;
 
		}
 

	
 
		/* Set scroll-amount seperately from counting, as to not compute num double
 
		 * for more carriages of the same type
 
		 */
 
		for (CargoID i = 0; i < NUM_CARGO; i++) {
 
			if (max_cargo[i] > 0) num++; // only count carriages that the train has
 
		}
 
		num++; // needs one more because first line is description string
 
	} else {
 
		for (const Train *v = Train::Get(veh_id); v != NULL; v = v->GetNextVehicle()) {
 
			GetCargoSummaryOfArticulatedVehicle(v, &_cargo_summary);
 
			num += max(1u, _cargo_summary.Length());
 

	
 
			uint length = GetLengthOfArticulatedVehicle(v);
 
			if (length > TRAIN_DETAILS_MAX_INDENT) num++;
 
		}
 
	}
 

	
 
	return num;
 
}
 

	
 
/**
 
 * Draw the details for the given vehicle at the given position
 
 *
 
 * @param v     current vehicle
 
 * @param left  The left most coordinate to draw
 
 * @param right The right most coordinate to draw
 
 * @param y     The y coordinate
 
 * @param vscroll_pos Position of scrollbar
 
 * @param vscroll_cap Number of lines currently displayed
 
 * @param det_tab Selected details tab
 
 */
 
void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab)
 
{
 
	/* draw the first 3 details tabs */
 
	if (det_tab != TDW_TAB_TOTALS) {
 
		bool rtl = _dynlang.text_dir == TD_RTL;
 
		Direction dir = rtl ? DIR_E : DIR_W;
 
		int x = rtl ? right : left;
 
		int sprite_y_offset = 4 + (FONT_HEIGHT_NORMAL - 10) / 2;
 
		int line_height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
 
		for (; v != NULL && vscroll_pos > -vscroll_cap; v = v->GetNextVehicle()) {
 
			GetCargoSummaryOfArticulatedVehicle(v, &_cargo_summary);
 

	
 
			/* Draw sprites */
 
			int dx = 0;
 
			uint dx = 0;
 
			int px = x;
 
			const Train *u = v;
 
			do {
 
				Point offset;
 
				int width = u->GetDisplayImageWidth(&offset);
 
				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
 
					PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
 
					DrawSprite(u->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + offset.y);
 
				}
 
				px += rtl ? -width : width;
 
				dx += width;
 
				u = u->Next();
 
			} while (u != NULL && u->IsArticulatedPart());
 

	
 
			bool separate_sprite_row = (dx > TRAIN_DETAILS_MAX_INDENT);
 
			if (separate_sprite_row) {
 
				vscroll_pos--;
 
				dx = 0;
 
			}
 

	
 
			uint num_lines = max(1u, _cargo_summary.Length());
 
			for (uint i = 0; i < num_lines; i++) {
 
				int sprite_width = max<int>(dx, TRAIN_DETAILS_MIN_INDENT) + 3;
 
				int data_left  = left + (rtl ? 0 : sprite_width);
 
				int data_right = right - (rtl ? sprite_width : 0);
 
				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
 
					int py = y - line_height * vscroll_pos;
 
					if (i > 0 || separate_sprite_row) {
 
						if (vscroll_pos != 0) GfxFillRect(left, py - WD_MATRIX_TOP - 1, right, py - WD_MATRIX_TOP, _colour_gradient[COLOUR_GREY][5]);
 
					}
 
					switch (det_tab) {
 
						case TDW_TAB_CARGO:
 
							if (i < _cargo_summary.Length()) {
 
								TrainDetailsCargoTab(&_cargo_summary[i], data_left, data_right, py);
 
							} else {
 
								DrawString(data_left, data_right, py, STR_QUANTITY_N_A, TC_LIGHT_BLUE);
 
							}
 
							break;
 

	
 
						case TDW_TAB_INFO:
 
							if (i == 0) TrainDetailsInfoTab(v, data_left, data_right, py);
 
							break;
 

	
 
						case TDW_TAB_CAPACITY:
 
							if (i < _cargo_summary.Length()) {
 
								TrainDetailsCapacityTab(&_cargo_summary[i], data_left, data_right, py);
 
							} else {
 
								DrawString(data_left, data_right, py, STR_VEHICLE_INFO_NO_CAPACITY);
src/video/allegro_v.cpp
Show inline comments
 
@@ -273,100 +273,98 @@ static const VkMapping _vk_mapping[] = {
 
	AM(KEY_0_PAD, KEY_9_PAD, '0', '9'),
 
	AS(KEY_SLASH_PAD,   WKC_NUM_DIV),
 
	AS(KEY_ASTERISK,    WKC_NUM_MUL),
 
	AS(KEY_MINUS_PAD,   WKC_NUM_MINUS),
 
	AS(KEY_PLUS_PAD,    WKC_NUM_PLUS),
 
	AS(KEY_ENTER_PAD,   WKC_NUM_ENTER),
 
	AS(KEY_DEL_PAD,     WKC_DELETE),
 

	
 
	/* Other non-letter keys */
 
	AS(KEY_SLASH,        WKC_SLASH),
 
	AS(KEY_SEMICOLON,    WKC_SEMICOLON),
 
	AS(KEY_EQUALS,       WKC_EQUALS),
 
	AS(KEY_OPENBRACE,    WKC_L_BRACKET),
 
	AS(KEY_BACKSLASH,    WKC_BACKSLASH),
 
	AS(KEY_CLOSEBRACE,   WKC_R_BRACKET),
 

	
 
	AS(KEY_QUOTE,   WKC_SINGLEQUOTE),
 
	AS(KEY_COMMA,   WKC_COMMA),
 
	AS(KEY_MINUS,   WKC_MINUS),
 
	AS(KEY_STOP,    WKC_PERIOD),
 
	AS(KEY_TILDE,   WKC_BACKQUOTE),
 
};
 

	
 
static uint32 ConvertAllegroKeyIntoMy()
 
{
 
	int scancode;
 
	int unicode = ureadkey(&scancode);
 

	
 
	const VkMapping *map;
 
	uint key = 0;
 

	
 
	for (map = _vk_mapping; map != endof(_vk_mapping); ++map) {
 
		if ((uint)(scancode - map->vk_from) <= map->vk_count) {
 
			key = scancode - map->vk_from + map->map_to;
 
			break;
 
		}
 
	}
 

	
 
	if (key_shifts & KB_SHIFT_FLAG) key |= WKC_SHIFT;
 
	if (key_shifts & KB_CTRL_FLAG)  key |= WKC_CTRL;
 
	if (key_shifts & KB_ALT_FLAG)   key |= WKC_ALT;
 
#if 0
 
	DEBUG(driver, 0, "Scancode character pressed %u", scancode);
 
	DEBUG(driver, 0, "Unicode character pressed %u", unicode);
 
#endif
 
	return (key << 16) + unicode;
 
}
 

	
 
enum {
 
	LEFT_BUTTON,
 
	RIGHT_BUTTON,
 
};
 
static const uint LEFT_BUTTON  = 0;
 
static const uint RIGHT_BUTTON = 1;
 

	
 
static void PollEvent()
 
{
 
	poll_mouse();
 

	
 
	bool mouse_action = false;
 

	
 
	/* Mouse buttons */
 
	static int prev_button_state;
 
	if (prev_button_state != mouse_b) {
 
		uint diff = prev_button_state ^ mouse_b;
 
		while (diff != 0) {
 
			int button = FindFirstBit(diff);
 
			ClrBit(diff, button);
 
			if (HasBit(mouse_b, button)) {
 
				/* Pressed mouse button */
 
				if (_rightclick_emulate && (key_shifts & KB_CTRL_FLAG)) {
 
					button = RIGHT_BUTTON;
 
					ClrBit(diff, RIGHT_BUTTON);
 
				}
 
				switch (button) {
 
					case LEFT_BUTTON:
 
						_left_button_down = true;
 
						break;
 

	
 
					case RIGHT_BUTTON:
 
						_right_button_down = true;
 
						_right_button_clicked = true;
 
						break;
 

	
 
					default:
 
						/* ignore rest */
 
						break;
 
				}
 
			} else {
 
				/* Released mouse button */
 
				if (_rightclick_emulate) {
 
					_right_button_down = false;
 
					_left_button_down = false;
 
					_left_button_clicked = false;
 
				} else if (button == LEFT_BUTTON) {
 
					_left_button_down = false;
 
					_left_button_clicked = false;
 
				} else if (button == RIGHT_BUTTON) {
 
					_right_button_down = false;
 
				}
 
			}
 
		}
src/video/cocoa/event.mm
Show inline comments
 
@@ -4,97 +4,97 @@
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/******************************************************************************
 
 *                             Cocoa video driver                             *
 
 * Known things left to do:                                                   *
 
 *  Nothing at the moment.                                                    *
 
 ******************************************************************************/
 

	
 
#ifdef WITH_COCOA
 

	
 
#include "../../stdafx.h"
 

	
 
#define Rect  OTTDRect
 
#define Point OTTDPoint
 
#import <Cocoa/Cocoa.h>
 
#undef Rect
 
#undef Point
 

	
 
#include "../../openttd.h"
 
#include "../../debug.h"
 
#include "../../os/macosx/splash.h"
 
#include "../../variables.h"
 
#include "../../settings_type.h"
 
#include "../../core/geometry_type.hpp"
 
#include "cocoa_v.h"
 
#include "cocoa_keys.h"
 
#include "../../blitter/factory.hpp"
 
#include "../../gfx_func.h"
 
#include "../../network/network.h"
 
#include "../../core/random_func.hpp"
 
#include "../../texteff.hpp"
 

	
 
#import <sys/time.h> /* gettimeofday */
 

	
 
/**
 
 * Important notice regarding all modifications!!!!!!!
 
 * There are certain limitations because the file is objective C++.
 
 * gdb has limitations.
 
 * C++ and objective C code can't be joined in all cases (classes stuff).
 
 * Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information.
 
 */
 

	
 

	
 
/* Right Mouse Button Emulation enum */
 
enum {
 
enum RightMouseButtonEmulationState {
 
	RMBE_COMMAND,
 
	RMBE_CONTROL,
 
	RMBE_OFF,
 
};
 

	
 

	
 
static bool _show_mouse = true;
 
static unsigned int _current_mods;
 
static bool _tab_is_down;
 
static bool _emulating_right_button;
 
#ifdef _DEBUG
 
static uint32 _tEvent;
 
#endif
 

	
 

	
 
static uint32 GetTick()
 
{
 
	struct timeval tim;
 

	
 
	gettimeofday(&tim, NULL);
 
	return tim.tv_usec / 1000 + tim.tv_sec * 1000;
 
}
 

	
 

	
 
void QZ_ShowMouse()
 
{
 
	if (!_show_mouse) {
 
		[ NSCursor unhide ];
 
		_show_mouse = true;
 

	
 
		/* Hide the openttd cursor when leaving the window */
 
		if (_cocoa_subdriver != NULL) UndrawMouseCursor();
 
		_cursor.in_window = false;
 
	}
 
}
 

	
 
void QZ_HideMouse()
 
{
 
	if (_show_mouse) {
 
		/* Don't hide the cursor when compiling in debug mode.
 
		 * Note: Not hiding the cursor will cause artefacts around it in 8bpp fullscreen mode. */
 
#ifndef _DEBUG
 
		[ NSCursor hide ];
 
#endif
 
		_show_mouse = false;
 

	
 
		/* Show the openttd cursor again */
 
		_cursor.in_window = true;
0 comments (0 inline, 0 general)