Subversion Repositories spk

Rev

Rev 1 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
#include "MultiSpkFile.h"
2
#include "File.h"
3
#include "XspFile.h"
4
 
5
CMultiSpkFile::~CMultiSpkFile()
6
{
7
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
8
	{
9
		SMultiSpkFile *ms = node->Data();
10
		if ( !ms )
11
			continue;
12
 
13
		if ( ms->sData )
14
		{
15
			delete ms->sData;
16
			ms->sData = NULL;
17
		}
18
 
19
		if ( ms->pFile )
20
		{
21
			delete ms->pFile;
22
			ms->pFile = NULL;
23
		}
24
 
25
		node->DeleteData();
26
	}
27
}
28
 
29
void CMultiSpkFile::CreatePackage(SMultiSpkFile *p)
30
{
31
	if ( !p )
32
		return;
33
 
34
	if ( p->iType == TYPE_XSP )
35
		p->pFile = new CXspFile();
36
	else if ( p->iType == TYPE_SPK )
37
		p->pFile = new CSpkFile();
38
	else if ( p->iType == TYPE_BASE )
39
		p->pFile = new CBaseFile();
40
}
41
 
42
bool CMultiSpkFile::AddFileNow ( CyString file, bool on )
43
{
44
	if ( this->AddFile(file, on) )
45
	{
46
		CyString findFile = file;
47
		findFile = findFile.FindReplace ( "\\", "/" );
48
		findFile = findFile.GetToken ( findFile.NumToken('/'), '/' );
49
 
50
		SMultiSpkFile *p = this->FindFile(findFile);
51
		if ( p )
52
		{
53
			this->CreatePackage(p);
54
			if ( p->pFile->ReadFile ( file, SPKREAD_ALL ) )
55
				return true;
56
		}
57
	}
58
 
59
	return false;
60
}
61
 
62
bool CMultiSpkFile::AddFile(SMultiSpkFile *ms)
63
{
64
	bool found = false;
65
	// find if theres any files with the same filename
66
	CListNode<SMultiSpkFile> *node;
67
	for ( node = m_lFiles.Front(); node; node = node->next() )
68
	{
69
		SMultiSpkFile *it = node->Data();
70
		if ( it->sName.Compare(ms->sName) )
71
		{
72
			m_lFiles.remove ( it );
73
			found = true;
74
			delete it;
75
			break;
76
		}
77
	}
78
 
79
	// now find if theres a file with the same script/author
80
	for ( node = m_lFiles.Front(); node; node = node->next() )
81
	{
82
		SMultiSpkFile *it = node->Data();
83
		if ( (it->sScriptAuthor.Compare(ms->sScriptAuthor)) && (it->sScriptName.Compare(ms->sScriptName)) )
84
		{
85
			m_lFiles.remove ( it );
86
			found = true;
87
			delete it;
88
			break;
89
		}
90
	}
91
 
92
	m_lFiles.push_back ( ms );
93
 
94
	m_bChanged = true;
95
	return true;
96
}
97
bool CMultiSpkFile::AddFile ( CyString file, bool on )
98
{
99
	// multipack
100
	if ( file.IsIn ( "::" ) )
101
	{
102
		CyString mfile = file.Left ( file.FindPos("::") );
103
		CMultiSpkFile spkfile;
104
		if ( spkfile.ReadFile ( mfile, false ) )
105
		{
106
			SMultiSpkFile *ms = new SMultiSpkFile;
107
			ms->bRemove = false;
108
			ms->sName = file.Right ( (int)(file.Length() - file.FindPos("::")) - 2 );
109
			ms->pFile = NULL;
110
			ms->sData = NULL;
111
			if ( spkfile.ExtractData ( ms ) )
112
			{
113
				ms->bOn = on;
114
				AddFile(ms);
115
				return true;
116
			}
117
			delete ms;
118
		}
119
		return false;
120
	}
121
 
122
	// check its a valid file
123
	int check = CBaseFile::CheckFile ( file );
124
	if ( check == SPKFILE_MULTI )
125
	{
126
		CMultiSpkFile spkfile;
127
		if ( spkfile.ReadFile ( file, false ) )
128
		{
129
			CLinkList<SMultiSpkFile> *list = spkfile.GetFileList();
130
			for ( SMultiSpkFile *it = list->First(); it; it = list->Next() )
131
			{
132
				SMultiSpkFile *ms = new SMultiSpkFile;
133
				ms->bRemove = false;
134
				ms->sName = it->sName;
135
				ms->pFile = NULL;
136
				ms->sData = NULL;
137
				if ( spkfile.ExtractData ( ms ) )
138
				{
139
					ms->bOn = on;
140
					AddFile(ms);
141
				}
142
				else
143
					delete ms;
144
			}
145
			return true;
146
		}
147
		return false;
148
	}
149
	else if ( check != SPKFILE_SINGLE && check != SPKFILE_SINGLESHIP )
150
		return false;
151
 
152
	FILE *id = fopen ( file.c_str(), "rb" );
153
	if ( !id )
154
		return false;
155
 
156
	// create entry
157
	SMultiSpkFile *ms = new SMultiSpkFile;
158
	ms->bRemove = false;
159
	ms->pFile = NULL;
160
	ms->sName = file;
161
	ms->sName = ms->sName.FindReplace ( "\\", "/" );
162
	ms->sName = ms->sName.GetToken ( ms->sName.NumToken('/'), '/' );
163
	ms->bOn = on;
164
 
165
	// find file size
166
	fseek ( id, 0, SEEK_END );
167
	ms->lSize = ftell ( id );
168
	fseek ( id, 0, SEEK_SET );
169
 
170
	// read data
171
	ms->sData = new char[ms->lSize];
172
	fread ( ms->sData, sizeof(char), ms->lSize, id );
173
 
174
	fclose ( id );
175
 
176
	CBaseFile *baseFile = NULL;
177
	if ( check == SPKFILE_SINGLE )
178
		baseFile = new CSpkFile;
179
	else if ( check == SPKFILE_SINGLESHIP )
180
		baseFile = new CXspFile;
181
 
182
	if ( baseFile )
183
	{
184
		if ( baseFile->ReadFile(file, SPKREAD_VALUES) )
185
		{
186
			ms->sScriptAuthor	= baseFile->GetAuthor();
187
			ms->sScriptName		= baseFile->GetName();
188
			ms->sScriptVersion	= baseFile->GetVersion();
189
			ms->iType			= baseFile->GetType();
190
		}
191
 
192
		delete baseFile;
193
	}
194
 
195
	AddFile(ms);
196
 
197
	return true;
198
}
199
 
200
SMultiSpkFile *CMultiSpkFile::AddFileEntry ( CyString filename )
201
{
202
	SMultiSpkFile *ms = new SMultiSpkFile;
203
	ms->bRemove = false;
204
	ms->pFile = NULL;
205
	ms->sName = filename;
206
	ms->bOn = true;
207
	ms->iType = -1;
208
 
209
	m_lFiles.push_back ( ms );
210
	m_bChanged = true;
211
 
212
	return ms;
213
}
214
 
215
CyString CMultiSpkFile::CreateData ()
216
{
217
	CyString ret;
218
	if ( !m_sName.Empty() )
219
		ret = CyString("Name: ") + m_sName + "\n";
220
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
221
	{
222
		SMultiSpkFile *ms = node->Data();
223
		if ( ms->iType == TYPE_XSP )
224
			ret += "XspFile: ";
225
		else 
226
			ret += "SpkFile: ";
227
 
228
		if ( ms->bOn )
229
			ret += "1:";
230
		else
231
			ret += "0:";
232
		ret += ms->lSize;
233
		ret += ":";
234
		ret += ms->sName;
235
		if ( !ms->sScriptName.Empty() )
236
			ret += (CyString(":") + ms->sScriptName + "|" + ms->sScriptAuthor + "|" + ms->sScriptVersion);
237
		ret += "\n";
238
	}
239
 
240
	return ret;
241
}
242
 
243
bool CMultiSpkFile::WriteFile ( CyString filename, CProgressInfo *progress )
244
{
245
	FILE *id = fopen ( filename.c_str(), "wb" );
246
	if ( !id )
247
		return false;
248
 
249
	// make sure we remove all packages that have been marked
250
	this->RemovePackages();
251
 
252
	CyString data = CreateData ();
253
 
254
	int comprLen = (int)data.Length(), uncomprLen = comprLen;;
255
	unsigned char *compr = NULL;
256
 
257
	bool compressed = false;
258
	int valueheader = m_SHeader.iCompression;
259
	if ( valueheader == SPKCOMPRESS_7ZIP )
260
		valueheader = SPKCOMPRESS_ZLIB;
261
 
262
	if ( valueheader == SPKCOMPRESS_ZLIB )
263
	{
264
		comprLen = uncomprLen;	
265
		if ( comprLen < 100 )
266
			comprLen = 200;
267
		else if ( comprLen < 1000 )
268
			comprLen *= 2;
269
 
270
		compr = (unsigned char *)calloc((unsigned int)comprLen, 1);
271
		int err = compress ( (unsigned char *)compr, (unsigned long *)&comprLen, (const unsigned char *)data.c_str(), (unsigned long)data.Length(), 0 );
272
		if ( err == Z_OK )
273
			compressed = true;
274
	}
275
 
276
	if ( !compressed )
277
	{
278
		comprLen = uncomprLen;
279
		compr = (unsigned char *)calloc((unsigned int)comprLen, 1);
280
		memcpy ( compr, data.c_str(), comprLen );
281
		valueheader = SPKCOMPRESS_NONE;
282
	}
283
 
284
	// write the main header to the file
285
	fprintf ( id, "MSPKCycrow;%.2f;%d;%d;%d;%d\n", FILEVERSION, valueheader, data.Length(), comprLen, (m_SHeader.bSelection) ? 1 : 0 );
286
	if ( ferror(id) )
287
	{
288
		fclose ( id );
289
		return false;
290
	}
291
 
292
	// write the compressed data to file
293
	fputc ( (unsigned char)(uncomprLen >> 24), id ); 
294
	fputc ( (unsigned char)(uncomprLen >> 16), id ); 
295
	fputc ( (unsigned char)(uncomprLen >> 8), id ); 
296
	fputc ( (unsigned char)uncomprLen, id ); 
297
	fwrite ( compr, sizeof(char), comprLen, id );
298
 
299
	free ( compr );
300
 
301
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
302
	{
303
		SMultiSpkFile *ms = node->Data();
304
		if ( progress )
305
			progress->UpdatePackage(ms);
306
		if ( (!ms->sData) && (ms->pFile) )
307
			ms->pFile->WriteData ( id, NULL );
308
		else
309
			fwrite ( ms->sData, sizeof(char), ms->lSize, id );
310
	}
311
 
312
	fclose ( id );
313
 
314
	return true;
315
}
316
 
317
bool CMultiSpkFile::ParseHeader ( CyString header )
318
{
319
	if ( header.GetToken ( 1, ';' ) != "MSPKCycrow" )
320
		return false;
321
 
322
	m_SHeader.fVersion = header.GetToken ( 2, ';' ).ToFloat();
323
	if ( m_SHeader.fVersion > FILEVERSION )
324
		return false;
325
 
326
	m_SHeader.iCompression = header.GetToken ( 3, ';' ).ToInt();
327
	m_SHeader.lUncomprLen = header.GetToken ( 4, ';' ).ToLong();
328
	m_SHeader.lComprLen = header.GetToken ( 5, ';' ).ToLong();
329
	m_SHeader.bSelection = (header.GetToken ( 4, ';' ).ToInt()) ? true : false;
330
 
331
	return true;
332
}
333
 
334
bool CMultiSpkFile::ParseValueLine ( CyString line )
335
{
336
	CyString first = line.GetToken ( 1, ' ' );
337
	CyString rest  = line.GetToken ( 2, -1, ' ' );
338
 
339
	if ( first == "Name:" )
340
		m_sName = rest;
341
	else if ( first == "SpkFile:" )
342
	{
343
		SMultiSpkFile *ms = new SMultiSpkFile;
344
		ms->bRemove = false;
345
		ms->pFile = NULL;
346
		ms->bOn = (rest.GetToken ( 1, ':' ).ToInt()) ? true : false;
347
		ms->lSize = rest.GetToken ( 2, ':' ).ToLong();
348
		ms->sName = rest.GetToken ( 3, ':' );
349
		ms->sData = NULL;
350
		ms->iType = TYPE_SPK;
351
		CyString r = rest.GetToken ( 4, -1, ':' );
352
		if ( !r.Empty() )
353
		{
354
			ms->sScriptName = r.GetToken ( 1, '|' );
355
			ms->sScriptAuthor = r.GetToken ( 2, '|' );
356
			ms->sScriptVersion = r.GetToken ( 3, -1, '|' );
357
		}
358
		m_lFiles.push_back ( ms );
359
	}
360
	else if ( first == "XspFile:" )
361
	{
362
		SMultiSpkFile *ms = new SMultiSpkFile;
363
		ms->bRemove = false;
364
		ms->pFile = NULL;
365
		ms->bOn = (rest.GetToken ( 1, ':' ).ToInt()) ? true : false;
366
		ms->lSize = rest.GetToken ( 2, ':' ).ToLong();
367
		ms->sName = rest.GetToken ( 3, ':' );
368
		ms->sData = NULL;
369
		ms->iType = TYPE_XSP;
370
		CyString r = rest.GetToken ( 4, -1, ':' );
371
		if ( !r.Empty() )
372
		{
373
			ms->sScriptName = r.GetToken ( 1, '|' );
374
			ms->sScriptAuthor = r.GetToken ( 2, '|' );
375
			ms->sScriptVersion = r.GetToken ( 3, -1, '|' );
376
		}
377
		m_lFiles.push_back ( ms );
378
	}
379
	else if ( first == "BaseFile:" )
380
	{
381
		SMultiSpkFile *ms = new SMultiSpkFile;
382
		ms->bRemove = false;
383
		ms->pFile = NULL;
384
		ms->bOn = (rest.GetToken ( 1, ':' ).ToInt()) ? true : false;
385
		ms->lSize = rest.GetToken ( 2, ':' ).ToLong();
386
		ms->sName = rest.GetToken ( 3, ':' );
387
		ms->sData = NULL;
388
		ms->iType = TYPE_BASE;
389
		CyString r = rest.GetToken ( 4, -1, ':' );
390
		if ( !r.Empty() )
391
		{
392
			ms->sScriptName = r.GetToken ( 1, '|' );
393
			ms->sScriptAuthor = r.GetToken ( 2, '|' );
394
			ms->sScriptVersion = r.GetToken ( 3, -1, '|' );
395
		}
396
		m_lFiles.push_back ( ms );
397
	}
398
	else
399
		return false;
400
 
401
	return true;
402
}
403
 
404
void CMultiSpkFile::RemovePackages()
405
{
406
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
407
	{
408
		if ( !node->Data()->bRemove ) continue;
409
		node->DeleteData();
410
	}
411
 
412
	m_lFiles.RemoveEmpty();
413
}
414
 
415
void CMultiSpkFile::ReadValues ( CyString values )
416
{
417
	int num = 0;
418
	CyString *lines = values.SplitToken ( '\n', &num );
419
 
420
	for ( int i = 0; i < num; i++ )
421
		ParseValueLine ( lines[i] );
422
 
423
	CLEANSPLIT(lines, num);
424
}
425
 
426
bool CMultiSpkFile::ReadFile ( CyString filename, bool readdata )
427
{
428
	FILE *id = fopen ( filename.c_str(), "rb" );
429
	if ( !id )
430
		return false;
431
 
432
	// first read the header
433
	if ( !ParseHeader ( CSpkFile::GetEndOfLine ( id, NULL, false ) ) )
434
		return false;
435
 
436
	ClearFiles ();
437
 
438
	int doneLen = 0;
439
	// next read the data values for the spk files
440
	if ( m_SHeader.lComprLen )
441
	{
442
		// read data to memory
443
		unsigned char *readData = new unsigned char[m_SHeader.lComprLen + 1];
444
		unsigned char size[4];
445
		fread ( size, 4, 1, id );
446
		fread ( readData, sizeof(unsigned char), m_SHeader.lComprLen, id );
447
		unsigned long uncomprLen = (size[0] << 24) + (size[1] << 16) + (size[2] << 8) + size[3];
448
 
449
		// check for zlib compression
450
		if ( m_SHeader.iCompression == SPKCOMPRESS_ZLIB )
451
		{
452
			// uncomress the data
453
			unsigned char *uncompr = new unsigned char[uncomprLen];
454
 
455
			int err = uncompress ( uncompr, &uncomprLen, readData, m_SHeader.lComprLen );
456
			if ( err == Z_OK )
457
				ReadValues ( CyString ((char *)uncompr) );
458
			doneLen = uncomprLen;
459
			delete uncompr;
460
		}
461
		else if ( m_SHeader.iCompression == SPKCOMPRESS_7ZIP )
462
		{
463
			long len = uncomprLen;
464
			unsigned char *compr = LZMADecode_C ( readData, m_SHeader.lComprLen, (size_t *)&len, NULL );
465
			if ( compr )
466
				ReadValues ( CyString ((char *)compr) );
467
		}
468
		// no compression
469
		else
470
			ReadValues ( CyString ((char *)readData) );
471
 
472
		delete readData;
473
	}
474
 
475
	if ( readdata )
476
	{
477
		for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
478
		{
479
			SMultiSpkFile *ms = node->Data();
480
			ms->sData = new char[ms->lSize];
481
			fread ( ms->sData, sizeof(char), ms->lSize, id );
482
		}
483
	}
484
 
485
	m_sFilename = filename;
486
 
487
	fclose ( id );
488
	m_bChanged = false;
489
 
490
	return true;
491
}
492
 
493
unsigned int CMultiSpkFile::GetAvailableFiles()
494
{
495
	unsigned int size = 0;
496
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
497
	{
498
		if ( node->Data()->bRemove ) continue;
499
		++size;
500
	}
501
 
502
	return size;
503
}
504
 
505
unsigned long CMultiSpkFile::GetFileSize()
506
{
507
	unsigned int size = 0;
508
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
509
	{
510
		if ( node->Data()->bRemove ) continue;
511
		size += node->Data()->lSize;
512
	}
513
 
514
	return size;
515
}
516
 
517
void CMultiSpkFile::ClearFiles ()
518
{
519
	m_lFiles.clear(true);
520
}
521
 
522
bool CMultiSpkFile::ExtractData ( SMultiSpkFile *ms )
523
{
524
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
525
	if ( !id )
526
		return false;
527
 
528
	// skip past the header
529
	CSpkFile::GetEndOfLine ( id, NULL, false );
530
	// seek past the values
531
	fseek ( id, 4, SEEK_CUR );
532
	fseek ( id, m_SHeader.lComprLen, SEEK_CUR );
533
 
534
	bool found = false;
535
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
536
	{
537
		SMultiSpkFile *it = node->Data();
538
		if ( ms->sName.Compare(it->sName) )
539
		{
540
			ms->lSize = it->lSize;
541
			ms->sScriptAuthor = it->sScriptAuthor;
542
			ms->sScriptName = it->sScriptName;
543
			ms->sScriptVersion = it->sScriptVersion;
544
			ms->bOn = it->bOn;
545
			ms->iType = it->iType;
546
			ms->sData = new char[ms->lSize];
547
			if ( it->sData )
548
				memcpy ( ms->sData, it->sData, ms->lSize );
549
			else
550
				fread ( ms->sData, sizeof(char), ms->lSize, id );
551
			found = true;
552
			break;
553
		}
554
		else
555
			fseek ( id, it->lSize, SEEK_CUR );
556
	}
557
 
558
	fclose ( id );
559
	return found;
560
}
561
 
562
bool CMultiSpkFile::ReadFileToMemory ( SMultiSpkFile *ms )
563
{
564
	if ( ms->sData )
565
		return true;
566
 
567
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
568
	if ( !id )
569
		return false;
570
 
571
	// skip past the header
572
	CSpkFile::GetEndOfLine ( id, NULL, false );
573
	// seek past the values
574
	fseek ( id, 4, SEEK_CUR );
575
	fseek ( id, m_SHeader.lComprLen, SEEK_CUR );
576
 
577
	bool found = false;
578
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
579
	{
580
		SMultiSpkFile *it = node->Data();
581
		if ( it == ms )
582
		{
583
			ms->sData = new char[ms->lSize];
584
			fread ( ms->sData, sizeof(char), ms->lSize, id );
585
			found = true;
586
			break;
587
		}
588
		else
589
			fseek ( id, it->lSize, SEEK_CUR );
590
	}
591
 
592
	fclose ( id );
593
	return found;
594
}
595
 
596
bool CMultiSpkFile::ExtractFile ( const CyString &file, CyString dir )
597
{
598
	SMultiSpkFile *ms = FindFile(file);
599
	if ( !ms ) return false;
600
	return ExtractFile(ms, dir);
601
}
602
 
603
bool CMultiSpkFile::ExtractFile ( SMultiSpkFile *ms, CyString dir )
604
{
605
	if ( !ms->sData )
606
	{
607
		if ( !ReadFileToMemory ( ms ) )
608
			return false;
609
	}
610
 
611
	CyString filename = dir;
612
	if ( !dir.Empty() )
613
		filename += "/";
614
	filename += ms->sName;
615
 
616
	FILE *id = fopen ( filename.c_str(), "wb" );
617
	if ( !id )
618
		return false;
619
 
620
	fwrite ( ms->sData, sizeof(char), ms->lSize, id );
621
	fclose ( id );
622
 
623
	return true;
624
}
625
 
626
bool CMultiSpkFile::ExtractAll ( CyString dir )
627
{
628
	if ( m_sFilename.Empty() )
629
		return false;
630
 
631
	if ( !ReadAllFilesToMemory () )
632
		return false;
633
 
634
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
635
	{
636
		SMultiSpkFile *ms = node->Data();
637
		if ( ms->bRemove ) continue;
638
		if ( !ms->sData )
639
			continue;
640
 
641
		FILE *id = fopen ( CyString(dir + "/" + ms->sName).c_str(), "wb" );
642
		if ( !id )
643
			continue;
644
 
645
		fwrite ( ms->sData, sizeof(char), ms->lSize, id );
646
		fclose ( id );
647
	}
648
	return true;
649
}
650
 
651
bool CMultiSpkFile::SplitMulti ( CyString filename, CyString destdir )
652
{
653
	if ( !ReadFile ( filename ) )
654
		return false;
655
 
656
	bool doneone = false;
657
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
658
	{
659
		SMultiSpkFile *ms = node->Data();
660
		if ( ms->bRemove ) continue;
661
		if ( !ms->sData )
662
			continue;
663
 
664
		CyString destfile = destdir;
665
		if ( !destfile.Empty() )
666
			destfile += "/";
667
		destfile += ms->sName;
668
		FILE *id = fopen ( destfile.c_str(), "wb" );
669
		if ( !id )
670
			continue;
671
 
672
		fwrite ( ms->sData, sizeof(char), ms->lSize, id );
673
		fclose ( id );
674
		doneone = true;
675
	}
676
 
677
	return doneone;
678
}
679
 
680
bool CMultiSpkFile::ReadAllFilesToMemory (CProgressInfo *progress)
681
{
682
	// no file to read from
683
	if ( m_sFilename.Empty() )
684
		return false;
685
 
686
	// now open the file
687
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
688
	if ( !id )
689
		return false;
690
 
691
	// read the header
692
	CSpkFile::GetEndOfLine ( id, NULL, false );
693
	// skip past values
694
	fseek ( id, 4, SEEK_CUR );
695
	fseek ( id, m_SHeader.lComprLen, SEEK_CUR );
696
 
697
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
698
	{
699
		SMultiSpkFile *ms = node->Data();
700
		if ( ms->bRemove ) continue;
701
		if ( progress )
702
			progress->UpdatePackage(ms);
703
		if ( !ms->sData )
704
		{
705
			ms->sData = new char[ms->lSize];
706
			fread ( ms->sData, sizeof(char), ms->lSize, id );
707
		}
708
		else
709
			fseek ( id, ms->lSize, SEEK_CUR );
710
	}
711
 
712
	return true;
713
}
714
 
715
bool CMultiSpkFile::RemoveFile ( CyString file )
716
{
717
	int num = 0;
718
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
719
	{
720
		SMultiSpkFile *it = node->Data();
721
		if ( file.Compare(it->sName) )
722
			return RemoveFile ( num );
723
		++num;
724
	}
725
	return false;
726
}
727
 
728
bool CMultiSpkFile::RemoveFile ( SMultiSpkFile *ms )
729
{
730
	int num = 0;
731
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
732
	{
733
		SMultiSpkFile *it = node->Data();
734
		if ( it == ms )
735
			return RemoveFile ( num );
736
		++num;
737
	}
738
	return false;
739
}
740
 
741
bool CMultiSpkFile::RemoveFile ( int id )
742
{
743
	if ( (id < 0) || (id >= m_lFiles.size()) )
744
		return false;
745
 
746
	SMultiSpkFile *file = m_lFiles.Get ( id );
747
	m_lFiles.erase ( id + 1 );
748
 
749
	if ( file )
750
		delete file;
751
 
752
	m_bChanged = true;
753
	return true;
754
}
755
 
756
bool CMultiSpkFile::MarkRemoveFile ( CyString file )
757
{
758
	int num = 0;
759
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
760
	{
761
		SMultiSpkFile *it = node->Data();
762
		if ( file.Compare(it->sName) )
763
			return MarkRemoveFile ( num );
764
		num++;
765
	}
766
	return false;
767
}
768
 
769
bool CMultiSpkFile::MarkRemoveFile ( SMultiSpkFile *ms )
770
{
771
	int num = 0;
772
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
773
	{
774
		SMultiSpkFile *it = node->Data();
775
		if ( it == ms )
776
			return MarkRemoveFile ( num );
777
		++num;
778
	}
779
	return false;
780
}
781
 
782
bool CMultiSpkFile::MarkRemoveFile ( int id )
783
{
784
	if ( (id < 0) || (id >= m_lFiles.size()) )
785
		return false;
786
 
787
	SMultiSpkFile *file = m_lFiles.Get ( id );
788
	file->bRemove = true;
789
	m_bChanged = true;
790
	return true;
791
}
792
 
793
void CMultiSpkFile::MarkRemoveAll()
794
{
795
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
796
		node->Data()->bRemove = true;
797
	m_bChanged = true;
798
}
799
 
800
 
801
bool CMultiSpkFile::ReadSpk( SMultiSpkFile *ms, int type )
802
{
803
	if ( ms->pFile->IsFullyLoaded() )
804
		return true;
805
 
806
	// no file to read from
807
	if ( m_sFilename.Empty() )
808
		return false;
809
 
810
	// now open the file
811
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
812
	if ( !id )
813
		return false;
814
 
815
	// read the header
816
	CSpkFile::GetEndOfLine ( id, NULL, false );
817
	// skip past values
818
	fseek ( id, 4, SEEK_CUR );
819
	fseek ( id, m_SHeader.lComprLen, SEEK_CUR );
820
 
821
	bool ret = false;
822
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
823
	{
824
		SMultiSpkFile *it = node->Data();
825
		if ( it == ms )
826
		{
827
			if ( !ms->pFile )
828
			{
829
				if ( ms->iType == TYPE_XSP )
830
					ms->pFile = new CXspFile;
831
				else
832
					ms->pFile = new CSpkFile;
833
			}
834
			ret = it->pFile->ReadFile ( id, type, NULL );
835
			break;
836
		}
837
		else
838
			fseek ( id, it->lSize, SEEK_CUR );
839
	}
840
 
841
	fclose ( id );
842
 
843
	return ret;
844
}
845
 
846
bool CMultiSpkFile::ReadAllPackages( int type, CLinkList<CBaseFile> *addToList )
847
{
848
	// no file to read from
849
	if ( m_sFilename.Empty() )
850
		return false;
851
 
852
	// now open the file
853
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
854
	if ( !id )
855
		return false;
856
 
857
	// read the header
858
	CSpkFile::GetEndOfLine ( id, NULL, false );
859
	// skip past values
860
	fseek ( id, 4, SEEK_CUR );
861
	fseek ( id, m_SHeader.lComprLen, SEEK_CUR );
862
 
863
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
864
	{
865
		SMultiSpkFile *ms = node->Data();
866
		CBaseFile *package = NULL;
867
		if ( ms->iType == TYPE_XSP )
868
			package = new CXspFile;
869
		else
870
			package = new CSpkFile;
871
 
872
		if ( !addToList )
873
		{
874
			if ( ms->pFile )
875
			{
876
				delete package;
877
				package = ms->pFile;
878
			}
879
		}
880
 
881
		if ( !package->IsFullyLoaded() )
882
		{
883
			long tell = ftell ( id );
884
			package->ReadFile ( id, type, NULL );
885
 
886
			if ( addToList )
887
			{
888
				addToList->push_back(package);
889
				package->SetEnabled(ms->bOn);
890
			}
891
			else if ( package )
892
				ms->pFile = package;
893
 
894
			// move to correct position in file for next stream of data
895
			// should be fine, this is more of a failsafe
896
			rewind ( id );
897
			fseek ( id, tell, SEEK_CUR );
898
		}
899
		fseek ( id, ms->lSize, SEEK_CUR );
900
	}
901
 
902
	fclose ( id );
903
 
904
	return true;
905
}
906
 
907
 
908
SMultiSpkFile *CMultiSpkFile::FindFile ( CyString name )
909
{
910
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
911
	{
912
		SMultiSpkFile *ms = node->Data();
913
		if ( ms->sName.Compare(name) )
914
			return ms;
915
	}
916
	return NULL;
917
}
918
 
919
void CMultiSpkFile::UpdatedPackage(CBaseFile *p)
920
{
921
	SMultiSpkFile *s = this->FindPackage(p);
922
	if ( s )
923
	{
924
		if ( s->sData )
925
			delete s->sData;
926
		s->sData = (char *)p->CreateData((size_t*)&s->lSize);
927
	}
928
}
929
 
930
SMultiSpkFile *CMultiSpkFile::FindPackage(CBaseFile *p)
931
{
932
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
933
	{
934
		SMultiSpkFile *ms = node->Data();
935
		if ( ms->pFile == p )
936
			return ms;
937
	}
938
 
939
	return NULL;
940
}
941
 
942
SMultiSpkFile *CMultiSpkFile::FindPackage(CyString name, CyString author)
943
{
944
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
945
	{
946
		SMultiSpkFile *ms = node->Data();
947
		if ( !ms->pFile )
948
			continue;
949
 
950
		if ( ms->pFile->GetName().Compare(name) && ms->pFile->GetAuthor().Compare(author) )
951
			return ms;
952
	}
953
 
954
	return NULL;
955
}