Subversion Repositories spk

Rev

Rev 51 | Rev 56 | Go to most recent revision | 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
		{
50 cycrow 186
			ms->sScriptAuthor	= baseFile->author();
187
			ms->sScriptName		= baseFile->name();
188
			ms->sScriptVersion	= baseFile->version();
1 cycrow 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
{
52 cycrow 245
	CFileIO File(filename);
246
	if ( !File.startWrite() ) return false;
1 cycrow 247
 
248
	// make sure we remove all packages that have been marked
249
	this->RemovePackages();
250
 
251
	CyString data = CreateData ();
252
 
253
	int comprLen = (int)data.Length(), uncomprLen = comprLen;;
254
	unsigned char *compr = NULL;
255
 
256
	bool compressed = false;
257
	int valueheader = m_SHeader.iCompression;
258
	if ( valueheader == SPKCOMPRESS_7ZIP )
259
		valueheader = SPKCOMPRESS_ZLIB;
260
 
261
	if ( valueheader == SPKCOMPRESS_ZLIB )
262
	{
263
		comprLen = uncomprLen;	
264
		if ( comprLen < 100 )
265
			comprLen = 200;
266
		else if ( comprLen < 1000 )
267
			comprLen *= 2;
268
 
269
		compr = (unsigned char *)calloc((unsigned int)comprLen, 1);
270
		int err = compress ( (unsigned char *)compr, (unsigned long *)&comprLen, (const unsigned char *)data.c_str(), (unsigned long)data.Length(), 0 );
271
		if ( err == Z_OK )
272
			compressed = true;
273
	}
274
 
275
	if ( !compressed )
276
	{
277
		comprLen = uncomprLen;
278
		compr = (unsigned char *)calloc((unsigned int)comprLen, 1);
279
		memcpy ( compr, data.c_str(), comprLen );
280
		valueheader = SPKCOMPRESS_NONE;
281
	}
282
 
283
	// write the main header to the file
52 cycrow 284
	if ( !File.write("MSPKCycrow;%.2f;%d;%d;%d;%d\n", FILEVERSION, valueheader, data.Length(), comprLen, (m_SHeader.bSelection) ? 1 : 0) ) return false;
1 cycrow 285
 
286
	// write the compressed data to file
52 cycrow 287
	File.writeSize(uncomprLen);
288
	File.write(compr, comprLen);
1 cycrow 289
	free ( compr );
290
 
52 cycrow 291
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() ) {
1 cycrow 292
		SMultiSpkFile *ms = node->Data();
293
		if ( progress )
294
			progress->UpdatePackage(ms);
295
		if ( (!ms->sData) && (ms->pFile) )
52 cycrow 296
			ms->pFile->WriteData(File, NULL);
1 cycrow 297
		else
52 cycrow 298
			File.write(ms->sData, ms->lSize);
1 cycrow 299
	}
300
 
301
	return true;
302
}
303
 
304
bool CMultiSpkFile::ParseHeader ( CyString header )
305
{
306
	if ( header.GetToken ( 1, ';' ) != "MSPKCycrow" )
307
		return false;
308
 
309
	m_SHeader.fVersion = header.GetToken ( 2, ';' ).ToFloat();
310
	if ( m_SHeader.fVersion > FILEVERSION )
311
		return false;
312
 
313
	m_SHeader.iCompression = header.GetToken ( 3, ';' ).ToInt();
314
	m_SHeader.lUncomprLen = header.GetToken ( 4, ';' ).ToLong();
315
	m_SHeader.lComprLen = header.GetToken ( 5, ';' ).ToLong();
316
	m_SHeader.bSelection = (header.GetToken ( 4, ';' ).ToInt()) ? true : false;
317
 
318
	return true;
319
}
320
 
321
bool CMultiSpkFile::ParseValueLine ( CyString line )
322
{
323
	CyString first = line.GetToken ( 1, ' ' );
324
	CyString rest  = line.GetToken ( 2, -1, ' ' );
325
 
326
	if ( first == "Name:" )
327
		m_sName = rest;
328
	else if ( first == "SpkFile:" )
329
	{
330
		SMultiSpkFile *ms = new SMultiSpkFile;
331
		ms->bRemove = false;
332
		ms->pFile = NULL;
333
		ms->bOn = (rest.GetToken ( 1, ':' ).ToInt()) ? true : false;
334
		ms->lSize = rest.GetToken ( 2, ':' ).ToLong();
335
		ms->sName = rest.GetToken ( 3, ':' );
336
		ms->sData = NULL;
337
		ms->iType = TYPE_SPK;
338
		CyString r = rest.GetToken ( 4, -1, ':' );
339
		if ( !r.Empty() )
340
		{
341
			ms->sScriptName = r.GetToken ( 1, '|' );
342
			ms->sScriptAuthor = r.GetToken ( 2, '|' );
343
			ms->sScriptVersion = r.GetToken ( 3, -1, '|' );
344
		}
345
		m_lFiles.push_back ( ms );
346
	}
347
	else if ( first == "XspFile:" )
348
	{
349
		SMultiSpkFile *ms = new SMultiSpkFile;
350
		ms->bRemove = false;
351
		ms->pFile = NULL;
352
		ms->bOn = (rest.GetToken ( 1, ':' ).ToInt()) ? true : false;
353
		ms->lSize = rest.GetToken ( 2, ':' ).ToLong();
354
		ms->sName = rest.GetToken ( 3, ':' );
355
		ms->sData = NULL;
356
		ms->iType = TYPE_XSP;
357
		CyString r = rest.GetToken ( 4, -1, ':' );
358
		if ( !r.Empty() )
359
		{
360
			ms->sScriptName = r.GetToken ( 1, '|' );
361
			ms->sScriptAuthor = r.GetToken ( 2, '|' );
362
			ms->sScriptVersion = r.GetToken ( 3, -1, '|' );
363
		}
364
		m_lFiles.push_back ( ms );
365
	}
366
	else if ( first == "BaseFile:" )
367
	{
368
		SMultiSpkFile *ms = new SMultiSpkFile;
369
		ms->bRemove = false;
370
		ms->pFile = NULL;
371
		ms->bOn = (rest.GetToken ( 1, ':' ).ToInt()) ? true : false;
372
		ms->lSize = rest.GetToken ( 2, ':' ).ToLong();
373
		ms->sName = rest.GetToken ( 3, ':' );
374
		ms->sData = NULL;
375
		ms->iType = TYPE_BASE;
376
		CyString r = rest.GetToken ( 4, -1, ':' );
377
		if ( !r.Empty() )
378
		{
379
			ms->sScriptName = r.GetToken ( 1, '|' );
380
			ms->sScriptAuthor = r.GetToken ( 2, '|' );
381
			ms->sScriptVersion = r.GetToken ( 3, -1, '|' );
382
		}
383
		m_lFiles.push_back ( ms );
384
	}
385
	else
386
		return false;
387
 
388
	return true;
389
}
390
 
391
void CMultiSpkFile::RemovePackages()
392
{
393
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
394
	{
395
		if ( !node->Data()->bRemove ) continue;
396
		node->DeleteData();
397
	}
398
 
399
	m_lFiles.RemoveEmpty();
400
}
401
 
402
void CMultiSpkFile::ReadValues ( CyString values )
403
{
404
	int num = 0;
405
	CyString *lines = values.SplitToken ( '\n', &num );
406
 
407
	for ( int i = 0; i < num; i++ )
408
		ParseValueLine ( lines[i] );
409
 
410
	CLEANSPLIT(lines, num);
411
}
412
 
413
bool CMultiSpkFile::ReadFile ( CyString filename, bool readdata )
414
{
415
	FILE *id = fopen ( filename.c_str(), "rb" );
416
	if ( !id )
417
		return false;
418
 
419
	// first read the header
420
	if ( !ParseHeader ( CSpkFile::GetEndOfLine ( id, NULL, false ) ) )
421
		return false;
422
 
423
	ClearFiles ();
424
 
425
	int doneLen = 0;
426
	// next read the data values for the spk files
427
	if ( m_SHeader.lComprLen )
428
	{
429
		// read data to memory
430
		unsigned char *readData = new unsigned char[m_SHeader.lComprLen + 1];
431
		unsigned char size[4];
432
		fread ( size, 4, 1, id );
433
		fread ( readData, sizeof(unsigned char), m_SHeader.lComprLen, id );
434
		unsigned long uncomprLen = (size[0] << 24) + (size[1] << 16) + (size[2] << 8) + size[3];
435
 
436
		// check for zlib compression
437
		if ( m_SHeader.iCompression == SPKCOMPRESS_ZLIB )
438
		{
439
			// uncomress the data
440
			unsigned char *uncompr = new unsigned char[uncomprLen];
441
 
442
			int err = uncompress ( uncompr, &uncomprLen, readData, m_SHeader.lComprLen );
443
			if ( err == Z_OK )
444
				ReadValues ( CyString ((char *)uncompr) );
445
			doneLen = uncomprLen;
446
			delete uncompr;
447
		}
448
		else if ( m_SHeader.iCompression == SPKCOMPRESS_7ZIP )
449
		{
450
			long len = uncomprLen;
451
			unsigned char *compr = LZMADecode_C ( readData, m_SHeader.lComprLen, (size_t *)&len, NULL );
452
			if ( compr )
453
				ReadValues ( CyString ((char *)compr) );
454
		}
455
		// no compression
456
		else
457
			ReadValues ( CyString ((char *)readData) );
458
 
459
		delete readData;
460
	}
461
 
462
	if ( readdata )
463
	{
464
		for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
465
		{
466
			SMultiSpkFile *ms = node->Data();
467
			ms->sData = new char[ms->lSize];
468
			fread ( ms->sData, sizeof(char), ms->lSize, id );
469
		}
470
	}
471
 
472
	m_sFilename = filename;
473
 
474
	fclose ( id );
475
	m_bChanged = false;
476
 
477
	return true;
478
}
479
 
480
unsigned int CMultiSpkFile::GetAvailableFiles()
481
{
482
	unsigned int size = 0;
483
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
484
	{
485
		if ( node->Data()->bRemove ) continue;
486
		++size;
487
	}
488
 
489
	return size;
490
}
491
 
492
unsigned long CMultiSpkFile::GetFileSize()
493
{
494
	unsigned int size = 0;
495
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
496
	{
497
		if ( node->Data()->bRemove ) continue;
498
		size += node->Data()->lSize;
499
	}
500
 
501
	return size;
502
}
503
 
504
void CMultiSpkFile::ClearFiles ()
505
{
506
	m_lFiles.clear(true);
507
}
508
 
509
bool CMultiSpkFile::ExtractData ( SMultiSpkFile *ms )
510
{
511
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
512
	if ( !id )
513
		return false;
514
 
515
	// skip past the header
516
	CSpkFile::GetEndOfLine ( id, NULL, false );
517
	// seek past the values
518
	fseek ( id, 4, SEEK_CUR );
519
	fseek ( id, m_SHeader.lComprLen, SEEK_CUR );
520
 
521
	bool found = false;
522
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
523
	{
524
		SMultiSpkFile *it = node->Data();
525
		if ( ms->sName.Compare(it->sName) )
526
		{
527
			ms->lSize = it->lSize;
528
			ms->sScriptAuthor = it->sScriptAuthor;
529
			ms->sScriptName = it->sScriptName;
530
			ms->sScriptVersion = it->sScriptVersion;
531
			ms->bOn = it->bOn;
532
			ms->iType = it->iType;
533
			ms->sData = new char[ms->lSize];
534
			if ( it->sData )
535
				memcpy ( ms->sData, it->sData, ms->lSize );
536
			else
537
				fread ( ms->sData, sizeof(char), ms->lSize, id );
538
			found = true;
539
			break;
540
		}
541
		else
542
			fseek ( id, it->lSize, SEEK_CUR );
543
	}
544
 
545
	fclose ( id );
546
	return found;
547
}
548
 
549
bool CMultiSpkFile::ReadFileToMemory ( SMultiSpkFile *ms )
550
{
551
	if ( ms->sData )
552
		return true;
553
 
554
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
555
	if ( !id )
556
		return false;
557
 
558
	// skip past the header
559
	CSpkFile::GetEndOfLine ( id, NULL, false );
560
	// seek past the values
561
	fseek ( id, 4, SEEK_CUR );
562
	fseek ( id, m_SHeader.lComprLen, SEEK_CUR );
563
 
564
	bool found = false;
565
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
566
	{
567
		SMultiSpkFile *it = node->Data();
568
		if ( it == ms )
569
		{
570
			ms->sData = new char[ms->lSize];
571
			fread ( ms->sData, sizeof(char), ms->lSize, id );
572
			found = true;
573
			break;
574
		}
575
		else
576
			fseek ( id, it->lSize, SEEK_CUR );
577
	}
578
 
579
	fclose ( id );
580
	return found;
581
}
582
 
583
bool CMultiSpkFile::ExtractFile ( const CyString &file, CyString dir )
584
{
585
	SMultiSpkFile *ms = FindFile(file);
586
	if ( !ms ) return false;
587
	return ExtractFile(ms, dir);
588
}
589
 
590
bool CMultiSpkFile::ExtractFile ( SMultiSpkFile *ms, CyString dir )
591
{
592
	if ( !ms->sData )
593
	{
594
		if ( !ReadFileToMemory ( ms ) )
595
			return false;
596
	}
597
 
598
	CyString filename = dir;
599
	if ( !dir.Empty() )
600
		filename += "/";
601
	filename += ms->sName;
602
 
603
	FILE *id = fopen ( filename.c_str(), "wb" );
604
	if ( !id )
605
		return false;
606
 
607
	fwrite ( ms->sData, sizeof(char), ms->lSize, id );
608
	fclose ( id );
609
 
610
	return true;
611
}
612
 
613
bool CMultiSpkFile::ExtractAll ( CyString dir )
614
{
615
	if ( m_sFilename.Empty() )
616
		return false;
617
 
618
	if ( !ReadAllFilesToMemory () )
619
		return false;
620
 
621
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
622
	{
623
		SMultiSpkFile *ms = node->Data();
624
		if ( ms->bRemove ) continue;
625
		if ( !ms->sData )
626
			continue;
627
 
628
		FILE *id = fopen ( CyString(dir + "/" + ms->sName).c_str(), "wb" );
629
		if ( !id )
630
			continue;
631
 
632
		fwrite ( ms->sData, sizeof(char), ms->lSize, id );
633
		fclose ( id );
634
	}
635
	return true;
636
}
637
 
638
bool CMultiSpkFile::SplitMulti ( CyString filename, CyString destdir )
639
{
640
	if ( !ReadFile ( filename ) )
641
		return false;
642
 
643
	bool doneone = false;
644
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
645
	{
646
		SMultiSpkFile *ms = node->Data();
647
		if ( ms->bRemove ) continue;
648
		if ( !ms->sData )
649
			continue;
650
 
651
		CyString destfile = destdir;
652
		if ( !destfile.Empty() )
653
			destfile += "/";
654
		destfile += ms->sName;
655
		FILE *id = fopen ( destfile.c_str(), "wb" );
656
		if ( !id )
657
			continue;
658
 
659
		fwrite ( ms->sData, sizeof(char), ms->lSize, id );
660
		fclose ( id );
661
		doneone = true;
662
	}
663
 
664
	return doneone;
665
}
666
 
667
bool CMultiSpkFile::ReadAllFilesToMemory (CProgressInfo *progress)
668
{
669
	// no file to read from
670
	if ( m_sFilename.Empty() )
671
		return false;
672
 
673
	// now open the file
674
	FILE *id = fopen ( m_sFilename.c_str(), "rb" );
675
	if ( !id )
676
		return false;
677
 
678
	// read the header
679
	CSpkFile::GetEndOfLine ( id, NULL, false );
680
	// skip past values
681
	fseek ( id, 4, SEEK_CUR );
682
	fseek ( id, m_SHeader.lComprLen, SEEK_CUR );
683
 
684
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
685
	{
686
		SMultiSpkFile *ms = node->Data();
687
		if ( ms->bRemove ) continue;
688
		if ( progress )
689
			progress->UpdatePackage(ms);
690
		if ( !ms->sData )
691
		{
692
			ms->sData = new char[ms->lSize];
693
			fread ( ms->sData, sizeof(char), ms->lSize, id );
694
		}
695
		else
696
			fseek ( id, ms->lSize, SEEK_CUR );
697
	}
698
 
699
	return true;
700
}
701
 
702
bool CMultiSpkFile::RemoveFile ( CyString file )
703
{
704
	int num = 0;
705
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
706
	{
707
		SMultiSpkFile *it = node->Data();
708
		if ( file.Compare(it->sName) )
709
			return RemoveFile ( num );
710
		++num;
711
	}
712
	return false;
713
}
714
 
715
bool CMultiSpkFile::RemoveFile ( SMultiSpkFile *ms )
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 ( it == ms )
722
			return RemoveFile ( num );
723
		++num;
724
	}
725
	return false;
726
}
727
 
728
bool CMultiSpkFile::RemoveFile ( int id )
729
{
730
	if ( (id < 0) || (id >= m_lFiles.size()) )
731
		return false;
732
 
733
	SMultiSpkFile *file = m_lFiles.Get ( id );
734
	m_lFiles.erase ( id + 1 );
735
 
736
	if ( file )
737
		delete file;
738
 
739
	m_bChanged = true;
740
	return true;
741
}
742
 
743
bool CMultiSpkFile::MarkRemoveFile ( CyString file )
744
{
745
	int num = 0;
746
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
747
	{
748
		SMultiSpkFile *it = node->Data();
749
		if ( file.Compare(it->sName) )
750
			return MarkRemoveFile ( num );
751
		num++;
752
	}
753
	return false;
754
}
755
 
756
bool CMultiSpkFile::MarkRemoveFile ( SMultiSpkFile *ms )
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 ( it == ms )
763
			return MarkRemoveFile ( num );
764
		++num;
765
	}
766
	return false;
767
}
768
 
769
bool CMultiSpkFile::MarkRemoveFile ( int id )
770
{
771
	if ( (id < 0) || (id >= m_lFiles.size()) )
772
		return false;
773
 
774
	SMultiSpkFile *file = m_lFiles.Get ( id );
775
	file->bRemove = true;
776
	m_bChanged = true;
777
	return true;
778
}
779
 
780
void CMultiSpkFile::MarkRemoveAll()
781
{
782
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
783
		node->Data()->bRemove = true;
784
	m_bChanged = true;
785
}
786
 
787
 
788
bool CMultiSpkFile::ReadSpk( SMultiSpkFile *ms, int type )
789
{
790
	if ( ms->pFile->IsFullyLoaded() )
791
		return true;
792
 
793
	// no file to read from
794
	if ( m_sFilename.Empty() )
795
		return false;
796
 
797
	// now open the file
51 cycrow 798
	std::fstream stream(m_sFilename.ToString().c_str(), std::ios::in | std::ios::binary);
799
	if ( !stream.is_open() ) return false;
1 cycrow 800
 
801
	// read the header
51 cycrow 802
	CBaseFile::readEndOfLine(stream, NULL, false);
1 cycrow 803
	// skip past values
51 cycrow 804
	stream.seekg(4 + m_SHeader.lComprLen, std::ios::cur);
1 cycrow 805
 
806
	bool ret = false;
51 cycrow 807
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() ) {
1 cycrow 808
		SMultiSpkFile *it = node->Data();
809
		if ( it == ms )
810
		{
811
			if ( !ms->pFile )
812
			{
813
				if ( ms->iType == TYPE_XSP )
814
					ms->pFile = new CXspFile;
815
				else
816
					ms->pFile = new CSpkFile;
817
			}
51 cycrow 818
			ret = it->pFile->readFile(stream, type, NULL);
1 cycrow 819
			break;
820
		}
821
		else
51 cycrow 822
			stream.seekg(it->lSize, std::ios::cur);
1 cycrow 823
	}
824
 
51 cycrow 825
	stream.clear();
1 cycrow 826
	return ret;
827
}
828
 
829
bool CMultiSpkFile::ReadAllPackages( int type, CLinkList<CBaseFile> *addToList )
830
{
831
	// no file to read from
832
	if ( m_sFilename.Empty() )
833
		return false;
834
 
835
	// now open the file
51 cycrow 836
	std::fstream stream(m_sFilename.ToString().c_str(), std::ios::in | std::ios::binary);
837
	if ( !stream.is_open() ) return false;
1 cycrow 838
 
839
	// read the header
51 cycrow 840
	CBaseFile::readEndOfLine(stream, NULL, false);
1 cycrow 841
	// skip past values
51 cycrow 842
	stream.seekg(4 + m_SHeader.lComprLen, std::ios::cur);
1 cycrow 843
 
51 cycrow 844
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() ) {
1 cycrow 845
		SMultiSpkFile *ms = node->Data();
846
		CBaseFile *package = NULL;
847
		if ( ms->iType == TYPE_XSP )
848
			package = new CXspFile;
849
		else
850
			package = new CSpkFile;
851
 
51 cycrow 852
		if ( !addToList ) {
853
			if ( ms->pFile ) {
1 cycrow 854
				delete package;
855
				package = ms->pFile;
856
			}
857
		}
858
 
51 cycrow 859
		if ( !package->IsFullyLoaded() ) {
860
			long tell = stream.tellg();
861
			package->readFile(stream, type, NULL);
1 cycrow 862
 
51 cycrow 863
			if ( addToList ) {
1 cycrow 864
				addToList->push_back(package);
865
				package->SetEnabled(ms->bOn);
866
			}
867
			else if ( package )
868
				ms->pFile = package;
869
 
870
			// move to correct position in file for next stream of data
871
			// should be fine, this is more of a failsafe
51 cycrow 872
			stream.seekg(tell, std::ios::beg);
1 cycrow 873
		}
51 cycrow 874
		stream.seekg(ms->lSize, std::ios::cur);
1 cycrow 875
	}
876
 
51 cycrow 877
	stream.close();
1 cycrow 878
	return true;
879
}
880
 
881
 
882
SMultiSpkFile *CMultiSpkFile::FindFile ( CyString name )
883
{
884
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
885
	{
886
		SMultiSpkFile *ms = node->Data();
887
		if ( ms->sName.Compare(name) )
888
			return ms;
889
	}
890
	return NULL;
891
}
892
 
893
void CMultiSpkFile::UpdatedPackage(CBaseFile *p)
894
{
895
	SMultiSpkFile *s = this->FindPackage(p);
896
	if ( s )
897
	{
898
		if ( s->sData )
899
			delete s->sData;
900
		s->sData = (char *)p->CreateData((size_t*)&s->lSize);
901
	}
902
}
903
 
904
SMultiSpkFile *CMultiSpkFile::FindPackage(CBaseFile *p)
905
{
906
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
907
	{
908
		SMultiSpkFile *ms = node->Data();
909
		if ( ms->pFile == p )
910
			return ms;
911
	}
912
 
913
	return NULL;
914
}
915
 
916
SMultiSpkFile *CMultiSpkFile::FindPackage(CyString name, CyString author)
917
{
918
	for ( CListNode<SMultiSpkFile> *node = m_lFiles.Front(); node; node = node->next() )
919
	{
920
		SMultiSpkFile *ms = node->Data();
921
		if ( !ms->pFile )
922
			continue;
923
 
50 cycrow 924
		if ( ms->pFile->name().Compare(name.ToString()) && ms->pFile->author().Compare(author.ToString()) )
1 cycrow 925
			return ms;
926
	}
927
 
928
	return NULL;
929
}