1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2009 by Denton Woods
5 // Last modified: 01/04/2009
6 //
7 // Filename: src-IL/src/il_files.c
8 //
9 // Description: File handling for DevIL
10 //
11 //-----------------------------------------------------------------------------
12
13
14 #define __FILES_C
15 #include "il_internal.h"
16 #include <stdarg.h>
17
18
19 // All specific to the next set of functions
20 ILboolean ILAPIENTRY iEofFile(void);
21 ILboolean ILAPIENTRY iEofLump(void);
22 ILint ILAPIENTRY iGetcFile(void);
23 ILint ILAPIENTRY iGetcLump(void);
24 ILuint ILAPIENTRY iReadFile(void *Buffer, ILuint Size, ILuint Number);
25 ILuint ILAPIENTRY iReadLump(void *Buffer, const ILuint Size, const ILuint Number);
26 ILint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode);
27 ILint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode);
28 ILint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode);
29 ILint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode);
30 ILuint ILAPIENTRY iTellRFile(void);
31 ILuint ILAPIENTRY iTellRLump(void);
32 ILuint ILAPIENTRY iTellWFile(void);
33 ILuint ILAPIENTRY iTellWLump(void);
34 ILint ILAPIENTRY iPutcFile(ILubyte Char);
35 ILint ILAPIENTRY iPutcLump(ILubyte Char);
36 ILint ILAPIENTRY iWriteFile(const void *Buffer, ILuint Size, ILuint Number);
37 ILint ILAPIENTRY iWriteLump(const void *Buffer, ILuint Size, ILuint Number);
38 ILHANDLE FileRead = NULL, FileWrite = NULL;
39 const void *ReadLump = NULL;
40 void *WriteLump = NULL;
41 ILuint ReadLumpPos = 0, ReadLumpSize = 0, ReadFileStart = 0, WriteFileStart = 0;
42 ILuint WriteLumpPos = 0, WriteLumpSize = 0;
43
44 fGetcProc GetcProcCopy;
45 fReadProc ReadProcCopy;
46 fSeekRProc SeekProcCopy;
47 fTellRProc TellProcCopy;
48 ILHANDLE (ILAPIENTRY *iopenCopy)(ILconst_string);
49 void (ILAPIENTRY *icloseCopy)(ILHANDLE);
50
51 fPutcProc PutcProcCopy;
52 fSeekWProc SeekWProcCopy;
53 fTellWProc TellWProcCopy;
54 fWriteProc WriteProcCopy;
55 ILHANDLE (ILAPIENTRY *iopenwCopy)(ILconst_string);
56 void (ILAPIENTRY *iclosewCopy)(ILHANDLE);
57
58 ILboolean UseCache = IL_FALSE;
59 ILubyte *Cache = NULL;
60 ILuint CacheSize, CachePos, CacheStartPos, CacheBytesRead;
61
62 // "Fake" size functions
63 // Definitions are in il_size.c.
64 ILint ILAPIENTRY iSizeSeek(ILint Offset, ILuint Mode);
65 ILuint ILAPIENTRY iSizeTell(void);
66 ILint ILAPIENTRY iSizePutc(ILubyte Char);
67 ILint ILAPIENTRY iSizeWrite(const void *Buffer, ILuint Size, ILuint Number);
68
69 // Just preserves the current read functions and replaces
70 // the current read functions with the default read funcs.
iPreserveReadFuncs()71 void ILAPIENTRY iPreserveReadFuncs()
72 {
73 // Create backups
74 GetcProcCopy = GetcProc;
75 ReadProcCopy = ReadProc;
76 SeekProcCopy = SeekRProc;
77 TellProcCopy = TellRProc;
78 iopenCopy = iopenr;
79 icloseCopy = icloser;
80
81 // Set the standard procs to read
82 ilResetRead();
83
84 return;
85 }
86
87
88 // Restores the read functions - must be used after iPreserveReadFuncs().
iRestoreReadFuncs()89 void ILAPIENTRY iRestoreReadFuncs()
90 {
91 GetcProc = GetcProcCopy;
92 ReadProc = ReadProcCopy;
93 SeekRProc = SeekProcCopy;
94 TellRProc = TellProcCopy;
95 iopenr = iopenCopy;
96 icloser = icloseCopy;
97
98 return;
99 }
100
101
102 // Just preserves the current read functions and replaces
103 // the current read functions with the default read funcs.
iPreserveWriteFuncs()104 void ILAPIENTRY iPreserveWriteFuncs()
105 {
106 // Create backups
107 PutcProcCopy = PutcProc;
108 SeekWProcCopy = SeekWProc;
109 TellWProcCopy = TellWProc;
110 WriteProcCopy = WriteProc;
111 iopenwCopy = iopenw;
112 iclosewCopy = iclosew;
113
114 // Set the standard procs to write
115 ilResetWrite();
116
117 return;
118 }
119
120
121 // Restores the read functions - must be used after iPreserveReadFuncs().
iRestoreWriteFuncs()122 void ILAPIENTRY iRestoreWriteFuncs()
123 {
124 PutcProc = PutcProcCopy;
125 SeekWProc = SeekWProcCopy;
126 TellWProc = TellWProcCopy;
127 WriteProc = WriteProcCopy;
128 iopenw = iopenwCopy;
129 iclosew = iclosewCopy;
130
131 return;
132 }
133
134
135 // Next 7 functions are the default read functions
136
iDefaultOpenR(ILconst_string FileName)137 ILHANDLE ILAPIENTRY iDefaultOpenR(ILconst_string FileName)
138 {
139 #ifndef _UNICODE
140 return (ILHANDLE)fopen((char*)FileName, "rb");
141 #else
142 // Windows has a different function, _wfopen, to open UTF16 files,
143 // whereas Linux just uses fopen for its UTF8 files.
144 #ifdef _WIN32
145 return (ILHANDLE)_wfopen(FileName, L"rb");
146 #else
147 return (ILHANDLE)fopen((char*)FileName, "rb");
148 #endif
149 #endif//UNICODE
150 }
151
152
iDefaultCloseR(ILHANDLE Handle)153 void ILAPIENTRY iDefaultCloseR(ILHANDLE Handle)
154 {
155 fclose((FILE*)Handle);
156 return;
157 }
158
159
iDefaultEof(ILHANDLE Handle)160 ILboolean ILAPIENTRY iDefaultEof(ILHANDLE Handle)
161 {
162 ILuint OrigPos, FileSize;
163
164 // Find out the filesize for checking for the end of file
165 OrigPos = itell();
166 iseek(0, IL_SEEK_END);
167 FileSize = itell();
168 iseek(OrigPos, IL_SEEK_SET);
169
170 if (itell() >= FileSize)
171 return IL_TRUE;
172 return IL_FALSE;
173 }
174
175
iDefaultGetc(ILHANDLE Handle)176 ILint ILAPIENTRY iDefaultGetc(ILHANDLE Handle)
177 {
178 ILint Val;
179
180 if (!UseCache) {
181 Val = fgetc((FILE*)Handle);
182 if (Val == IL_EOF)
183 ilSetError(IL_FILE_READ_ERROR);
184 }
185 else {
186 Val = 0;
187 if (iread(&Val, 1, 1) != 1)
188 return IL_EOF;
189 }
190 return Val;
191 }
192
193
iDefaultRead(void * Buffer,ILuint Size,ILuint Number,ILHANDLE Handle)194 ILint ILAPIENTRY iDefaultRead(void *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle)
195 {
196 return (ILint)fread(Buffer, Size, Number, (FILE*)Handle);
197 }
198
199
iDefaultRSeek(ILHANDLE Handle,ILint Offset,ILint Mode)200 ILint ILAPIENTRY iDefaultRSeek(ILHANDLE Handle, ILint Offset, ILint Mode)
201 {
202 return fseek((FILE*)Handle, Offset, Mode);
203 }
204
205
iDefaultWSeek(ILHANDLE Handle,ILint Offset,ILint Mode)206 ILint ILAPIENTRY iDefaultWSeek(ILHANDLE Handle, ILint Offset, ILint Mode)
207 {
208 return fseek((FILE*)Handle, Offset, Mode);
209 }
210
211
iDefaultRTell(ILHANDLE Handle)212 ILint ILAPIENTRY iDefaultRTell(ILHANDLE Handle)
213 {
214 return ftell((FILE*)Handle);
215 }
216
217
iDefaultWTell(ILHANDLE Handle)218 ILint ILAPIENTRY iDefaultWTell(ILHANDLE Handle)
219 {
220 return ftell((FILE*)Handle);
221 }
222
223
iDefaultOpenW(ILconst_string FileName)224 ILHANDLE ILAPIENTRY iDefaultOpenW(ILconst_string FileName)
225 {
226 #ifndef _UNICODE
227 return (ILHANDLE)fopen((char*)FileName, "wb");
228 #else
229 // Windows has a different function, _wfopen, to open UTF16 files,
230 // whereas Linux just uses fopen.
231 #ifdef _WIN32
232 return (ILHANDLE)_wfopen(FileName, L"wb");
233 #else
234 return (ILHANDLE)fopen((char*)FileName, "wb");
235 #endif
236 #endif//UNICODE
237 }
238
239
iDefaultCloseW(ILHANDLE Handle)240 void ILAPIENTRY iDefaultCloseW(ILHANDLE Handle)
241 {
242 fclose((FILE*)Handle);
243 return;
244 }
245
246
iDefaultPutc(ILubyte Char,ILHANDLE Handle)247 ILint ILAPIENTRY iDefaultPutc(ILubyte Char, ILHANDLE Handle)
248 {
249 return fputc(Char, (FILE*)Handle);
250 }
251
252
iDefaultWrite(const void * Buffer,ILuint Size,ILuint Number,ILHANDLE Handle)253 ILint ILAPIENTRY iDefaultWrite(const void *Buffer, ILuint Size, ILuint Number, ILHANDLE Handle)
254 {
255 return (ILint)fwrite(Buffer, Size, Number, (FILE*)Handle);
256 }
257
258
ilResetRead()259 void ILAPIENTRY ilResetRead()
260 {
261 ilSetRead(iDefaultOpenR, iDefaultCloseR, iDefaultEof, iDefaultGetc,
262 iDefaultRead, iDefaultRSeek, iDefaultRTell);
263 return;
264 }
265
266
ilResetWrite()267 void ILAPIENTRY ilResetWrite()
268 {
269 ilSetWrite(iDefaultOpenW, iDefaultCloseW, iDefaultPutc,
270 iDefaultWSeek, iDefaultWTell, iDefaultWrite);
271 return;
272 }
273
274
275 //! Allows you to override the default file-reading functions.
ilSetRead(fOpenRProc Open,fCloseRProc Close,fEofProc Eof,fGetcProc Getc,fReadProc Read,fSeekRProc Seek,fTellRProc Tell)276 void ILAPIENTRY ilSetRead(fOpenRProc Open, fCloseRProc Close, fEofProc Eof, fGetcProc Getc, fReadProc Read, fSeekRProc Seek, fTellRProc Tell)
277 {
278 iopenr = Open;
279 icloser = Close;
280 EofProc = Eof;
281 GetcProc = Getc;
282 ReadProc = Read;
283 SeekRProc = Seek;
284 TellRProc = Tell;
285
286 return;
287 }
288
289
290 //! Allows you to override the default file-writing functions.
ilSetWrite(fOpenRProc Open,fCloseRProc Close,fPutcProc Putc,fSeekWProc Seek,fTellWProc Tell,fWriteProc Write)291 void ILAPIENTRY ilSetWrite(fOpenRProc Open, fCloseRProc Close, fPutcProc Putc, fSeekWProc Seek, fTellWProc Tell, fWriteProc Write)
292 {
293 iopenw = Open;
294 iclosew = Close;
295 PutcProc = Putc;
296 WriteProc = Write;
297 SeekWProc = Seek;
298 TellWProc = Tell;
299
300 return;
301 }
302
303
304 // Tells DevIL that we're reading from a file, not a lump
iSetInputFile(ILHANDLE File)305 void iSetInputFile(ILHANDLE File)
306 {
307 ieof = iEofFile;
308 igetc = iGetcFile;
309 iread = iReadFile;
310 iseek = iSeekRFile;
311 itell = iTellRFile;
312 FileRead = File;
313 ReadFileStart = itell();
314 }
315
316
317 // Tells DevIL that we're reading from a lump, not a file
iSetInputLump(const void * Lump,ILuint Size)318 void iSetInputLump(const void *Lump, ILuint Size)
319 {
320 ieof = iEofLump;
321 igetc = iGetcLump;
322 iread = iReadLump;
323 iseek = iSeekRLump;
324 itell = iTellRLump;
325 ReadLump = Lump;
326 ReadLumpPos = 0;
327 ReadLumpSize = Size;
328 }
329
330
331 // Tells DevIL that we're writing to a file, not a lump
iSetOutputFile(ILHANDLE File)332 void iSetOutputFile(ILHANDLE File)
333 {
334 // Helps with ilGetLumpPos().
335 WriteLump = NULL;
336 WriteLumpPos = 0;
337 WriteLumpSize = 0;
338
339 iputc = iPutcFile;
340 iseekw = iSeekWFile;
341 itellw = iTellWFile;
342 iwrite = iWriteFile;
343 FileWrite = File;
344 }
345
346
347 // This is only called by ilDetermineSize. Associates iputc, etc. with
348 // "fake" writing functions in il_size.c.
iSetOutputFake(void)349 void iSetOutputFake(void)
350 {
351 iputc = iSizePutc;
352 iseekw = iSizeSeek;
353 itellw = iSizeTell;
354 iwrite = iSizeWrite;
355 return;
356 }
357
358
359 // Tells DevIL that we're writing to a lump, not a file
iSetOutputLump(void * Lump,ILuint Size)360 void iSetOutputLump(void *Lump, ILuint Size)
361 {
362 // In this case, ilDetermineSize is currently trying to determine the
363 // output buffer size. It already has the write functions it needs.
364 if (Lump == NULL)
365 return;
366
367 iputc = iPutcLump;
368 iseekw = iSeekWLump;
369 itellw = iTellWLump;
370 iwrite = iWriteLump;
371 WriteLump = Lump;
372 WriteLumpPos = 0;
373 WriteLumpSize = Size;
374 }
375
376
ilGetLumpPos()377 ILuint ILAPIENTRY ilGetLumpPos()
378 {
379 if (WriteLump)
380 return WriteLumpPos;
381 return 0;
382 }
383
384
ilprintf(const char * Line,...)385 ILuint ILAPIENTRY ilprintf(const char *Line, ...)
386 {
387 char Buffer[2048]; // Hope this is large enough
388 va_list VaLine;
389 ILuint i;
390
391 va_start(VaLine, Line);
392 vsprintf(Buffer, Line, VaLine);
393 va_end(VaLine);
394
395 i = ilCharStrLen(Buffer);
396 iwrite(Buffer, 1, i);
397
398 return i;
399 }
400
401
402 // To pad zeros where needed...
ipad(ILuint NumZeros)403 void ipad(ILuint NumZeros)
404 {
405 ILuint i = 0;
406 for (; i < NumZeros; i++)
407 iputc(0);
408 return;
409 }
410
411
412 //
413 // The rest of the functions following in this file are quite
414 // self-explanatory, except where commented.
415 //
416
417 // Next 12 functions are the default write functions
418
iEofFile(void)419 ILboolean ILAPIENTRY iEofFile(void)
420 {
421 return EofProc((FILE*)FileRead);
422 }
423
424
iEofLump(void)425 ILboolean ILAPIENTRY iEofLump(void)
426 {
427 if (ReadLumpSize)
428 return (ReadLumpPos >= ReadLumpSize);
429 return IL_FALSE;
430 }
431
432
iGetcFile(void)433 ILint ILAPIENTRY iGetcFile(void)
434 {
435 if (!UseCache) {
436 return GetcProc(FileRead);
437 }
438 if (CachePos >= CacheSize) {
439 iPreCache(CacheSize);
440 }
441
442 CacheBytesRead++;
443 return Cache[CachePos++];
444 }
445
446
iGetcLump(void)447 ILint ILAPIENTRY iGetcLump(void)
448 {
449 // If ReadLumpSize is 0, don't even check to see if we've gone past the bounds.
450 if (ReadLumpSize > 0) {
451 if (ReadLumpPos + 1 > ReadLumpSize) {
452 ReadLumpPos--;
453 ilSetError(IL_FILE_READ_ERROR);
454 return IL_EOF;
455 }
456 }
457
458 return *((ILubyte*)ReadLump + ReadLumpPos++);
459 }
460
461
iReadFile(void * Buffer,ILuint Size,ILuint Number)462 ILuint ILAPIENTRY iReadFile(void *Buffer, ILuint Size, ILuint Number)
463 {
464 ILuint TotalBytes = 0, BytesCopied;
465 ILuint BuffSize = Size * Number;
466 ILuint NumRead;
467
468 if (!UseCache) {
469 NumRead = ReadProc(Buffer, Size, Number, FileRead);
470 if (NumRead != Number)
471 ilSetError(IL_FILE_READ_ERROR);
472 return NumRead;
473 }
474
475 /*if (Cache == NULL || CacheSize == 0) { // Shouldn't happen, but we check anyway.
476 return ReadProc(Buffer, Size, Number, FileRead);
477 }*/
478
479 if (BuffSize < CacheSize - CachePos) {
480 memcpy(Buffer, Cache + CachePos, BuffSize);
481 CachePos += BuffSize;
482 CacheBytesRead += BuffSize;
483 if (Size != 0)
484 BuffSize /= Size;
485 return BuffSize;
486 }
487 else {
488 while (TotalBytes < BuffSize) {
489 // If loop through more than once, after first, CachePos is 0.
490 if (TotalBytes + CacheSize - CachePos > BuffSize)
491 BytesCopied = BuffSize - TotalBytes;
492 else
493 BytesCopied = CacheSize - CachePos;
494
495 memcpy((ILubyte*)Buffer + TotalBytes, Cache + CachePos, BytesCopied);
496 TotalBytes += BytesCopied;
497 CachePos += BytesCopied;
498 if (TotalBytes < BuffSize) {
499 iPreCache(CacheSize);
500 }
501 }
502 }
503
504 // DW: Changed on 12-27-2008. Was causing the position to go too far if the
505 // cache was smaller than the buffer.
506 //CacheBytesRead += TotalBytes;
507 CacheBytesRead = CachePos;
508 if (Size != 0)
509 TotalBytes /= Size;
510 if (TotalBytes != Number)
511 ilSetError(IL_FILE_READ_ERROR);
512 return TotalBytes;
513 }
514
515
iReadLump(void * Buffer,const ILuint Size,const ILuint Number)516 ILuint ILAPIENTRY iReadLump(void *Buffer, const ILuint Size, const ILuint Number)
517 {
518 ILuint i, ByteSize = IL_MIN( Size*Number, ReadLumpSize-ReadLumpPos);
519
520 for (i = 0; i < ByteSize; i++) {
521 *((ILubyte*)Buffer + i) = *((ILubyte*)ReadLump + ReadLumpPos + i);
522 if (ReadLumpSize > 0) { // ReadLumpSize is too large to care about apparently
523 if (ReadLumpPos + i > ReadLumpSize) {
524 ReadLumpPos += i;
525 if (i != Number)
526 ilSetError(IL_FILE_READ_ERROR);
527 return i;
528 }
529 }
530 }
531
532 ReadLumpPos += i;
533 if (Size != 0)
534 i /= Size;
535 if (i != Number)
536 ilSetError(IL_FILE_READ_ERROR);
537 return i;
538 }
539
540
iPreCache(ILuint Size)541 ILboolean iPreCache(ILuint Size)
542 {
543 // Reading from a memory lump, so don't cache.
544 if (iread == iReadLump) {
545 //iUnCache(); // DW: Removed 06-10-2002.
546 return IL_TRUE;
547 }
548
549 if (Cache) {
550 ifree(Cache);
551 }
552
553 if (Size == 0) {
554 Size = 1;
555 }
556
557 Cache = (ILubyte*)ialloc(Size);
558 if (Cache == NULL) {
559 return IL_FALSE;
560 }
561
562 UseCache = IL_FALSE;
563 CacheStartPos = itell();
564 CacheSize = iread(Cache, 1, Size);
565 if (CacheSize != Size)
566 ilGetError(); // Get rid of the IL_FILE_READ_ERROR.
567
568 //2003-09-09: uncommented the following line to prevent
569 //an infinite loop in ilPreCache()
570 CacheSize = Size;
571 CachePos = 0;
572 UseCache = IL_TRUE;
573 CacheBytesRead = 0;
574
575 return IL_TRUE;
576 }
577
578
iUnCache()579 void iUnCache()
580 {
581 //changed 2003-09-01:
582 //make iUnCache smart enough to return if
583 //no cache is used
584 if (!UseCache)
585 return;
586
587 if (iread == iReadLump)
588 return;
589
590 CacheSize = 0;
591 CachePos = 0;
592 if (Cache) {
593 ifree(Cache);
594 Cache = NULL;
595 }
596 UseCache = IL_FALSE;
597
598 iseek(CacheStartPos + CacheBytesRead, IL_SEEK_SET);
599
600 return;
601 }
602
603
iSeekRFile(ILint Offset,ILuint Mode)604 ILint ILAPIENTRY iSeekRFile(ILint Offset, ILuint Mode)
605 {
606 if (Mode == IL_SEEK_SET)
607 Offset += ReadFileStart; // This allows us to use IL_SEEK_SET in the middle of a file.
608 return SeekRProc(FileRead, Offset, Mode);
609 }
610
611
612 // Returns 1 on error, 0 on success
iSeekRLump(ILint Offset,ILuint Mode)613 ILint ILAPIENTRY iSeekRLump(ILint Offset, ILuint Mode)
614 {
615 switch (Mode)
616 {
617 case IL_SEEK_SET:
618 if (Offset > (ILint)ReadLumpSize)
619 return 1;
620 ReadLumpPos = Offset;
621 break;
622
623 case IL_SEEK_CUR:
624 if (ReadLumpPos + Offset > ReadLumpSize)
625 return 1;
626 ReadLumpPos += Offset;
627 break;
628
629 case IL_SEEK_END:
630 if (Offset > 0)
631 return 1;
632 // Should we use >= instead?
633 if (abs(Offset) > (ILint)ReadLumpSize) // If ReadLumpSize == 0, too bad
634 return 1;
635 ReadLumpPos = ReadLumpSize + Offset;
636 break;
637
638 default:
639 return 1;
640 }
641
642 return 0;
643 }
644
645
iTellRFile(void)646 ILuint ILAPIENTRY iTellRFile(void)
647 {
648 return TellRProc(FileRead);
649 }
650
651
iTellRLump(void)652 ILuint ILAPIENTRY iTellRLump(void)
653 {
654 return ReadLumpPos;
655 }
656
657
iGetFile(void)658 ILHANDLE ILAPIENTRY iGetFile(void)
659 {
660 return FileRead;
661 }
662
663
iGetLump(void)664 const ILubyte* ILAPIENTRY iGetLump(void) {
665 return (ILubyte*)ReadLump;
666 }
667
668
669
670 // Next 4 functions are the default write functions
671
iPutcFile(ILubyte Char)672 ILint ILAPIENTRY iPutcFile(ILubyte Char)
673 {
674 return PutcProc(Char, FileWrite);
675 }
676
677
iPutcLump(ILubyte Char)678 ILint ILAPIENTRY iPutcLump(ILubyte Char)
679 {
680 if (WriteLumpPos >= WriteLumpSize)
681 return IL_EOF; // IL_EOF
682 *((ILubyte*)(WriteLump) + WriteLumpPos++) = Char;
683 return Char;
684 }
685
686
iWriteFile(const void * Buffer,ILuint Size,ILuint Number)687 ILint ILAPIENTRY iWriteFile(const void *Buffer, ILuint Size, ILuint Number)
688 {
689 ILuint NumWritten;
690 NumWritten = WriteProc(Buffer, Size, Number, FileWrite);
691 if (NumWritten != Number) {
692 ilSetError(IL_FILE_WRITE_ERROR);
693 return 0;
694 }
695 return NumWritten;
696 }
697
698
iWriteLump(const void * Buffer,ILuint Size,ILuint Number)699 ILint ILAPIENTRY iWriteLump(const void *Buffer, ILuint Size, ILuint Number)
700 {
701 ILuint SizeBytes = Size * Number;
702 ILuint i = 0;
703
704 for (; i < SizeBytes; i++) {
705 if (WriteLumpSize > 0) {
706 if (WriteLumpPos + i >= WriteLumpSize) { // Should we use > instead?
707 ilSetError(IL_FILE_WRITE_ERROR);
708 WriteLumpPos += i;
709 return i;
710 }
711 }
712
713 *((ILubyte*)WriteLump + WriteLumpPos + i) = *((ILubyte*)Buffer + i);
714 }
715
716 WriteLumpPos += SizeBytes;
717
718 return SizeBytes;
719 }
720
721
iSeekWFile(ILint Offset,ILuint Mode)722 ILint ILAPIENTRY iSeekWFile(ILint Offset, ILuint Mode)
723 {
724 if (Mode == IL_SEEK_SET)
725 Offset += WriteFileStart; // This allows us to use IL_SEEK_SET in the middle of a file.
726 return SeekWProc(FileWrite, Offset, Mode);
727 }
728
729
730 // Returns 1 on error, 0 on success
iSeekWLump(ILint Offset,ILuint Mode)731 ILint ILAPIENTRY iSeekWLump(ILint Offset, ILuint Mode)
732 {
733 switch (Mode)
734 {
735 case IL_SEEK_SET:
736 if (Offset > (ILint)WriteLumpSize)
737 return 1;
738 WriteLumpPos = Offset;
739 break;
740
741 case IL_SEEK_CUR:
742 if (WriteLumpPos + Offset > WriteLumpSize)
743 return 1;
744 WriteLumpPos += Offset;
745 break;
746
747 case IL_SEEK_END:
748 if (Offset > 0)
749 return 1;
750 // Should we use >= instead?
751 if (abs(Offset) > (ILint)WriteLumpSize) // If WriteLumpSize == 0, too bad
752 return 1;
753 WriteLumpPos = WriteLumpSize + Offset;
754 break;
755
756 default:
757 return 1;
758 }
759
760 return 0;
761 }
762
763
iTellWFile(void)764 ILuint ILAPIENTRY iTellWFile(void)
765 {
766 return TellWProc(FileWrite);
767 }
768
769
iTellWLump(void)770 ILuint ILAPIENTRY iTellWLump(void)
771 {
772 return WriteLumpPos;
773 }
774