/*
 * roterm.c - RISC OS replacement for term.c
 *
 * David Bryan, 1995
 */

#include <signal.h>
#include "kernel.h"
#include "swis.h"
#include "config.h"
#include "ispell.h"
#include "proto.h"
#include "msgs.h"

#define OS_GWBRow 129
#define OS_GWRCol 130
#define OS_GWTRow 131
#define OS_TWLCol 132
#define OS_TWBRow 133
#define OS_TWRCol 134
#define OS_TWTRow 135
#define OS_OrgX 136
#define OS_OrgY 137
#define OS_GCsX 138
#define OS_GCsY 139
#define OS_OlderCsX 140
#define OS_OlderCsY 141
#define OS_OldCsX 142
#define OS_OldCsY 143
#define OS_GCsIX 144
#define OS_GCsIY 145
#define OS_NewPtX 146
#define OS_NewPtY 147
#define OS_ScreenStart 148
#define OS_DisplayStart 149
#define OS_TotalScreenSize 150
#define OS_GPLFMD 151
#define OS_CPLBMD 152
#define OS_GFCOL 153
#define OS_GBCOL 154
#define OS_TForeCol 155
#define OS_TBackCol 156
#define OS_GFTint 157
#define OS_GBTint 158
#define OS_TFTint 159
#define OS_TBTint 160
#define OS_MaxMode 161
#define OS_GCharSizeX 162
#define OS_GCharSizeY 163
#define OS_GCharSpaceX 164
#define OS_GCharSpaceY 165
#define OS_HLineAddr 166
#define OS_TCharSizeX 167
#define OS_TCharSizeY 168
#define OS_TCharSpaceX 169
#define OS_TCharSpaceY 17

#ifndef USESH
#define NEED_SHELLESCAPE
#endif

static _kernel_swi_regs swi_regs_in, swi_regs_out;
static int fg, bg;

void erase (void)
{
  putchar (12);
}

void move (int row, int col)
{
  putchar (31);
  putchar (col);
  putchar (row);
}

void inverse (void)
{
  putchar (17);
  putchar (bg);
  putchar (17);
  putchar (fg+128);
}

void normal (void)
{
  putchar (17);
  putchar (fg);
  putchar (17);
  putchar (bg+128);
}

void backup (void)
{
  putchar (8);
}

static int os_read_vdu_variable (int vdu_variable)
{
  static int vdu_variable_block[2] = {0,-1};

  vdu_variable_block[0] = vdu_variable;
  swi_regs_in.r[0] = (int) &vdu_variable_block;
  swi_regs_in.r[1] = (int) &vdu_variable_block;
  _kernel_swi (OS_ReadVduVariables, &swi_regs_in, &swi_regs_out);

  return vdu_variable_block[0];
}

static void checkterm (void)
{
  co = os_read_vdu_variable (OS_TWRCol);
  li = os_read_vdu_variable (OS_TWBRow);
  bg = os_read_vdu_variable (OS_TBackCol);
  fg = os_read_vdu_variable (OS_TForeCol);

#if MAXCONTEXT == MINCONTEXT
  contextsize = MINCONTEXT;
#else /* MAXCONTEXT == MINCONTEXT */
  if (contextsize == 0)
#ifdef CONTEXTROUNDUP
    contextsize = (li * CONTEXTPCT + 99) / 100;
#else /* CONTEXTROUNDUP */
    contextsize = (li * CONTEXTPCT) / 100;
#endif /* CONTEXTROUNDUP */
  if (contextsize > MAXCONTEXT)
    contextsize = MAXCONTEXT;
  else if (contextsize < MINCONTEXT)
    contextsize = MINCONTEXT;
#endif /* MAX_CONTEXT == MIN_CONTEXT */
  /*
   * Insist on 2 lines for the screen header, 2 for blank lines
   * separating areas of the screen, 2 for word choices, and 2 for
   * the minimenu, plus however many are needed for context.  If
   * possible, make the context smaller to fit on the screen.
   */
  if (li < contextsize + 8  &&  contextsize > MINCONTEXT)
    {
    contextsize = li - 8;
    if (contextsize < MINCONTEXT)
      contextsize = MINCONTEXT;
    }
  if (li < MINCONTEXT + 8)
    fprintf (stderr, TERM_C_SMALL_SCREEN, MINCONTEXT + 8);
}

void stop (void)
{
  printf (TERM_C_TO_LEAVE_SUPERVISOR);
  fflush (stdout);
  system ("GOS");
  checkterm ();  /* The sodding user might have changed mode! */
}

SIGNAL_TYPE done (int signo)
{
  erase ();

  destroy_memory_area (hash_table_area);
  destroy_memory_area (lexicon_area);

  exit(EXIT_SUCCESS);
}

void onstop (int signo)
{
  signal (SIGINT, SIG_IGN);
  signal (SIGTERM, SIG_IGN);

  destroy_memory_area (hash_table_area);
  destroy_memory_area (lexicon_area);

  exit(EXIT_FAILURE);
}

void terminit (void)
{
  erase ();

  co = os_read_vdu_variable (OS_TWRCol);
  li = os_read_vdu_variable (OS_TWBRow);
  bg = os_read_vdu_variable (OS_TBackCol);
  fg = os_read_vdu_variable (OS_TForeCol);

  erasechar = (char) 8;
  killchar = (char) 21;

  checkterm ();

  /* We now force the C library to stop getting in the
   * way of us reading from and writting to the terminal. */

  *stdin  = *(fopen ("rawkbd:", "r"));
  *stdout = *(fopen ("rawvdu:", "wb"));

  setvbuf (stdin, NULL, _IONBF, 0);        /* Unix cbreak mode. */

  signal (SIGINT, onstop);
  signal (SIGTERM, onstop);
}


#ifndef USESH
#define NEED_SHELLESCAPE
#endif
#ifndef REGEX_LOOKUP
#define NEED_SHELLESCAPE
#endif
#ifdef NEED_SHELLESCAPE
int shellescape (char *buf)
{
  int system_return_value = system (buf);
  printf (TERM_C_TYPE_SPACE);
  fflush (stdout);

#ifdef COMMANDFORSPACE
  ch = GETKEYSTROKE ();
  if (ch != ' '  &&  ch != '\n'  &&  ch != '\r')
    ungetc (ch, stdin);
#else
  while (GETKEYSTROKE () != ' ')
    ;
#endif
  return system_return_value;
}
#endif

#ifdef USESH
void shescape (char *buf)
{
  system (buf);
  printf (TERM_C_TYPE_SPACE);
  fflush (stdout);

#ifdef COMMANDFORSPACE
  ch = GETKEYSTROKE ();
  if (ch != ' '  &&  ch != '\n'  &&  ch != '\r')
    ungetc (ch, stdin);
#else
  while (GETKEYSTROKE () != ' ')
     ;
#endif
}
#endif
