#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<ncurses.h>
#include"fejs.h"
#include"io.h"


#define HLEN 100


char *mbox = NULL;
char mhist[HLEN][256];
int histp = -1;
int histl = 0;


void
mwrite(char *s) {
  if (! mbox) {
    mbox = malloc(1);
    mbox[0] = 0;
  }
  mbox = realloc(mbox, strlen(mbox) + strlen(s) + 2);
  
  strcat(mbox, s);
  strcat(mbox, " ");
  
  histp++;
  if (histp >= HLEN)
    histp = 0;
  if (histl < HLEN)
    histl++;
  
  strcpy(mhist[histp], s);
  
  mpaint();
}


int
mdraw(int m) {
  int mx, my, l, mm = 1;
  int c, d;
  
  getmaxyx(scr,my,mx);
  c = d = mx;
  
  if ((l = strlen(mbox)) <= (2 * mx)) {
    if (l < mx) {
      c = l;
      d = 0;
    } else {
      c = mx;
      d = l - mx;
    }
  } else
    m = 1;
  
  if (m) {
    if (c < mx - 8)
      mm = 0;
    else
      if (d > mx - 8)
	d = mx - 8;
  }
  
  {
    char *sb = malloc(c + 9),
        *ssb = malloc(d + 9),
	  *s = sb,
	 *ss = ssb,
	 *sp;
    int zz;
    
    strncpy(s, mbox, c);
    s[c] = 0;
    
    if (c < l && mbox[c - 1] != ' ') {
      int z;
      
      if ((sp = strrchr(s, ' '))) {
	*sp = 0;
	z = (int)(sp - s);
	d += c - z;
	if (d > mx - m? 8: 0)
	  d = mx - m? 8: 0;
	c = z;
	mm = 1;
      }
    }
    
    while (*s == ' ')
      s++;
    while (s[zz = (strlen(s) - 1)] == ' ')
      s[zz] = 0;
    
    strncpy(ss, mbox + c, d);
    ss[d] = 0;
    if (c + d < l && mbox[c + d - 1] != ' ') {
      int z;
      
      if ((sp = strrchr(ss, ' '))) {
	*sp = 0;
	z = (int)(sp - ss);
	d = z;
      }
    }
    while (*ss == ' ')
      ss++;
    while (ss[zz = (strlen(ss) - 1)] == ' ')
      ss[zz] = 0;
    
    if (m)
      strcat(mm? ss: s, " -more- ");
    
    pclear(0, 2);
    pputstr(0, 0, s, 0);
    pputstr(0, 1, ss, 0);
    refresh();
    
    free(sb);
    free(ssb);
  }
  
  return c + d;
}

int
mpaint() {
  return mdraw(0);
}

void
mflush(int fm) {
  char *m = mbox;
  int p, r;
  
  if (! mbox[0])
    return;
  
  do {
    r = strlen(mbox);
    p = mdraw(fm);
    if (fm || p < r)
      getch();
    mbox += p;
  } while (p < r);
  
  mbox = realloc(m, 1);
  mbox[0] = 0;
}

void
mhistory() {
  int i, s=0;
  
  pclear(0, 25);
  pputstr(25, 0, "Message history", C_YELLOW);
  pputstr(10, 24, "Type Z for quit  --  R for reset  --  PgUp/PgDn for scrolling", C_YELLOW);
  
  while (1) {
    pclear(2, 21);
    
    for (i = s; i < ((s + 21) > histl? histl: s + 21); i++)
      pputstr(0, i - s + 2, mhist[histl < HLEN? i: (histp + i >= HLEN? histp + i - HLEN: histp + i)], 0);
    
    refresh();
    i = toupper(getch());
    
    switch (i) {
      case KEY_PPAGE: s -= 21;
		      if (s < 0)
			s = 0;
		      break;
		      
      case KEY_NPAGE: if (s < histl - 21)
			s += 21;
		      break;
		      
      case 'R': histp = -1;
		histl = 0;
		break;
		
      case 'Z': pclear(0, 25);
		return;
    }
  }
}

int
take_dir(char *pre, int *dx, int *dy, int td) {
  char q[256];
  
  mflush(1);
  
  strcpy(q, pre);
  strcat(q, " (choose a direction, abadon with q)? ");
  
  if (td) {
    char tab[][3] = {"789", "456", "123"};
    char ins[256];
    
    sprintf(ins, "[%c]", tab[*dy + 1][*dx + 1]);
    strcat(q, ins);
  }
  
  pputstr(0, 0, q, 0);
  
  while (1)
    switch (getch()) {
      case '4':
      case KEY_LEFT : *dx=-1; *dy=0; pclear(0,1); return 1;
      case '6':
      case KEY_RIGHT: *dx=1; *dy=0; pclear(0,1); return 1;
      case '8':
      case KEY_UP   : *dx=0; *dy=-1; pclear(0,1); return 1;
      case '2':
      case KEY_DOWN : *dx=0; *dy=1; pclear(0,1); return 1;
      case '7':
      case KEY_HOME : *dx=-1; *dy=-1; pclear(0,1); return 1;
      case '1':
      case KEY_END  : *dx=-1; *dy=1; pclear(0,1); return 1;
      case '3':
      case KEY_NPAGE: *dx=1; *dy=1; pclear(0,1); return 1;
      case '9':
      case KEY_PPAGE: *dx=1; *dy=-1; pclear(0,1); return 1;
      case '5':
      case KEY_B2   : *dx=0; *dy=0; pclear(0,1); return 1;
      case '\033':
      case 'q'      : pclear(0,1); return 0;
      case KEY_ENTER:
      case '\r'     :
      case '\n'     : if (td) { pclear(0,1); return 1; }
    }
}

int
take_place(char *pre, int *dx, int *dy) {
  char q[256];
   
  mflush(1);
  
  strcpy(q, pre);
  strcat(q, " (choose a place, abadon with q)? ");
  
  pputstr(0, 0, q, 0);
  
  while (1) {
    pmove(*dx + sx, *dy + sy);
    refresh();
    
    switch (getch()) {
      case '4':
      case KEY_LEFT : if (*dx>0) (*dx)--; break;
      case '6':
      case KEY_RIGHT: if (*dx<80) (*dx)++; break;
      case '8':
      case KEY_UP   : if (*dy>0) (*dy)--; break;
      case '2':
      case KEY_DOWN : if (*dy<20) (*dy)++; break;
      case '7':
      case KEY_HOME : if (*dx>0 && *dy>0) { (*dx)--; (*dy)--; } break;
      case '1':
      case KEY_END  : if (*dx>0 && *dy<20) { (*dx)--; (*dy)++; } break;
      case '3':
      case KEY_NPAGE: if (*dx<80 && *dy<20) { (*dx)++; (*dy)++; } break;
      case '9':
      case KEY_PPAGE: if (*dx<80 && *dy>0) { (*dx)++; (*dy)--; } break;
      case '\033':
      case 'q'      : pclear(0,1); return 0;
      case KEY_ENTER:
      case ' '      :
      case '\r'     :
      case '\n'     : pclear(0,1); return 1;
    }
  }
}

char *
aprintf(char *f, ...) {
  static char buf[10240];
  va_list vl;

  va_start(vl, f);
  vsprintf(buf, f, vl);
  va_end(vl);

  return buf;
}
