/* Arch/MM1/ui.c 
    vi:ts=3 sw=3:
 */

#include <stdio.h>
#include <signal.h>
#include <sgstat.h>
#include "defs.h"
#include "extern.h"
#include "tags.h"
#include "prefs.h"

LOCAL void nonblocking_io P((void));
LOCAL void sane_tty P((void));
LOCAL void (*INIT)P((void)) = nonblocking_io;

LOCAL int show;
/* poor man's timer */
LOCAL int current_pattern;
LOCAL int count_pattern, count_song;
#define SMALL_DELAY 25

LOCAL struct sgbuf sanity;
LOCAL struct sgbuf *psanity = 0;

LOCAL int is_fg;

/* signal handler */

LOCAL void goodbye(sig)
int sig;
{
   static char buffer[25];

   sprintf(buffer, "Signal %d", sig);
   end_all(buffer);
}

LOCAL void abort_this(sig)
int sig;
{
   end_all("Abort");
}


int run_in_fg()
{
   int val;

   if (!isatty(fileno(stdin)) || !isatty(fileno(stdout)))
      return FALSE;

   return TRUE;
}

LOCAL void switch_mode()
{
   struct sgbuf zap;

   signal(SIGINT, goodbye);
   signal(SIGQUIT, goodbye);
   signal(SIGUSR1, abort_this);

   if (run_in_fg()) {
      _gs_opt(fileno(stdin), &zap);

      zap.sg_pause = 0;    /* no pause at end of page */
      zap.sg_backsp = 0;     /* nondestructive backspace */
      zap.sg_delete = 0; /* no delete sequence */
      zap.sg_echo = 0; /* don't echo chars */
      zap.sg_dlnch = 0xff; /* ^X delete line character */
      zap.sg_rlnch = 0xff; /* ^D reprint line character */
      zap.sg_dulnch = 0xff; /* ^A duplicate line character */
      zap.sg_psch = 0xff; /* ^W pause character */
      zap.sg_eofch = 0xff; /* escape key in OS-9 */
      zap.sg_kbich = 0xff; /* ^C interrupt character */
      zap.sg_kbach = 0xff; /* ^E abort character */
      /* Note ^S and ^Q are disabled! */
      zap.sg_xon = 0xff;   /* ^Q XON */
      zap.sg_xoff = 0xff;  /* ^S XOFF */

      _ss_opt(fileno(stdin), &zap);

      is_fg = TRUE;
   } else
      is_fg = FALSE;
}

/* nonblocking_io():
 * try to setup the keyboard to non blocking io
 */
LOCAL void nonblocking_io()
{
   show = get_pref_scalar(PREF_SHOW);

   if (!psanity) {
      psanity = &sanity;
      _gs_opt(fileno(stdin), psanity);
   }
   switch_mode();
   at_end(sane_tty);
}


/* sane_tty():
 * restores everything to a sane state before returning to shell */
LOCAL void sane_tty()
{
   _ss_opt(fileno(stdin), psanity);
}

LOCAL int may_getchar()
{
   char buffer;

   INIT_ONCE;

   if (run_in_fg() && !is_fg)
      switch_mode();
   if (run_in_fg() && (_gs_rdy(fileno(stdin)) > 0) ) {
      read(fileno(stdin), &buffer, 1);
      return buffer;
   }
   return EOF;
}

LOCAL struct tag result[2];

struct tag *get_ui()
{
   result[0].type = TAG_END;
   result[1].type = TAG_END;
   count_pattern++;
   count_song++;
   switch(may_getchar()) {
   case 'n':
      result[0].type = UI_NEXT_SONG;
      break;
   case 'p':
      if (count_song > SMALL_DELAY)
         result[0].type = UI_RESTART;
      else
         result[0].type = UI_PREVIOUS_SONG;
      count_song = 0;
      break;
   case 'x':
   case 'e':
   case 'q':
      result[0].type = UI_QUIT;
      break;
   case 's':
      result[0].type = UI_SET_BPM;
      result[0].data.scalar = 50;
      break;
   case 'S':
      result[0].type = UI_SET_BPM;
      result[0].data.scalar = 60;
      break;
   case '>':
      result[0].type = UI_JUMP_TO_PATTERN;
      result[0].data.scalar = current_pattern + 1;
      break;
   case '<':
      result[0].type = UI_JUMP_TO_PATTERN;
      result[0].data.scalar = current_pattern;
      if (count_pattern < SMALL_DELAY)
         result[0].data.scalar--;
      break;
   case '?':
      show = !show;
      set_pref_scalar(PREF_SHOW, show);
      if (show)
         putchar('\n');
      break;
   default:
      break;
   }
   return result;
}

void notice(s)
char *s;
{
   fprintf(stderr, "%s\n", s);
}

void status(s)
char *s;
{
   if (run_in_fg()) {
      if (s)
         puts(s);
      else
         putchar('\n');
   }
}

LOCAL char title[25];

void song_title(s)
char *s;
{
   strncpy(title, s, 25);
   if (run_in_fg() && !show)
      puts(title);
   count_song = 0;
}

LOCAL char scroll_buffer[80];

GENERIC begin_info(title)
char *title;
{
   if (run_in_fg())
      return scroll_buffer;
   else
      return 0;
}

void infos(handle, s)
GENERIC handle;
char *s;
{
   if (handle)
      printf(s);
}

void info(handle, line)
GENERIC handle;
char *line;
{
   if (handle)
      puts(line);
}

void end_info(handle)
GENERIC handle;
{
   if (handle)
      fflush(stdout);
}

LOCAL char *last_result = 0;

char *new_scroll(void)
{
   if (run_in_fg()) {
      last_result = scroll_buffer;
      strcpy(scroll_buffer, "             |             |             |             ");
   }
   else
      last_result = 0;
   return last_result;
}

void scroll()
{
   if (run_in_fg() && last_result) {
      puts(scroll_buffer);
      fflush(stdout);
   }
}

void display_pattern(current, total, real)
int current, total, real;
   {
   if (run_in_fg())
      {
      if (show)
         printf("\n%3d/%3d[%3d] %s\n", current, total, real, title);
      else
         printf("%3d/%3d\b\b\b\b\b\b\b", current, total);
      fflush(stdout); 
      }
   current_pattern = current;
   count_pattern = 0;
   }

