diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2011-10-14 04:55:05 +0200 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2011-10-14 04:55:05 +0200 |
commit | 6aa0e0017d7d0cddc006da885946934b06949a91 (patch) | |
tree | 66b688ec32e2f91266db760b1762f2a50cc52036 /libslang/src/sldostty.c | |
parent | a966db5b71328f6adf9dd767e64b322a3bd7ed9c (diff) | |
download | erlang-slang-fork-6aa0e0017d7d0cddc006da885946934b06949a91.tar.gz |
include libslang-1.4.9 and automatically build it and link erlang-slang against it
few (erlang) people will still have libslang-1.4.9 installed or spend time
to get it to link against the driver
Diffstat (limited to 'libslang/src/sldostty.c')
-rw-r--r-- | libslang/src/sldostty.c | 519 |
1 files changed, 519 insertions, 0 deletions
diff --git a/libslang/src/sldostty.c b/libslang/src/sldostty.c new file mode 100644 index 0000000..bc3f32a --- /dev/null +++ b/libslang/src/sldostty.c @@ -0,0 +1,519 @@ +/* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis + * This file is part of the S-Lang library. + * + * You may distribute under the terms of either the GNU General Public + * License or the Perl Artistic License. + */ + +#include "slinclud.h" + +#ifdef __DJGPP__ +# define _NAIVE_DOS_REGS +#endif + +#include <dos.h> + +#if defined (__EMX__) +# define int86 _int86 +# define delay _sleep2 +#endif /* __EMX__ */ + +#if defined (__WATCOMC__) +# include <conio.h> +# include <bios.h> +# define int86 int386 +#endif + +#if defined (__DJGPP__) +# include <sys/farptr.h> +# include <go32.h> +# include <bios.h> +#endif + +#ifndef _NKEYBRD_READ +# define _NKEYBRD_READ 0x0 +#endif +#ifndef _NKEYBRD_READY +# define _NKEYBRD_READY 0x1 +#endif +#ifndef _NKEYBRD_SHIFTSTATUS +# define _NKEYBRD_SHIFTSTATUS 0x2 +#endif + +#define BIOSKEY slbioskey +#if defined(__WATCOMC__) +# define keyWaiting() _bios_keybrd(_NKEYBRD_READY) +#else +# define keyWaiting() BIOSKEY(_NKEYBRD_READY) +#endif + +#ifndef __EMX__ +# define USE_MOUSE_CODE 1 +#else +# define USE_MOUSE_CODE 0 +#endif + +#include "slang.h" +#include "_slang.h" + +#ifdef __cplusplus +# define _DOTS_ ... +#else +# define _DOTS_ void +#endif + +#if !defined (__EMX__) && !defined (__GO32__) && !defined (__WATCOMC__) +#define HAS_INT9 +#endif + +#ifdef __GO32__ +# include <signal.h> +#endif + +#if defined (HAS_INT9) +static void interrupt (*int9_old) (_DOTS_); +static unsigned char far *shift = (unsigned char far *) 0x417; +static unsigned int Abort_Scan_Code = 34; /* 34 = scan code for ^G */ + +/*----------------------------------------------------------------------*\ + * an interrupt 9 handler, not for use with most 32 bit compilers +\*----------------------------------------------------------------------*/ +static void interrupt int9_handler (_DOTS_) +{ + unsigned char s, s1; + + s1 = *shift & 0xF; /* ignore caps, ins, num lock, scroll lock */ + s = inp (0x60); + if (s1 & 0x04) /* control key */ + { + if (s == Abort_Scan_Code) + { + if (SLang_Ignore_User_Abort == 0) SLang_Error = SL_USER_BREAK; + SLKeyBoard_Quit = 1; + } + } + (*int9_old) (); +} +#endif /* HAS_INT9 */ + +static void int9_change (int set) +{ +#if defined (HAS_INT9) + if (set) /* install a new handler */ + { + if (int9_old != NULL) return; + int9_old = getvect (9); + setvect (9, int9_handler); + } + else if (int9_old != NULL) /* restore the old handler */ + { + setvect (9, int9_old); + int9_old = NULL; + } +#else + (void) set; +#endif /* HAS_INT9 */ +} + +/*----------------------------------------------------------------------*\ + * Function: static void set_ctrl_break (int state); + * + * set the control-break setting +\*----------------------------------------------------------------------*/ +static void set_ctrl_break (int state) +{ +#if defined (__EMX__) + (void) state; /* not really required */ +#else /* __EMX__ */ + + static int prev = 0; + +# if defined (__GO32__) + if (state == 0) + { +# if __DJGPP__ >= 2 + signal (SIGINT, SIG_IGN); +# endif + prev = getcbrk (); + setcbrk (0); + } + else + { +# if __DJGPP__ >= 2 + signal (SIGINT, SIG_DFL); +# endif + setcbrk (prev); + } +# else /* __GO32__ */ +# if defined(__WATCOMC__) + fprintf (stderr, "Have not yet defined set_ctrl_break for __WATCOMC__\n"); + prev = state; +# else + asm mov dl, byte ptr prev + asm mov ax, state + asm cmp ax, 0 + asm jne L1 + asm mov ah, 33h + asm mov al, 0 + asm mov dl, byte ptr prev + asm int 21h + asm xor ax, ax + asm mov al, dl + asm mov prev, ax + asm mov dl, 0 + L1: + asm mov al, 1 + asm mov ah, 33h + asm int 21h +# endif /* __WATCOMC__ */ +# endif /* __GO32__ */ +#endif /* __EMX__ */ +} + +/*----------------------------------------------------------------------*\ + * static unsigned int slbioskey (int op); + * + * op 0-2 (standard) and 0x10-0x12 (extended) are valid + * + * 0, 0x10 _NKEYBRD_READ - read the key + * 1, 0x11 _NKEYBRD_READY - check if a key is waiting + * if so give a peek of its value, otherwise return 0 + * 2, 0x12 _NKEYBRD_SHIFTSTATUS - get shift flags + * (Ins, Cap, Num, Scroll, Alt, ^Ctrl L_shift, R_shift) + * flags = ICNSA^LR only the lower byte is valid! +\*----------------------------------------------------------------------*/ +static int bios_key_f = 0; +static unsigned int slbioskey (int op) +{ + union REGS r; + r.h.ah = (op & 0x03) | bios_key_f; + int86 (0x16, &r, &r); +#if defined(__WATCOMC__) + /* return (_bios_keybrd ((op & 0x03) | bios_key_f)); */ +# if 1 /* the correct zero flag for watcom? */ + /* is zero flag set? (no key waiting) */ + if ((op & _NKEYBRD_READY) && (r.x.cflag & 0x40) == 0x40) return 0; +# else /* the correct zero flag for watcom? */ + /* is zero flag set? (no key waiting) */ + if ((op & _NKEYBRD_READY) && (r.x.cflag & 0x4)) return 0; +# endif + return (r.x.eax & 0xffff); +#else + /* is zero flag set? (no key waiting) */ + if (op & _NKEYBRD_READY) + { + if ((r.x.flags & 0x40) == 0x40) + return 0; + if (r.x.ax == 0) /* CTRL-BREAK */ + return -1; + } + return (r.x.ax & 0xffff); +#endif +} + +#if USE_MOUSE_CODE +/*----------------------------------------------------------------------*\ + * Simple mouse routines for 16/32-bit DOS-targets. + * Gisle Vanem <giva@bgnett.no> +\*----------------------------------------------------------------------*/ + +#define HARD_MOUSE_RESET 0 + +static int Have_Mouse = 0; +static int Process_Mouse_Events = 0; + +/*----------------------------------------------------------------------*\ + * peem_far_mem() + * +\*----------------------------------------------------------------------*/ +static unsigned long peek_dos_mem (unsigned long dos_addr, + unsigned char *pentry) +{ + unsigned long vector; + unsigned char entry; + +#if defined(__DJGPP__) +# define MAKE_LINEAR(seg,ofs) ((unsigned long)(((seg) << 4) + (ofs))) + vector = _farpeekl (_dos_ds, dos_addr); + entry = _farpeekb (_dos_ds, MAKE_LINEAR(vector >> 16, vector & 0xffff)); + +#elif defined(__EMX__) + vector = 0; + entry = 0; /* to-do!! */ + +#elif defined(__WATCOMC__) && defined(__FLAT__) /* wcc386 */ + vector = *(unsigned long*) dos_addr; + entry = *(unsigned char*) vector; +#else + vector = *(unsigned long far*) dos_addr; + entry = *(unsigned char far*) vector; +#endif + + if (pentry) + *pentry = entry; + return (vector); +} + +/*----------------------------------------------------------------------*\ + * mouse_pressed (int button, int *x_pos, int *y_pos) + * + * Return 1 if left (0) or right (1) mouse-button was pressed. +\*----------------------------------------------------------------------*/ +static int mouse_pressed (int button, int *x_pos, int *y_pos) +{ + union REGS r; + + r.x.ax = 5; + r.x.bx = button; + int86 (0x33, &r, &r); + *x_pos = r.x.cx; + *y_pos = r.x.dx; + return (r.x.bx); +} + +/*----------------------------------------------------------------------*\ + * mouse_show (int show) + * + * Show (show=1) or hide (show=0) the mouse cursor +\*----------------------------------------------------------------------*/ +static int mouse_show (int show) +{ + union REGS r; + + if (Have_Mouse == 0) + return -1; + + r.x.ax = show ? 1 : 2; + int86 (0x33, &r, &r); + return 0; +} + +/*----------------------------------------------------------------------*\ + * mouse_exit (void) + * + * Do a soft-reset of the mouse-driver (hides cursor) +\*----------------------------------------------------------------------*/ +static void mouse_exit (void) +{ + union REGS r; + r.x.ax = 0x21; + int86 (0x33, &r, &r); +} + +/*----------------------------------------------------------------------*\ + * mouse_init (void) + * + * Peek at mouse interrupt vector for a driver. + * Do a soft/hard-reset of the mouse-driver. + * Add a SLang atexit function +\*----------------------------------------------------------------------*/ +static int mouse_init (void) +{ + union REGS r; + unsigned char entry = 0; + unsigned long vector = peek_dos_mem (4*0x33, &entry); + + if (!vector || entry == 0xCF) /* NULL or points to IRET */ + return -1; + +#if HARD_MOUSE_RESET + r.x.ax = 0; /* mouse hard-reset and reinit */ +#else + r.x.ax = 0x21; /* mouse soft-reset and reinit */ +#endif + + int86 (0x33, &r, &r); + if (r.x.ax != 0xFFFF) + return -1; + + (void) SLang_add_cleanup_function (mouse_exit); + Have_Mouse = 1; + return 0; +} + +/*----------------------------------------------------------------------*\ + * static int mouse_get_event (void); + * + * Poll mouse for changed button-state and encode x/y position and + * button state into an escape sequence "\e[M.." +\*----------------------------------------------------------------------*/ +static int mouse_get_event (void) +{ + char buf [6]; + int x, y; + + if (!Have_Mouse || Process_Mouse_Events == 0) + return (0); + + if (mouse_pressed(0, &x, &y)) /* left button pressed? */ + buf[3] = 040; + else if (mouse_pressed(1, &x, &y)) /* right button pressed */ + buf[3] = 041; + else return (0); + +#if 0 /* test */ + fprintf (stderr, "mouse_get_event: x=%d, y=%d\n", x, y); +#endif + + /* + * Taken from slw32tty.c / process_mouse_event(): + * + * We have a simple press or release. Encode it as an escape sequence + * and buffer the result. The encoding is: + * 'ESC [ M b x y' + * where b represents the button state, and x,y represent the coordinates. + * The ESC is handled by the calling routine. + */ + buf[0] = 27; + buf[1] = '['; + buf[2] = 'M'; + buf[4] = 1 + ' ' + (x >> 3); /* textmode co-ordinates are 1/8th of */ + buf[5] = 1 + ' ' + (y >> 3); /* graphics-mode co-ordinates */ + + if (SLang_buffer_keystring (buf, sizeof(buf)) < 0) + return (0); + return (1); +} + +#endif /* USE_MOUSE_CODE */ + +/*----------------------------------------------------------------------*\ + * Function: int SLang_init_tty (int abort_char, int no_flow_control, + * int opost); + * + * initialize the keyboard interface and attempt to set-up the interrupt 9 + * handler if ABORT_CHAR is non-zero. + * NO_FLOW_CONTROL and OPOST are only for compatiblity and are ignored. +\*----------------------------------------------------------------------*/ +int SLang_init_tty (int abort_char, int no_flow_control, int opost) +{ + (void) no_flow_control; + (void) opost; + + bios_key_f = 0x10; /* assume it's an enhanced keyboard */ +#if defined (HAS_INT9) + bios_key_f &= peekb (0x40,0x96); /* verify it's true */ + if (abort_char > 0) Abort_Scan_Code = (unsigned int) abort_char; +#else + (void) abort_char; +#endif + + set_ctrl_break (0); + + return 0; +} + +/*----------------------------------------------------------------------*\ + * Function: void SLang_reset_tty (void); + * + * reset the tty before exiting +\*----------------------------------------------------------------------*/ +void SLang_reset_tty (void) +{ + int9_change (0); + set_ctrl_break (1); +} + +/*----------------------------------------------------------------------*\ + * Function: int _SLsys_input_pending (int tsecs); + * + * sleep for *tsecs tenths of a sec waiting for input +\*----------------------------------------------------------------------*/ +int _SLsys_input_pending (int tsecs) +{ + if (keyWaiting()) return 1; + + /* Convert tsecs to units of 20 ms */ + tsecs = tsecs * 5; + + /* If tsecs is less than 0, it represents millisecs */ + if (tsecs < 0) + tsecs = -tsecs / 100; + + while ((tsecs > 0) && (SLang_Input_Buffer_Len == 0)) + { + delay (20); /* 20 ms or 1/50 sec */ +#if USE_MOUSE_CODE + if (1 == mouse_get_event ()) + return SLang_Input_Buffer_Len; +#endif + if (keyWaiting()) break; + tsecs--; + } + return (tsecs); +} + +/*----------------------------------------------------------------------*\ + * Function: unsigned int _SLsys_getkey (void); + * + * Wait for and get the next available mouse-event / keystroke. + * Also re-maps some useful keystrokes. + * + * Backspace (^H) => Del (127) + * Ctrl-Space => ^@ (^@^3 - a pc NUL char) + * extended keys are prefixed by a null character +\*----------------------------------------------------------------------*/ +unsigned int _SLsys_getkey (void) +{ + unsigned int key, scan, ch, shift; + + while ((SLang_Input_Buffer_Len == 0) + && (0 == _SLsys_input_pending (300))) + ; + + if (SLang_Input_Buffer_Len) + return SLang_getkey (); + + key = BIOSKEY(_NKEYBRD_READ); + ch = key & 0xff; + scan = key >> 8; + shift = BIOSKEY(_NKEYBRD_SHIFTSTATUS) & 0xf; + + if (key == 0x0e08) + return 127; /* Backspace key */ + + switch (ch) + { + case 32: + if (0 == (shift & 0x04)) + break; + /* ^space = ^@ */ + scan = 3; /* send back Ctrl-@ => ^@^C */ + /* drop */ + case 0xe0: + case 0: /* extended key code */ + ch = _SLpc_convert_scancode (scan, 0, 1); + } + return (ch); +} + +/*----------------------------------------------------------------------*\ + * Function: void SLang_set_abort_signal (void (*handler)(int)); +\*----------------------------------------------------------------------*/ +int SLang_set_abort_signal (void (*handler)(int)) +{ + if (handler == NULL) int9_change (1); + return 0; +} + +int SLtt_set_mouse_mode (int mode, int force) +{ +#if USE_MOUSE_CODE + (void) force; + + if ((Have_Mouse == 0) + && (-1 == mouse_init ())) + { + Process_Mouse_Events = 0; + return -1; + } + + Process_Mouse_Events = mode; + return mouse_show (mode); +#else + (void) mode; + (void) force; + + return -1; +#endif +} |