2 * $Logfile: /Freespace2/code/CFile/CfileList.cpp $
7 * Code for doing directory lists and sorts
10 * Revision 1.2 2002/05/07 03:16:43 theoddone33
11 * The Great Newline Fix
13 * Revision 1.1.1.1 2002/05/03 03:28:08 root
17 * 3 2/22/99 10:31p Andsager
18 * Get rid of unneeded includes.
20 * 2 10/07/98 10:52a Dave
23 * 1 10/07/98 10:48a Dave
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.
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
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.
40 * 3 4/10/98 12:18a Hoffoss
41 * Make pilot image search in pack file possible.
43 * 2 3/30/98 10:36p Allender
44 * be sure to call _findclose() when done reading a file list
46 * 1 12/28/97 11:48a John
58 #include <winbase.h> /* needed for memory mapping of file functions */
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 )
80 if (sort == CF_SORT_NAME) {
83 for (i=incr; i<n; i++) {
86 if (stricmp(list[j], list[j + incr]) > 0) {
88 list[j] = list[j + incr];
93 info[j] = info[j + incr];
109 } else if (sort == CF_SORT_TIME) {
113 for (i=incr; i<n; i++) {
116 if (info[j].write_time < info[j + incr].write_time) {
118 list[j] = list[j + incr];
122 info[j] = info[j + incr];
137 nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
141 // cf_compress - Do Run Length Compression on a block of data. Targa format.
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 )
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
157 // set the threshold -- the minimum valid run length
158 rlthresh = 2; // Require a 2 pixel span before rle'ing
160 // set the first pixel up
162 flagbyte = out; // place to put next flag if run
168 // loop till data processing complete
171 // if we have accumulated a 128-byte packet, process it
172 if ( pixcount == 129 ) {
175 // set the run flag if this is a run
177 if ( rlcount >= rlthresh ) {
182 // copy the data into place
184 memmove( flagbyte, copyloc, pixcount-1 );
185 flagbyte += pixcount-1;
188 // set up for next packet
192 // if zeroth byte, handle as special case
193 if ( pixcount == 1 ) {
195 copyloc = inputpixel; /* point to 1st guy in packet */
196 matchpixel = inputpixel; /* set pointer to pix to match */
202 // assembling a packet -- look at next pixel
204 // current pixel == match pixel?
205 if ( *inputpixel == *matchpixel ) {
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
212 if ( ++rlcount == rlthresh ) {
214 // close a non-run packet
216 if ( pixcount > (rlcount+1) ) {
217 // write out length and do not set run flag
219 *flagbyte++ = (char)(pixcount - 2 - rlthresh);
221 memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
222 flagbyte += (pixcount-1-rlcount);
224 copyloc = inputpixel;
225 pixcount = rlcount + 1;
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
235 if ( rlcount >= rlthresh ) {
237 *flagbyte++ = (char)(0x80 | rlcount);
238 memmove(flagbyte, copyloc, 1 );
244 // not a match and currently not a run
245 // - save the current pixel
246 // - reset the run-length flag
248 matchpixel = inputpixel;
253 } while ( inputpixel < (in + bytecount));
255 // quit this buffer without loosing any data
256 if ( --pixcount >= 1 ) {
257 *flagbyte = (char)(pixcount - 1);
258 if ( rlcount >= rlthresh ) {
263 // copy the data into place
265 memmove(flagbyte, copyloc, pixcount );
266 flagbyte += pixcount;
268 return(flagbyte-out);
272 // cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
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 )
282 char *param_out = out;
287 int run_span = count & 0x80;
296 memset( out, c, count );
299 memmove( out, in, count );
306 return out - param_out;
311 // cfread() reads from a file and decompresses it
313 // returns: returns the number of full elements read
316 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
318 char *out = (char *)buf;
324 if ( cfread( &count, 1, 1, cfile ) != 1 ) {
328 int run_span = count & 0x80;
336 if ( cfread( &c, 1, 1, cfile ) != 1 ) {
339 memset( out, c, count );
341 if ( cfread( out, 1, count, cfile ) != count ) {
346 if ( out >= (char *)buf + (elsize*nelem)) {
354 return (out - (char *)buf)/elsize;
357 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
359 char *in = (char *)param_buf;
360 int bytecount = (param_elsize * param_nelem );
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
369 // set the threshold -- the minimum valid run length
370 rlthresh = 2; // Require a 2 pixel span before rle'ing
372 // set the first pixel up
379 // loop till data processing complete
382 // if we have accumulated a 128-byte packet, process it
383 if ( pixcount == 129 ) {
386 // set the run flag if this is a run
388 if ( rlcount >= rlthresh ) {
393 cfwrite( &code, 1, 1, cfile );
395 // copy the data into place
396 cfwrite( copyloc, 1, pixcount-1, cfile );
399 // set up for next packet
403 // if zeroth byte, handle as special case
404 if ( pixcount == 1 ) {
406 copyloc = inputpixel; /* point to 1st guy in packet */
407 matchpixel = inputpixel; /* set pointer to pix to match */
413 // assembling a packet -- look at next pixel
415 // current pixel == match pixel?
416 if ( *inputpixel == *matchpixel ) {
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
423 if ( ++rlcount == rlthresh ) {
425 // close a non-run packet
427 if ( pixcount > (rlcount+1) ) {
428 // write out length and do not set run flag
430 ubyte code = (ubyte)(pixcount - 2 - rlthresh);
431 cfwrite( &code, 1, 1, cfile );
433 cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
434 copyloc = inputpixel;
435 pixcount = rlcount + 1;
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
445 if ( rlcount >= rlthresh ) {
447 ubyte code = (ubyte)(0x80 | rlcount);
448 cfwrite( &code, 1, 1, cfile );
449 cfwrite( copyloc, 1, 1, cfile );
454 // not a match and currently not a run
455 // - save the current pixel
456 // - reset the run-length flag
458 matchpixel = inputpixel;
463 } while ( inputpixel < (in + bytecount));
465 // quit this buffer without loosing any data
466 if ( --pixcount >= 1 ) {
467 ubyte code = ubyte(pixcount - 1);
469 // set the run flag if this is a run
471 if ( rlcount >= rlthresh ) {
476 cfwrite( &code, 1, 1, cfile );
478 // copy the data into place
479 cfwrite( copyloc, 1, pixcount, cfile );