]> icculus.org git repositories - taylor/freespace2.git/blob - src/cfile/cfilelist.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / cfile / cfilelist.cpp
1 /*
2  * $Logfile: /Freespace2/code/CFile/CfileList.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Code for doing directory lists and sorts
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:43  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:08  root
14  * Initial import.
15  *
16  * 
17  * 3     2/22/99 10:31p Andsager
18  * Get rid of unneeded includes.
19  * 
20  * 2     10/07/98 10:52a Dave
21  * Initial checkin.
22  * 
23  * 1     10/07/98 10:48a Dave
24  * 
25  * 6     5/13/98 10:22p John
26  * Added cfile functions to read/write rle compressed blocks of data.
27  * Made palman use it for .clr files.  Made alphacolors calculate on the
28  * fly rather than caching to/from disk.
29  * 
30  * 5     5/06/98 5:30p John
31  * Removed unused cfilearchiver.  Removed/replaced some unused/little used
32  * graphics functions, namely gradient_h and _v and pixel_sp.   Put in new
33  * DirectX header files and libs that fixed the Direct3D alpha blending
34  * problems.
35  * 
36  * 4     4/30/98 4:53p John
37  * Restructured and cleaned up cfile code.  Added capability to read off
38  * of CD-ROM drive and out of multiple pack files.
39  * 
40  * 3     4/10/98 12:18a Hoffoss
41  * Make pilot image search in pack file possible.
42  * 
43  * 2     3/30/98 10:36p Allender
44  * be sure to call _findclose() when done reading a file list
45  * 
46  * 1     12/28/97 11:48a John
47  *
48  * $NoKeywords: $
49  */
50
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdio.h>
54 #ifndef PLAT_UNIX
55 #include <io.h>
56 #include <direct.h>
57 #include <windows.h>
58 #include <winbase.h>            /* needed for memory mapping of file functions */
59 #endif
60
61 #include "pstypes.h"
62 #include "cfile.h"
63 //#include "outwnd.h"
64 //#include "vecmat.h"
65 //#include "timer.h"
66
67 // Sorts a list of filenames using the specified sorting method (CF_SORT_*).
68 //   n = number of filenames in list to sort
69 //   list = list of filenames to be sorted
70 //   sort = sorting method to use (one of the CF_SORT_* defines)
71 //   info = extra info for each file.  Only required if sorting by time, however if you
72 //          have extra file info, you should pass it as well to get it sorted too (so an
73 //          index into list is the same index for info for that file
74 void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
75 {
76         int i, j, incr;
77         char *t;
78         file_list_info tt;
79
80         if (sort == CF_SORT_NAME) {
81                 incr = n / 2;
82                 while (incr > 0) {
83                         for (i=incr; i<n; i++) {
84                                 j = i - incr;
85                                 while (j >= 0) {
86                                         if (stricmp(list[j], list[j + incr]) > 0) {
87                                                 t = list[j];
88                                                 list[j] = list[j + incr];
89                                                 list[j + incr] = t;
90
91                                                 if (info) {
92                                                         tt = info[j];
93                                                         info[j] = info[j + incr];
94                                                         info[j + incr] = tt;
95                                                 }
96
97                                                 j -= incr;
98
99                                         } else
100                                                 break;
101                                 }
102                         }
103
104                         incr /= 2;
105                 }
106
107                 return;
108
109         } else if (sort == CF_SORT_TIME) {
110                 Assert(info);
111                 incr = n / 2;
112                 while (incr > 0) {
113                         for (i=incr; i<n; i++) {
114                                 j = i - incr;
115                                 while (j >= 0) {
116                                         if (info[j].write_time < info[j + incr].write_time) {
117                                                 t = list[j];
118                                                 list[j] = list[j + incr];
119                                                 list[j + incr] = t;
120
121                                                 tt = info[j];
122                                                 info[j] = info[j + incr];
123                                                 info[j + incr] = tt;
124                                                 j -= incr;
125
126                                         } else
127                                                 break;
128                                 }
129                         }
130
131                         incr /= 2;
132                 }
133
134                 return;
135         }
136
137         nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
138 }
139
140
141 //      cf_compress - Do Run Length Compression on a block of data. Targa format.
142 //
143 //      Usage:
144 //                              out                     Buffer to write it out to
145 //                              in                              Buffer to compress
146 //                              bytecount       Number of bytes input
147 int cf_compress(char *out, char *in, int bytecount )
148 {
149         int pixcount;           // number of pixels in the current packet
150         char *inputpixel=NULL;  // current input pixel position
151         char *matchpixel=NULL;  // pixel value to match for a run
152         char *flagbyte=NULL;            // location of last flag byte to set
153         int rlcount;            // current count in r.l. string 
154         int rlthresh;           // minimum valid run length
155         char *copyloc;          // location to begin copying at
156
157         // set the threshold -- the minimum valid run length
158         rlthresh = 2;                                   // Require a 2 pixel span before rle'ing
159         
160         // set the first pixel up
161
162         flagbyte = out; // place to put next flag if run
163         inputpixel = in;
164         pixcount = 1;
165         rlcount = 0;
166         copyloc = (char *)0;
167
168         // loop till data processing complete
169         do      {
170
171                 // if we have accumulated a 128-byte packet, process it
172                 if ( pixcount == 129 )  {
173                         *flagbyte = 127;
174
175                         // set the run flag if this is a run
176
177                         if ( rlcount >= rlthresh )      {
178                                         *flagbyte |= 0x80;
179                                         pixcount = 2;
180                         }
181
182                         // copy the data into place
183                         ++flagbyte;
184                         memmove( flagbyte, copyloc, pixcount-1 );
185                         flagbyte += pixcount-1;
186                         pixcount = 1;
187
188                         // set up for next packet
189                         continue;
190                 }
191
192                 // if zeroth byte, handle as special case
193                 if ( pixcount == 1 )    {
194                         rlcount = 0;
195                         copyloc = inputpixel;           /* point to 1st guy in packet */
196                         matchpixel = inputpixel;        /* set pointer to pix to match */
197                         pixcount = 2;
198                         inputpixel += 1;
199                         continue;
200                 }
201
202                 // assembling a packet -- look at next pixel
203
204                 // current pixel == match pixel?
205                 if ( *inputpixel == *matchpixel )       {
206
207                         //      establishing a run of enough length to
208                         //      save space by doing it
209                         //              -- write the non-run length packet
210                         //              -- start run-length packet
211
212                         if ( ++rlcount == rlthresh )    {
213                                 
214                                 //      close a non-run packet
215                                 
216                                 if ( pixcount > (rlcount+1) )   {
217                                         // write out length and do not set run flag
218
219                                         *flagbyte++ = (char)(pixcount - 2 - rlthresh);
220
221                                         memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
222                                         flagbyte += (pixcount-1-rlcount);
223
224                                         copyloc = inputpixel;
225                                         pixcount = rlcount + 1;
226                                 }
227                         }
228                 } else {
229
230                         // no match -- either break a run or continue without one
231                         //      if a run exists break it:
232                         //              write the bytes in the string (1+1)
233                         //              start the next string
234
235                         if ( rlcount >= rlthresh )      {
236
237                                 *flagbyte++ = (char)(0x80 | rlcount);
238                                 memmove(flagbyte, copyloc, 1 );
239                                 flagbyte += 1;
240                                 pixcount = 1;
241                                 continue;
242                         } else {
243
244                                 //      not a match and currently not a run
245                                 //              - save the current pixel
246                                 //              - reset the run-length flag
247                                 rlcount = 0;
248                                 matchpixel = inputpixel;
249                         }
250                 }
251                 pixcount++;
252                 inputpixel += 1;
253         } while ( inputpixel < (in + bytecount));
254
255         // quit this buffer without loosing any data
256         if ( --pixcount >= 1 )  {
257                 *flagbyte = (char)(pixcount - 1);
258                 if ( rlcount >= rlthresh )      {
259                         *flagbyte |= 0x80;
260                         pixcount = 1;
261                 }
262
263                 // copy the data into place
264                 ++flagbyte;
265                 memmove(flagbyte, copyloc, pixcount );
266                 flagbyte += pixcount;
267         }
268         return(flagbyte-out);
269 }
270
271
272 //      cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
273 //
274 //      Usage:
275 //                              out                     Buffer to write it out to
276 //                              in                              Buffer to compress
277 //                              bytecount       Number of bytes input
278 int cf_decompress(char *out, char *in )
279 {
280         int count;
281
282         char *param_out = out;
283
284         while(1)        {
285         
286                 count = int(*in++);
287                 int run_span = count & 0x80;
288
289                 count &= (~0x80);
290
291                 if ( count > 0 )        {
292                         if ( run_span ) {
293                                 // RLE'd data
294                                 ubyte c = *in++;
295
296                                 memset( out, c, count );
297                                 out += count;
298                         } else {
299                                 memmove( out, in, count );
300                                 in += count;
301                                 out += count;
302                         }
303                 }
304         }
305
306         return out - param_out;
307                         
308 }
309
310
311 // cfread() reads from a file and decompresses it
312 //
313 // returns:   returns the number of full elements read
314 //            
315 //
316 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
317 {
318         char *out = (char *)buf;
319         
320         while(1)        {
321
322                 byte count;
323
324                 if ( cfread( &count, 1, 1, cfile ) != 1 )       {
325                         break;
326                 }
327
328                 int run_span = count & 0x80;
329                 count &= (~0x80);
330                 count++;
331
332                 if ( count > 0 )        {
333                         if ( run_span ) {
334                                 // RLE'd data
335                                 byte c;
336                                 if ( cfread( &c, 1, 1, cfile ) != 1 )   {
337                                         break;
338                                 }
339                                 memset( out, c, count );
340                         } else {
341                                 if ( cfread( out, 1, count, cfile ) != count )  {
342                                         break;
343                                 }
344                         }
345                         out += count;
346                         if ( out >= (char *)buf + (elsize*nelem))       {
347                                 break;
348                         }
349                 } else {
350                         break;
351                 }
352         }
353
354         return (out - (char *)buf)/elsize;
355 }
356
357 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
358 {
359         char *in = (char *)param_buf;
360         int bytecount = (param_elsize * param_nelem );
361
362         int pixcount;           // number of pixels in the current packet
363         char *inputpixel=NULL;  // current input pixel position
364         char *matchpixel=NULL;  // pixel value to match for a run
365         int rlcount;            // current count in r.l. string 
366         int rlthresh;           // minimum valid run length
367         char *copyloc;          // location to begin copying at
368
369         // set the threshold -- the minimum valid run length
370         rlthresh = 2;                                   // Require a 2 pixel span before rle'ing
371         
372         // set the first pixel up
373
374         inputpixel = in;
375         pixcount = 1;
376         rlcount = 0;
377         copyloc = (char *)0;
378
379         // loop till data processing complete
380         do      {
381
382                 // if we have accumulated a 128-byte packet, process it
383                 if ( pixcount == 129 )  {
384                         ubyte code = 127;
385
386                         // set the run flag if this is a run
387
388                         if ( rlcount >= rlthresh )      {
389                                         code |= 0x80;
390                                         pixcount = 2;
391                         }
392
393                         cfwrite( &code, 1, 1, cfile );
394
395                         // copy the data into place
396                         cfwrite( copyloc, 1, pixcount-1, cfile );
397                         pixcount = 1;
398
399                         // set up for next packet
400                         continue;
401                 }
402
403                 // if zeroth byte, handle as special case
404                 if ( pixcount == 1 )    {
405                         rlcount = 0;
406                         copyloc = inputpixel;           /* point to 1st guy in packet */
407                         matchpixel = inputpixel;        /* set pointer to pix to match */
408                         pixcount = 2;
409                         inputpixel += 1;
410                         continue;
411                 }
412
413                 // assembling a packet -- look at next pixel
414
415                 // current pixel == match pixel?
416                 if ( *inputpixel == *matchpixel )       {
417
418                         //      establishing a run of enough length to
419                         //      save space by doing it
420                         //              -- write the non-run length packet
421                         //              -- start run-length packet
422
423                         if ( ++rlcount == rlthresh )    {
424                                 
425                                 //      close a non-run packet
426                                 
427                                 if ( pixcount > (rlcount+1) )   {
428                                         // write out length and do not set run flag
429
430                                         ubyte code = (ubyte)(pixcount - 2 - rlthresh);
431                                         cfwrite( &code, 1, 1, cfile );
432
433                                         cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
434                                         copyloc = inputpixel;
435                                         pixcount = rlcount + 1;
436                                 }
437                         }
438                 } else {
439
440                         // no match -- either break a run or continue without one
441                         //      if a run exists break it:
442                         //              write the bytes in the string (1+1)
443                         //              start the next string
444
445                         if ( rlcount >= rlthresh )      {
446
447                                 ubyte code = (ubyte)(0x80 | rlcount);
448                                 cfwrite( &code, 1, 1, cfile );
449                                 cfwrite( copyloc, 1, 1, cfile );
450                                 pixcount = 1;
451                                 continue;
452                         } else {
453
454                                 //      not a match and currently not a run
455                                 //              - save the current pixel
456                                 //              - reset the run-length flag
457                                 rlcount = 0;
458                                 matchpixel = inputpixel;
459                         }
460                 }
461                 pixcount++;
462                 inputpixel += 1;
463         } while ( inputpixel < (in + bytecount));
464
465         // quit this buffer without loosing any data
466         if ( --pixcount >= 1 )  {
467                 ubyte code = ubyte(pixcount - 1);
468
469                 // set the run flag if this is a run
470
471                 if ( rlcount >= rlthresh )      {
472                                 code |= 0x80;
473                                 pixcount = 1;
474                 }
475
476                 cfwrite( &code, 1, 1, cfile );
477
478                 // copy the data into place
479                 cfwrite( copyloc, 1, pixcount, cfile );
480         }
481
482         return param_nelem;
483 }
484