Subversion Repositories spk

Rev

Rev 196 | Rev 223 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 196 Rev 197
Line 1... Line 1...
1
 
1
 
2
#include "ModDiff.h"
2
#include "ModDiff.h"
3
#include "File_IO.h"
3
#include "File_IO.h"
4
#include "CatFile.h"
4
#include "CatFile.h"
5
 
5
 
6
CModDiff::CModDiff(const Utils::String &dir, const Utils::String &sAddon, int maxPatch) : m_pCatFile(NULL), m_sAddon(sAddon), m_sTempDir("."), m_iMaxPatch(maxPatch)
6
CModDiff::CModDiff(const Utils::WString &dir, const Utils::WString &sAddon, int maxPatch) : m_pCatFile(NULL), m_sAddon(sAddon), m_sTempDir(L"."), m_iMaxPatch(maxPatch)
7
{
7
{
8
	m_bLoaded = this->LoadDirectory(dir);
8
	m_bLoaded = this->LoadDirectory(dir);
9
}
9
}
10
 
10
 
11
CModDiff::~CModDiff(void)
11
CModDiff::~CModDiff(void)
12
{
12
{
13
	delete m_pCatFile;
13
	delete m_pCatFile;
14
}
14
}
15
 
15
 
16
bool CModDiff::LoadDirectory(const Utils::String &dir)
16
bool CModDiff::LoadDirectory(const Utils::WString &dir)
17
{
17
{
18
	m_sCurrentDir = dir;
18
	m_sCurrentDir = dir;
19
	m_fileSystem.setAddon(m_sAddon);
19
	m_fileSystem.setAddon(m_sAddon);
20
	return m_fileSystem.LoadFilesystem(dir, m_iMaxPatch);
20
	return m_fileSystem.LoadFilesystem(dir, m_iMaxPatch);
21
}
21
}
Line 36... Line 36...
36
	}
36
	}
37
 
37
 
38
	return true;
38
	return true;
39
}
39
}
40
 
40
 
41
Utils::String CModDiff::_extractFile(const Utils::String &sFile, const Utils::String &sTo)
41
Utils::WString CModDiff::_extractFile(const Utils::WString &sFile, const Utils::WString &sTo)
42
{
42
{
43
	SInCatFile *c = m_pCatFile->findData(sFile);
43
	SInCatFile *c = m_pCatFile->findData(sFile);
44
	if ( !c ) c = m_pCatFile->findData(m_sAddon + "/" + sFile);
44
	if ( !c ) c = m_pCatFile->findData(m_sAddon + L"/" + sFile);
45
	if ( !c ) return m_fileSystem.ExtractGameFile(sFile, sTo);
45
	if ( !c ) return m_fileSystem.extractGameFile(sFile, sTo);
46
	if (m_pCatFile->extractFile(c, sTo)) return sTo;
46
	if (m_pCatFile->extractFile(c, sTo)) return sTo;
47
	return "";
47
	return L"";
48
}
48
}
49
 
49
 
50
bool CModDiff::doDiff(const Utils::String &sModFile)
50
bool CModDiff::doDiff(const Utils::WString &sModFile)
51
{
51
{
52
	// find the file in the loaded cat
52
	// find the file in the loaded cat
53
	SInCatFile *c = m_pCatFile->findData(sModFile);
53
	SInCatFile *c = m_pCatFile->findData(sModFile);
54
	if ( !c ) c = m_pCatFile->findData(m_sAddon + "/" + sModFile);
54
	if ( !c ) c = m_pCatFile->findData(m_sAddon + L"/" + sModFile);
55
	if ( !c ) return false;
55
	if ( !c ) return false;
56
 
56
 
57
	Utils::WString temp = m_sTempDir.toWString();
57
	Utils::WString temp = m_sTempDir;
58
 
58
 
59
	// extract the matching file
59
	// extract the matching file
60
	Utils::String sToFile = CFileIO(temp + L"/" + CFileIO(c->sFile).filename()).fullFilenameStr();
60
	Utils::WString sToFile = CFileIO(temp + L"/" + CFileIO(c->sFile).filename()).fullFilename();
61
	if ( !m_pCatFile->extractFile(sModFile, sToFile) ) return false;
61
	if ( !m_pCatFile->extractFile(sModFile, sToFile) ) return false;
62
 
62
 
63
	// create a diff
63
	// create a diff
64
	Utils::String to = m_fileSystem.ExtractGameFile(c->sFile, sToFile + ".compare");
64
	Utils::WString to = m_fileSystem.extractGameFile(c->sFile, sToFile + L".compare");
65
	if ( !to.empty() ) {
65
	if ( !to.empty() ) {
66
		SDiffFile *diff = diffFile(to, sToFile, c->sFile);
66
		SDiffFile *diff = diffFile(to, sToFile, c->sFile);
67
		if ( diff ) { 
67
		if ( diff ) { 
68
			this->_adjustFile(sModFile, diff, false);
68
			this->_adjustFile(sModFile, diff, false);
69
		}
69
		}
Line 77... Line 77...
77
 
77
 
78
 
78
 
79
bool CModDiff::_adjustTShips(SDiffFile *pDiff, bool bReverse)
79
bool CModDiff::_adjustTShips(SDiffFile *pDiff, bool bReverse)
80
{
80
{
81
	// need to read TCockpits
81
	// need to read TCockpits
82
	Utils::String sTo = this->_extractFile("types/TCockpits.pck", "TCockpits.xml");
82
	Utils::WString sTo = this->_extractFile(L"types/TCockpits.pck", L"TCockpits.xml");
83
	if ( sTo.empty() ) return false;
83
	if ( sTo.empty() ) return false;
84
	CFileIO TCockpits("TCockpits.xml");
84
	CFileIO TCockpits(L"TCockpits.xml");
85
	if ( !TCockpits.exists() ) return false;
85
	if ( !TCockpits.exists() ) return false;
86
	std::vector<Utils::String> lines;
86
	std::vector<Utils::WString> lines;
87
	if (!TCockpits.readLines(lines))
87
	if (!TCockpits.readLines(lines))
88
		return false;
88
		return false;
89
 
89
 
90
	// remove all the comments
90
	// remove all the comments
91
	auto itr = lines.begin();
91
	auto itr = lines.begin();
92
	while(itr != lines.end())
92
	while(itr != lines.end())
93
	{
93
	{
94
		if ((*itr)[0] == '/')
94
		if ((*itr)[0] == L'/')
95
			itr = lines.erase(itr);
95
			itr = lines.erase(itr);
96
		else
96
		else
97
			itr++;
97
			itr++;
98
	}
98
	}
99
	lines.erase(lines.begin());
99
	lines.erase(lines.begin());
100
 
100
 
101
	std::map<Utils::String, int> fileSet;
101
	std::map<Utils::WString, int> fileSet;
102
	int iPos = 0;
102
	int iPos = 0;
103
	for(itr = lines.begin(); itr != lines.end(); itr++)
103
	for(itr = lines.begin(); itr != lines.end(); itr++)
104
		fileSet[itr->token(";", -2)] = iPos++;
104
		fileSet[itr->token(L";", -2)] = iPos++;
105
 
105
 
106
	// now cycle through ships and adjust the cockpits
106
	// now cycle through ships and adjust the cockpits
107
	int iCount = -1;
107
	int iCount = -1;
108
	for ( SDiffEntry *pEntry = pDiff->m_lEntries.First(); pEntry; pEntry = pDiff->m_lEntries.Next() ) {
108
	for ( SDiffEntry *pEntry = pDiff->m_lEntries.First(); pEntry; pEntry = pDiff->m_lEntries.Next() ) {
109
		switch (pEntry->iType) {
109
		switch (pEntry->iType) {
110
			case DIFFTYPE_ADDITION:
110
			case DIFFTYPE_ADDITION:
111
				{
111
				{
112
					SDiffEntryAddition *pAddition = static_cast<SDiffEntryAddition *>(pEntry);
112
					SDiffEntryAddition *pAddition = static_cast<SDiffEntryAddition *>(pEntry);
113
					if ( pAddition ) {
113
					if ( pAddition ) {
114
						for ( int t = 0; t < 6; t++ ) {
114
						for ( int t = 0; t < 6; t++ ) {
115
							Utils::String sE = pAddition->sEntry.token(";", 32 + (t * 2));
115
							Utils::WString sE = pAddition->sEntry.token(L";", 32 + (t * 2));
116
							if ( !bReverse && sE.isNumber() )
116
							if ( !bReverse && sE.isNumber() )
117
							{
117
							{
118
								int iTurret = sE;
118
								int iTurret = sE;
119
								if ( iTurret && static_cast<size_t>(iTurret) < lines.size()) 
119
								if ( iTurret && static_cast<size_t>(iTurret) < lines.size()) 
120
								{
120
								{
121
									Utils::String sCockpit = lines[iTurret];
121
									Utils::WString sCockpit = lines[iTurret];
122
									pAddition->sEntry = pAddition->sEntry.replaceToken(";", 32 + (t * 2), sCockpit.token(";", -2) + ":" + static_cast<long>(iTurret));
122
									pAddition->sEntry = pAddition->sEntry.replaceToken(L";", 32 + (t * 2), sCockpit.token(L";", -2) + ":" + static_cast<long>(iTurret));
123
								}
123
								}
124
							}
124
							}
125
							else if ( bReverse && !sE.isNumber() ) {
125
							else if ( bReverse && !sE.isNumber() ) {
126
								int iUnfound = 0;
126
								int iUnfound = 0;
127
								if ( sE.isin(":") ) {
127
								if ( sE.contains(L":") ) {
128
									iUnfound = sE.token(":", 2);
128
									iUnfound = sE.token(L":", 2);
129
									sE = sE.token(":", 1);
129
									sE = sE.token(L":", 1);
130
								}
130
								}
131
								int iEntry = (fileSet.find(sE) == fileSet.end()) ? iUnfound : fileSet[sE];
131
								int iEntry = (fileSet.find(sE) == fileSet.end()) ? iUnfound : fileSet[sE];
132
								pAddition->sEntry = pAddition->sEntry.replaceToken(";", 32 + (t * 2), static_cast<long>(iEntry));
132
								pAddition->sEntry = pAddition->sEntry.replaceToken(L";", 32 + (t * 2), static_cast<long>(iEntry));
133
							}
133
							}
134
						}
134
						}
135
					}
135
					}
136
				}
136
				}
137
				break;
137
				break;
138
			case DIFFTYPE_CHANGE:
138
			case DIFFTYPE_CHANGE:
139
				{
139
				{
140
					SDiffEntryChange *pChange = static_cast<SDiffEntryChange *>(pEntry);
140
					SDiffEntryChange *pChange = static_cast<SDiffEntryChange *>(pEntry);
141
					if ( pChange->iPos >= 32 && pChange->iPos <= 42 && (pChange->iPos % 2) && pChange->sEntry.isNumber() ) {
141
					if ( pChange->iPos >= 32 && pChange->iPos <= 42 && (pChange->iPos % 2) && pChange->sEntry.isNumber() ) {
142
						Utils::String sCockpit = lines[pChange->sEntry.toInt()];
142
						Utils::WString sCockpit = lines[pChange->sEntry.toInt()];
143
						pChange->sEntry = sCockpit.token(";", -2) + ":" + pChange->sEntry;
143
						pChange->sEntry = sCockpit.token(L";", -2) + L":" + pChange->sEntry;
144
					}
144
					}
145
				}
145
				}
146
				break;
146
				break;
147
		}
147
		}
148
	}
148
	}
149
 
149
 
150
	return true;
150
	return true;
151
}
151
}
152
 
152
 
153
int CModDiff::_specialType(const Utils::WString &sFile) const
153
int CModDiff::_specialType(const Utils::WString &sFile) const
154
{
154
{
155
	if ( sFile.Compare(L"TShips") ) return MERGETYPE_TSHIPS;
155
	if ( sFile.Compare(L"TShips") ) return MERGETYPE_TSHIPS;
156
	return MERGETYPE_NONE;
156
	return MERGETYPE_NONE;
157
}
157
}
158
 
158
 
159
void CModDiff::_adjustFile(const Utils::String &sFile, SDiffFile *pDiff, bool bReverse)
159
void CModDiff::_adjustFile(const Utils::WString &sFile, SDiffFile *pDiff, bool bReverse)
160
{
160
{
161
	// check if we need to adjust the file
161
	// check if we need to adjust the file
162
	CFileIO File(sFile);
162
	CFileIO File(sFile);
163
	int iType = _specialType(File.baseName());
163
	int iType = _specialType(File.baseName());
164
	if ( iType == MERGETYPE_NONE ) return;
164
	if ( iType == MERGETYPE_NONE ) return;
Line 169... Line 169...
169
			this->_adjustTShips(pDiff, bReverse);
169
			this->_adjustTShips(pDiff, bReverse);
170
			break;
170
			break;
171
	}
171
	}
172
}
172
}
173
 
173
 
174
bool CModDiff::CreateDiff(const Utils::String &modfile)
174
bool CModDiff::CreateDiff(const Utils::WString &modfile)
175
{
175
{
176
	ClearError();
176
	ClearError();
177
 
177
 
178
	//check for valid parameters
178
	//check for valid parameters
179
	if ( !CFileIO(modfile).ExistsOld() ) { m_iError = MDERR_FILENOTFOUND; return false; }
179
	if ( !CFileIO::Exists(modfile) ) { m_iError = MDERR_FILENOTFOUND; return false; }
180
 
180
 
181
	Utils::String addonDir = "";
181
	Utils::WString addonDir = L"";
182
	int addonSize = addonDir.length() + 1;
182
	int addonSize = addonDir.length() + 1;
183
 
183
 
184
	// try and open the mod file
184
	// try and open the mod file
185
	CCatFile cat;
185
	CCatFile cat;
186
	if ( cat.open(modfile, addonDir, CATREAD_DAT, false) != CATERR_NONE ) { m_iError = MDERR_CANTOPENMOD; return false; }
186
	if ( cat.open(modfile, addonDir, CATREAD_DAT, false) != CATERR_NONE ) { m_iError = MDERR_CANTOPENMOD; return false; }
187
 
187
 
188
	Utils::WString temp = m_sTempDir.toWString();
188
	Utils::WString temp = m_sTempDir;
189
 
189
 
190
	// we'll need to read in all the types/text files
190
	// we'll need to read in all the types/text files
191
	for (unsigned int i = 0; i < cat.GetNumFiles(); i++)
191
	for (unsigned int i = 0; i < cat.GetNumFiles(); i++)
192
	{
192
	{
193
		SInCatFile *f = cat.GetFile(i);
193
		SInCatFile *f = cat.GetFile(i);
194
		Utils::String checkFile = f->sFile.findReplace("\\", "/");
194
		Utils::WString checkFile = f->sFile.findReplace(L"\\", L"/");
195
		if ( (checkFile.left(6).Compare("types/") || checkFile.left(2).Compare("t/") || checkFile.left(6 + addonSize).Compare(addonDir + "/types/") || checkFile.left(2 + addonSize).Compare(addonDir + "/t/")) && _validFile(checkFile) )
195
		if ( (checkFile.left(6).Compare(L"types/") || checkFile.left(2).Compare(L"t/") || checkFile.left(6 + addonSize).Compare(addonDir + L"/types/") || checkFile.left(2 + addonSize).Compare(addonDir + L"/t/")) && _validFile(checkFile) )
196
		{
196
		{
197
			// extract the file to the temp dir
197
			// extract the file to the temp dir
198
			Utils::String toFile = CFileIO(temp + L"/" + CFileIO(f->sFile).filename()).fullFilenameStr();
198
			Utils::WString toFile = CFileIO(temp + L"/" + CFileIO(f->sFile).filename()).fullFilename();
199
			if (cat.extractFile(f, toFile ))
199
			if (cat.extractFile(f, toFile ))
200
			{
200
			{
201
				// now extract the matching file from the game dir
201
				// now extract the matching file from the game dir
202
				if ( m_fileSystem.ExtractGameFile(f-&gt;sFile, toFile + ".compare") )
202
				if (!m_fileSystem.extractGameFile(f-&gt;sFile, toFile + L".compare").empty() )
203
				{
203
				{
204
					diffFile(toFile + ".compare", toFile, f->sFile);
204
					diffFile(toFile + L".compare", toFile, f->sFile);
205
					CFileIO::Remove(toFile + ".compare");
205
					CFileIO::Remove(toFile + L".compare");
206
				}
206
				}
207
				// make sure we clear up afterwards
207
				// make sure we clear up afterwards
208
				CFileIO::Remove(toFile);
208
				CFileIO::Remove(toFile);
209
			}
209
			}
210
		}
210
		}
211
	}
211
	}
212
 
212
 
213
	return true;
213
	return true;
214
}
214
}
215
 
215
 
216
SDiffFile *CModDiff::diffFile(const Utils::String &baseFile, const Utils::String &modFile, const Utils::String &fileType)
216
SDiffFile *CModDiff::diffFile(const Utils::WString &baseFile, const Utils::WString &modFile, const Utils::WString &fileType)
217
{
217
{
218
	int type = 0;
218
	int type = 0;
219
 
219
 
220
	SDiffFile *diffFile = new SDiffFile;
220
	SDiffFile *diffFile = new SDiffFile;
221
	diffFile->sFile = fileType;
221
	diffFile->sFile = fileType;
Line 234... Line 234...
234
			node[0] = baseLines.begin();
234
			node[0] = baseLines.begin();
235
			node[1] = lines.begin();
235
			node[1] = lines.begin();
236
			std::vector<Utils::String>::iterator endNode[2];
236
			std::vector<Utils::String>::iterator endNode[2];
237
			endNode[0] = baseLines.end();
237
			endNode[0] = baseLines.end();
238
			endNode[1] = lines.end();
238
			endNode[1] = lines.end();
239
 
239
 
240
			Utils::String prev[2];
240
			Utils::String prev[2];
241
 
241
 
242
			while (node[0] != endNode[0] || node[1] != endNode[1])
242
			while (node[0] != endNode[0] || node[1] != endNode[1])
243
			{
243
			{
244
				Utils::String str[2];
244
				Utils::String str[2];
Line 267... Line 267...
267
					// first check for mismatch amount, one of the nodes will be empty
267
					// first check for mismatch amount, one of the nodes will be empty
268
					if ( str[0].empty() && !str[1].empty() ) // mod file has more entries (these must be additions)
268
					if ( str[0].empty() && !str[1].empty() ) // mod file has more entries (these must be additions)
269
					{
269
					{
270
						SDiffEntryAddition *entry = new SDiffEntryAddition;
270
						SDiffEntryAddition *entry = new SDiffEntryAddition;
271
						entry->iID = id;
271
						entry->iID = id;
272
						entry->sEntry = str[1];
272
						entry->sEntry = str[1].toWString();
273
						diffFile->m_lEntries.push_back(entry);
273
						diffFile->m_lEntries.push_back(entry);
274
					}
274
					}
275
					else if ( str[1].empty() && !str[0].empty() ) // mod file has less entries (must have removed some)
275
					else if ( str[1].empty() && !str[0].empty() ) // mod file has less entries (must have removed some)
276
					{
276
					{
277
						SDiffEntry *entry = new SDiffEntryRemoval;
277
						SDiffEntry *entry = new SDiffEntryRemoval;
Line 287... Line 287...
287
 
287
 
288
					++id;
288
					++id;
289
				}
289
				}
290
			}
290
			}
291
		}
291
		}
292
	}
292
	}
293
 
293
 
294
	if ( diffFile->m_lEntries.empty() ) {
294
	if ( diffFile->m_lEntries.empty() ) {
295
		delete diffFile;
295
		delete diffFile;
296
		return NULL;
296
		return NULL;
297
	}
297
	}
298
	else {
298
	else {
299
		m_lFiles.push_back(diffFile);
299
		m_lFiles.push_back(diffFile);
300
		return diffFile;
300
		return diffFile;
301
	}
301
	}
302
}
302
}
303
 
303
 
304
int CModDiff::_amountPosition(const Utils::String &fileType)
304
int CModDiff::_amountPosition(const Utils::WString &fileType)
305
{
305
{
306
	return 2;
306
	return 2;
307
}
307
}
308
 
308
 
309
bool CModDiff::_isLineComplete(const Utils::String &line, const Utils::String &fileType, bool first)
309
bool CModDiff::_isLineComplete(const Utils::WString &line, const Utils::WString &fileType, bool first)
310
{
310
{
311
	if ( first )
311
	if ( first )
312
	{
312
	{
313
		if ( line.countToken(";") > _amountPosition(fileType) ) return true;
313
		if ( line.countToken(L";") > _amountPosition(fileType) ) return true;
314
		return false;
314
		return false;
315
	}
315
	}
316
 
316
 
317
	return true;
317
	return true;
318
}
318
}
319
 
319
 
320
void CModDiff::_compareLine(const Utils::String &line1, const Utils::String &line2, int type, int id, SDiffFile *diffFile)
320
void CModDiff::_compareLine(const Utils::WString &line1, const Utils::WString &line2, int type, int id, SDiffFile *diffFile)
321
{
321
{
322
	int max1, max2;
322
	std::vector<Utils::WString> str1;
323
	Utils::String *str1 = line1.tokenise(";", &amp;max1);
323
	std::vector<Utils::WString&gt; str2;
324
	Utils::String *str2 = line2.tokenise(";", &max2);
324
	if (!line1.tokenise(L";", str1))
325
 
325
		return;
326
	if ( !str1 || !str2 ) return;
326
	if (!line2.tokenise(L";", str2))
-
 
327
		return;
327
 
328
 
328
	int max = ((max1 > max2) ? max2 : max1);
329
	size_t max = ((str1.size() > str2.size()) ? str2.size() : str1.size());
329
	for ( int i = 0; i < max; i++ )
330
	for (size_t i = 0; i < max; i++ )
330
	{
331
	{
331
		if ( str1[i] == str2[i] ) continue;
332
		if ( str1[i] == str2[i] ) continue;
332
		if ( str1[i].Compare(str2[i]) ) continue;
333
		if ( str1[i].Compare(str2[i]) ) continue;
333
		if ( str1[i].empty() && str2[i].empty() ) continue;
334
		if ( str1[i].empty() && str2[i].empty() ) continue;
334
		if ( str1[i].length() && str1[i][0] == '\0' && str2[i].length() && str2[i][0] == '\0' ) continue;
335
		if ( str1[i].length() && str1[i][0] == '\0' && str2[i].length() && str2[i][0] == '\0' ) continue;
Line 353... Line 354...
353
 
354
 
354
bool CModDiff::WriteDiff(const Utils::String &file)
355
bool CModDiff::WriteDiff(const Utils::String &file)
355
{
356
{
356
	if ( m_lFiles.empty() ) return false;
357
	if ( m_lFiles.empty() ) return false;
357
 
358
 
358
	Utils::CStringList lines;
359
	Utils::WStringList lines;
359
	
360
	
360
	for ( CListNode<SDiffFile> *node = m_lFiles.Front(); node; node = node->next() )
361
	for ( CListNode<SDiffFile> *node = m_lFiles.Front(); node; node = node->next() )
361
	{
362
	{
362
		lines.pushBack("$$" + node->Data()->sFile);
363
		lines.pushBack(L"$$" + node->Data()->sFile);
363
		for ( CListNode<SDiffEntry> *node2 = node->Data()->m_lEntries.Front(); node2; node2 = node2->next() )
364
		for ( CListNode<SDiffEntry> *node2 = node->Data()->m_lEntries.Front(); node2; node2 = node2->next() )
364
		{
365
		{
365
			switch(node2->Data()->iType)
366
			switch(node2->Data()->iType)
366
			{
367
			{
367
				case DIFFTYPE_ADDITION:
368
				case DIFFTYPE_ADDITION:
368
					lines.pushBack("+++:" + Utils::String::Number((long)node2->Data()->iID) + ":" + ((SDiffEntryAddition *)node2->Data())->sEntry);
369
					lines.pushBack(L"+++:" + Utils::WString::Number((long)node2->Data()->iID) + L":" + ((SDiffEntryAddition *)node2->Data())->sEntry);
369
					break;
370
					break;
370
				case DIFFTYPE_REMOVAL:
371
				case DIFFTYPE_REMOVAL:
371
					lines.pushBack("---:" + Utils::String::Number((long)node2->Data()->iID));
372
					lines.pushBack(L"---:" + Utils::WString::Number((long)node2->Data()->iID));
372
					break;
373
					break;
373
				case DIFFTYPE_CHANGE:
374
				case DIFFTYPE_CHANGE:
374
					lines.pushBack("///:" + Utils::String::Number((long)node2->Data()->iID) + ":" + Utils::String::Number((long)((SDiffEntryChange *)node2->Data())->iPos) + ":" + ((SDiffEntryChange *)node2->Data())->sEntry);
375
					lines.pushBack(L"///:" + Utils::WString::Number((long)node2->Data()->iID) + L":" + Utils::WString::Number((long)((SDiffEntryChange *)node2->Data())->iPos) + L":" + ((SDiffEntryChange *)node2->Data())->sEntry);
375
					break;
376
					break;
376
			}
377
			}
377
		}
378
		}
378
	}
379
	}
379
	
380
	
Line 397... Line 398...
397
		{
398
		{
398
			if (itr->left(2).Compare("$$") )
399
			if (itr->left(2).Compare("$$") )
399
			{
400
			{
400
				diffFile = new SDiffFile;
401
				diffFile = new SDiffFile;
401
				m_lFiles.push_back(diffFile);
402
				m_lFiles.push_back(diffFile);
402
				diffFile->sFile = itr->right(-2);
403
				diffFile->sFile = itr->right(-2).toWString();
403
			}
404
			}
404
			else if ( diffFile )
405
			else if ( diffFile )
405
			{
406
			{
406
				if ( itr->left(4).Compare("+++:") )
407
				if ( itr->left(4).Compare("+++:") )
407
				{
408
				{
408
					SDiffEntryAddition *addition = new SDiffEntryAddition;
409
					SDiffEntryAddition *addition = new SDiffEntryAddition;
409
					addition->iID = itr->token(":", 2).toInt();
410
					addition->iID = itr->token(":", 2).toInt();
410
					addition->sEntry = itr->tokens(":", 3);
411
					addition->sEntry = itr->tokens(":", 3).toWString();
411
					diffFile->m_lEntries.push_back(addition);
412
					diffFile->m_lEntries.push_back(addition);
412
				}
413
				}
413
				else if ( itr->left(4).Compare("---:") )
414
				else if ( itr->left(4).Compare("---:") )
414
				{
415
				{
415
					SDiffEntryRemoval *entry = new SDiffEntryRemoval;
416
					SDiffEntryRemoval *entry = new SDiffEntryRemoval;
Line 419... Line 420...
419
				else if (itr->left(4).Compare("///:") )
420
				else if (itr->left(4).Compare("///:") )
420
				{
421
				{
421
					SDiffEntryChange *entry = new SDiffEntryChange;
422
					SDiffEntryChange *entry = new SDiffEntryChange;
422
					entry->iID = itr->token(":", 2).toInt();
423
					entry->iID = itr->token(":", 2).toInt();
423
					entry->iPos = itr->token(":", 3).toInt();
424
					entry->iPos = itr->token(":", 3).toInt();
424
					entry->sEntry = itr->tokens(":", 4);
425
					entry->sEntry = itr->tokens(":", 4).toWString();
425
					diffFile->m_lEntries.push_back(entry);
426
					diffFile->m_lEntries.push_back(entry);
426
				}
427
				}
427
			}
428
			}
428
		}
429
		}
429
 
430
 
Line 444... Line 445...
444
 
445
 
445
	this->ApplyMod(mod);
446
	this->ApplyMod(mod);
446
 
447
 
447
	bool ret = false;
448
	bool ret = false;
448
 
449
 
449
	Utils::WString temp = m_sTempDir.toWString();
450
	Utils::WString temp = m_sTempDir;
450
	Utils::String addonDir = "";
451
	Utils::WString addonDir = L"";
451
 
452
 
452
	CCatFile cat;
453
	CCatFile cat;
453
	if ( !CCatFile::Opened(cat.open(mod, addonDir, CATREAD_CATDECRYPT, true)) )
454
	if ( !CCatFile::Opened(cat.open(mod, addonDir, CATREAD_CATDECRYPT, true)) )
454
		return false;
455
		return false;
455
 
456
 
456
	for ( CListNode<SDiffFile> *node = m_lFiles.Front(); node; node = node->next() )
457
	for ( CListNode<SDiffFile> *node = m_lFiles.Front(); node; node = node->next() )
457
	{
458
	{
458
		// extract the file from the game
459
		// extract the file from the game
459
		SDiffFile *f = node->Data();
460
		SDiffFile *f = node->Data();
460
 
461
 
461
		Utils::CStringList writeLines;
462
		Utils::WStringList writeLines;
462
		int id;
463
		int id;
463
		if ( _readGameFile(f->sFile, writeLines, &id) )
464
		if ( _readGameFile(f->sFile, writeLines, &id))
464
		{
465
		{
465
			// now apply the diff
466
			// now apply the diff
466
			this->_adjustFile(f->sFile, f, true);
467
			this->_adjustFile(f->sFile, f, true);
467
			for ( CListNode<SDiffEntry> *eNode = f->m_lEntries.Front(); eNode; eNode = eNode->next() )
468
			for ( CListNode<SDiffEntry> *eNode = f->m_lEntries.Front(); eNode; eNode = eNode->next() )
468
			{
469
			{
469
				switch ( eNode->Data()->iType )
470
				switch ( eNode->Data()->iType )
470
				{
471
				{
471
					case DIFFTYPE_ADDITION:
472
					case DIFFTYPE_ADDITION:
472
						writeLines.pushBack(((SDiffEntryAddition *)eNode->Data())->sEntry);
473
						writeLines.pushBack(((SDiffEntryAddition *)eNode->Data())->sEntry.toString());
473
						break;
474
						break;
474
					case DIFFTYPE_REMOVAL:
475
					case DIFFTYPE_REMOVAL:
475
						writeLines.removeAt(eNode->Data()->iID);
476
						writeLines.removeAt(eNode->Data()->iID);
476
						break;
477
						break;
477
					case DIFFTYPE_CHANGE:
478
					case DIFFTYPE_CHANGE:
478
						{
479
						{
479
							auto strAt = writeLines.get(eNode->Data()->iID);
480
							auto strAt = writeLines.get(eNode->Data()->iID);
480
							if ( strAt )
481
							if ( strAt )
481
								strAt->str = strAt->str.replaceToken(";", ((SDiffEntryChange *)eNode->Data())->iPos, ((SDiffEntryChange *)eNode->Data())->sEntry);
482
								strAt->str = strAt->str.replaceToken(L";", ((SDiffEntryChange *)eNode->Data())->iPos, ((SDiffEntryChange *)eNode->Data())->sEntry);
482
						}
483
						}
483
						break;
484
						break;
484
				}
485
				}
485
			}
486
			}
486
 
487
 
487
			// add our comments and info
488
			// add our comments and info
488
			writeLines.pushFront(Utils::String((long)id) + ";" + (long)writeLines.size() + ";");
489
			writeLines.pushFront(Utils::WString((long)id) + L";" + (long)writeLines.size() + L";");
489
			writeLines.pushFront("// Generated by ModDiff (SPK Version: " + Utils::String::FromFloat(GetLibraryVersion(), 2) + ")");
490
			writeLines.pushFront(L"// Generated by ModDiff (SPK Version: " + Utils::WString::FromFloat(GetLibraryVersion(), 2) + L")");
490
 
491
 
491
			// now write the file
492
			// now write the file
492
			CFileIO WriteFile(temp + L"/" + CFileIO(f->sFile).filename());
493
			CFileIO WriteFile(temp + L"/" + CFileIO(f->sFile).filename());
493
			if ( WriteFile.writeFile(&writeLines) )
494
			if ( WriteFile.writeFile(&writeLines) )
494
			{
495
			{
495
				if ( cat.appendFile(m_sTempDir + "/" + CFileIO(f->sFile).filenameStr(), f->sFile) )
496
				if ( cat.appendFile(m_sTempDir + L"/" + CFileIO(f->sFile).filename(), f->sFile) )
496
					ret = true;
497
					ret = true;
497
				WriteFile.remove();
498
				WriteFile.remove();
498
			}
499
			}
499
		}
500
		}
500
	}
501
	}
Line 503... Line 504...
503
		cat.WriteCatFile();
504
		cat.WriteCatFile();
504
 
505
 
505
	return ret;
506
	return ret;
506
}
507
}
507
 
508
 
508
bool CModDiff::_readGameFile(const Utils::String &file, Utils::CStringList &writeLines, int *id)
509
bool CModDiff::_readGameFile(const Utils::WString &file, Utils::WStringList &writeLines, int *id)
509
{
510
{
510
	bool ret = false;
511
	bool ret = false;
511
 
512
 
512
	Utils::String sTo = m_fileSystem.ExtractGameFile(file, m_sTempDir + "/" + CFileIO(file).filenameStr());
513
	Utils::WString sTo = m_fileSystem.extractGameFile(file, m_sTempDir + L"/" + CFileIO(file).filename());
513
	if ( !sTo.empty() ) {
514
	if ( !sTo.empty() ) {
514
		CFileIO File(sTo);
515
		CFileIO File(sTo);
515
 
516
 
516
		Utils::CStringList *lines = File.readLinesStr();
517
		std::vector<Utils::WString> lines;
517
		if ( lines )
518
		if(File.readLines(lines))
518
		{
519
		{
519
			int entries = -1;
520
			int entries = -1;
520
			for(auto itr = lines->begin(); itr != lines->end(); itr++)
521
			for(auto itr = lines.begin(); itr != lines.end(); itr++)
521
			{
522
			{
522
				Utils::String l = (*itr)->str;
523
				Utils::WString l = *itr;
523
				l.removeFirstSpace();
524
				l.removeFirstSpace();
524
				if ( l.empty() ) continue;
525
				if ( l.empty() ) continue;
525
				if ( l.left(1) == "/" ) continue;
526
				if ( l.left(1) == L"/" ) continue;
526
 
527
 
527
				if ( entries == -1 )
528
				if ( entries == -1 )
528
				{
529
				{
529
					entries = l.token(":", 2).toInt();
530
					entries = l.token(L":", 2).toInt();
530
					if ( id )
531
					if ( id )
531
						(*id) = l.token(":", 1).toInt();
532
						(*id) = l.token(L":", 1).toInt();
532
				}
533
				}
533
				else
534
				else
534
					writeLines.pushBack(l);
535
					writeLines.pushBack(l);
535
			}
536
			}
536
			delete lines;
-
 
537
			ret = true;
537
			ret = true;
538
		}
538
		}
539
		File.close();
539
		File.close();
540
		File.remove();
540
		File.remove();
541
	}
541
	}
542
 
542
 
543
	return ret;
543
	return ret;
544
}
544
}
545
 
545
 
546
 
546
 
547
bool CModDiff::_validFile(const Utils::String &file)
547
bool CModDiff::_validFile(const Utils::WString &file)
548
{
548
{
549
	return CModDiff::CanBeDiffed(file);
549
	return CModDiff::CanBeDiffed(file);
550
}
550
}
551
 
551
 
552
bool CModDiff::CanBeDiffed(const Utils::String &file)
552
bool CModDiff::CanBeDiffed(const Utils::WString &file)
553
{
553
{
554
	Utils::WString checkFile = file.toWString();
554
	Utils::WString checkFile = file;
555
	checkFile = CFileIO(file).dir() + L"/" + CFileIO(file).baseName();
555
	checkFile = CFileIO(file).dir() + L"/" + CFileIO(file).baseName();
556
 
556
 
557
	// all t files are the same format
557
	// all t files are the same format
558
	if ( checkFile.left(7).Compare(L"types/T") )
558
	if ( checkFile.left(7).Compare(L"types/T") )
559
		return true;
559
		return true;