12777ee89Sespie /* -*-C-*- */
22777ee89Sespie 
3*99fd0875Safresh1 #define PERL_NO_GET_CONTEXT     /* we want efficiency */
42777ee89Sespie #include "EXTERN.h"
52777ee89Sespie #include "perl.h"
62777ee89Sespie #include "XSUB.h"
72777ee89Sespie #include "ppport.h"
82777ee89Sespie 
92777ee89Sespie #define InputStream PerlIO *
102777ee89Sespie 
112777ee89Sespie /*******************************************************************
122777ee89Sespie 
132777ee89Sespie  Copyright (C) 1994,1995,1996,1997 Kenneth Albanowski. Unlimited
142777ee89Sespie  distribution and/or modification is allowed as long as this copyright
152777ee89Sespie  notice remains intact.
162777ee89Sespie 
172777ee89Sespie  Written by Kenneth Albanowski on Thu Oct  6 11:42:20 EDT 1994
182777ee89Sespie  Contact at kjahds@kjahds.com or CIS:70705,126
192777ee89Sespie 
20*99fd0875Safresh1  Maintained by Jonathan Stowe <jns@gellyfish.co.uk>
212777ee89Sespie 
22*99fd0875Safresh1  The below captures the history prior to it being in full time version
23*99fd0875Safresh1  control:
24*99fd0875Safresh1 
25*99fd0875Safresh1  $Id: ReadKey.xs,v 2.22 2005/01/11 21:15:17 jonathan Exp $
262777ee89Sespie 
272777ee89Sespie  Version 2.21, Sun Jul 28 12:57:56 BST 2002
282777ee89Sespie     Fix to improve the chances of automated testing succeeding
292777ee89Sespie 
302777ee89Sespie  Version 2.20, Tue May 21 07:52:47 BST 2002
312777ee89Sespie     Patch from Autrijus Tang fixing Win32 Breakage with bleadperl
322777ee89Sespie 
332777ee89Sespie  Version 2.19, Thu Mar 21 07:25:31 GMT 2002
342777ee89Sespie     Added check for definedness of $_[0] in comparisons in ReadKey, ReadLine
352777ee89Sespie     after reports of warnings.
362777ee89Sespie 
372777ee89Sespie  Version 2.18, Sun Feb 10 13:06:57 GMT 2002
382777ee89Sespie     Altered prototyping style after reports of compile failures on
392777ee89Sespie     Windows.
402777ee89Sespie 
412777ee89Sespie  Version 2.17, Fri Jan 25 06:58:47 GMT 2002
422777ee89Sespie     The '_' macro for non-ANSI compatibility was removed in 5.7.2
432777ee89Sespie 
442777ee89Sespie  Version 2.16, Thu Nov 29 21:19:03 GMT 2001
452777ee89Sespie     It appears that the genchars.pl bit of the patch didnt apply
462777ee89Sespie     Applied the new ppport.h from Devel::PPPort
472777ee89Sespie 
482777ee89Sespie  Version 2.15, Sun Nov  4 15:02:37 GMT 2001 (jns)
492777ee89Sespie     Applied the patch in
502777ee89Sespie     http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2001-01/msg01588.html
512777ee89Sespie     for PerlIO compatibility.
522777ee89Sespie 
532777ee89Sespie  Version 2.14, Sun Mar 28 23:26:13 EST 1999
542777ee89Sespie     ppport.h 1.007 fixed for 5.005_55.
552777ee89Sespie 
562777ee89Sespie  Version 2.13, Wed Mar 24 20:46:06 EST 1999
572777ee89Sespie  	Adapted to ppport.h 1.006.
582777ee89Sespie 
592777ee89Sespie  Version 2.12, Wed Jan  7 10:33:11 EST 1998
602777ee89Sespie  	Slightly modified test and error reporting for Win32.
612777ee89Sespie 
622777ee89Sespie  Version 2.11, Sun Dec 14 00:39:12 EST 1997
632777ee89Sespie     First attempt at Win32 support.
642777ee89Sespie 
652777ee89Sespie  Version 2.10, skipped
662777ee89Sespie 
672777ee89Sespie  Version 2.09, Tue Oct  7 13:07:43 EDT 1997
682777ee89Sespie     Grr. Added explicit detection of sys/poll.h and poll.h.
692777ee89Sespie 
702777ee89Sespie  Version 2.08, Mon Oct  6 16:07:44 EDT 1997
712777ee89Sespie     Changed poll.h to sys/poll.h.
722777ee89Sespie 
732777ee89Sespie  Version 2.07, Sun Jan 26 19:11:56 EST 1997
742777ee89Sespie     Added $VERSION to .pm.
752777ee89Sespie 
762777ee89Sespie  Version 2.06, Tue Nov 26 01:47:09 EST 1996
772777ee89Sespie     Added PERLIO support and removed duplicate declaration in .pm.
782777ee89Sespie 
792777ee89Sespie  Version 2.05, Tue Mar 12 19:08:33 EST 1996
802777ee89Sespie  	Changed poll support so it works. Cleaned up .pm a little.
812777ee89Sespie 
822777ee89Sespie  Version 2.04, Tue Oct 10 05:35:48 EDT 1995
832777ee89Sespie  	Whoops. Changed GetTermSize back so that GSIZE code won't be
842777ee89Sespie  	compiled if GWINSZ is being used. Also took ts_xxx and ts_yyy
852777ee89Sespie  	out of GSIZE.
862777ee89Sespie 
872777ee89Sespie  Version 2.03, Thu Sep 21 21:53:16 EDT 1995
882777ee89Sespie 	Fixed up debugging info in Readkey.pm, and changed TermSizeVIO
892777ee89Sespie 	to use _scrsize(). Hopefully this is GO for both Solaris and OS/2.
902777ee89Sespie 
912777ee89Sespie  Version 2.02, Mon Sep 18 22:17:57 EDT 1995
922777ee89Sespie 	Workaround for Solaris bug wasn't sufficient. Modularlized
932777ee89Sespie 	GetTermSize into perl code, and added support for the
942777ee89Sespie 	`resize` executable. Hard coded path for Solaris machines.
952777ee89Sespie 
962777ee89Sespie  Version 2.01, Wed Sep 13 22:22:23 EDT 1995
972777ee89Sespie 	Change error reporting around in getscreensize so that if
982777ee89Sespie  	an ioctl fails but getenv succeeds, no warning will be
992777ee89Sespie 	printed. This is an attempt to work around a Solaris bug where
1002777ee89Sespie 	TIOCGWINSZ fails in telnet sessions.
1012777ee89Sespie 
1022777ee89Sespie  Version 2.00, Mon Sep  4 06:37:24 EDT 1995
1032777ee89Sespie 	Added timeouts to select/poll, added USE_STDIO_PTR support
1042777ee89Sespie 	(required for recent perl revisions), and fixed up compilation
1052777ee89Sespie 	under OS/2.
1062777ee89Sespie 
1072777ee89Sespie  Version 1.99, Fri Aug 11 20:18:11 EDT 1995
1082777ee89Sespie 	Add file handles to ReadMode.
1092777ee89Sespie 
1102777ee89Sespie  Version 1.97, Mon Apr 10 21:41:52 EDT 1995
1112777ee89Sespie 	Changed mode 5 to disable UC & delays. Added more ECHO flags.
1122777ee89Sespie         Tested termio[s] & sgtty.
1132777ee89Sespie 	Added termoptions so test.pl can give more info.
1142777ee89Sespie 
1152777ee89Sespie  Version 1.96,
1162777ee89Sespie 	Mucked with filehandle selection in ReadKey.pm.
1172777ee89Sespie 
1182777ee89Sespie  Version 1.95,
1192777ee89Sespie 	Cleaning up for distribution.
1202777ee89Sespie 
1212777ee89Sespie  Version 1.94,
1222777ee89Sespie 	Dealt with get/settermsize sillyness.
1232777ee89Sespie 
1242777ee89Sespie  Version 1.91, Sat Mar 11 23:47:04 EST 1995:
1252777ee89Sespie 	Andy's patches, and a bit of termsize finesse.
1262777ee89Sespie 
1272777ee89Sespie  Version 1.9, Thu Mar  9 14:11:49 EST 1995:
1282777ee89Sespie 	Modifying for portability. Prototypes, singed chars, etc.
1292777ee89Sespie 
1302777ee89Sespie  Version 1.8, Mon Jan  9 23:18:14 EST 1995:
1312777ee89Sespie 	Added use of Configure.pm. No changes to ReadKey.
1322777ee89Sespie 
1332777ee89Sespie  Version 1.7, Fri Dec 16 13:48:14 EST 1994:
1342777ee89Sespie    Getting closer to release. Added new readmode 2. Had to bump up other
1352777ee89Sespie    modes, unfortunately. This is the _last_ time I do that. If I have to
1362777ee89Sespie    bump up the modes again, I'm switching to a different scheme.
1372777ee89Sespie 
1382777ee89Sespie  Version 1.6, Wed Dec 14 17:36:59 EST 1994:
1392777ee89Sespie 	Completly reorganized the control-char support (twice!) so that
1402777ee89Sespie 	it is automatically ported by the preproccessor for termio[s], or
1412777ee89Sespie 	by an included script for sgtty. Logical defaults for sgtty are included
1422777ee89Sespie 	too. Added Sun TermSize support. (Hope I got it right.)
1432777ee89Sespie 
1442777ee89Sespie  Version 1.5, Fri Dec  9 16:07:49 EST 1994:
1452777ee89Sespie 	Added SetTermSize, GetSpeeds, Get/SetControlChars, PerlIO support.
1462777ee89Sespie 
1472777ee89Sespie  Version 1.01, Thu Oct 20 23:32:39 EDT 1994:
1482777ee89Sespie 	Added Select_fd_set_t casts to select() call.
1492777ee89Sespie 
1502777ee89Sespie  Version 1.0: First "real" release. Everything seems cool.
1512777ee89Sespie 
1522777ee89Sespie 
1532777ee89Sespie *******************************************************************/
1542777ee89Sespie 
1552777ee89Sespie /***
1562777ee89Sespie 
1572777ee89Sespie  Things to do:
1582777ee89Sespie 
1592777ee89Sespie 	Make sure the GetSpeed function is doing it's best to separate ispeed
1602777ee89Sespie 	from ospeed.
1612777ee89Sespie 
1622777ee89Sespie 	Separate the stty stuff from ReadMode, so that stty -a can be easily
1632777ee89Sespie 	used, among other things.
1642777ee89Sespie 
1652777ee89Sespie ***/
1662777ee89Sespie 
1672777ee89Sespie 
1682777ee89Sespie 
1692777ee89Sespie /* Using these defines, you can elide anything you know
1702777ee89Sespie    won't work properly */
1712777ee89Sespie 
1722777ee89Sespie /* Methods of doing non-blocking reads */
1732777ee89Sespie 
1742777ee89Sespie /*#define DONT_USE_SELECT*/
1752777ee89Sespie /*#define DONT_USE_POLL*/
1762777ee89Sespie /*#define DONT_USE_NODELAY*/
1772777ee89Sespie 
1782777ee89Sespie 
1792777ee89Sespie /* Terminal I/O packages */
1802777ee89Sespie 
1812777ee89Sespie /*#define DONT_USE_TERMIOS*/
1822777ee89Sespie /*#define DONT_USE_TERMIO*/
1832777ee89Sespie /*#define DONT_USE_SGTTY*/
1842777ee89Sespie 
1852777ee89Sespie /* IOCTLs that can be used for GetTerminalSize */
1862777ee89Sespie 
1872777ee89Sespie /*#define DONT_USE_GWINSZ*/
1882777ee89Sespie /*#define DONT_USE_GSIZE*/
1892777ee89Sespie 
1902777ee89Sespie /* IOCTLs that can be used for SetTerminalSize */
1912777ee89Sespie 
1922777ee89Sespie /*#define DONT_USE_SWINSZ*/
1932777ee89Sespie /*#define DONT_USE_SSIZE*/
1942777ee89Sespie 
1952777ee89Sespie 
1962777ee89Sespie /* This bit is for OS/2 */
1972777ee89Sespie 
1982777ee89Sespie #ifdef OS2
1992777ee89Sespie #       define I_FCNTL
2002777ee89Sespie #       define HAS_FCNTL
2012777ee89Sespie 
2022777ee89Sespie #       define O_NODELAY O_NDELAY
2032777ee89Sespie 
2042777ee89Sespie #       define DONT_USE_SELECT
2052777ee89Sespie #       define DONT_USE_POLL
2062777ee89Sespie 
2072777ee89Sespie #       define DONT_USE_TERMIOS
2082777ee89Sespie #       define DONT_USE_SGTTY
2092777ee89Sespie #       define I_TERMIO
2102777ee89Sespie #       define CC_TERMIO
2112777ee89Sespie 
2122777ee89Sespie /* This flag should be off in the lflags when we enable termio mode */
2132777ee89Sespie #      define TRK_IDEFAULT     IDEFAULT
2142777ee89Sespie 
2152777ee89Sespie #       define INCL_SUB
2162777ee89Sespie #       define INCL_DOS
2172777ee89Sespie 
2182777ee89Sespie #       include <os2.h>
2192777ee89Sespie #	include <stdlib.h>
2202777ee89Sespie 
2212777ee89Sespie #       define VIOMODE
2222777ee89Sespie #else
2232777ee89Sespie         /* no os2 */
2242777ee89Sespie #endif
2252777ee89Sespie 
2262777ee89Sespie /* This bit is for Windows 95/NT */
2272777ee89Sespie 
2282777ee89Sespie #ifdef WIN32
2292777ee89Sespie #		define DONT_USE_TERMIO
2302777ee89Sespie #		define DONT_USE_TERMIOS
2312777ee89Sespie #		define DONT_USE_SGTTY
2322777ee89Sespie #		define DONT_USE_POLL
2332777ee89Sespie #		define DONT_USE_SELECT
2342777ee89Sespie #		define DONT_USE_NODELAY
2352777ee89Sespie #		define USE_WIN32
2362777ee89Sespie #		include <io.h>
2372777ee89Sespie #		if defined(_get_osfhandle) && (PERL_VERSION == 4) && (PERL_SUBVERSION < 5)
2382777ee89Sespie #			undef _get_osfhandle
2392777ee89Sespie #			if defined(_MSC_VER)
2402777ee89Sespie #				define level _cnt
2412777ee89Sespie #			endif
2422777ee89Sespie #		endif
2432777ee89Sespie #endif
2442777ee89Sespie 
2452777ee89Sespie /* This bit for NeXT */
2462777ee89Sespie 
2472777ee89Sespie #ifdef _NEXT_SOURCE
2482777ee89Sespie   /* fcntl with O_NDELAY (FNDELAY, actually) is broken on NeXT */
2492777ee89Sespie # define DONT_USE_NODELAY
2502777ee89Sespie #endif
2512777ee89Sespie 
2522777ee89Sespie #if !defined(DONT_USE_NODELAY)
2532777ee89Sespie # ifdef HAS_FCNTL
2542777ee89Sespie #  define Have_nodelay
2552777ee89Sespie #  ifdef I_FCNTL
2562777ee89Sespie #   include <fcntl.h>
2572777ee89Sespie #  endif
2582777ee89Sespie #  ifdef I_SYS_FILE
2592777ee89Sespie #   include <sys/file.h>
2602777ee89Sespie #  endif
2612777ee89Sespie #  ifdef I_UNISTD
2622777ee89Sespie #   include <unistd.h>
2632777ee89Sespie #  endif
2642777ee89Sespie 
2652777ee89Sespie /* If any other headers are needed for fcntl or O_NODELAY, they need to get
2662777ee89Sespie    included right here */
2672777ee89Sespie 
2682777ee89Sespie #  if !defined(O_NODELAY)
2692777ee89Sespie #   if !defined(FNDELAY)
2702777ee89Sespie #    undef Have_nodelay
2712777ee89Sespie #   else
2722777ee89Sespie #    define O_NODELAY FNDELAY
2732777ee89Sespie #   endif
2742777ee89Sespie #  else
2752777ee89Sespie #   define O_NODELAY O_NDELAY
2762777ee89Sespie #  endif
2772777ee89Sespie # endif
2782777ee89Sespie #endif
2792777ee89Sespie 
2802777ee89Sespie #if !defined(DONT_USE_SELECT)
2812777ee89Sespie # ifdef HAS_SELECT
2822777ee89Sespie #  ifdef I_SYS_SELECT
2832777ee89Sespie #   include <sys/select.h>
2842777ee89Sespie #  endif
2852777ee89Sespie 
2862777ee89Sespie /* If any other headers are likely to be needed for select, they need to be
2872777ee89Sespie    included right here */
2882777ee89Sespie 
2892777ee89Sespie #  define Have_select
2902777ee89Sespie # endif
2912777ee89Sespie #endif
2922777ee89Sespie 
2932777ee89Sespie #if !defined(DONT_USE_POLL)
2942777ee89Sespie # ifdef HAS_POLL
2952777ee89Sespie #  ifdef HAVE_POLL_H
2962777ee89Sespie #   include <poll.h>
2972777ee89Sespie #   define Have_poll
2982777ee89Sespie #  endif
2992777ee89Sespie #  ifdef HAVE_SYS_POLL_H
3002777ee89Sespie #   include <sys/poll.h>
3012777ee89Sespie #   define Have_poll
3022777ee89Sespie #  endif
3032777ee89Sespie # endif
3042777ee89Sespie #endif
3052777ee89Sespie 
3062777ee89Sespie #ifdef DONT_USE_TERMIOS
3072777ee89Sespie # ifdef I_TERMIOS
3082777ee89Sespie #  undef I_TERMIOS
3092777ee89Sespie # endif
3102777ee89Sespie #endif
3112777ee89Sespie #ifdef DONT_USE_TERMIO
3122777ee89Sespie # ifdef I_TERMIO
3132777ee89Sespie #  undef I_TERMIO
3142777ee89Sespie # endif
3152777ee89Sespie #endif
3162777ee89Sespie #ifdef DONT_USE_SGTTY
3172777ee89Sespie # ifdef I_SGTTY
3182777ee89Sespie #  undef I_SGTTY
3192777ee89Sespie # endif
3202777ee89Sespie #endif
3212777ee89Sespie 
3222777ee89Sespie /* Pre-POSIX SVR3 systems sometimes define struct winsize in
3232777ee89Sespie    sys/ptem.h.  However, sys/ptem.h needs a type mblk_t (?) which
3242777ee89Sespie    is defined in <sys/stream.h>.
3252777ee89Sespie    No, Configure (dist3.051) doesn't know how to check for this.
3262777ee89Sespie */
3272777ee89Sespie #ifdef I_SYS_STREAM
3282777ee89Sespie # include <sys/stream.h>
3292777ee89Sespie #endif
3302777ee89Sespie #ifdef I_SYS_PTEM
3312777ee89Sespie # include <sys/ptem.h>
3322777ee89Sespie #endif
3332777ee89Sespie 
3342777ee89Sespie #ifdef I_TERMIOS
3352777ee89Sespie # include <termios.h>
3362777ee89Sespie #else
3372777ee89Sespie # ifdef I_TERMIO
3382777ee89Sespie #  include <termio.h>
3392777ee89Sespie # else
3402777ee89Sespie #  ifdef I_SGTTY
3412777ee89Sespie #   include <sgtty.h>
3422777ee89Sespie #  endif
3432777ee89Sespie # endif
3442777ee89Sespie #endif
3452777ee89Sespie 
3462777ee89Sespie #ifdef I_TERMIOS
3472777ee89Sespie # define CC_TERMIOS
3482777ee89Sespie #else
3492777ee89Sespie # ifdef I_TERMIO
3502777ee89Sespie #  define CC_TERMIO
3512777ee89Sespie # else
3522777ee89Sespie #  ifdef I_SGTTY
3532777ee89Sespie #   define CC_SGTTY
3542777ee89Sespie #  endif
3552777ee89Sespie # endif
3562777ee89Sespie #endif
3572777ee89Sespie 
3582777ee89Sespie #ifndef TRK_IDEFAULT
3592777ee89Sespie /* This flag should be off in the lflags when we enable termio mode */
3602777ee89Sespie #      define TRK_IDEFAULT     0
3612777ee89Sespie #endif
3622777ee89Sespie 
3632777ee89Sespie /* Fix up the disappearance of the '_' macro in Perl 5.7.2 */
3642777ee89Sespie 
3652777ee89Sespie #ifndef _
3662777ee89Sespie #  ifdef CAN_PROTOTYPE
3672777ee89Sespie #    define _(args) args
3682777ee89Sespie #  else
3692777ee89Sespie #    define _(args) ()
3702777ee89Sespie #  endif
3712777ee89Sespie #endif
3722777ee89Sespie 
3732777ee89Sespie #define DisableFlush (1) /* Should flushing mode changes be enabled?
3742777ee89Sespie 		            I think not for now. */
3752777ee89Sespie 
3762777ee89Sespie 
3772777ee89Sespie #define STDIN PerlIO_stdin()
3782777ee89Sespie 
3792777ee89Sespie #include "cchars.h"
3802777ee89Sespie 
3812777ee89Sespie 
382*99fd0875Safresh1 STATIC int GetTermSizeVIO _((pTHX_ PerlIO * file,
3832777ee89Sespie 	int * retwidth, int * retheight,
3842777ee89Sespie 	int * xpix, int * ypix));
3852777ee89Sespie 
386*99fd0875Safresh1 STATIC int GetTermSizeGWINSZ _((pTHX_ PerlIO * file,
3872777ee89Sespie 	int * retwidth, int * retheight,
3882777ee89Sespie 	int * xpix, int * ypix));
3892777ee89Sespie 
390*99fd0875Safresh1 STATIC int GetTermSizeGSIZE _((pTHX_ PerlIO * file,
3912777ee89Sespie 	int * retwidth, int * retheight,
3922777ee89Sespie 	int * xpix, int * ypix));
3932777ee89Sespie 
394*99fd0875Safresh1 STATIC int GetTermSizeWin32 _((pTHX_ PerlIO * file,
3952777ee89Sespie 	int * retwidth, int * retheight,
3962777ee89Sespie 	int * xpix, int * ypix));
3972777ee89Sespie 
398*99fd0875Safresh1 STATIC int SetTerminalSize _((pTHX_ PerlIO * file,
3992777ee89Sespie 	int width, int height,
4002777ee89Sespie 	int xpix, int ypix));
4012777ee89Sespie 
402*99fd0875Safresh1 STATIC void ReadMode _((pTHX_ PerlIO * file,int mode));
4032777ee89Sespie 
404*99fd0875Safresh1 STATIC int pollfile _((pTHX_ PerlIO * file, double delay));
4052777ee89Sespie 
406*99fd0875Safresh1 STATIC int setnodelay _((pTHX_ PerlIO * file, int mode));
4072777ee89Sespie 
408*99fd0875Safresh1 STATIC int selectfile _((pTHX_ PerlIO * file, double delay));
4092777ee89Sespie 
410*99fd0875Safresh1 STATIC int Win32PeekChar _((pTHX_ PerlIO * file, double delay, char * key));
4112777ee89Sespie 
412*99fd0875Safresh1 STATIC int getspeed _((pTHX_ PerlIO * file, I32 *in, I32 * out ));
4132777ee89Sespie 
4142777ee89Sespie 
4152777ee89Sespie #ifdef VIOMODE
GetTermSizeVIO(pTHX_ PerlIO * file,int * retwidth,int * retheight,int * xpix,int * ypix)416*99fd0875Safresh1 int GetTermSizeVIO(pTHX_ PerlIO *file,int *retwidth,int *retheight,int *xpix,int *ypix)
4172777ee89Sespie {
4182777ee89Sespie 	/*int handle=PerlIO_fileno(file);
4192777ee89Sespie 
4202777ee89Sespie         static VIOMODEINFO *modeinfo = NULL;
4212777ee89Sespie 
4222777ee89Sespie         if (modeinfo == NULL)
4232777ee89Sespie                 modeinfo = (VIOMODEINFO *)malloc(sizeof(VIOMODEINFO));
4242777ee89Sespie 
4252777ee89Sespie         VioGetMode(modeinfo,0);
4262777ee89Sespie         *retheight = modeinfo->row ?: 25;
4272777ee89Sespie         *retwidth = modeinfo->col ?: 80;*/
4282777ee89Sespie 	int buf[2];
4292777ee89Sespie 
4302777ee89Sespie 	_scrsize(&buf[0]);
4312777ee89Sespie 
4322777ee89Sespie 	*retwidth = buf[0]; *retheight = buf[1];
4332777ee89Sespie 
4342777ee89Sespie         *xpix = *ypix = 0;
4352777ee89Sespie         return 0;
4362777ee89Sespie }
4372777ee89Sespie #else
GetTermSizeVIO(pTHX_ PerlIO * file,int * retwidth,int * retheight,int * xpix,int * ypix)438*99fd0875Safresh1 int GetTermSizeVIO(pTHX_ PerlIO *file,int * retwidth,int *retheight, int *xpix,int *ypix)
4392777ee89Sespie {
4402777ee89Sespie 	croak("TermSizeVIO is not implemented on this architecture");
4412777ee89Sespie         return 0;
4422777ee89Sespie }
4432777ee89Sespie #endif
4442777ee89Sespie 
4452777ee89Sespie 
4462777ee89Sespie #if defined(TIOCGWINSZ) && !defined(DONT_USE_GWINSZ)
GetTermSizeGWINSZ(pTHX_ PerlIO * file,int * retwidth,int * retheight,int * xpix,int * ypix)447*99fd0875Safresh1 int GetTermSizeGWINSZ(pTHX_ PerlIO *file,int *retwidth,int *retheight,int *xpix,int *ypix)
4482777ee89Sespie {
4492777ee89Sespie 	int handle=PerlIO_fileno(file);
4502777ee89Sespie 	struct winsize w;
4512777ee89Sespie 
4522777ee89Sespie 	if (ioctl (handle, TIOCGWINSZ, &w) == 0) {
4532777ee89Sespie 		*retwidth=w.ws_col; *retheight=w.ws_row;
4542777ee89Sespie 		*xpix=w.ws_xpixel; *ypix=w.ws_ypixel; return 0;
4552777ee89Sespie 	}
4562777ee89Sespie 	else {
4572777ee89Sespie 		return -1; /* failure */
4582777ee89Sespie 	}
4592777ee89Sespie 
4602777ee89Sespie }
4612777ee89Sespie #else
GetTermSizeGWINSZ(pTHX_ PerlIO * file,int * retwidth,int * retheight,int * xpix,int * ypix)462*99fd0875Safresh1 int GetTermSizeGWINSZ(pTHX_ PerlIO *file,int *retwidth,int *retheight,int *xpix,int *ypix)
4632777ee89Sespie {
4642777ee89Sespie 	croak("TermSizeGWINSZ is not implemented on this architecture");
4652777ee89Sespie         return 0;
4662777ee89Sespie }
4672777ee89Sespie #endif
4682777ee89Sespie 
4692777ee89Sespie #if (!defined(TIOCGWINSZ) || defined(DONT_USE_GWINSZ)) && (defined(TIOCGSIZE) && !defined(DONT_USE_GSIZE))
GetTermSizeGSIZE(pTHX_ PerlIO * file,int * retwidth,int * retheight,int * xpix,int * ypix)470*99fd0875Safresh1 int GetTermSizeGSIZE(pTHX_ PerlIO *file,int *retwidth,int *retheight,int *xpix,int *ypix)
4712777ee89Sespie {
4722777ee89Sespie 	int handle=PerlIO_fileno(file);
4732777ee89Sespie 
4742777ee89Sespie 	struct ttysize w;
4752777ee89Sespie 
4762777ee89Sespie 	if (ioctl (handle, TIOCGSIZE, &w) == 0) {
4772777ee89Sespie 		*retwidth=w.ts_cols; *retheight=w.ts_lines;
4782777ee89Sespie 		*xpix=0/*w.ts_xxx*/; *ypix=0/*w.ts_yyy*/; return 0;
4792777ee89Sespie 	}
4802777ee89Sespie 	else {
4812777ee89Sespie 		return -1; /* failure */
4822777ee89Sespie 	}
4832777ee89Sespie }
4842777ee89Sespie #else
GetTermSizeGSIZE(pTHX_ PerlIO * file,int * retwidth,int * retheight,int * xpix,int * ypix)485*99fd0875Safresh1 int GetTermSizeGSIZE(pTHX_ PerlIO *file,int *retwidth,int *retheight,int *xpix,int *ypix)
4862777ee89Sespie {
4872777ee89Sespie 	croak("TermSizeGSIZE is not implemented on this architecture");
4882777ee89Sespie         return 0;
4892777ee89Sespie }
4902777ee89Sespie #endif
4912777ee89Sespie 
4922777ee89Sespie #ifdef USE_WIN32
GetTermSizeWin32(pTHX_ PerlIO * file,int * retwidth,int * retheight,int * xpix,int * ypix)493*99fd0875Safresh1 int GetTermSizeWin32(pTHX_ PerlIO *file,int *retwidth,int *retheight,int *xpix,int *ypix)
4942777ee89Sespie {
4952777ee89Sespie 	int handle=PerlIO_fileno(file);
4962777ee89Sespie 	HANDLE whnd = (HANDLE)_get_osfhandle(handle);
4972777ee89Sespie 	CONSOLE_SCREEN_BUFFER_INFO info;
4982777ee89Sespie 
4992777ee89Sespie 	if (GetConsoleScreenBufferInfo(whnd, &info)) {
5002777ee89Sespie 		/* Logic: return maximum possible screen width, but return
5012777ee89Sespie 		   only currently selected height */
5022777ee89Sespie 		if (retwidth)
5032777ee89Sespie 			*retwidth = info.dwMaximumWindowSize.X;
5042777ee89Sespie 			/*info.srWindow.Right - info.srWindow.Left;*/
5052777ee89Sespie 		if (retheight)
5062777ee89Sespie 			*retheight = info.srWindow.Bottom - info.srWindow.Top;
5072777ee89Sespie 		if (xpix)
5082777ee89Sespie 			*xpix = 0;
5092777ee89Sespie 		if (ypix)
5102777ee89Sespie 			*ypix = 0;
5112777ee89Sespie 		return 0;
5122777ee89Sespie 	} else
5132777ee89Sespie 		return -1;
5142777ee89Sespie }
5152777ee89Sespie #else
GetTermSizeWin32(pTHX_ PerlIO * file,int * retwidth,int * retheight,int * xpix,int * ypix)516*99fd0875Safresh1 int GetTermSizeWin32(pTHX_ PerlIO *file,int *retwidth,int *retheight,int *xpix,int *ypix)
5172777ee89Sespie {
5182777ee89Sespie 	croak("TermSizeWin32 is not implemented on this architecture");
5192777ee89Sespie         return 0;
5202777ee89Sespie }
5212777ee89Sespie #endif /* USE_WIN32 */
5222777ee89Sespie 
5232777ee89Sespie 
termsizeoptions()524*99fd0875Safresh1 STATIC int termsizeoptions() {
5252777ee89Sespie 	return	0
5262777ee89Sespie #ifdef VIOMODE
5272777ee89Sespie 		| 1
5282777ee89Sespie #endif
5292777ee89Sespie #if defined(TIOCGWINSZ) && !defined(DONT_USE_GWINSZ)
5302777ee89Sespie 		| 2
5312777ee89Sespie #endif
5322777ee89Sespie #if defined(TIOCGSIZE) && !defined(DONT_USE_GSIZE)
5332777ee89Sespie 		| 4
5342777ee89Sespie #endif
5352777ee89Sespie #if defined(USE_WIN32)
5362777ee89Sespie 		| 8
5372777ee89Sespie #endif
5382777ee89Sespie 		;
5392777ee89Sespie }
5402777ee89Sespie 
5412777ee89Sespie 
SetTerminalSize(pTHX_ PerlIO * file,int width,int height,int xpix,int ypix)542*99fd0875Safresh1 int SetTerminalSize(pTHX_ PerlIO *file,int width,int height,int xpix,int ypix)
5432777ee89Sespie {
5442777ee89Sespie 	int handle=PerlIO_fileno(file);
5452777ee89Sespie 
5462777ee89Sespie #ifdef VIOMODE
5472777ee89Sespie         return -1;
5482777ee89Sespie #else
5492777ee89Sespie 
5502777ee89Sespie #if defined(TIOCSWINSZ) && !defined(DONT_USE_SWINSZ)
551*99fd0875Safresh1 	char buffer[10];
5522777ee89Sespie 	struct winsize w;
5532777ee89Sespie 
5542777ee89Sespie 	w.ws_col=width;
5552777ee89Sespie 	w.ws_row=height;
5562777ee89Sespie 	w.ws_xpixel=xpix;
5572777ee89Sespie 	w.ws_ypixel=ypix;
5582777ee89Sespie 	if (ioctl (handle, TIOCSWINSZ, &w) == 0) {
5592777ee89Sespie 		sprintf(buffer,"%d",width); /* Be polite to our children */
5602777ee89Sespie 		my_setenv("COLUMNS",buffer);
5612777ee89Sespie 		sprintf(buffer,"%d",height);
5622777ee89Sespie 		my_setenv("LINES",buffer);
5632777ee89Sespie 		return 0;
5642777ee89Sespie 	}
5652777ee89Sespie 	else {
5662777ee89Sespie 		croak("TIOCSWINSZ ioctl call to set terminal size failed: %s",Strerror(errno));
5672777ee89Sespie 		return -1;
5682777ee89Sespie 	}
5692777ee89Sespie #else
5702777ee89Sespie # if defined(TIOCSSIZE) && !defined(DONT_USE_SSIZE)
571*99fd0875Safresh1 	char buffer[10];
5722777ee89Sespie 	struct ttysize w;
5732777ee89Sespie 
5742777ee89Sespie 	w.ts_lines=height;
5752777ee89Sespie 	w.ts_cols=width;
5762777ee89Sespie 	w.ts_xxx=xpix;
5772777ee89Sespie 	w.ts_yyy=ypix;
5782777ee89Sespie 	if (ioctl (handle, TIOCSSIZE, &w) == 0) {
5792777ee89Sespie 		sprintf(buffer,"%d",width);
5802777ee89Sespie 		my_setenv("COLUMNS",buffer);
5812777ee89Sespie 		sprintf(buffer,"%d",height);
5822777ee89Sespie 		my_setenv("LINES",buffer);
5832777ee89Sespie 		return 0;
5842777ee89Sespie 	}
5852777ee89Sespie 	else {
5862777ee89Sespie 		croak("TIOCSSIZE ioctl call to set terminal size failed: %s",Strerror(errno));
5872777ee89Sespie 		return -1;
5882777ee89Sespie 	}
5892777ee89Sespie # else
5902777ee89Sespie 	/*sprintf(buffer,"%d",width)   * Should we could do this and then *
5912777ee89Sespie 	my_setenv("COLUMNS",buffer)    * said we succeeded?               *
5922777ee89Sespie 	sprintf(buffer,"%d",height);
5932777ee89Sespie 	my_setenv("LINES",buffer)*/
5942777ee89Sespie 
5952777ee89Sespie 	return -1; /* Fail */
5962777ee89Sespie # endif
5972777ee89Sespie #endif
5982777ee89Sespie #endif
5992777ee89Sespie 
6002777ee89Sespie }
6012777ee89Sespie 
602*99fd0875Safresh1 STATIC const I32 terminal_speeds[] = {
6032777ee89Sespie #ifdef B50
6042777ee89Sespie 	50, B50,
6052777ee89Sespie #endif
6062777ee89Sespie #ifdef B75
6072777ee89Sespie 	75, B75,
6082777ee89Sespie #endif
6092777ee89Sespie #ifdef B110
6102777ee89Sespie 	110, B110,
6112777ee89Sespie #endif
6122777ee89Sespie #ifdef B134
6132777ee89Sespie 	134, B134,
6142777ee89Sespie #endif
6152777ee89Sespie #ifdef B150
6162777ee89Sespie 	150, B150,
6172777ee89Sespie #endif
6182777ee89Sespie #ifdef B200
6192777ee89Sespie 	200, B200,
6202777ee89Sespie #endif
6212777ee89Sespie #ifdef B300
6222777ee89Sespie 	300, B300,
6232777ee89Sespie #endif
6242777ee89Sespie #ifdef B600
6252777ee89Sespie 	600, B600,
6262777ee89Sespie #endif
6272777ee89Sespie #ifdef B1200
6282777ee89Sespie 	1200, B1200,
6292777ee89Sespie #endif
6302777ee89Sespie #ifdef B1800
6312777ee89Sespie 	1800, B1800,
6322777ee89Sespie #endif
6332777ee89Sespie #ifdef B2400
6342777ee89Sespie 	2400, B2400,
6352777ee89Sespie #endif
6362777ee89Sespie #ifdef B4800
6372777ee89Sespie 	4800, B4800,
6382777ee89Sespie #endif
6392777ee89Sespie #ifdef B9600
6402777ee89Sespie 	9600, B9600,
6412777ee89Sespie #endif
6422777ee89Sespie #ifdef B19200
6432777ee89Sespie 	19200, B19200,
6442777ee89Sespie #endif
6452777ee89Sespie #ifdef B38400
6462777ee89Sespie 	38400, B38400,
6472777ee89Sespie #endif
6482777ee89Sespie #ifdef B57600
6492777ee89Sespie 	57600, B57600,
6502777ee89Sespie #endif
6512777ee89Sespie #ifdef B115200
6522777ee89Sespie 	115200, B115200,
6532777ee89Sespie #endif
6542777ee89Sespie #ifdef EXTA
6552777ee89Sespie 	19200, EXTA,
6562777ee89Sespie #endif
6572777ee89Sespie #ifdef EXTB
6582777ee89Sespie 	38400, EXTB,
6592777ee89Sespie #endif
6602777ee89Sespie #ifdef B0
6612777ee89Sespie 	0,  B0,
6622777ee89Sespie #endif
6632777ee89Sespie 	-1,-1
6642777ee89Sespie };
6652777ee89Sespie 
getspeed(pTHX_ PerlIO * file,I32 * in,I32 * out)666*99fd0875Safresh1 int getspeed(pTHX_ PerlIO *file,I32 *in, I32 *out)
6672777ee89Sespie {
6682777ee89Sespie 	int handle=PerlIO_fileno(file);
669*99fd0875Safresh1 #if defined(I_TERMIOS) || defined(I_TERMIO) || defined(I_SGTTY)
6702777ee89Sespie 	int i;
671*99fd0875Safresh1 #endif
6722777ee89Sespie #       ifdef I_TERMIOS
6732777ee89Sespie 	/* Posixy stuff */
6742777ee89Sespie 
6752777ee89Sespie 	struct termios buf;
6762777ee89Sespie 	tcgetattr(handle,&buf);
6772777ee89Sespie 
6782777ee89Sespie 	*in = *out = -1;
6792777ee89Sespie 	*in = cfgetispeed(&buf);
6802777ee89Sespie 	*out = cfgetospeed(&buf);
6812777ee89Sespie 	for(i=0;terminal_speeds[i]!=-1;i+=2) {
6822777ee89Sespie 		if(*in == terminal_speeds[i+1])
6832777ee89Sespie 			{ *in = terminal_speeds[i]; break; }
6842777ee89Sespie 	}
6852777ee89Sespie 	for(i=0;terminal_speeds[i]!=-1;i+=2) {
6862777ee89Sespie 		if(*out == terminal_speeds[i+1])
6872777ee89Sespie 			{ *out = terminal_speeds[i]; break; }
6882777ee89Sespie 	}
6892777ee89Sespie 	return 0;
6902777ee89Sespie 
6912777ee89Sespie #       else
6922777ee89Sespie #        ifdef I_TERMIO
6932777ee89Sespie 	 /* SysV stuff */
6942777ee89Sespie 	 struct termio buf;
6952777ee89Sespie 
6962777ee89Sespie 	 ioctl(handle,TCGETA,&buf);
6972777ee89Sespie 
6982777ee89Sespie 	*in=*out=-1;
6992777ee89Sespie 	for(i=0;terminal_speeds[i]!=-1;i+=2) {
7002777ee89Sespie 		if((buf.c_cflag & CBAUD) == terminal_speeds[i+1])
7012777ee89Sespie 			{ *in=*out=terminal_speeds[i]; break; }
7022777ee89Sespie 	}
7032777ee89Sespie 	return 0;
7042777ee89Sespie 
7052777ee89Sespie #        else
7062777ee89Sespie #         ifdef I_SGTTY
7072777ee89Sespie 	  /* BSD stuff */
7082777ee89Sespie 	  struct sgttyb buf;
7092777ee89Sespie 
7102777ee89Sespie 	  ioctl(handle,TIOCGETP,&buf);
7112777ee89Sespie 
7122777ee89Sespie 	*in=*out=-1;
7132777ee89Sespie 
7142777ee89Sespie 	for(i=0;terminal_speeds[i]!=-1;i+=2)
7152777ee89Sespie 		if(buf.sg_ospeed == terminal_speeds[i+1])
7162777ee89Sespie 			{ *out = terminal_speeds[i]; break; }
7172777ee89Sespie 
7182777ee89Sespie 	for(i=0;terminal_speeds[i]!=-1;i+=2)
7192777ee89Sespie 		if(buf.sg_ispeed == terminal_speeds[i+1])
7202777ee89Sespie 			{ *in = terminal_speeds[i]; break; }
7212777ee89Sespie 
7222777ee89Sespie 	return 0;
7232777ee89Sespie 
7242777ee89Sespie 
7252777ee89Sespie #         else
7262777ee89Sespie 
7272777ee89Sespie 	   /* No termio, termios or sgtty. I suppose we can try stty,
7282777ee89Sespie 	      but it would be nice if you could get a better OS */
7292777ee89Sespie 
7302777ee89Sespie 	return -1;
7312777ee89Sespie 
7322777ee89Sespie #         endif
7332777ee89Sespie #        endif
7342777ee89Sespie #       endif
7352777ee89Sespie }
7362777ee89Sespie 
7372777ee89Sespie #ifdef WIN32
7382777ee89Sespie struct tbuffer { DWORD Mode; };
7392777ee89Sespie #else
7402777ee89Sespie #ifdef I_TERMIOS
7412777ee89Sespie #define USE_TERMIOS
7422777ee89Sespie #define tbuffer termios
7432777ee89Sespie #else
7442777ee89Sespie #ifdef I_TERMIO
7452777ee89Sespie #define USE_TERMIO
7462777ee89Sespie #define tbuffer termio
7472777ee89Sespie #else
7482777ee89Sespie #ifdef I_SGTTY
7492777ee89Sespie #define USE_SGTTY
7502777ee89Sespie struct tbuffer {
7512777ee89Sespie 	  struct sgttyb buf;
7522777ee89Sespie #if defined(TIOCGETC)
7532777ee89Sespie 	  struct tchars tchar;
7542777ee89Sespie #endif
7552777ee89Sespie #if defined(TIOCGLTC)
7562777ee89Sespie 	  struct ltchars ltchar;
7572777ee89Sespie #endif
7582777ee89Sespie #if defined(TIOCLGET)
7592777ee89Sespie 	  int local;
7602777ee89Sespie #endif
7612777ee89Sespie };
7622777ee89Sespie #else
7632777ee89Sespie #define USE_STTY
7642777ee89Sespie struct tbuffer {
7652777ee89Sespie 	int dummy;
7662777ee89Sespie };
7672777ee89Sespie #endif
7682777ee89Sespie #endif
7692777ee89Sespie #endif
7702777ee89Sespie #endif
7712777ee89Sespie 
772*99fd0875Safresh1 static HV * filehash; /* Used to store the original terminal settings for each handle*/
773*99fd0875Safresh1 static HV * modehash; /* Used to record the current terminal "mode" for each handle*/
7742777ee89Sespie 
ReadMode(pTHX_ PerlIO * file,int mode)775*99fd0875Safresh1 void ReadMode(pTHX_ PerlIO *file,int mode)
7762777ee89Sespie {
7772777ee89Sespie 	dTHR;
7782777ee89Sespie 	int handle;
7792777ee89Sespie 	int firsttime;
7802777ee89Sespie 	int oldmode;
7812777ee89Sespie 	struct tbuffer work;
7822777ee89Sespie 	struct tbuffer	savebuf;
7832777ee89Sespie 
7842777ee89Sespie 
7852777ee89Sespie 	handle=PerlIO_fileno(file);
7862777ee89Sespie 
7872777ee89Sespie 	firsttime=!hv_exists(filehash, (char*)&handle, sizeof(int));
7882777ee89Sespie 
7892777ee89Sespie 
7902777ee89Sespie #	ifdef WIN32
7912777ee89Sespie 
7922777ee89Sespie 	if (!GetConsoleMode((HANDLE)_get_osfhandle(handle), &work.Mode))
7932777ee89Sespie 	    croak("GetConsoleMode failed, LastError=|%d|",GetLastError());
7942777ee89Sespie 
7952777ee89Sespie #	endif /* WIN32 */
7962777ee89Sespie 
7972777ee89Sespie #       ifdef USE_TERMIOS
7982777ee89Sespie 	/* Posixy stuff */
7992777ee89Sespie 
8002777ee89Sespie 	tcgetattr(handle,&work);
8012777ee89Sespie 
8022777ee89Sespie 
8032777ee89Sespie 
8042777ee89Sespie #endif
8052777ee89Sespie #ifdef USE_TERMIO
8062777ee89Sespie 	 /* SysV stuff */
8072777ee89Sespie 
8082777ee89Sespie 	 ioctl(handle,TCGETA,&work);
8092777ee89Sespie 
8102777ee89Sespie 
8112777ee89Sespie #endif
8122777ee89Sespie #ifdef USE_SGTTY
8132777ee89Sespie 	  /* BSD stuff */
8142777ee89Sespie 
8152777ee89Sespie 	  ioctl(handle,TIOCGETP,&work.buf);
8162777ee89Sespie # 	  if defined(TIOCGETC)
8172777ee89Sespie 	   ioctl(handle,TIOCGETC,&work.tchar);
8182777ee89Sespie #	  endif
8192777ee89Sespie #         if defined(TIOCLGET)
8202777ee89Sespie 	   ioctl(handle,TIOCLGET,&work.local);
8212777ee89Sespie #	  endif
8222777ee89Sespie #	  if defined(TIOCGLTC)
8232777ee89Sespie 	   ioctl(handle,TIOCGLTC,&work.ltchar);
8242777ee89Sespie #	  endif
8252777ee89Sespie 
8262777ee89Sespie 
8272777ee89Sespie #endif
8282777ee89Sespie 
8292777ee89Sespie 
8302777ee89Sespie 	if(firsttime) {
8312777ee89Sespie 		firsttime=0;
8322777ee89Sespie 		memcpy((void*)&savebuf,(void*)&work,sizeof(struct tbuffer));
8332777ee89Sespie 		if(!hv_store(filehash,(char*)&handle,sizeof(int),
8342777ee89Sespie 			newSVpv((char*)&savebuf,sizeof(struct tbuffer)),0))
8352777ee89Sespie 			croak("Unable to stash terminal settings.\n");
8362777ee89Sespie 		if(!hv_store(modehash,(char*)&handle,sizeof(int),newSViv(0),0))
8372777ee89Sespie 			croak("Unable to stash terminal settings.\n");
8382777ee89Sespie 	} else {
8392777ee89Sespie 		SV ** temp;
8402777ee89Sespie 		if(!(temp=hv_fetch(filehash,(char*)&handle,sizeof(int),0)))
8412777ee89Sespie 			croak("Unable to retrieve stashed terminal settings.\n");
8422777ee89Sespie 		memcpy(&savebuf,SvPV(*temp,PL_na),sizeof(struct tbuffer));
8432777ee89Sespie 		if(!(temp=hv_fetch(modehash,(char*)&handle,sizeof(int),0)))
8442777ee89Sespie 			croak("Unable to retrieve stashed terminal mode.\n");
8452777ee89Sespie 		oldmode=SvIV(*temp);
8462777ee89Sespie 	}
8472777ee89Sespie 
8482777ee89Sespie #ifdef WIN32
8492777ee89Sespie 
8502777ee89Sespie 	switch (mode) {
8512777ee89Sespie 		case 5:
8522777ee89Sespie 			/* Should 5 disable ENABLE_WRAP_AT_EOL_OUTPUT? */
8532777ee89Sespie 		case 4:
8542777ee89Sespie 			work.Mode &= ~(ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT|ENABLE_LINE_INPUT|ENABLE_PROCESSED_OUTPUT);
8552777ee89Sespie 			work.Mode |= 0;
8562777ee89Sespie 			break;
8572777ee89Sespie 		case 3:
8582777ee89Sespie 			work.Mode &= ~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT);
8592777ee89Sespie 			work.Mode |= ENABLE_PROCESSED_INPUT|ENABLE_PROCESSED_OUTPUT;
8602777ee89Sespie 			break;
8612777ee89Sespie 		case 2:
8622777ee89Sespie 			work.Mode &= ~(ENABLE_ECHO_INPUT);
8632777ee89Sespie 			work.Mode |= ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT|ENABLE_PROCESSED_OUTPUT;
8642777ee89Sespie 			break;
8652777ee89Sespie 		case 1:
8662777ee89Sespie 			work.Mode &= ~(0);
8672777ee89Sespie 			work.Mode |= ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT|ENABLE_PROCESSED_OUTPUT;
8682777ee89Sespie 			break;
8692777ee89Sespie 		case 0:
8702777ee89Sespie 			work = savebuf;
8712777ee89Sespie 			firsttime = 1;
8722777ee89Sespie 			break;
8732777ee89Sespie 	}
8742777ee89Sespie 
8752777ee89Sespie 	if (!SetConsoleMode((HANDLE)_get_osfhandle(handle), work.Mode))
8762777ee89Sespie 	    croak("SetConsoleMode failed, LastError=|%d|",GetLastError());
8772777ee89Sespie 
8782777ee89Sespie #endif /* WIN32 */
8792777ee89Sespie 
8802777ee89Sespie 
8812777ee89Sespie #ifdef USE_TERMIOS
8822777ee89Sespie 
8832777ee89Sespie 
8842777ee89Sespie /* What, me worry about standards? */
8852777ee89Sespie 
8862777ee89Sespie #       if !defined (VMIN)
8872777ee89Sespie #		define VMIN VEOF
8882777ee89Sespie #       endif
8892777ee89Sespie 
8902777ee89Sespie #	if !defined (VTIME)
8912777ee89Sespie #		define VTIME VEOL
8922777ee89Sespie #	endif
8932777ee89Sespie 
8942777ee89Sespie #	if !defined (IXANY)
8952777ee89Sespie #		define IXANY (0)
8962777ee89Sespie #	endif
8972777ee89Sespie 
8982777ee89Sespie #ifndef IEXTEN
8992777ee89Sespie #ifdef IDEFAULT
9002777ee89Sespie #define IEXTEN IDEFAULT
9012777ee89Sespie #endif
9022777ee89Sespie #endif
9032777ee89Sespie 
9042777ee89Sespie /* XXX Is ONLCR in POSIX?.  The value of '4' seems to be the same for
9052777ee89Sespie    both SysV and Sun, so it's probably rather general, and I'm not
9062777ee89Sespie    aware of a POSIX way to do this otherwise.
9072777ee89Sespie */
9082777ee89Sespie #ifndef ONLCR
9092777ee89Sespie # define ONLCR 4
9102777ee89Sespie #endif
9112777ee89Sespie 
9122777ee89Sespie #ifndef IMAXBEL
9132777ee89Sespie #define IMAXBEL 0
9142777ee89Sespie #endif
9152777ee89Sespie #ifndef ECHOE
9162777ee89Sespie #define ECHOE 0
9172777ee89Sespie #endif
9182777ee89Sespie #ifndef ECHOK
9192777ee89Sespie #define ECHOK 0
9202777ee89Sespie #endif
9212777ee89Sespie #ifndef ECHONL
9222777ee89Sespie #define ECHONL 0
9232777ee89Sespie #endif
9242777ee89Sespie #ifndef ECHOPRT
9252777ee89Sespie #define ECHOPRT 0
9262777ee89Sespie #endif
9272777ee89Sespie #ifndef FLUSHO
9282777ee89Sespie #define FLUSHO 0
9292777ee89Sespie #endif
9302777ee89Sespie #ifndef PENDIN
9312777ee89Sespie #define PENDIN 0
9322777ee89Sespie #endif
9332777ee89Sespie #ifndef ECHOKE
9342777ee89Sespie #define ECHOKE 0
9352777ee89Sespie #endif
9362777ee89Sespie #ifndef ONLCR
9372777ee89Sespie #define ONLCR 0
9382777ee89Sespie #endif
9392777ee89Sespie #ifndef OCRNL
9402777ee89Sespie #define OCRNL 0
9412777ee89Sespie #endif
9422777ee89Sespie #ifndef ONLRET
9432777ee89Sespie #define ONLRET 0
9442777ee89Sespie #endif
9452777ee89Sespie #ifndef IUCLC
9462777ee89Sespie #define IUCLC 0
9472777ee89Sespie #endif
9482777ee89Sespie #ifndef OPOST
9492777ee89Sespie #define OPOST 0
9502777ee89Sespie #endif
9512777ee89Sespie #ifndef OLCUC
9522777ee89Sespie #define OLCUC 0
9532777ee89Sespie #endif
9542777ee89Sespie #ifndef ECHOCTL
9552777ee89Sespie #define ECHOCTL 0
9562777ee89Sespie #endif
9572777ee89Sespie #ifndef XCASE
9582777ee89Sespie #define XCASE 0
9592777ee89Sespie #endif
9602777ee89Sespie #ifndef BRKINT
9612777ee89Sespie #define BRKINT 0
9622777ee89Sespie #endif
9632777ee89Sespie 
9642777ee89Sespie 
9652777ee89Sespie 	if(mode==5) {
9662777ee89Sespie 		/*\
9672777ee89Sespie 		 *  Disable everything except parity if needed.
9682777ee89Sespie 		\*/
9692777ee89Sespie 
9702777ee89Sespie 		/* Hopefully, this should put the tty into unbuffered mode
9712777ee89Sespie 		with signals and control characters (both posixy and normal)
9722777ee89Sespie 		disabled, along with flow control. Echo should be off.
9732777ee89Sespie 		CR/LF is not translated, along with 8-bit/parity */
9742777ee89Sespie 
9752777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
9762777ee89Sespie 
9772777ee89Sespie 		work.c_lflag &= ~(ICANON|ISIG|IEXTEN );
9782777ee89Sespie 		work.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ECHOCTL);
9792777ee89Sespie 		work.c_lflag &= ~(ECHOPRT|ECHOKE|FLUSHO|PENDIN|XCASE);
9802777ee89Sespie 		work.c_lflag |= NOFLSH;
9812777ee89Sespie         work.c_iflag &= ~(IXOFF|IXON|IXANY|ICRNL|IMAXBEL|BRKINT);
9822777ee89Sespie 
9832777ee89Sespie 		if(((work.c_iflag & INPCK) != INPCK) ||
9842777ee89Sespie                    ((work.c_cflag & PARENB) != PARENB)) {
9852777ee89Sespie 			work.c_iflag &= ~ISTRIP;
9862777ee89Sespie 			work.c_iflag |= IGNPAR;
9872777ee89Sespie 			work.c_iflag &= ~PARMRK;
9882777ee89Sespie 		}
9892777ee89Sespie 		work.c_oflag &= ~(OPOST |ONLCR|OCRNL|ONLRET);
9902777ee89Sespie 
9912777ee89Sespie 		work.c_cc[VTIME] = 0;
9922777ee89Sespie 		work.c_cc[VMIN] = 1;
9932777ee89Sespie 	}
9942777ee89Sespie 	else if(mode==4) {
9952777ee89Sespie 		/* Hopefully, this should put the tty into unbuffered mode
9962777ee89Sespie 		with signals and control characters (both posixy and normal)
9972777ee89Sespie 		disabled, along with flow control. Echo should be off.
9982777ee89Sespie 		About the only thing left unchanged is 8-bit/parity */
9992777ee89Sespie 
10002777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
10012777ee89Sespie 
10022777ee89Sespie 		/*work.c_iflag = savebuf.c_iflag;*/
10032777ee89Sespie 		work.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO);
10042777ee89Sespie 		work.c_lflag &= ~(ECHOE | ECHOK | ECHONL|ECHOCTL|ECHOPRT|ECHOKE);
10052777ee89Sespie         work.c_iflag &= ~(IXON | IXANY | BRKINT);
10062777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
10072777ee89Sespie 		work.c_cc[VTIME] = 0;
10082777ee89Sespie 		work.c_cc[VMIN] = 1;
10092777ee89Sespie 	}
10102777ee89Sespie 	else if(mode==3)
10112777ee89Sespie 	{
10122777ee89Sespie 		/* This should be an unbuffered mode with signals and control
10132777ee89Sespie 		characters enabled, as should be flow control. Echo should
10142777ee89Sespie 		still be off */
10152777ee89Sespie 
10162777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
10172777ee89Sespie 
10182777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
10192777ee89Sespie 		work.c_lflag &= ~(ICANON | ECHO);
10202777ee89Sespie 		work.c_lflag &= ~(ECHOE | ECHOK | ECHONL|ECHOCTL|ECHOPRT|ECHOKE);
10212777ee89Sespie 		work.c_lflag |= ISIG | IEXTEN;
10222777ee89Sespie 		/*work.c_iflag &= ~(IXON | IXOFF | IXANY);
10232777ee89Sespie 		work.c_iflag |= savebuf.c_iflag & (IXON|IXOFF|IXANY);
10242777ee89Sespie 		work.c_oflag = savebuf.c_oflag;*/
10252777ee89Sespie 		work.c_cc[VTIME] = 0;
10262777ee89Sespie 		work.c_cc[VMIN] = 1;
10272777ee89Sespie 	}
10282777ee89Sespie 	else if(mode==2)
10292777ee89Sespie 	{
10302777ee89Sespie 		/* This should be an unbuffered mode with signals and control
10312777ee89Sespie 		characters enabled, as should be flow control. Echo should
10322777ee89Sespie 		still be off */
10332777ee89Sespie 
10342777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
10352777ee89Sespie 
10362777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
10372777ee89Sespie 		work.c_lflag |= ICANON|ISIG|IEXTEN;
10382777ee89Sespie 		work.c_lflag &= ~ECHO;
10392777ee89Sespie 		work.c_lflag &= ~(ECHOE | ECHOK | ECHONL|ECHOCTL|ECHOPRT|ECHOKE);
10402777ee89Sespie 		/*work.c_iflag &= ~(IXON |IXOFF|IXANY);
10412777ee89Sespie 		work.c_iflag |= savebuf.c_iflag & (IXON|IXOFF|IXANY);
10422777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
10432777ee89Sespie 		work.c_cc[VTIME] = savebuf.c_cc[VTIME];
10442777ee89Sespie 		work.c_cc[VMIN] = savebuf.c_cc[VMIN];*/
10452777ee89Sespie 	}
10462777ee89Sespie 	else if(mode==1)
10472777ee89Sespie 	{
10482777ee89Sespie 		/* This should be an unbuffered mode with signals and control
10492777ee89Sespie 		characters enabled, as should be flow control. Echo should
10502777ee89Sespie 		still be off */
10512777ee89Sespie 
10522777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
10532777ee89Sespie 
10542777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
10552777ee89Sespie 		work.c_lflag |= ICANON|ECHO|ISIG|IEXTEN;
10562777ee89Sespie 		/*work.c_iflag &= ~(IXON |IXOFF|IXANY);
10572777ee89Sespie 		work.c_iflag |= savebuf.c_iflag & (IXON|IXOFF|IXANY);
10582777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
10592777ee89Sespie 		work.c_cc[VTIME] = savebuf.c_cc[VTIME];
10602777ee89Sespie 		work.c_cc[VMIN] = savebuf.c_cc[VMIN];*/
10612777ee89Sespie 	}
10622777ee89Sespie 	else if(mode==0){
10632777ee89Sespie 		/*work.c_lflag &= ~BITMASK;
10642777ee89Sespie 		work.c_lflag |= savebuf.c_lflag & BITMASK;
10652777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
10662777ee89Sespie 		work.c_cc[VTIME] = savebuf.c_cc[VTIME];
10672777ee89Sespie 		work.c_cc[VMIN] = savebuf.c_cc[VMIN];
10682777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
10692777ee89Sespie 		work.c_iflag &= ~(IXON|IXOFF|IXANY);
10702777ee89Sespie 		work.c_iflag |= savebuf.c_iflag & (IXON|IXOFF|IXANY);*/
10712777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
10722777ee89Sespie 		/*Copy(&work,&savebuf,1,sizeof(struct tbuffer));*/
10732777ee89Sespie 
10742777ee89Sespie 		firsttime=1;
10752777ee89Sespie 	}
10762777ee89Sespie 	else
10772777ee89Sespie 	{
10782777ee89Sespie 		croak("ReadMode %d is not implemented on this architecture.",mode);
10792777ee89Sespie 		return;
10802777ee89Sespie 	}
10812777ee89Sespie 
10822777ee89Sespie 
10832777ee89Sespie 	/* If switching from a "lower power" mode to a higher one, keep the
10842777ee89Sespie 	data that may be in the queue, as it can easily be type-ahead. On
10852777ee89Sespie 	switching to a lower mode from a higher one, however, flush the queue
10862777ee89Sespie 	so that raw keystrokes won't hit an unexpecting program */
10872777ee89Sespie 
10882777ee89Sespie 	if(DisableFlush || oldmode<=mode)
10892777ee89Sespie 		tcsetattr(handle,TCSANOW,&work);
10902777ee89Sespie 	else
10912777ee89Sespie 		tcsetattr(handle,TCSAFLUSH,&work);
10922777ee89Sespie 
10932777ee89Sespie 	/*tcsetattr(handle,TCSANOW,&work);*/ /* It might be better to FLUSH
10942777ee89Sespie 					   when changing gears to a lower mode,
10952777ee89Sespie 					   and only use NOW for higher modes.
10962777ee89Sespie 					*/
10972777ee89Sespie 
10982777ee89Sespie 
10992777ee89Sespie #endif
11002777ee89Sespie #ifdef USE_TERMIO
11012777ee89Sespie 
11022777ee89Sespie /* What, me worry about standards? */
11032777ee89Sespie 
11042777ee89Sespie #	 if !defined (IXANY)
11052777ee89Sespie #                define IXANY (0)
11062777ee89Sespie #        endif
11072777ee89Sespie 
11082777ee89Sespie #ifndef ECHOE
11092777ee89Sespie #define ECHOE 0
11102777ee89Sespie #endif
11112777ee89Sespie #ifndef ECHOK
11122777ee89Sespie #define ECHOK 0
11132777ee89Sespie #endif
11142777ee89Sespie #ifndef ECHONL
11152777ee89Sespie #define ECHONL 0
11162777ee89Sespie #endif
11172777ee89Sespie #ifndef XCASE
11182777ee89Sespie #define XCASE 0
11192777ee89Sespie #endif
11202777ee89Sespie #ifndef BRKINT
11212777ee89Sespie #define BRKINT 0
11222777ee89Sespie #endif
11232777ee89Sespie 
11242777ee89Sespie 
11252777ee89Sespie 
11262777ee89Sespie 	 if(mode==5) {
11272777ee89Sespie 		/* This mode should be echo disabled, signals disabled,
11282777ee89Sespie 		flow control disabled, and unbuffered. CR/LF translation
11292777ee89Sespie    	 	is off, and 8 bits if possible */
11302777ee89Sespie 
11312777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
11322777ee89Sespie 
11332777ee89Sespie 		work.c_lflag &= ~(ECHO | ISIG | ICANON | XCASE);
11342777ee89Sespie 		work.c_lflag &= ~(ECHOE | ECHOK | ECHONL | TRK_IDEFAULT);
11352777ee89Sespie 		work.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | BRKINT);
11362777ee89Sespie 		if((work.c_cflag | PARENB)!=PARENB ) {
11372777ee89Sespie 			work.c_iflag &= ~(ISTRIP|INPCK);
11382777ee89Sespie 			work.c_iflag |= IGNPAR;
11392777ee89Sespie 		}
11402777ee89Sespie 		work.c_oflag &= ~(OPOST|ONLCR);
11412777ee89Sespie 		work.c_cc[VMIN] = 1;
11422777ee89Sespie 		work.c_cc[VTIME] = 1;
11432777ee89Sespie 	 }
11442777ee89Sespie 	 else if(mode==4) {
11452777ee89Sespie 		/* This mode should be echo disabled, signals disabled,
11462777ee89Sespie 		flow control disabled, and unbuffered. Parity is not
11472777ee89Sespie 		touched. */
11482777ee89Sespie 
11492777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
11502777ee89Sespie 
11512777ee89Sespie 		work.c_lflag &= ~(ECHO | ISIG | ICANON);
11522777ee89Sespie 		work.c_lflag &= ~(ECHOE | ECHOK | ECHONL TRK_IDEFAULT);
11532777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
11542777ee89Sespie 		work.c_iflag &= ~(IXON | IXOFF | IXANY | BRKINT);
11552777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
11562777ee89Sespie 		work.c_cc[VMIN] = 1;
11572777ee89Sespie 		work.c_cc[VTIME] = 1;
11582777ee89Sespie 	 }
11592777ee89Sespie 	 else if(mode==3) {
11602777ee89Sespie 		/* This mode tries to have echo off, signals enabled,
11612777ee89Sespie 		flow control as per the original setting, and unbuffered. */
11622777ee89Sespie 
11632777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
11642777ee89Sespie 
11652777ee89Sespie 		work.c_lflag &= ~(ECHO | ICANON);
11662777ee89Sespie 		work.c_lflag &= ~(ECHOE | ECHOK | ECHONL | TRK_IDEFAULT);
11672777ee89Sespie 		work.c_lflag |= ISIG;
11682777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
11692777ee89Sespie 		work.c_iflag &= ~(IXON | IXOFF | IXANY);
11702777ee89Sespie 		work.c_iflag |= savebuf.c_iflag & (IXON|IXOFF|IXANY);
11712777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
11722777ee89Sespie 		work.c_cc[VMIN] = 1;
11732777ee89Sespie 		work.c_cc[VTIME] = 1;
11742777ee89Sespie 	 }
11752777ee89Sespie 	 else if(mode==2) {
11762777ee89Sespie 		/* This mode tries to set echo on, signals on, and buffering
11772777ee89Sespie 		on, with flow control set to whatever it was originally. */
11782777ee89Sespie 
11792777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
11802777ee89Sespie 
11812777ee89Sespie 		work.c_lflag |= (ISIG | ICANON);
11822777ee89Sespie 		work.c_lflag &= ~ECHO;
11832777ee89Sespie 		work.c_lflag &= ~(ECHOE | ECHOK | ECHONL | TRK_IDEFAULT);
11842777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
11852777ee89Sespie 		work.c_iflag &= ~(IXON | IXOFF | IXANY);
11862777ee89Sespie 		work.c_iflag |= savebuf.c_iflag & (IXON|IXOFF|IXANY);
11872777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
11882777ee89Sespie 		work.c_cc[VMIN] = savebuf.c_cc[VMIN];
11892777ee89Sespie 		work.c_cc[VTIME] = savebuf.c_cc[VTIME];
11902777ee89Sespie 
11912777ee89Sespie 		/* This assumes turning ECHO and ICANON back on is
11922777ee89Sespie 		   sufficient to re-enable cooked mode. If this is a
11932777ee89Sespie 		   problem, complain to me */
11942777ee89Sespie 
11952777ee89Sespie 		/* What the heck. We're already saving the entire buf, so
11962777ee89Sespie 		I'm now going to reset VMIN and VTIME too. Hope this works
11972777ee89Sespie 		properly */
11982777ee89Sespie 
11992777ee89Sespie 	 }
12002777ee89Sespie 	 else if(mode==1) {
12012777ee89Sespie 		/* This mode tries to set echo on, signals on, and buffering
12022777ee89Sespie 		on, with flow control set to whatever it was originally. */
12032777ee89Sespie 
12042777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
12052777ee89Sespie 
12062777ee89Sespie 		work.c_lflag |= (ECHO | ISIG | ICANON);
12072777ee89Sespie       work.c_iflag &= ~TRK_IDEFAULT;
12082777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
12092777ee89Sespie 		work.c_iflag &= ~(IXON | IXOFF | IXANY);
12102777ee89Sespie 		work.c_iflag |= savebuf.c_iflag & (IXON|IXOFF|IXANY);
12112777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
12122777ee89Sespie 		work.c_cc[VMIN] = savebuf.c_cc[VMIN];
12132777ee89Sespie 		work.c_cc[VTIME] = savebuf.c_cc[VTIME];
12142777ee89Sespie 
12152777ee89Sespie 		/* This assumes turning ECHO and ICANON back on is
12162777ee89Sespie 		   sufficient to re-enable cooked mode. If this is a
12172777ee89Sespie 		   problem, complain to me */
12182777ee89Sespie 
12192777ee89Sespie 		/* What the heck. We're already saving the entire buf, so
12202777ee89Sespie 		I'm now going to reset VMIN and VTIME too. Hope this works
12212777ee89Sespie 		properly */
12222777ee89Sespie 	}
12232777ee89Sespie 	 else if(mode==0) {
12242777ee89Sespie 		/* Put things back the way they were */
12252777ee89Sespie 
12262777ee89Sespie 		/*work.c_lflag = savebuf.c_lflag;
12272777ee89Sespie 		work.c_iflag = savebuf.c_iflag;
12282777ee89Sespie 		work.c_oflag = savebuf.c_oflag;
12292777ee89Sespie 		work.c_cc[VMIN] = savebuf.c_cc[VMIN];
12302777ee89Sespie 		work.c_cc[VTIME] = savebuf.c_cc[VTIME];*/
12312777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
12322777ee89Sespie 		firsttime=1;
12332777ee89Sespie 	 }
12342777ee89Sespie  	 else
12352777ee89Sespie  	 {
12362777ee89Sespie 		croak("ReadMode %d is not implemented on this architecture.",mode);
12372777ee89Sespie 		return;
12382777ee89Sespie 	 }
12392777ee89Sespie 
12402777ee89Sespie 
12412777ee89Sespie 	 if(DisableFlush || oldmode<=mode)
12422777ee89Sespie 		ioctl(handle,TCSETA,&work);
12432777ee89Sespie 	 else
12442777ee89Sespie 		ioctl(handle,TCSETAF,&work);
12452777ee89Sespie 
12462777ee89Sespie #endif
12472777ee89Sespie #ifdef USE_SGTTY
12482777ee89Sespie 
12492777ee89Sespie 
12502777ee89Sespie 	  if(mode==5) {
12512777ee89Sespie 		/* Unbuffered, echo off, signals off, flow control off */
12522777ee89Sespie 		/* CR-CR/LF mode off too, and 8-bit path enabled. */
12532777ee89Sespie #	 	if defined(TIOCLGET) && defined(LPASS8)
12542777ee89Sespie 		 if((work.buf.sg_flags & (EVENP|ODDP))==0 ||
12552777ee89Sespie 		    (work.buf.sg_flags & (EVENP|ODDP))==(EVENP|ODDP))
12562777ee89Sespie 		 	 work.local |= LPASS8; /* If parity isn't being used, use 8 bits */
12572777ee89Sespie #		endif
12582777ee89Sespie 	  	work.buf.sg_flags &= ~(ECHO|CRMOD);
12592777ee89Sespie 	  	work.buf.sg_flags |= (RAW|CBREAK);
12602777ee89Sespie # 	  	if defined(TIOCGETC)
12612777ee89Sespie 		 work.tchar.t_intrc = -1;
12622777ee89Sespie 		 work.tchar.t_quitc = -1;
12632777ee89Sespie 		 work.tchar.t_startc= -1;
12642777ee89Sespie 		 work.tchar.t_stopc = -1;
12652777ee89Sespie 		 work.tchar.t_eofc  = -1;
12662777ee89Sespie 		 work.tchar.t_brkc  = -1;
12672777ee89Sespie #		endif
12682777ee89Sespie #		if defined(TIOCGLTC)
12692777ee89Sespie 		 work.ltchar.t_suspc= -1;
12702777ee89Sespie 		 work.ltchar.t_dsuspc= -1;
12712777ee89Sespie 		 work.ltchar.t_rprntc= -1;
12722777ee89Sespie 		 work.ltchar.t_flushc= -1;
12732777ee89Sespie 		 work.ltchar.t_werasc= -1;
12742777ee89Sespie 		 work.ltchar.t_lnextc= -1;
12752777ee89Sespie #		endif
12762777ee89Sespie 	  }
12772777ee89Sespie 	  else if(mode==4) {
12782777ee89Sespie 		/* Unbuffered, echo off, signals off, flow control off */
12792777ee89Sespie 	  	work.buf.sg_flags &= ~(ECHO|RAW);
12802777ee89Sespie 	  	work.buf.sg_flags |= (CBREAK|CRMOD);
12812777ee89Sespie #	 	if defined(TIOCLGET)
12822777ee89Sespie 		 work.local=savebuf.local;
12832777ee89Sespie #		endif
12842777ee89Sespie # 	  	if defined(TIOCGETC)
12852777ee89Sespie 		 work.tchar.t_intrc = -1;
12862777ee89Sespie 		 work.tchar.t_quitc = -1;
12872777ee89Sespie 		 work.tchar.t_startc= -1;
12882777ee89Sespie 		 work.tchar.t_stopc = -1;
12892777ee89Sespie 		 work.tchar.t_eofc  = -1;
12902777ee89Sespie 		 work.tchar.t_brkc  = -1;
12912777ee89Sespie #		endif
12922777ee89Sespie #		if defined(TIOCGLTC)
12932777ee89Sespie 		 work.ltchar.t_suspc= -1;
12942777ee89Sespie 		 work.ltchar.t_dsuspc= -1;
12952777ee89Sespie 		 work.ltchar.t_rprntc= -1;
12962777ee89Sespie 		 work.ltchar.t_flushc= -1;
12972777ee89Sespie 		 work.ltchar.t_werasc= -1;
12982777ee89Sespie 		 work.ltchar.t_lnextc= -1;
12992777ee89Sespie #		endif
13002777ee89Sespie 	  }
13012777ee89Sespie 	  else if(mode==3) {
13022777ee89Sespie 		/* Unbuffered, echo off, signals on, flow control on */
13032777ee89Sespie 		work.buf.sg_flags &= ~(RAW|ECHO);
13042777ee89Sespie 	  	work.buf.sg_flags |= CBREAK|CRMOD;
13052777ee89Sespie #	 	if defined(TIOCLGET)
13062777ee89Sespie 		 work.local=savebuf.local;
13072777ee89Sespie #		endif
13082777ee89Sespie #		if defined(TIOCGLTC)
13092777ee89Sespie 		 work.tchar = savebuf.tchar;
13102777ee89Sespie #		endif
13112777ee89Sespie #		if defined(TIOCGLTC)
13122777ee89Sespie 		 work.ltchar = savebuf.ltchar;
13132777ee89Sespie #		endif
13142777ee89Sespie  	  }
13152777ee89Sespie 	  else if(mode==2) {
13162777ee89Sespie 		/* Buffered, echo on, signals on, flow control on */
13172777ee89Sespie 		work.buf.sg_flags &= ~(RAW|CBREAK);
13182777ee89Sespie 		work.buf.sg_flags |= CRMOD;
13192777ee89Sespie 		work.buf.sg_flags &= ~ECHO;
13202777ee89Sespie #	 	if defined(TIOCLGET)
13212777ee89Sespie 		 work.local=savebuf.local;
13222777ee89Sespie #		endif
13232777ee89Sespie #		if defined(TIOCGLTC)
13242777ee89Sespie 		 work.tchar = savebuf.tchar;
13252777ee89Sespie #		endif
13262777ee89Sespie #		if defined(TIOCGLTC)
13272777ee89Sespie 		 work.ltchar = savebuf.ltchar;
13282777ee89Sespie #		endif
13292777ee89Sespie 	  }
13302777ee89Sespie 	  else if(mode==1) {
13312777ee89Sespie 		/* Buffered, echo on, signals on, flow control on */
13322777ee89Sespie 		work.buf.sg_flags &= ~(RAW|CBREAK);
13332777ee89Sespie 		work.buf.sg_flags |= ECHO|CRMOD;
13342777ee89Sespie #	 	if defined(TIOCLGET)
13352777ee89Sespie 		 work.local=savebuf.local;
13362777ee89Sespie #		endif
13372777ee89Sespie #		if defined(TIOCGLTC)
13382777ee89Sespie 		 work.tchar = savebuf.tchar;
13392777ee89Sespie #		endif
13402777ee89Sespie #		if defined(TIOCGLTC)
13412777ee89Sespie 		 work.ltchar = savebuf.ltchar;
13422777ee89Sespie #		endif
13432777ee89Sespie 	  }
13442777ee89Sespie 	  else if(mode==0){
13452777ee89Sespie 		/* Original settings */
13462777ee89Sespie #if 0
13472777ee89Sespie 		work.buf.sg_flags &= ~(RAW|CBREAK|ECHO|CRMOD);
13482777ee89Sespie 		work.buf.sg_flags |= savebuf.sg_flags & (RAW|CBREAK|ECHO|CRMOD);
13492777ee89Sespie #	 	if defined(TIOCLGET)
13502777ee89Sespie 		 work.local=savebuf.local;
13512777ee89Sespie #		endif
13522777ee89Sespie #		if defined(TIOCGLTC)
13532777ee89Sespie 		 work.tchar = savebuf.tchar;
13542777ee89Sespie #		endif
13552777ee89Sespie #		if defined(TIOCGLTC)
13562777ee89Sespie 		 work.ltchar = savebuf.ltchar;
13572777ee89Sespie #		endif
13582777ee89Sespie #endif
13592777ee89Sespie 		memcpy((void*)&work,(void*)&savebuf,sizeof(struct tbuffer));
13602777ee89Sespie 		firsttime=1;
13612777ee89Sespie 	  }
13622777ee89Sespie  	  else
13632777ee89Sespie  	  {
13642777ee89Sespie 		croak("ReadMode %d is not implemented on this architecture.",mode);
13652777ee89Sespie 		return;
13662777ee89Sespie 	  }
13672777ee89Sespie #if defined(TIOCLSET)
13682777ee89Sespie 	  ioctl(handle,TIOCLSET,&work.local);
13692777ee89Sespie #endif
13702777ee89Sespie #if defined(TIOCSETC)
13712777ee89Sespie 	  ioctl(handle,TIOCSETC,&work.tchar);
13722777ee89Sespie #endif
13732777ee89Sespie #	  if defined(TIOCGLTC)
13742777ee89Sespie 	   ioctl(handle,TIOCSLTC,&work.ltchar);
13752777ee89Sespie #	  endif
13762777ee89Sespie 	  if(DisableFlush || oldmode<=mode)
13772777ee89Sespie 	  	ioctl(handle,TIOCSETN,&work.buf);
13782777ee89Sespie 	  else
13792777ee89Sespie 		ioctl(handle,TIOCSETP,&work.buf);
13802777ee89Sespie #endif
13812777ee89Sespie #ifdef USE_STTY
13822777ee89Sespie 
13832777ee89Sespie 	   /* No termio, termios or sgtty. I suppose we can try stty,
13842777ee89Sespie 	      but it would be nice if you could get a better OS */
13852777ee89Sespie 
13862777ee89Sespie 	   if(mode==5)
13872777ee89Sespie 		system("/bin/stty  raw -cbreak -isig -echo -ixon -onlcr -icrnl -brkint");
13882777ee89Sespie 	   else if(mode==4)
13892777ee89Sespie 		system("/bin/stty -raw  cbreak -isig -echo -ixon  onlcr  icrnl -brkint");
13902777ee89Sespie 	   else if(mode==3)
13912777ee89Sespie 		system("/bin/stty -raw  cbreak  isig -echo  ixon  onlcr  icrnl  brkint");
13922777ee89Sespie 	   else if(mode==2)
13932777ee89Sespie 		system("/bin/stty -raw -cbreak  isig  echo  ixon  onlcr  icrnl  brkint");
13942777ee89Sespie 	   else if(mode==1)
13952777ee89Sespie 		system("/bin/stty -raw -cbreak  isig -echo  ixon  onlcr  icrnl  brkint");
13962777ee89Sespie 	   else if(mode==0)
13972777ee89Sespie 		system("/bin/stty -raw -cbreak  isig  echo  ixon  onlcr  icrnl  brkint");
13982777ee89Sespie 
13992777ee89Sespie 	   /* Those probably won't work, but they couldn't hurt
14002777ee89Sespie               at this point */
14012777ee89Sespie 
14022777ee89Sespie #endif
14032777ee89Sespie 
14042777ee89Sespie 	/*warn("Mode set to %d.\n",mode);*/
14052777ee89Sespie 
14062777ee89Sespie 	if( firsttime ) {
14072777ee89Sespie 		(void)hv_delete(filehash,(char*)&handle,sizeof(int),0);
14082777ee89Sespie 		(void)hv_delete(modehash,(char*)&handle,sizeof(int),0);
14092777ee89Sespie 	} else {
14102777ee89Sespie 		if(!hv_store(modehash,(char*)&handle,sizeof(int),
14112777ee89Sespie 			newSViv(mode),0))
14122777ee89Sespie 			croak("Unable to stash terminal settings.\n");
14132777ee89Sespie 	}
14142777ee89Sespie 
14152777ee89Sespie }
14162777ee89Sespie 
14172777ee89Sespie #ifdef USE_PERLIO
14182777ee89Sespie 
14192777ee89Sespie /* Make use of a recent addition to Perl, if possible */
14202777ee89Sespie # define FCOUNT(f) PerlIO_get_cnt(f)
14212777ee89Sespie #else
14222777ee89Sespie 
14232777ee89Sespie  /* Make use of a recent addition to Configure, if possible */
14242777ee89Sespie # ifdef USE_STDIO_PTR
14252777ee89Sespie #  define FCOUNT(f) PerlIO_get_cnt(f)
14262777ee89Sespie # else
14272777ee89Sespie   /* This bit borrowed from pp_sys.c. Complain to Larry if it's broken. */
14282777ee89Sespie   /* If any of this works PerlIO_get_cnt() will too ... NI-S */
14292777ee89Sespie #  if defined(USE_STD_STDIO) || defined(atarist) /* this will work with atariST */
14302777ee89Sespie #   define FBASE(f) ((f)->_base)
14312777ee89Sespie #   define FSIZE(f) ((f)->_cnt + ((f)->_ptr - (f)->_base))
14322777ee89Sespie #   define FPTR(f) ((f)->_ptr)
14332777ee89Sespie #   define FCOUNT(f) ((f)->_cnt)
14342777ee89Sespie #  else
14352777ee89Sespie #   if defined(USE_LINUX_STDIO)
14362777ee89Sespie #     define FBASE(f) ((f)->_IO_read_base)
14372777ee89Sespie #     define FSIZE(f) ((f)->_IO_read_end - FBASE(f))
14382777ee89Sespie #     define FPTR(f) ((f)->_IO_read_ptr)
14392777ee89Sespie #     define FCOUNT(f) ((f)->_IO_read_end - FPTR(f))
14402777ee89Sespie #   endif
14412777ee89Sespie #  endif
14422777ee89Sespie # endif
14432777ee89Sespie #endif
14442777ee89Sespie 
14452777ee89Sespie /* This is for the best, I'm afraid. */
14462777ee89Sespie #if !defined(FCOUNT)
14472777ee89Sespie # ifdef Have_select
14482777ee89Sespie #  undef Have_select
14492777ee89Sespie # endif
14502777ee89Sespie # ifdef Have_poll
14512777ee89Sespie #  undef Have_poll
14522777ee89Sespie # endif
14532777ee89Sespie #endif
14542777ee89Sespie 
14552777ee89Sespie /* Note! If your machine has a bolixed up select() call that doesn't
14562777ee89Sespie understand this syntax, either fix the checkwaiting call below, or define
14572777ee89Sespie DONT_USE_SELECT. */
14582777ee89Sespie 
14592777ee89Sespie #ifdef Have_select
selectfile(pTHX_ PerlIO * file,double delay)1460*99fd0875Safresh1 int selectfile(pTHX_ PerlIO *file,double delay)
14612777ee89Sespie {
14622777ee89Sespie 	struct timeval t;
14632777ee89Sespie 	int handle=PerlIO_fileno(file);
14642777ee89Sespie 
14652777ee89Sespie 	/*char buf[32];
14662777ee89Sespie 	Select_fd_set_t fd=(Select_fd_set_t)&buf[0];*/
14672777ee89Sespie 
14682777ee89Sespie 	fd_set fd;
14692777ee89Sespie 	if (PerlIO_fast_gets(file) && PerlIO_get_cnt(file) > 0)
14702777ee89Sespie 		return 1;
14712777ee89Sespie 
14722777ee89Sespie 	/*t.tv_sec=t.tv_usec=0;*/
14732777ee89Sespie 
14742777ee89Sespie         if (delay < 0.0)
14752777ee89Sespie             delay = 0.0;
14762777ee89Sespie         t.tv_sec = (long)delay;
14772777ee89Sespie         delay -= (double)t.tv_sec;
14782777ee89Sespie         t.tv_usec = (long)(delay * 1000000.0);
14792777ee89Sespie 
14802777ee89Sespie 	FD_ZERO(&fd);
14812777ee89Sespie 	FD_SET(handle,&fd);
14822777ee89Sespie 	if(select(handle+1,(Select_fd_set_t)&fd,
14832777ee89Sespie 			   (Select_fd_set_t)0,
14842777ee89Sespie 			   (Select_fd_set_t)&fd, &t)) return -1;
14852777ee89Sespie 	else return 0;
14862777ee89Sespie }
14872777ee89Sespie 
14882777ee89Sespie #else
selectfile(pTHX_ PerlIO * file,double delay)1489*99fd0875Safresh1 int selectfile(pTHX_ PerlIO *file, double delay)
14902777ee89Sespie {
14912777ee89Sespie 	croak("select is not supported on this architecture");
14922777ee89Sespie 	return 0;
14932777ee89Sespie }
14942777ee89Sespie #endif
14952777ee89Sespie 
14962777ee89Sespie #ifdef Have_nodelay
setnodelay(pTHX_ PerlIO * file,int mode)1497*99fd0875Safresh1 int setnodelay(pTHX_ PerlIO *file, int mode)
14982777ee89Sespie {
14992777ee89Sespie 	int handle=PerlIO_fileno(file);
15002777ee89Sespie 	int flags;
15012777ee89Sespie 	flags=fcntl(handle,F_GETFL,0);
15022777ee89Sespie 	if(mode)
15032777ee89Sespie 		flags|=O_NODELAY;
15042777ee89Sespie 	else
15052777ee89Sespie 		flags&=~O_NODELAY;
15062777ee89Sespie 	fcntl(handle,F_SETFL,flags);
15072777ee89Sespie 	return 0;
15082777ee89Sespie }
15092777ee89Sespie 
15102777ee89Sespie #else
setnodelay(pTHX_ PerlIO * file,int mode)1511*99fd0875Safresh1 int setnodelay(pTHX_ PerlIO *file, int mode)
15122777ee89Sespie {
15132777ee89Sespie 	croak("setnodelay is not supported on this architecture");
15142777ee89Sespie 	return 0;
15152777ee89Sespie }
15162777ee89Sespie #endif
15172777ee89Sespie 
15182777ee89Sespie #ifdef Have_poll
pollfile(pTHX_ pTHX_ PerlIO * file,double delay)1519*99fd0875Safresh1 int pollfile(pTHX_ pTHX_ PerlIO *file,double delay)
15202777ee89Sespie {
15212777ee89Sespie 	int handle=PerlIO_fileno(file);
15222777ee89Sespie 	struct pollfd fds;
15232777ee89Sespie 	if (PerlIO_fast_gets(f) && PerlIO_get_cnt(f) > 0)
15242777ee89Sespie 		return 1;
15252777ee89Sespie 	if(delay<0.0) delay = 0.0;
15262777ee89Sespie 	fds.fd=handle;
15272777ee89Sespie 	fds.events=POLLIN;
15282777ee89Sespie 	fds.revents=0;
15292777ee89Sespie 	return (poll(&fds,1,(long)(delay * 1000.0))>0);
15302777ee89Sespie }
15312777ee89Sespie #else
pollfile(pTHX_ PerlIO * file,double delay)1532*99fd0875Safresh1 int pollfile(pTHX_ PerlIO *file,double delay)
15332777ee89Sespie {
15342777ee89Sespie 	croak("pollfile is not supported on this architecture");
15352777ee89Sespie 	return 0;
15362777ee89Sespie }
15372777ee89Sespie #endif
15382777ee89Sespie 
15392777ee89Sespie #ifdef WIN32
15402777ee89Sespie 
15412777ee89Sespie /*
15422777ee89Sespie 
15432777ee89Sespie  This portion of the Win32 code is partially borrowed from a version of PDCurses.
15442777ee89Sespie 
15452777ee89Sespie */
15462777ee89Sespie 
15472777ee89Sespie typedef struct {
15482777ee89Sespie     int repeatCount;
15492777ee89Sespie     int vKey;
15502777ee89Sespie     int vScan;
15512777ee89Sespie     int ascii;
15522777ee89Sespie     int control;
15532777ee89Sespie } win32_key_event_t;
15542777ee89Sespie 
15552777ee89Sespie #define KEY_PUSH(I, K) { events[I].repeatCount = 1; events[I].ascii = K; }
15562777ee89Sespie #define KEY_PUSH3(K1, K2, K3) \
15572777ee89Sespie     do { \
15582777ee89Sespie              eventCount = 0;            \
15592777ee89Sespie              KEY_PUSH(2, K1);           \
15602777ee89Sespie              KEY_PUSH(1, K2);           \
15612777ee89Sespie              KEY_PUSH(0, K3);           \
15622777ee89Sespie              eventCount = 3;            \
15632777ee89Sespie              goto again;                \
15642777ee89Sespie     } while (0)
15652777ee89Sespie 
15662777ee89Sespie #define KEY_PUSH4(K1, K2, K3, K4) \
15672777ee89Sespie     do { \
15682777ee89Sespie              eventCount = 0;            \
15692777ee89Sespie              KEY_PUSH(3, K1);           \
15702777ee89Sespie              KEY_PUSH(2, K2);           \
15712777ee89Sespie              KEY_PUSH(1, K3);           \
15722777ee89Sespie              KEY_PUSH(0, K4);           \
15732777ee89Sespie              eventCount = 4;            \
15742777ee89Sespie              goto again;                \
15752777ee89Sespie     } while (0)
15762777ee89Sespie 
Win32PeekChar(pTHX_ PerlIO * file,double delay,char * key)1577*99fd0875Safresh1 int Win32PeekChar(pTHX_ PerlIO *file,double delay,char *key)
15782777ee89Sespie {
15792777ee89Sespie 	int handle;
15802777ee89Sespie 	HANDLE whnd;
15812777ee89Sespie 	INPUT_RECORD record;
15822777ee89Sespie 	DWORD readRecords;
15832777ee89Sespie 
15842777ee89Sespie #if 0
15852777ee89Sespie 	static int keyCount = 0;
15862777ee89Sespie 	static char lastKey = 0;
15872777ee89Sespie #endif
15882777ee89Sespie 
15892777ee89Sespie #define MAX_EVENTS 4
15902777ee89Sespie     static int eventCount = 0;
15912777ee89Sespie     static win32_key_event_t events[MAX_EVENTS];
15922777ee89Sespie     int keyCount;
15932777ee89Sespie 
15942777ee89Sespie 	file = STDIN;
15952777ee89Sespie 
15962777ee89Sespie 	handle = PerlIO_fileno(file);
15972777ee89Sespie 	whnd = /*GetStdHandle(STD_INPUT_HANDLE)*/(HANDLE)_get_osfhandle(handle);
15982777ee89Sespie 
15992777ee89Sespie 
16002777ee89Sespie again:
16012777ee89Sespie #if 0
16022777ee89Sespie 	if (keyCount > 0) {
16032777ee89Sespie 		keyCount--;
16042777ee89Sespie 		*key = lastKey;
16052777ee89Sespie 	    return TRUE;
16062777ee89Sespie 	}
16072777ee89Sespie #endif
16082777ee89Sespie 
16092777ee89Sespie     /* printf("eventCount: %d\n", eventCount); */
16102777ee89Sespie     if (eventCount) {
16112777ee89Sespie         /* printf("key %d; repeatCount %d\n", *key, events[eventCount - 1].repeatCount); */
16122777ee89Sespie         *key = events[eventCount - 1].ascii;
16132777ee89Sespie         events[eventCount - 1].repeatCount--;
16142777ee89Sespie         if (events[eventCount - 1].repeatCount <= 0) {
16152777ee89Sespie             eventCount--;
16162777ee89Sespie         }
16172777ee89Sespie         return TRUE;
16182777ee89Sespie     }
16192777ee89Sespie 
16202777ee89Sespie 	if (delay > 0) {
1621*99fd0875Safresh1 		if (WaitForSingleObject(whnd, delay * 1000) != WAIT_OBJECT_0)
16222777ee89Sespie 		{
16232777ee89Sespie 			return FALSE;
16242777ee89Sespie 		}
16252777ee89Sespie 	}
16262777ee89Sespie 
16272777ee89Sespie 	if (delay != 0) {
16282777ee89Sespie 		PeekConsoleInput(whnd, &record, 1, &readRecords);
16292777ee89Sespie 		if (readRecords == 0) {
16302777ee89Sespie 			return(FALSE);
16312777ee89Sespie         }
16322777ee89Sespie 	}
16332777ee89Sespie 
16342777ee89Sespie 	ReadConsoleInput(whnd, &record, 1, &readRecords);
16352777ee89Sespie 	switch(record.EventType)
16362777ee89Sespie    {
16372777ee89Sespie     case KEY_EVENT:
16382777ee89Sespie 		/* printf("\nkeyDown = %d, repeat = %d, vKey = %d, vScan = %d, ASCII = %d, Control = %d\n",
16392777ee89Sespie 			record.Event.KeyEvent.bKeyDown,
16402777ee89Sespie 			record.Event.KeyEvent.wRepeatCount,
16412777ee89Sespie 			record.Event.KeyEvent.wVirtualKeyCode,
16422777ee89Sespie 			record.Event.KeyEvent.wVirtualScanCode,
16432777ee89Sespie 			record.Event.KeyEvent.uChar.AsciiChar,
16442777ee89Sespie 			record.Event.KeyEvent.dwControlKeyState); */
16452777ee89Sespie 
16462777ee89Sespie          if (record.Event.KeyEvent.bKeyDown == FALSE)
16472777ee89Sespie             goto again;                        /* throw away KeyUp events */
16482777ee89Sespie 
16492777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 38) { /* up */
16502777ee89Sespie              KEY_PUSH3(27, 91, 65);
16512777ee89Sespie          }
16522777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 40) { /* down */
16532777ee89Sespie              KEY_PUSH3(27, 91, 66);
16542777ee89Sespie          }
16552777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 39) { /* right */
16562777ee89Sespie              KEY_PUSH3(27, 91, 67);
16572777ee89Sespie          }
16582777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 37) { /* left */
16592777ee89Sespie              KEY_PUSH3(27, 91, 68);
16602777ee89Sespie          }
16612777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 33) { /* page up */
16622777ee89Sespie              KEY_PUSH3(27, 79, 121);
16632777ee89Sespie          }
16642777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 34) { /* page down */
16652777ee89Sespie              KEY_PUSH3(27, 79, 115);
16662777ee89Sespie          }
16672777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 36) { /* home */
16682777ee89Sespie              KEY_PUSH4(27, 91, 49, 126);
16692777ee89Sespie          }
16702777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 35) { /* end */
16712777ee89Sespie              KEY_PUSH4(27, 91, 52, 126);
16722777ee89Sespie          }
16732777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 45) { /* insert */
16742777ee89Sespie              KEY_PUSH4(27, 91, 50, 126);
16752777ee89Sespie          }
16762777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 46) { /* delete */
16772777ee89Sespie              KEY_PUSH4(27, 91, 51, 126);
16782777ee89Sespie          }
16792777ee89Sespie 
16802777ee89Sespie          if (record.Event.KeyEvent.wVirtualKeyCode == 16
16812777ee89Sespie          ||  record.Event.KeyEvent.wVirtualKeyCode == 17
16822777ee89Sespie          ||  record.Event.KeyEvent.wVirtualKeyCode == 18
16832777ee89Sespie          ||  record.Event.KeyEvent.wVirtualKeyCode == 20
16842777ee89Sespie          ||  record.Event.KeyEvent.wVirtualKeyCode == 144
16852777ee89Sespie          ||  record.Event.KeyEvent.wVirtualKeyCode == 145)
16862777ee89Sespie             goto again;  /* throw away shift/alt/ctrl key only key events */
16872777ee89Sespie          keyCount = record.Event.KeyEvent.wRepeatCount;
16882777ee89Sespie 		 break;
16892777ee89Sespie     default:
16902777ee89Sespie          keyCount = 0;
16912777ee89Sespie          goto again;
16922777ee89Sespie          break;
16932777ee89Sespie    }
16942777ee89Sespie 
16952777ee89Sespie  *key = record.Event.KeyEvent.uChar.AsciiChar;
16962777ee89Sespie  keyCount--;
16972777ee89Sespie 
16982777ee89Sespie  if (keyCount) {
16992777ee89Sespie      events[0].repeatCount = keyCount;
17002777ee89Sespie      events[0].ascii = *key;
17012777ee89Sespie      eventCount = 1;
17022777ee89Sespie  }
17032777ee89Sespie 
17042777ee89Sespie  return(TRUE);
17052777ee89Sespie 
17062777ee89Sespie  /* again:
17072777ee89Sespie 	return (FALSE);
17082777ee89Sespie 	*/
17092777ee89Sespie 
17102777ee89Sespie 
17112777ee89Sespie }
17122777ee89Sespie #else
Win32PeekChar(pTHX_ PerlIO * file,double delay,char * key)1713*99fd0875Safresh1 int Win32PeekChar(pTHX_ PerlIO *file, double delay,char *key)
17142777ee89Sespie {
17152777ee89Sespie 	croak("Win32PeekChar is not supported on this architecture");
17162777ee89Sespie 	return 0;
17172777ee89Sespie }
17182777ee89Sespie #endif
17192777ee89Sespie 
17202777ee89Sespie 
blockoptions()1721*99fd0875Safresh1 STATIC int blockoptions() {
17222777ee89Sespie 	return	0
17232777ee89Sespie #ifdef Have_nodelay
17242777ee89Sespie 		| 1
17252777ee89Sespie #endif
17262777ee89Sespie #ifdef Have_poll
17272777ee89Sespie 		| 2
17282777ee89Sespie #endif
17292777ee89Sespie #ifdef Have_select
17302777ee89Sespie 		| 4
17312777ee89Sespie #endif
17322777ee89Sespie #ifdef USE_WIN32
17332777ee89Sespie 		| 8
17342777ee89Sespie #endif
17352777ee89Sespie 		;
17362777ee89Sespie }
17372777ee89Sespie 
termoptions()1738*99fd0875Safresh1 STATIC int termoptions() {
17392777ee89Sespie 	int i=0;
17402777ee89Sespie #ifdef USE_TERMIOS
17412777ee89Sespie 	i=1;
17422777ee89Sespie #endif
17432777ee89Sespie #ifdef USE_TERMIO
17442777ee89Sespie 	i=2;
17452777ee89Sespie #endif
17462777ee89Sespie #ifdef USE_SGTTY
17472777ee89Sespie 	i=3;
17482777ee89Sespie #endif
17492777ee89Sespie #ifdef USE_STTY
17502777ee89Sespie 	i=4;
17512777ee89Sespie #endif
17522777ee89Sespie #ifdef USE_WIN32
17532777ee89Sespie 	i=5;
17542777ee89Sespie #endif
17552777ee89Sespie 	return i;
17562777ee89Sespie }
17572777ee89Sespie 
17582777ee89Sespie 
17592777ee89Sespie 
17602777ee89Sespie MODULE = Term::ReadKey		PACKAGE = Term::ReadKey
17612777ee89Sespie 
17622777ee89Sespie int
17632777ee89Sespie selectfile(file,delay)
17642777ee89Sespie 	InputStream	file
17652777ee89Sespie 	double	delay
1766*99fd0875Safresh1 CODE:
1767*99fd0875Safresh1 	RETVAL = selectfile(aTHX_ file, delay);
1768*99fd0875Safresh1 OUTPUT:
1769*99fd0875Safresh1 	RETVAL
17702777ee89Sespie 
17712777ee89Sespie # Clever, eh?
17722777ee89Sespie void
17732777ee89Sespie SetReadMode(mode,file=STDIN)
17742777ee89Sespie 	int	mode
17752777ee89Sespie 	InputStream	file
17762777ee89Sespie 	CODE:
17772777ee89Sespie 	{
1778*99fd0875Safresh1 		ReadMode(aTHX_ file,mode);
17792777ee89Sespie 	}
17802777ee89Sespie 
17812777ee89Sespie int
17822777ee89Sespie setnodelay(file,mode)
17832777ee89Sespie 	InputStream	file
17842777ee89Sespie 	int	mode
1785*99fd0875Safresh1 CODE:
1786*99fd0875Safresh1 	RETVAL = setnodelay(aTHX_ file, mode);
1787*99fd0875Safresh1 OUTPUT:
1788*99fd0875Safresh1 	RETVAL
17892777ee89Sespie 
17902777ee89Sespie int
17912777ee89Sespie pollfile(file,delay)
17922777ee89Sespie 	InputStream	file
17932777ee89Sespie 	double	delay
1794*99fd0875Safresh1 CODE:
1795*99fd0875Safresh1 	RETVAL = pollfile(aTHX_ file, delay);
1796*99fd0875Safresh1 OUTPUT:
1797*99fd0875Safresh1 	RETVAL
17982777ee89Sespie 
17992777ee89Sespie SV *
Win32PeekChar(file,delay)18002777ee89Sespie Win32PeekChar(file, delay)
18012777ee89Sespie 	InputStream	file
18022777ee89Sespie 	double	delay
18032777ee89Sespie 	CODE:
18042777ee89Sespie 	{
18052777ee89Sespie 		char key;
1806*99fd0875Safresh1 		if (Win32PeekChar(aTHX_ file, delay, &key))
18072777ee89Sespie 			RETVAL = newSVpv(&key, 1);
18082777ee89Sespie 		else
18092777ee89Sespie 			RETVAL = newSVsv(&PL_sv_undef);
18102777ee89Sespie 	}
18112777ee89Sespie 	OUTPUT:
18122777ee89Sespie 	RETVAL
18132777ee89Sespie 
18142777ee89Sespie int
blockoptions()18152777ee89Sespie blockoptions()
18162777ee89Sespie 
18172777ee89Sespie int
18182777ee89Sespie termoptions()
18192777ee89Sespie 
18202777ee89Sespie int
18212777ee89Sespie termsizeoptions()
18222777ee89Sespie 
18232777ee89Sespie void
18242777ee89Sespie GetTermSizeWin32(file=STDIN)
18252777ee89Sespie 	InputStream	file
18262777ee89Sespie 	PPCODE:
18272777ee89Sespie 	{
18282777ee89Sespie 		int x,y,xpix,ypix;
1829*99fd0875Safresh1 		if( GetTermSizeWin32(aTHX_ file,&x,&y,&xpix,&ypix)==0)
18302777ee89Sespie 		{
18312777ee89Sespie 			EXTEND(sp, 4);
18322777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)x)));
18332777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)y)));
18342777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)xpix)));
18352777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)ypix)));
18362777ee89Sespie 		}
18372777ee89Sespie 		else
18382777ee89Sespie 		{
18392777ee89Sespie 			ST(0) = sv_newmortal();
18402777ee89Sespie 		}
18412777ee89Sespie 	}
18422777ee89Sespie 
18432777ee89Sespie void
18442777ee89Sespie GetTermSizeVIO(file=STDIN)
18452777ee89Sespie 	InputStream	file
18462777ee89Sespie 	PPCODE:
18472777ee89Sespie 	{
18482777ee89Sespie 		int x,y,xpix,ypix;
1849*99fd0875Safresh1 		if( GetTermSizeVIO(aTHX_ file,&x,&y,&xpix,&ypix)==0)
18502777ee89Sespie 		{
18512777ee89Sespie 			EXTEND(sp, 4);
18522777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)x)));
18532777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)y)));
18542777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)xpix)));
18552777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)ypix)));
18562777ee89Sespie 		}
18572777ee89Sespie 		else
18582777ee89Sespie 		{
18592777ee89Sespie 			ST(0) = sv_newmortal();
18602777ee89Sespie 		}
18612777ee89Sespie 	}
18622777ee89Sespie 
18632777ee89Sespie void
18642777ee89Sespie GetTermSizeGWINSZ(file=STDIN)
18652777ee89Sespie 	InputStream	file
18662777ee89Sespie 	PPCODE:
18672777ee89Sespie 	{
18682777ee89Sespie 		int x,y,xpix,ypix;
1869*99fd0875Safresh1 		if( GetTermSizeGWINSZ(aTHX_ file,&x,&y,&xpix,&ypix)==0)
18702777ee89Sespie 		{
18712777ee89Sespie 			EXTEND(sp, 4);
18722777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)x)));
18732777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)y)));
18742777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)xpix)));
18752777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)ypix)));
18762777ee89Sespie 		}
18772777ee89Sespie 		else
18782777ee89Sespie 		{
18792777ee89Sespie 			ST(0) = sv_newmortal();
18802777ee89Sespie 		}
18812777ee89Sespie 	}
18822777ee89Sespie 
18832777ee89Sespie void
18842777ee89Sespie GetTermSizeGSIZE(file=STDIN)
18852777ee89Sespie 	InputStream	file
18862777ee89Sespie 	PPCODE:
18872777ee89Sespie 	{
18882777ee89Sespie 		int x,y,xpix,ypix;
1889*99fd0875Safresh1 		if( GetTermSizeGSIZE(aTHX_ file,&x,&y,&xpix,&ypix)==0)
18902777ee89Sespie 		{
18912777ee89Sespie 			EXTEND(sp, 4);
18922777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)x)));
18932777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)y)));
18942777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)xpix)));
18952777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)ypix)));
18962777ee89Sespie 		}
18972777ee89Sespie 		else
18982777ee89Sespie 		{
18992777ee89Sespie 			ST(0) = sv_newmortal();
19002777ee89Sespie 		}
19012777ee89Sespie 	}
19022777ee89Sespie 
19032777ee89Sespie int
19042777ee89Sespie SetTerminalSize(width,height,xpix,ypix,file=STDIN)
19052777ee89Sespie 	int	width
19062777ee89Sespie 	int	height
19072777ee89Sespie 	int	xpix
19082777ee89Sespie 	int	ypix
19092777ee89Sespie 	InputStream	file
19102777ee89Sespie 	CODE:
19112777ee89Sespie 	{
1912*99fd0875Safresh1 		RETVAL=SetTerminalSize(aTHX_ file,width,height,xpix,ypix);
19132777ee89Sespie 	}
19142777ee89Sespie 	OUTPUT:
19152777ee89Sespie 		RETVAL
19162777ee89Sespie 
19172777ee89Sespie void
19182777ee89Sespie GetSpeed(file=STDIN)
19192777ee89Sespie 	InputStream	file
19202777ee89Sespie 	PPCODE:
19212777ee89Sespie 	{
19222777ee89Sespie 		I32 in,out;
1923*99fd0875Safresh1 /*
1924*99fd0875Safresh1  *    experimentally relaxed for
1925*99fd0875Safresh1  *    https://rt.cpan.org/Ticket/Display.html?id=88050
19262777ee89Sespie 		if(items!=0) {
19272777ee89Sespie 			croak("Usage: Term::ReadKey::GetSpeed()");
19282777ee89Sespie 		}
1929*99fd0875Safresh1 */
1930*99fd0875Safresh1 		if(getspeed(aTHX_ file,&in,&out)) {
19312777ee89Sespie 			/* Failure */
19322777ee89Sespie 			ST( 0) = sv_newmortal();
19332777ee89Sespie 		} else {
19342777ee89Sespie 			EXTEND(sp, 2);
19352777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)in)));
19362777ee89Sespie 			PUSHs(sv_2mortal(newSViv((IV)out)));
19372777ee89Sespie 		}
19382777ee89Sespie 	}
19392777ee89Sespie 
19402777ee89Sespie 
19412777ee89Sespie 
19422777ee89Sespie BOOT:
19432777ee89Sespie newXS("Term::ReadKey::GetControlChars", XS_Term__ReadKey_GetControlChars, file);
19442777ee89Sespie newXS("Term::ReadKey::SetControlChars", XS_Term__ReadKey_SetControlChars, file);
19452777ee89Sespie filehash=newHV();
19462777ee89Sespie modehash=newHV();
1947