/* 3270 local editing functions

   This file contains selected cursor movement and local editing
   functions.  They were moved out of s3270.c because that file
   was taking too long to compile.				*/


#include "s3270loc.h"
extern char alphanum[];		/* Alphanumeric character table */
extern field *cursfield();


/* Move cursor to start of next unprotected field */
loc_goinp()
{
  register field *cursf, *f;

  if (!(cursf = cursfield())) return 0;
  if (cursf->attrib & UNPROTECTED && cursf->len > 1)
    {
      if (getcursor() == cursf->pos) newcursor(getcursor() + 1);
      return 0;
    }
  for (f = cursf->next;
       f != cursf && (!(f->attrib & UNPROTECTED) || f->len <= 1);
       f = f->next);
  if (f == cursf) newcursor(0);
  else newcursor(f->pos + 1);
  return 0;
}


/* Do automatic skip from last character of an unprotected field */
loc_autoskip()
{
  register field *cursf;

  if (!(cursf = cursfield()) || getcursor() != cursf->pos) return 0;

  /* If next field is alphanumeric or numeric and unprotected, go there */
  if (cursf->len > 1 && (!(cursf->attrib & NUMERIC) ||
			 cursf->attrib & UNPROTECTED))
    newcursor(getcursor() + 1);

  /* Otherwise go to first character of next unprotected field */
  else loc_goinp();
  return 0;
}


/* Do forward tab */
loc_tab()
{
  register int oldcursor;
  register field *f;

  oldcursor = getcursor();
  loc_goinp();
  if (getcursor() != oldcursor) return 0;
  if (!(f = cursfield())) return 0;
  newcursor(f->next->pos + 1);
  loc_goinp();
  return 0;
}


/* Do backward tab */
loc_backtab(scrsize)
{
  register field *cursf, *f;

  if (!(cursf = cursfield())) return 0;
  if (getcursor() != cursf->pos && getcursor() != nextpos(cursf->pos) &&
      cursf->len > 1)
    {
      newcursor(cursf->pos + 1);
      return 0;
    }
  for (f = cursf->prev;
       f != cursf && (!(f->attrib & UNPROTECTED) || f->len <= 1);
       f = f->prev);
  if (f == cursf) newcursor(0);
  else newcursor(f->pos + 1);
  return 0;
}


/* Handle "End" key:  If field has nulls at the end, then position after
   last non-null character.  Otherwise, position after the last non-blank
   and non-null character.  */

loc_end(screen, scrsize)
     unsigned char *screen;
     int scrsize;
{
  register int pos;
  register field *cursf;
  Boolean lastnull;

  if (!(cursf = cursfield())) return 0;
  pos = cursf->pos + cursf->len - 1;
  if (pos >= scrsize) pos -= scrsize;
  lastnull = !screen[pos];
  for (; pos != cursf->pos; pos = prevpos(pos))
    if (screen[pos] && screen[pos] != EBCSPACE ||
	lastnull && screen[pos]) break;
  newcursor(pos + 1);
  return 0;
}


/* Position to end of current word */
loc_forward_word(screen)
     unsigned char *screen;
{
  register int pos, endpos;
  register field *cursf;

  cursf = cursfield();
  if (cursf) endpos = cursf->next->pos;
  else endpos = 0;
  pos = getcursor();
  while (!alphanum[screen[getcursor()]] || cursf &&
	 (getcursor() == cursf->pos || !(cursf->attrib & UNPROTECTED) ||
	  cursf->len <= 1))
    {
      newcursor(getcursor() + 1);
      if (cursf && getcursor() == endpos) 
	{
	  cursf = cursf->next;
	  endpos = cursf->next->pos;
	}
      if (getcursor() == pos) break;
    }
  pos = getcursor();
  while (alphanum[screen[getcursor()]] &&
	 (!cursf || getcursor() != cursf->pos &&
 	            cursf->attrib & UNPROTECTED &&
	            cursf->len > 1))
    {
      newcursor(getcursor() + 1);
      if (cursf && getcursor() == endpos) 
	{
	  cursf = cursf->next;
	  endpos = cursf->next->pos;
	}
      if (getcursor() == pos) break;
    }
}


/* Position to start of previous word */
loc_backward_word(screen)
     unsigned char *screen;
{
  register int pos;
  register field *cursf;

  newcursor(getcursor() - 1);
  cursf = cursfield();
  pos = getcursor();
  while (!alphanum[screen[getcursor()]] || cursf &&
	 (getcursor() == cursf->pos || !(cursf->attrib & UNPROTECTED) ||
	  cursf->len <= 1))
    {
      if (cursf && getcursor() == cursf->pos) cursf = cursf->prev;
      newcursor(getcursor() - 1);
      if (getcursor() == pos) break;
    }
  pos = getcursor();
  while (alphanum[screen[getcursor()]] &&
	 (!cursf || getcursor() != cursf->pos &&
	            cursf->attrib & UNPROTECTED &&
	            cursf->len > 1))
    {
      if (cursf && getcursor() == cursf->pos) cursf = cursf->prev;
      newcursor(getcursor() - 1);
      if (getcursor() == pos) break;
    }
  newcursor(getcursor() + 1);
}


/* Delete characters until the end of the current word */
loc_kill_word(screen, scrsize)
     unsigned char *screen;
     int scrsize;
{
  register int pos, len;
  register field *cursf;

  cursf = cursfield();
  if (!cursf || getcursor() == cursf->pos || !(cursf->attrib & UNPROTECTED))
    return False;

  /* Find last non-null character in field after cursor */
  pos = cursf->pos + cursf->len - 1;
  if (pos >= scrsize) pos -= scrsize;
  for (; pos != getcursor(); pos = prevpos(pos))
    if (screen[pos]) break;
  if (pos == getcursor() && !screen[pos]) return False;

  /* Compute maximum number of characters to delete */
  len = pos - getcursor() + 1;
  if (len < 0) len += scrsize;
  
  /* Delete until we reach an alpha or trailing null */
  for (pos = 0;
       pos < len && !alphanum[screen[getcursor()]] && delete();
       pos++);
  
  /* Then delete all the alphas */
  while (alphanum[screen[getcursor()]] && delete());
  return True;
}


/* Delete characters backwards until the beginning of the preceding word */
loc_backward_kill(screen)
     unsigned char *screen;
{
  register field *cursf;
  newcursor(getcursor() - 1);
  cursf = cursfield();
  if (!cursf || getcursor() == cursf->pos || !(cursf->attrib & UNPROTECTED))
    {
      newcursor(getcursor() + 1);
      return False;
    }

  /* Delete backward until we find an alpha or beginning of field */
  while (getcursor() != cursf->pos && !alphanum[screen[getcursor()]])
    {
      (void) delete();
      newcursor(getcursor() - 1);
    }      
  if (getcursor() == cursf->pos)
    {
      newcursor(getcursor() + 1);
      return True;
    }
  
  /* Delete backward until a non-alpha is found */
  while (getcursor() != cursf->pos && alphanum[screen[getcursor()]])
    {
      (void) delete();
      newcursor(getcursor() - 1);
    }      

  /* Position just after the non-alpha */
  newcursor(getcursor() + 1);
  return True;
}


