Example #1
0
/**
 * Create a new GRFError that is a deep copy of an existing error message.
 * @param error The GRFError object to make a copy of.
 */
GRFError::GRFError(const GRFError &error) :
	ZeroedMemoryAllocator(),
	custom_message(error.custom_message),
	data(error.data),
	message(error.message),
	severity(error.severity)
{
	if (error.custom_message != NULL) this->custom_message = stredup(error.custom_message);
	if (error.data           != NULL) this->data           = stredup(error.data);
	memcpy(this->param_value, error.param_value, sizeof(this->param_value));
}
Example #2
0
void DetermineBasePaths(const char *exe)
{
	char tmp[MAX_PATH];
	TCHAR path[MAX_PATH];
#ifdef WITH_PERSONAL_DIR
	if (SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, path))) {
		strecpy(tmp, FS2OTTD(path), lastof(tmp));
		AppendPathSeparator(tmp, lastof(tmp));
		strecat(tmp, PERSONAL_DIR, lastof(tmp));
		AppendPathSeparator(tmp, lastof(tmp));
		_searchpaths[SP_PERSONAL_DIR] = stredup(tmp);
	} else {
		_searchpaths[SP_PERSONAL_DIR] = NULL;
	}

	if (SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path))) {
		strecpy(tmp, FS2OTTD(path), lastof(tmp));
		AppendPathSeparator(tmp, lastof(tmp));
		strecat(tmp, PERSONAL_DIR, lastof(tmp));
		AppendPathSeparator(tmp, lastof(tmp));
		_searchpaths[SP_SHARED_DIR] = stredup(tmp);
	} else {
		_searchpaths[SP_SHARED_DIR] = NULL;
	}
#else
	_searchpaths[SP_PERSONAL_DIR] = NULL;
	_searchpaths[SP_SHARED_DIR]   = NULL;
#endif

	/* Get the path to working directory of OpenTTD */
	getcwd(tmp, lengthof(tmp));
	AppendPathSeparator(tmp, lastof(tmp));
	_searchpaths[SP_WORKING_DIR] = stredup(tmp);

	if (!GetModuleFileName(NULL, path, lengthof(path))) {
		DEBUG(misc, 0, "GetModuleFileName failed (%lu)\n", GetLastError());
		_searchpaths[SP_BINARY_DIR] = NULL;
	} else {
		TCHAR exec_dir[MAX_PATH];
		_tcsncpy(path, convert_to_fs(exe, path, lengthof(path)), lengthof(path));
		if (!GetFullPathName(path, lengthof(exec_dir), exec_dir, NULL)) {
			DEBUG(misc, 0, "GetFullPathName failed (%lu)\n", GetLastError());
			_searchpaths[SP_BINARY_DIR] = NULL;
		} else {
			strecpy(tmp, convert_from_fs(exec_dir, tmp, lengthof(tmp)), lastof(tmp));
			char *s = strrchr(tmp, PATHSEPCHAR);
			*(s + 1) = '\0';
			_searchpaths[SP_BINARY_DIR] = stredup(tmp);
		}
	}

	_searchpaths[SP_INSTALLATION_DIR]       = NULL;
	_searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL;
}
Example #3
0
	/**
	 * Construct the blitter, and register it.
	 * @param name        The name of the blitter.
	 * @param description A longer description for the blitter.
	 * @param usable      Whether the blitter is usable (on the current computer). For example for disabling SSE blitters when the CPU can't handle them.
	 * @pre name != nullptr.
	 * @pre description != nullptr.
	 * @pre There is no blitter registered with this name.
	 */
	BlitterFactory(const char *name, const char *description, bool usable = true) :
			name(stredup(name)), description(stredup(description))
	{
		if (usable) {
			/*
			 * Only add when the blitter is usable. Do not bail out or
			 * do more special things since the blitters are always
			 * instantiated upon start anyhow and freed upon shutdown.
			 */
			std::pair<Blitters::iterator, bool> P = GetBlitters().insert(Blitters::value_type(this->name, this));
			assert(P.second);
		} else {
			DEBUG(driver, 1, "Not registering blitter %s as it is not usable", name);
		}
	}
Example #4
0
/**
 * Change the name of the president.
 * @param tile unused
 * @param flags operation to perform
 * @param p1 unused
 * @param p2 unused
 * @param text the new name or an empty string when resetting to the default
 * @return the cost of this operation or an error
 */
CommandCost CmdRenamePresident(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	bool reset = StrEmpty(text);

	if (!reset) {
		if (Utf8StringLength(text) >= MAX_LENGTH_PRESIDENT_NAME_CHARS) return CMD_ERROR;
		if (!IsUniquePresidentName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
	}

	if (flags & DC_EXEC) {
		Company *c = Company::Get(_current_company);
		free(c->president_name);

		if (reset) {
			c->president_name = NULL;
		} else {
			c->president_name = stredup(text);

			if (c->name_1 == STR_SV_UNNAMED && c->name == NULL) {
				char buf[80];

				seprintf(buf, lastof(buf), "%s Transport", text);
				DoCommand(0, 0, 0, DC_EXEC, CMD_RENAME_COMPANY, buf);
			}
		}

		MarkWholeScreenDirty();
		CompanyAdminUpdate(c);
	}

	return CommandCost();
}
Example #5
0
	OskWindow(WindowDesc *desc, Window *parent, int button) : Window(desc)
	{
		this->parent = parent;
		assert(parent != NULL);

		NWidgetCore *par_wid = parent->GetWidget<NWidgetCore>(button);
		assert(par_wid != NULL);

		assert(parent->querystrings.Contains(button));
		this->qs         = parent->querystrings.Find(button)->second;
		this->caption = (par_wid->widget_data != STR_NULL) ? par_wid->widget_data : this->qs->caption;
		this->text_btn   = button;
		this->text       = &this->qs->text;
		this->querystrings[WID_OSK_TEXT] = this->qs;

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

		this->InitNested(0);
		this->SetFocusedWidget(WID_OSK_TEXT);

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

		this->UpdateOskState();
	}
Example #6
0
/**
 * Construct a new in-memory group of an Ini file.
 * @param parent the file we belong to
 * @param name   the name of the group
 * @param last   the last element of the name of the group
 */
IniGroup::IniGroup(IniLoadFile *parent, const char *name, const char *last) : next(nullptr), type(IGT_VARIABLES), item(nullptr), comment(nullptr)
{
	this->name = stredup(name, last);
	str_validate(this->name, this->name + strlen(this->name));

	this->last_item = &this->item;
	*parent->last_group = this;
	parent->last_group = &this->next;

	if (parent->list_group_names != nullptr) {
		for (uint i = 0; parent->list_group_names[i] != nullptr; i++) {
			if (strcmp(this->name, parent->list_group_names[i]) == 0) {
				this->type = IGT_LIST;
				return;
			}
		}
	}
	if (parent->seq_group_names != nullptr) {
		for (uint i = 0; parent->seq_group_names[i] != nullptr; i++) {
			if (strcmp(this->name, parent->seq_group_names[i]) == 0) {
				this->type = IGT_SEQUENCE;
				return;
			}
		}
	}
}
Example #7
0
/**
 * Marks subsidy as awarded, creates news and AI event
 * @param company awarded company
 */
void Subsidy::AwardTo(CompanyID company)
{
	assert(!this->IsAwarded());

	this->awarded = company;
	this->remaining = SUBSIDY_CONTRACT_MONTHS;

	char company_name[MAX_LENGTH_COMPANY_NAME_CHARS * MAX_CHAR_LENGTH];
	SetDParam(0, company);
	GetString(company_name, STR_COMPANY_NAME, lastof(company_name));

	char *cn = stredup(company_name);

	/* Add a news item */
	Pair reftype = SetupSubsidyDecodeParam(this, false);
	InjectDParam(1);

	SetDParamStr(0, cn);
	AddNewsItem(
		STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF + _settings_game.difficulty.subsidy_multiplier,
		NT_SUBSIDIES, NF_NORMAL,
		(NewsReferenceType)reftype.a, this->src, (NewsReferenceType)reftype.b, this->dst,
		cn
	);
	AI::BroadcastNewEvent(new ScriptEventSubsidyAwarded(this->index));
	Game::NewEvent(new ScriptEventSubsidyAwarded(this->index));

	InvalidateWindowData(WC_SUBSIDIES_LIST, 0);
}
Example #8
0
/**
 * Rename a sign. If the new name of the sign is empty, we assume
 * the user wanted to delete it. So delete it. Ownership of signs
 * has no meaning/effect whatsoever except for eyecandy
 * @param tile unused
 * @param flags type of operation
 * @param p1 index of the sign to be renamed/removed
 * @param p2 unused
 * @param text the new name or an empty string when resetting to the default
 * @return the cost of this operation or an error
 */
CommandCost CmdRenameSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	Sign *si = Sign::GetIfValid(p1);
	if (si == NULL) return CMD_ERROR;
	if (si->owner == OWNER_DEITY && _current_company != OWNER_DEITY && _game_mode != GM_EDITOR) return CMD_ERROR;

	/* Rename the signs when empty, otherwise remove it */
	if (!StrEmpty(text)) {
		if (Utf8StringLength(text) >= MAX_LENGTH_SIGN_NAME_CHARS) return CMD_ERROR;

		if (flags & DC_EXEC) {
			/* Delete the old name */
			free(si->name);
			/* Assign the new one */
			si->name = stredup(text);
			if (_game_mode != GM_EDITOR) si->owner = _current_company;

			si->UpdateVirtCoord();
			InvalidateWindowData(WC_SIGN_LIST, 0, 1);
		}
	} else { // Delete sign
		if (flags & DC_EXEC) {
			si->sign.MarkDirty();
			delete si;

			InvalidateWindowData(WC_SIGN_LIST, 0, 0);
		}
	}

	return CommandCost();
}
Example #9
0
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	int argc;
	char *argv[64]; // max 64 command line arguments

	CrashLog::InitialiseCrashLog();

#if defined(UNICODE)
	/* Check if a win9x user started the win32 version */
	if (HasBit(GetVersion(), 31)) usererror("This version of OpenTTD doesn't run on windows 95/98/ME.\nPlease download the win9x binary and try again.");
#endif

	/* Convert the command line to UTF-8. We need a dedicated buffer
	 * for this because argv[] points into this buffer and this needs to
	 * be available between subsequent calls to FS2OTTD(). */
	char *cmdline = stredup(FS2OTTD(GetCommandLine()));

#if defined(_DEBUG)
	CreateConsole();
#endif

	_set_error_mode(_OUT_TO_MSGBOX); // force assertion output to messagebox

	/* setup random seed to something quite random */
	SetRandomSeed(GetTickCount());

	argc = ParseCommandLine(cmdline, argv, lengthof(argv));

	/* Make sure our arguments contain only valid UTF-8 characters. */
	for (int i = 0; i < argc; i++) ValidateString(argv[i]);

	openttd_main(argc, argv);
	free(cmdline);
	return 0;
}
Example #10
0
/**
 * Change the configured music set and reset playback
 * @param index Index of music set to switch to
 */
void ChangeMusicSet(int index)
{
	if (BaseMusic::GetIndexOfUsedSet() == index) return;

	/* Resume playback after switching?
	 * Always if music is already playing, and also if the user is switching
	 * away from an empty music set.
	 * If the user switches away from an empty set, assume it's because they
	 * want to hear music now. */
	bool shouldplay = _song_is_active || (BaseMusic::GetUsedSet()->num_available == 0);
	StopMusic();

	const char *name = BaseMusic::GetSet(index)->name;
	BaseMusic::SetSet(name);
	free(BaseMusic::ini_set);
	BaseMusic::ini_set = stredup(name);

	InitializeMusic();
	ResetPlaylist();
	_settings_client.music.playing = shouldplay;

	InvalidateWindowData(WC_MUSIC_TRACK_SELECTION, 0);
	InvalidateWindowData(WC_MUSIC_WINDOW, 0);
	InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_GAME_OPTIONS, 0, true);
}
Example #11
0
/**
 * Copy data from temporary engine array into the real engine pool.
 */
void CopyTempEngineData()
{
    Engine *e;
    FOR_ALL_ENGINES(e) {
        if (e->index >= _temp_engine.size()) break;

        const Engine *se = GetTempDataEngine(e->index);
        e->intro_date          = se->intro_date;
        e->age                 = se->age;
        e->reliability         = se->reliability;
        e->reliability_spd_dec = se->reliability_spd_dec;
        e->reliability_start   = se->reliability_start;
        e->reliability_max     = se->reliability_max;
        e->reliability_final   = se->reliability_final;
        e->duration_phase_1    = se->duration_phase_1;
        e->duration_phase_2    = se->duration_phase_2;
        e->duration_phase_3    = se->duration_phase_3;
        e->flags               = se->flags;
        e->preview_asked       = se->preview_asked;
        e->preview_company     = se->preview_company;
        e->preview_wait        = se->preview_wait;
        e->company_avail       = se->company_avail;
        e->company_hidden      = se->company_hidden;
        if (se->name != NULL) e->name = stredup(se->name);
    }

    /* Get rid of temporary data */
    _temp_engine.clear();
}
Example #12
0
/**
 * Create a new GRFConfig that is a deep copy of an existing config.
 * @param config The GRFConfig object to make a copy of.
 */
GRFConfig::GRFConfig(const GRFConfig &config) :
	ZeroedMemoryAllocator(),
	ident(config.ident),
	name(config.name),
	info(config.info),
	url(config.url),
	version(config.version),
	min_loadable_version(config.min_loadable_version),
	flags(config.flags & ~(1 << GCF_COPY)),
	status(config.status),
	grf_bugs(config.grf_bugs),
	num_params(config.num_params),
	num_valid_params(config.num_valid_params),
	palette(config.palette),
	has_param_defaults(config.has_param_defaults)
{
	MemCpyT<uint8>(this->original_md5sum, config.original_md5sum, lengthof(this->original_md5sum));
	MemCpyT<uint32>(this->param, config.param, lengthof(this->param));
	if (config.filename != NULL) this->filename = stredup(config.filename);
	this->name->AddRef();
	this->info->AddRef();
	this->url->AddRef();
	if (config.error != NULL) this->error = new GRFError(*config.error);
	for (uint i = 0; i < config.param_info.Length(); i++) {
		if (config.param_info[i] == NULL) {
			*this->param_info.Append() = NULL;
		} else {
			*this->param_info.Append() = new GRFParameterInfo(*config.param_info[i]);
		}
	}
}
Example #13
0
/**
 * Rename a waypoint.
 * @param tile unused
 * @param flags type of operation
 * @param p1 id of waypoint
 * @param p2 unused
 * @param text the new name or an empty string when resetting to the default
 * @return the cost of this operation or an error
 */
CommandCost CmdRenameWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	Waypoint *wp = Waypoint::GetIfValid(p1);
	if (wp == NULL) return CMD_ERROR;

	if (wp->owner != OWNER_NONE) {
		CommandCost ret = CheckOwnership(wp->owner);
		if (ret.Failed()) return ret;
	}

	bool reset = StrEmpty(text);

	if (!reset) {
		if (Utf8StringLength(text) >= MAX_LENGTH_STATION_NAME_CHARS) return CMD_ERROR;
		if (!IsUniqueWaypointName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
	}

	if (flags & DC_EXEC) {
		free(wp->name);
		wp->name = reset ? NULL : stredup(text);

		wp->UpdateVirtCoord();
	}
	return CommandCost();
}
Example #14
0
/**
 * Place a sign at the given coordinates. Ownership of sign has
 * no effect whatsoever except for the colour the sign gets for easy recognition,
 * but everybody is able to rename/remove it.
 * @param tile tile to place sign at
 * @param flags type of operation
 * @param p1 unused
 * @param p2 unused
 * @param text unused
 * @return the cost of this operation or an error
 */
CommandCost CmdPlaceSign(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	/* Try to locate a new sign */
	if (!Sign::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_SIGNS);

	/* Check sign text length if any */
	if (!StrEmpty(text) && Utf8StringLength(text) >= MAX_LENGTH_SIGN_NAME_CHARS) return CMD_ERROR;

	/* When we execute, really make the sign */
	if (flags & DC_EXEC) {
		Sign *si = new Sign(_game_mode == GM_EDITOR ? OWNER_DEITY : _current_company);
		int x = TileX(tile) * TILE_SIZE;
		int y = TileY(tile) * TILE_SIZE;

		si->x = x;
		si->y = y;
		si->z = GetSlopePixelZ(x, y);
		if (!StrEmpty(text)) {
			si->name = stredup(text);
		}
		si->UpdateVirtCoord();
		InvalidateWindowData(WC_SIGN_LIST, 0, 0);
		_new_sign_id = si->index;
	}

	return CommandCost();
}
Example #15
0
/**
 * Register a an alias for an already existing command in the console
 * @param name name of the alias that will be used
 * @param cmd name of the command that 'name' will be alias of
 */
void IConsoleAliasRegister(const char *name, const char *cmd)
{
	if (IConsoleAliasGet(name) != NULL) {
		IConsoleError("an alias with this name already exists; insertion aborted");
		return;
	}

	char *new_alias = RemoveUnderscores(stredup(name));
	char *cmd_aliased = stredup(cmd);
	IConsoleAlias *item_new = MallocT<IConsoleAlias>(1);

	item_new->next = NULL;
	item_new->cmdline = cmd_aliased;
	item_new->name = new_alias;

	IConsoleAddSorted(&_iconsole_aliases, item_new);
}
Example #16
0
/**
 * Construct a new in-memory item of an Ini file.
 * @param parent the group we belong to
 * @param name   the name of the item
 * @param last   the last element of the name of the item
 */
IniItem::IniItem(IniGroup *parent, const char *name, const char *last) : next(nullptr), value(nullptr), comment(nullptr)
{
	this->name = stredup(name, last);
	str_validate(this->name, this->name + strlen(this->name));

	*parent->last_item = this;
	parent->last_item = &this->next;
}
Example #17
0
bool Squirrel::CallStringMethodStrdup(HSQOBJECT instance, const char *method_name, const char **res, int suspend)
{
	HSQOBJECT ret;
	if (!this->CallMethod(instance, method_name, &ret, suspend)) return false;
	if (ret._type != OT_STRING) return false;
	*res = stredup(ObjectToString(&ret));
	ValidateString(*res);
	return true;
}
Example #18
0
void AIScannerInfo::Initialize()
{
	ScriptScanner::Initialize("AIScanner");

	/* Create the dummy AI */
	free(this->main_script);
	this->main_script = stredup("%_dummy");
	extern void Script_CreateDummyInfo(HSQUIRRELVM vm, const char *type, const char *dir);
	Script_CreateDummyInfo(this->engine->GetVM(), "AI", "ai");
}
Example #19
0
/**
 * Updates the original text of the OSK so when the 'parent' changes the
 * original and you press on cancel you won't get the 'old' original text
 * but the updated one.
 * @param parent window that just updated its orignal text
 * @param button widget number of parent's textbox to update
 */
void UpdateOSKOriginalText(const Window *parent, int button)
{
	OskWindow *osk = dynamic_cast<OskWindow *>(FindWindowById(WC_OSK, 0));
	if (osk == NULL || osk->parent != parent || osk->text_btn != button) return;

	free(osk->orig_str_buf);
	osk->orig_str_buf = stredup(osk->qs->text.buf);

	osk->SetDirty();
}
Example #20
0
/**
 * Copy and convert old custom names to UTF-8.
 * They were all stored in a 512 by 32 (200 by 24 for TTO) long string array
 * and are now stored with stations, waypoints and other places with names.
 * @param id the StringID of the custom name to clone.
 * @return the clones custom name.
 */
char *CopyFromOldName(StringID id)
{
	/* Is this name an (old) custom name? */
	if (GetStringTab(id) != TEXT_TAB_OLD_CUSTOM) return NULL;

	if (IsSavegameVersionBefore(SLV_37)) {
		/* Allow for expansion when converted to UTF-8. */
		char tmp[LEN_OLD_STRINGS * MAX_CHAR_LENGTH];
		uint offs = _savegame_type == SGT_TTO ? LEN_OLD_STRINGS_TTO * GB(id, 0, 8) : LEN_OLD_STRINGS * GB(id, 0, 9);
		const char *strfrom = &_old_name_array[offs];
		char *strto = tmp;

		for (; *strfrom != '\0'; strfrom++) {
			WChar c = (byte)*strfrom;

			/* Map from non-ISO8859-15 characters to UTF-8. */
			switch (c) {
				case 0xA4: c = 0x20AC; break; // Euro
				case 0xA6: c = 0x0160; break; // S with caron
				case 0xA8: c = 0x0161; break; // s with caron
				case 0xB4: c = 0x017D; break; // Z with caron
				case 0xB8: c = 0x017E; break; // z with caron
				case 0xBC: c = 0x0152; break; // OE ligature
				case 0xBD: c = 0x0153; break; // oe ligature
				case 0xBE: c = 0x0178; break; // Y with diaresis
				default: break;
			}

			/* Check character will fit into our buffer. */
			if (strto + Utf8CharLen(c) > lastof(tmp)) break;

			strto += Utf8Encode(strto, c);
		}

		/* Terminate the new string and copy it back to the name array */
		*strto = '\0';

		return stredup(tmp);
	} else {
		/* Name will already be in UTF-8. */
		return stredup(&_old_name_array[LEN_OLD_STRINGS * GB(id, 0, 9)]);
	}
}
Example #21
0
/**
 * Copy the given data into our instance.
 * @param data The data to copy.
 */
ErrorMessageData::ErrorMessageData(const ErrorMessageData &data)
{
	*this = data;
	for (size_t i = 0; i < lengthof(this->strings); i++) {
		if (this->strings[i] != NULL) {
			this->strings[i] = stredup(this->strings[i]);
			this->decode_params[i] = (size_t)this->strings[i];
		}
	}
}
Example #22
0
/**
 * Register a new command to be used in the console
 * @param name name of the command that will be used
 * @param proc function that will be called upon execution of command
 */
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc, IConsoleHook *hook)
{
	IConsoleCmd *item_new = MallocT<IConsoleCmd>(1);
	item_new->name = RemoveUnderscores(stredup(name));
	item_new->next = NULL;
	item_new->proc = proc;
	item_new->hook = hook;

	IConsoleAddSorted(&_iconsole_cmds, item_new);
}
Example #23
0
/**
 * Create a new GRFConfig.
 * @param filename Set the filename of this GRFConfig to filename. The argument
 *   is copied so the original string isn't needed after the constructor.
 */
GRFConfig::GRFConfig(const char *filename) :
	name(new GRFTextWrapper()),
	info(new GRFTextWrapper()),
	url(new GRFTextWrapper()),
	num_valid_params(lengthof(param))
{
	if (filename != NULL) this->filename = stredup(filename);
	this->name->AddRef();
	this->info->AddRef();
	this->url->AddRef();
}
Example #24
0
/**
 * Change to named music set, and reset playback.
 * @param set_name Name of music set to select
 */
void MusicSystem::ChangeMusicSet(const char *set_name)
{
	BaseMusic::SetSet(set_name);

	free(BaseMusic::ini_set);
	BaseMusic::ini_set = stredup(set_name);

	this->BuildPlaylists();
	this->ChangePlaylist(this->selected_playlist);

	InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_GAME_OPTIONS, 0, true);
}
Example #25
0
	/**
	 * Construct the blitter, and register it.
	 * @param name        The name of the blitter.
	 * @param description A longer description for the blitter.
	 * @param usable      Whether the blitter is usable (on the current computer). For example for disabling SSE blitters when the CPU can't handle them.
	 * @pre name != NULL.
	 * @pre description != NULL.
	 * @pre There is no blitter registered with this name.
	 */
	BlitterFactory(const char *name, const char *description, bool usable = true) :
			name(stredup(name)), description(stredup(description))
	{   //stredup,相当于malloc&copystr
		/*strdup()函数是c语言中常用的一种字符串拷贝库函数,一般和free()函数成对出现。
		*/
	
		if (usable) {
			/*
			 * Only add when the blitter is usable. Do not bail out or
			 * do more special things since the blitters are always
			 * instantiated upon start anyhow and freed upon shutdown.
			 */
			/*std::map的insert函数,返回结果有两个,iterator和bool,其中iterator应该是当前插入的对象的访问迭代器.
			  bool,表示这一次插入是否成功.
			*/
			std::pair<Blitters::iterator, bool> P = GetBlitters().insert(Blitters::value_type(this->name, this));
			assert(P.second);
		} else {
			DEBUG(driver, 1, "Not registering blitter %s as it is not usable", name);
		}
	}
Example #26
0
/**
 * Read all the raw language strings from the given file.
 * @param file The file to read from.
 * @return The raw strings, or NULL upon error.
 */
LanguageStrings *ReadRawLanguageStrings(const char *file)
{
	LanguageStrings *ret = NULL;
	FILE *fh = NULL;
	try {
		size_t to_read;
		fh = FioFOpenFile(file, "rb", GAME_DIR, &to_read);
		if (fh == NULL) {
			return NULL;
		}

		const char *langname = strrchr(file, PATHSEPCHAR);
		if (langname == NULL) {
			langname = file;
		} else {
			langname++;
		}

		/* Check for invalid empty filename */
		if (*langname == '.' || *langname == 0) {
			fclose(fh);
			return NULL;
		}

		ret = new LanguageStrings(langname, strchr(langname, '.'));

		char buffer[2048];
		while (to_read != 0 && fgets(buffer, sizeof(buffer), fh) != NULL) {
			size_t len = strlen(buffer);

			/* Remove trailing spaces/newlines from the string. */
			size_t i = len;
			while (i > 0 && (buffer[i - 1] == '\r' || buffer[i - 1] == '\n' || buffer[i - 1] == ' ')) i--;
			buffer[i] = '\0';

			*ret->lines.Append() = stredup(buffer, buffer + to_read - 1);

			if (len > to_read) {
				to_read = 0;
			} else {
				to_read -= len;
			}
		}

		fclose(fh);
		return ret;
	} catch (...) {
		if (fh != NULL) fclose(fh);
		delete ret;
		return NULL;
	}
}
Example #27
0
/**
 * Create a new custom news item.
 * @param tile unused
 * @param flags type of operation
 * @param p1 various bitstuffed elements
 * - p1 = (bit  0 -  7) - NewsType of the message.
 * - p1 = (bit  8 - 15) - NewsReferenceType of first reference.
 * - p1 = (bit 16 - 23) - Company this news message is for.
 * @param p2 First reference of the news message.
 * @param text The text of the news message.
 * @return the cost of this operation or an error
 */
CommandCost CmdCustomNewsItem(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
	if (_current_company != OWNER_DEITY) return CMD_ERROR;

	NewsType type = (NewsType)GB(p1, 0, 8);
	NewsReferenceType reftype1 = (NewsReferenceType)GB(p1, 8, 8);
	CompanyID company = (CompanyID)GB(p1, 16, 8);

	if (company != INVALID_OWNER && !Company::IsValidID(company)) return CMD_ERROR;
	if (type >= NT_END) return CMD_ERROR;
	if (StrEmpty(text)) return CMD_ERROR;

	switch (reftype1) {
		case NR_NONE: break;
		case NR_TILE:
			if (!IsValidTile(p2)) return CMD_ERROR;
			break;

		case NR_VEHICLE:
			if (!Vehicle::IsValidID(p2)) return CMD_ERROR;
			break;

		case NR_STATION:
			if (!Station::IsValidID(p2)) return CMD_ERROR;
			break;

		case NR_INDUSTRY:
			if (!Industry::IsValidID(p2)) return CMD_ERROR;
			break;

		case NR_TOWN:
			if (!Town::IsValidID(p2)) return CMD_ERROR;
			break;

		case NR_ENGINE:
			if (!Engine::IsValidID(p2)) return CMD_ERROR;
			break;

		default: return CMD_ERROR;
	}

	if (company != INVALID_OWNER && company != _local_company) return CommandCost();

	if (flags & DC_EXEC) {
		char *news = stredup(text);
		SetDParamStr(0, news);
		AddNewsItem(STR_NEWS_CUSTOM_ITEM, type, NF_NORMAL, reftype1, p2, NR_NONE, UINT32_MAX, news);
	}

	return CommandCost();
}
Example #28
0
const char *MusicDriver_ExtMidi::Start(const char * const * parm)
{
	if (strcmp(VideoDriver::GetInstance()->GetName(), "allegro") == 0 ||
			strcmp(SoundDriver::GetInstance()->GetName(), "allegro") == 0) {
		return "the extmidi driver does not work when Allegro is loaded.";
	}

	const char *command = GetDriverParam(parm, "cmd");
	if (StrEmpty(command)) command = EXTERNAL_PLAYER;

	this->command = stredup(command);
	this->song[0] = '\0';
	this->pid = -1;
	return NULL;
}
Example #29
0
/**
 * Get the group with the given name. If it doesn't exist
 * and \a create_new is \c true create a new group.
 * @param name name of the group to find.
 * @param len  the maximum length of said name (\c 0 means length of the string).
 * @param create_new Allow creation of group if it does not exist.
 * @return The requested group if it exists or was created, else \c nullptr.
 */
IniGroup *IniLoadFile::GetGroup(const char *name, size_t len, bool create_new)
{
	if (len == 0) len = strlen(name);

	/* does it exist already? */
	for (IniGroup *group = this->group; group != nullptr; group = group->next) {
		if (!strncmp(group->name, name, len) && group->name[len] == 0) {
			return group;
		}
	}

	if (!create_new) return nullptr;

	/* otherwise make a new one */
	IniGroup *group = new IniGroup(this, name, name + len - 1);
	group->comment = stredup("\n");
	return group;
}
Example #30
0
/**
 * Clone the custom name of a vehicle, adding or incrementing a number.
 * @param src Source vehicle, with a custom name.
 * @param dst Destination vehicle.
 */
static void CloneVehicleName(const Vehicle *src, Vehicle *dst)
{
	char buf[256];

	/* Find the position of the first digit in the last group of digits. */
	size_t number_position;
	for (number_position = strlen(src->name); number_position > 0; number_position--) {
		/* The design of UTF-8 lets this work simply without having to check
		 * for UTF-8 sequences. */
		if (src->name[number_position - 1] < '0' || src->name[number_position - 1] > '9') break;
	}

	/* Format buffer and determine starting number. */
	int num;
	byte padding = 0;
	if (number_position == strlen(src->name)) {
		/* No digit at the end, so start at number 2. */
		strecpy(buf, src->name, lastof(buf));
		strecat(buf, " ", lastof(buf));
		number_position = strlen(buf);
		num = 2;
	} else {
		/* Found digits, parse them and start at the next number. */
		strecpy(buf, src->name, lastof(buf));
		buf[number_position] = '\0';
		char *endptr;
		num = strtol(&src->name[number_position], &endptr, 10) + 1;
		padding = endptr - &src->name[number_position];
	}

	/* Check if this name is already taken. */
	for (int max_iterations = 1000; max_iterations > 0; max_iterations--, num++) {
		/* Attach the number to the temporary name. */
		seprintf(&buf[number_position], lastof(buf), "%0*d", padding, num);

		/* Check the name is unique. */
		if (IsUniqueVehicleName(buf)) {
			dst->name = stredup(buf);
			break;
		}
	}

	/* All done. If we didn't find a name, it'll just use its default. */
}