/* $Revision Header *** Header built automatically - do not edit! ***********
 *
 *	(C) Copyright 1991 by Torsten Jürgeleit
 *
 *	Name .....: texts.c
 *	Created ..: Thursday 19-Dec-91 16:46:55
 *	Revision .: 2
 *
 *	Date        Author                 Comment
 *	=========   ====================   ====================
 *	21-Mar-92   Torsten Jürgeleit      flags for converting numbers
 *	28-Dec-91   Torsten Jürgeleit      no complement if ri_ScreenDepth == 1
 *                                         and not count gadget value text
 *	19-Dec-91   Torsten Jürgeleit      Created this file!
 *
 ****************************************************************************
 *
 *	Text output and converting functions
 *
 * $Revision Header ********************************************************/

	/* Includes */

#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/text.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 <string.h>
#include "/render/render.h"
#include "/language/language.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,
						 BYTE **language_text_array)
{
   if (ri && win && td) {
      for ( ; td->td_Type != INTUISUP_DATA_END &&
				  td->td_Type <= MAX_TEXT_DATA_TYPE; td++) {
	 BYTE *text;

	 if (td->td_Type == TEXT_DATA_TYPE_TEXT) {
	    text = get_language_text(td->td_Text, language_text_array);
	 } else {
	    text = td->td_Text;
	 }
	 print_text(ri, win, text, td->td_LeftEdge + hoffset,
				      td->td_TopEdge + voffset, td->td_Type,
					     td->td_Flags, td->td_TextAttr);
      }
   }
}
	/* 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)
{
   USHORT width = 0;

   if (ri && (win || (flags & TEXT_DATA_FLAG_NO_PRINT)) &&
				    (text || type != TEXT_DATA_TYPE_TEXT)) {
      struct TextFont  *tf;

      /* If no text attr given then use screen text attr */
      if (!text_attr || !(text_attr = ask_font(ri, text_attr))) {
	 text_attr = &ri->ri_TextAttr;
      }

      /* Load font into memory */
      if (tf = open_font(ri, text_attr)) {
	 struct IntuiText  itext, *it = &itext;
	 struct TextAttr   tattr, *ta = &tattr;
	 BYTE buffer[MAX_NUM_BUFFER_SIZE];

	 /* 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 */
	 if (type != TEXT_DATA_TYPE_TEXT) {
	    USHORT conv_flags = 0;

	    /* Calc convert flags */
	    if (flags & TEXT_DATA_FLAG_NUM_IDENTIFIER) {
	       conv_flags |= CONVERT_FLAG_IDENTIFIER;
	    }
	    if (flags & TEXT_DATA_FLAG_NUM_C_STYLE) {
	       conv_flags |= CONVERT_FLAG_C_STYLE;
	    }
	    if (flags & TEXT_DATA_FLAG_NUM_LEADING_ZEROES) {
	       conv_flags |= CONVERT_FLAG_LEADING_ZEROES;
	    }
	    if (flags & TEXT_DATA_FLAG_NUM_UPPER_CASE) {
	       conv_flags |= CONVERT_FLAG_UPPER_CASE;
	    }

	    /* Convert number to text */
	    switch (type) {
	       case TEXT_DATA_TYPE_NUM_UNSIGNED_DEC :
		  convert_unsigned_dec((ULONG)text, &buffer[0], conv_flags);
		  break;

	       case TEXT_DATA_TYPE_NUM_SIGNED_DEC :
		  convert_signed_dec((LONG)text, &buffer[0], conv_flags);
		  break;

	       case TEXT_DATA_TYPE_NUM_HEX :
		  convert_hex((ULONG)text, &buffer[0], conv_flags);
		  break;

	       case TEXT_DATA_TYPE_NUM_BIN :
		  convert_bin((ULONG)text, &buffer[0], conv_flags);
		  break;
	    }
	 }

	 /* Get length of intui text */
	 it->IText     = (UBYTE *)(type == TEXT_DATA_TYPE_TEXT ? text :
								&buffer[0]);
	 it->ITextFont = ta;
	 width         = IntuiTextLength(it);
	 if (!(flags & TEXT_DATA_FLAG_NO_PRINT)) {

	    /* Init intui text */
	    it->LeftEdge = 0;
	    it->TopEdge  = 0;
	    it->BackPen  = ri->ri_BackPen;
	    it->NextText = NULL;

	    /* 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) &&
						  (ri->ri_ScreenDepth > 1 ||
				 (flags & INTERNAL_TEXT_DATA_FLAG_COUNT))) {
	       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;
	    }
	    PrintIText(win->RPort, it, (LONG)left_edge, (LONG)top_edge);
	 }
	 CloseFont(tf);
      }
   }
   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 flags)
{
   USHORT len = 0;

   if (!num) {

      /* Insert zero value */
      if (!(flags & CONVERT_FLAG_LEADING_ZEROES)) {
	 if (buffer) {
	    *buffer++ = '0';
	 }
	 len++;
      } else {
	 if (buffer) {
	    strcpy(buffer, "0000000000");
	    buffer += MAX_DEC_NUM_DIGITS;
	 }
	 len += MAX_DEC_NUM_DIGITS;
      }
   } else {
      USHORT i = 0;

      /* Strip leading zeros */
      if (!(flags & CONVERT_FLAG_LEADING_ZEROES)) {
	 for ( ; i < MAX_DEC_NUM_DIGITS; i++) {
	    if (num >= dec_table[i]) {
	       break;
	    }
	 }
      }

      /* Convert num */
      for ( ; i < MAX_DEC_NUM_DIGITS; i++) {
	 BYTE digit = num / dec_table[i];

	 if (digit) {
	    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 flags)
{
   USHORT len = 0;

   if (!num) {

      /* Insert zero value */
      if (!(flags & CONVERT_FLAG_LEADING_ZEROES)) {
	 if (buffer) {
	    *buffer++ = '0';
	 }
	 len++;
      } else {
	 if (buffer) {
	    strcpy(buffer, "0000000000");
	    buffer += MAX_DEC_NUM_DIGITS;
	 }
	 len += MAX_DEC_NUM_DIGITS;
      }
   } else {
      USHORT i = 0;

      /* If num is negativ then prepend minus sign */
      if (num < 0) {
	 if (buffer) {
	    *buffer++ = '-';
	 }
	 len++;
	 num = -num;
      }

      /* Strip leading zeros */
      if (!(flags & CONVERT_FLAG_LEADING_ZEROES)) {
	 for ( ; i < MAX_DEC_NUM_DIGITS; i++) {
	    if (num >= dec_table[i]) {
	       break;
	    }
	 }
      }

      /* Convert num */
      for ( ; i < MAX_DEC_NUM_DIGITS; i++, len++) {
	 BYTE digit = num / dec_table[i];

	 if (digit) {
	    num -= digit * dec_table[i];
	 }
	 if (buffer) {
	    *buffer++ = '0' + digit;
	 }
      }
   }
   if (buffer) {
      *buffer = '\0';
   }
   return(len);
}
	/* Convert num to string with hex value of num */

   USHORT
convert_hex(ULONG num, BYTE *buffer, USHORT flags)
{
   USHORT len = 0;

   /* Insert identifier */
   if (flags & CONVERT_FLAG_IDENTIFIER) {
      if (flags & CONVERT_FLAG_C_STYLE) {
	 if (buffer) {
	    if (flags & CONVERT_FLAG_UPPER_CASE) {
	       strcpy(buffer, "0X");
	    } else {
	       strcpy(buffer, "0x");
	    }
	    buffer += 2;
	 }
	 len += 2;
      } else {
         if (buffer) {
	    *buffer++ = '$';
	 }
	 len++;
      }
   }
   if (!num) {

      /* Insert zero value */
      if (!(flags & CONVERT_FLAG_LEADING_ZEROES)) {
	 if (buffer) {
	    *buffer++ = '0';
	 }
	 len++;
      } else {
	 if (buffer) {
	    strcpy(buffer, "00000000");
	    buffer += MAX_HEX_NUM_DIGITS;
	 }
	 len += MAX_HEX_NUM_DIGITS;
      }
   } else {
      ULONG mask = 0xf0000000;
      SHORT i = (MAX_HEX_NUM_DIGITS - 1) * 4;

      /* Strip leading zeros */
      if (!(flags & CONVERT_FLAG_LEADING_ZEROES)) {
	 for ( ; i >= 0; i -= 4, mask >>= 4) {
	    if ((num & mask) >> i) {
	       break;
	    }
	 }
      }

      /* Convert num */
      for ( ; i >= 0; i -= 4, mask >>= 4, len++) {
	 if (buffer) {
	    BYTE digit = (num & mask) >> i;

	    if (flags & CONVERT_FLAG_UPPER_CASE) {
	       *buffer++ = (digit < 10 ? '0' : 'A' - 10) + digit;
	    } else {
	       *buffer++ = (digit < 10 ? '0' : 'a' - 10) + digit;
	    }
	 }
      }
   }
   if (buffer) {
      *buffer = '\0';
   }
   return(len);
}
	/* Convert num to string with bin value of num */

   USHORT
convert_bin(ULONG num, BYTE *buffer, USHORT flags)
{
   USHORT len = 0;

   /* Insert identifier */
   if (flags & CONVERT_FLAG_IDENTIFIER) {
      if (buffer) {
	 *buffer++ = '%';
      }
      len++;
   }
   if (!num) {

      /* Insert zero value */
      if (!(flags & CONVERT_FLAG_LEADING_ZEROES)) {
	 if (buffer) {
	    *buffer++ = '0';
	 }
	 len++;
      } else {
	 if (buffer) {
	    strcpy(buffer, "00000000000000000000000000000000");
	    buffer += MAX_BIN_NUM_DIGITS;
	 }
	 len += MAX_BIN_NUM_DIGITS;
      }
   } else {
      ULONG  mask = 0x80000000;
      USHORT i = 0;

      /* Strip leading zeros */
      if (!(flags & CONVERT_FLAG_LEADING_ZEROES)) {
	 for ( ; i < MAX_BIN_NUM_DIGITS; i++, mask >>= 1) {
	    if (num & mask) {
	       break;
	    }
	 }
      }

      /* Convert num */
      for ( ; i < MAX_BIN_NUM_DIGITS; i++, mask >>= 1, len++) {
	 if (num & mask) {
	    if (buffer) {
	       *buffer++ = '1';
	    }
	 } else {
	    if (buffer) {
	       *buffer++ = '0';
	    }
	 }
      }
   }
   if (buffer) {
      *buffer = '\0';
   }
   return(len);
}
