/*
**  This file is part of Zterp, and is
**  Copyright 1992, 1993 Charles Hannum
*/

#include <sys/types.h>
#include "main.h"
#include "object.h"
#include "variable.h"
#include "jump.h"
#include "print.h"
#include "output.h"

void
print_character (x)
  uword x;
{
  buffer_character (x);
}

void
print_number (x)
  sword x;
{
  if (x == 0)
    buffer_character ('0');
  else if (x < 0)
    x = -x, buffer_character ('-');
  else
  {
    char s[6], *p = s + 6;
    *(--p) = '\0';
    while (x)
    {
      *(--p) = '0' + x % 10;
      x = x / 10;
    }
    print_string (p);
  }
}

void
print_near (a)
  uword a;
{
  print_encoded (near_address (a));
}

void
print_object_name (n)
  uword n;
{
  print_encoded (near_address (get_data (object_ptr (n)) + 1));
}

void
print_far (a)
  uword a;
{
  print_encoded (far_address (a));
}

void
print_immediate ()
{
  set_pc (print_encoded (pc));
}

void
print_immediate_and_ret ()
{
  print_immediate ();
  print_newline ();
  ret_true ();
}

void
print_string (char *p)
{
  char c;
  while ((c = *p) != '\0')
  {
    switch (c)
    {
      case '\n':
	print_newline ();
	break;
      default:
	buffer_character (c);
	break;
    }
    ++p;
  }
}

zpointer
print_encoded (zpointer p)
{
  uword x;
  sword mode = 0;
  uword alpha = 0, alpha_lock = 0;
  do {
    int n;
    uword codes[3];
    x = get_word (p);
    p += 2;
    for (n = 0; n < 3; n++)
    {
      codes[n] = x & 0x1f;
      x >>= 5;
    }
    for (n = 3; n;)
    {
      uword code = codes[--n];
      if (mode < 0)
      {
	print_encoded (near_address (((get_word (shortcut + (((mode & 0x60) | code) << 1))) << 1)));
	alpha = alpha_lock;
	mode = 0;
      }
      else if (mode)
      {
	buffer_character ((mode & 0xe0) | code);
	alpha = alpha_lock;
	mode = 0;
      }
      else if (alpha == 3)
	mode = 0x4000 | (code << 5);
      else if (code < 6)
	if (code == 0)
	{
	  buffer_character (' ');
	  alpha = alpha_lock;
	}
	else
	{
	  if (code == 1 && zil_version == 1)
	  {
	    print_newline ();
	    alpha = alpha_lock;
	  }
	  else if (code == 1 || (code <= 3 && zil_version >= 3))
	    mode = 0x8000 | ((code - 1) << 5);
	  else
	    if (zil_version >= 3)
	    {
	      code -= 3;
	      if (!alpha)
	        alpha = code;
	      else if (alpha != code)
	        alpha = 0;
	      else
	        alpha_lock = alpha;
	    }
	    else
	      alpha = (code & 1) + 1;
	}
      else if (alpha != 2 || code > (7 - (zil_version < 2)))
      {
	buffer_character (alphabet[alpha * 26 + code - 6]);
	alpha = alpha_lock;
      }
      else if (code == 6)
	++alpha;
      else /* code == 7 */
      {
	print_newline ();
	alpha = alpha_lock;
      }
    }
  } while (!x);
  return (p);
}

void
print_status ()
{
  extern char *buffer_end, *buffer_top;
  int n;

  set_window (1);
  set_video (1);
  set_buffer (0);

  buffer_character (' ');
  print_object_name (fetch_variable_nopop (LOCAL_VARS + 0));

  n = buffer_end - buffer_top;
  if (header->flags1 & 0x02)
    n -= 20;
  else
    n -= 30;
  while (n--)
    buffer_character (' ');
  
  if (header->flags1 & 0x02)
  {
    uword hour = fetch_variable_nopop (LOCAL_VARS + 1),
	  minute = fetch_variable_nopop (LOCAL_VARS + 2),
	  hour_12 = (hour % 12) ? (hour % 12) : 12;
    char s[] = {hour_12 < 10 ? ' ' : (hour_12 / 10 + '0'), hour_12 % 10 + '0', ':',
		minute / 10 + '0', minute % 10 + '0', ' ',
		hour >= 12 ? 'p' : 'a', 'm', '\0'};
    print_string ("Time: ");
    print_string (s);
  }
  else
  {
    print_string ("Score: ");
    print_number (fetch_variable_nopop (LOCAL_VARS + 1));
    n = buffer_end - buffer_top - 14;
    while (n--)
      buffer_character (' ');
    print_string ("Moves: ");
    print_number (fetch_variable_nopop (LOCAL_VARS + 2));
  }

  n = buffer_end - buffer_top;
  while (n--)
    buffer_character (' ');

  set_buffer (1);
  set_window (0);
}
