/* custom keyboard input routines using ncurses */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <curses.h>
#include <keycodes.h>

typedef unsigned char uchar;


static void do_char(WINDOW *w, int c, char *temp, int mk_upper, int *pos,
       int *len, int maxlen, int insert)
{
   int i;

   if(mk_upper)
       c = toupper(c);

   if ((c == 0) || ((*pos) == maxlen))
       return;
   if ((!(insert)) || ((*pos) == (*len))) {
       temp[(*pos)++] = (char)c;
       if ((*pos) > (*len)) (*len)++;
           waddch(w, c);
   } else {
       if((*len) == maxlen)
           return;

       for (i = (*len)++; i >= (*pos); i--)
           temp[i + 1] = temp[i];
       temp[(*pos)++] = (char)c;
       waddch(w, c);
       for (i = (*pos); i < (*len); i++)
           waddch(w, temp[i]);
       for (i = (*len); i > (*pos); i--)
           waddch(w, K_BACKSPACE);
   }
}

int edgets(WINDOW *w, char *s, int maxlen, int mk_upper)
{
   char *temp;
   int insert = 1, done = 0, pos, len, i, c;

   waddstr(w, s);

   temp = malloc(maxlen + 1);
   strcpy(temp, s);

   pos = strlen(s);
   len = strlen(s);

   while (! done) {
       c = wgetch(w);
       if(c == ERR) continue;

       switch (c) {
           case K_CTL_Y:       /* Clear whole line */
               if (len == 0)
                   break;

               for (i = pos; i < len; i++)
                   waddch(w, ' ');
               for (i = len-1; i >= 0; i--) {
                   waddch(w, K_BACKSPACE);
                   waddch(w, ' ');
                   waddch(w, K_BACKSPACE);
               }
               pos = len = 0;
               break;
           case KEY_LEFT:
               if (pos == 0)
                   break;
               pos--;
               waddch(w, K_BACKSPACE);
               break;
           case KEY_RIGHT:
               if (pos == len)
                   break;
               if (pos != maxlen) {
                   waddch(w, temp[pos]);
                   pos++;
               }
               break;
           case KEY_HOME:
               while (pos-- > 0)
                   waddch(w, K_BACKSPACE);
               pos = 0;
               break;
           case KEY_END:
               while (pos < len)
                   waddch(w, temp[pos++]);
               break;
           case KEY_IC:        /* Toggle insert mode */
               insert = (!(insert));
               break;
           case KEY_DC:        /* Delete character */
               if (pos == len)
                   break;
               for (i = pos; i < len; i++)
                   temp[i] = temp[i + 1];
               len--;
               for (i = pos; i < len; i++)
                   waddch(w, temp[i]);
               waddch(w, ' ');
               for (i = len + 1; i > pos; i--)
                   waddch(w, K_BACKSPACE);
               break;
           case KEY_BACKSPACE:
               if (pos == 0)
                   break;
               if (pos != len) {
                   for (i = pos - 1; i < len; i++)
                       temp[i] = temp[i + 1];
                   pos--;
                   len--;
                   waddch(w, K_BACKSPACE);
                   for (i = pos; i < len; i++)
                       waddch(w, temp[i]);
                   waddch(w, ' ');
                   for (i = len; i >= pos; i--)
                       waddch(w, K_BACKSPACE);
               } else {
                   waddch(w, K_BACKSPACE);
                   waddch(w, ' ');
                   waddch(w, K_BACKSPACE);
                   pos = --len;
               }
               break;
           case K_ENTER:
           case KEY_ENTER:
           case K_LINEFEED:
       /*      waddch(w, K_LINEFEED); */
               done = 1;
               break;
           case K_CTL_L:       /* Clear to right of cursor */
               for (i = pos; i < len; ++i)
                   waddch(w, ' ');
               for (i = pos; i < len; ++i)
                   waddch(w, K_BACKSPACE);
               len = pos;
               break;
           case K_CTL_F:       /* Next word  */
               do {
                   if (pos == len)
                       break;
                   if (pos != maxlen) {
                       waddch(w, temp[pos]);
                       pos++;
                   }
               } while (isspace(temp[pos]));
               do {
                   if (pos == len)
                       break;
                   if (pos != maxlen) {
                       waddch(w, temp[pos]);
                       pos++;
                   }
               } while (!isspace(temp[pos]));
               break;
           case K_CTL_B:       /* Previous word */
               do {
                   if (pos == 0)
                       break;
                   pos--;
                   waddch(w, K_BACKSPACE);
               } while (isspace(temp[pos]));
               do {
                   if (pos == 0)
                       break;
                   pos--;
                   waddch(w, K_BACKSPACE);
               } while (!isspace(temp[pos]));
               break;
           default:
               if((c < KEY_MIN) && (c >= 0x20))
                   do_char(w, c, temp, mk_upper, &pos, &len, maxlen, insert);
       }
       wrefresh(w);
   }

   temp[len] = '\0';
   strcpy(s, temp);
   free(temp);
   return len;
}

int yesno(WINDOW *w)
{
   int c;

   while (1) {
       c = toupper(wgetch(w));
       if ((c == 'Y') || (c == 'N')) break;
   }

   if (c == 'Y')
       return 1;
   else
       return 0;
}