diff options
Diffstat (limited to 'urt/rle_hdr.c')
-rw-r--r-- | urt/rle_hdr.c | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/urt/rle_hdr.c b/urt/rle_hdr.c new file mode 100644 index 00000000..3cc0401d --- /dev/null +++ b/urt/rle_hdr.c @@ -0,0 +1,297 @@ +/* + * This software is copyrighted as noted below. It may be freely copied, + * modified, and redistributed, provided that the copyright notice is + * preserved on all copies. + * + * There is no warranty or other guarantee of fitness for this software, + * it is provided solely "as is". Bug reports or fixes may be sent + * to the author, who may or may not act on them as he desires. + * + * You may not include this software in a program or other software product + * without supplying the source, or without informing the end-user that the + * source is available for no extra charge. + * + * If you modify this software, you should include a notice giving the + * name of the person performing the modification, the date of modification, + * and the reason for such modification. + */ +/* + * rle_hdr.c - Functions to manipulate rle_hdr structures. + * + * Author: Spencer W. Thomas + * EECS Dept. + * University of Michigan + * Date: Mon May 20 1991 + * Copyright (c) 1991, University of Michigan + */ + +#include "rle.h" + +#include <string.h> + +/***************************************************************** + * TAG( rle_names ) + * + * Load program and file names into header. + * Inputs: + * the_hdr: Header to modify. + * pgmname: The program name. + * fname: The file name. + * img_num: Number of the image within the file. + * Outputs: + * the_hdr: Modified header. + * Algorithm: + * If values previously filled in (by testing is_init field), + * free them. Make copies of file name and program name, + * modifying file name for standard i/o. Set is_init field. + */ +void +rle_names( the_hdr, pgmname, fname, img_num ) +rle_hdr *the_hdr; +CONST_DECL char *pgmname; +CONST_DECL char *fname; +int img_num; +{ +#if 0 + /* Can't do this because people do hdr1 = hdr2, which copies + the pointers. */ + + /* If filled in, free previous values. */ + if ( the_hdr->is_init == RLE_INIT_MAGIC && + the_hdr->cmd != NULL && the_hdr->file_name != NULL ) + { + if ( pgmname != the_hdr->cmd ) + free( the_hdr->cmd ); + if ( fname != the_hdr->file_name ) + free( the_hdr->file_name ); + } +#endif + + /* Mark as filled in. */ + the_hdr->is_init = RLE_INIT_MAGIC; + + /* Default file name for stdin/stdout. */ + if ( fname == NULL || strcmp( fname, "-" ) == 0 || *fname == '\0' ) + fname = "Standard I/O"; + if ( pgmname == NULL ) + pgmname = rle_dflt_hdr.cmd; + + /* Fill in with copies of the strings. */ + if ( the_hdr->cmd != pgmname ) + { + char *tmp = (char *)malloc( strlen( pgmname ) + 1 ); + RLE_CHECK_ALLOC( pgmname, tmp, 0 ); + strcpy( tmp, pgmname ); + the_hdr->cmd = tmp; + } + + if ( the_hdr->file_name != fname ) + { + char *tmp = (char *)malloc( strlen( fname ) + 1 ); + RLE_CHECK_ALLOC( pgmname, tmp, 0 ); + strcpy( tmp, fname ); + the_hdr->file_name = tmp; + } + + the_hdr->img_num = img_num; +} + + +/* Used by rle_hdr_cp and rle_hdr_init to avoid recursion loops. */ +static int no_recurse = 0; + +/***************************************************************** + * TAG( rle_hdr_cp ) + * + * Make a "safe" copy of a rle_hdr structure. + * Inputs: + * from_hdr: Header to be copied. + * Outputs: + * to_hdr: Copy of from_hdr, with all memory referred to + * by pointers copied. Also returned as function + * value. If NULL, a static header is used. + * Assumptions: + * It is safe to call rle_hdr_init on to_hdr. + * Algorithm: + * Initialize to_hdr, copy from_hdr to it, then copy the memory + * referred to by all non-null pointers. + */ +rle_hdr * +rle_hdr_cp( from_hdr, to_hdr ) +rle_hdr *from_hdr, *to_hdr; +{ + static rle_hdr dflt_hdr; + CONST_DECL char *cmd, *file; + int num; + + /* Save command, file name, and image number if already initialized. */ + if ( to_hdr && to_hdr->is_init == RLE_INIT_MAGIC ) + { + cmd = to_hdr->cmd; + file = to_hdr->file_name; + num = to_hdr->img_num; + } + else + { + cmd = file = NULL; + num = 0; + } + + if ( !no_recurse ) + { + no_recurse++; + rle_hdr_init( to_hdr ); + no_recurse--; + } + + if ( to_hdr == NULL ) + to_hdr = &dflt_hdr; + + *to_hdr = *from_hdr; + + if ( to_hdr->bg_color ) + { + int size = to_hdr->ncolors * sizeof(int); + to_hdr->bg_color = (int *)malloc( size ); + RLE_CHECK_ALLOC( to_hdr->cmd, to_hdr->bg_color, "background color" ); + memcpy( to_hdr->bg_color, from_hdr->bg_color, size ); + } + + if ( to_hdr->cmap ) + { + int size = to_hdr->ncmap * (1 << to_hdr->cmaplen) * sizeof(rle_map); + to_hdr->cmap = (rle_map *)malloc( size ); + RLE_CHECK_ALLOC( to_hdr->cmd, to_hdr->cmap, "color map" ); + memcpy( to_hdr->cmap, from_hdr->cmap, size ); + } + + /* Only copy array of pointers, as the original comment memory + * never gets overwritten. + */ + if ( to_hdr->comments ) + { + int size = 0; + CONST_DECL char **cp; + for ( cp=to_hdr->comments; *cp; cp++ ) + size++; /* Count the comments. */ + /* Check if there are really any comments. */ + if ( size ) + { + size++; /* Copy the NULL pointer, too. */ + size *= sizeof(char *); + to_hdr->comments = (CONST_DECL char **)malloc( size ); + RLE_CHECK_ALLOC( to_hdr->cmd, to_hdr->comments, "comments" ); + memcpy( to_hdr->comments, from_hdr->comments, size ); + } + else + to_hdr->comments = NULL; /* Blow off empty comment list. */ + } + + /* Restore the names to their original values. */ + to_hdr->cmd = cmd; + to_hdr->file_name = file; + + /* Lines above mean nothing much happens if cmd and file are != NULL. */ + rle_names( to_hdr, to_hdr->cmd, to_hdr->file_name, num ); + + return to_hdr; +} + +/***************************************************************** + * TAG( rle_hdr_clear ) + * + * Clear out the allocated memory pieces of a header. + * + * This routine is intended to be used internally by the library, to + * clear a header before putting new data into it. It clears all the + * fields that would be set by reading in a new image header. + * Therefore, it does not clear the program and file names. + * + * Inputs: + * the_hdr: To be cleared. + * Outputs: + * the_hdr: After clearing. + * Assumptions: + * If is_init field is RLE_INIT_MAGIC, the header has been + * properly initialized. This will fail every 2^(-32) times, on + * average. + * Algorithm: + * Free memory and set to zero all pointers, except program and + * file name. + */ +void +rle_hdr_clear( the_hdr ) +rle_hdr *the_hdr; +{ + /* Try to free memory. Assume if is_init is properly set that this + * header has been previously initialized, therefore it is safe to + * free memory. + */ + if ( the_hdr && the_hdr->is_init == RLE_INIT_MAGIC ) + { + if ( the_hdr->bg_color ) + free( the_hdr->bg_color ); + the_hdr->bg_color = 0; + if ( the_hdr->cmap ) + free( the_hdr->cmap ); + the_hdr->cmap = 0; + /* Unfortunately, we don't know how to free the comment memory. */ + if ( the_hdr->comments ) + free( the_hdr->comments ); + the_hdr->comments = 0; + } +} + + + +/***************************************************************** + * TAG( rle_hdr_init ) + * + * Initialize a rle_hdr structure. + * Inputs: + * the_hdr: Header to be initialized. + * Outputs: + * the_hdr: Initialized header. + * Assumptions: + * If the_hdr->is_init is RLE_INIT_MAGIC, the header has been + * previously initialized. + * If the_hdr is a copy of another rle_hdr structure, the copy + * was made with rle_hdr_cp. + * Algorithm: + * Fill in fields of rle_dflt_hdr that could not be set by the loader + * If the_hdr is rle_dflt_hdr, do nothing else + * Else: + * If the_hdr is NULL, return a copy of rle_dflt_hdr in static storage + * If the_hdr->is_init is RLE_INIT_MAGIC, free all memory + * pointed to by non-null pointers. + * If this is a recursive call to rle_hdr_init, clear *the_hdr and + * return the_hdr. + * Else make a copy of rle_dflt_hdr and return its address. Make the + * copy in static storage if the_hdr is NULL, and in the_hdr otherwise. + */ +rle_hdr * +rle_hdr_init( the_hdr ) +rle_hdr *the_hdr; +{ + rle_hdr *ret_hdr; + + rle_dflt_hdr.rle_file = stdout; + /* The rest of rle_dflt_hdr is set by the loader's data initialization */ + + if ( the_hdr == &rle_dflt_hdr ) + return the_hdr; + + rle_hdr_clear( the_hdr ); + + /* Only call rle_hdr_cp if not called from there. */ + if ( !no_recurse ) + { + no_recurse++; + ret_hdr = rle_hdr_cp( &rle_dflt_hdr, the_hdr ); + no_recurse--; + } + else + ret_hdr = the_hdr; + + return ret_hdr; +} |