about summary refs log tree commit diff
path: root/urt/rle_hdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'urt/rle_hdr.c')
-rw-r--r--urt/rle_hdr.c297
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;
+}