Logo Search packages:      
Sourcecode: vh version File versions  Download package

screen.c

/*****************************************************************************

NAME
   screen.c -- augmented pseudo-curses(3) screen support

SYNOPSIS
   int LINES, COLS;           -- terminal depth & width globals

   int initscr()        -- init screen, set LINES and COLS
   int endwin()               -- de-initialize screen code
   int clear()                -- clear screen
   int refresh()        -- refresh real screen from virtual screen
   int ungetch(c)       -- put c on queue to be grabbed by next getch()
   int inch()                 -- get char from current update location.
   int move(y, x)       -- move update cursor to row y colum x
   int addch(c)               -- add char c at update location
   int addstr(s)              -- write string from update location
   int attrset(a)       -- set attribute (A_NORMAL, A_REVERSE, A_BOLD)
   bool has_color()           -- do we have color?
   int napms()                -- nap for some number of milliseconds
   void beep();               -- beep the terminal bell

   int egetch()               -- get mouse event or character, no echo
   void readscr(lx,ly,rx,ry, s)     -- get content of screen line

   bool has_mouse()           -- is there a mouse?
   void mouse_init()          -- initialize mouse
   int mouse_status(py,px)    -- get mouse location and button state
   void mouse_show()          -- show mouse cursor
   void mouse_hide()          -- hide mouse cursor

DESCRIPTION
   The idea here is to present a system-independent interface that looks like
a subset of curses(3), with a minimum of hooks for mouse handling and one
concession to Borland C for optimizations's sake.

   The addch() and addstr() functions move the update cursor to the right after
writing.  The argument of addch() may have an attribute logical-or'ed in.
The inch() call returns a char with attribute or'ed in; A_CHARTEXT masks out
the character only. The following special keycap defines are used:

   KEY_HELP       -- not on PC keyboard
   KEY_REFRESH          -- not on PC keyboard
   KEY_NPAGE            -- PgDn
   KEY_PPAGE            -- PgUp
   KEY_UP         -- Up Arrow
   KEY_DOWN       -- Down Arrow
   KEY_REFERENCE  -- not on PC keyboard
   KEY_ENTER            -- Enter
   KEY_RIGHT            -- Right Arrow
   KEY_LEFT       -- Left Arrow
   KEY_FIND       -- not on PC keyboard
   KEY_SFIND            -- not on PC keyboard
   KEY_SELECT           -- not on PC keyboard
   KEY_HOME       -- Home
   KEY_BEG        -- not on PC keyboard
   KEY_END        -- End
   KEY_UNDO       -- not on PC keyboard
   KEY_PRINT            -- not on PC keyboard
   KEY_MOUSE            -- mouse event happened (not supported by curses(3))

Mouse state defines returned by mouse_status():

   LEFT_DOWN            -- left mouse button down
   LEFT_UP        -- left mouse button release
   RIGHT_DOWN           -- right mouse button down
   RIGHT_UP       -- right mouse button up

Special mouse coordinate values:

   CMDLINE        -- command line of application window
   THUMBCOL       -- thumb column of application window

BUGS
   The MS-DOS implementation doesn't do optimization for the 
scrolling case.

AUTHORS
   Package interface design and UNIX curses(3) code by Eric S. Raymond.
   MS-DOS code by Raymond D. Gardner.
   Please see the READ.ME in this directory for license terms.

******************************************************************************/
/* LINTLIBRARY */
#include <assert.h>

#include "screen.h"

#ifdef CURSES
/*******************************************************************
 *
 * Support for curses(3) under UNIX.
 *
 ******************************************************************/
#ifdef MOUSE
#include <fcntl.h>
#include <sys/mouse.h>

/*
 * We want to make the mouse relatively insensitive to small motions.
 * The code ignores all but 1 in MXSCALE horizontal motions and 1 in MYSCALE
 * vertical motions.  The factors differ as they do because most fonts have
 * a roghly 2/1 aspect ratio; thus, to get the same real rate of vertical
 * motion as horizontal, MYSCALE should be twice as large.
 */
#define MXSCALE   2
#define MYSCALE (MXSCALE * 2)

static int mousefd;     /* mouse file descriptir */
static int msy, msx;    /* current mouse coordinates */ 
static int mstat; /* current mouse status */
static bool mvis = TRUE;      /* should cursor be visible? */
static bool mcolor;     /* show mouse cursor in color? */
#endif /* MOUSE */

void mouse_init()
/* initialize the mouse */
{
#ifdef MOUSE
    /*
     * If there's an active mouse, set O_NODELAY on input so we
     * can alternate polling for keystrokes and mouse events without
     * blocking.
     */
    if ((mousefd = open("/dev/mouse", O_RDONLY)) != ERR)
      nodelay(stdscr, TRUE);
#endif /* MOUSE */
#ifdef SCROLLBAR
    COLS--;
#endif /* SCROLLBAR */
}

void mouse_color(on)
/* should the mouse cursor be in color? */
bool  on;
{
#ifdef MOUSE
    if (on && has_colors())
      init_pair(COLOR_PAIRS - 1, COLOR_BLACK, COLOR_YELLOW);
    mcolor = on;
#endif /* MOUSE */
}

void mouse_move(y, x)
/* move the mouse hotspot to a given location */
int   y, x;
{
#ifdef MOUSE
    msy = y;
    msx = x;
#endif /* MOUSE */
}

void mouse_show()
{
#ifdef MOUSE
    mvis = TRUE;
#endif /* MOUSE */
}

void mouse_hide()
{
#ifdef MOUSE
    mvis = FALSE;
#endif /* MOUSE */
}

int mouse_status(py, px)
/* get current mouse status, return coordinates */
int   *py, *px;
{
#ifdef MOUSE
    if (mousefd != ERR)
    {
#ifdef SCROLLBAR
      *px = (msx == COLS) ? THUMBCOL : msx;
#else
      *px = msx;
#endif /* SCROLLBAR */
      *py = msy;
      return(mstat);
    }
#endif /* MOUSE */
    return(*px = *py = ERR);
}

static int cgetch()
/* get single character or mouse event */
{
#ifndef MOUSE
    return(getch());
#else
#ifdef ATTMOUSE
    struct mouseinfo m;
#endif /* ATTMOUSE */
    int mchattr, oldx, oldy, oldmy, oldmx;
    int     c;

    if (mousefd == ERR)
      return(getch());

    if (mvis)
    {
      getyx(stdscr, oldy, oldx);

      move(msy, msx);
      mchattr = inch();
      move(msy, msx);
      if (mcolor)
          addch((mchattr & 0xff) | COLOR_PAIR(COLOR_PAIRS - 1));
      else
          addch(mchattr ^ A_REVERSE);
      oldmy = msy; oldmx = msx;
      refresh();
    }

    for (;;)
    {
      /* first poll for a character */
      if ((c = getch()) != ERR)
          break;

      /* then poll for a mouse event */
#ifdef ATTMOUSE
      (void) ioctl(mousefd, MOUSEIOCREAD, &m);
      if ((m.status &~ MOVEMENT) | m.xmotion | m.ymotion)
      {
          register i, newx, newy;

          newx = msx;
          if (m.xmotion < 0)
            for (i = 0; i < -(m.xmotion / MXSCALE); i++)
                if (newx <= 0)
                  break;
                else
                  newx--;
          if (m.xmotion > 0)
            for (i = 0; i < (m.xmotion / MXSCALE); i++)
#ifdef SCROLLBAR
                if (newx >= COLS)
#else
                if (newx >= COLS - 1)
#endif /* SCROLLBAR */
                  break;
                else
                  newx++;
          msx = newx;
          newy = msy;
          if (m.ymotion < 0)
            for (i = 0; i < -(m.ymotion / MYSCALE); i++)
                if (newy <= 0)
                  break;
                else
                  newy--;
          if (m.ymotion > 0)
            for (i = 0; i < (m.ymotion / MYSCALE); i++)
                if (newy >= LINES - 1)
                  break;
                else
                  newy++;
          msy = newy;

          mstat = 0;
          if (m.status & BUT1CHNG)
            if (m.status & BUT1STAT)
                mstat |= BUTTON1_PRESSED;
            else
                mstat |= BUTTON1_RELEASED;
          if (m.status & BUT3CHNG)
            if (m.status & BUT3STAT)
                mstat |= BUTTON3_PRESSED;
            else
                mstat |= BUTTON3_RELEASED;

          c = KEY_MOUSE;
          break;
      }

      /* keep polling till you get one or the other */
    }
#endif /* ATTMOUSE */

    if (mvis)
    {
      move(oldmy, oldmx);
      addch(mchattr);
      move(oldy, oldx);
    }

    return(c);
#endif /* MOUSE */
}

void readscr(lx, ly, rx, ry, outbuf)
/* get text from screen */
int   lx, ly, rx, ry;
char  *outbuf;
{
    int     x, y;

    for (x = lx; x <= rx; x++)
      for (y = ly; y <= ry; y++)
      {
          move(y, x);
          *outbuf++ = inch() & A_CHARTEXT;
      }
    *outbuf = '\0';
}

#ifndef A_COLOR
bool has_colors()
{
    return(FALSE);
}

int start_color()
{
    /* do nothing */
}
int init_pair(pn, fg, bg)
int pn, fg, bg;
{
    /* do nothing */
}

#endif /* A_COLOR */

#endif /* CURSES */

#ifdef OLDCURSES
/*******************************************************************
 *
 * Support for BSD curses, which is missing some stuff...
 *
 ******************************************************************/

int attrset(a)
/* set write attribute for subsequent operations */
chtype      a;
{
    /*
     * It would be real nice to have more attributes supported in here...
     */
    if (a | A_REVERSE)
      standout();
    else
      standend();
    return(OK);
}

void beep()
{
    (void) putchar('\007');
}

int start_color()
{
    /* do nothing */
}

/*ARGSUSED0*/
int init_pair(pn, fg, bg)
int pn, fg, bg;
{
    /* do nothing */
}

unsigned char acs_map[] =
{
   /* ACS_BSSB */ '+',
   /* ACS_SSBB */ '+',
   /* ACS_BBSS */ '+',
   /* ACS_SBBS */ '+',
   /* ACS_SBSS */ '|',
   /* ACS_SSSB */ '|',
   /* ACS_SSBS */ '-',
   /* ACS_BSSS */ '-',
   /* ACS_BSBS */ '-',
   /* ACS_SBSB */ '|',
   /* ACS_SSSS */ '+',
   /* ACS_S1 */         '~',  /* scan line 1 */
   /* ACS_S9 */         '_',  /* scan line 9 */
   /* ACS_DIAMOND */    '*',  /* diamond */
   /* ACS_CKBOARD */    '#',  /* checker board */
   /* ACS_DEGREE */     'o',  /* degree symbol */
   /* ACS_PLMINUS */    '#',  /* plus/minus */
   /* ACS_BULLET */     '*',  /* bullet */
   /* ACS_LARROW */     27,   /* arrow pointing left */
   /* ACS_RARROW */     '>',  /* arrow pointing right */
   /* ACS_DARROW */     'V',  /* arrow pointing down */
   /* ACS_UARROW */     '^',  /* arrow pointing up */
   /* ACS_BOARD */      '#',  /* board of squares */
   /* ACS_LANTERN */    '#',  /* lantern symbol */
   /* ACS_BLOCK */      '#',  /* solid square block */
};
#endif /* OLDCURSES */

#ifdef MSDOS
/*******************************************************************
 *
 * Support for Borland C under MS-DOS
 *
 ******************************************************************/
#include <dos.h>
#include <conio.h>

#define GQDEPTH         32    /* depth of character push queue */

int LINES, COLS, COLOR_PAIRS, COLORS = 8;

/* vtype values */
#define     PGA         (7)
#define     VGA         (6)
#define     MCGA        (5)
#define     EGA         (4)
#define     CGA         (3)
#define     HERC        (2)
#define     MDA         (1)
#define     NONE        (0)
#define     VUNKNOWN    (-1)

/* hascolor values: */
#define     COLOR       (2)
#define     MONO        (1)

static int hascolor;
static char screensave[MAXROWS*MAXCOLS*2];      /* save user's screen here */

int bufseg;       /* vid buffer segment addr for emulating gettext/puttext */

#ifdef __TURBOC__
bool has_snowy_CGA = FALSE;
#endif /* __TURBOC__ */

int initscr()
{
    union REGS r;
    struct SREGS s;
    int vtype, vchrome, xmode, *mode = &xmode;

    /* default assumptions */
    hascolor = 0;
    LINES = 25;
    bufseg = 0xb800;

    /* get mode and columns */
    r.h.ah = 0x0F;
    int86(0x10, &r, &r);
    *mode = r.h.al;
    COLS = r.h.ah;

    r.x.ax = 0x1200;          /* alternate function select */
    r.x.bx = 0x0010;
    int86(0x10, &r, &r);
    if (r.x.bx != 0x0010)     /* must be pga/vga/mcga/ps2/ega */
    {
      vtype = EGA;            /* provisional assumption */
      hascolor = r.h.bh ? MONO : COLOR;

      /* now try for "higher" display than EGA */

      r.x.ax = 0x1A00;  /* get display combination */
      int86(0x10, &r, &r);
      if (r.h.al == 0x1A)     /* must be pga/vga/mcga/ps2 */
      {
          switch (r.h.bl)
          {
          case 0: vtype = NONE;     break;
          case 1: vtype = MDA;      break;
          case 2: vtype = CGA;      break;
          case 4: vtype = EGA;      break;
          case 5: vtype = EGA;      break;
          case 6: vtype = PGA;      break;
          case 7: vtype = VGA;      break;
          case 8: vtype = VGA;      break;
          case 0xC:           /* fall through; analog vs. digital display */
          case 0xA: vtype = MCGA;   break;
          case 0xB: vtype = MCGA;   break;
          default:
            vtype = VUNKNOWN;
            break;
          }
      }

      /* get number of rows on screen */
      if (vtype == EGA || vtype == MCGA || vtype == VGA)
      {
          segread(&s);
          r.x.ax = 0x1130;    /* get font info */
          r.h.bh = 0;
          int86x(0x10, &r, &r, &s);
          LINES = r.h.dl + 1;
      } 
      else
          LINES = *(int far *)MK_FP(0x40, 0x84);
    }
    else
    {             /* not pga/vga/mcga/ps2/ega */
      if (*mode != 7)
          vtype = CGA;
      else
      {
          vtype = MDA;
          hascolor = MONO;
      }
    }

    bufseg = 0xb800;
    if (vtype == MDA || hascolor == MONO)
       bufseg = 0xb000;

    gettext(1, 1, COLS, LINES, screensave);     /* save user's screen */
#ifdef SCROLLBAR
    COLS--;
#endif /* SCROLLBAR */

#ifdef __TURBOC__
    {
      extern int _video[12];
      if (! has_snowy_CGA)
          _video[5] = 0;
    }
#endif
    return OK;
}

#ifdef __ZTC__
/*******************************************************************
*
* gettext()/puttext() -- simulate Borland screen i/o routines
*
*******************************************************************/

int puttext(int left, int top, int right, int bot, char *buf)
{
    int cols, row;
    char far *vid;
    char far *vidstart;
    char *lim;
    cols = right - left + 1;
    --left;
    --top;
    vidstart = vid = MK_FP(bufseg, top*160+left*2);
    for ( row = top; row < bot; ++ row )
    {
      for ( lim = buf + cols * 2; buf < lim; )
          *vid++ = *buf++;
      vid = vidstart += 160;
    }
    return 0;
}

int gettext(int left, int top, int right, int bot, char *buf)
{
    int cols, row;
    char far *vid;
    char far *vidstart;
    char *lim;

    cols = right - left + 1;
    --left;
    --top;
    vidstart = vid = MK_FP(bufseg, top*160+left*2);
    for ( row = top; row < bot; ++ row )
    {
      for ( lim = buf + cols * 2; buf < lim; )
          *buf++ = *vid++;
      vid = vidstart += 160;
    }
    return 0;
}
#endif /* __ZTC__ */


int endwin()
/* de-initialize window handling */
{
#ifdef SCROLLBAR
    COLS++;
#endif /* SCROLLBAR */
    puttext(1, 1, COLS, LINES, screensave);     /* restore user screen */
    move(LINES-1,0);
    return OK;
}

bool has_colors()
/* is color available? */
{
    return(hascolor == COLOR);
}

void readscr(int left, int top, int right, int bot, char *buf0)
/* read the text out of screen region into a buffer */
{
    char s[MAXCOLS * 2];
    register char *buf;
    register char *p;
    register int k;
    int size;

    buf = buf0;
    k = (bot-top+1)*(right-left+1);
    assert(k <= MAXCOLS);
    gettext(left+1, top+1, right+1, bot+1, s);
    p = s;
    do
    {
      *buf++ = *p;
      p += 2;
    } while ( --k );
    *buf = 0;
}

int refresh()
{
    /* do nothing; this is a write-through implementation */
    return OK;
}

/********************** mouse routines ************************/

static bool mse = FALSE;      /* nonzero iff mouse is present */

bool has_mouse()
/* is there a mouse? */
{
    return(mse);
}

void mouse_color(on)
/* show mouse cursor in color? */
bool  on;
{
    (void)on;           /* quiet the compiler warning */
    /* do nothing */
}

void mouse_init()
/* initialize the mouse */
{
    union REGS r;
    struct SREGS sregs;

    segread(&sregs);
    r.x.ax = 0x3533;
    int86x(0x21, &r, &r, &sregs); /* get mouse driver int addr */
    if (sregs.es == 0 && r.x.bx == 0) /* if addr is zero, no mouse */
      return;

    /* if addr points to IRET, no mouse */
    if (*(unsigned char far *)MK_FP(sregs.es, r.x.bx) == 0xcf)
      return;

    r.x.ax = 0;
    int86(0x33, &r, &r);      /* try to init mouse driver */
    mse = r.x.ax;       /* set mouse status global var */
      mouse_show();
}

void mouse_show()
/* turn on the mouse cursor */
{
    union REGS r;

    if (mse)
    {
      r.x.ax = 1;
      int86(0x33, &r, &r);
    }
}

void mouse_hide()
/* turn off mouse cursor */
{
    union REGS r;

    if (mse)
    {
      r.x.ax = 2;
      int86(0x33, &r, &r);
    }
}

void mouse_move(y, x)
/* set mouse cursor position (zero-origin coordinates) */
int   y, x;
{
    union REGS r;

    if (mse)
    {
      r.x.ax = 4;
      r.x.cx = x << 3;
      r.x.dx = y << 3;
      int86(0x33, &r, &r);
    }
}

/******************* screen/cursor routines ****************/

static int cury, curx;        /* virtual update cursor */
static chtype cattr;          /* current attribute */
static chtype pairs[64];      /* color pair array */

int move(row, col)
/* cursor positioning */
int row, col;
{
    union REGS regs;

    mouse_hide();
    regs.h.ah = 2;
    regs.h.bh = 0;
    regs.h.dh = row;
    regs.h.dl = col;

    int86(0x10, &regs, &regs);
    mouse_show();

    cury = row;
    curx = col;
    return 0;
}

int getyx(row, col)
/* get current cursor position */
int *row;
int *col;
{
    *row = cury;
    *col = curx;
    return 0;
}

static void scroll(forward, nlines, attr, top, bot, left, right)
/* scroll screen region */
bool forward;
int nlines, attr, top, bot, left, right;
{
    union REGS regs;

    mouse_hide();
    regs.h.ah = 6 + !forward;
    regs.h.al = nlines;
    regs.h.bh = attr;
    regs.h.ch = top;
    regs.h.cl = left;
    regs.h.dh = bot;
    regs.h.dl = right;
    int86(0x10, &regs, &regs);
    mouse_show();
}

int clear()
{
    scroll(TRUE, 0, pcattr(cattr), 0, LINES - 1, 0, COLS - 1);
    move(0, 0);
    return OK;
}

int pcattr(a)
/* map A_* and color attributes to the bits in IBM CGA/EGA attribute words */
chtype a;
{
    chtype attr = 0;
    int p;

#ifdef RDGOPT
    static chtype prevarg = -1234;  /* very unlikely first value */
    static int prevattr;

    if ( a == prevarg )       /* if same arg as last one ... */
      return prevattr;  /* ... return prev value */

    prevarg = a;        /* save for next time */
#endif /* RDGOPT */

    if ( ! (a & A_COLOR) )
    {
      /* monochrome attributes */
      attr  = 0x0007;                     /* "normal" attr */
      if (a & A_STANDOUT)           attr  = 0x0070;
      if (a & A_REVERSE)            attr  = 0x0070;
      if (a & A_BLINK)        attr |= 0x0080;
      if (a & A_UNDERLINE)          attr |= 0x0001;
    }
    else
    {
      /* color setup */
      if (p = PAIR_NUMBER(a))
          attr |= pairs[p];
    }
    if (a & A_BOLD)           attr |= 0x0008; /* works for color or mono */

#ifdef RDGOPT
    prevattr = attr;    /* save for next time */
#endif /* RDGOPT */

    return(attr);
}

static void swrite(row, col, s0, attr)
/* write data, starting at given row/col, with given attribute */
int row, col;
char *s0;
int attr;
{
    char buf[MAXCOLS * 2];
    register char *s;

    ++row;
    ++col;
    s = s0;
    if ( *s )
    {
      register int *p;
      register int n;
      n = strlen(s);
      p = (int *)buf;
      memset(buf, attr, n * 2);
      *(char *)p = *s;
      --n;
      if ( n )
      {
          do
          {
            *(char *)(++p) = *++s;
          } while ( --n );
      }
      ++s;
    }    

    mouse_hide();
    if ( s > s0 )
      puttext(col, row, col + (s - s0) - 1, row, buf);
    mouse_show();
}

int attrset(a)
/* set write attribute for subsequent operations */
chtype      a;
{
    cattr = a;
    return(OK);
}

int start_color()
{
    if (!has_colors())
      return(ERR);

    COLOR_PAIRS = sizeof(pairs) / sizeof(int);

    return(OK);
}

int init_pair(n, fg, bg)
/* initialize a given color pair to given foreground/background combination */
int   n, fg, bg;
{
    /*
     * By a not-so-amazing coincidence, the numbers of the 8 basic
     * curses(3) colors are precisely the RGB bit patters needed
     * to coerce an IBM CGA adapter.
     */
    if (n < COLOR_PAIRS)
    {
      pairs[n] = (bg << 4) | fg;
      return(OK);
    }
    else
      return(ERR);
}

int addstr(s)
/* write a string to the screen, advancing the update cursor */
char  *s;
{
    swrite(cury, curx, s, pcattr(cattr));
    curx += strlen(s);
    return(OK);
}

int _addch(c)
/* write a character to the screen, advancing the update cursor */
chtype      c;
{
    static char s[2];
    chtype attr;

    if ( (attr = c & A_ATTRIBUTES) == 0 )
      attr = cattr;
    s[0] = c;
    swrite(cury, curx, s, pcattr(attr));
    curx++;
    return(OK);
}

/*********** keyboard & mouse handling *****************/

/* status variables for last mouse event */
static int lastx, lasty;      /* last mouse position */
static int lastevent;   /* last button event */

/* We use MSDOS function 6 (direct console i/o) to avoid problems
** with control-c/control-break checking
*/
static int dos06(int ch) /* ch is -1 for input; anything else for output */
{
#define ZFLAG 0x40
    union REGS r;

    r.h.ah = 6;
    r.h.dl = ch;
    intdos(&r, &r);
    if ( ch == -1 )
      return r.x.flags & ZFLAG ? -1 : r.h.al;
    else
      return 0;
}

static int cinp(int nowait)
{
    int r;

    do
    {
      r = dos06(-1);
    } while ( ! nowait && r == -1 );
    if ( r == 0 )
    {
      r = 256 + dos06(-1);
      assert(r > 256);
    }
    else if ( r == -1 )
    {
      r = 0;
    }
    return r;
}

static int getkey()
{
    return cinp(FALSE);
}

static int getkeynowait()
{
    return cinp(TRUE);
}

int mse_status_raw(py, px)
int *px, *py;
{
    union REGS r;

    r.x.ax = 3;
    int86(0x33, &r, &r);
    *px = r.x.cx >> 3;  /* translate coords to col/row */
    *py = r.x.dx >> 3;
    return r.x.bx;
}

static int cgetch()
/* return next keypress or mouse click */
{
    static int left_was_down = FALSE;
    static int right_was_down = FALSE;
    int code;

    /* no mouse? then just get a keystroke */
    if (!mse)
      code = getkey();
    else          /* there's a mouse; wait on event */
      for (;;)
      {
          int x, y, mse_stat;

          if (code = getkeynowait())
            break;
#if 00
          mse_stat = mouse_status(&y, &x);
#endif
          /* poll the mouse */
          mse_stat = mse_status_raw(&lasty, &lastx);
          
          if ( mse_stat & 1 )
          {
            if ( ! left_was_down )
            {
                left_was_down = TRUE;
                lastevent = (lastevent & ~ BUTTON1_RELEASED) | BUTTON1_PRESSED;
                return KEY_MOUSE;
            }
            else
            {
#ifdef SCROLLBAR
                napms(150);
                if ( mse_status_raw(&lasty, &lastx) & 1 && lastx == COLS )
                {
                    lastevent =
                        (lastevent & ~ BUTTON1_RELEASED) | BUTTON1_PRESSED;
                  return KEY_MOUSE;
                }
#endif /* SCROLLBAR */
            }
          }
          else
          {
            if ( left_was_down )
            {
                left_was_down = FALSE;
                lastevent = (lastevent & ~ BUTTON1_PRESSED) | BUTTON1_RELEASED;
                return KEY_MOUSE;
            }
            else
                lastevent = 0;
          }

          if ( mse_stat & 2 )
          {
            if ( ! right_was_down )
            {
                right_was_down = TRUE;
                lastevent = (lastevent & ~ BUTTON3_RELEASED) | BUTTON3_PRESSED;
                return KEY_MOUSE;
            }
          }
          else
          {
            if ( right_was_down )
            {
                right_was_down = FALSE;
                lastevent = (lastevent & ~ BUTTON3_PRESSED) | BUTTON3_RELEASED;
                return KEY_MOUSE;
            }
            else
                lastevent = 0;
          }

#if 00
          lastevent = 0;
          if ((mse_stat & 0x01) != left_was_down)
          {
            lastevent |= (left_was_down ? BUTTON1_RELEASED : BUTTON1_PRESSED);
            left_was_down = !left_was_down;
            return(KEY_MOUSE);
          }

          if ((mse_stat & 0x02) != right_was_down)
          {
            lastevent |= (right_was_down ? BUTTON3_RELEASED : BUTTON3_PRESSED);
            right_was_down = !right_was_down;
            return(KEY_MOUSE);
          }
#endif
      }

    /* special-key code translation */
    switch (code)
    {
    case 315:     return(KEY_F(1)); /* break; */
    case 316:     return(KEY_F(2)); /* break; */
    case 317:     return(KEY_F(3)); /* break; */
    case 318:     return(KEY_F(4)); /* break; */
    case 319:     return(KEY_F(5)); /* break; */
    case 320:     return(KEY_F(6)); /* break; */
    case 321:     return(KEY_F(7)); /* break; */
    case 322:     return(KEY_F(8)); /* break; */
    case 323:     return(KEY_F(9)); /* break; */
    case 324:     return(KEY_F(10));      /* break; */

    case 328:     return(KEY_UP);         /* break; */
    case 336:     return(KEY_DOWN); /* break; */
    case 331:     return(KEY_LEFT); /* break; */
    case 333:     return(KEY_RIGHT);      /* break; */

    case 335:     return(KEY_END);  /* break; */
    case 327:     return(KEY_HOME); /* break; */
    case 337:     return(KEY_NPAGE);      /* break; */
    case 329:     return(KEY_PPAGE);      /* break; */

    default:            break;
    }
    return(code);
}

int mouse_status(py, px)
/* return status caught by last mouse button event */
int   *py, *px;
{
    *py = lasty;
#ifdef SCROLLBAR
    *px = (lastx == COLS) ? THUMBCOL : lastx;
#else
    *px = lastx;
#endif /* SCROLLBAR */
    return(lastevent);
}

int inch()
/* get character and attribute at current update position */
{
    char    buf[4];

    gettext(curx + 1, cury + 1, curx + 1, cury + 1, buf);
    return(buf[0]);
}

#include <time.h>
#define     millisecs()       ((clock() * 10000)/(int)(double)(0.5+CLK_TCK*10))

int napms(n)
/* sleep for n milliseconds */
int   n;
{
    long    t0 = millisecs() + n;

    while (millisecs() < t0)
      continue;
    return(millisecs());
}

void beep()
{
    (void) putchar('\007');
}

unsigned char acs_map[] =
{
   /* ACS_BSSB */ 218,
   /* ACS_SSBB */ 192,
   /* ACS_BBSS */ 191,
   /* ACS_SBBS */ 217,
   /* ACS_SBSS */ 180,
   /* ACS_SSSB */ 195,
   /* ACS_SSBS */ 193,
   /* ACS_BSSS */ 194,
   /* ACS_BSBS */ 196,
   /* ACS_SBSB */ 179,
   /* ACS_SSSS */ 197,
   /* ACS_S1 */         223,  /* scan line 1 (actually top-half on) */
   /* ACS_S9 */         22,   /* scan line 9 */
   /* ACS_DIAMOND */    254,  /* diamond (actually bullet) */
   /* ACS_CKBOARD */    178,  /* checker board (stipple) */
   /* ACS_DEGREE */     248,  /* degree symbol */
   /* ACS_PLMINUS */    241,  /* plus/minus */
   /* ACS_BULLET */     254,  /* bullet */
   /* ACS_LARROW */     27,   /* arrow pointing left */
   /* ACS_RARROW */     26,   /* arrow pointing right */
   /* ACS_DARROW */     25,   /* arrow pointing down */
   /* ACS_UARROW */     24,   /* arrow pointing up */
   /* ACS_BOARD */      220,  /* board of squares */
   /* ACS_LANTERN */    15,   /* lantern symbol */
   /* ACS_BLOCK */      219,  /* solid square block */
};
#endif /* MSDOS */

#if defined(OLDCURSES) || defined(AMIGA)
/* character push queue */
static chtype getchq[GQDEPTH];
static int gqc = 0;

int egetch()
/* get single character or mouse event */
{
    /* queued characters waiting? then go */
    if (gqc > 0)
      return(getchq[--gqc]);
    else
      return(cgetch());
}

int ungetch(c)
/* try to queue a character for input */
int   c;
{
    if (gqc >= GQDEPTH)
      return(ERR);
    else
    {
      getchq[gqc++] = c;
      return(OK);
    }
}
#else
int egetch()
/* get single character or mouse event */
{
    return(cgetch());
}
#endif /* !defined(OLDCURSES) && !defined(AMIGA) */

/* screen.c ends here */

Generated by  Doxygen 1.6.0   Back to index