/*
spacemaze - Fly a space ship through a maze and collect all the items.
Copyright (C) 2000, 2001, 2002 John Ericson
This program 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; either version 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2000-03-25 High / John Ericson john.ericson@home.se
*/
#include "campaign.h"
void CampaignStartDocument(campaign_s *campaign);
void CampaignEndDocument(campaign_s *campaign);
void CampaignCharacters(campaign_s *campaign, const xmlChar *ch, int len);
void CampaignStartElement(campaign_s *campaign, const xmlChar *name, const xmlChar **attrs);
void CampaignEndElement(campaign_s *campaign, const xmlChar *name);
void CampaignWarning(campaign_s *campaign, const char *msg, ...);
void CampaignError(campaign_s *campaign, const char *msg, ...);
void CampaignFatalError(campaign_s *campaign, const char *msg, ...);
static xmlSAXHandler CampaignSAXParser = {
0, /* internalSubset */
0, /* isStandalone */
0, /* hasInternalSubset */
0, /* hasExternalSubset */
0, /* resolveEntity */
0, /* getEntity */
0, /* entityDecl */
0, /* notationDecl */
0, /* attributeDecl */
0, /* elementDecl */
0, /* unparsedEntityDecl */
0, /* setDocumentLocator */
(startDocumentSAXFunc) CampaignStartDocument, /* startDocument */
(endDocumentSAXFunc) CampaignEndDocument, /* endDocument */
(startElementSAXFunc) CampaignStartElement, /* startElement */
(endElementSAXFunc) CampaignEndElement, /* endElement */
0, /* reference */
(charactersSAXFunc) CampaignCharacters, /* characters */
0, /* ignorableWhitespace */
0, /* processingInstruction */
0, /* comment */
(warningSAXFunc) CampaignWarning, /* warning */
(errorSAXFunc) CampaignError, /* error */
(fatalErrorSAXFunc) CampaignFatalError, /* fatalError */
};
static campaign_state_s state;
/* Used to buffer input from the characters callback */
static char ch_buffer[1024];
static int ch_buffer_len;
int LoadCampaign(campaign_s *campaign, const char *filename) {
int ret = 0;
xmlParserCtxtPtr ctxt;
ctxt = xmlCreateFileParserCtxt(filename);
if (ctxt == NULL) return -1;
ctxt->sax = &CampaignSAXParser;
ctxt->userData = campaign;
xmlParseDocument(ctxt);
if (ctxt->wellFormed)
ret = 0;
else
ret = -1;
if (&CampaignSAXParser != NULL)
ctxt->sax = NULL;
xmlFreeParserCtxt(ctxt);
return ret;
}
void CampaignStartDocument(campaign_s *campaign) {
int i;
/* Clean out the variable */
strcpy(campaign->name, "(Noname)");
strcpy(campaign->version, "(Noversion)");
campaign->maxplayers = 1;
campaign->numlevels = 0;
/* Clean out the levels array */
for (i = 0; i < MAXLEVELSINCAMPAIGN; i++) {
strcpy(campaign->levels[i].filename, "");
}
state = CAMPAIGN_START;
}
void CampaignEndDocument(campaign_s *campaign) {
/*
Since we increase the element everytime we leave them (CampaignEndElement),
we have to decrease all one step at the end of the document parsing to get
the right size.
*/
/* Mark the end of the levels array with an empty string */
strcpy(campaign->levels[campaign->numlevels+1].filename, "");
campaign->numlevels--;
}
void CampaignCharacters(campaign_s *campaign, const xmlChar *ch, int len) {
/*
An XML parser isn't guaranteed to return the entire contents of a tag in a
characters callback therefor we use a buffer to bundle it all togehter and
process the string in the call to end_element.
*/
char output[40];
int i;
/* Copy ch to output */
for (i = 0; (i < len) && (i < 30);i++)
output[i] = ch[i];
/* Put an NULL at the end */
output[i] = 0;
strcat(ch_buffer, output);
ch_buffer_len += len;
}
void CampaignStartElement(campaign_s *campaign, const xmlChar *name, const xmlChar **attrs) {
if (strcmp(name, "Campaign") == 0) {
state += CAMPAIGN_CAMPAIGN;
/* Start parsing attrib line if there is any attribs */
/* This code could be generalized since its useful on several places */
if (attrs != NULL)
if (strcmp(attrs[0], "version") == 0)
strcpy(campaign->version, attrs[1]);
else
printf("Unknown attribut %s in %s found. Ignoring.\n", attrs[1], name);
}
else if (strcmp(name, "Info") == 0) state += CAMPAIGN_INFO;
else if (strcmp(name, "Name") == 0) state += CAMPAIGN_NAME;
else if (strcmp(name, "Author") == 0) state += CAMPAIGN_AUTHOR;
else if (strcmp(name, "Description") == 0) state += CAMPAIGN_DESCRIPTION;
else if (strcmp(name, "Gametype") == 0) state += CAMPAIGN_GAMETYPE;
else if (strcmp(name, "Levels") == 0) state += CAMPAIGN_LEVELS;
else if (strcmp(name, "LevelFile") == 0) {
state += CAMPAIGN_LEVELFILE;
if (attrs != NULL)
if (strcmp(attrs[0], "file") == 0)
strcpy(campaign->levels[campaign->numlevels++].filename, attrs[1]);
else
printf("Unknown attribut %s in %s found. Ignoring.\n", attrs[1], name);
}
else
printf("Unknown Element <%s> found. Ignoring.\n", name);
}
void CampaignEndElement(campaign_s *campaign, const xmlChar *name) {
char *output;
ch_buffer[ch_buffer_len] = 0;
output = trim(ch_buffer);
strcpy(ch_buffer, output);
switch (state) {
case (CAMPAIGN_CAMPAIGN + CAMPAIGN_INFO + CAMPAIGN_NAME):
strcpy(campaign->name, ch_buffer);
break;
case (CAMPAIGN_CAMPAIGN + CAMPAIGN_INFO + CAMPAIGN_AUTHOR):
case (CAMPAIGN_CAMPAIGN + CAMPAIGN_INFO + CAMPAIGN_DESCRIPTION):
case (CAMPAIGN_CAMPAIGN + CAMPAIGN_INFO + CAMPAIGN_GAMETYPE):
/* Info we dont use at the moment */
break;
/*
case (CAMPAIGN_CAMPAIGN + CAMPAIGN_LEVELS + CAMPAIGN_LEVELFILE):
/* Why cant I use strtof? */
/* strcpy(campaign->levels[campaign->numlevels].filename, ch_buffer);
break;
*/
}
/* Reset characters buffer */
ch_buffer[0] = 0;
ch_buffer_len = 0;
if (strcmp(name, "Campaign") == 0) state -= CAMPAIGN_CAMPAIGN;
else if (strcmp(name, "Info") == 0) state -= CAMPAIGN_INFO;
else if (strcmp(name, "Name") == 0) state -= CAMPAIGN_NAME;
else if (strcmp(name, "Author") == 0) state -= CAMPAIGN_AUTHOR;
else if (strcmp(name, "Description") == 0) state -= CAMPAIGN_DESCRIPTION;
else if (strcmp(name, "Gametype") == 0) state -= CAMPAIGN_GAMETYPE;
else if (strcmp(name, "Levels") == 0) state -= CAMPAIGN_LEVELS;
else if (strcmp(name, "LevelFile") == 0) state -= CAMPAIGN_LEVELFILE;
}
void CampaignWarning(campaign_s *campaign, const char *msg, ...) {
va_list args;
char buffer[255];
strcpy(buffer, "Loading campaign warning: ");
va_start(args, msg);
vsprintf(&buffer[strlen(buffer)], msg, args);
printf("%s", buffer);
va_end(args);
}
void CampaignError(campaign_s *campaign, const char *msg, ...) {
va_list args;
char buffer[255];
strcpy(buffer, "Loading campaign error: ");
va_start(args, msg);
vsprintf(&buffer[strlen(buffer)], msg, args);
printf("%s", buffer);
va_end(args);
}
void CampaignFatalError(campaign_s *campaign, const char *msg, ...) {
va_list args;
char buffer[255];
strcpy(buffer, "Loading campaign fatal error: ");
va_start(args, msg);
vsprintf(&buffer[strlen(buffer)], msg, args);
printf("%s", buffer);
va_end(args);
}