		/*************************************
		 *                                   *
		 *            Gadgets v2.0           *
		 *   by Torsten Jürgeleit in 05/91   *
		 *                                   *
		 *          Routines - Part 2        *
		 *                                   *
		 *************************************/

	/* Includes */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#include <functions.h>
#include <string.h>
#include "/render/render.h"
#include "/texts/texts.h"
#include "/borders/borders.h"
#include "gadgets.h"
#include "imports.h"

	/* Count entries in gadget data array */

   USHORT
count_gadget_data_entries(struct GadgetData  *gd)
{
   USHORT data_entries = 0;

   while (gd->gd_Type != INTUISUP_DATA_END &&
				      gd->gd_Type <= MAX_GADGET_DATA_TYPE) {
      data_entries++;
      gd++;
   }
   return(data_entries);
}
	/* Get buffer size for gadgets and borders */

   ULONG
get_gadget_buffer_size(struct GadgetList  *gl)
{
   struct RenderInfo  *ri = gl->gl_RenderInfo;
   struct GadgetData  *gd = gl->gl_Data;
   struct TextAttr    *text_attr;
   struct Image       *image;
   ULONG  flags;
   USHORT i, type, gadget_size, border_size, num, height, spacing,
	  data_entries = gl->gl_DataEntries;
   BYTE   **text;
   ULONG  buffer_size = 0;

   for (i = 0; i < data_entries; i++, gd++) {
      type  = gd->gd_Type;
      flags = gd->gd_Flags;
      /* if monochrome display then set HIGHCOMP flag */
      if (ri->ri_ScreenDepth == 1) {
	 flags |= GADGET_DATA_FLAG_HIGH_COMP;
      }
      switch(type) {
	 case GADGET_DATA_TYPE_BUTTON :
	    gadget_size = sizeof(struct ExtendedGadget);
	    if ((flags & GADGET_DATA_FLAG_BUTTON_TOGGLE &&
				   flags & GADGET_DATA_FLAG_BUTTON_IMAGE) ||
				       flags & GADGET_DATA_FLAG_HIGH_COMP) {
	       border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
	    } else {
	       border_size = 2 * BORDER_TYPE_BOX1_BUFFER_SIZE;
	    }
	    /* add image struct size if chip mem copies of image data needed */
	    if (gd->gd_Flags & GADGET_DATA_FLAG_BUTTON_IMAGE) {
	       if ((image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonNormalRender) &&
				       check_gadget_image(image) == FALSE) {
		  buffer_size += sizeof(struct Image);
	       }
	       if ((image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonSelectRender) &&
				       check_gadget_image(image) == FALSE) {
		  buffer_size += sizeof(struct Image);
	       }
	    }
	    break;
	 case GADGET_DATA_TYPE_CHECK :
	    gadget_size = sizeof(struct ExtendedGadget);
	    border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
	    break;
	 case GADGET_DATA_TYPE_MX :
	    text = gd->gd_SpecialData.gd_MXData.gd_MXTextArray;
	    num  = 0;
	    while (*text++) {
	       num++;
	    }
	    gadget_size = num * (sizeof(struct ExtendedGadget) +
			  sizeof(struct IntuiText)) + sizeof(struct MXData);
	    border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
	    break;
	 case GADGET_DATA_TYPE_STRING :
	 case GADGET_DATA_TYPE_INTEGER :
	    /* calc size of input buffer */
	    if (type == GADGET_DATA_TYPE_STRING) {
	       num = gd->gd_SpecialData.gd_InputData.gd_InputLen;
	       if (flags & (GADGET_DATA_FLAG_STRING_UNSIGNED_DEC |
					GADGET_DATA_FLAG_STRING_SIGNED_DEC |
					       GADGET_DATA_FLAG_STRING_HEX |
					     GADGET_DATA_FLAG_STRING_BIN)) {
		  if (num < MAX_BIN_NUM_DIGITS) {
		     num = MAX_BIN_NUM_DIGITS;
		  }
	       }
	    } else {
	       num = MAX_DEC_NUM_DIGITS;
	    }
	    if (num & 1) {   /* odd input len ? */
	       num += 1;
	    } else {
	       num += 2;   /* inc for end of string marker */
	    }
	    gadget_size = sizeof(struct ExtendedGadget) +
					    sizeof(struct StringInfo) + num;
	    border_size = BORDER_TYPE_BOX2_BUFFER_SIZE;
	    break;
	 case GADGET_DATA_TYPE_SLIDER :
	    gadget_size = sizeof(struct ExtendedGadget) +
			    sizeof(struct PropInfo) + sizeof(struct Image) +
						  sizeof(struct SliderData);
	    border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
	    break;
	 case GADGET_DATA_TYPE_SCROLLER :
	    if (flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS) {
	       gadget_size = sizeof(struct ExtendedGadget) +
			    sizeof(struct PropInfo) + sizeof(struct Image) +
						sizeof(struct ScrollerData);
	       border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
	    } else {
	       gadget_size = 3 * sizeof(struct ExtendedGadget) +
			    sizeof(struct PropInfo) + sizeof(struct Image) +
						sizeof(struct ScrollerData);
	       if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
		  border_size = 3 * BORDER_TYPE_BOX1_BUFFER_SIZE;
	       } else {
		  border_size = 5 * BORDER_TYPE_BOX1_BUFFER_SIZE;
	       }
	    }
	    break;
	 case GADGET_DATA_TYPE_CYCLE :
	    gadget_size = sizeof(struct ExtendedGadget) +
						   sizeof(struct CycleData);
	    if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
	       border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
	    } else {
	       border_size = 2 * BORDER_TYPE_BOX1_BUFFER_SIZE;
	    }
	    break;
	 case GADGET_DATA_TYPE_COUNT :
	    gadget_size = sizeof(struct ExtendedGadget) +
						   sizeof(struct CountData);
	    border_size = 2 * BORDER_TYPE_BOX1_BUFFER_SIZE;
	    break;
	 case GADGET_DATA_TYPE_LISTVIEW :
	    if (flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY) {
	       num = 0;
	    } else {
	       if (!(text_attr = gd->gd_TextAttr)) {
		  text_attr = &gl->gl_RenderInfo->ri_TextAttr;
	       }
	       height  = gd->gd_Height;
	       spacing = gd->gd_SpecialData.gd_ListViewData.gd_ListViewSpacing;
	       if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
		  height -= 2 * 1;
	       }
	       num = (height + spacing) / (text_attr->ta_YSize + spacing);
	    }
	    gadget_size = (3 + num) * sizeof(struct ExtendedGadget) +
			    sizeof(struct PropInfo) + sizeof(struct Image) +
						sizeof(struct ListViewData);
	    if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
	       border_size = 4 * BORDER_TYPE_BOX1_BUFFER_SIZE;
	    } else {
	       border_size = 6 * BORDER_TYPE_BOX1_BUFFER_SIZE;
	    }
	    break;
	 case GADGET_DATA_TYPE_PALETTE :
	    num         = 1L << gd->gd_SpecialData.gd_PaletteData.gd_PaletteDepth;
	    gadget_size = num * (sizeof(struct ExtendedGadget) +
			 sizeof(struct Image)) + sizeof(struct PaletteData);
	    if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
	       border_size = num * BORDER_TYPE_BOX1_BUFFER_SIZE;
	    } else {
	       border_size = num * (2 * BORDER_TYPE_BOX1_BUFFER_SIZE);
	    }
	    if (!(flags & GADGET_DATA_FLAG_PALETTE_NO_INDICATOR)) {
	       gadget_size += sizeof(struct ExtendedGadget) +
						       sizeof(struct Image);
	       border_size += BORDER_TYPE_BOX1_BUFFER_SIZE;
	    }
	    break;
      }
      buffer_size += gadget_size;
      if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	 buffer_size += border_size;
      }
   }
   return(buffer_size);
}
	/* Get buffer size for image data */

   ULONG
get_image_buffer_size(struct GadgetList  *gl)
{
   struct GadgetData  *gd = gl->gl_Data;
   struct Image       *image;
   ULONG  buffer_size = 0;
   USHORT i, data_entries = gl->gl_DataEntries;

   for (i = 0; i < data_entries; i++, gd++) {
      if (gd->gd_Type == GADGET_DATA_TYPE_BUTTON &&
			   (gd->gd_Flags & GADGET_DATA_FLAG_BUTTON_IMAGE)) {
	 if ((image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonNormalRender) &&
				       check_gadget_image(image) == FALSE) {
	    buffer_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0))
					 * image->Height * image->Depth * 2;
	 }
	 if ((image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonSelectRender) &&
				       check_gadget_image(image) == FALSE) {
	    buffer_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0))
					 * image->Height * image->Depth * 2;
	 }
      }
   }
   return(buffer_size);
}
	/* Initialize gadgets from gadget list */

   VOID
init_gadgets(struct GadgetList  *gl, SHORT hoffset, SHORT voffset)
{
   struct RenderInfo      *ri = gl->gl_RenderInfo;
   struct GadgetData      *gd;
   struct ExtendedGadget  *egad, *first_egad;
   struct Image           *image;
   struct IntuiText       itext;
   struct TextAttr        *text_attr;
   struct MXData          *mx;
   struct SliderData      *sl;
   struct ScrollerData    *sc;
   struct CycleData       *cy;
   struct CountData       *co;
   struct ListViewData    *lv;
   struct PaletteData     *pd;
   BYTE   **text, *buffer = gl->gl_GadgetBuffer,
	  *image_buffer = gl->gl_ImageBuffer;
   ULONG  min, max, flags;
   USHORT i, j, k, type, save_left_edge, left_edge, top_edge, width, height,
	  max_width, num, len, xoffset, yoffset, xmin, ymin, xnum, ynum,
	  yinc, spacing, data_entries = gl->gl_DataEntries;

   for (i = 0, gd = gl->gl_Data; i < data_entries; i++, gd++) {
      /* get gadget data */
      type      = gd->gd_Type;
      flags     = gd->gd_Flags;
      left_edge = gd->gd_LeftEdge + hoffset;
      top_edge  = gd->gd_TopEdge + voffset;
      width     = gd->gd_Width;
      height    = gd->gd_Height;
      text_attr = (gd->gd_TextAttr ? gd->gd_TextAttr : &ri->ri_TextAttr);
      /* inner window position needed ? */
      if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
	 left_edge += ri->ri_WindowBorderLeft;
	 top_edge  += ri->ri_WindowBorderTop;
      }
      /* init intui text */
      itext.ITextFont = text_attr;
      /* get gadget buffer ptr and reserve buffer */
      egad    = first_egad = gl->gl_Gadgets[i] = (struct ExtendedGadget *)
								     buffer;
      buffer += sizeof(struct ExtendedGadget);
      /* calc border offsets */
      if (flags & GADGET_DATA_FLAG_NO_BORDER) {
	 xoffset = 0;
	 yoffset = 0;
      } else {
	 switch (type) {
	    case GADGET_DATA_TYPE_MX :
	       xoffset = 8;
	       yoffset = 4;
	       break;
	    case GADGET_DATA_TYPE_STRING :
	    case GADGET_DATA_TYPE_INTEGER :
	       xoffset = 6;
	       yoffset = 3;
	       break;
	    case GADGET_DATA_TYPE_CYCLE :
	    case GADGET_DATA_TYPE_COUNT :
	       xoffset = 2;
	       yoffset = 1;
	       break;
	    default :
	       xoffset = 4;
	       yoffset = 2;
	       break;
	 }
      }
      /* if fixed gadget dimensions or data buffers so init them yet */
      switch (type) {
	 case GADGET_DATA_TYPE_CHECK :
	    /* calc fixed dimensions of check gadget */
	    width  = IMAGE_CHECK_WIDTH + 2 * IMAGE_HORIZ_OFFSET;
	    height = IMAGE_CHECK_HEIGHT + 2 * IMAGE_VERT_OFFSET;
	    break;
	 case GADGET_DATA_TYPE_MX :
	    /* init mx data */
	    mx      = (struct MXData *)buffer;
	    buffer += sizeof(struct MXData);
	    /* calc fixed dimensions of mx gadget */
	    width  = IMAGE_KNOB_WIDTH;
	    height = IMAGE_KNOB_HEIGHT;
	    /* calc vertical offset between mx gadget */
	    if ((yinc = text_attr->ta_YSize) < height) {
	       yinc = height;
	    }
	    yinc += gd->gd_SpecialData.gd_MXData.gd_MXSpacing;
	    /* count mx gadgets and calc maximal text width */
	    text      = gd->gd_SpecialData.gd_MXData.gd_MXTextArray;
	    num       = 0;
	    max_width = 0;
	    while (*text) {
	       itext.IText = (UBYTE *)*text++;
	       if ((len = IntuiTextLength(&itext)) > max_width) {
		  max_width = len;
	       }
	       num++;
	    }
	    mx->mx_TextEntries = num;
	    /* left and top edge of gadget */
	    if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
	       left_edge += max_width + xoffset + 8;
	    } else {
	       left_edge += xoffset;
	    }
	    if (text_attr->ta_YSize > height) {
	       top_edge += (text_attr->ta_YSize - height) / 2 + yoffset;
	    } else {
	       top_edge += yoffset;
	    }
	    break;
	 case GADGET_DATA_TYPE_STRING :
	 case GADGET_DATA_TYPE_INTEGER :
	    /* calc fixed height of input gadgets */
	    height = ri->ri_TextAttr.ta_YSize;
	    break;
	 case GADGET_DATA_TYPE_SLIDER :
	    /* init slider data */
	    sl      = (struct SliderData *)buffer;
	    buffer += sizeof(struct SliderData);
	    break;
	 case GADGET_DATA_TYPE_SCROLLER :
	    /* calc minimum dimensions of scroller gadget */
	    if (!(flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS)) {
	       xmin = IMAGE_ARROW_WIDTH + IMAGE_HORIZ_OFFSET + xoffset;
	       ymin = IMAGE_ARROW_HEIGHT + IMAGE_VERT_OFFSET + yoffset;
	       if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
		  if (width < xmin) {
		     width = xmin;
		  }
		  if (height < 3 * ymin) {
		     height = 3 * ymin;
		  }
	       } else {
		  if (width < 3 * xmin) {
		     width = 3 * xmin;
		  }
		  if (height < ymin) {
		     height = ymin;
		  }
	       }
	    }
	    /* init scroller data */
	    sc      = (struct ScrollerData *)buffer;
	    buffer += sizeof(struct ScrollerData);
	    break;
	 case GADGET_DATA_TYPE_CYCLE :
	    /* init cycle data */
	    cy      = (struct CycleData *)buffer;
	    buffer += sizeof(struct CycleData);
	    break;
	 case GADGET_DATA_TYPE_COUNT :
	    /* init count data */
	    co      = (struct CountData *)buffer;
	    buffer += sizeof(struct CountData);
	    break;
	 case GADGET_DATA_TYPE_LISTVIEW :
	    /* calc minimum dimension of list view gadget */
	    xmin = IMAGE_ARROW_WIDTH + IMAGE_HORIZ_OFFSET + xoffset;
	    ymin = IMAGE_ARROW_HEIGHT + IMAGE_VERT_OFFSET + yoffset;
	    if (height < 3 * ymin) {
	       height = 3 * ymin;
	    }
	    spacing = gd->gd_SpecialData.gd_ListViewData.gd_ListViewSpacing;
	    yinc    = text_attr->ta_YSize + spacing;
	    num     = (height - 2 * yoffset + spacing) / yinc;
	    height  = num * yinc + 2 * yoffset;
	    /* init list view data */
	    lv      = (struct ListViewData *)buffer;
	    buffer += sizeof(struct ListViewData);
	    break;
	 case GADGET_DATA_TYPE_PALETTE :
	    /* calc dimension of color squares of palette */
	    min  = gd->gd_SpecialData.gd_PaletteData.gd_PaletteColorOffset;
	    max  = 1L << gd->gd_SpecialData.gd_PaletteData.gd_PaletteDepth;
	    xnum = max;   /* start with all squares in a horizontal line */
	    ynum = 1;
	    while (xnum > 1 && (width / xnum) / 2 < height / ynum) {
	       xnum /= 2;
	       ynum *= 2;
	    }
	    if (!(flags & GADGET_DATA_FLAG_PALETTE_NO_INDICATOR)) {
	       /* insert color indicator */
	       if (flags & GADGET_DATA_FLAG_PALETTE_INDICATOR_TOP) {
		  ynum++;
	       } else {
		  xnum++;
	       }
	    }
	    /* calc gadget dimension */
	    if (xnum == 1) {
	       xmin = width;
	    } else {
	       xmin  = (width - 2 * (xnum - 1)) / xnum;
	       width = xmin * xnum + 2 * (xnum - 1);
	    }
	    if (ynum == 1) {
	       ymin = height;
	    } else {
	       ymin   = (height - 1 * (ynum - 1)) / ynum;
	       height = ymin * ynum + 1 * (ynum - 1);
	    }
	    /* init palette data */
	    pd      = (struct PaletteData *)buffer;
	    buffer += sizeof(struct PaletteData);
	    break;
      }
      /* init gadget */
      switch (type) {
	 case GADGET_DATA_TYPE_BUTTON :
	    buffer = init_extended_gadget(egad, buffer, gl, i,
		    EXTENDED_GADGET_TYPE_BUTTON, left_edge, top_edge, width,
								    height);
	    break;
	 case GADGET_DATA_TYPE_CHECK :
	    buffer = init_extended_gadget(egad, buffer, gl, i,
		     EXTENDED_GADGET_TYPE_CHECK, left_edge, top_edge, width,
								    height);
	    break;
	 case GADGET_DATA_TYPE_MX :
	    /* init all mx gadgets */
	    text = gd->gd_SpecialData.gd_MXData.gd_MXTextArray;
	    for (j = 0; j < num; j++, text++) {
	       buffer = init_extended_gadget(egad, buffer, gl, i,
			EXTENDED_GADGET_TYPE_MX, left_edge, top_edge, width,
								    height);
	       buffer = init_mx_text(egad, buffer, *text, width, height,
							  flags, text_attr);
	       egad->eg_Gadget.GadgetID = j;   /* num of mx gadget */
	       if (j < (num - 1)) {   /* another mx gadget ? */
		  top_edge += yinc;
		  egad      = egad->eg_NextGadget =
					    (struct ExtendedGadget *)buffer;
		  buffer   += sizeof(struct ExtendedGadget);
	       }
	    }
	    /* calc area dimension and draw border around it */
	    width += max_width + 2 * xoffset + 8;
	    height = yinc * num + 2 * yoffset -
				  gd->gd_SpecialData.gd_MXData.gd_MXSpacing;
	    if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	       if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
		  left_edge = -(max_width + xoffset + 8);
	       } else {
		  left_edge = -xoffset;   /* default right */
	       }
	       if (text_attr->ta_YSize > height) {
		  top_edge = -((text_attr->ta_YSize - height) / 2 + yoffset);
	       } else {
		  top_edge = -yoffset;
	       }
	       first_egad->eg_Flags  = EXTENDED_GADGET_FLAG_RENDER_BORDER;
	       first_egad->eg_Render = (APTR)buffer;
	       buffer                = init_border(ri, buffer, left_edge,
			 top_edge, width, height, BORDER_DATA_TYPE_BOX1_IN);
	    }
	    break;
	 case GADGET_DATA_TYPE_STRING :
	    buffer = init_extended_gadget(egad, buffer, gl, i,
		    EXTENDED_GADGET_TYPE_STRING, left_edge, top_edge, width,
								    height);
	    break;
	 case GADGET_DATA_TYPE_INTEGER :
	    buffer = init_extended_gadget(egad, buffer, gl, i,
		   EXTENDED_GADGET_TYPE_INTEGER, left_edge, top_edge, width,
								    height);
	    break;
	 case GADGET_DATA_TYPE_SLIDER :
	    /* init slider data */
	    sl->sl_Flags = flags;
	    sl->sl_Min   = gd->gd_SpecialData.gd_SliderData.gd_SliderMin;
	    sl->sl_Max   = gd->gd_SpecialData.gd_SliderData.gd_SliderMax;
	    buffer       = init_extended_gadget(egad, buffer, gl, i,
		      EXTENDED_GADGET_TYPE_SLIDER_PROP, left_edge, top_edge,
							     width, height);
	    break;
	 case GADGET_DATA_TYPE_SCROLLER :
	    /* init scroller data */
	    sc->sc_Flags   = flags;
	    sc->sc_Total   = gd->gd_SpecialData.gd_ScrollerData.gd_ScrollerTotal;
	    sc->sc_Visible = gd->gd_SpecialData.gd_ScrollerData.gd_ScrollerVisible;
	    /* init scroller gadgets */
	    if (flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS) {
	       buffer = init_extended_gadget(egad, buffer, gl, i,
			      EXTENDED_GADGET_TYPE_SCROLLER_PROP, left_edge,
						   top_edge, width, height);
	    } else {
	       if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
		  /* create vertical scroller - prop gadget first */
		  buffer = init_extended_gadget(egad, buffer, gl, i,
			      EXTENDED_GADGET_TYPE_SCROLLER_PROP, left_edge,
				  top_edge, width, height - 2 * (ymin + 1));
		  /* init scroller up arrow gadget */
		  egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
								     buffer;
		  buffer += sizeof(struct ExtendedGadget);
		  buffer  = init_extended_gadget(egad, buffer, gl, i,
				EXTENDED_GADGET_TYPE_SCROLLER_UP, left_edge,
			     top_edge + height - 2 * ymin - 1, width, ymin);
		  /* change type of vertical scroller arrow gadget for correct counting */
		  egad->eg_Type = EXTENDED_GADGET_TYPE_SCROLLER_DOWN;
		  /* init scroller down arrow gadget */
		  egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
								     buffer;
		  buffer += sizeof(struct ExtendedGadget);
		  buffer  = init_extended_gadget(egad, buffer, gl, i,
			      EXTENDED_GADGET_TYPE_SCROLLER_DOWN, left_edge,
				     top_edge + height - ymin, width, ymin);
		  /* change type of vertical scroller arrow gadget for correct counting */
		  egad->eg_Type = EXTENDED_GADGET_TYPE_SCROLLER_UP;
	       } else {
		  /* create horizontal scroller - prop gadget first */
		  buffer = init_extended_gadget(egad, buffer, gl, i,
			      EXTENDED_GADGET_TYPE_SCROLLER_PROP, left_edge,
				  top_edge, width - 2 * (xmin + 1), height);
		  /* init scroller left arrow gadget */
		  egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
								     buffer;
		  buffer += sizeof(struct ExtendedGadget);
		  buffer  = init_extended_gadget(egad, buffer, gl, i,
			     EXTENDED_GADGET_TYPE_SCROLLER_LEFT, left_edge +
			      width - 2 * xmin - 1, top_edge, xmin, height);
		  /* init scroller right arrow gadget */
		  egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
								     buffer;
		  buffer += sizeof(struct ExtendedGadget);
		  buffer  = init_extended_gadget(egad, buffer, gl, i,
			    EXTENDED_GADGET_TYPE_SCROLLER_RIGHT, left_edge +
				      width - xmin, top_edge, xmin, height);
	       }
	    }
	    break;
	 case GADGET_DATA_TYPE_CYCLE :
	    /* count entries and calc max width of cycle text array */
       	    text = gd->gd_SpecialData.gd_CycleData.gd_CycleTextArray;
	    num  = max_width = 0;
	    while (*text) {
	       itext.IText = (UBYTE *)*text++;
	       if ((len = IntuiTextLength(&itext)) > max_width) {
		  max_width = len;
	       }
	       num++;
	    }
	    /* init cycle data */
	    image              = &ri->ri_Images[IMAGE_CYCLE];
	    xmin               = image->LeftEdge + image->Width + xoffset + 4;
	    cy->cy_LeftEdge    = left_edge + xmin + (SHORT)(width -
						  max_width - xmin - 4) / 2;
	    cy->cy_TopEdge     = top_edge + (SHORT)(height -
						   text_attr->ta_YSize) / 2;
	    cy->cy_Width       = max_width;
	    cy->cy_Height      = text_attr->ta_YSize;
	    cy->cy_Flags       = flags;
	    cy->cy_TextAttr    = text_attr;
	    cy->cy_TextArray   = gd->gd_SpecialData.gd_CycleData.gd_CycleTextArray;
	    cy->cy_TextEntries = num;
	    buffer             = init_extended_gadget(egad, buffer, gl, i,
		     EXTENDED_GADGET_TYPE_CYCLE, left_edge, top_edge, width,
								    height);
	    break;
	 case GADGET_DATA_TYPE_COUNT :
	    /* calc max width of count value */
	    min = gd->gd_SpecialData.gd_CountData.gd_CountMin;
	    max = gd->gd_SpecialData.gd_CountData.gd_CountMax;
	    if (flags & GADGET_DATA_FLAG_COUNT_SIGNED_DEC) {
	       len       = convert_signed_dec((LONG)min, (BYTE *)NULL);
	       max_width = convert_signed_dec((LONG)max, (BYTE *)NULL);
	    } else {
	       len       = convert_unsigned_dec(min, (BYTE *)NULL);
	       max_width = convert_unsigned_dec(max, (BYTE *)NULL);
	    }
	    if (len > max_width) {
	       max_width = len;
	    }
	    itext.IText = (UBYTE *)"8";
	    max_width  *= IntuiTextLength(&itext);
	    /* init count data */
	    co->co_LeftEdge = left_edge + (SHORT)(width - max_width) / 2;
	    co->co_TopEdge  = top_edge + (SHORT)(height -
					        text_attr->ta_YSize) / 2;
	    co->co_Width    = max_width;
	    co->co_Height   = text_attr->ta_YSize;
	    co->co_Flags    = flags;
	    co->co_TextAttr = text_attr;
	    co->co_Min      = min;
	    co->co_Max      = max;
	    buffer          = init_extended_gadget(egad, buffer, gl, i,
		     EXTENDED_GADGET_TYPE_COUNT, left_edge, top_edge, width,
								    height);
	    break;
	 case GADGET_DATA_TYPE_LISTVIEW :
	    /* init list view data */
	    lv->lv_LeftEdge       = left_edge + xoffset;
	    lv->lv_TopEdge        = top_edge + yoffset;
	    lv->lv_Width          = width - 2 * xoffset - xmin - 2;
	    lv->lv_Height         = height - 2 * yoffset;
	    lv->lv_Flags          = flags;
	    lv->lv_TextAttr       = text_attr;
	    lv->lv_VisibleEntries = num;
	    lv->lv_EntryHeight    = yinc;
	    /* create vertical scroller - prop gadget first */
	    left_edge += width - xmin;
	    buffer     = init_extended_gadget(egad, buffer, gl, i,
		    EXTENDED_GADGET_TYPE_LISTVIEW_PROP, left_edge, top_edge,
					     xmin, height - 2 * (ymin + 1));
	    /* create entry field border */
	    if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	       ((struct Border *)egad->eg_Render)->NextBorder->NextBorder =
						    (struct Border *)buffer;
	       if (flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY) {
		  j = BORDER_DATA_TYPE_BOX1_IN;
	       } else {
		  j = BORDER_DATA_TYPE_BOX1_OUT;
	       }
	       buffer = init_border(ri, buffer, -(width + xoffset - xmin),
				     -yoffset, width - xmin - 2, height, j);
	    }
	    /* init list view up arrow gadget */
	    egad    = egad->eg_NextGadget = (struct ExtendedGadget *)buffer;
	    buffer += sizeof(struct ExtendedGadget);
	    buffer  = init_extended_gadget(egad, buffer, gl, i,
		     EXTENDED_GADGET_TYPE_LISTVIEW_UP, left_edge, top_edge +
					 height - 2 * ymin - 1, xmin, ymin);
	    /* init list view down arrow gadget */
	    egad    = egad->eg_NextGadget = (struct ExtendedGadget *)buffer;
	    buffer += sizeof(struct ExtendedGadget);
	    buffer  = init_extended_gadget(egad, buffer, gl, i,
		   EXTENDED_GADGET_TYPE_LISTVIEW_DOWN, left_edge, top_edge +
						 height - ymin, xmin, ymin);
	    /* init list view entry gadgets */
	    if (!(flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY)) {
	       left_edge = lv->lv_LeftEdge;
	       top_edge  = lv->lv_TopEdge;
	       for (j = 0; j < num; j++, top_edge += yinc) {
		  egad            = egad->eg_NextGadget =
					    (struct ExtendedGadget *)buffer;
		  buffer         += sizeof(struct ExtendedGadget);
		  buffer          = init_extended_gadget(egad, buffer, gl,
			  i, EXTENDED_GADGET_TYPE_LISTVIEW_ENTRY, left_edge,
					      top_edge, lv->lv_Width, yinc);
		  egad->eg_Gadget.GadgetID = j;   /* num of entry gadget */
	       }
	    }
	    break;
	 case GADGET_DATA_TYPE_PALETTE :
	    /* init palette data */
	    pd->pd_Flags       = flags;
	    pd->pd_ColorOffset = min;
	    pd->pd_MaxColors   = max;
	    /* build color indicator */
	    if (!(flags & GADGET_DATA_FLAG_PALETTE_NO_INDICATOR)) {
	       if (flags & GADGET_DATA_FLAG_PALETTE_INDICATOR_TOP) {
		  buffer    = init_extended_gadget(egad, buffer, gl, i,
			  EXTENDED_GADGET_TYPE_PALETTE_INDICATOR, left_edge,
						     top_edge, width, ymin);
		  top_edge += ymin + 1;
		  ynum--;
	       } else {
		  buffer     = init_extended_gadget(egad, buffer, gl, i,
			  EXTENDED_GADGET_TYPE_PALETTE_INDICATOR, left_edge,
						    top_edge, xmin, height);
		  left_edge += xmin + 2;
		  xnum--;
	       }
	       egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
								     buffer;
	       buffer += sizeof(struct ExtendedGadget);
	    }
	    /* build color gadgets */
	    save_left_edge = left_edge;
	    num            = gd->gd_SpecialData.gd_PaletteData.gd_PaletteColorOffset;
	    for (j = 0; j < ynum; j++, top_edge += ymin + 1) {
	       for (k = 0, left_edge = save_left_edge; k < xnum; k++,
						    left_edge += xmin + 2) {
		  buffer = init_extended_gadget(egad, buffer, gl, i,
			      EXTENDED_GADGET_TYPE_PALETTE_COLOR, left_edge,
						      top_edge, xmin, ymin);
		  ((struct Image *)egad->eg_Render)->PlaneOnOff = egad->eg_Gadget.GadgetID = num++;
		  if (j < (ynum - 1) || k < (xnum - 1)) {
		     egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
								     buffer;
		     buffer += sizeof(struct ExtendedGadget);
		  }
	       }
	    }
	    break;
      }
      /* init border dimension for editor */
      first_egad->eg_BorderWidth  = width;
      first_egad->eg_BorderHeight = height;
      /* init text and images */
      if (gd->gd_Text) {
	 init_gadget_text(first_egad, gd->gd_Text, width, height, flags,
								 text_attr);
      }
      if (image_buffer && type == GADGET_DATA_TYPE_BUTTON && (flags &
					  GADGET_DATA_FLAG_BUTTON_IMAGE)) {
	 image_buffer = init_image_data(egad, image_buffer);
      }
      set_gadget_attributes(gl, i, flags, gd->gd_SpecialData.gd_Data.gd_Data1,
					gd->gd_SpecialData.gd_Data.gd_Data2,
				       gd->gd_SpecialData.gd_Data.gd_Data3);
   }
}
	/* Init extended gadget */

   STATIC BYTE *
init_extended_gadget(struct ExtendedGadget  *egad, BYTE *buffer,
		     struct GadgetList  *gl, USHORT data_entry, USHORT type,
	     USHORT left_edge, USHORT top_edge, USHORT width, USHORT height)
{
   struct RenderInfo  *ri = gl->gl_RenderInfo;
   struct GadgetData  *gd = gl->gl_Data + data_entry;
   struct Gadget      *gad = &egad->eg_Gadget;
   struct StringInfo  *sinfo;
   struct PropInfo    *pinfo;
   struct Image       *image;
   ULONG  flags = gd->gd_Flags;
   USHORT len;

   /* if monochrome display then set HIGHCOMP flag */
   if (ri->ri_ScreenDepth == 1) {
      flags |= GADGET_DATA_FLAG_HIGH_COMP;
   }
   /* init extended gadget */
   egad->eg_Type       = type;
   egad->eg_DataEntry  = data_entry;
   egad->eg_GadgetList = gl;
   /* init normal gadget */
   gad->LeftEdge      = left_edge;
   gad->TopEdge       = top_edge;
   gad->Width         = width;
   gad->Height        = height;
   gad->MutualExclude = ISUP_ID;
   switch (type) {
      case EXTENDED_GADGET_TYPE_BUTTON :
	 gad->GadgetType = BOOLGADGET;
	 if (flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) {
	    gad->Activation = RELVERIFY | TOGGLESELECT;
	    if (flags & GADGET_DATA_FLAG_BUTTON_IMAGE) {
	       gad->Flags = GADGIMAGE | GADGHIMAGE;
	       buffer     = init_gadget_image(egad, gd, buffer);
	    }
	 } else {
	    gad->Activation = RELVERIFY;
	    if (flags & GADGET_DATA_FLAG_BUTTON_IMAGE) {
	       if ((flags & GADGET_DATA_FLAG_NO_BORDER) &&
				    !(flags & GADGET_DATA_FLAG_HIGH_COMP)) {
		  gad->Flags = GADGIMAGE | GADGHIMAGE;
		  buffer     = init_gadget_image(egad, gd, buffer);
	       } else {
		  egad->eg_Flags = EXTENDED_GADGET_FLAG_RENDER_IMAGE;
		  buffer         = init_gadget_image(egad, gd, buffer);
	       }
	    }
	 }
	 break;
      case EXTENDED_GADGET_TYPE_CHECK :
      case EXTENDED_GADGET_TYPE_MX :
	 gad->GadgetType = BOOLGADGET;
	 gad->Activation = TOGGLESELECT | GADGIMMEDIATE;
	 gad->Flags      = GADGIMAGE | GADGHIMAGE;
	 if (type == EXTENDED_GADGET_TYPE_CHECK) {
	    gad->GadgetRender = (APTR)&ri->ri_Images[IMAGE_CHECK_UNSELECTED];
	    gad->SelectRender = (APTR)&ri->ri_Images[IMAGE_CHECK_SELECTED];
	 } else {
	    gad->GadgetRender = (APTR)&ri->ri_Images[IMAGE_KNOB_UNSELECTED];
	    gad->SelectRender = (APTR)&ri->ri_Images[IMAGE_KNOB_SELECTED];
	 }
	 break;
      case EXTENDED_GADGET_TYPE_STRING :
      case EXTENDED_GADGET_TYPE_INTEGER :
	 gad->GadgetType = STRGADGET;
	 if (type == EXTENDED_GADGET_TYPE_STRING) {
	    gad->Activation = RELVERIFY;
	 } else {
	    gad->Activation = RELVERIFY | LONGINT;
	 }
	 gad->Flags       = GADGHCOMP;
	 gad->SpecialInfo = (APTR)buffer;
	 /* calc size of input buffer */
	 if (type == GADGET_DATA_TYPE_STRING) {
	    len = gd->gd_SpecialData.gd_InputData.gd_InputLen;
	    if (flags & (GADGET_DATA_FLAG_STRING_UNSIGNED_DEC |
					GADGET_DATA_FLAG_STRING_SIGNED_DEC |
					       GADGET_DATA_FLAG_STRING_HEX |
					     GADGET_DATA_FLAG_STRING_BIN)) {
	       if (len < MAX_BIN_NUM_DIGITS) {
		  len = MAX_BIN_NUM_DIGITS;
	       }
	    }
	 } else {
	    len = MAX_DEC_NUM_DIGITS;
	 }
	 /* init string info */
	 sinfo           = (struct StringInfo *)buffer;
	 buffer         += sizeof(struct StringInfo);
	 sinfo->Buffer   = (UBYTE *)buffer;
	 sinfo->MaxChars = len;
	 if (len & 1) {   /* input len odd */
	    buffer += len + 1;
	 } else {
	    buffer += len + 2;
	 }
	 break;
      case EXTENDED_GADGET_TYPE_SLIDER_PROP :
      case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
      case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
	 gad->GadgetType   = PROPGADGET;
	 gad->Activation   = GADGIMMEDIATE | RELVERIFY | FOLLOWMOUSE;
	 gad->Flags        = GADGHNONE;
	 gad->GadgetRender = (APTR)buffer;   /* needed for auto knob */
	 buffer           += sizeof(struct Image);
	 gad->SpecialInfo  = (APTR)buffer;
	 /* init prop info */
	 pinfo   = (struct PropInfo *)buffer;
	 buffer += sizeof(struct PropInfo);
	 if (type == EXTENDED_GADGET_TYPE_LISTVIEW_PROP || flags &
					GADGET_DATA_FLAG_ORIENTATION_VERT) {
	    pinfo->Flags = AUTOKNOB | FREEVERT | PROPBORDERLESS;
	 } else {
	    pinfo->Flags = AUTOKNOB | FREEHORIZ | PROPBORDERLESS;
	 }
	 break;
      case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
      case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
      case EXTENDED_GADGET_TYPE_SCROLLER_UP :
      case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
      case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
      case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
	 gad->GadgetType = BOOLGADGET;
	 gad->Activation = GADGIMMEDIATE | RELVERIFY;
	 switch (type) {
	    case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
	       egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_ARROW_LEFT];
	       break;
	    case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
	       egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_ARROW_RIGHT];
	       break;
	    case EXTENDED_GADGET_TYPE_SCROLLER_UP :
	    case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
	       egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_ARROW_UP];
	       break;
	    case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
	    case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
	       egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_ARROW_DOWN];
	       break;
	 }
	 egad->eg_Flags = EXTENDED_GADGET_FLAG_RENDER_IMAGE;
	 break;
      case EXTENDED_GADGET_TYPE_CYCLE :
	 gad->GadgetType = BOOLGADGET;
	 gad->Activation = RELVERIFY;
	 egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_CYCLE];
	 egad->eg_Flags  = EXTENDED_GADGET_FLAG_RENDER_IMAGE;
	 break;
      case EXTENDED_GADGET_TYPE_COUNT :
	 gad->GadgetType = BOOLGADGET;
	 gad->Activation = TOGGLESELECT | GADGIMMEDIATE;
	 egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_COUNT_LEFT];
	 egad->eg_Flags  = EXTENDED_GADGET_FLAG_RENDER_IMAGE;
	 break;
      case EXTENDED_GADGET_TYPE_LISTVIEW_ENTRY :
	 gad->GadgetType = BOOLGADGET;
	 gad->Activation = RELVERIFY;
	 gad->Flags      = GADGHCOMP;
	 break;
      case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
      case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
	 gad->GadgetType = BOOLGADGET;
	 gad->Activation = RELVERIFY;
	 /* init image */
	 image   = (struct Image *)buffer;
	 buffer += sizeof(struct Image);
	 if (flags & GADGET_DATA_FLAG_NO_BORDER) {
	    image->Width    = width;
	    image->Height   = height;
	 } else {
	    image->LeftEdge = 0;
	    image->TopEdge  = 0;
	    image->Width    = width - 2 * 4;
	    image->Height   = height - 2 * 2;
	 }
	 image->Depth    = ri->ri_ScreenDepth;
	 egad->eg_Render = (APTR)image;
	 egad->eg_Flags  = EXTENDED_GADGET_FLAG_RENDER_IMAGE;
	 break;
   }
   if (flags & GADGET_DATA_FLAG_DISABLED) {
      gad->Flags |= GADGDISABLED;
   }
   return(init_gadget_border(buffer, ri, egad, flags));
}
	/* Init gadget border */

   STATIC BYTE *
init_gadget_border(BYTE *buffer, struct RenderInfo  *ri,
				  struct ExtendedGadget  *egad, ULONG flags)
{
   struct Gadget  *gad = &egad->eg_Gadget;
   USHORT width = gad->Width, height = gad->Height;

   switch (egad->eg_Type) {
      case EXTENDED_GADGET_TYPE_BUTTON :
	 if ((flags & GADGET_DATA_FLAG_BUTTON_TOGGLE)  &&
				  (flags & GADGET_DATA_FLAG_BUTTON_IMAGE)) {
	    /* init non toggle border out */
	    if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	       egad->eg_Render = (APTR)buffer;
	       egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_BORDER;
	       buffer          = init_border(ri, buffer, 0, 0, width,
					 height, BORDER_DATA_TYPE_BOX1_OUT);
	    }
	 } else {
	    /* init toggle border */
	    if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
	       gad->Flags |= GADGHCOMP;
	       if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
		  gad->GadgetRender = (APTR)buffer;
		  buffer            = init_border(ri, buffer, 0, 0, width,
					 height, BORDER_DATA_TYPE_BOX1_OUT);
	       }
	    } else {
	       if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
		  gad->Flags       |= GADGHIMAGE;
		  gad->GadgetRender = (APTR)buffer;
		  buffer            = init_border(ri, buffer, 0, 0, width,
					 height, BORDER_DATA_TYPE_BOX1_OUT);
		  gad->SelectRender = (APTR)buffer;
		  buffer            = init_border(ri, buffer, 0, 0, width,
					  height, BORDER_DATA_TYPE_BOX1_IN);
	       } else {
		  if (!(gad->Flags & GADGHIMAGE)) {
		     gad->Flags |= GADGHNONE;
		  }
	       }
	    }
	 }
	 break;
      case EXTENDED_GADGET_TYPE_CHECK :
	 /* init non toggle border out */
	 if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	    egad->eg_Render = (APTR)buffer;
	    egad->eg_Flags  = EXTENDED_GADGET_FLAG_RENDER_BORDER;
	    buffer          = init_border(ri, buffer, 0, 0, width, height,
						 BORDER_DATA_TYPE_BOX1_OUT);
	 }
	 break;
      case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
      case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
      case EXTENDED_GADGET_TYPE_SCROLLER_UP :
      case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
      case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
      case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
      case EXTENDED_GADGET_TYPE_CYCLE :
      case EXTENDED_GADGET_TYPE_COUNT :
      case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
	 /* init toggle border */
	 if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
	    gad->Flags |= GADGHCOMP;
	    if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	       gad->GadgetRender = (APTR)buffer;
	       buffer            = init_border(ri, buffer, 0, 0,
				  width, height, BORDER_DATA_TYPE_BOX1_OUT);
	    }
	 } else {
	    if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	       gad->Flags       |= GADGHIMAGE;
	       gad->GadgetRender = (APTR)buffer;
	       buffer            = init_border(ri, buffer, 0, 0, width,
					 height, BORDER_DATA_TYPE_BOX1_OUT);
	       gad->SelectRender = (APTR)buffer;
	       buffer            = init_border(ri, buffer, 0, 0, width,
					  height, BORDER_DATA_TYPE_BOX1_IN);
	    } else {
	       gad->Flags |= GADGHNONE;
	    }
	 }
	 break;
      case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
	 /* init non toggle border in */
	 gad->Flags |= GADGHNONE;
	 if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	    gad->GadgetRender = (APTR)buffer;
	    buffer            = init_border(ri, buffer, 0, 0, width, height,
						  BORDER_DATA_TYPE_BOX1_IN);
	 }
	 break;
      case EXTENDED_GADGET_TYPE_STRING :
      case EXTENDED_GADGET_TYPE_INTEGER :
	 /* init input border */
	 if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	    gad->GadgetRender = (APTR)buffer;
	    gad->LeftEdge    += 6;
	    gad->TopEdge     += 3;
	    gad->Width       -= 2 * 6;
	    buffer            = init_border(ri, buffer, -6, -3, width,
				 height + 2 * 3, BORDER_DATA_TYPE_BOX2_OUT);
	 }
	 break;
      case EXTENDED_GADGET_TYPE_SLIDER_PROP :
      case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
      case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
	 /* init prop border */
	 if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
	    egad->eg_Render = (APTR)buffer;
	    egad->eg_Flags  = EXTENDED_GADGET_FLAG_RENDER_BORDER;
	    gad->LeftEdge  += 4;
	    gad->TopEdge   += 2;
	    gad->Width     -= 2 * 4;
	    gad->Height    -= 2 * 2;
	    buffer          = init_border(ri, buffer, -4, -2, width, height,
						 BORDER_DATA_TYPE_BOX1_OUT);
	 }
	 break;
   }
   return(buffer);
}
	/* Init gadget text */

   STATIC USHORT
init_gadget_text(struct ExtendedGadget  *egad, BYTE *text, USHORT width,
		    USHORT height, ULONG flags, struct TextAttr  *text_attr)
{
   struct IntuiText  itext;
   BYTE   c, *ptr, hot_key_id[] = "_";
   USHORT type = (egad->eg_GadgetList->gl_Data + egad->eg_DataEntry)->gd_Type;
   SHORT  i, xoffset, yoffset, left_edge, top_edge, text_width, text_height;

   /* search hot key in gadget text */
   if (flags & GADGET_DATA_FLAG_HOT_KEY) {
      for (i = 0, ptr = text; *ptr; i++) {
	 if (*ptr++ == '_' && (c = *ptr)) {
	    if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
						   (c >= '0' && c <= '9')) {
	       egad->eg_Hotkey    = (USHORT)c;
	       egad->eg_HotkeyPos = i + 1;
	       egad->eg_Flags    |= EXTENDED_GADGET_FLAG_HOT_KEY;
	       break;
	    }
	 }
      }
   }
   /* calc text dimension */
   itext.IText     = (UBYTE *)text;
   itext.ITextFont = text_attr;
   text_width      = IntuiTextLength(&itext);
   text_height     = text_attr->ta_YSize;
   if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOT_KEY) {
      itext.IText = (UBYTE *)&hot_key_id[0];
      text_width -= IntuiTextLength(&itext);
   }
   /* calc border offset */
   if (flags & GADGET_DATA_FLAG_NO_BORDER) {
      xoffset = 0;
      yoffset = 0;
   } else {
      switch (type) {
	 case GADGET_DATA_TYPE_MX :
	    xoffset = 8;
	    yoffset = 4;
	    break;
	 case GADGET_DATA_TYPE_STRING :
	 case GADGET_DATA_TYPE_INTEGER :
	    xoffset = 6;
	    yoffset = 0;
	    break;
	 case GADGET_DATA_TYPE_SLIDER :
	 case GADGET_DATA_TYPE_SCROLLER :
	 case GADGET_DATA_TYPE_LISTVIEW :
	    xoffset = 4;
	    yoffset = 2;
	    break;
	 default :
	    xoffset = 0;
	    yoffset = 0;
	    break;
      }
   }
   /* calc text pos */
   switch (type) {
      case GADGET_DATA_TYPE_MX :
	 if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
	    left_edge = -(width - egad->eg_Gadget.Width - xoffset - (SHORT)
						  (width - text_width) / 2);
	 } else {
	    left_edge = (SHORT)(width - text_width) / 2 - xoffset;
	 }
	 top_edge = -(text_height + yoffset + 4);
	 break;
      case GADGET_DATA_TYPE_LISTVIEW :
	 left_edge = -(width - egad->eg_Gadget.Width - xoffset - (SHORT)
						  (width - text_width) / 2);
	 top_edge  = -(text_height + yoffset + 4);
	 break;
      case GADGET_DATA_TYPE_PALETTE :
	 left_edge = (SHORT)(width - text_width) / 2;
	 top_edge  = -(text_height + 4);
	 break;
      default :
	 /* calc horizontal pos */
	 if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
	    left_edge = -(text_width + xoffset + 8);
	 } else {
	    if (flags & GADGET_DATA_FLAG_TEXT_RIGHT) {
	       left_edge = width - xoffset + 8;
	    } else {
	       left_edge = (SHORT)(width - 2 * xoffset - text_width) / 2;
	    }
	 }
	 /* calc vertical pos */
	 if (flags & GADGET_DATA_FLAG_TEXT_ABOVE) {
	    top_edge = -(text_height + yoffset + 4);
	 } else {
	    if (flags & GADGET_DATA_FLAG_TEXT_BELOW) {
	       top_edge = height - yoffset + 4;
	    } else {
	       top_edge = (SHORT)(height - 2 * yoffset - text_height) / 2;
	    }
	 }
	 break;
   }
   egad->eg_TextLeftEdge = left_edge;
   egad->eg_TextTopEdge  = top_edge;
   egad->eg_Text         = text;
   return(text_width);
}
	/* Init mutual exclude gadget text */

   STATIC BYTE *
init_mx_text(struct ExtendedGadget  *egad, BYTE *buffer, BYTE *text,
      USHORT width, USHORT height, ULONG flags, struct TextAttr  *text_attr)
{
   struct RenderInfo  *ri = egad->eg_GadgetList->gl_RenderInfo;
   struct IntuiText   *itext;

   itext            = (struct IntuiText *)buffer;
   buffer          += sizeof(struct IntuiText);
   itext->FrontPen  = (flags & GADGET_DATA_FLAG_TEXT_COLOR2 ?
					 ri->ri_TextPen2 : ri->ri_TextPen1);
   itext->BackPen   = ri->ri_BackPen;
   itext->DrawMode  = JAM2;
   itext->IText     = (UBYTE *)text;
   itext->ITextFont = text_attr;
   itext->TopEdge   = (SHORT)(height - text_attr->ta_YSize) / 2;
   if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
      itext->LeftEdge = -(IntuiTextLength(itext) + 8);
   } else {
      itext->LeftEdge = width + 8;   /* default right */
   }
   egad->eg_Gadget.GadgetText = itext;
   return(buffer);
}
	/* Check image for valid chip mem data */

   STATIC BOOL
check_gadget_image(struct Image  *image)
{
   BYTE *data;
   BOOL result;

   if ((data = (BYTE *)image->ImageData) && !(TypeOfMem(data) & MEMF_CHIP)) {
      result = FALSE;
   } else {
      result = TRUE;
   }
   return(result);
}
	/* Init gadget image */

   STATIC BYTE *
init_gadget_image(struct ExtendedGadget  *egad, struct GadgetData  *gd,
							       BYTE *buffer)
{
   struct Gadget  *gad = &egad->eg_Gadget;
   struct Image   *image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonNormalRender;

   if (gad->Flags & GADGIMAGE) {
      if (check_gadget_image(image) == FALSE) {
	 egad->eg_Flags = EXTENDED_GADGET_FLAG_NORMAL_IMAGE_COPY;
	 CopyMem((BYTE *)image, buffer, (LONG)sizeof(struct Image));
	 image   = (struct Image *)buffer;
	 buffer += sizeof(struct Image);
      }
      gad->GadgetRender = (APTR)image;
      if (gad->Flags & GADGHIMAGE) {
	 if (!(image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonSelectRender)) {
	    gad->Flags &= ~GADGHIGHBITS;
	    gad->Flags |= GADGHNONE;
	 } else {
	    if (check_gadget_image(image) == FALSE) {
	       egad->eg_Flags |= EXTENDED_GADGET_FLAG_SELECT_IMAGE_COPY;
	       CopyMem((BYTE *)image, buffer, (LONG)sizeof(struct Image));
	       image   = (struct Image *)buffer;
	       buffer += sizeof(struct Image);
	    }
	    gad->SelectRender = (APTR)image;
	 }
      }
   } else {
      if (check_gadget_image(image) == FALSE) {
	 egad->eg_Flags |= EXTENDED_GADGET_FLAG_NORMAL_IMAGE_COPY;
	 CopyMem((BYTE *)image, buffer, (LONG)sizeof(struct Image));
	 image   = (struct Image *)buffer;
	 buffer += sizeof(struct Image);
      }
      egad->eg_Render = (APTR)image;
   }
   return(buffer);
}
	/* Init image data - make chipmem copy if needed */

   STATIC BYTE *
init_image_data(struct ExtendedGadget  *egad, BYTE *buffer)
{
   struct Gadget  *gad = &egad->eg_Gadget;
   struct Image   *image;
   UBYTE flags = egad->eg_Flags;
   BYTE  *data;
   LONG  size;

   if (flags & EXTENDED_GADGET_FLAG_NORMAL_IMAGE_COPY) {
      if (flags & EXTENDED_GADGET_FLAG_RENDER_IMAGE) {
	 image = (struct Image *)egad->eg_Render;
      } else {
	 image = (struct Image *)gad->GadgetRender;
      }
      if ((data = (BYTE *)image->ImageData) && !(TypeOfMem(data) &
							       MEMF_CHIP)) {
	 size = (image->Width / 16 + (image->Width & 15 ? 1 : 0))
					 * image->Height * image->Depth * 2;
	 CopyMem(data, buffer, size);
	 image->ImageData = (UWORD *)buffer;
	 buffer          += size;
      }
   }
   if (flags & EXTENDED_GADGET_FLAG_SELECT_IMAGE_COPY) {
      image = (struct Image *)gad->SelectRender;
      if ((data = (BYTE *)image->ImageData) && !(TypeOfMem(data) &
							       MEMF_CHIP)) {
	 size = (image->Width / 16 + (image->Width & 15 ? 1 : 0))
					 * image->Height * image->Depth * 2;
	 CopyMem(data, buffer, size);
	 image->ImageData = (UWORD *)buffer;
	 buffer          += size;
      }
   }
   return(buffer);
}
