/*
 *
 *  ALL03
 *
 *  26.07.2002
 *
 *  by Fabio Sturman
 *
 *  fabio.sturman@tiscali.it
 *
 *  keys.c
 *
 *  keyboard-input module
 *
 */

/* Copyright (c) 2002 Fabio Sturman (fabio.sturman@tiscali.it)
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <string.h>
#include <conio.h>
#include "../include/keys.h"

/*
 *  clear_screen
 *
 *  clear screen
 */
void clear_screen(void)
{
  /* ansi */
  printf("\033[2J");
}

/*
 *  keyget
 *
 *  vedi keys.h
 */
int key_get(void)
{
  /* ANSI */
  int i;
  
  i=getch();
  if(i==0)
  {
    i=getch();
    return(i+256);
  }
  else return (i);
}

/*
 *  waitesc
 *
 *
 */
void wait_esc(void)
{
  while (key_get()!=K_ESC) ;
}

/*
 *  waitenter
 *
 *
 */
void wait_enter(void)        
{
  while (key_get()!=K_CR) ;
}

/*
 *  set_xy_pos
 *
 *
 */
void set_xy_pos(int xcu, int ycu)
{
  /* ansi */
  printf("\033[%d;%dH", ycu, xcu);
}


struct inss {
  int x1, y1, ml, mw;
  int x, l, b;            // x corrente l(en) corrente b(ase) corrente
  int key;                // tasto premuto
  char *s;                // stringa da editare
};

#define AC_LA           1
#define AC_RA           2
#define AC_HOME         3
#define AC_END          4
#define AC_DEL          5
#define AC_BS           6
#define AC_ENTER        7
#define AC_ABORT        8
#define AC_FIX          9

/*
 *  in_disp
 *
 *  print string and set cursor
 *
 */
void in_disp(struct inss *is)
{
   int i;
   char ss[80];

   for(i=0;i<is->mw;i++)
     if ((i+is->b)<is->l) *(ss+i)=*(is->s+is->b+i);
     else *(ss+i)=' ';
   *(ss+is->mw)=0;
   set_xy_pos(is->x1,is->y1);
   printf("%s",ss);
   set_xy_pos(is->x1+is->x, is->y1);
#ifdef WATCOM
   flushall();
#endif
}

/*
 *  reads keyboard and transform
 *  key in action (for use with mouse)
 */
int in_gac(struct inss *is)
{
  int a, k;

  in_disp(is);
  k=key_get();
  is->key=k;
  switch(k)
  {
    case K_LA: a=AC_LA; break;
    case K_RA: a=AC_RA; break;
    case K_HOME: a=AC_HOME; break;
    case K_END: a=AC_END; break;
    case K_BS: a=AC_BS; break;
    case K_DELETE: a=AC_DEL; break;
    case K_CR: a=AC_ENTER; break;
    case K_ESC: a=AC_ABORT; break;
    default:
      if((k>=32)&&(k<=126)) a=k;
      else a=-1;
    break;
  }
  return(a);
}

/*
 *  cursor left
 */
void in_la(struct inss *is)
{
  if(is->x>0) (is->x)--;
  else
  {
    if(is->b>0) (is->b)--;
  }
}

/*
 *  cursor right
 */
void in_ra(struct inss *is)
{
  if((is->x+is->b)<is->l)
  {
    if(is->x<(is->mw-1)) (is->x)++;
    else (is->b)++;
  }
}

/*
 *  home
 */
void in_home(struct inss *is)
{
  is->x=0;
  is->b=0;
}

/*
 *  end
 */
void in_end(struct inss *is)
{
  int t;

  is->b=0;
  t=is->l;
  while((t-is->mw)>0)
  {
    t-=is->mw;
    is->b+=is->mw;
  }
  is->x=t;
}

/*
 *  delete
 */
void in_del(struct inss *is)
{
  int i;

  if((is->x+is->b)<is->l)
  {
    for(i=is->x+is->b;i<is->l;i++) *(is->s+i)=*(is->s+i+1);
    (is->l)--;
  }
}

/*
 *  backspace
 */
void in_bs(struct inss *is)
{
  int i;

  if(is->x>0)
  {
    for(i=is->x+is->b;i<=is->l;i++) *(is->s+i-1)=*(is->s+i);
    (is->l)--;
    (is->x)--;
  }
}

/*
 *  insert char
 */
void in_char(struct inss *is)
{
  int i;

  if((is->l)<(is->ml-1))
  {
    if((is->x+is->b)!=(is->l))
      for(i=is->l;i>=is->x;i--) *(is->s+is->b+i+1)=*(is->s+is->b+i);
    *(is->s+is->x+is->b)=is->key;
    (is->x)++;
    if((is->x)>=(is->mw))
    {
      (is->x)--;
      (is->b)++;
    }
    (is->l)++;
    *(is->s+is->l)=0;
  }
}

/*
 *  inputstr
 *
 *            -
 *            ^
 *
 *            y1
 *
 *            v
 *  |<  x1   ><title><string to edit>
 
 *
 *  x1= x title (0-79)
 *  y1= y title (0-24)
 *  title= title
 *  st= string to edit
 *  ml= max len string st
 *  mw= max len edit window
 *  cursor= cursor at exit 0=off  1=on
 *
 *  returns K_ESC or K_ENTER
 *  if K_ESC st not changed
 */
int inputstr(int x1, int y1, char *title, char *st, int ml, int mw)
{
  struct inss is;
  char tst[80];
  int i, j, ac, rc;

  strcpy(tst,st);
  set_xy_pos(x1, y1);
  
  printf("%s",title);
  
  i=strlen(title);
  j=strlen(st);

  is.s=tst;
  is.x1=x1+i;
  is.y1=y1;
  is.ml=ml;
  is.mw=mw;
  is.l=j;
  in_end(&is);
  do
  {
    ac=in_gac(&is);
    rc=0;
    switch(ac)
    {
      case AC_LA: in_la(&is); break;
      case AC_RA: in_ra(&is); break;
      case AC_DEL: in_del(&is); break;
      case AC_BS:  in_bs(&is); break;
      case AC_HOME: in_home(&is); break;
      case AC_END: in_end(&is); break;
      case AC_ENTER:
         *(tst+is.l)=0;
         strcpy(st,tst);
         rc=K_CR;
      break;
      case AC_ABORT:
        rc=K_ESC;
      break;
      default:
        if((ac>=32) && (ac<=126)) in_char(&is);
      break;
    }
  }
  while((ac!=AC_ENTER)&&(ac!=AC_ABORT));

  return(rc);
}


