#include "config.h"

#include <stdio.h>
#include <signal.h>

#include <errno.h>

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include "slang.h"
#include "_slang.h"
#include "slcurses.h"

/* This file is meant to implement a primitive curses implementation in
 * terms of SLsmg calls.  The fact is that the interfaces are sufficiently 
 * different that a 100% emulation is not possible.
 */

SLcurses_Window_Type *SLcurses_Stdscr;
int SLcurses_Esc_Delay = 150;	       /* 0.15 seconds */
SLtt_Char_Type SLcurses_Acs_Map [128];
int SLcurses_Is_Endwin = 1;


static void blank_line (unsigned short *b, unsigned int len, unsigned short color)
{
   unsigned short *bmax;
   
   bmax = b + len;
   color = (color << 8) | 32;
   
   while (b < bmax) *b++ = color;
}

int SLcurses_mvprintw (int r, int c, char *fmt, ...)
{
   char p[1000];
   va_list ap;

   SLcurses_wmove (SLcurses_Stdscr, r, c);
   
   va_start(ap, fmt);
   (void) vsprintf(p, fmt, ap);
   va_end(ap);
   
   SLcurses_waddnstr (SLcurses_Stdscr, p, -1);
   return 0;
}

int SLcurses_mvwprintw (SLcurses_Window_Type *w, int r, int c, char *fmt, ...)
{
   char p[1000];
   va_list ap;

   SLcurses_wmove (w, r, c);
   
   va_start(ap, fmt);
   (void) vsprintf(p, fmt, ap);
   va_end(ap);
   
   SLcurses_waddnstr (w, p, -1);
   return 0;
}

int SLcurses_nil (void)
{
   return 0;
}

int SLcurses_has_colors(void)
{
   return SLtt_Use_Ansi_Colors;
}

int SLcurses_nodelay (SLcurses_Window_Type *w, int onoff)
{
   w->delay_off = (onoff ? 0 : -1);
   return 0;
}

int SLcurses_wgetch (SLcurses_Window_Type *w)
{
   if (w == NULL)
     return ERR;
   
   SLcurses_wrefresh (w);

   if ((w->delay_off == -1) ||
       SLang_input_pending (w->delay_off))
     {
	if (w->use_keypad)
	  {
	     int ch = SLang_getkey ();
	     if (ch == '\033')
	       {
		  if (0 == SLang_input_pending (ESCDELAY / 100))
		    return ch;
	       }
	     else if (ch == 0xFFFF) return ERR;
	     SLang_ungetkey (ch);
	     return SLkp_getkey ();
	  }
	return SLang_getkey ();
     }
   
   return ERR;
}

int SLcurses_getch (void)
{
   return SLcurses_wgetch (SLcurses_Stdscr);
}

/* This is a super hack.  That fact is that SLsmg and curses 
 * are incompatible.
 */
static unsigned char Color_Objects[256];

static unsigned int map_attr_to_object (SLtt_Char_Type attr)
{
   unsigned int obj;
   SLtt_Char_Type at;
   
   obj = (attr >> 8) & 0xFF;
   
   if (SLtt_Use_Ansi_Colors)
     {
	if (Color_Objects[obj] != 0) return obj;
	
	at = SLtt_get_color_object (obj & 0xF);
	
	if (attr & A_BOLD) at |= SLTT_BOLD_MASK;
	if (attr & A_UNDERLINE) at |= SLTT_ULINE_MASK;
	if (attr & A_REVERSE) at |= SLTT_REV_MASK;
	
	SLtt_set_color_object (obj, at);

	Color_Objects[obj] = 1;
     }
   else obj = obj & 0xF0;
   
   return obj;
   
}

int SLcurses_start_color (void)
{
   int f, b;
   int obj;
   
   if (SLtt_Use_Ansi_Colors == 0) return -1;
   
   obj = 0;
   for (f = 0; f < 8; f++)
     {
	for (b = 0; b < 8; b++)
	  {
	     obj++;
	     SLtt_set_color_fgbg (obj, f, b);
	  }
     }
   return 0;
}

#ifdef SIGINT
static void sigint_handler (int sig)
{
   SLang_reset_tty ();
   SLsmg_reset_smg ();
   exit (sig);
}
#endif


 
/* Values are assumed to be 0, 1, 2.  This fact is exploited */
static int TTY_State;

static int init_tty (int suspend_ok)
{
   if (-1 == SLang_init_tty (-1, 1, 0))
     return -1;

#ifdef REAL_UNIX_SYSTEM
   if (suspend_ok) SLtty_set_suspend_state (1);
#endif
   return 0;
}

int SLcurses_raw (void)
{
   TTY_State = 1;
   return init_tty (0);
}

int SLcurses_cbreak (void)
{
   TTY_State = 2;
   return init_tty (1);
}


#if defined(SIGTSTP) && defined(SIGSTOP)
static void sigtstp_handler (int sig)
{
   sig = errno;
   
   SLsmg_suspend_smg ();
   
   if (TTY_State)
     SLang_reset_tty ();
   
   kill(getpid(),SIGSTOP);

   SLsmg_resume_smg ();
   
   if (TTY_State) init_tty (TTY_State - 1);
   
   signal (SIGTSTP, sigtstp_handler);
   errno = sig;
}
#endif


SLcurses_Window_Type *SLcurses_initscr (void)
{
   SLcurses_Is_Endwin = 0;
   SLsmg_Newline_Moves = -1;
   SLtt_get_terminfo ();
   
   if ((-1 == SLkp_init ())
       || (-1 == SLcurses_cbreak ()))
     {
	SLang_doerror (NULL);
	return NULL;
     }
   
   SLcurses_Stdscr = SLcurses_newwin (0, 0, 0, 0);
   if (NULL == SLcurses_Stdscr)
     return NULL;

   SLsmg_init_smg ();

#ifdef SIGINT
   signal (SIGINT, sigint_handler);
#endif
   
#if defined(SIGTSTP) && defined(SIGSTOP)
   signal (SIGTSTP, sigtstp_handler);
#endif
   
   SLtt_set_mono (A_BOLD >> 8, NULL, SLTT_BOLD_MASK);
   SLtt_set_mono (A_UNDERLINE >> 8, NULL, SLTT_ULINE_MASK);
   SLtt_set_mono (A_REVERSE >> 8, NULL, SLTT_REV_MASK);
   /* SLtt_set_mono (A_BLINK >> 8, NULL, SLTT_BLINK_MASK); */
   SLtt_set_mono ((A_BOLD|A_UNDERLINE) >> 8, NULL, SLTT_ULINE_MASK|SLTT_BOLD_MASK);
   SLtt_set_mono ((A_REVERSE|A_UNDERLINE) >> 8, NULL, SLTT_ULINE_MASK|SLTT_REV_MASK);
   
   if (SLtt_Has_Alt_Charset)
     {
       SLcurses_Acs_Map[SLSMG_ULCORN_CHAR] = SLSMG_ULCORN_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_URCORN_CHAR] = SLSMG_URCORN_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_LLCORN_CHAR] = SLSMG_LLCORN_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_LRCORN_CHAR] = SLSMG_LRCORN_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_UTEE_CHAR] = SLSMG_UTEE_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_DTEE_CHAR] = SLSMG_DTEE_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_LTEE_CHAR] = SLSMG_LTEE_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_RTEE_CHAR] = SLSMG_RTEE_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_VLINE_CHAR] = SLSMG_VLINE_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_HLINE_CHAR] = SLSMG_HLINE_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_PLUS_CHAR] = SLSMG_PLUS_CHAR | A_ALTCHARSET;
       SLcurses_Acs_Map[SLSMG_CKBRD_CHAR] = SLSMG_CKBRD_CHAR | A_ALTCHARSET;
     }
   else
     {
       /* ugly defaults to use on terminals which don't support graphics */
       SLcurses_Acs_Map[SLSMG_ULCORN_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_URCORN_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_LLCORN_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_LRCORN_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_UTEE_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_DTEE_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_LTEE_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_RTEE_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_VLINE_CHAR] = '|';
       SLcurses_Acs_Map[SLSMG_HLINE_CHAR] = '-';
       SLcurses_Acs_Map[SLSMG_PLUS_CHAR] = '+';
       SLcurses_Acs_Map[SLSMG_CKBRD_CHAR] = '#';
     }

   
   return SLcurses_Stdscr;
}

int SLcurses_wattrset (SLcurses_Window_Type *w, SLtt_Char_Type ch)
{
   unsigned int obj;
   
   obj = map_attr_to_object (ch);
   w->color = obj;
   w->attr = ch;
   return 0;
}

int SLcurses_wattroff (SLcurses_Window_Type *w, SLtt_Char_Type ch)
{
   if (SLtt_Use_Ansi_Colors)
     return SLcurses_wattrset (w, 0);
   
   w->attr &= ~ch;
   return SLcurses_wattrset (w, w->attr);
}

int SLcurses_wattron (SLcurses_Window_Type *w, SLtt_Char_Type ch)
{
   if (SLtt_Use_Ansi_Colors)
     return SLcurses_wattrset (w, ch);
   
   w->attr |= ch;
   return SLcurses_wattrset (w, w->attr);
}

int SLcurses_delwin (SLcurses_Window_Type *w)
{	   
   if (w == NULL) return 0;
   if (w->lines != NULL)
     {
	unsigned short **lines = w->lines;
	if (w->is_subwin == 0)
	  {
	     unsigned int r, rmax;
	     
	     rmax = w->nrows;
	     for (r = 0; r < rmax; r++)
	       {
		  if (lines[r] != NULL)
		    SLFREE (lines[r]);
	       }
	  }
   
	SLFREE (lines);
     }
   
   SLFREE (w);
   if (w == SLcurses_Stdscr)
     SLcurses_Stdscr = NULL;
   return 0;
}



SLcurses_Window_Type *SLcurses_newwin (unsigned int nrows, unsigned int ncols, 
				       unsigned int r, unsigned int c)
{
   SLcurses_Window_Type *win;
   unsigned short **lines;
   
   if (r >= (unsigned int) SLtt_Screen_Rows)
     return NULL;
   if (c >= (unsigned int) SLtt_Screen_Cols)
     return NULL;
   
   if (NULL == (win = (SLcurses_Window_Type *) SLMALLOC (sizeof (SLcurses_Window_Type))))
     return NULL;
   
   SLMEMSET ((char *) win, 0, sizeof (SLcurses_Window_Type));
   
   if (nrows == 0)
     nrows = (unsigned int) SLtt_Screen_Rows - r;
   if (ncols == 0)
     ncols = (unsigned int) SLtt_Screen_Cols - c;
	
   lines = (unsigned short **) SLMALLOC (nrows * sizeof (unsigned short *));
   if (lines == NULL)
     {
	SLcurses_delwin (win);
	return NULL;
     }
   
   SLMEMSET ((char *) lines, 0, nrows * sizeof (unsigned short *));
   
   win->lines = lines;
   win->scroll_max = win->nrows = nrows;
   win->ncols = ncols;
   win->_begy = r;
   win->_begx = c;
   win->_maxx = (c + ncols) - 1;
   win->_maxy = (r + nrows) - 1;
   win->modified = 1;
   win->delay_off = -1;
   
   for (r = 0; r < nrows; r++)
     {
	unsigned short *b;
	
	b = (unsigned short *) SLMALLOC (ncols * sizeof (short));
	if (b == NULL)
	  {
	     SLcurses_delwin (win);
	     return NULL;
	  }
	lines [r] = b;
	blank_line (b, ncols, 0);
     }
   
   return win;
}


int SLcurses_wmove (SLcurses_Window_Type *win, unsigned int r, unsigned int c)
{
   if (win == NULL) return -1;
   win->_cury = r;
   win->_curx = c;
   win->modified = 1;
   return 0;
}

static int do_newline (SLcurses_Window_Type *w)
{
   w->_curx = 0;
   w->_cury += 1;
   if (w->_cury >= w->scroll_max)
     {
	w->_cury = w->scroll_max - 1;
	if (w->scroll_ok)
	  SLcurses_wscrl (w, 1);
     }
   
   return 0;
}

int SLcurses_waddch (SLcurses_Window_Type *win, SLtt_Char_Type attr)
{
   unsigned short *b, ch;
   unsigned short color;
   
   if (win == NULL) return -1;

   if (win->_cury >= win->nrows)
     {
	/* Curses seems to move current postion to top of window. */
	win->_cury = win->_curx = 0;
	return -1;
     }

   win->modified = 1;
   
   ch = attr & 0xFF;
   
   if (attr == ch)
     color = win->color;
   else 
     {
	/* hack to pick up the default color for graphics chars */
	if (((attr & A_COLOR) == 0) && ((attr & A_ALTCHARSET) != 0))
	  {
	     attr |= win->color << 8;
	  }
	color = map_attr_to_object (attr);
     }

   if (ch < ' ')
     {
	if (ch == '\n')
	  {
	     SLcurses_wclrtoeol (win);
	     return do_newline (win);
	  }
	
	if (ch == '\r')
	  {
	     win->_curx = 0;
	     return 0;
	  }
	
	if (ch == '\b')
	  {
	     if (win->_curx > 0)
	       win->_curx--;
	     
	     return 0;
	  }
	
	/* HACK HACK!!!! */
	if (ch == '\t') ch = ' ';
     }
   
   if (win->_curx >= win->ncols)
     do_newline (win);
   
   b = win->lines[win->_cury] + win->_curx;
   *b = ch | (color << 8);
   win->_curx++;
	
   return 0;
}

int SLcurses_wnoutrefresh (SLcurses_Window_Type *w)
{
   unsigned int len;
   unsigned int r, c;
   unsigned int i, imax;

   if (SLcurses_Is_Endwin)
     {
	if (TTY_State) init_tty (TTY_State - 1);
       	SLsmg_resume_smg ();
	SLcurses_Is_Endwin = 0;
     }
   
   if (w == NULL) 
     {
	SLsmg_refresh ();
	return -1;
     }
   
   if (w->modified == 0)
     return 0;
   
   r = w->_begy;
   c = w->_begx;
   
   len = w->ncols;
   imax = w->nrows;
   
   for (i = 0; i < imax; i++)
     {
	SLsmg_gotorc (r, c);
	SLsmg_write_color_chars (w->lines[i], len);
	r++;
     }
   
   if (w->has_box)
     SLsmg_draw_box(w->_begy, w->_begx, w->nrows, w->ncols);
   
   SLsmg_gotorc (w->_begy + w->_cury, w->_begx + w->_curx);
   w->modified = 0;
   return 0;
}

   
int SLcurses_wrefresh (SLcurses_Window_Type *w)
{
   if (w == NULL)
     return -1;
   
   if (w->modified == 0) 
     return 0;
   
   SLcurses_wnoutrefresh (w);
   SLsmg_refresh ();
   return 0;
}

int SLcurses_wclrtoeol (SLcurses_Window_Type *w)
{
   unsigned short *b, *bmax;
   unsigned short blank;
   
   if (w == NULL) return -1;
   if (w->_cury >= w->nrows)
     return 0;
   
   w->modified = 1;
   
   blank = (w->color << 8) | 0x20;
   
   b = w->lines[w->_cury];
   bmax = b + w->ncols;
   b += w->_curx;
   
   while (b < bmax) *b++ = blank;
   return 0;
}

int SLcurses_wclrtobot (SLcurses_Window_Type *w)
{
   unsigned short *b, *bmax;
   unsigned short blank;
   unsigned int r;
   
   if (w == NULL) return -1;
   
   w->modified = 1;
   blank = (w->color << 8) | 0x20;
   SLcurses_wclrtoeol (w);
   for (r = w->_cury + 1; r < w->nrows; r++)
     {
	b = w->lines [r];
	bmax = b + w->ncols;
   
	while (b < bmax) *b++ = blank;
     }

   return 0;
}

int SLcurses_wscrl (SLcurses_Window_Type *w, int n)
{
   unsigned short **lines;
   unsigned int r, rmax, rmin, ncols;
   unsigned short color;
   
   if ((w == NULL) || (w->scroll_ok == 0))
     return -1;
   
   w->modified = 1;
#if 0
   if (w->is_subwin)
     {
	SLang_reset_tty ();
	SLsmg_reset_smg ();
	fprintf (stderr, "\rAttempt to scroll a subwindow\n");
	exit (1);
     }
#endif

   color = w->color;
   ncols = w->ncols;
   lines = w->lines;
   rmax = w->scroll_max;
   rmin = w->scroll_min;
   if (rmax > w->nrows)
     rmax = w->nrows;
   if (rmin >= rmax)
     return 0;
   
   while (n > 0)
     {
	for (r = rmin + 1; r < rmax; r++)
	  {
	     /* lines[r - 1] = lines[r]; */
	     memcpy ((char *)lines[r - 1], (char *)lines[r], 
		     sizeof (short) * ncols);
	  }
	blank_line (lines[rmax - 1], ncols, color);
	n--;
     }
   
   rmax--;
   while (n < 0)
     {	
	for (r = rmax; r > rmin; r--)
	  {
	     memcpy ((char *)lines[r], (char *)lines[r - 1],
		     sizeof (short) * ncols);
	  }
	blank_line (lines[rmin], ncols, color);
	n++;
     }
   
   /* wmove (w, w->nrows - 1, 0); */
   /* wclrtobot (w); */
   return 0;
}

/* Note: if len is < 0, entire string will be used.
 */
int SLcurses_waddnstr (SLcurses_Window_Type *w, char *str, int len)
{
   unsigned short *b;
   unsigned short color;
   unsigned char ch;
   unsigned int nrows, ncols, crow, ccol;
   
   if ((w == NULL) 
       || (str == NULL))
     return -1;
   
   w->modified = 1;
   nrows = w->nrows;
   ncols = w->ncols;
   crow = w->_cury;
   ccol = w->_curx;
   color = (w->color << 8);

   if (w->scroll_max <= nrows)
     nrows = w->scroll_max;
   
   if (crow >= nrows)
     crow = 0;			       /* wrap back to top */
	
   b = w->lines [crow] + ccol;
   
   while (len && ((ch = (unsigned char) *str++) != 0))
     {
	len--;

	if (ch == '\n')
	  {
	     w->_cury = crow;
	     w->_curx = ccol;
	     SLcurses_wclrtoeol (w);
	     do_newline (w);
	     crow = w->_cury;
	     ccol = w->_curx;
	     b = w->lines[crow];
	     continue;
	  }
	
	if (ccol >= ncols)
	  {
	     ccol = 0;
	     crow++;
	     if (crow >= nrows)
	       {
		  w->_curx = 0;
		  w->_cury = crow;
		  do_newline (w);
		  crow = w->_cury;
		  ccol = w->_curx;
	       }

	     b = w->lines [crow];
	  }

	if (ch == '\t')
	  {
	     unsigned int n = ccol;
	     n += SLsmg_Tab_Width;
	     n = SLsmg_Tab_Width - (n % SLsmg_Tab_Width);
	     if (ccol + n > ncols) n = ncols - len;
	     ccol += n;
	     while (n--)
	       *b++ = color | ' ';
	     continue;
	  }
	
	*b++ = color | ch;
	ccol++;
     }
   
   w->_curx = ccol;
   w->_cury = crow;
   
   return 0;
}

int SLcurses_wprintw (SLcurses_Window_Type *w, char *fmt, ...)
{
   char p[1000];
   va_list ap;

   va_start(ap, fmt);
   (void) vsprintf(p, fmt, ap);
   va_end(ap);
   
   SLcurses_waddnstr (w, p, -1);
   return 0;
}


/* This routine IS NOT CORRECT.  It needs to compute the proper overlap
 * and copy accordingly.  Here, I just assume windows are same size.
 */
#if 0
int SLcurses_overlay (SLcurses_Window_Type *swin, SLcurses_Window_Type *dwin)
{
   unsigned short *s, *smax, *d, *dmax;
   
   if ((swin == NULL) || (dwin == NULL))
     return -1;
   
   s = swin->buf;
   smax = swin->bufmax;
   d = dwin->buf;
   dmax = dwin->bufmax;
   
   while ((s < smax) && (d < dmax))
     {
	unsigned short ch = *s++;
	if ((ch & 0xFF) != ' ')
	  *d = ch;
	d++;
     }
   
   return -1;			       /* not implemented */
}

#endif

SLcurses_Window_Type *SLcurses_subwin (SLcurses_Window_Type *orig, 
				       unsigned int nlines, unsigned int ncols,
				       unsigned int begin_y, unsigned int begin_x)
{
   SLcurses_Window_Type *sw;
   int r, c;
   unsigned int i;
   
   if (orig == NULL)
     return NULL;
   
   sw = (SLcurses_Window_Type *) SLMALLOC (sizeof (SLcurses_Window_Type));
   if (sw == NULL)
     return NULL;
   
   SLMEMSET ((char *)sw, 0, sizeof (SLcurses_Window_Type));
   r = 1 + ((int)orig->nrows - (int)nlines) / 2;
   if (r < 0) r = 0;
   if (r + nlines > orig->nrows) nlines = orig->nrows - r;

   c = ((int)orig->ncols - (int)ncols) / 2;
   if (c < 0) c = 0;
   if (c + ncols > orig->ncols) ncols = orig->ncols - c;
   
   sw->scroll_min = 0;
   sw->scroll_max = sw->nrows = nlines;
   sw->ncols = ncols;
   sw->_begy = begin_y;
   sw->_begx = begin_x;
   sw->_maxx = (begin_x + ncols) - 1;
   sw->_maxy = (begin_y + nlines) - 1;

   sw->lines = (unsigned short **) SLMALLOC (nlines * sizeof (unsigned short *));
   if (sw->lines == NULL)
     {
	SLcurses_delwin (sw);
	return NULL;
     }
   
   for (i = 0; i < nlines; i++)
     {
	sw->lines [i] = orig->lines [r + i] + c;
     }
   
   sw->is_subwin = 1;
   return sw;
}


int SLcurses_wclear (SLcurses_Window_Type *w)
{
   unsigned int i;
   
   if (w != NULL) w->modified = 1;
   for (i=0; i < w->nrows; i++) 
     blank_line (w->lines[i], w->ncols, w->color);
   return 0;
}

int SLcurses_printw (char *fmt, ...)
{
   char p[1000];
   va_list ap;

   va_start(ap, fmt);
   (void) vsprintf(p, fmt, ap);
   va_end(ap);
   
   SLcurses_waddnstr (SLcurses_Stdscr, p, -1);
   return 0;
}

int SLcurses_wdelch (SLcurses_Window_Type *w)
{
   unsigned short *p, *p1, *pmax;

   p = w->lines[w->_cury];
   pmax = p + w->ncols;
   p += w->_curx;
   p1 = p + 1;

   while (p1 < pmax)
     {
	*p = *p1;
	p = p1;
	p1++;
     }

   if (p < pmax)
     *p = ' ' | (w->color << 8);

   w->modified = 1;
   return 0;
}

int SLcurses_winsch (SLcurses_Window_Type *w, int ch)
{
   unsigned short *p, *p1, *pmax;

   p = w->lines[w->_cury];
   pmax = p + w->ncols;
   p += w->_curx;
   p1 = pmax - 1;

   while (pmax > p)
     {
	*pmax = *p1;
	pmax = p1;
	p1--;
     }

   if (p < pmax)
     *p = (unsigned short) ch | (w->color << 8);

   w->modified = 1;
   return 0;
}

int SLcurses_endwin (void)
{
   SLcurses_Is_Endwin = 1;
   SLsmg_suspend_smg ();
   SLang_reset_tty ();
   return 0;
}

#if 0
int SLcurses_mvwscanw (SLcurses_Window_Type *w, unsigned int r, unsigned int c,
		       char *fmt, ...)
{
#if HAVE_VFSCANF
   int ret;
   va_list ap;

   SLcurses_wmove (w, r, c);
   SLcurses_wrefresh (w);
   
   va_start(ap, fmt);
   ret = vfscanf (stdin, fmt, ap);
   va_end(ap);
   return ret;
#else
   return 0;
#endif
}

int SLcurses_wscanw (SLcurses_Window_Type *w, char *fmt, ...)
{
#if HAVE_VFSCANF
  va_list ap;
   int ret;
   
   SLcurses_wrefresh (w);

   va_start(ap, fmt);
   ret = vfscanf (stdin, fmt, ap);
   va_end(ap);
   
   return ret;
#else
   return 0;
#endif
}

int SLcurses_scanw (char *fmt, ...)
{
#ifdef HAVE_VFSCANF
   va_list ap;
   int ret;
   
   SLcurses_wrefresh (SLcurses_Stdscr);

   va_start(ap, fmt);
   ret = vfscanf (stdin, fmt, ap);
   va_end(ap);
   
   return ret;
#else
   return 0;
#endif
}
#endif

int SLcurses_clearok (SLcurses_Window_Type *w, int bf)
{
   if (bf)
     {
	SLsmg_cls ();
	w->modified = 1;
     }
   return 0;
}
