home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
-
- 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 BSD
- /*******************************************************************
- *
- * Support for BSD, 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 /* BSD */
-
- #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, ®s, ®s);
- 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, ®s, ®s);
- 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(CURSES) || defined(BSD) || 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(CURSES) || defined(BSD) */
-
- /* screen.c ends here */
-