/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1991 by Torsten Jürgeleit
 *
 *	Name .....: borders.c
 *	Created ..: Thursday 19-Dec-91 17:25:52
 *	Revision .: 1
 *
 *	Date        Author                 Comment
 *	=========   ====================   ====================
 *	24-Jan-92   Torsten Jürgeleit      new support function for
 *                                         modify_gadget()
 *	19-Dec-91   Torsten Jürgeleit      Created this file!
 *
 ****************************************************************************
 *
 *	Routines to draw borders with 3D look
 *
 * $Revision Header ********************************************************/

	/* Includes */

#include <exec/types.h>
#include <intuition/intuition.h>
#ifdef AZTEC_C
#include <functions.h>   /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
#endif
#include <libraries/memwatch.h>   /* header file for memory debug link library (Fish 240) - AFTER functions.h */
#include "/render/render.h"
#include "borders.h"

	/* Defines */

#define MAX_BORDER_BUFFER_SIZE			BORDER_TYPE_BOX2_BUFFER_SIZE

#define BORDER_VEC_MODE_BOX_TOP_LEFT		0
#define BORDER_VEC_MODE_BOX_BOTTOM_RIGHT	1

	/* Static prototypes */

VOID fill_border_vec(SHORT *vec, USHORT width, USHORT height, USHORT mode);

	/* Static pragmas */

#pragma regcall(fill_border_vec(a0,d0,d1,d2))

	/* Display borders described by border list */

   VOID
display_borders(struct RenderInfo  *ri, struct Window  *win,
		       struct BorderData  *bd, SHORT hoffset, SHORT voffset)
{
   if (ri && win && bd) {
      for ( ; bd->bd_Type != INTUISUP_DATA_END &&
				bd->bd_Type <= MAX_BORDER_DATA_TYPE; bd++) {
	 draw_border(ri, win, bd->bd_LeftEdge + hoffset, bd->bd_TopEdge +
		 voffset, bd->bd_Width, bd->bd_Height, (USHORT)bd->bd_Type);
      }
   }
}
	/* Draw border */

   VOID
draw_border(struct RenderInfo  *ri, struct Window  *win, USHORT left_edge,
		  USHORT top_edge, USHORT width, USHORT height, USHORT type)
{
   if (ri && win) {
      BYTE buffer[MAX_BORDER_BUFFER_SIZE];

      init_border(ri, &buffer[0], 0, 0, width, height, type);
      if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
	 left_edge += ri->ri_WindowBorderLeft;
	 top_edge  += ri->ri_WindowBorderTop;
      }
      DrawBorder(win->RPort, (struct Border *)&buffer[0], (LONG)left_edge,
							   (LONG)top_edge);
   }
}
	/* Init border - NON STATIC because needed for gadget routines too */

    BYTE *
init_border(struct RenderInfo  *ri, BYTE *buffer, SHORT left_edge,
		   SHORT top_edge, USHORT width, USHORT height, USHORT type)
{
   struct Border  *border = (struct Border *)buffer;
   UBYTE  highlight_pen, shadow_pen;
   SHORT  *vec;
   USHORT i, vec_mode, vec_width, vec_height;

   switch (type) {
      case BORDER_DATA_TYPE_BOX1_OUT :
      case BORDER_DATA_TYPE_BOX2_OUT :
	 highlight_pen = ri->ri_HighlightPen;
	 shadow_pen    = ri->ri_ShadowPen;
	 break;

      case BORDER_DATA_TYPE_BOX1_IN :
      case BORDER_DATA_TYPE_BOX2_IN :
	 highlight_pen = ri->ri_ShadowPen;
	 shadow_pen    = ri->ri_HighlightPen;
	 break;
   }
   switch (type) {
      case BORDER_DATA_TYPE_BOX1_OUT :
      case BORDER_DATA_TYPE_BOX1_IN :
	 vec = (SHORT *)(border + 2);
	 for (i = 0; i < 2; i++, border++, vec += 10) {
	    if (i & 1) {   /* odd ? */
	       border->FrontPen = shadow_pen;
	       vec_mode         = BORDER_VEC_MODE_BOX_BOTTOM_RIGHT;
	    } else {
	       border->FrontPen = highlight_pen;
	       vec_mode         = BORDER_VEC_MODE_BOX_TOP_LEFT;
	    }
	    border->LeftEdge = left_edge;
	    border->TopEdge  = top_edge;
	    border->DrawMode = JAM1;
	    border->Count    = 5;
	    border->XY       = vec;
	    if (i < 1) {
	       border->NextBorder = border + 1;
	    } else {
	       border->NextBorder = NULL;
	    }
	    fill_border_vec(vec, width, height, vec_mode);
	 }
	 buffer += BORDER_TYPE_BOX1_BUFFER_SIZE;
	 break;

      case BORDER_DATA_TYPE_BOX2_OUT :
      case BORDER_DATA_TYPE_BOX2_IN :
	 vec = (SHORT *)(border + 4);
	 for (i = 0; i < 4; i++, border++, vec += 10) {
	    if (i < 2) {
	       border->LeftEdge = left_edge;
	       border->TopEdge  = top_edge;
	       if (i & 1) {   /* odd ? */
		  border->FrontPen = shadow_pen;
		  vec_mode         = BORDER_VEC_MODE_BOX_BOTTOM_RIGHT;
	       } else {
		  border->FrontPen = highlight_pen;
		  vec_mode         = BORDER_VEC_MODE_BOX_TOP_LEFT;
	       }
	       vec_width  = width;
	       vec_height = height;
	    } else {
	       border->LeftEdge = left_edge + 2;
	       border->TopEdge  = top_edge + 1;
	       if (i & 1) {   /* odd ? */
		  border->FrontPen = highlight_pen;
		  vec_mode         = BORDER_VEC_MODE_BOX_BOTTOM_RIGHT;
	       } else {
		  border->FrontPen = shadow_pen;
		  vec_mode         = BORDER_VEC_MODE_BOX_TOP_LEFT;
	       }
	       vec_width  = width - 4;
	       vec_height = height - 2;
	    }
	    border->DrawMode = JAM1;
	    border->Count    = 5;
	    border->XY       = vec;
	    if (i < 3) {
	       border->NextBorder = border + 1;
	    } else {
	       border->NextBorder = NULL;
	    }
	    fill_border_vec(vec, vec_width, vec_height, vec_mode);
	 }
	 buffer += BORDER_TYPE_BOX2_BUFFER_SIZE;
	 break;
   }
   return(buffer);
}
	/* Resize border - NON STATIC because needed for gadget routines */

    VOID
resize_border(struct Border  *border, USHORT width, USHORT height,
								USHORT type)
{
   USHORT i;

   switch (type) {
      case BORDER_DATA_TYPE_BOX1_OUT :
      case BORDER_DATA_TYPE_BOX1_IN :
	 for (i = 0; border; i++, border = border->NextBorder) {
	    USHORT vec_mode;

	    if (i & 1) {   /* odd ? */
	       vec_mode = BORDER_VEC_MODE_BOX_BOTTOM_RIGHT;
	    } else {
	       vec_mode = BORDER_VEC_MODE_BOX_TOP_LEFT;
	    }
	    fill_border_vec(border->XY, width, height, vec_mode);
	 }
	 break;

      case BORDER_DATA_TYPE_BOX2_OUT :
      case BORDER_DATA_TYPE_BOX2_IN :
	 for (i = 0; border; i++, border = border->NextBorder) {
	    USHORT vec_mode, vec_width, vec_height;

	    if (i < 2) {
	       if (i & 1) {   /* odd ? */
		  vec_mode = BORDER_VEC_MODE_BOX_BOTTOM_RIGHT;
	       } else {
		  vec_mode = BORDER_VEC_MODE_BOX_TOP_LEFT;
	       }
	       vec_width  = width;
	       vec_height = height;
	    } else {
	       if (i & 1) {   /* odd ? */
		  vec_mode = BORDER_VEC_MODE_BOX_BOTTOM_RIGHT;
	       } else {
		  vec_mode = BORDER_VEC_MODE_BOX_TOP_LEFT;
	       }
	       vec_width  = width - 4;
	       vec_height = height - 2;
	    }
	    fill_border_vec(border->XY, vec_width, vec_height, vec_mode);
	 }
	 break;
   }
}
	/* Fill border vector */

   STATIC VOID
fill_border_vec(SHORT *vec, USHORT width, USHORT height, USHORT mode)
{
   switch (mode) {
      case BORDER_VEC_MODE_BOX_TOP_LEFT :
	 *(vec++) = width - 2;
	 *(vec++) = 0;
	 *(vec++) = 0;
	 *(vec++) = 0;
	 *(vec++) = 0;
	 *(vec++) = height - 1;
	 *(vec++) = 1;
	 *(vec++) = height - 2;
	 *(vec++) = 1;
	 *(vec)   = 1;
	 break;

      case BORDER_VEC_MODE_BOX_BOTTOM_RIGHT :
	 *(vec++) = 1;
	 *(vec++) = height - 1;
	 *(vec++) = width - 1;
	 *(vec++) = height - 1;
	 *(vec++) = width - 1;
	 *(vec++) = 0;
	 *(vec++) = width - 2;
	 *(vec++) = 1;
	 *(vec++) = width - 2;
	 *(vec)   = height - 2;
	 break;
   }
}
