#include <clocale>
#include <cstdio>
#include <fstream>
#include <sstream>
#include <string>
#include <clocale>
using namespace std;
#include "body.h"
#include "findFile.h"
#include "keywords.h"
#include "Options.h"
#include "parse.h"
#include "PlanetProperties.h"
#include "xpDefines.h"
#include "xpUtil.h"
#include "libplanet/Planet.h"
static PlanetProperties *defaultProperties;
static PlanetProperties *currentProperties;
static void
readConfig(const char *line, PlanetProperties *planetProperties[])
{
int i = 0;
while (isDelimiter(line[i]))
{
i++;
if (static_cast<unsigned int> (i) > strlen(line)) return;
}
if (isEndOfLine(line[i])) return;
Options *options = Options::getInstance();
while (static_cast<unsigned int> (i) < strlen(line))
{
char *returnString = NULL;
int val = parse(i, line, returnString);
if (val != BODY && currentProperties == NULL)
xpExit("No Planet defined in config file!\n",
__FILE__, __LINE__);
switch (val)
{
case ARC_COLOR:
{
int r, g, b;
if (sscanf(returnString, "%d,%d,%d", &r, &g, &b) == 3)
{
unsigned char color[3] = { r & 0xff, g & 0xff, b & 0xff };
currentProperties->ArcColor(color);
}
else
{
xpWarn("Need three values for arc_color\n",
__FILE__, __LINE__);
}
}
break;
case ARC_FILE:
currentProperties->AddArcFile(returnString);
break;
case BODY:
{
body index = Planet::parseBodyName(returnString);
if (index < RANDOM_BODY)
{
// [default] should come first in the config file.
// The first time we get to a body after [default],
// set all of the planet properties to the default
// value. If [default] isn't first, all of the bodies
// specified before it get wiped out.
if (currentProperties == defaultProperties)
{
for (int ibody = SUN; ibody < RANDOM_BODY; ibody++)
{
*planetProperties[ibody] = *defaultProperties;
}
}
currentProperties = planetProperties[index];
}
else if (index == DEFAULT)
{
// We really shouldn't have to do this, since
// currentProperties is set to defaultProperties
// before the file is read in, and [default] should
// come at the top.
currentProperties = defaultProperties;
}
else
{
xpExit("Unknown body in config file\n", __FILE__, __LINE__);
}
}
break;
case BUMP_MAP:
{
// This is one that doesn't belong in [default]
if (currentProperties == defaultProperties)
{
ostringstream errStr;
errStr << "bump_map specified in [default] section. "
<< "You probably want to put it in a specific "
<< "planet's section (like [earth]).\n";
xpWarn(errStr.str(), __FILE__, __LINE__);
}
string bumpMap(returnString);
if (bumpMap.find('.') == string::npos)
bumpMap += defaultMapExt;
currentProperties->BumpMap(bumpMap);
}
break;
case BUMP_SCALE:
{
checkLocale(LC_NUMERIC, "C");
double bumpScale;
sscanf(returnString, "%lf", &bumpScale);
currentProperties->BumpScale(bumpScale);
checkLocale(LC_NUMERIC, "");
}
break;
case CLOUD_GAMMA:
{
checkLocale(LC_NUMERIC, "C");
double cloudGamma;
sscanf(returnString, "%lf", &cloudGamma);
currentProperties->CloudGamma(cloudGamma);
checkLocale(LC_NUMERIC, "");
}
break;
case CLOUD_MAP:
{
// This is one that doesn't belong in [default]
if (currentProperties == defaultProperties)
{
ostringstream errStr;
errStr << "cloud_map specified in [default] section. "
<< "You probably want to put it in a specific "
<< "planet's section (like [earth]).\n";
xpWarn(errStr.str(), __FILE__, __LINE__);
}
string cloudMap(returnString);
if (cloudMap.find('.') == string::npos)
cloudMap += defaultMapExt;
currentProperties->CloudMap(cloudMap);
}
break;
case CLOUD_SSEC:
currentProperties->SSECMap(returnString[0] == 't'
|| returnString[0] == 'T');
break;
case CLOUD_THRESHOLD:
{
int t;
sscanf(returnString, "%d", &t);
if (t < 0)
t = 0;
else if (t > 255)
t = 255;
currentProperties->CloudThreshold(t);
}
break;
case COLOR:
{
int r, g, b;
if (sscanf(returnString, "%d,%d,%d", &r, &g, &b) == 3)
{
unsigned char color[3] = { r & 0xff, g & 0xff, b & 0xff };
currentProperties->Color(color);
}
else
{
xpWarn("Need three values for color\n",
__FILE__, __LINE__);
}
}
break;
case DAY_MAP:
case IMAGE:
// This is one that doesn't belong in [default]
if (currentProperties == defaultProperties)
{
ostringstream errStr;
errStr << "image or map specified in [default] section. "
<< "You probably want to put it in a specific "
<< "planet's section (like [earth]).\n";
xpWarn(errStr.str(), __FILE__, __LINE__);
}
currentProperties->DayMap(returnString);
break;
case DELIMITER:
break;
case DRAW_ORBIT:
{
bool drawOrbit = (returnString[0] == 't'
|| returnString[0] == 'T');
currentProperties->DrawOrbit(drawOrbit);
}
break;
case ENDOFLINE:
break;
case GRID:
{
bool grid = (returnString[0] == 't'
|| returnString[0] == 'T');
currentProperties->Grid(grid);
}
break;
case GRID1:
{
int grid1;
sscanf(returnString, "%d", &grid1);
if (grid1 < 0 || grid1 > 90)
xpExit("grid1 must be between 0 and 90\n",
__FILE__, __LINE__);
currentProperties->Grid1(grid1);
}
break;
case GRID2:
{
int grid2;
sscanf(returnString, "%d", &grid2);
if (grid2 < 0)
xpExit("grid2 must be positive\n", __FILE__, __LINE__);
currentProperties->Grid2(grid2);
}
break;
case GRID_COLOR:
{
int r, g, b;
if (sscanf(returnString, "%d,%d,%d", &r, &g, &b) == 3)
{
unsigned char color[3] = { r & 0xff, g & 0xff, b & 0xff };
currentProperties->GridColor(color);
}
else
{
xpWarn("Need three values for grid_color\n",
__FILE__, __LINE__);
}
}
break;
case MAGNIFY:
{
checkLocale(LC_NUMERIC, "C");
double value;
sscanf(returnString, "%lf", &value);
if (value < 0) value = 1;
currentProperties->Magnify(value);
checkLocale(LC_NUMERIC, "");
}
break;
case MAP_BOUNDS:
{
// This is one that doesn't belong in [default]
if (currentProperties == defaultProperties)
{
ostringstream errStr;
errStr << "map_bounds specified in [default] section. "
<< "You probably want to put it in a specific "
<< "planet's section (like [earth]).\n";
xpWarn(errStr.str(), __FILE__, __LINE__);
}
checkLocale(LC_NUMERIC, "C");
double uly, ulx, lry, lrx;
int numRead = sscanf(returnString, "%lf,%lf,%lf,%lf",
&uly, &ulx, &lry, &lrx);
if (numRead == 4)
{
currentProperties->MapBounds(true, uly, ulx, lry, lrx);
}
else
{
xpWarn("Need four values for mapbounds\n",
__FILE__, __LINE__);
}
checkLocale(LC_NUMERIC, "");
}
break;
case MARKER_COLOR:
{
int r, g, b;
if (sscanf(returnString, "%d,%d,%d", &r, &g, &b) == 3)
{
unsigned char color[3] = { r & 0xff, g & 0xff, b & 0xff };
currentProperties->MarkerColor(color);
}
else
{
xpWarn("Need three values for marker_color\n",
__FILE__, __LINE__);
}
}
break;
case MARKER_FILE:
currentProperties->AddMarkerFile(returnString);
break;
case MARKER_FONT:
currentProperties->MarkerFont(returnString);
break;
case MARKER_FONTSIZE:
{
int fontSize;
sscanf(returnString, "%d", &fontSize);
if (fontSize > 0)
{
currentProperties->MarkerFontSize(fontSize);
}
else
{
xpWarn("fontSize must be positive.\n",
__FILE__, __LINE__);
}
}
break;
case MAX_RAD_FOR_LABEL:
{
checkLocale(LC_NUMERIC, "C");
double value;
sscanf(returnString, "%lf", &value);
currentProperties->MaxRadiusForLabel(value);
checkLocale(LC_NUMERIC, "");
}
break;
case MIN_RAD_FOR_LABEL:
{
checkLocale(LC_NUMERIC, "C");
double value;
sscanf(returnString, "%lf", &value);
currentProperties->MinRadiusForLabel(value);
checkLocale(LC_NUMERIC, "");
}
break;
case MIN_RAD_FOR_MARKERS:
{
checkLocale(LC_NUMERIC, "C");
double value;
sscanf(returnString, "%lf", &value);
currentProperties->MinRadiusForMarkers(value);
checkLocale(LC_NUMERIC, "");
}
break;
case NAME:
// This is one that doesn't belong in [default]
if (currentProperties == defaultProperties)
{
ostringstream errStr;
errStr << "name specified in [default] section. "
<< "You probably want to put it in a specific "
<< "planet's section (like [earth]).\n";
xpWarn(errStr.str(), __FILE__, __LINE__);
}
currentProperties->Name(returnString);
break;
case NIGHT_MAP:
// This is one that doesn't belong in [default]
if (currentProperties == defaultProperties)
{
ostringstream errStr;
errStr << "night_map specified in [default] section. "
<< "You probably want to put it in a specific "
<< "planet's section (like [earth]).\n";
xpWarn(errStr.str(), __FILE__, __LINE__);
}
currentProperties->NightMap(returnString);
break;
case ORBIT:
{
checkLocale(LC_NUMERIC, "C");
double start, stop, delta;
int numRead = sscanf(returnString, "%lf,%lf,%lf",
&start, &stop, &delta);
if (numRead == 3)
{
currentProperties->StartOrbit(start);
currentProperties->StopOrbit(stop);
currentProperties->DelOrbit(delta);
}
else
{
xpWarn("Need three values for orbit\n",
__FILE__, __LINE__);
}
checkLocale(LC_NUMERIC, "");
}
break;
case ORBIT_COLOR:
{
int r, g, b;
if (sscanf(returnString, "%d,%d,%d", &r, &g, &b) == 3)
{
unsigned char color[3] = { r & 0xff, g & 0xff, b & 0xff };
currentProperties->OrbitColor(color);
}
else
{
xpWarn("Need three values for orbit_color\n",
__FILE__, __LINE__);
}
}
break;
case RANDOM_ORIGIN:
currentProperties->RandomOrigin(returnString[0] == 't'
|| returnString[0] == 'T');
break;
case RANDOM_TARGET:
currentProperties->RandomTarget(returnString[0] == 't'
|| returnString[0] == 'T');
break;
case SATELLITE_FILE:
currentProperties->AddSatelliteFile(returnString);
break;
case SHADE:
{
int s;
sscanf(returnString, "%d", &s);
if (s < 0)
s = 0;
else if (s > 100)
s = 100;
currentProperties->Shade(s/100.);
}
break;
case SPECULAR_MAP:
currentProperties->SpecularMap(returnString);
break;
case TEXT_COLOR:
{
int r, g, b;
if (sscanf(returnString, "%d,%d,%d", &r, &g, &b) == 3)
{
unsigned char color[3] = { r & 0xff, g & 0xff, b & 0xff };
currentProperties->TextColor(color);
}
else
{
xpWarn("Need three values for text_color\n",
__FILE__, __LINE__);
}
}
break;
case TWILIGHT:
{
int value;
sscanf(returnString, "%d", &value);
if (value >= 0 && value <= 90)
{
currentProperties->Twilight(value);
}
else
{
xpWarn("Twilight value should be between 0 and 90 degrees\n",
__FILE__, __LINE__);
}
}
break;
default:
{
ostringstream errStr;
errStr << "Unknown keyword in configuration file:\n\t"
<< line << endl;
xpWarn(errStr.str(), __FILE__, __LINE__);
}
break;
}
if (val != DELIMITER && options->Verbosity() > 3)
{
ostringstream msg;
msg << "value is " << keyWordString[val - '?'];
if (returnString != NULL)
msg << ", returnString is " << returnString;
msg << endl;
xpMsg(msg.str(), __FILE__, __LINE__);
}
delete [] returnString;
if (val == ENDOFLINE) break;
}
}
void
readConfigFile(string configFile, PlanetProperties *planetProperties[])
{
bool foundFile = findFile(configFile, "config");
if (foundFile)
{
defaultProperties = new PlanetProperties(UNKNOWN_BODY);
currentProperties = defaultProperties;
ifstream inFile(configFile.c_str());
char *line = new char[256];
while (inFile.getline(line, 256, '\n') != NULL)
readConfig(line, planetProperties);
// This condition will only be true if [default] is the only
// section in the config file. In this case, set all planet
// properties to the default values.
if (currentProperties == defaultProperties)
{
for (int ibody = SUN; ibody < RANDOM_BODY; ibody++)
{
*planetProperties[ibody] = *defaultProperties;
}
}
inFile.close();
delete [] line;
delete defaultProperties;
}
else
{
ostringstream errStr;
errStr << "Can't load configuration file " << configFile << endl;
xpExit(errStr.str(), __FILE__, __LINE__);
}
}
syntax highlighted by Code2HTML, v. 0.9.1