/*****  ctl.c - (c) rohan drape, 2006 *****/

#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <time.h>
#include <curses.h>
#include <signal.h>

#define name_n 128
#define data_n 512

struct pt {
  int r;
  int c;
};

struct ctl {
  int nr;
  int nc;
  int n;
  double data[data_n];
  char name[data_n][name_n];
  double incr[data_n];
};

int nindex(struct ctl ct, int r, int c)
{
  return (r * ct.nc) + c;
}

struct pt loc(struct ctl c)
{
  struct pt z;
  z.r = c.n / c.nc;
  z.c = c.n % c.nc;
  return z;
}

void allincr(struct ctl *c, double z)
{
  int i;
  for(i = 0; i < data_n; i++) {
    c->incr[i] = z;
  }
}

void finish(int sig)
{
  endwin();
  exit(0);
}

void shutdown(void *PTR)
{
  exit(1);
}

void putprompt(int r, const char *prompt)
{
  move(r,0);
  addstr(prompt);
}  

void getcmd(int r, const char *prompt, char *result, int n)
{
  move(r,0);
  addstr(prompt);
  echo();
  getnstr(result, n);
  noecho();
  halfdelay(1);
  move(2,0);
  clrtoeol();
}

double getnum(int r, const char *prompt)
{
  char tmp[512];
  getcmd(r, prompt, tmp, 512);
  return strtod(tmp, NULL);
}

/* sr = status row */

int sr(struct ctl c)
{
  return (c.nr * 3) + 2;
}

/* pr = prompt row */

int pr(struct ctl c)
{
  return (c.nr * 3) + 3;
}

int main(int argc, char **argv)
{
  struct ctl c;
  int i,j,k;
  struct pt l;
  MEVENT m;
  c.nr = 8;
  c.nc = 8;
  c.n = 0;
  for(i = 0; i < data_n; i++) {
    c.data[i] = 0.0;
    c.name[i][0] = '\0';
    c.incr[i] = 0.05;
  }
  signal(SIGINT, finish);
  initscr();
  keypad(stdscr, TRUE);
  nonl();
  halfdelay(1);
  noecho();
  mousemask(ALL_MOUSE_EVENTS, NULL);
  
  while (1) {
    int ch;
    ch = getch();
    switch(ch) {
    case 'r':
      erase();
      refresh();
      break;
    case KEY_LEFT:
      if(c.n > 0) {
	c.n -= 1;
      }
      break;
    case KEY_RIGHT:
      if(c.n < (c.nr * c.nc) - 1) {
	c.n += 1;
      }
      break;
    case KEY_UP:
      l = loc(c);
      if(l.r > 0) {
	c.n = nindex(c,l.r-1,l.c);
      }
      break;
    case KEY_DOWN:
      l = loc(c);
      if(l.r < c.nr - 1) {
	c.n = nindex(c,l.r+1,l.c);
      }
      break;
    case KEY_SLEFT:
      c.data[c.n] -= c.incr[c.n];
      break;
    case KEY_SRIGHT:
      c.data[c.n] += c.incr[c.n];
      break;
    case 'i':
      c.incr[c.n] = getnum(pr(c), "Set local increment: ");
      break;
    case 'I':
      allincr(&c, getnum(pr(c), "Set global increment: "));
      break;
    case 'q':
      finish(SIGINT);
      break;
    case KEY_MOUSE:
      getmouse(&m);
      if(m.bstate && BUTTON1_PRESSED) {
	c.n = nindex(c, m.y / 3, m.x / 8);
      }
    case ERR:
      break;
    }
      
    erase();
    for(i = 0, k = 0; i < c.nr ; i++) {
      for(j = 0; j < c.nc; j++, k++) {
	char s[8];
	if(c.n == k) {
	  mvaddstr((i*3)+0, j*8, "**");
	}
	snprintf(s,8,"%f",c.data[nindex(c,i,j)]);
	mvaddstr((i*3)+1, j*8, s);
      }
    }
    refresh();
    l = loc(c);
    //printf("r=%d, c=%d, n=%d\n", l.r, l.c, c.n);
  }
  
  endwin();
  return 0;
}

