/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1991 by Torsten Jürgeleit
 *
 *	Name .....: subs.c
 *	Created ..: Sunday 22-Dec-91 21:23:09
 *	Revision .: 0
 *
 *	Date        Author                 Comment
 *	=========   ====================   ====================
 *	22-Dec-91   Torsten Jürgeleit      Created this file!
 *
 ****************************************************************************
 *
 *	Subroutines
 *
 * $Revision Header ********************************************************/

	/* Includes */

#include "includes.h"
#include "defines.h"
#include "imports.h"
#include "protos.h"

	/* Draw box in given window */

   VOID
draw_box(struct Window  *win, struct Box  *box)
{
   struct RastPort  *rp = win->RPort;

   SetDrMd(rp, (LONG)COMPLEMENT);
   Move(rp, (LONG)box->bo_X1, (LONG)box->bo_Y1);
   Draw(rp, (LONG)box->bo_X2, (LONG)box->bo_Y1);
   Draw(rp, (LONG)box->bo_X2, (LONG)box->bo_Y2);
   Draw(rp, (LONG)box->bo_X1, (LONG)box->bo_Y2);
   Draw(rp, (LONG)box->bo_X1, (LONG)box->bo_Y1);
}
	/* Draw box in given window with border of 1 pixel */

   VOID
draw_box_with_border(struct Window  *win, struct Box  *box)
{
   struct RastPort  *rp = win->RPort;

   SetDrMd(rp, (LONG)COMPLEMENT);
   Move(rp, (LONG)(box->bo_X1 - 1), (LONG)(box->bo_Y1 - 1));
   Draw(rp, (LONG)(box->bo_X2 + 1), (LONG)(box->bo_Y1 - 1));
   Draw(rp, (LONG)(box->bo_X2 + 1), (LONG)(box->bo_Y2 + 1));
   Draw(rp, (LONG)(box->bo_X1 - 1), (LONG)(box->bo_Y2 + 1));
   Draw(rp, (LONG)(box->bo_X1 - 1), (LONG)(box->bo_Y1 - 1));
}
	/* Draw box in given window with offset */

   VOID
draw_box_with_offset(struct Window  *win, struct Box  *box, SHORT xoffset,
							      SHORT yoffset)
{
   struct RastPort  *rp = win->RPort;

   SetDrMd(rp, (LONG)COMPLEMENT);
   Move(rp, (LONG)(box->bo_X1 + xoffset), (LONG)(box->bo_Y1 + yoffset));
   Draw(rp, (LONG)(box->bo_X2 + xoffset), (LONG)(box->bo_Y1 + yoffset));
   Draw(rp, (LONG)(box->bo_X2 + xoffset), (LONG)(box->bo_Y2 + yoffset));
   Draw(rp, (LONG)(box->bo_X1 + xoffset), (LONG)(box->bo_Y2 + yoffset));
   Draw(rp, (LONG)(box->bo_X1 + xoffset), (LONG)(box->bo_Y1 + yoffset));
}
	/* Get head of EXEC list */

   VOID *
get_head(struct List  *list)
{
   struct Node  *node = list->lh_Head;

   /* Check for empty list ? */
   if (!node->ln_Succ) {
      node = NULL;
   }
   return((VOID *)node);
}
	/* Get tail of EXEC list */

   VOID *
get_tail(struct List  *list)
{
   struct Node  *node = list->lh_TailPred;

   /* Check for empty list ? */
   if (!node->ln_Pred) {
      node = NULL;
   }
   return((VOID *)node);
}
	/* Get next node of EXEC list entry */

   VOID *
get_succ(struct Node  *node)
{
   /* Check for end of list ? */
   node = node->ln_Succ;
   if (!node->ln_Succ) {
      node = NULL;
   }
   return((VOID *)node);
}
	/* Get previous node of EXEC list entry */

   VOID *
get_pred(struct Node  *node)
{
   /* Check for start of list ? */
   node = node->ln_Pred;
   if (!node->ln_Pred) {
      node = NULL;
   }
   return((VOID *)node);
}
	/* Get node from list by given number */

   VOID *
get_node(struct List  *list, USHORT num)
{
   struct Node  *node;

   if (node = get_head(list)) {
      while (num-- && (node = get_succ(node)));
   }
   return((VOID *)node);
}
	/* Duplicate text string */

   SHORT
duplicate_string(BYTE *text, BYTE **ptr)
{
   LONG  len;
   SHORT status = EDITOR_STATUS_NORMAL;

   if (!text || (len = strlen(text) + 1) == 1) {
      *ptr = NULL;
   } else {
      if (!(*ptr = DosAllocMem(len))) {
	 status = EDITOR_ERROR_OUT_OF_MEM;
      } else {
	 CopyMem(text, *ptr, len);
      }
   }
   return(status);
}
	/* Convert string to lower case */

   VOID
lower_string(BYTE *text, BYTE *ptr)
{
   if (ptr && text) {
      BYTE c;

      while ((c = *text++) != '\0') {
	 *ptr++ = tolower(c);
      }
      *ptr = '\0';
   }
}
	/* Convert string to upper case */

   VOID
upper_string(BYTE *text, BYTE *ptr)
{
   if (ptr && text) {
      BYTE c;

      while ((c = *text++) != '\0') {
	 *ptr++ = toupper(c);
      }
      *ptr = '\0';
   }
}
	/* Duplicate text list */

   SHORT
duplicate_text_list(struct Template  *old_tp, struct Template  *new_tp)
{
   struct Node  *node;
   SHORT status = EDITOR_STATUS_NORMAL;

   NewList(&new_tp->tp_TextList);
   for (node = get_head(&old_tp->tp_TextList); node &&
		    status == EDITOR_STATUS_NORMAL; node = get_succ(node)) {
      status = add_template_text_list_entry(new_tp, node->ln_Name);
   }
   return(status);
}
	/* Build template text list from given text array */

   SHORT
build_template_text_list(struct Template  *tp, BYTE **text_array)
{
   BYTE  *text;
   SHORT status = EDITOR_STATUS_NORMAL;

   NewList(&tp->tp_TextList);
   for (text = *text_array; text && status == EDITOR_STATUS_NORMAL;
						     text = *++text_array) {
      status = add_template_text_list_entry(tp, text);
   }
   if (status != EDITOR_STATUS_NORMAL) {
      free_template_text_list(tp);
   }
   return(status);
}
	/* Build text list entry */

   struct Node *
build_text_list_entry(BYTE *text)
{
   struct Node  *node;

   if (node = AllocMem((LONG)sizeof(struct Node), (LONG)MEMF_PUBLIC |
							      MEMF_CLEAR)) {
      if (!(node->ln_Name = DosAllocMem((LONG)(strlen(text) + 1)))) {
	 FreeMem(node, (LONG)sizeof(struct Node));
	 node = NULL;
      } else {
	 strcpy(node->ln_Name, text);
      }
   }
   return(node);
}
	/* Add text entry to template text list */

   SHORT
add_template_text_list_entry(struct Template  *tp, BYTE *text)
{
   struct Node  *node;
   SHORT status = EDITOR_STATUS_NORMAL;

   if (!(node = build_text_list_entry(text))) {
      status = EDITOR_ERROR_OUT_OF_MEM;
   } else {
      AddTail(&tp->tp_TextList, node);
   }
   return(status);
}
	/* Free template text list */

   VOID
free_template_text_list(struct Template  *tp)
{
   struct List  *list = &tp->tp_TextList;
   struct Node  *node;

   while (node = RemHead(list)) {
      free_text_list_entry(node);
   }
}
	/* Free text list entry */

   VOID
free_text_list_entry(struct Node  *node)
{
   DosFreeMem(node->ln_Name);
   FreeMem(node, (LONG)sizeof(struct Node));
}
	/* Build template text array from template text list */

   SHORT
build_template_text_array(struct Template  *tp)
{
   struct List  *list = &tp->tp_TextList;
   struct Node  *node;
   BYTE   **text_array;
   USHORT count = 0;
   SHORT  status = EDITOR_STATUS_NORMAL;

   /* Count entries in text list */
   for (node = get_head(list); node; node = get_succ(node)) {
      count++;
   }
   if (!(text_array = DosAllocMem((LONG)(count + 1) * sizeof(BYTE *)))) {
      status = EDITOR_ERROR_OUT_OF_MEM;
   } else {
      struct GadgetData  *gd = &tp->tp_Data.tp_GadgetData;

      switch (tp->tp_Type) {
	 case TEMPLATE_TYPE_MX :
	    gd->gd_SpecialData.gd_MXData.gd_MXTextArray = text_array;
	    break;
	 case TEMPLATE_TYPE_CYCLE :
	    gd->gd_SpecialData.gd_CycleData.gd_CycleTextArray = text_array;
	    break;
      }

      /* Fill text array with pointers to text list entries */
      for (node = get_head(list); node && status == EDITOR_STATUS_NORMAL;
						    node = get_succ(node)) {
	 *text_array++ = node->ln_Name;
      }
      *text_array = NULL;   /* mark end of text array */
   }
   return(status);
}
	/* Free template text array */

   VOID
free_template_text_array(struct Template  *tp)
{
   struct GadgetData  *gd = &tp->tp_Data.tp_GadgetData;
   BYTE **text_array;

   switch (tp->tp_Type) {
      case TEMPLATE_TYPE_MX :
	 text_array = gd->gd_SpecialData.gd_MXData.gd_MXTextArray;
	 gd->gd_SpecialData.gd_MXData.gd_MXTextArray = NULL;
	 break;
      case TEMPLATE_TYPE_CYCLE :
	 text_array = gd->gd_SpecialData.gd_CycleData.gd_CycleTextArray;
	 gd->gd_SpecialData.gd_CycleData.gd_CycleTextArray = NULL;
	 break;
      default :
	 text_array = NULL;
	 break;
   }
   DosFreeMem(text_array);
}
