git » fp-git.git » master » tree

[master] / PR / src / lib / xml / unknown.c

/*  Princed V3 - Prince of Persia Level Editor for PC Version
    Copyright (C) 2003 Princed Development Team

    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

    The authors of this program may be contacted at http://forum.princed.com.ar
*/

/*
unknown.c: Princed Resources : Unknown resources handler implementation
���������
 Copyright 2003 Princed Development Team
  Created: 24 Aug 2003

  Author: Enrique Calot <ecalot.cod@princed.com.ar>
  Version: 1.01 (2003-Oct-23)
  Version: 1.50 (2005-Dec-19)

 Note:
  DO NOT remove this copyright notice
*/

/***************************************************************\
|                  I M P L E M E N T A T I O N                  |
\***************************************************************/

/* Includes */
#include "common.h"
#include "disk.h"
#include "memory.h"
#include "parse.h" /* getTagStructure */
#include "stringformat.h"
#include "translate.h"
#include "tree.h"
#include "unknown.h"
#include <stdio.h>
#include <string.h>

/***************************************************************\
|                     Unknown.xml primitives                    |
\***************************************************************/

/* XML generation defines */

#define RES_XML_UNKNOWN_FILES "%t%03n.%e"
#define XML_TAG_RESOURCES     "resources"
#define XML_ATTRV_VERSION     "build-1"

char* unknown_getVersion(const char* oldVersion) {
	char* newVersion;
	int l,i;

	if (!oldVersion||!oldVersion[0]) return strallocandcopy(XML_ATTRV_VERSION);
	l=strlen(oldVersion);
	newVersion=malloc(l+5); /* l+2 is enough */
	for (i=0;i<l&&isNumber(oldVersion[l-i-1]);i++);

	if (l!=i) strncpy(newVersion,oldVersion,l-i);
	if (i)    sprintf(newVersion+(l-i),"%d",atoi(oldVersion+(l-i))+1);
	else newVersion[l]=0;

	return newVersion;
}

tUnknownFile unknownFile;

/***************************************************************\
|                           Logging Layer                       |
\***************************************************************/

int unknownLogStart (const char* file,int optionflag, const char* backupExtension) {
	if (unknownFile.fd) return PR_RESULT_F_XML_ALREADY_OPEN; /* File already open */

	/* Use default filename if file is NULL */
	if (!file) file=RES_XML_UNKNOWN_XML;

	/* Remember optionflag and backupExtension */
	unknownFile.optionflag=optionflag;
	unknownFile.backupExtension=strallocandcopy(backupExtension);
	unknownFile.currentDat=NULL;

	/* Read the previous file if exists */
	{
		int error;

		unknownFile.status.folderFirst=NULL;
		unknownFile.status.folderCursor=NULL;
		unknownFile.tree=xmlParseFile(file,&error);
		if (error) {
			unknownFile.tree=getTagStructure();
			unknownFile.tree->version=strallocandcopy(XML_ATTRV_VERSION);
			unknownFile.tree->tag=strallocandcopy(XML_TAG_RESOURCES);
		} else {
			char* version=unknown_getVersion(unknownFile.tree->version);
			freeAllocation(unknownFile.tree->version);
			unknownFile.tree->version=version;
		}
	}

	/* Open the file */
	if (!writeOpen(file,&unknownFile.fd,optionflag)) return PR_RESULT_F_XML_FILE; /* file not open */

	return PR_RESULT_SUCCESS; /* Ok */
}

int unknownLogStop () {
	int i;
	tTag* t;

	if (!unknownFile.fd) return PR_RESULT_F_XML_NOT_OPEN; /* File not open */

	/* common factor tree reducing function */
	if (unknownFile.tree) xmlOptimizeCommonFactor(unknownFile.tree->child);

	/* it is time to fix the inheritances */
	resourceTreeFixInheritances(&unknownFile.tree);

	/* now we'll add the new generated part of the tree at the end of the second level (resources id the first) */
	if (unknownFile.tree) {
		xmlOptimizeCommonFactor(unknownFile.tree); /* here some common factors are moved up */
		if (unknownFile.tree->child) {
			for (t=unknownFile.tree->child;t->next;t=t->next);
			t->next=unknownFile.status.folderFirst; /* the first folder of the new tree */
		} else {
			unknownFile.tree->child=unknownFile.status.folderFirst; /* the first folder of the new tree */
		}
	}

	/* generate the XML file */
	treeXmlGenerate(0,unknownFile.tree,unknownFile.fd);

	/* it's time to free the tree */
	freeParsedStructure (&unknownFile.tree);

	/* and close the file */
	writeCloseOk(unknownFile.fd,unknownFile.optionflag,unknownFile.backupExtension);

	/* Free structures */
	freeAllocation(unknownFile.currentDat);
	freeAllocation(unknownFile.backupExtension);
	unknownFile.backupExtension=NULL;
	unknownFile.fd=NULL;
	for (i=0;i<RES_FILE_TYPES_COUNT;i++) unknownFile.typeCount[i]=0; /* re-initialize in 0 for next file processing */

	return PR_RESULT_SUCCESS; /* Ok */
}

int unknownLogAppend(const char* vFiledat,tResourceId id,const char* ext,tResourceType type,const char* vDirExt,tResourceId pal,const char* vFiledatWithPath,int optionflag,int count, unsigned long int flags,const char* filename) {
	if (!unknownFile.fd) return PR_RESULT_F_XML_NOT_OPEN; /* File not open, logging is off, just a warning */

	if (!unknownFile.currentDat) { /* this is the beginning of the file */
		treeStatusFolder(vFiledatWithPath,vFiledat,pal.value,translateInt2Ext(strToLower(pal.index)),&unknownFile.status);
		unknownFile.currentDat=strallocandcopy(vFiledat);
		/* it could be moved here the read-parsing-loading and write-opening,
		 * but it is necessary to know the parsing status before the extractions are started */
		treeDeleteFile(vFiledat,unknownFile.tree);
	} else if (!equalsIgnoreCase(unknownFile.currentDat,vFiledat)) {
		int i;
		treeStatusFolder(vFiledatWithPath,vFiledat,pal.value,translateInt2Ext(strToLower(pal.index)),&unknownFile.status);
		freeAllocation(unknownFile.currentDat);
		unknownFile.currentDat=strallocandcopy(vFiledat);
		treeDeleteFile(vFiledat,unknownFile.tree);
		for (i=0;i<RES_FILE_TYPES_COUNT;i++) unknownFile.typeCount[i]=0; /* re-initialize in 0 for next file processing */
	}

	treeStatusItem(id.value,translateInt2Ext(strToLower(id.index)),filename,getExtDesc(type),flags,getExtDesc(type),count,id.order,&unknownFile.status);

	return PR_RESULT_SUCCESS;
}

/***************************************************************\
|                     Middle layer function                     |
\***************************************************************/

void getFileName(char* vFileext,const char* vDirExt,const tResource* r,const char* vFiledat, const char* vDatFileName,int optionflag, const char* backupExtension,const char* format) {
	static const char* extarray[]=RES_FILE_EXTENSIONS;
	const char* filename;
	int pos;

	if (r->path==NULL) {
		pos=((r->type<RES_FILE_TYPES_COUNT)&&(r->type>=0))?r->type:eResTypeOtherBinary;
		unknownFile.typeCount[pos]++;

		/* set filename */
		if (!format) format=RES_XML_UNKNOWN_FILES;
		filename=parseformat(format,r->id.value,r->id.index,getExtDesc(pos),extarray[pos],unknownFile.typeCount[pos],r->id.order,r->desc,r->name);

		sprintf(vFileext,"%s/"RES_XML_UNKNOWN_PATH"/%s/%s",vDirExt,vDatFileName,filename);
		unknownLogAppend(vDatFileName,r->id,extarray[pos],r->type,vDirExt,r->paletteId,vFiledat,optionflag,unknownFile.typeCount[pos],r->flags,filename);
	} else {
		/* set filename */
		sprintf(vFileext,"%s/%s",vDirExt,r->path);
	}
}