 /*
  * Khoros: $Id: xvdisplay.c,v 1.4 1992/03/20 22:48:40 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: xvdisplay.c,v 1.4 1992/03/20 22:48:40 dkhoros Exp $";
#endif

 /*
  * $Log: xvdisplay.c,v $
 * Revision 1.4  1992/03/20  22:48:40  dkhoros
 * VirtualPatch5
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 *            Copyright 1990 University of New Mexico
 *  
 *  Permission to use, copy, modify, distribute, and sell this
 *  software and its documentation for any purpose is hereby
 *  granted without fee, provided that the above copyright
 *  notice appear in all copies and that both that copyright
 *  notice and this permission notice appear in supporting docu-
 *  mentation, and that the name of UNM not be used in advertis-
 *  ing or publicity pertaining to distribution of the software
 *  without specific, written prior permission.  UNM makes no
 *  representations about the suitability of this software for
 *  any purpose.  It is provided "as is" without express or
 *  implied warranty.
 *  
 *  UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 *  NESS, IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 *  INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 *  RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 *  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 *  OF THIS SOFTWARE.
 *  
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "xvdisplay.h"

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>            xvdisplay Utility Routines		      <<<<
   >>>>                                                       <<<<
   >>>>		    xvd_init_xvdisplay()		      <<<<
   >>>>		    xvd_build_xvdisplay()		      <<<<
   >>>>		    xvd_create_xvdisplay()		      <<<<
   >>>>		    xvd_update_xvdisplay()		      <<<<
   >>>>		    xvd_clear_xvdisplay()		      <<<<
   >>>>		    xvd_delete_xvdisplay()		      <<<<
   >>>>                                                       <<<<
   >>>>		    xvd_init_visual()			      <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */




/************************************************************
*
*  MODULE NAME: xvd_init_xvdisplay
*
*      PURPOSE: initialize the xvdisplay structure.  For use of
*		initializing the xvdisplay structure without creating
*		any X resources or creating the XImage display widget.
*
*	 INPUT: display - the display for which we will be initializing
*		image   - the viff display image
*		shape   - the viff shape bitmap
*		clip    - the viff clip bitmap
*		overlay - the viff overlay image
*		private_cmap   - create a private colormap (if needed)
*		read_only - create read only color cells
*		shape_parent - whether the shape mask should be expanded
*			       so as not to shape it's parent
*
*       OUTPUT: the DisplayStructure
*
*    CALLED BY: the application program
*
*   WRITTEN BY: Mark Young
*
*
*************************************************************/


DisplayStructure *xvd_init_xvdisplay(display, image, shape, clip, overlay,
			 private_cmap, read_only, shape_parent, colormap)

Display	       *display;
struct xvimage *image, *shape, *clip, *overlay;
int	       private_cmap, read_only, shape_parent;
Colormap       colormap;
{
	DisplayStructure *xvdisplay;


	xvdisplay = (DisplayStructure *) XtCalloc(1, sizeof(DisplayStructure));
	xvdisplay->image =
	xvdisplay->disp_image = image;
	xvdisplay->shape = shape;
	xvdisplay->clip  = clip;
	xvdisplay->overlay   = overlay;
	xvdisplay->display   = display;
	xvdisplay->colormap  = colormap;
	xvdisplay->read_only = read_only;
	xvdisplay->shape_parent     = shape_parent;
	xvdisplay->private_colormap = private_cmap;

	if (xvd_init_visual(xvdisplay) == False)
	{
	   XtFree(xvdisplay);
	   return(NULL);
	}

	if (xvdisplay->vinfo->class == TrueColor ||
	    xvdisplay->vinfo->class == DirectColor)
	   xvdisplay->truecolor = TRUE;
	else
	   xvdisplay->truecolor = FALSE;

	(void) xvd_add_xvdisplay_list(xvdisplay);
	return(xvdisplay);

}  /* end xvd_init_xvdisplay */



/************************************************************
*
*  MODULE NAME: xvd_build_xvdisplay
*
*      PURPOSE: build the xvdisplay structure.  For use of creating
*		all X resources associated with the xvdisplay structure,
*		without creating XImage display widget.
*
*	 INPUT: xvdisplay - the display structure for which we will build
*
*       OUTPUT: the DisplayStructure
*
*    CALLED BY: the application program
*
*   WRITTEN BY: Mark Young
*
*
*************************************************************/


int xvd_build_xvdisplay(xvdisplay)

DisplayStructure *xvdisplay;
{
	if (xvdisplay->image == NULL)
	   return(True);
	else if (xvdisplay->image->imagedata == NULL)
	{
	   xvf_error_wait("Error!  No image data found.  The image is probably \
a colormap rather than an image, since no image data was found. Please re-run \
the program with an image that has column and row size of at least 1 \
('vfileinfo' can be used to obtain information about the image).",
			"xvd_build_xvdisplay", NULL);
	   return(False);
	}

	if (!xvd_check_image(xvdisplay))
	   return(False);

	/*
	 *  Create the X Colormap.  To do this we need to create and load
	 *  the X color array.
	 */
	if (!xvd_initialize_colormap(xvdisplay))
	   return(False);

	if (!xvd_load_xcolors(xvdisplay))
	   return(False);

	if (!xvd_create_colormap(xvdisplay))
	   return(False);

	/*
	 *  Create the ximage.  This image will create and copy the image's
	 *  imagedata and create an X11 image suitable to display.  If we
	 *  fail then clean up and return failure.
	 */
	if (!_xvd_load_ximage(xvdisplay, xvdisplay->disp_image,
			&xvdisplay->ximage, &xvdisplay->pixmap))
	{
	   return(False);
	}

	/*
	 *  if a clip image mask exists, initialize & create it.
	 */
	if (xvdisplay->clip != NULL)
	{
	   if (xvd_check_clip(xvdisplay))
	   {
	      (void) _xvd_update_ximage(xvdisplay, xvdisplay->clip,
			&xvdisplay->xclip, &xvdisplay->clip_mask);
	   }
	}

	/*
	 *  if an overlay image exists, initialize & create it.
	 */
	if (xvdisplay->overlay != NULL)
	{
	   if (xvd_check_overlay(xvdisplay))
	   {
	      (void) _xvd_update_ximage(xvdisplay, xvdisplay->overlay,
			&xvdisplay->xoverlay, &xvdisplay->overlay_pixmap);

	      (void) _xvd_update_ximage(xvdisplay, xvdisplay->ovmask, NULL,
			&xvdisplay->overlay_mask);
	   }
	}

	/*
	 *  now return that the newly assigned display structure has been
	 *  sucessfully build.
	 */
	return(True);

}  /* end xvd_build_xvdisplay */


/************************************************************
*
*  MODULE NAME: xvd_create_xvdisplay
*
*      PURPOSE: Initializes & creates the xvdisplay structure
*		all X resources associated with the xvdisplay structure,
*		without creating XImage display widget.
*
*	 INPUT: display - pointer to X11 Display structure
*		image	- viff image to use
*	        shape   - viff image to use as shape mask (if desired)
*		private_cmap - False if application can only use default
*			       colormap
*		read_only - False if application needs color cells
*			       to be Read/Write; True otherwise
*		name - name for raster widget
*		xpos & ypos - position on screen to place image.
*			      (-1,-1) will allow user to place image using 
*			      the window manager.
*		position_widget - indicates whether or not to put a position
*				  widget at the bottom.
*
*       OUTPUT: the DisplayStructure
*
*    CALLED BY: the application program
*
*   WRITTEN BY: Mark Young
*
*
*************************************************************/


DisplayStructure *xvd_create_xvdisplay(display, image, shape, clip, overlay,
		private_cmap, read_only, name, xpos, ypos, position_widget)
Display 	*display;
struct xvimage  *image, *shape, *clip, *overlay;
int 		 private_cmap, read_only;
char 		*name;
int   		 xpos, ypos;
int		 position_widget;
{
	int    i;
	Arg    args[MaxArgs];
	char   geometry[50];
	Widget toplevel, back;
	DisplayStructure *xvdisplay;



	/*
	 *  Call xvd_init_xvdisplay to create the image and display
	 *  structure.
	 */
	if (!(xvdisplay = xvd_init_xvdisplay(display, image, shape, clip,
			overlay, private_cmap, read_only, True, NULL)))
	{
	   return(NULL);
	}

	/*
	 *  If the user specifies the name then copy it into display structure.
	 */
	if (name != NULL)
	   xvdisplay->name = xvf_strcpy(name);

	/*
         *  Create top level application shell widget
         */
	i = 0;
        XtSetArg(args[i], XtNinput, True);		     i++;
        XtSetArg(args[i], XtNtitle, xvf_strcpy(name));       i++;
        XtSetArg(args[i], XtNallowShellResize, True);	     i++;
	if (xpos != -1 && ypos != -1)
        {
           (void) sprintf(geometry, "+%d+%d", xpos, ypos);
           XtSetArg(args[i], XtNgeometry, geometry);            i++;
        }
	xvdisplay->toplevel =
	toplevel = XtAppCreateShell(name, name, applicationShellWidgetClass, 
				    display, args, i);

	/*
         *  Create the backplane for the image & position widgets
	 *  created by xvd_create_raster()
         */
        i = 0;
        XtSetArg(args[i], XtNinput, True);		    i++;
	XtSetArg(args[i], XtNmappedWhenManaged, True);	    i++;
	XtSetArg(args[i], XtNresizable, True);		    i++;
        back = XtCreateManagedWidget("back", formWidgetClass, toplevel,args,i);

	/*
	 *  Call xvd_build_xvdisplay to build the image and display structure.
	 */
	if (xvd_build_xvdisplay(xvdisplay) == False)
	{
	   return(NULL);
	}

	/*
	 *  Create the display's icon widget.
	 */
        i = 0;
	xvd_create_icon(display, xvdisplay, 64, 64);
        XtSetArg(args[i], XtNiconWindow, XtWindow(xvdisplay->icon));      i++;
	XtSetValues(toplevel, args, i);


	/*
	 *  Create and place the widget.
	 */
	xvd_create_raster(display, back, xvdisplay, position_widget);
	XtRealizeWidget(toplevel);

	if (xvdisplay->shape != NULL)
	   xvd_update_shape(xvdisplay, NULL);


        /*
         *  Set the colormap for the raster widget.
         */
        xvd_set_colormap(xvdisplay->raster, xvdisplay->colormap);
	xvf_add_toplevel(toplevel);
	return(xvdisplay);
}



/************************************************************
*
*  MODULE NAME: xvd_clear_xvdisplay
*
*      PURPOSE: clears and free's all internal associated resources and
*		memory of and xvdisplay structure.  This means that
*		all ximages and pixmaps are cleared.  The input images
*		supplied by the user are cleared if the "free_images"
*		parameter is set to True, otherwise these image pointers
*		are simply cleared from the display structure.
*
*	 INPUT: xvdisplay  - the xvdisplay structure to be freed.
*
*       OUTPUT: none
*
*    CALLED BY: the application program
*
*   WRITTEN BY: Mark Young
*
*
*************************************************************/

xvd_clear_xvdisplay(xvdisplay, free_images)

DisplayStructure *xvdisplay;
int		 free_images;
{
	int	i;
	Arg	args[MaxArgs];

	Display *display = xvdisplay->display;
	int screen = XDefaultScreen(display);


	if (xvdisplay == NULL)
	   return;

	if (xvdisplay->colormap != XDefaultColormap(display, screen))
	{
	   XFreeColormap(display, xvdisplay->colormap);
	   xvdisplay->colormap = XDefaultColormap(display, screen);
	}

	if (xvdisplay->image != xvdisplay->disp_image &&
	    xvdisplay->disp_image != NULL)
	{
	   freeimage(xvdisplay->disp_image);
	}

	if (free_images == True)
	{
	   if (xvdisplay->image != NULL)   freeimage(xvdisplay->image);
	   if (xvdisplay->shape != NULL)   freeimage(xvdisplay->shape);
	   if (xvdisplay->overlay != NULL) freeimage(xvdisplay->overlay);
	   if (xvdisplay->clip != NULL)    freeimage(xvdisplay->clip);
	   if (xvdisplay->ovmask  != NULL) freeimage(xvdisplay->ovmask);
	}
	xvdisplay->disp_image = NULL;
	xvdisplay->image      = NULL;
	xvdisplay->shape      = NULL;
	xvdisplay->clip       = NULL;
	xvdisplay->overlay    = NULL;
	xvdisplay->ovmask     = NULL;

	if (xvdisplay->ximage != NULL)
	{
	   XDestroyImage(xvdisplay->ximage);
	   xvdisplay->ximage = NULL;
	}
	if (xvdisplay->xshape != NULL)
	{
	   XDestroyImage(xvdisplay->xshape);
	   xvdisplay->xshape = NULL;
	}
	if (xvdisplay->xclip  != NULL)
	{
	   XDestroyImage(xvdisplay->xclip);
	   xvdisplay->xclip = NULL;
	}
	if (xvdisplay->xoverlay != NULL)
	{
	   XDestroyImage(xvdisplay->xoverlay);
	   xvdisplay->xoverlay = NULL;
	}
	if (xvdisplay->icon_ximage != NULL)
	{
	   XDestroyImage(xvdisplay->icon_ximage);
	   xvdisplay->icon_ximage = NULL;
	}


	if (xvdisplay->pixmap != NULL)
	{
	   XFreePixmap(display, xvdisplay->pixmap);
	   xvdisplay->pixmap = None;
	}
	if (xvdisplay->shape_mask != NULL)
	{
	   XFreePixmap(display, xvdisplay->shape_mask);
	   xvdisplay->shape_mask = None;
	}
	if (xvdisplay->clip_mask != NULL)
	{
	   XFreePixmap(display, xvdisplay->clip_mask);
	   xvdisplay->clip_mask = None;
	}
	if (xvdisplay->overlay_mask != NULL)
	{
	   XFreePixmap(display, xvdisplay->overlay_mask);
	   xvdisplay->overlay_mask = None;
	}
	if (xvdisplay->overlay_pixmap != NULL)
	{
	   XFreePixmap(display, xvdisplay->overlay_pixmap);
	   xvdisplay->overlay_pixmap = None;
	}
	if (xvdisplay->icon_pixmap != NULL)
	{
	   XFreePixmap(display, xvdisplay->icon_pixmap);
	   xvdisplay->icon_pixmap = None;
	}

        /*
         *  Clear the raster widget
         */
        i = 0;
        XtSetArg(args[i], XtNshape, xvdisplay->shape_mask);		i++;
        XtSetArg(args[i], XtNclip, xvdisplay->clip_mask);		i++;
	XtSetArg(args[i], XtNcolormap, xvdisplay->colormap);		i++;
        XtSetArg(args[i], XtNimage, xvdisplay->ximage);			i++;
        XtSetArg(args[i], XtNpixmap, xvdisplay->pixmap);		i++;
	XtSetArg(args[i], XtNoverlay, xvdisplay->overlay_pixmap);	i++;
	XtSetArg(args[i], XtNoverlayMask, xvdisplay->overlay_mask);	i++;
	XtSetValues(xvdisplay->raster, args, i);

	if (xvdisplay->icon != NULL)
	   xvd_update_icon(xvdisplay);

}  /* end xvd_clear_xvdisplay */



/************************************************************
*
*  MODULE NAME: xvd_update_xvdisplay
*
*      PURPOSE: Updates the all the associated images with the
*		xvdisplay structure at once.
*
*        INPUT: xvdisplay - the xvdisplay structure to be updated.
*		image     - the display image to be updated.
*		shape     - the shape image to be updated.
*		clip      - the clip image to be updated.
*		overlay   - the overlay image to be updated.
*
*       OUTPUT: returns True if we are successful, otherwise False.
*
*    CALLED BY: the application program
*
*   WRITTEN BY: Mark Young
*
*
*************************************************************/


int xvd_update_xvdisplay(xvdisplay, image, shape, clip, overlay)

DisplayStructure *xvdisplay;
struct xvimage   *image, *shape, *clip, *overlay;
{
	struct  xvimage *tmp_image, *tmp_disp, *tmp_shape, *tmp_clip,
			*tmp_overlay;


	tmp_image   = xvdisplay->image;
	tmp_disp    = xvdisplay->disp_image;
	tmp_shape   = xvdisplay->shape;
	tmp_clip    = xvdisplay->clip;
	tmp_overlay = xvdisplay->overlay;
	if (image   != NULL) xvdisplay->image   = image;
	if (shape   != NULL) xvdisplay->shape   = shape;
	if (clip    != NULL) xvdisplay->clip    = clip;
	if (overlay != NULL) xvdisplay->overlay = overlay;

	if (!xvd_update_image(xvdisplay, NULL))
	{
	   xvdisplay->image = tmp_image;
	   xvdisplay->disp_image = tmp_disp;
	   return(False);
	}
	else
	{
	   if (tmp_image != tmp_disp)
	      freeimage(tmp_disp);

	   if (tmp_image != NULL)
	      freeimage(tmp_image);
	}

	if (!xvd_update_shape(xvdisplay, NULL))
	{
	   xvdisplay->shape = tmp_shape;
	   return(False);
	}
	else if (tmp_shape != NULL)
	   freeimage(tmp_shape);

	if (!xvd_update_clip(xvdisplay, NULL))
	{
	   xvdisplay->clip  = tmp_clip;
	   return(False);
	}
	else if (tmp_clip != NULL)
	   freeimage(tmp_clip);

	if (!xvd_update_overlay(xvdisplay, NULL))
	{
	   xvdisplay->overlay = tmp_overlay;
	   return(False);
	}
	else if (tmp_overlay != NULL)
	   freeimage(tmp_overlay);

	return(True);

}  /* end xvd_update_xvdisplay */



/************************************************************
*
*  MODULE NAME: xvd_delete_xvdisplay
*
*      PURPOSE: deletes and free's all associated resources and
*		memory of and xvdisplay structure.  This routine
*		replaces the old xvd_delete_image() routine.
*
*	 INPUT: xvdisplay - the xvdisplay structure to be freed.
*
*       OUTPUT: none
*
*    CALLED BY: the application program
*
*   WRITTEN BY: Mark Young
*
*
*************************************************************/

xvd_delete_xvdisplay(xvdisplay)

DisplayStructure *xvdisplay;
{
	Display *display = xvdisplay->display;
	int screen = XDefaultScreen(display);

	if (xvdisplay == NULL)
	   return;

	if (xvdisplay->toplevel != NULL)
	{
	   XtUnmapWidget(xvdisplay->toplevel);
	   XtDestroyWidget(xvdisplay->toplevel);
	}
	else if (xvdisplay->raster != NULL)
	{
	   XtUnmapWidget(xvdisplay->raster);
	   XtDestroyWidget(xvdisplay->raster);
	}

	if (xvdisplay->icon != NULL)
	{
	   XtUnmapWidget(xvdisplay->icon);
	   XtDestroyWidget(xvdisplay->icon);
	}

	if (xvdisplay->colormap != XDefaultColormap(display, screen))
	   XFreeColormap(display, xvdisplay->colormap);

	/*
	 *  These images are specified by the user, so we need to check to
	 *  see if the user wants us to free these images for them.
	 *
	 *  Note: the disp_image and ovmask are internal images and therefore
	 *        should be freed
	 */
	if (xvdisplay->image != xvdisplay->disp_image &&
	    xvdisplay->disp_image != NULL)
	{
	   freeimage(xvdisplay->disp_image);
	}

	if (xvdisplay->overlay != xvdisplay->ovmask &&
	    xvdisplay->ovmask != NULL)
	{
	   freeimage(xvdisplay->ovmask);
	}

	if (xvdisplay->image   != NULL) freeimage(xvdisplay->image);
	if (xvdisplay->shape   != NULL) freeimage(xvdisplay->shape);
	if (xvdisplay->clip    != NULL) freeimage(xvdisplay->clip);
	if (xvdisplay->overlay != NULL) freeimage(xvdisplay->overlay);

	if (xvdisplay->ximage != NULL) XDestroyImage(xvdisplay->ximage);
	if (xvdisplay->xshape != NULL) XDestroyImage(xvdisplay->xshape);
	if (xvdisplay->xclip  != NULL) XDestroyImage(xvdisplay->xclip);
	if (xvdisplay->xoverlay != NULL) XDestroyImage(xvdisplay->xoverlay);
	if (xvdisplay->icon_ximage!=NULL) XDestroyImage(xvdisplay->icon_ximage);

	if (xvdisplay->pixmap != NULL)
	   XFreePixmap(display, xvdisplay->pixmap);

	if (xvdisplay->shape_mask != NULL)
	   XFreePixmap(display, xvdisplay->shape_mask);

	if (xvdisplay->clip_mask != NULL)
	   XFreePixmap(display, xvdisplay->clip_mask);

	if (xvdisplay->overlay_mask != NULL)
	   XFreePixmap(display, xvdisplay->overlay_mask);

	if (xvdisplay->overlay_pixmap != NULL)
	   XFreePixmap(display, xvdisplay->overlay_pixmap);

	if (xvdisplay->icon_pixmap != NULL)
	   XFreePixmap(display, xvdisplay->icon_pixmap);

	(void) xvd_delete_xvdisplay_list(xvdisplay);
	XtFree(xvdisplay);

}  /* end xvd_delete_xvdisplay */



/************************************************************
*
*  MODULE NAME: xvd_init_visual
*
*      PURPOSE: initializes the visual for a Display Structure.
*
*	 INPUT: xvdispaly - the DisplayStructure
*
*    CALLED BY: xvd_init_xvdisplay()
*
*   WRITTEN BY: Mark Young
*
*
*************************************************************/


int xvd_init_visual(xvdisplay)

DisplayStructure *xvdisplay;
{
	struct      xvimage *image;
	int	    i, id, count, greyscale_image;

	Display	    *display = xvdisplay->display;
	int	    screen = XDefaultScreen(display);

	long	    mask;
	Visual	    *default_visual;
	XVisualInfo vinfo, *vinfos;


	if (xvdisplay->image != NULL)
	{
	   image = xvdisplay->image;
	   if ((image->map_scheme == VFF_MS_NONE ||
	       image->map_storage_type == VFF_MAPTYP_1_BYTE &&
	       image->map_row_size == 1) &&
	       (xvd_truecolor_image(image) == False))
	   {
	      greyscale_image = True;
	   }
	   else
	      greyscale_image = False;
	}
	else
	   greyscale_image = False;

	/*
	 *   Find the useable visuals
	 */
	mask = VisualScreenMask;
	vinfo.screen = screen;
	vinfos = XGetVisualInfo(display, mask, &vinfo, &count);
	default_visual = DefaultVisual(display, screen);

	id = -1;
	for (i = 0; i < count; i++)
	{
	    if (xvdisplay->read_only == True)
	    {
	       if (vinfos[i].class == PseudoColor ||
                   vinfos[i].class == StaticColor ||
                   vinfos[i].class == TrueColor ||
                   vinfos[i].class == DirectColor ||
		   greyscale_image == True &&
		   (vinfos[i].class == StaticGray ||
		    vinfos[i].class == GrayScale))
	       {
		  if (id == -1)
		     id = i;
		  else if (vinfos[i].depth > vinfos[id].depth ||
			   (vinfos[i].visual == default_visual &&
			    vinfos[i].depth == vinfos[id].depth))
		  {
		     id = i;
		  }
	       }
	    }
	    else
	    {
	       if (vinfos[i].class == PseudoColor ||
	           vinfos[i].class == DirectColor ||
		   (greyscale_image == True && vinfos[i].class == GrayScale))
	       {
		  if (id == -1)
		     id = i;
		  else if (vinfos[i].depth > vinfos[id].depth ||
			   (vinfos[i].visual == default_visual &&
			    vinfos[i].depth == vinfos[id].depth))
		  {
		     id = i;
		  }
	       }
	   }
	}

	if (id == -1)
	{
	   if (xvdisplay->read_only == True)
	   {
	      xvf_error_wait("Error!  Unable to find suitable visual for \
displaying 'read only' images.  Please use the 'xdpyinfo' command to correctly \
verify that a reasonable visual is currently avaiable for displaying images.",
			"xvd_init_visual", NULL);
	   }
	   else
	   {
	      xvf_error_wait("Error!  Unable to find suitable visual for \
displaying 'read/write' images.  This application needs a PseudoColor or \
GrayScale visual class (if displaying a greyscale image).  Please use the \
'xdpyinfo' command to verify that a reasonable visual is currently \
available for displaying images.", "xvd_init_visual", NULL);
	   }
	   return(False);
	}
	xvdisplay->vinfo  = &vinfos[id];
	xvdisplay->visual = vinfos[id].visual;
	xvdisplay->depth  = vinfos[id].depth;


	/*
	 *  Found the best visual, but if no colormap is specified and we
	 *  are using the default colormap then go ahead and use it.
	 */
	if (xvdisplay->colormap == NULL)
	{
	   if (xvdisplay->visual == default_visual)
	   {
	      xvdisplay->colormap = DefaultColormap(display, screen);
	   }
	   else
	   {
	      xvdisplay->colormap = XCreateColormap(display, RootWindow(display,
			screen), xvdisplay->visual, AllocNone);
	   }
	}
	return(True);
}
