ftp.nice.ch/pub/next/unix/developer/slang0.99-34.s.tar.gz#/slang/src/slcurses.c

This is slcurses.c in view mode; [Download] [Up]

#include "config.h"

#include <stdio.h>
#include <signal.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.
 */


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

   SLsmg_gotorc (r, c);
   
   va_start(ap, fmt);
   (void) vsprintf(p, fmt, ap);
   va_end(ap);
   
   SLsmg_write_string (p);
   return 0;
}


int SLcurses_nil (void)
{
   return 0;
}

int SLcurses_has_colors(void)
{
   return SLtt_Use_Ansi_Colors;
}

static int Delay_Off;

int SLcurses_nodelay (SLcurses_Window_Type *w, int onoff)
{
   Delay_Off = onoff;
   return 0;
}

int SLcurses_getch (void)
{
   SLsmg_refresh ();
   if ((Delay_Off == 0) ||
       SLang_input_pending (0))
     return SLang_getkey ();
   
   return 0xFFFF;
}

/* 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


 
static int TTY_State;
static int init_tty (int suspend_ok)
{
   SLang_init_tty (-1, 0, 0);
   if (suspend_ok) SLtty_set_suspend_state (1);
   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)
{
   SLsmg_suspend_smg ();
   
   if (TTY_State)
     SLang_reset_tty ();
   
   kill(getpid(),SIGSTOP);

   SLsmg_resume_smg ();
   
   if (TTY_State == 1)
     SLcurses_raw ();
   else if (TTY_State == 2)
     SLcurses_cbreak ();
   
   signal (SIGTSTP, sigtstp_handler);
}
#endif


int SLcurses_initscr (void)
{
   SLsmg_Newline_Moves = -1;
   SLtt_get_terminfo ();
   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);
   
   return 0;
}


int SLcurses_addch (SLtt_Char_Type attr)
{
   unsigned int obj;
   unsigned short ch;
   
   if (attr == (attr & 0xFF))
     {
	SLsmg_write_char (attr & 0xFF);
	return 0;
     }
   
   obj = map_attr_to_object (attr);
   
   ch = (attr & 0xFF) | (obj << 8);
   
   SLsmg_write_color_chars (&ch, 1);
   return 0;
}

int SLcurses_mvaddch (int r, int c, SLtt_Char_Type attr)
{
   SLsmg_gotorc (r, c);
   return SLcurses_addch (attr);
}

static SLtt_Char_Type Current_Attr;

int SLcurses_attrset (SLtt_Char_Type ch)
{
   unsigned int obj;
   
   obj = map_attr_to_object (ch);
   SLsmg_set_color (obj);
   Current_Attr = ch;
   return 0;
}

int SLcurses_attroff (SLtt_Char_Type ch)
{
   if (SLtt_Use_Ansi_Colors)
     return SLcurses_attrset (0);
   
   Current_Attr &= ~ch;
   return SLcurses_attrset (Current_Attr);
}

int SLcurses_attron (SLtt_Char_Type ch)
{
   if (SLtt_Use_Ansi_Colors)
     return SLcurses_attrset (ch);
   
   Current_Attr |= ch;
   return SLcurses_attrset (Current_Attr);
}



SLcurses_Window_Type *SLcurses_newwin (unsigned int nrows, unsigned int ncols, 
				       unsigned int r, unsigned int c)
{
   SLcurses_Window_Type *win;
   unsigned short *b, *bmax;
   unsigned int len;
   
   if (NULL == (win = (SLcurses_Window_Type *) SLMALLOC (sizeof (SLcurses_Window_Type))))
     return NULL;
   
   SLMEMSET ((char *) win, 0, sizeof (SLcurses_Window_Type));
   
   len = nrows * ncols;
   if (NULL == (b = (unsigned short *) SLMALLOC (len * sizeof (unsigned short))))
     {
	SLFREE (win);
	return NULL;
     }
   win->b = win->buf = b;
   win->bufmax = bmax = b + len;
   
   while (b < bmax) *b++ = ' ';
	
   win->row = r;
   win->col = c;
   win->nrows = nrows;
   win->ncols = ncols;
   win->crow = 0;
   win->ccol = 0;
   win->color = 0;
   
   return win;
}


int SLcurses_wmove (SLcurses_Window_Type *win, unsigned int r, unsigned int c)
{
   if (win == NULL) return -1;
   win->crow = r;
   win->ccol = c;
   win->b = win->buf + (r * win->ncols + c);
   return 0;
}

int SLcurses_waddch (SLcurses_Window_Type *win, char ch)
{
   unsigned short *b;
   
   if (win == NULL) return -1;
   
   b = win->b;
   if (b < win->bufmax)
     {
	*b++ = ch | win->color;
	win->b = b;
	win->ccol++;
	
	if (win->ccol >= win->ncols)
	  {
	     win->ccol = 0;
	     win->crow++;
	  }
     }
   return 0;
}

int SLcurses_delwin (SLcurses_Window_Type *w)
{	   
   if (w != NULL)
     {
	if (w->buf != NULL)
	  free (w->buf);
	free (w);
     }
   return 0;
}

int SLcurses_wnoutrefresh (SLcurses_Window_Type *w)
{
   unsigned short *b, *bmax;
   unsigned int len;
   unsigned int r, c;
   
   if (w == NULL) 
     {
	SLsmg_refresh ();
	return -1;
     }
   
   r = w->row;
   c = w->col;
   
   b = w->buf;
   bmax = w->bufmax;
   
   len = w->ncols;
   
   while (b < bmax)
     {
	SLsmg_gotorc (r, c);
	SLsmg_write_color_chars (b, len);
	r++;
	b += len;
     }
   SLsmg_gotorc (w->row + w->crow, w->col + w->ccol);
   return 0;
}

   
int SLcurses_wrefresh (SLcurses_Window_Type *w)
{
   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;
   
   blank = w->color | 0x20;
   bmax = w->buf + (w->crow + 1) * w->ncols;
   b = w->b;
   
   if (bmax > w->bufmax) bmax = w->bufmax;
   
   while (b < bmax) *b++ = blank;
   return 0;
}

int SLcurses_wclrtobot (SLcurses_Window_Type *w)
{
   unsigned short *b, *bmax;
   unsigned short blank;
   
   if (w == NULL) return -1;
   
   blank = w->color | 0x20;
   b = w->b;
   bmax = w->bufmax;
   
   while (b < bmax) *b++ = blank;
   return 0;
}

int SLcurses_scroll (SLcurses_Window_Type *w)
{
   if (w == NULL) return -1;
   
   memcpy ((char *) w->buf, (char *) w->buf + w->ncols,
	   sizeof (short) * (w->nrows - 1) * w->ncols);
   wmove (w, w->nrows - 1, 0);
   wclrtobot (w);
   return 0;
}

static void update_cursor_position (SLcurses_Window_Type *w)
{
   unsigned int offset;
   
   offset = w->b - w->buf;
   w->crow = offset / w->ncols;
   w->ccol = offset % w->ncols;
}

int SLcurses_waddstr (SLcurses_Window_Type *w, char *str)
{
   unsigned short *b, *bmax;
   unsigned short color;
   unsigned char ch;
   
   if (w == NULL) return -1;
   
   b = w->b;
   bmax = w->bufmax;
   color = w->color;
   
   while ((b < bmax) && ((ch = (unsigned char) *str) != 0))
     {
	if (ch == '\n')
	  {
	     update_cursor_position (w);
	     SLcurses_wclrtoeol (w);
	     SLcurses_wmove (w, w->crow, 0);
	  }
	else *b++ = color | ch;
     }
   
   update_cursor_position (w);
   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.
 */
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 */
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.