#include "LYCurses.h"
#include "HTUtils.h"
#include "LYUtils.h"
#include "LYStrings.h"
#include "LYGlobalDefs.h"

#include <ctype.h>

/*
 * LYstrncpy() terminates strings with a null byte.
 * Writes a null byte into the n+1 byte of dst.
 */
PUBLIC char * LYstrncpy ARGS3(char *,dst, char *,src, int,n)
{
    char *val;

    val = strncpy(dst, src, n);
    *(dst+n) = '\0';
    return val;
}

#ifdef VMS
#define GetChar() ttgetc()
#else
#define GetChar() getchar()  /* used to be "getc(stdin)" and "getch()" */
#endif VMS


/*
 * LYgetch() translates some escape sequences and may fake noecho
 */
PUBLIC int LYgetch ()
{
    int a, b, c;

    c = GetChar();

    if (c == 27) {	/* handle escape sequence */
	b = GetChar();

	if (b == '[' || b == 'O') {
	    a = GetChar();
	}

	else
	    a = b;

	switch (a) {
	case 'A': c = UPARROW; break;
	case 'x': c = UPARROW; break;  /* keypad up on pc ncsa telnet */
	case 'B': c = DNARROW; break;
	case 'r': c = DNARROW; break; /* keypad down on pc ncsa telnet */
	case 'C': c = RTARROW; break;
	case 'v': c = RTARROW; break; /* keypad right on pc ncsa telnet */
	case 'D': c = LTARROW; break;
	case 't': c = LTARROW; break; /* keypad left on pc ncsa telnet */
	case 'y': c = PGUP; break;  /* keypad on pc ncsa telnet */
	case 's': c = PGDOWN; break;  /* keypad on pc ncsa telnet */
	case 'w': c = HOME; break;  /* keypad on pc ncsa telnet */
	case 'q': c = END; break;  /* keypad on pc ncsa telnet */
	case 'm': c = '-'; break;  /* keypad on pc ncsa telnet */
	case 'l': c = '+'; break;  /* keypad on pc ncsa telnet */
	case 'M': c = '\n'; break; /* kepad enter on pc ncsa telnet */
	case 'P': c = F1; break;
	case 'u': c = F1; break;  /* macintosh help button */
	case '5':			/* vt 300 prev. screen */
	    if (b == '[' && GetChar() == '~')
		c = '-';
	    break;
	case '6':			/* vt 300 next screen */
	    if (b == '[' && GetChar() == '~')
		c = '+';
	    break;
	}
    }
    return(c);
}

/*
 * display the current value of the string and allow the user
 * to edit it.
 */

#ifdef getyx
#define GetYX(y,x)   getyx(stdscr,y,x)
#else
#define GetYX(y,x)   y = stdscr->_cury, x = stdscr->_curx
#endif

PUBLIC int LYgetstr ARGS2(char *,inputline, int,hidden)
{
     int pointer = 0;
     int tmp_pointer;
     int ch;
     int startcol, startline;
     int cur_col;
     BOOLEAN line_extended=FALSE;  /* TRUE if the line was moved to accomadate
                                    * more text entry
                                    */

     /* get the initial position of the curser */
     GetYX(startline, startcol);

     /*** Check to see if there's something in the inputline already ***/

     if(strlen(inputline)+startcol+5 > COLS-1) {
        pointer = (strlen(inputline) - ((COLS-1) - startcol)) + 10;
        line_extended = TRUE;
     }

     cur_col = startcol;
     while (inputline[pointer] != '\0') {
	  if(!hidden)
              addch(inputline[pointer]);
	  else
	      addch('*');
          pointer ++;
          cur_col++;
     }
     refresh();

     for (;;) {
          ch = LYgetch();

          switch (ch) {

#ifdef AIX
          case '\227':
#endif
          case '\n':
          case '\r':
          case '\t':
          case DNARROW:
          case UPARROW:
               inputline[pointer] = '\0';
               return(ch);
               break;

          /* Control-G aborts */
          case 7:
               inputline[0] = '\0';
               return(-1);

                /* break */  /* implicit break */

          /* erase all the junk on the line and start fresh */
          case 21 :
                move(startline, startcol);
                clrtoeol();
                pointer = 0;  /* clear inputline */
                cur_col = startcol;
                line_extended = FALSE;
                refresh();
                break;

          /**  Backspace and delete **/

          case '\010':
          case '\177':
          case LTARROW:
               if (pointer > 0) {
                    addch('\010');
                    addch(' ');
                    addch('\010');

                    pointer--;
                    cur_col--;

                    if(line_extended && cur_col+15 < COLS-1) {
                        if(pointer + startcol+5 > COLS-1) {
                            tmp_pointer = (pointer - ((COLS-1) - startcol)) + 5;
                        } else {
                            tmp_pointer = 0;
                            line_extended = FALSE;
                        }

                        move(startline, startcol);
                        clrtoeol();

                        cur_col = startcol;

                        while (tmp_pointer != pointer) {
	  			if(!hidden)
              			    addch(inputline[tmp_pointer]);
	  			else
	      			    addch('*');
                                tmp_pointer ++;
                                cur_col++;
                        }

                    }
                    refresh();

               } else if(ch == LTARROW) {
                   inputline[0] = '\0';
                   return(ch);
               }
               break;


          default:
               if (printable(ch)) {
                    inputline[pointer++]= ch;
                    cur_col++;
		    if(!hidden)
                        addch(ch);
		    else
                        addch('*');

                    if(cur_col+2 > COLS-1) {
                        tmp_pointer = (pointer - ((COLS-1) - startcol)) + 10;
                        line_extended = TRUE;

                        move(startline, startcol);
                        clrtoeol();

                        cur_col = startcol;

                        while (tmp_pointer != pointer) {
			 	if(!hidden)
                                    addch(inputline[tmp_pointer]);
                                else
                                    addch('*');

                                tmp_pointer ++;
                                cur_col++;
                        }

                    }
                    refresh();
               }
               /* else
                  return(ch); */
                /* just ignore unprintable charactors */
          }
     }

}

/*
 * LYstrstr will find the first occurence of the string pointed to by tarptr
 * in the string pointed to by chptr.  
 * It is a case insensitive search.
 */
PUBLIC char * LYstrstr ARGS2(char *,chptr, char *,tarptr)
{
    char *tmpchptr, *tmptarptr;
    BOOLEAN flag=FALSE;

    for(; *chptr != '\0'; chptr++) {
	if(toupper(*chptr) == toupper(*tarptr)) {	
	    /* see if they line up */ 
	    for(tmpchptr = chptr+1, tmptarptr = tarptr+1;
	         toupper(*tmpchptr) == toupper(*tmptarptr)
		 && *tmptarptr != '\0' && *tmpchptr != '\0';
	        			*tmpchptr++, *tmptarptr++)
		   ; /* null body */ 
	    if(*tmptarptr == '\0') {
		flag = TRUE;
	  	break;
	    }
	}
    } /* end for */

    if(flag)
	return(chptr);
    /*else*/
	return(NULL);
}	

/*      Allocate a new copy of a string, and returns it
*/
PUBLIC char * SNACopy ARGS3 (char **,dest, CONST char *,src, int,n)
{
  if (*dest) free(*dest);
  if (! src)
    *dest = NULL;
  else {
    *dest = (char *) calloc (n + 1,1);
    if (*dest == NULL) outofmem(__FILE__, "SNACopy");
    strncpy (*dest, src, n);
    *(*dest + n) = '\0'; /* terminate */
  }
  return *dest;
}

/*      String Allocate and Concatenate
*/
PUBLIC char * SNACat ARGS3 (char **,dest, CONST char *,src, int,n)
{
  if (src && *src) {
    if (*dest) {
      int length = strlen (*dest);
      *dest = (char *) realloc (*dest, length + n + 1);
      if (*dest == NULL) outofmem(__FILE__, "SNACat");
      strncpy (*dest + length, src, n);
      *(*dest + length + n) = '\0'; /* terminate */
    } else {
      *dest = (char *) calloc (strlen(src) + 1,1);
      if (*dest == NULL) outofmem(__FILE__, "SNACat");
      strncpy (*dest, src,n);
      *dest[n] = '\0'; /* terminate */
    }
  }
  return *dest;
}


