/*
 * Copyright (C) 1997-2009, R3vis Corporation.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA, or visit http://www.gnu.org/copyleft/lgpl.html.
 *
 * Original Contributor:
 *   Wes Bethel, R3vis Corporation, Marin County, California
 *   http://www.r3vis.com/
 * Additional Contributor(s):
 *
 * The OpenRM project is located at http://openrm.sourceforge.net/.
 */
/*
 * $Id: rmvmap.c,v 1.6 2005/02/19 16:22:50 wes Exp $
 * Version: $Name: v180-alpha-02 $
 * $Revision: 1.6 $
 * $Log: rmvmap.c,v $
 * Revision 1.6  2005/02/19 16:22:50  wes
 * Distro sync and consolidation.
 *
 * Revision 1.5  2005/01/23 17:00:22  wes
 * Copyright updated to 2005.
 *
 * Revision 1.4  2004/03/30 14:13:31  wes
 * Fixed declarations and man page docs for several routines.
 *
 * Revision 1.3  2004/01/16 16:49:50  wes
 * Updated copyright line for 2004.
 *
 * Revision 1.2  2003/02/02 02:07:16  wes
 * Updated copyright to 2003.
 *
 * Revision 1.1.1.1  2003/01/28 02:15:23  wes
 * Manual rebuild of rm150 repository.
 *
 * Revision 1.5  2003/01/16 22:21:17  wes
 * Updated all source files to reflect new organization of header files:
 * all header files formerly located in include/rmaux, include/rmi, include/rmv
 * are now located in include/rm.
 *
 * Revision 1.4  2002/04/30 19:36:22  wes
 * Updated copyright dates.
 *
 * Revision 1.3  2001/03/31 17:12:39  wes
 * v1.4.0-alpha-2 checkin.
 *
 * Revision 1.2  2000/04/20 16:29:47  wes
 * Documentation additions/enhancements, some code rearragement.
 *
 * Revision 1.1.1.1  2000/02/28 21:29:40  wes
 * OpenRM 1.2 Checkin
 *
 * Revision 1.1.1.1  2000/02/28 17:18:47  wes
 * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
 *
 */

#include <rm/rm.h>
#include "rmprivat.h"

/* PRIVATE declarations */
RMenum private_rmVismapCheckSize (const RMvisMap *v, int indx, char *funcName);

/*
 * ----------------------------------------------------
 * @Name rmVismapNew
 @pstart
 RMvisMap *rmVismapNew (int size)
 @pend

 @astart 
 int size - an int that specifyingthe size of the visualization
    colormap (input). 
 @aend

 @dstart

 Creates a new visualization Colormap, returning the handle to the
 caller. The caller should use rmVismapDelete() when the vismap is no
 longer needed to free memory.

 The size of the visualization colormap is dictated by the input
 parameter. The newly created visualization colormap of length "size"
 is set to all zeroes.

 @dend
 * ----------------------------------------------------
 */
RMvisMap *
rmVismapNew (int size)
{
    RMvisMap *v = malloc(sizeof(RMvisMap));

    memset(v, 0, sizeof(RMvisMap));
    rmVismapSetSize(v, size);
    return(v);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapDup
 @pstart
 RMvisMap * rmVismapDup (const RMvisMap *toDuplicate)
 @pend

 @astart
 const RMvisMap *toDuplicate - a handle to an RMvisMap
 @aend

 @dstart

 Creates a new RMvisMap object that is an exact duplicate of the input
 RMvisMap object. Returns a handle to the newly created RMvisMap to
 the caller if successful, or returns NULL upon failure.

 The caller should use rmVismapDelete() to free the new RMvisMap
 object when no longer needed.
 
 @dend
 * ----------------------------------------------------
 */
RMvisMap *
rmVismapDup (const RMvisMap *toDuplicate)
{
    /* create a new vismap, copy contents of an existing one into it */
    RMvisMap *t = rmVismapNew(rmVismapGetSize(toDuplicate));

    if (t == NULL)
    {
	rmError("rmVismapDup() error: unable to create a new RMvisMap, possibly due to a malloc error inside rmVismapNew().");
	return NULL;
    }

    /* we really should do a component-by-component copy, but instead..  */
    memcpy((void *)t, (void *)toDuplicate, sizeof(RMvisMap));

    /*
     * this works for the time being ONLY because we used fixed-size
     * arrays for the vismap. when we graduate to dynamically-sized
     * arrays, things will become more complicated and the memcpy
     * won't work.
     */
    return(t);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapDelete
 @pstart
 RMenum rmVismapDelete (RMvisMap *toDelete) 
 @pend

 @astart
 RMvisMap *toDelete - a handle to an RMvisMap that will be deleted
 @aend

 @dstart
 
 Releases the resources associated with an RMvisMap object. This
 routine is the opposite of rmVismapNew(). The caller should not
 reference the RMvisMap object after making this call.

 Returns RM_CHILL upon success, or RM_WHACKED upon failure.
 
 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapDelete (RMvisMap *toDelete)
{
    if (toDelete == NULL)
    {
	rmWarning("rmVismapDelete() warning: the input RMvisMap object is NULL, avoiding NULL pointer free.");
	return(RM_WHACKED);
    }
    else
	free(toDelete);
    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapSetColor3D
 @pstart
 RMenum rmVismapSetColor3D (RMvisMap *toModify,
                           int indx,
			   const RMcolor3D *newColor)
 @pend

 @astart
 RMvisMap *toModify - input RMvisMap object that will be modified.

 int index - an integer index of the entry in the RMvisMap that will
    be modified.

 const RMcolor3D *newColor - the 4-component color that will be copied
    into the RMvisMap at location "index".

 @aend

 @dstart

 Use this routine to set the 3-component color of an RMvisMap object.
 Each entry in the RMvisMap object is a 4-component color (RGBA), and
 this routine writes over the RGB channels at one such entry at
 location "index" in the RMvisMap with the caller supplied
 data. RM_CHILL is returned upon successful modification of the
 RMvisMap object. RM_WHACKED is returned if "toModify" is NULL, if
 "indx" is out of range, or if the input RMcolor3D object "newColor"
 is NULL.

 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapSetColor3D (RMvisMap *toModify,
		    int indx,
		    const RMcolor3D *newColor)
{
    if ((RM_ASSERT(toModify, "rmVismapSetColor3D() error: the input RMvisMap object is NULL") == RM_WHACKED) ||
	(RM_ASSERT(newColor, "rmVismapSetColor3D() error: the input RMcolorD object is NULL") == RM_WHACKED) ||
	(private_rmVismapCheckSize((const RMvisMap *)toModify, indx, "rmVismapSetColor3D") == RM_WHACKED))
	return(RM_WHACKED);

    toModify->r[indx] = newColor->r;
    toModify->g[indx] = newColor->g;
    toModify->b[indx] = newColor->b;

    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapGetColor3D
 @pstart
 RMenum rmVismapGetColor3D (const RMvisMap *toQuery,
	 	            int indx,
		            RMcolor3D *retColor)
 @pend

 @astart
 RMvisMap *toQuery - input RMvisMap object that will be queried.

 int index - an integer index of the entry in the RMvisMap that will
    be returned to the caller.

 RMcolor3D *retColor - a handle to an RMcolor3D object that will be
    modified to contain the 3-component color at location "indx" from
    within the RMvisMap "toQuery." 3-component color means the R,G,B
    channels of the RMvisMap; the alpha channel is ignored. 
 @aend

 @dstart
 
 Copies the 3-component color from the RMvisMap object "toQuery" at
 location "indx" into the caller supplied object. This routine returns
 RM_CHILL upon success, or RM_WHACKED if "toQuery" is NULL, if "indx"
 is out of range, or if the pointer to the caller supplied object is
 NULL.
 
 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapGetColor3D (const RMvisMap *toQuery,
		    int indx,
		    RMcolor3D *retColor)
{
    if ((RM_ASSERT(toQuery, "rmVismapGetColor3D() error: the input RMvisMap object is NULL") == RM_WHACKED) ||
	(RM_ASSERT(retColor, "rmVismapGetColor3D() error: the return RMcolor3D object is NULL") == RM_WHACKED) ||
	(private_rmVismapCheckSize(toQuery, indx, "rmVismapGetColor3D") == RM_WHACKED))
	return(RM_WHACKED);

    retColor->r = toQuery->r[indx];
    retColor->g = toQuery->g[indx];
    retColor->b = toQuery->b[indx];

    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapSetColor4D
 @pstart
 RMenum rmVismapSetColor4D (RMvisMap *toModify,
                            int index,
			    const RMcolor4D *newColor)
 @pend

 @astart
 RMvisMap *toModify - input RMvisMap object that will be modified.

 int index - an integer index of the entry in the RMvisMap that will
    be modified.

 const RMcolor4D *newColor - the 4-component color that will be copied
    into the RMvisMap at location "index"
 @aend

 @dstart

 Use this routine to set the 4-component color of an RMvisMap object.
 Each entry in the RMvisMap object is a 4-component color, and this
 routine writes over one such entry at location "index" in the
 RMvisMap with the caller supplied data. RM_CHILL is returned upon
 successful modification of the RMvisMap object. RM_WHACKED is
 returned if "toModify" is NULL, if "indx" is out of range, or if the
 input RMcolor4D object "newColor" is NULL.

 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapSetColor4D (RMvisMap *toModify,
		    int indx,
		    const RMcolor4D *newColor)
{
    if ((RM_ASSERT(toModify, "rmVismapSetColor4D() error: the input RMvisMap object is NULL") == RM_WHACKED) ||
	(RM_ASSERT(newColor, "rmVismapSetColor4D() error: the input RMcolor4D object is NULL") == RM_WHACKED) ||
	(private_rmVismapCheckSize((const RMvisMap *)toModify, indx, "rmVismapSetColor4D") == RM_WHACKED))
	return(RM_WHACKED);

    toModify->r[indx] = newColor->r;
    toModify->g[indx] = newColor->g;
    toModify->b[indx] = newColor->b;
    toModify->a[indx] = newColor->a;
    
    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapGetColor4D
 @pstart
 RMenum rmVismapGetColor4D (const RMvisMap *toQuery,
	 	            int indx,
		            RMcolor4D *retColor)
 @pend

 @astart
 RMvisMap *toQuery - input RMvisMap object that will be queried.

 int index - an integer index of the entry in the RMvisMap that will
    be returned to the caller.

 RMcolor4D *retColor - a handle to an RMcolor4D object that will be
    modified to contain the 4-component color at location "indx" from
    within the RMvisMap "toQuery." 
 @aend

 @dstart
 
 Copies the 4-component color from the RMvisMap object "toQuery" at
 location "indx" into the caller supplied object. This routine returns
 RM_CHILL upon success, or RM_WHACKED if "toQuery" is NULL, if "indx"
 is out of range, or if the pointer to the caller supplied object is
 NULL.
 
 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapGetColor4D (const RMvisMap *toQuery,
		    int indx,
		    RMcolor4D *retColor)
{
    if ((RM_ASSERT(toQuery, "rmVismapGetColor4D() error: the input RMvisMap object is NULL") == RM_WHACKED) ||
	(RM_ASSERT(retColor, "rmVismapGetColor4D() error: the return RMcolor4D object is NULL") == RM_WHACKED) ||
	(private_rmVismapCheckSize(toQuery, indx, "rmVismapGetColor4D") == RM_WHACKED))
	return(RM_WHACKED);

    retColor->r = toQuery->r[indx];
    retColor->g = toQuery->g[indx];
    retColor->b = toQuery->b[indx];
    retColor->a = toQuery->a[indx];

    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapSetTfMin
 @pstart
 RMenum rmVismapSetTfMin (RMvisMap *toModify,
		          float newTFMin)
 @pend

 @astart
 RMvisMap *toModify - a handle to an RMvisMap object that will be
    modified by this routine (input).

 float newTFMin - a floating point value that will be assigned to the
    RMvisMap object's minimum transfer function attribute.
 @aend

 @dstart

 Use this routine in conjunction with rmVismapSetTfMax to define a
 linear transfer function for the RMvisMap object. Returns RM_CHILL
 upon success, or RM_WHACKED if the input RMvisMap object is NULL.

 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapSetTfMin (RMvisMap *toModify,
		  float newTFMin)
{
    if (RM_ASSERT(toModify, "rmVismapSetTfMin() error: the input RMvisMap is NULL") == RM_WHACKED)
	return(RM_WHACKED);
    
    toModify->transfer_min = newTFMin;
    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapGetTfMin
 @pstart
 float rmVismapGetTfMin (const RMvisMap *toQuery)
 @pend

 @astart
 const RMvisMap *toQuery - a handle to an RMvisMap object (input)
 @aend

 @dstart
 
 Returns to the caller a floating point value that is the RMvisMap
 object's transfer function lower bound.
 
 @dend
 * ----------------------------------------------------
 */
float
rmVismapGetTfMin (const RMvisMap *toQuery)
{
    if (RM_ASSERT(toQuery, "rmVismapGetTfMin error() the input RMvisMap object is NULL") == RM_WHACKED)
	return(0.0F);
    
    return(toQuery->transfer_min);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapSetTfMax
 @pstart
 RMenum rmVismapSetTfMax (RMvisMap *toModify,
		          float newTFMax)
 @pend

 @astart

 RMvisMap *toModify - a handle to an RMvisMap object that will be
    modified by this routine (input).

 float newTFMax - a floating point value that will be assigned to the
    RMvisMap object's maximum transfer function attribute (input).
 @aend

 @dstart

 Use this routine in conjunction with rmVismapSetTfMin to define a
 linear transfer function for the RMvisMap object. Returns RM_CHILL
 upon success, or RM_WHACKED if the input RMvisMap object is NULL.

 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapSetTfMax (RMvisMap *toModify,
		  float newTFMax)
{
    if (RM_ASSERT(toModify, "rmVismapSetTfMax() error: the input RMvisMap is NULL") == RM_WHACKED)
	return(RM_WHACKED);
    
    toModify->transfer_max = newTFMax;
    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapGetTfMax
 @pstart
 float rmVismapGetTfMax (const RMvisMap *toQuery)
 @pend

 @astart
 const RMvisMap *toQuery - a handle to an RMvisMap object (input)
 @aend

 @dstart
 
 Returns to the caller a floating point value that is the RMvisMap
 object's transfer function upper bound.
 
 @dend
 * ----------------------------------------------------
 */
float
rmVismapGetTfMax (const RMvisMap *toQuery)
{
    if (RM_ASSERT(toQuery,"rmVismapGetTfMax() error: the input RMvisMap object is NULL") == RM_WHACKED)
	return(0.0F);
    
    return(toQuery->transfer_max);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapIndexFromData
 @pstart
 int rmVismapIndexFromData (const RMvisMap *map,
                            float val)
 @pend

 @astart
 const RMvisMap *map - a handle to an RMvisMap object (input).

 float val - a floating point value (input).
 @aend

 @dstart

 Use this routine to compute an index from a raw data value. RMvisMap
 objects contain internal parameters to define a transfer function
 (see rmVismapSetTfMin() and rmVismapSetTfMax() ). This routine
 computes an integer index thus: ((val-min)/(max-min))*(size-1). The
 return value is clamped to be in the range 0..size-1, where "size" is
 the number of entries in the RMvisMap object.
 
 @dend
 * ----------------------------------------------------
 */
int
rmVismapIndexFromData (const RMvisMap *map,
		       float val)
{
    /* look through the bracket values in the map, return the index into the map */
    int   index;
    float fval;

    if (RM_ASSERT(map, "rmVismapIndexFromData() error: the input RMvisMap object is NULL") == RM_WHACKED)
	return(0);

    fval = ((val-map->transfer_min) / (map->transfer_max-map->transfer_min));

    if (fval < 0.0)
        fval = 0.0;
    else 
       if (fval > 1.0)
	  fval = 1.0;
    
    index = (float)(map->nentries - 1) * fval;
    return(index);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapSetSize
 @pstart
 RMenum rmVismapSetSize (RMvisMap *toModify,
		         int newSize)
 @pend

 @astart
 RMvisMap *toModify - a handle to an RMvisMap object.

 int newSize - an integer value defining the new number of entries in
    the RMvisMap object "toModify."
 @aend

 @dstart

 This routine is used to modify the number of entries in the RMvisMap
 object. The new requested size must be greater than 0 and less than
 256. As of 1/15/2000, 256 is the current maximum and default size of
 the RMvisMap object. This routine does not cause any internal tables
 to be realloced, it just changes the size attribute of the table. The
 size attribute is checked by routines that set/get RMvisMap entries
 in validity checking input.

 This routine will return RM_CHILL to the caller upon success, or
 RM_WHACKED if the input RMvisMap object is NULL or if the "newSize"
 parameter is out of range.
 
 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapSetSize (RMvisMap *toModify,
		 int newSize)
{
    if (RM_ASSERT(toModify, "rmVismapSetSize() error: the input RMvisMap object is NULL") == RM_WHACKED)
	return(RM_WHACKED);
    if ((newSize <= 0) || (newSize > RMV_DEFAULT_MAP_SIZE ))
    {
	rmError(" rmVismapSetSize() the requested newSize is either too large or too small.");
	return(RM_WHACKED);
    }

    /*
     * TODO:
     *
     * at this time (1/15/2000) the size of the R,G,B,A tables in the
     * RMvisMap object is fixed, defined by the constant RMV_DEFAULT_MAP_SIZE.
     * at some point in the future, we will want to dynamically allocate
     * those tables. when we do that, we'll need to change this set size
     * routine to realloc the tables to the new requested size.
     */
    toModify->nentries = newSize;
    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapGetSize
 @pstart
 int rmVismapGetSize (const RMvisMap *toQuery)
 @pend

 @astart 

 const RMvisMap *toQuery - a handle to the RMvisMap object to be
    queried. 
 @aend

 @dstart
 
 Returns to the caller the number of entries in the visualization colormap
 of the of the RMvisMap object. A non-negative integer is returned upon
 success, or -1 is returned if the input RMvisMap object is NULL.
 
 @dend
 * ----------------------------------------------------
 */
int
rmVismapGetSize (const RMvisMap *toQuery)
{
    if (RM_ASSERT(toQuery, "rmVismapGetSize() error: input RMvisMap pointer is NULL.") == RM_WHACKED)
	return(-1);
    return(toQuery->nentries);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapSetAlpha
 @pstart
 RMenum rmVismapSetAlpha (RMvisMap *toModify,
		          int indx,
			  float newAlpha)
 @pend

 @astart
 RMvisMap *toModify - a handle to an RMvisMap object (input).

 int indx - an integer value specifying which entry of the RMvisMap
    object will be modified by this routine (input).

 float newAlpha - a floating point value that will be copied into the
    RMvisMap object "toModify" at location "indx". Alpha values
    usually range between 0.0 and 1.0.
 @aend

 @dstart

 Sets that alpha component of the 4-component color in the RMvisMap
 object "toModify" at entry "indx." Returns RM_CHILL to the caller if
 successful.  RM_WHACKED is returned if "toModify" is NULL, or if
 "indx" is out of range.
 
 @dend
 * ----------------------------------------------------
 */
RMenum
rmVismapSetAlpha (RMvisMap *toModify,
		  int indx,
		  float value)
{
    if ((RM_ASSERT(toModify, "rmVismapSetAlpha() error: the input RMvisMap object is NULL") == RM_WHACKED) ||
	(private_rmVismapCheckSize(toModify, indx, "rmVismapSetAlpha") == RM_WHACKED))
	return(RM_WHACKED);
    
    toModify->a[indx] = value;
    return(RM_CHILL);
}


/*
 * ----------------------------------------------------
 * @Name rmVismapGetAlpha
 @pstart
 float rmVismapGetAlpha (const RMvisMap *toQuery,
	 	         int indx)
 @pend

 @astart
 const RMvisMap *toQuery - a handle to an RMvisMap object to be
    queried (input).

 int indx - the index of the entry in the RMvisMap object to query
    (input).
 @aend

 @dstart

 Returns to the caller the alpha component of the RMvisMap object at
 entry "indx." If "indx" is out of range, rmWarning() is called
 issuing an error message, and -1.0 is returned to the caller. Alpha
 values usually range between 0.0 and 1.0.

 @dend
 * ----------------------------------------------------
 */
float
rmVismapGetAlpha (const RMvisMap *toQuery,
		  int indx)
{
    if ((RM_ASSERT(toQuery, "rmVismapGetAlpha() error: the input RMvisMap object is NULL") == RM_WHACKED) ||
	(private_rmVismapCheckSize(toQuery, indx, "rmVismapGetAlpha") == RM_WHACKED))
	return(0.0F);
    else
	return(toQuery->a[indx]);
}


/*
 * ----------------------------------------------------
 * @Name rmDefaultVismap
 @pstart
 RMvisMap *rmDefaultVismap (void)
 @pend

 @astart
 No arguments.
 @aend

 @dstart

 This routine performs a two-fold function. First, it creates a new
 RMvisMap object containing 256 entries. Second, it assigns default
 values to the RGBA channels of the new colormap. A handle to the new
 RMvisMap object is returned to the caller. When caller no longer
 needs the RMvisMap object, use "rmVismapDelete()" to free the object.
 The default colormap will be set to:
   
 1. A hue ramp from .66 to 0.0 (blue-cyan-green-yellow-orange-red)
 2. Constant saturation & brightness of 1.0
 3. Alpha ramp from 0..1 (low to high)
 4. transfer function min/max of 0..1

 @dend
 * ----------------------------------------------------
 */
RMvisMap *
rmDefaultVismap (void)
{
    int       i, n;
    float     h, dh, s, v, a, da;
    RMvisMap *t;
    RMcolor3D rgb;

    n = RMV_DEFAULT_MAP_SIZE;

    t = rmVismapNew(n);
    if (t == NULL)
    {
	rmError(" rmDefaultVismap() error: unable to allocate a new RMvisMap object.");
	return(NULL);
    }
    
    h = 0.66F;
    dh = -0.66 / (float)(n - 1);
    s = 1.0;
    v = 1.0;
    a = 0.0;
    da = 1.0 / (float)(n - 1);

    for (i = 0; i < n; i++)
    {
        rmHSVtoRGB(h, s, v, &(rgb.r), &(rgb.g), &(rgb.b));
        rmVismapSetColor3D(t, i, &rgb);
	rmVismapSetAlpha(t, i, a);

	h += dh;
	a += da;
    }

    rmVismapSetTfMin(t, 0.0F);
    rmVismapSetTfMax(t, 1.0F);
    
    return(t);
}


/* PRIVATE
 *
 * private_rmVismapCheckSize performs a validity/range check operation. The
 * input parameter "indx" is compared to the RMvisMap object's size attribute.
 * If "indx" is greater than or equal to zero, but less than the RMvisMap
 * object's size attribute, this routine returns RM_CHILL. Otherwise,
 * rmWarning is called with a descriptive error message, and RM_WHACKED
 * is returned to the caller.
 */
RMenum
private_rmVismapCheckSize (const RMvisMap *v,
			   int indx,
			   char *funcName)
{
    if ((indx < 0) || (indx >= rmVismapGetSize(v)))
    {
	char buf[1024];

	if (strlen(funcName) > 900)
	{
	    rmWarning("private_rmVismapCheckSize() warning: the index into the RMvisMap object is out of range, and the string length of the function name is unreasonable.");
	    return(RM_WHACKED);
	}
	
	sprintf(buf, "in function %s the index (value = %d) is out of range (<= 0 or >= %d) \n", funcName, indx, rmVismapGetSize(v));
	rmWarning(buf);
	return(RM_WHACKED);
    }
    else
	return(RM_CHILL);
    
}
/* EOF */
