/*
  Window
*/

#include "window.h"

#include "config.h"
#include "console.h"
#include "file.h"
#include "head.h"
#include "infocom.h"
#include "jump.h"
#include "mem.h"
#include "os.h"
#include "print.h"
#include "shared.h"
#include "var.h"
#include "wio.h"

static bool cursor_pos_saved;

/*
**	Enhanced Windowing and Screen Printing Functions.
*/

void set_current_window(word the_window)
{
  extern word current_window;
  extern bool disable_script;

  if(hd_five())
    flush_prt_buff();
  current_window = the_window;
  if(the_window != 0)
  {
    /* Use the Upper Window. */
    save_cursor_position();
    use_window(STATUS_WINDOW);
    disable_script = 1;
    goto_xy(0, 0);
  }
  else
  {
    /* Use the Lower Window. */
    use_window(TEXT_WINDOW);
    disable_script = 0;
    restore_cursor_position();
    set_text_mode(0);
  }
}

void split_screen(word param)
{
  extern bool windowing_enabled;
  extern word status_height;
  extern int linecount;
  word old_height = status_height;

  /* Addition from Zip set_status_size */
  if(!hd_plus())
    ++param;

  if(param == 0)
  {
    /* Use the entire Screen. */

    use_window(FULL_SCREEN);
    /* restore_cursor_position(); */
    windowing_enabled = 0;
    status_height = 0;
    linecount = 0;
  }
  else
  {
    windowing_enabled = 1;
    status_height = min(param, hd_height() - 1);
    if(!hd_plus())
    {
      save_cursor_position();
      erase_window(0, status_height);
      restore_cursor_position();
    }
    use_window(TEXT_WINDOW);
    if(hd_five())
    {
      int x, y;
      get_xy(&x, &y);
      if(y < status_height)
        set_xy(0, hd_height() - 1);
    }
  }
  {
    int i;
    start_update();
    for(i = status_height; i < old_height; ++i) touch(i);
    finish_update();
  }
}

void save_cursor_position(void)
{
  if(!cursor_pos_saved)
  {
    save_cursor();
    cursor_pos_saved = 1;
  }
}

void restore_cursor_position(void)
{
  if(cursor_pos_saved)
  {
    restore_cursor();
    cursor_pos_saved = 0;
  }
  else if(hd_version() > VERSION_4)
  {
    set_xy(0, hd_height() - 1);
  }
}

void do_beep(word sound)
{
  USE(sound);
}

void erase_line(word mode)
{
  if(mode == 1)
    erase_to_eoln();
}

void do_clear_screen(word param)
{
  extern word status_height;

  switch((signed_word) param)
  {
    case -1:
      split_screen((word) 0);
      erase_window(0, (word) hd_height());
      if(hd_version() == VERSION_4)
	set_xy(0, hd_height() - 1);
      break;
    case 0:
      erase_window(status_height, (word) hd_height());
      break;
    case 1:
      erase_window(0, status_height);
      break;
  }
}

void set_cursor_posn(word y, word x)
{
  extern word current_window;

  if(current_window != 0)
  {
    if(hd_five())
      flush_prt_buff();
    goto_xy(x - 1, y - 1);
  }
}

void set_text_mode(word mode)
{
  /* Pack down from bit field.  Limits the display somewhat. */
  int font = FONT_NORMAL;
  if(mode & 8) font = FONT_FIXED;
  if(mode & 4) font = FONT_EMPH;
  if(mode & 2) font = FONT_BOLD;
  if(mode & 1) font = FONT_REVS;
  if(mode == 9) font = FONT_FIXED_REVS;
  print_char(make_font_request(font));
}

void set_text_colour(word fore,  word back)
{
  print_char(make_attr_request(make_attr(fore, back)));
}

void io_buffer_mode(word param)
{
  extern bool use_buffered_io;

  if(param == 0)
  {
    use_buffered_io = 0;
    flush_prt_buff();
  }
  else
  {
    use_buffered_io = 1;
  }
}

void io_mode(signed_word mode, word buffer)
{
  extern long_word internal_io_buffer;
  extern word int_io_buff_length;
  extern bool enable_screen;
  extern bool script_on;
  extern bool use_internal_buffer;

  switch(mode)
  {
    case 1:
      enable_screen = 1;
      break;
    case 2:
      if(!script_on)
      {
        hd_set_script(1);
        script_on = open_script();
	if(!script_on)
	  hd_err_script();
      }
      break;
    case 3:
      use_internal_buffer = 1;
      internal_io_buffer  = buffer;
      int_io_buff_length  = 0;
      break;
    case -1:
      enable_screen = 0;
      break;
    case -2:
      script_on = 0;
      hd_set_script(0);
      close_script();
      break;
    case -3:
      use_internal_buffer = 0;
      wr_word_addr(internal_io_buffer, int_io_buff_length);
      /* internal_io_buffer += 1; */
      wr_byte_addr(internal_io_buffer + 2 + int_io_buff_length, 0);
      break;
  }
}

void get_key(void)
{
  extern word param_stack[];
  extern int linecount;

  if(hd_five())
    flush_prt_buff();

  linecount = 0;
  if(param_stack[1] == 1)
  {
#if 0 /* wait_for_key is TRUE */
    if(param_stack[0] < 3
    || wait_for_key(param_stack[2] / 10, param_stack[3]))
#endif
      store(read_the_key());
  }
  else
  {
    store(0);
  }
}

word read_the_key(void)
{
  int ch, done;
  do
  {
    done = 1;
    ch = get_ch();
    switch(ch)
    {
      case '\a':
      case '\013':
      case '\b':
      case '\r':
	break;
      case 'P' - '@':
	ch = 0x5C;
	break;
      case 'N' - '@':
	ch = ' ';
	break;
      case 'F' - '@':
	ch = '+';
	break;
      case 'B' - '@':
	ch = '-';
	break;
      case '\n':
	ch = '\r';
	break;
      default:
	done = ch >= ' ';
	break;
    }
  } while(!done);
  return ch;
}

#if 0
bool wait_for_key(word time_out, word address)
{
  /* Optimise until kbd_hit implemented fully */
  return 1;
  word delay = time_out;
  do
  {
    do
    {
      long now = os_time();
      do
      {
	if(kbd_hit())
	  return 1;
      } while(os_time() - now < 1);
    } while(--delay != 0);
  } while(special_gosub(address) == 0);
  return 0;
}
#endif
