Fix ICU iterators on leading/trailing whitespace
[openttd/fttd.git] / src / driver.cpp
blobdd03e5e7b6e372c35b183a3f8cdfeb352296b909
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
10 /** @file driver.cpp Base for all driver handling. */
12 #include "stdafx.h"
13 #include "debug.h"
14 #include "sound/sound_driver.hpp"
15 #include "music/music_driver.hpp"
16 #include "video/video_driver.hpp"
17 #include "string_func.h"
19 VideoDriver *_video_driver; ///< The currently active video driver.
20 char *_ini_videodriver; ///< The video driver a stored in the configuration file.
21 int _num_resolutions; ///< The number of resolutions.
22 Dimension _resolutions[32]; ///< List of resolutions.
23 Dimension _cur_resolution; ///< The current resolution.
24 bool _rightclick_emulate; ///< Whether right clicking is emulated.
26 SoundDriver *_sound_driver; ///< The currently active sound driver.
27 char *_ini_sounddriver; ///< The sound driver a stored in the configuration file.
29 MusicDriver *_music_driver; ///< The currently active music driver.
30 char *_ini_musicdriver; ///< The music driver a stored in the configuration file.
32 char *_ini_blitter; ///< The blitter as stored in the configuration file.
33 bool _blitter_autodetected; ///< Was the blitter autodetected or specified by the user?
35 /**
36 * Get a string parameter the list of parameters.
37 * @param parm The parameters.
38 * @param name The parameter name we're looking for.
39 * @return The parameter value.
41 const char *GetDriverParam(const char * const *parm, const char *name)
43 size_t len;
45 if (parm == NULL) return NULL;
47 len = strlen(name);
48 for (; *parm != NULL; parm++) {
49 const char *p = *parm;
51 if (strncmp(p, name, len) == 0) {
52 if (p[len] == '=') return p + len + 1;
53 if (p[len] == '\0') return p + len;
56 return NULL;
59 /**
60 * Get a boolean parameter the list of parameters.
61 * @param parm The parameters.
62 * @param name The parameter name we're looking for.
63 * @return The parameter value.
65 bool GetDriverParamBool(const char * const *parm, const char *name)
67 return GetDriverParam(parm, name) != NULL;
70 /**
71 * Get an integer parameter the list of parameters.
72 * @param parm The parameters.
73 * @param name The parameter name we're looking for.
74 * @param def The default value if the parameter doesn't exist.
75 * @return The parameter value.
77 int GetDriverParamInt(const char * const *parm, const char *name, int def)
79 const char *p = GetDriverParam(parm, name);
80 return p != NULL ? atoi(p) : def;
83 /**
84 * Find the requested driver and return its class.
85 * @param name the driver to select.
86 * @param type the type of driver to select
87 * @post Sets the driver so GetCurrentDriver() returns it too.
89 Driver *DriverFactoryBase::SelectDriver(const char *name, Driver::Type type)
91 if (GetDrivers().size() == 0) return NULL;
93 if (StrEmpty(name)) {
94 /* Probe for this driver, but do not fall back to dedicated/null! */
95 for (int priority = 10; priority > 0; priority--) {
96 Drivers::iterator it = GetDrivers().begin();
97 for (; it != GetDrivers().end(); ++it) {
98 DriverFactoryBase *d = (*it).second;
100 /* Check driver type */
101 if (d->type != type) continue;
102 if (d->priority != priority) continue;
104 Driver *newd = d->CreateInstance();
105 const char *err = newd->Start(NULL);
106 if (err == NULL) {
107 DEBUG(driver, 1, "Successfully probed %s driver '%s'", GetDriverTypeName(type), d->name);
108 delete *GetActiveDriver(type);
109 *GetActiveDriver(type) = newd;
110 return newd;
113 DEBUG(driver, 1, "Probing %s driver '%s' failed with error: %s", GetDriverTypeName(type), d->name, err);
114 delete newd;
117 usererror("Couldn't find any suitable %s driver", GetDriverTypeName(type));
118 } else {
119 char *parm;
120 char buffer[256];
121 const char *parms[32];
123 /* Extract the driver name and put parameter list in parm */
124 strecpy(buffer, name, lastof(buffer));
125 parm = strchr(buffer, ':');
126 parms[0] = NULL;
127 if (parm != NULL) {
128 uint np = 0;
129 /* Tokenize the parm. */
130 do {
131 *parm++ = '\0';
132 if (np < lengthof(parms) - 1) parms[np++] = parm;
133 while (*parm != '\0' && *parm != ',') parm++;
134 } while (*parm == ',');
135 parms[np] = NULL;
138 /* Find this driver */
139 Drivers::iterator it = GetDrivers().begin();
140 for (; it != GetDrivers().end(); ++it) {
141 DriverFactoryBase *d = (*it).second;
143 /* Check driver type */
144 if (d->type != type) continue;
146 /* Check driver name */
147 if (strcasecmp(buffer, d->name) != 0) continue;
149 /* Found our driver, let's try it */
150 Driver *newd = d->CreateInstance();
152 const char *err = newd->Start(parms);
153 if (err != NULL) {
154 delete newd;
155 usererror("Unable to load driver '%s'. The error was: %s", d->name, err);
158 DEBUG(driver, 1, "Successfully loaded %s driver '%s'", GetDriverTypeName(type), d->name);
159 delete *GetActiveDriver(type);
160 *GetActiveDriver(type) = newd;
161 return newd;
163 usererror("No such %s driver: %s\n", GetDriverTypeName(type), buffer);
168 * Build a human readable list of available drivers, grouped by type.
169 * @param p The buffer to write to.
170 * @param last The last element in the buffer.
171 * @return The end of the written buffer.
173 char *DriverFactoryBase::GetDriversInfo(char *p, const char *last)
175 for (Driver::Type type = Driver::DT_BEGIN; type != Driver::DT_END; type++) {
176 p += seprintf(p, last, "List of %s drivers:\n", GetDriverTypeName(type));
178 for (int priority = 10; priority >= 0; priority--) {
179 Drivers::iterator it = GetDrivers().begin();
180 for (; it != GetDrivers().end(); it++) {
181 DriverFactoryBase *d = (*it).second;
182 if (d->type != type) continue;
183 if (d->priority != priority) continue;
184 p += seprintf(p, last, "%18s: %s\n", d->name, d->GetDescription());
188 p += seprintf(p, last, "\n");
191 return p;
195 * Construct a new DriverFactory.
196 * @param type The type of driver.
197 * @param priority The priority within the driver class.
198 * @param name The name of the driver.
199 * @param description A long-ish description of the driver.
201 DriverFactoryBase::DriverFactoryBase(Driver::Type type, int priority, const char *name, const char *description) :
202 type(type), priority(priority), name(name), description(description)
204 /* Prefix the name with driver type to make it unique */
205 char buf[32];
206 strecpy(buf, GetDriverTypeName(type), lastof(buf));
207 strecpy(buf + 5, name, lastof(buf));
209 const char *longname = strdup(buf);
211 std::pair<Drivers::iterator, bool> P = GetDrivers().insert(Drivers::value_type(longname, this));
212 assert(P.second);
216 * Frees memory used for this->name
218 DriverFactoryBase::~DriverFactoryBase()
220 /* Prefix the name with driver type to make it unique */
221 char buf[32];
222 strecpy(buf, GetDriverTypeName(type), lastof(buf));
223 strecpy(buf + 5, this->name, lastof(buf));
225 Drivers::iterator it = GetDrivers().find(buf);
226 assert(it != GetDrivers().end());
228 const char *longname = (*it).first;
230 GetDrivers().erase(it);
231 free(longname);
233 if (GetDrivers().empty()) delete &GetDrivers();