		/*************************************
		 *                                   *
		 *            Borders v2.0           *
		 *   by Torsten Jürgeleit in 05/91   *
		 *                                   *
		 *              Routines             *
		 *                                   *
		 *************************************/

	/* Includes */

#include <exec/types.h>
#include <intuition/intuition.h>
#include <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)
{
   while (bd->bd_Type != INTUISUP_DATA_END &&
				      bd->bd_Type <= MAX_BORDER_DATA_TYPE) {
      draw_border(ri, win, bd->bd_LeftEdge + hoffset, bd->bd_TopEdge +
		 voffset, bd->bd_Width, bd->bd_Height, (USHORT)bd->bd_Type);
      bd++;
   }
}
	/* Draw border */

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

   init_border(ri, border, 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 *)border, (LONG)left_edge, (LONG)
								 top_edge);
}
	/* Init border */

    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);
}
	/* Fill border vector array */

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