 /*
  * Khoros: $Id: create.c,v 1.4 1992/03/20 22:44:19 dkhoros Exp $
  */

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

 /*
  * $Log: create.c,v $
 * Revision 1.4  1992/03/20  22:44:19  dkhoros
 * VirtualPatch5
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability 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 OTHER DAMAGES WHAT-
 * SOEVER 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 PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

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

/*
 *  fonts used by create_pixel_display
 */
static  num_fonts = 5;
static  char *fonts[] =
{
          "fixed",
          "-adobe-times-medium-r-normal--12*",
          "-adobe-times-bold-r-normal--12*",
          "6x10",
          "variable"
};


/********************************************************
*
*  Routine Name:  create_display
*
*       Purpose:  prepares the animate workspace for the
*		  animation.
*
*         Input:  form   - the form
*		  index  - the index into the form
*		  widget - the workspace widget
*		  use_pixmap - create pixmap images
*		  use_iconic - create iconic animation as well
*		  use_root   - use the root window to animate
*
*        Output:  none
*
*     Called By:  leditimage()
*
*    Written By:  Mark Young & Tom Sauer
*
********************************************************/

create_display(form, index, parent, use_pixmap, use_iconic, use_root)

xvf_form *form;
Widget	 parent;
int	 index, use_pixmap, use_iconic, use_root;
{
	int	   i;
	Arg	   args[10];
	char	   temp[512];
	unsigned   long mask;
	void	   manage_icon(), redisplay_animate();


	/*
	 *  Create and place the raster widget and assign the colormap
	 *  to the raster widget.
	 */
	xvd_create_raster(display, parent, xvdisplay, False);
	xvd_set_colormap(xvdisplay->raster, xvdisplay->colormap);

	if (use_iconic == True)
	{
	   xvd_create_icon(xvdisplay->display, xvdisplay, 64, 64);
	   xvf_change_form_glyph(form, xvdisplay->icon, ICON);

	   mask = StructureNotifyMask | ExposureMask;
	   XtAddEventHandler(xvdisplay->icon, mask, FALSE, redisplay_animate,
			     NULL);
	}

	/*
	 *  Add a callback to handle the refreshing of the animate window.
	 */
	mask = StructureNotifyMask | ExposureMask;
	XtAddEventHandler(xvdisplay->raster, mask, FALSE, redisplay_animate,
			NULL);

	/*
	 *  Add a callback to handle the un-iconifying of the toplevel window
	 */
	mask = StructureNotifyMask;
	XtAddEventHandler(form->toplevel, mask, FALSE, manage_icon, form);

	/*
	 *  initialize the band number
	 */
	xvanimate = (AnimateStructure *) XtCalloc(1, sizeof(AnimateStructure));
	xvanimate->number    = 0;
	xvanimate->speed     = 0.5;
	xvanimate->direction = STOP;
	xvanimate->control   = LOOP;
	xvanimate->use_iconic = use_iconic;
	xvanimate->use_pixmap = use_pixmap;
	xvanimate->use_root   = use_root;
	xvanimate->show_band  = False;
	xvanimate->iconified  = False;


	/*
	 *  Create the gc used to render the images to the window.
	 */
        gc = XCreateGC(display, XtWindow(xvdisplay->raster), 0, NULL);
	XSetClipMask(display, gc, xvdisplay->clip_mask);

	/*
	 *  Load the font to be used when showing the band number
	 */
	for (i = 0; i < num_fonts; i++)
        {
            if ((xvanimate->font = XLoadQueryFont(display, fonts[i])) != NULL)
	       break;
	}

	if (xvanimate->font != NULL)
	{
	   XCharStruct ov_return;
	   int         ascent, descent, dir_return;

	   XSetFont(display, gc, xvanimate->font->fid);
	   XTextExtents(xvanimate->font, " 000 ", 5, &dir_return, &ascent,
			&descent, &ov_return);
	   xvanimate->font_height = ascent + descent;
	}

	/*
	 *  Now initialize the images to be displayed
	 */
	init_image(xvdisplay);
}



init_image(xvdisplay)

DisplayStructure *xvdisplay;
{
	int	   i, image_num;
	char	   error[512];
	struct	   xvimage **imagelist, **xvd_seperate_images();
	XImage	   *ximage, *icon_ximage;
	Pixmap	   pixmap, icon_pixmap;


	if (xvdisplay->image == NULL)
	   return;

	xvanimate->width     = xvdisplay->image->row_size;
	xvanimate->height    = xvdisplay->image->col_size;
	xvanimate->icon_width  = xvdisplay->image->row_size;
	xvanimate->icon_height = xvdisplay->image->col_size;

	/*
	 *  Set the foreground and background if the image is bit
	 *  so that the correct colors will be rendered.
	 */
	if (xvdisplay->image->data_storage_type == VFF_TYP_BIT)
	{
	   XSetForeground(display, gc, xvdisplay->xcolors[1].pixel);
	   XSetBackground(display, gc, xvdisplay->xcolors[0].pixel);
	}

	image_num = xvdisplay->image->num_data_bands;
	if (!(imagelist = xvd_seperate_images(xvdisplay->image, &image_num)))
	{
	   xvf_error_wait("Out of memory! Failed to seperate the images to \
be initialized.  Will not be able to animate any of these images.", "animate",
			 NULL);
	   return;
	}

	ximage = icon_ximage = NULL;
	for (i = 0; i < image_num; i++)
	{
	    printf("initializing band %d... ", i);
	    if (!(ximage = xvd_create_ximage(xvdisplay, imagelist[i], ximage)))
	    {
	       sprintf(error,"Error! Failed to convert the '%d' image to be \
displayed", i);
	       xvf_error_wait(error, "animate", NULL);
	       return;
	    }
	    else
	    {
	       if (xvanimate->use_pixmap == True)
		  pixmap = xvd_create_pixmap(xvdisplay, ximage, None);
	       else
		  pixmap = None;

	       icon_ximage = xvd_shrink_ximage(xvdisplay->display, ximage, 64,
			64, icon_ximage);
	       if (icon_ximage != NULL && xvanimate->use_pixmap == True)
		  icon_pixmap = xvd_create_pixmap(xvdisplay, icon_ximage, None);
	       else
		  icon_pixmap = None;

	       add_image(xvanimate, ximage, pixmap, icon_ximage, icon_pixmap);

	       /*
	        *  If the pixmap is None then we need to NULL out ximage
		*  so that a new one will be created next time we call
		*  xvd_create_ximage().
		*/
	       if (pixmap != None)
		  printf("(pixmap)  ");
	       else
	       {
		  printf("(ximage)  ", i);
		  ximage = NULL;
	       }

	       if (icon_pixmap == None)
		  icon_ximage = NULL;
	    }
	    printf("done\n", i);
	}
	free(imagelist);
	xvd_clear_image(xvdisplay, True);
}

add_image(xvanimate, ximage, pixmap, icon_ximage, icon_pixmap)

AnimateStructure *xvanimate;
XImage		 *ximage, *icon_ximage;
Pixmap		 pixmap, icon_pixmap;
{
	Image	*current;


	/*
	 *  create the current image to be added to the xvanimate list.
	 */
	current = (Image *) XtCalloc(1, sizeof(Image));

	if (pixmap == None)
	   current->ximage = ximage;
	else
	   current->pixmap = pixmap;

	if (icon_pixmap == None)
	   current->icon_ximage = icon_ximage;
	else
	   current->icon_pixmap = icon_pixmap;

	current->num = xvanimate->number++;
	current->depth  = ximage->depth;

	/*
	 *  If the list is currently empty then add it to the head of the
	 *  image list.  Otherwise add it to the end.
	 */ 
	if (xvanimate->head == NULL)
	{
	   current->prev = current->next = NULL;
	   xvanimate->head = xvanimate->tail = xvanimate->current = current;
	}
	else
	{
	   /*
	    *  If the head and tail are pointing to the same image
	    *  then we need to set the first image's next pointer
	    *  to this current image.
	    */
	   if (xvanimate->head == xvanimate->tail)
	      xvanimate->head->next = current;

	   xvanimate->tail->next = current;
	   current->prev = xvanimate->tail;
	   xvanimate->tail = current;
	   current->next = NULL;
	}
}

delete_image(xvanimate, num)

AnimateStructure *xvanimate;
int		 num;
{
	Image *current;


	/*
	 *  Race thru the image list looking for the image with the
	 *  corresponding "num".
	 */
	current = xvanimate->head;
	while (current != NULL)
	{
	   if (current->num == num)
	      break;
	   else
	      current = current->next;
	}

	/*
	 *  Delete the image from the list and free the associated memory.
	 */
	if (current != NULL)
	{
	   /*
	    *
	    */
	   if (current == xvanimate->head)
	   {
	      xvanimate->head = xvanimate->head->next;
	      if (xvanimate->head == NULL)
	         xvanimate->tail = NULL;
	      else
		 xvanimate->head->prev = NULL;
	   }
	   else if (current == xvanimate->tail)
	   {
	      xvanimate->tail = xvanimate->tail->prev;
	      xvanimate->tail->next = NULL;
	   }
	   else
	   {
	      current->next->prev = current->prev;
	      current->prev->next = current->next;
	   }

	   if (current->pixmap != NULL)
	      XFreePixmap(XtDisplay(xvdisplay->raster), current->pixmap);

	   if (current->ximage != NULL)
	      XDestroyImage(current->ximage);

	   if (current->icon_pixmap != NULL)
	      XFreePixmap(XtDisplay(xvdisplay->raster), current->icon_pixmap);

	   if (current->icon_ximage != NULL)
	      XDestroyImage(current->icon_ximage);

	   free(current);
	   xvanimate->number--;
	}
}

destroy_images(xvanimate)

AnimateStructure *xvanimate;
{
	Image *current, *next;

	/*
	 *  Race thru the image list killing the images.
	 */
	current = xvanimate->head;
	while (current != NULL)
	{
	   next = current->next;
	   delete_image(xvanimate, current->num);
	   current = next;
	}
}

int animate_test()
{
	XSynchronize(display, True);
}
