/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1991 by Torsten Jürgeleit
 *
 *	Name .....: gadgets2.c
 *	Created ..: Thursday 19-Dec-91 20:52:53
 *	Revision .: 1
 *
 *	Date        Author                 Comment
 *	=========   ====================   ====================
 *	05-Jan-92   Torsten Jürgeleit      now try to open font before
 *                                         initializing gadget;
 *                                         correct display of larger fonts for
 *                                         mutual exclude gadgets
 *	19-Dec-91   Torsten Jürgeleit      Created this file!
 *
 ****************************************************************************
 *
 *	Gadget support routines - part 2
 *
 * $Revision Header ********************************************************/

	/* Includes */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/inputevent.h>
#include <intuition/intuition.h>
#include <functions.h>
#include <libraries/memwatch.h>		/* AFTER functions.h */
#include <string.h>
#include "/render/render.h"
#include "/texts/texts.h"
#include "/borders/borders.h"
#include "/language/language.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;
   USHORT i, data_entries = gl->gl_DataEntries;
   ULONG  buffer_size = 0;

   for (i = 0; i < data_entries; i++, gd++) {
      BYTE   **text;
      USHORT gadget_size, border_size, num, height, spacing,
	     type = gd->gd_Type;
      ULONG  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) {
	       struct Image  *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 {
	       struct TextAttr  *ta;

	       if (!(ta = gd->gd_TextAttr)) {
		  ta = &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) / (ta->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;
   USHORT i, data_entries = gl->gl_DataEntries;
   ULONG  buffer_size = 0;

   for (i = 0; i < data_entries; i++, gd++) {
      if (gd->gd_Type == GADGET_DATA_TYPE_BUTTON &&
			   (gd->gd_Flags & GADGET_DATA_FLAG_BUTTON_IMAGE)) {
	 struct Image  *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 = gl->gl_Data;
   BYTE   *buffer = gl->gl_GadgetBuffer, *image_buffer = gl->gl_ImageBuffer;
   USHORT i, data_entries = gl->gl_DataEntries;

   for (i = 0; i < data_entries; i++, gd++) {
      struct ExtendedGadget  *egad, *first_egad;
      struct Image           *image;
      struct IntuiText       itext;
      struct MXData          *mx;
      struct SliderData      *sl;
      struct ScrollerData    *sc;
      struct CycleData       *cy;
      struct CountData       *co;
      struct ListViewData    *lv;
      struct PaletteData     *pd;
      struct TextAttr        *ta;
      struct TextFont        *tf;
      BYTE   **text;
      USHORT j, max_width, num, len, xoffset, yoffset, xmin, ymin,
	     xnum, ynum, yinc, spacing, text_height,
	     type = gd->gd_Type, left_edge = gd->gd_LeftEdge + hoffset,
	     top_edge = gd->gd_TopEdge + voffset, width = gd->gd_Width,
	     height = gd->gd_Height;
      ULONG  min, max, flags = gd->gd_Flags;

      /* Inner window position needed ? */
      if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
	 left_edge += ri->ri_WindowBorderLeft;
	 top_edge  += ri->ri_WindowBorderTop;
      }

      /* Get gadget buffer ptr and reserve buffer */
      egad    = gl->gl_Gadgets[i] = (struct ExtendedGadget *)buffer;
      buffer += sizeof(struct ExtendedGadget);

      /* Save ptr to first gadget of ISUP object */
      first_egad = egad;

      /* Open text font and save data */
      if (!(ta = gd->gd_TextAttr) || !(ta = ask_font(ri, ta))) {
	 ta = &ri->ri_TextAttr;
	 tf = ri->ri_TextFont;
      } else {
	 if (!(tf = open_font(ri, ta))) {
	    ta = &ri->ri_TextAttr;
	    tf = ri->ri_TextFont;
	 } else {
	    egad->eg_Flags |= EXTENDED_GADGET_FLAG_CLOSE_FONT;
	 }
      }
      egad->eg_TextAttr = ta;
      egad->eg_TextFont = tf;
      text_height       = ta->ta_YSize;

      /* Init intui text */
      itext.ITextFont = ta;

      /* 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_height) < 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 *)get_language_text(*text++,
						  gl->gl_LanguageTextArray);
	       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_height > height) {
	       top_edge += (text_height - 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_height + 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, get_language_text(*text,
		       gl->gl_LanguageTextArray), width, height, flags, ta);
	       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 border offsets first - need old height */
	    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_height > height) {
		  top_edge = -((text_height - height) / 2 + yoffset);
	       } else {
		  top_edge = -yoffset;
	       }
	    }

	    /* 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)) {
	       first_egad->eg_Render = (APTR)buffer;
	       buffer                = init_border(ri, buffer, left_edge,
			 top_edge, width, height, BORDER_DATA_TYPE_BOX1_IN);
	       first_egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_BORDER;
	    }
	    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 *)get_language_text(*text++,
						  gl->gl_LanguageTextArray);
	       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_Flags       = flags;
	    cy->cy_LeftEdge    = left_edge + xmin + (SHORT)(width -
						  max_width - xmin - 4) / 2;
	    cy->cy_TopEdge     = top_edge + (SHORT)(height - text_height) / 2;
	    cy->cy_Width       = max_width;
	    cy->cy_Height      = text_height;
	    cy->cy_EntryHeight = text_height +
			    gd->gd_SpecialData.gd_CycleData.gd_CycleSpacing;
	    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_height) / 2;
	    co->co_Width    = max_width;
	    co->co_Height   = text_height;
	    co->co_Flags    = flags;
	    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_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)) {
	       USHORT border_type;

	       ((struct Border *)egad->eg_Render)->NextBorder->NextBorder =
						    (struct Border *)buffer;
	       if (flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY) {
		  border_type = BORDER_DATA_TYPE_BOX1_IN;
	       } else {
		  border_type = BORDER_DATA_TYPE_BOX1_OUT;
	       }
	       buffer = init_border(ri, buffer, -(width + xoffset - xmin),
			   -yoffset, width - xmin - 2, height, border_type);
	    }

	    /* 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 */
	    num = gd->gd_SpecialData.gd_PaletteData.gd_PaletteColorOffset;
	    for (j = 0; j < ynum; j++, top_edge += ymin + 1) {
	       USHORT k, temp_left_edge = left_edge;

	       for (k = 0; k < xnum; k++, temp_left_edge += xmin + 2) {
		  buffer = init_extended_gadget(egad, buffer, gl, i,
			 EXTENDED_GADGET_TYPE_PALETTE_COLOR, temp_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, get_language_text(gd->gd_Text,
		       gl->gl_LanguageTextArray), width, height, flags, ta);
      }
      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;
   if (flags & GADGET_DATA_FLAG_MOVE_POINTER) {
      egad->eg_Flags |= EXTENDED_GADGET_FLAG_MOVE_POINTER;
   }

   /* 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 {
		  buffer          = init_gadget_image(egad, gd, buffer);
		  egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_IMAGE;
	       }
	    }
	 }
	 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 = TOGGLESELECT | GADGIMMEDIATE;
	 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 VOID
init_gadget_text(struct ExtendedGadget  *egad, BYTE *text, USHORT width,
			   USHORT height, ULONG flags, struct TextAttr  *ta)
{
   /* Search hotkey in gadget text */
   if (flags & GADGET_DATA_FLAG_HOTKEY) {
      BYTE   *ptr = text;
      USHORT i;

      for (i = 0; *ptr; i++) {
	 BYTE c;

	 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_HOTKEY;
	       break;
	    }
	 }
      }
   }

   /* Ignore text if no output is required */
   if (!(flags & GADGET_DATA_FLAG_NO_TEXT_OUTPUT)) {
      struct IntuiText  itext;
      SHORT  text_width, text_height, xoffset, yoffset, left_edge, top_edge;
      USHORT type = (egad->eg_GadgetList->gl_Data +
					       egad->eg_DataEntry)->gd_Type;
      /* Calc text dimension */
      itext.IText     = (UBYTE *)text;
      itext.ITextFont = ta;
      text_width      = IntuiTextLength(&itext);
      text_height     = ta->ta_YSize;
      if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOTKEY) {
	 itext.IText = (UBYTE *)&hotkey_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;
	    }
	    if (text_height > IMAGE_KNOB_HEIGHT) {
	       top_edge = -((text_height - IMAGE_KNOB_HEIGHT) / 2);
	    } else {
	       top_edge = 0;
	    }
	    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;
   }
}
	/* 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  *ta)
{
   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 = ta;
   itext->TopEdge   = (SHORT)(height - ta->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;
   BYTE  *data;
   LONG  size;
   UBYTE flags = egad->eg_Flags;

   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);
}
