/*
 *	Universal Terminal Interface -- Scrolling and Inserts
 *
 *	(c) 1997 Martin Mares, <mj@ericsson.cz>
 */

#include "termint.h"

byte in_window;				/* Scrolling window active */
ulg win_r0, win_c0, win_r1, win_c1;	/* Scrolling window */
byte ins_mode;				/* Insertion mode: 0=none, 1=ins, 2=del */

/* Initialize */

void
scroll_init(void)
{
  win_r1 = rows - 1;
  win_c1 = columns - 1;
}

/* Scrolling window */

void
reset_window(void)
{
}

/* Mode switching */

void
set_ins_mode(int i)
{
  if (ins_mode != i)
    {
      TR("Toggling mode %d -> %d\n", ins_mode, i);
      switch (ins_mode)
	{
	case IM_INSERT:
	  send(STR(INSERT_OFF));
	  break;
	case IM_DELETE:
	  send(STR(DELETE_OFF));
	  break;
	}
      ins_mode = i;
      switch (i)
	{
	case IM_INSERT:
	  send(STR(INSERT_ON));
	  break;
	case IM_DELETE:
	  send(STR(DELETE_ON));
	  break;
	}
    }
}

/* Move region */

void
Tmove(int r, int c, int h, int w, int rr, int cc)
{
  int pos0, pos1, sop0, sop1, ww;

  if (r == rr && c == cc)		/* Trivial case */
    return;

  r += ww_r0;
  c += ww_c0;
  rr += ww_r0;
  cc += ww_c0;

  TR("Moving %d.%d/%d.%d to %d.%d\n", r, c, h, w, rr, cc);
  light(rr, cc, h, w);

  if (rr > r || rr == r && cc > c)	/* End-to-start */
    {
      pos0 = (r+h) * columns + c + w;
      sop0 = (rr+h) * columns + cc + w;
      while (h--)
	{
	  pos0 -= columns;
	  sop0 -= columns;
	  pos1 = pos0;
	  sop1 = sop0;
	  for(ww=0; ww<w; ww++)
	    {
	      pos1--, sop1--;
	      cnew[sop1] = cnew[pos1];
	      anew[sop1] = anew[pos1];
	      knew[sop1] = knew[pos1];
	    }
	}
    }
  else					/* Start-to-end */
    {
      pos0 = r * columns + c;
      sop0 = rr * columns + cc;
      while (h--)
	{
	  pos1 = pos0;
	  sop1 = sop0;
	  for(ww=0; ww<w; ww++)
	    {
	      cnew[sop1] = cnew[pos1];
	      anew[sop1] = anew[pos1];
	      knew[sop1] = knew[pos1];
	      pos1++, sop1++;
	    }
	  pos0 += columns;
	  sop0 += columns;
	}
    }
}

/* Universal scrolling (no optimizations yet) */

void
Tscroll(int r, int c, int h, int w, int dr, int dc)
{
  if (dr && dc)
    {
      Tscroll(r, c, h, w, dr, 0);
      dr = 0;
    }
  TR("Scrolling %d.%d/%d.%d by %d/%d\n",r, c, h, w, dr, dc);
  if (dr)
    {
      if (dr >= h || dr <= -h)
	Tclear(r, c, h, w);
      else if (dr >= 0)
	{
	  Tmove(r, c, h-dr, w, r+dr, c);
	  Tclear(r, c, dr, w);
	}
      else
	{
	  Tmove(r-dr, c, h+dr, w, r, c);
	  Tclear(r+h+dr, c, -dr, w);
	}
    }
  if (dc)
    {
      if (dc >= w || dc <= -w)
	Tclear(r, c, h, w);
      else if (dc >= 0)
	{
	  Tmove(r, c, h, w-dc, r, c+dc);
	  Tclear(r, c, h, dc);
	}
      else
	{
	  Tmove(r, c-dc, h, w+dc, r, c);
	  Tclear(r, c+w+dc, h, -dc);
	}
    }
}

/* Insertion (doesn't use insert mode yet) */

void
Tinsert(int r, int c, int w, byte *text)
{
  Tscroll(r, c, w, 1, 0, strlen(text));
  Tgoto(r, c);
  Tputs(text);
}
