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

	/* Includes */

#include <exec/types.h>
#include <graphics/text.h>
#include <intuition/intuition.h>
#include <functions.h>
#include <string.h>
#include "/render/render.h"
#include "texts.h"

	/* Display texts described by text list */

   VOID
display_texts(struct RenderInfo  *ri, struct Window  *win,
			 struct TextData  *td, SHORT hoffset, SHORT voffset)
{
   while (td->td_Type != INTUISUP_DATA_END &&
					td->td_Type <= MAX_TEXT_DATA_TYPE) {
      print_text(ri, win, td->td_Text, td->td_LeftEdge + hoffset,
			td->td_TopEdge + voffset, td->td_Type, td->td_Flags,
							   td->td_TextAttr);
      td++;
   }
}
	/* Print text and return width of text */

   USHORT
print_text(struct RenderInfo  *ri, struct Window  *win, BYTE *text,
	       USHORT left_edge, USHORT top_edge, USHORT type, USHORT flags,
						struct TextAttr  *text_attr)
{
   struct IntuiText  it;
   struct TextAttr   ta;
   BYTE   buffer[MAX_NUM_BUFFER_SIZE];
   USHORT width;

   if (ri && text) {
      /* if no text attr given then use screen text attr */
      if (!text_attr) {
	 text_attr = &ri->ri_TextAttr;
      }
      /* build text attr with style described by flags */
      CopyMem((BYTE *)text_attr, (BYTE *)&ta, (LONG)sizeof(struct TextAttr));
      ta.ta_Style = FS_NORMAL;
      if (flags & TEXT_DATA_FLAG_BOLD) {
	 ta.ta_Style |= FSF_BOLD;
      }
      if (flags & TEXT_DATA_FLAG_ITALIC) {
	 ta.ta_Style |= FSF_ITALIC;
      }
      if (flags & TEXT_DATA_FLAG_UNDERLINED) {
	 ta.ta_Style |= FSF_UNDERLINED;
      }
      /* if number then convert it to text */
      switch (type) {
	 case TEXT_DATA_TYPE_NUM_UNSIGNED_DEC :
	    convert_unsigned_dec((ULONG)text, &buffer[0]);
	    break;
	 case TEXT_DATA_TYPE_NUM_SIGNED_DEC :
	    convert_signed_dec((LONG)text, &buffer[0]);
	    break;
	 case TEXT_DATA_TYPE_NUM_HEX :
	    convert_hex((ULONG)text, &buffer[0]);
	    break;
	 case TEXT_DATA_TYPE_NUM_BIN :
	    convert_bin((ULONG)text, &buffer[0]);
	    break;
      }
      /* init intui text */
      it.LeftEdge  = 0;
      it.TopEdge   = 0;
      it.BackPen   = ri->ri_BackPen;
      it.IText     = (UBYTE *)(type == TEXT_DATA_TYPE_TEXT ? text : &buffer[0]);
      it.ITextFont = &ta;
      it.NextText  = NULL;
      width        = IntuiTextLength(&it);
      if (!(flags & TEXT_DATA_FLAG_NO_PRINT)) {
	 /* perform modifications indicated by flags */
	 if (flags & TEXT_DATA_FLAG_CENTER) {
	    left_edge = (win->Width - width) / 2;
	 } else {
	    if (flags & TEXT_DATA_FLAG_PLACE_LEFT) {
	       left_edge -= width;
	    }
	 }
	 if (flags & TEXT_DATA_FLAG_COLOR2) {
	    it.FrontPen = ri->ri_TextPen2;
	 } else {
	    it.FrontPen = ri->ri_TextPen1;
	 }
	 if (flags & TEXT_DATA_FLAG_COMPLEMENT) {
	    it.FrontPen ^= (1 << ri->ri_ScreenDepth) - 1;
	    it.BackPen  ^= (1 << ri->ri_ScreenDepth) - 1;
	 }
	 if (flags & TEXT_DATA_FLAG_BACK_FILL) {
	    it.DrawMode = JAM2;
	 } else {
	    it.DrawMode = JAM1;
	 }
	 if (!(flags & TEXT_DATA_FLAG_ABSOLUTE_POS) && (ri->ri_Flags &
					   RENDER_INFO_FLAG_INNER_WINDOW)) {
	    if (!(flags & TEXT_DATA_FLAG_CENTER)) {
	       left_edge += ri->ri_WindowBorderLeft;
	    }
	    top_edge  += ri->ri_WindowBorderTop;
	 }
	 if (win) {
	    PrintIText(win->RPort, &it, (LONG)left_edge, (LONG)top_edge);
	 }
      }
   }
   return(width);
}
	/* Convert num to string with unsigned dec value of num */

ULONG dec_table[MAX_DEC_NUM_DIGITS] = {   /* used also by gadgets.c */
   1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1
};

   USHORT
convert_unsigned_dec(ULONG num, BYTE *buffer)
{
   USHORT i, len = 0;
   BYTE   digit;

   if (!num) {
      if (buffer) {
	 *buffer++ = '0';
      }
      len++;
   } else {
      /* strip leading zeros */
      for (i = 0; i < MAX_DEC_NUM_DIGITS; i++) {
	 if (num >= dec_table[i]) {
	    break;
	 }
      }
      /* convert num */
      for ( ; i < MAX_DEC_NUM_DIGITS; i++) {
	 if (digit = num / dec_table[i]) {
	    num -= digit * dec_table[i];
	 }
	 if (buffer) {
	    *buffer++ = '0' + digit;
	 }
	 len++;
      }
   }
   if (buffer) {
      *buffer = '\0';
   }
   return(len);
}
	/* Convert num to string with signed dec value of num */

   USHORT
convert_signed_dec(LONG num, BYTE *buffer)
{
   USHORT i, len = 0;
   BYTE   digit;

   if (!num) {
      if (buffer) {
	 *buffer++ = '0';
      }
      len++;
   } else {
      /* if num is negativ then prepend minus sign */
      if (num < 0) {
	 if (buffer) {
	    *buffer++ = '-';
	 }
	 len++;
	 num = -num;
      }
      /* strip leading zeros */
      for (i = 0; i < MAX_DEC_NUM_DIGITS; i++) {
	 if (num >= dec_table[i]) {
	    break;
	 }
      }
      /* convert num */
      for ( ; i < MAX_DEC_NUM_DIGITS; i++) {
	 if (digit = num / dec_table[i]) {
	    num -= digit * dec_table[i];
	 }
	 if (buffer) {
	    *buffer++ = '0' + digit;
	 }
	 len++;
      }
   }
   if (buffer) {
      *buffer = '\0';
   }
   return(len);
}
	/* Convert num to string with hex value of num */

   USHORT
convert_hex(ULONG num, BYTE *buffer)
{
   ULONG  mask = 0xf0000000;
   USHORT len = 0;
   SHORT  i;
   BYTE   digit;

   if (!num) {
      if (buffer) {
         *buffer++ = '0';
      }
      len++;
   } else {
      /* strip leading zeros */
      for (i = (MAX_HEX_NUM_DIGITS - 1) * 4; i >= 0; i -= 4) {
	 if (digit = (num & mask) >> i) {
	    break;
	 } else {
	    mask >>= 4;
	 }
      }
      /* convert num */
      for ( ; i >= 0; i -= 4) {
	 digit     = (num & mask) >> i;
	 mask    >>= 4;
	 if (buffer) {
	    *buffer++ = (digit < 10 ? '0' : 'a' - 10) + digit;
	 }
	 len++;
      }
   }
   if (buffer) {
      *buffer = '\0';
   }
   return(len);
}
	/* Convert num to string with bin value of num */

   USHORT
convert_bin(ULONG num, BYTE *buffer)
{
   ULONG  mask = 0x80000000;
   USHORT i, len = 0;

   if (!num) {
      if (buffer) {
	 *buffer++ = '0';
      }
      len++;
   } else {
      /* strip leading zeros */
      for (i = 0; i < MAX_BIN_NUM_DIGITS; i++) {
	 if (num & mask) {
	    break;
	 } else {
	    mask >>= 1;
	 }
      }
      /* convert num */
      for ( ; i < MAX_BIN_NUM_DIGITS; i++) {
	 if (num & mask) {
	    if (buffer) {
	       *buffer++ = '1';
	    }
	 } else {
	    if (buffer) {
	       *buffer++ = '0';
	    }
	 }
	 len++;
	 mask >>= 1;
      }
   }
   if (buffer) {
      *buffer = '\0';
   }
   return(len);
}
