/* 
 *  @OPENGROUP_COPYRIGHT@
 *  COPYRIGHT NOTICE
 *  Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc.
 *  Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group
 *  ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for
 *  the full copyright text.
 *  
 *  This software is subject to an open license. It may only be
 *  used on, with or for operating systems which are themselves open
 *  source systems. You must contact The Open Group for a license
 *  allowing distribution and sublicensing of this software on, with,
 *  or for operating systems which are not Open Source programs.
 *  
 *  See http://www.opengroup.org/openmotif/license for full
 *  details of the license agreement. Any use, reproduction, or
 *  distribution of the program constitutes recipient's acceptance of
 *  this agreement.
 *  
 *  EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
 *  PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
 *  WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
 *  OR FITNESS FOR A PARTICULAR PURPOSE
 *  
 *  EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
 *  NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT,
 *  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 *  DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED
 *  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
 *  EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGES.
*/ 
/* 
 * HISTORY
*/ 
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$TOG: Mrmwvalues.c /main/12 1999/04/16 09:42:44 mgreess $"
#endif
#endif

/*
*  (c) Copyright 1989, 1990, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */

/*
 *++
 *  FACILITY:
 *
 *      UIL Resource Manager (URM):
 *
 *  ABSTRACT:
 *
 *	This module contains the routines which implement modifying
 *	a widget (XtSetValues) from UID literals.
 *
 *--
 */


/*
 *
 *  INCLUDE FILES
 *
 */

#include <Mrm/MrmAppl.h>
#include <Mrm/Mrm.h>


/*
 *
 *  TABLE OF CONTENTS
 *
 *	UrmFetchSetValues	Do XtSetValues from UID literals.
 *
 */



/*
 *++
 *
 *  PROCEDURE DESCRIPTION:
 *
 *	UrmFetchSetValues is the internal routine which will
 *	modify a widget via XtSetValues on an argument list whose values
 *	are evaluated literals from a URM hierarchy. 
 *
 *	The args list has ordinary Strings as each tag name. Each value
 *	is interpreted as a String whose value is the index of a literal
 *	to be fetched and evaluated as the actual value. This routine
 *	constructs its own arglist, copying each tag, and setting the
 *	value to the fetched, fixed up, and converted literal value. The
 *	argument is not set in this list (is dropped) if there are any
 *	errors.
 *
 *	This code must also handle pixmaps in the same way that URM does;
 *	it defers converting icons and inserting them in the list
 *	until all the rest of the arglist is done; this allows FG/BG
 *	values to be uncovered in the list for use in the pixmap.
 *
 *  FORMAL PARAMETERS:
 *
 *	hierarchy_id	URM hierarchy from which to read public resources
 *	w		widget to be modified
 *	args		arglist, with literal indexes as values
 *	num_args	# args in args
 *
 *  IMPLICIT INPUTS:
 *
 *  IMPLICIT OUTPUTS:
 *
 *  FUNCTION VALUE:
 *
 *	MrmSUCCESS		operation succeeded
 *	MrmPARTIAL_SUCCESS	at least one fetch suboperation succeeded
 *	other			any error fatal to the operation
 *
 *  SIDE EFFECTS:
 *
 *--
 */

Cardinal 
UrmFetchSetValues (MrmHierarchy		hierarchy_id ,
		   Widget		w ,
		   ArgList		args ,
		   Cardinal		num_args )
{
  /*
   * Local structures
   */
  typedef struct {
    RGMIconImagePtr	icon ;		/* icon to be converted */
    int		pixndx ;	/* argument in arglist (args) */
  } _SavePixmapArg, *_SavePixmapArgPtr ;

  /*
   *  Local variables
   */
  Cardinal		result ;	/* function results */
  int			num_succ = 0;	/* # of successful fetches */
  int			fet_fail = 0;	/* # of failed fetches */
  int			cvt_fail = 0;	/* # failed conversions */
  Cardinal		badfet_res = MrmNOT_FOUND; /* to save NOT_FOUND */
  ArgList		locargs ;	/* local arglist */
  Cardinal		num_used = 0 ;	/* # args used in arglist */
  RGMResourceDescPtr	resptr ;	/* descriptor for literals */
  int			indexlen = 0 ;	/* longest literal length */
  URMPointerListPtr	ptrlist ;	/* to hold scratch contexts */
  int			ndx ;		/* loop index */
  IDBFile		file_id ;	/* file from which literal read */
  MrmType		reptype ;	/* arg value representation type */
  long			val ;		/* value as immediate or pointer */
  int			vec_count ;	/* number of items in val if vector */
  int			vec_size ;
  _SavePixmapArg	pixargs[10] ;	/* to save pixmap args */
  Cardinal		pixargs_cnt = 0 ;  /* # pixargs saved */
  _SavePixmapArgPtr	savepix ;	/* current saved pixmap entry */
  Screen		*screen ;	/* screen for pixmaps */
  Display		*display ;	/* display for pixmaps */
  Pixel			fgint = (Pixel) -1 ; /* fg for pixmaps. */
  Pixel			bgint = (Pixel) -1 ; /* background for pixmaps */
  Pixmap		pixmap ;	/* pixmap created from icon */
  Boolean		swap_needed = FALSE; 

  /*
   * Create local arglist and pointer list for contexts.
   */
  locargs = (ArgList) XtMalloc (num_args*sizeof(Arg)) ;
  UrmPlistInit (num_args, &ptrlist) ;

  /*
   * Find the longest literal index, and allocate a resource descriptor
   * which can hold it. Set the fixed fields of the descriptor.
   */
  for ( ndx=0 ; ndx<num_args ; ndx++ )
    indexlen = MAX (indexlen, strlen((char*)args[ndx].value)) ;

  /*
   * Create a resource descriptor which can be reused to fetch each literal
   */
  resptr = (RGMResourceDescPtr) XtMalloc (sizeof(RGMResourceDesc)+indexlen) ;
  resptr->access = URMaPublic ;
  resptr->type = URMrIndex ;
  resptr->res_group = URMgLiteral ;
  resptr->cvt_type = URMtNul ;

  /*
   * Loop through all the entries in the given arglist. Copy each tag into
   * the local arglist. Create a new context to hold the literal, then
   * try to read it from the hierarchy.
   */
  for ( ndx=0 ; ndx<num_args ; ndx++ )
    {
      locargs[num_used].name = args[ndx].name ;
      strcpy (resptr->key.index, (char*)args[ndx].value) ;
      result = Urm__CW_ReadLiteral (resptr, hierarchy_id, NULL,
				    ptrlist, &reptype, &val, &vec_count, 
				    &file_id, &vec_size) ;
      if ( result == MrmSUCCESS )
	num_succ += 1;
      else
	{
	  fet_fail += 1;
	  if ( result != MrmNOT_FOUND )
	    badfet_res = result;
	  continue;
	}

      /*
       * Fix up and perform conversion on the value. If this succeeds, put it
       * in the local arglist. Special casing is required for some types,
       * particularly icons.
       *
       * Type conversion for some ASCIZ strings is also provided as a V1
       * compatibility feature.
       */
      switch ( reptype )
        {
	case MrmRtypeIconImage:
	  savepix = &pixargs[pixargs_cnt] ;
	  savepix->icon = (RGMIconImagePtr) val ;
	  savepix->pixndx = ndx ;
	  pixargs_cnt += 1 ;
	  continue ;
	case MrmRtypeFontList:
	  /* Check for 1.1 version and malloc new fontlist if necessary. */
	  if (strcmp(file_id->db_version, URM1_1version) <= 0)
	    {
	      int count = ((OldRGMFontListPtr)val)->count;
	      RGMFontListPtr fontlist = (RGMFontListPtr)
		XtMalloc(sizeof(RGMFontList) +
			 (sizeof(RGMFontItem) * (count - 1)));
	      result = Urm__CW_FixupValue((long)fontlist, reptype, 
					  (XtPointer)val, file_id,
					  &swap_needed);
	      XtFree((char *)val);
	      val = (long)fontlist;
	    }
	  else
	    result = Urm__CW_FixupValue (val, reptype, (XtPointer)val, 
					 file_id, &swap_needed) ;

	default:
	  result = 
	    Urm__CW_FixupValue (val, reptype, (XtPointer)val, file_id,
				&swap_needed) ;
	  if ( result != MrmSUCCESS )
	    {
	      num_succ -= 1;
	      cvt_fail += 1;
	      continue;
	    }
	  if (XtIsWidget(w))
	    display = XtDisplay(w);
	  else
	    display = XtDisplay(XtParent(w));
	    
	  result = Urm__CW_ConvertValue (XtParent(w), &val, reptype, (MrmType)0,
					 display, hierarchy_id,  NULL) ;
	  if ( result != MrmSUCCESS )
	    {
	      num_succ -= 1;
	      cvt_fail += 1;
	      continue;
	    }
	  locargs[num_used].value = (XtArgVal)val ;
	  num_used += 1 ;
	  break ;
        }

      /*
       * Do any processing based on specific arguments (after conversion):
       *	- retain FG/BG info
       */
      switch ( reptype )
	{
	case MrmRtypeColor:
	  if ( strcmp(args[ndx].name,XmNforeground) == 0 )
	    fgint = val;

	  else if ( strcmp (args[ndx].name,XmNbackground) == 0 )
	    bgint = val;
	  break ;
        }

    }	/* end loop */

  /*
   * Now set any pixmap arguments. This requires finding the display, screen,
   * foreground, and background values for this widget. These values are
   * available from the parent widget and the arglist.
   */
  if ( pixargs_cnt > 0 )
    {
      Urm__CW_GetPixmapParms (w, &screen, &display, &fgint, &bgint) ;
      for ( ndx=0,savepix=pixargs ; ndx<pixargs_cnt ; ndx++,savepix++ )
        {
	  result = UrmCreatePixmap (savepix->icon, screen, display,
				    (Pixel)fgint, (Pixel)bgint, &pixmap, w) ;
	  if ( result != MrmSUCCESS )
	    {
	      num_succ -= 1;
	      cvt_fail += 1;
	      continue;
	    }
	  locargs[num_used].name = args[savepix->pixndx].name ;
	  locargs[num_used].value = (XtArgVal) pixmap ;
	  num_used += 1 ;
        }
    }

  /*
   * arglist creation complete. Modify the widget if we have succeeded in
   * fetching any values. Deallocate resources.
   */
  if ( num_used > 0 )
    XtSetValues (w, locargs, num_used) ;

  XtFree ((char*)locargs) ;
  XtFree ((char*)resptr) ;
  for ( ndx=0 ; ndx<UrmPlistNum(ptrlist) ; ndx++ )
    UrmFreeResourceContext ((URMResourceContextPtr)UrmPlistPtrN(ptrlist,ndx)) ;
  UrmPlistFree (ptrlist) ;

  /*
   * Result depends on number of successes vs. number of failurs
   */
  if ( num_succ > 0 )
    {
      if ( fet_fail==0 && cvt_fail == 0 )
	return MrmSUCCESS;
      else
	return MrmPARTIAL_SUCCESS;
    }
  if ( fet_fail > 0 )
    return badfet_res;
  else
    return MrmFAILURE;

}

