2 * $Logfile: /Freespace2/code/CFile/CfileList.cpp $
7 * Code for doing directory lists and sorts
10 * Revision 1.1 2002/05/03 03:28:08 root
14 * 3 2/22/99 10:31p Andsager
15 * Get rid of unneeded includes.
17 * 2 10/07/98 10:52a Dave
20 * 1 10/07/98 10:48a Dave
22 * 6 5/13/98 10:22p John
23 * Added cfile functions to read/write rle compressed blocks of data.
24 * Made palman use it for .clr files. Made alphacolors calculate on the
25 * fly rather than caching to/from disk.
27 * 5 5/06/98 5:30p John
28 * Removed unused cfilearchiver. Removed/replaced some unused/little used
29 * graphics functions, namely gradient_h and _v and pixel_sp. Put in new
30 * DirectX header files and libs that fixed the Direct3D alpha blending
33 * 4 4/30/98 4:53p John
34 * Restructured and cleaned up cfile code. Added capability to read off
35 * of CD-ROM drive and out of multiple pack files.
37 * 3 4/10/98 12:18a Hoffoss
38 * Make pilot image search in pack file possible.
40 * 2 3/30/98 10:36p Allender
41 * be sure to call _findclose() when done reading a file list
43 * 1 12/28/97 11:48a John
55 #include <winbase.h> /* needed for memory mapping of file functions */
64 // Sorts a list of filenames using the specified sorting method (CF_SORT_*).
65 // n = number of filenames in list to sort
66 // list = list of filenames to be sorted
67 // sort = sorting method to use (one of the CF_SORT_* defines)
68 // info = extra info for each file. Only required if sorting by time, however if you
69 // have extra file info, you should pass it as well to get it sorted too (so an
70 // index into list is the same index for info for that file
71 void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
77 if (sort == CF_SORT_NAME) {
80 for (i=incr; i<n; i++) {
83 if (stricmp(list[j], list[j + incr]) > 0) {
85 list[j] = list[j + incr];
90 info[j] = info[j + incr];
106 } else if (sort == CF_SORT_TIME) {
110 for (i=incr; i<n; i++) {
113 if (info[j].write_time < info[j + incr].write_time) {
115 list[j] = list[j + incr];
119 info[j] = info[j + incr];
134 nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
138 // cf_compress - Do Run Length Compression on a block of data. Targa format.
141 // out Buffer to write it out to
142 // in Buffer to compress
143 // bytecount Number of bytes input
144 int cf_compress(char *out, char *in, int bytecount )
146 int pixcount; // number of pixels in the current packet
147 char *inputpixel=NULL; // current input pixel position
148 char *matchpixel=NULL; // pixel value to match for a run
149 char *flagbyte=NULL; // location of last flag byte to set
150 int rlcount; // current count in r.l. string
151 int rlthresh; // minimum valid run length
152 char *copyloc; // location to begin copying at
154 // set the threshold -- the minimum valid run length
155 rlthresh = 2; // Require a 2 pixel span before rle'ing
157 // set the first pixel up
159 flagbyte = out; // place to put next flag if run
165 // loop till data processing complete
168 // if we have accumulated a 128-byte packet, process it
169 if ( pixcount == 129 ) {
172 // set the run flag if this is a run
174 if ( rlcount >= rlthresh ) {
179 // copy the data into place
181 memmove( flagbyte, copyloc, pixcount-1 );
182 flagbyte += pixcount-1;
185 // set up for next packet
189 // if zeroth byte, handle as special case
190 if ( pixcount == 1 ) {
192 copyloc = inputpixel; /* point to 1st guy in packet */
193 matchpixel = inputpixel; /* set pointer to pix to match */
199 // assembling a packet -- look at next pixel
201 // current pixel == match pixel?
202 if ( *inputpixel == *matchpixel ) {
204 // establishing a run of enough length to
205 // save space by doing it
206 // -- write the non-run length packet
207 // -- start run-length packet
209 if ( ++rlcount == rlthresh ) {
211 // close a non-run packet
213 if ( pixcount > (rlcount+1) ) {
214 // write out length and do not set run flag
216 *flagbyte++ = (char)(pixcount - 2 - rlthresh);
218 memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
219 flagbyte += (pixcount-1-rlcount);
221 copyloc = inputpixel;
222 pixcount = rlcount + 1;
227 // no match -- either break a run or continue without one
228 // if a run exists break it:
229 // write the bytes in the string (1+1)
230 // start the next string
232 if ( rlcount >= rlthresh ) {
234 *flagbyte++ = (char)(0x80 | rlcount);
235 memmove(flagbyte, copyloc, 1 );
241 // not a match and currently not a run
242 // - save the current pixel
243 // - reset the run-length flag
245 matchpixel = inputpixel;
250 } while ( inputpixel < (in + bytecount));
252 // quit this buffer without loosing any data
253 if ( --pixcount >= 1 ) {
254 *flagbyte = (char)(pixcount - 1);
255 if ( rlcount >= rlthresh ) {
260 // copy the data into place
262 memmove(flagbyte, copyloc, pixcount );
263 flagbyte += pixcount;
265 return(flagbyte-out);
269 // cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
272 // out Buffer to write it out to
273 // in Buffer to compress
274 // bytecount Number of bytes input
275 int cf_decompress(char *out, char *in )
279 char *param_out = out;
284 int run_span = count & 0x80;
293 memset( out, c, count );
296 memmove( out, in, count );
303 return out - param_out;
308 // cfread() reads from a file and decompresses it
310 // returns: returns the number of full elements read
313 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
315 char *out = (char *)buf;
321 if ( cfread( &count, 1, 1, cfile ) != 1 ) {
325 int run_span = count & 0x80;
333 if ( cfread( &c, 1, 1, cfile ) != 1 ) {
336 memset( out, c, count );
338 if ( cfread( out, 1, count, cfile ) != count ) {
343 if ( out >= (char *)buf + (elsize*nelem)) {
351 return (out - (char *)buf)/elsize;
354 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
356 char *in = (char *)param_buf;
357 int bytecount = (param_elsize * param_nelem );
359 int pixcount; // number of pixels in the current packet
360 char *inputpixel=NULL; // current input pixel position
361 char *matchpixel=NULL; // pixel value to match for a run
362 int rlcount; // current count in r.l. string
363 int rlthresh; // minimum valid run length
364 char *copyloc; // location to begin copying at
366 // set the threshold -- the minimum valid run length
367 rlthresh = 2; // Require a 2 pixel span before rle'ing
369 // set the first pixel up
376 // loop till data processing complete
379 // if we have accumulated a 128-byte packet, process it
380 if ( pixcount == 129 ) {
383 // set the run flag if this is a run
385 if ( rlcount >= rlthresh ) {
390 cfwrite( &code, 1, 1, cfile );
392 // copy the data into place
393 cfwrite( copyloc, 1, pixcount-1, cfile );
396 // set up for next packet
400 // if zeroth byte, handle as special case
401 if ( pixcount == 1 ) {
403 copyloc = inputpixel; /* point to 1st guy in packet */
404 matchpixel = inputpixel; /* set pointer to pix to match */
410 // assembling a packet -- look at next pixel
412 // current pixel == match pixel?
413 if ( *inputpixel == *matchpixel ) {
415 // establishing a run of enough length to
416 // save space by doing it
417 // -- write the non-run length packet
418 // -- start run-length packet
420 if ( ++rlcount == rlthresh ) {
422 // close a non-run packet
424 if ( pixcount > (rlcount+1) ) {
425 // write out length and do not set run flag
427 ubyte code = (ubyte)(pixcount - 2 - rlthresh);
428 cfwrite( &code, 1, 1, cfile );
430 cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
431 copyloc = inputpixel;
432 pixcount = rlcount + 1;
437 // no match -- either break a run or continue without one
438 // if a run exists break it:
439 // write the bytes in the string (1+1)
440 // start the next string
442 if ( rlcount >= rlthresh ) {
444 ubyte code = (ubyte)(0x80 | rlcount);
445 cfwrite( &code, 1, 1, cfile );
446 cfwrite( copyloc, 1, 1, cfile );
451 // not a match and currently not a run
452 // - save the current pixel
453 // - reset the run-length flag
455 matchpixel = inputpixel;
460 } while ( inputpixel < (in + bytecount));
462 // quit this buffer without loosing any data
463 if ( --pixcount >= 1 ) {
464 ubyte code = ubyte(pixcount - 1);
466 // set the run flag if this is a run
468 if ( rlcount >= rlthresh ) {
473 cfwrite( &code, 1, 1, cfile );
475 // copy the data into place
476 cfwrite( copyloc, 1, pixcount, cfile );