summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--minislang/Makefile15
-rw-r--r--minislang/_slang.h598
-rw-r--r--minislang/config.h113
-rw-r--r--minislang/jdmacros.h76
-rw-r--r--minislang/sl-feat.h18
-rw-r--r--minislang/slang.h1547
-rw-r--r--minislang/sldisply.c2313
-rw-r--r--minislang/slerr.c182
-rw-r--r--minislang/slgetkey.c270
-rw-r--r--minislang/sllimits.h65
-rw-r--r--minislang/slmisc.c256
-rw-r--r--minislang/slsignal.c346
-rw-r--r--minislang/slsmg.c1395
-rw-r--r--minislang/sltermin.c1128
-rw-r--r--minislang/slutty.c595
15 files changed, 8917 insertions, 0 deletions
diff --git a/minislang/Makefile b/minislang/Makefile
new file mode 100644
index 000000000..282d12a85
--- /dev/null
+++ b/minislang/Makefile
@@ -0,0 +1,15 @@
+OBJS = sldisply.o slerr.o slgetkey.o slmisc.o slsignal.o slsmg.o \
+ sltermin.o slutty.o
+
+CFLAGS = -fPIC
+
+all: libslang.so
+
+libslang.so: $(OBJS)
+ gcc -o $@ -shared -Wl,-soname,libslang.so.1 $(OBJS)
+
+clean:
+ rm -f *.o libslang.so
+
+install: libslang.so
+ install -s libslang.so $(DESTDIR)/usr/lib/libslang.so.1
diff --git a/minislang/_slang.h b/minislang/_slang.h
new file mode 100644
index 000000000..2474c9f7b
--- /dev/null
+++ b/minislang/_slang.h
@@ -0,0 +1,598 @@
+/* header file for S-Lang internal structures that users do not (should not)
+ need. Use slang.h for that purpose. */
+/* Copyright (c) 1992, 1998 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 "config.h"
+
+#include <string.h>
+
+#include "jdmacros.h"
+#include "sllimits.h"
+
+#ifdef VMS
+# define SLANG_SYSTEM_NAME "_VMS"
+#else
+# if defined (IBMPC_SYSTEM)
+# define SLANG_SYSTEM_NAME "_IBMPC"
+# else
+# define SLANG_SYSTEM_NAME "_UNIX"
+# endif
+#endif /* VMS */
+
+
+/* These quantities are main_types for byte-compiled code. They are used
+ * by the inner_interp routine. The _BC_ means byte-code.
+ */
+
+#define _SLANG_BC_LVARIABLE SLANG_LVARIABLE
+#define _SLANG_BC_GVARIABLE SLANG_GVARIABLE
+#define _SLANG_BC_IVARIABLE SLANG_IVARIABLE
+#define _SLANG_BC_RVARIABLE SLANG_RVARIABLE
+#define _SLANG_BC_INTRINSIC SLANG_INTRINSIC
+#define _SLANG_BC_FUNCTION SLANG_FUNCTION
+#define _SLANG_BC_MATH_UNARY SLANG_MATH_UNARY
+#define _SLANG_BC_APP_UNARY SLANG_APP_UNARY
+
+#define _SLANG_BC_BINARY 0x10
+#define _SLANG_BC_LITERAL 0x11 /* constant objects */
+#define _SLANG_BC_LITERAL_INT 0x12
+#define _SLANG_BC_LITERAL_STR 0x13
+#define _SLANG_BC_BLOCK 0x14
+
+/* These 3 MUST be in this order too ! */
+#define _SLANG_BC_RETURN 0x15
+#define _SLANG_BC_BREAK 0x16
+#define _SLANG_BC_CONTINUE 0x17
+
+#define _SLANG_BC_EXCH 0x18
+#define _SLANG_BC_LABEL 0x19
+#define _SLANG_BC_LOBJPTR 0x1A
+#define _SLANG_BC_GOBJPTR 0x1B
+#define _SLANG_BC_X_ERROR 0x1C
+/* These must be in this order */
+#define _SLANG_BC_X_USER0 0x1D
+#define _SLANG_BC_X_USER1 0x1E
+#define _SLANG_BC_X_USER2 0x1F
+#define _SLANG_BC_X_USER3 0x20
+#define _SLANG_BC_X_USER4 0x21
+
+#define _SLANG_BC_ARGS_END_DIRECTIVE 0x22
+#define _SLANG_BC_ARGS_START_DIRECTIVE 0x23
+#define _SLANG_BC_CALL_DIRECT 0x24
+#define _SLANG_BC_CALL_DIRECT_FRAME 0x25
+#define _SLANG_BC_UNARY 0x26
+
+
+#define _SLANG_BC_DEREF_ASSIGN 0x30
+#define _SLANG_BC_SET_LOCAL_LVALUE 0x31
+#define _SLANG_BC_SET_GLOBAL_LVALUE 0x32
+#define _SLANG_BC_SET_INTRIN_LVALUE 0x33
+#define _SLANG_BC_SET_STRUCT_LVALUE 0x34
+#define _SLANG_BC_FIELD 0x35
+
+#define _SLANG_BC_LINE_NUM 0x40
+
+/* Byte-Code Sub Types (_BCST_) */
+
+/* These are sub_types of _SLANG_BC_BLOCK */
+#define _SLANG_BCST_ERROR_BLOCK 0x01
+#define _SLANG_BCST_EXIT_BLOCK 0x02
+#define _SLANG_BCST_USER_BLOCK0 0x03
+#define _SLANG_BCST_USER_BLOCK1 0x04
+#define _SLANG_BCST_USER_BLOCK2 0x05
+#define _SLANG_BCST_USER_BLOCK3 0x06
+#define _SLANG_BCST_USER_BLOCK4 0x07
+/* The user blocks MUST be in the above order */
+#define _SLANG_BCST_LOOP 0x10
+#define _SLANG_BCST_WHILE 0x11
+#define _SLANG_BCST_FOR 0x12
+#define _SLANG_BCST_FOREVER 0x13
+#define _SLANG_BCST_CFOR 0x14
+#define _SLANG_BCST_DOWHILE 0x15
+#define _SLANG_BCST_IF 0x20
+#define _SLANG_BCST_IFNOT 0x21
+#define _SLANG_BCST_ELSE 0x22
+#define _SLANG_BCST_ANDELSE 0x23
+#define _SLANG_BCST_ORELSE 0x24
+#define _SLANG_BCST_SWITCH 0x25
+
+/* assignment (_SLANG_BC_SET_*_LVALUE) subtypes. The order MUST correspond
+ * to the assignment token order with the ASSIGN_TOKEN as the first!
+ */
+#define _SLANG_BCST_ASSIGN 0x01
+#define _SLANG_BCST_PLUSEQS 0x02
+#define _SLANG_BCST_MINUSEQS 0x03
+#define _SLANG_BCST_PLUSPLUS 0x04
+#define _SLANG_BCST_POST_PLUSPLUS 0x05
+#define _SLANG_BCST_MINUSMINUS 0x06
+#define _SLANG_BCST_POST_MINUSMINUS 0x07
+
+
+/* These use SLANG_PLUS, SLANG_MINUS, SLANG_PLUSPLUS, etc... */
+
+
+typedef union
+{
+ long l_val;
+ VOID_STAR p_val;
+ char *s_val;
+ int i_val;
+ SLang_MMT_Type *ref;
+ SLang_Name_Type *n_val;
+#if SLANG_HAS_FLOAT
+ double f_val;
+#endif
+ struct _SLang_Struct_Type *struct_val;
+ struct _SLang_Array_Type *array_val;
+}
+_SL_Object_Union_Type;
+
+typedef struct
+{
+ unsigned char data_type; /* SLANG_INT_TYPE, ... */
+ _SL_Object_Union_Type v;
+}
+SLang_Object_Type;
+
+
+struct _SLang_MMT_Type
+{
+ unsigned char data_type; /* int, string, etc... */
+ VOID_STAR user_data; /* address of user structure */
+ unsigned int count; /* number of references */
+};
+
+extern int _SLang_pop_object_of_type (unsigned char, SLang_Object_Type *);
+
+
+typedef struct
+{
+ char *name; /* slstring */
+ SLang_Object_Type obj;
+}
+_SLstruct_Field_Type;
+
+typedef struct _SLang_Struct_Type
+{
+ _SLstruct_Field_Type *fields;
+ unsigned int nfields; /* number used */
+ unsigned int num_refs;
+}
+_SLang_Struct_Type;
+
+extern void _SLstruct_delete_struct (_SLang_Struct_Type *);
+extern int _SLang_push_struct (_SLang_Struct_Type *);
+extern int _SLang_pop_struct (_SLang_Struct_Type **);
+extern int _SLstruct_init (void);
+extern SLang_Object_Type *_SLstruct_get_assign_obj (char *);
+extern int _SLstruct_get_field (char *);
+extern int _SLstruct_define_struct (void);
+extern int _SLstruct_define_typedef (void);
+extern int _SLstruct_create_struct (unsigned int,
+ char **,
+ unsigned char *,
+ VOID_STAR *);
+
+extern int _SLang_push_void_star (unsigned char, VOID_STAR);
+extern int _SLang_push_i_val (unsigned char, int);
+extern int _SLang_pop_i_val (unsigned char, int *);
+
+extern int _SLang_pop_datatype (unsigned char *);
+extern int _SLang_push_datatype (unsigned char);
+
+
+struct _SLang_Ref_Type
+{
+ int is_global;
+ union
+ {
+ SLang_Name_Type *nt;
+ SLang_Object_Type *local_obj;
+ }
+ v;
+};
+
+extern int _SLang_dereference_ref (SLang_Ref_Type *);
+extern int _SLang_deref_assign (SLang_Ref_Type *);
+extern int _SLang_push_ref (int, VOID_STAR);
+
+extern SLang_Object_Type *_SLStack_Pointer;
+extern int SLang_pop(SLang_Object_Type *);
+extern void SLang_free_object (SLang_Object_Type *);
+
+extern int _SLpush_slang_obj (SLang_Object_Type *);
+
+extern char *_SLexpand_escaped_char(char *, char *);
+extern void _SLexpand_escaped_string (char *, char *, char *);
+
+extern int _SLreverse_stack (int);
+extern int _SLroll_stack (int);
+/* If argument *p is positive, the top |*p| objects on the stack are rolled
+ * up. If negative, the stack is rolled down.
+ */
+
+extern int _SLang_apropos (char *, unsigned int);
+
+/* returns a pointer to an SLstring string-- use SLang_free_slstring */
+extern char *_SLstringize_object (SLang_Object_Type *);
+extern int _SLdump_objects (char *, SLang_Object_Type *, unsigned int, int);
+
+extern int _SLarray_aput (void);
+extern int _SLarray_aget (void);
+extern int _SLarray_inline_implicit_array (void);
+extern int _SLarray_inline_array (void);
+extern int
+_SLarray_typecast (unsigned char, VOID_STAR, unsigned int,
+ unsigned char, VOID_STAR, int);
+
+
+extern SLang_Object_Type *_SLRun_Stack;
+extern SLang_Object_Type *_SLStack_Pointer;
+
+extern int _SLang_Trace;
+extern int _SLstack_depth(void);
+extern char *_SLang_Current_Function_Name;
+
+extern int _SLang_trace_fun(char *);
+extern int _SLang_Compile_Line_Num_Info;
+
+extern char *_SLstring_dup_hashed_string (char *, unsigned long);
+extern unsigned long _SLcompute_string_hash (char *);
+extern char *_SLstring_make_hashed_string (char *, unsigned int, unsigned long *);
+extern void _SLfree_hashed_string (char *, unsigned int, unsigned long);
+unsigned long _SLstring_hash (unsigned char *, unsigned char *);
+extern int _SLinit_slcomplex (void);
+
+/* frees upon error. NULL __NOT__ ok. */
+extern int _SLang_push_slstring (char *);
+
+extern int SLang_push(SLang_Object_Type *);
+extern int SLadd_global_variable (char *);
+extern void _SLang_clear_error (void);
+
+extern int _SLdo_pop (void);
+extern unsigned int _SLsys_getkey (void);
+extern int _SLsys_input_pending (int);
+#ifdef IBMPC_SYSTEM
+extern unsigned int _SLpc_convert_scancode (unsigned int);
+#endif
+#ifdef REAL_UNIX_SYSTEM
+extern int SLtt_tigetflag (char *, char **);
+extern int SLtt_tigetnum (char *, char **);
+extern char *SLtt_tigetstr (char *, char **);
+extern char *SLtt_tigetent (char *);
+#endif
+
+extern unsigned char SLang_Input_Buffer [SL_MAX_INPUT_BUFFER_LEN];
+
+extern int _SLregister_types (void);
+extern SLang_Class_Type *_SLclass_get_class (unsigned char);
+extern VOID_STAR _SLclass_get_ptr_to_value (SLang_Class_Type *, SLang_Object_Type *);
+extern void _SLclass_type_mismatch_error (unsigned char, unsigned char);
+extern int _SLclass_init (void);
+extern int _SLclass_typecast (unsigned char, int, int);
+
+extern unsigned char _SLclass_Class_Type [256];
+
+extern int (*_SLclass_get_typecast (unsigned char, unsigned char, int))
+(unsigned char, VOID_STAR, unsigned int,
+ unsigned char, VOID_STAR);
+
+extern int (*_SLclass_get_binary_fun (int, SLang_Class_Type *, SLang_Class_Type *, SLang_Class_Type **))
+(int,
+ unsigned char, VOID_STAR, unsigned int,
+ unsigned char, VOID_STAR, unsigned int,
+ VOID_STAR);
+
+extern int (*_SLclass_get_unary_fun (int, SLang_Class_Type *, SLang_Class_Type **, int))
+(int, unsigned char, VOID_STAR, unsigned int, VOID_STAR);
+
+extern int _SLarray_add_bin_op (unsigned char type);
+
+extern int _SLang_call_funptr (SLang_Name_Type *);
+extern void _SLset_double_format (char *);
+
+extern char *_SLdefines[];
+
+
+extern int _SLerrno_errno;
+extern int _SLerrno_init (void);
+
+typedef struct _SLang_Array_Type
+{
+ unsigned char data_type;
+ unsigned int sizeof_type;
+ VOID_STAR data;
+ unsigned int num_elements;
+ unsigned int num_dims;
+ int dims [SLARRAY_MAX_DIMS];
+ VOID_STAR (*index_fun)_PROTO((struct _SLang_Array_Type *, int *));
+ /* This function is designed to allow a type to store an array in
+ * any manner it chooses. This function returns the address of the data
+ * value at the specified index location.
+ */
+ unsigned int flags;
+#define DATA_VALUE_IS_READ_ONLY 1
+#define DATA_VALUE_IS_POINTER 2
+#define DATA_VALUE_IS_RANGE 4
+#define DATA_VALUE_IS_INTRINSIC 8
+ SLang_Class_Type *cl;
+ unsigned int num_refs;
+}
+SLang_Array_Type;
+
+extern int SLang_pop_array (SLang_Array_Type **, int);
+extern int SLang_push_array (SLang_Array_Type *, int);
+extern void SLang_free_array (SLang_Array_Type *);
+extern int _SLarray_init_slarray (void);
+extern SLang_Array_Type *SLang_create_array (unsigned char, int, VOID_STAR, int *, unsigned int);
+
+extern int _SLcompile_push_context (void);
+extern int _SLcompile_pop_context (void);
+extern int _SLang_Auto_Declare_Globals;
+
+#if 1
+typedef struct
+{
+ unsigned char type;
+ union
+ {
+ int i_val;
+ char *s_val; /* Used for IDENT_TOKEN, FLOAT, etc... */
+ } v;
+ int free_sval_flag;
+ unsigned int num_refs;
+ unsigned long hash;
+#if _SLANG_HAS_DEBUG_CODE
+ int line_number;
+#endif
+}
+_SLang_Token_Type;
+
+extern void _SLcompile (_SLang_Token_Type *);
+extern void (*_SLcompile_ptr)(_SLang_Token_Type *);
+
+/* *** TOKENS *** */
+
+/* If value of any token is changed, the following arrays must be also modified
+ * Variable File
+ * ---------------------------------
+ * Reserved_Keywords_Type sltoken.c
+ * Ops_Type sltoken.c
+ * Comp_Func_Index slang.c
+ * Op_Types slang.c
+ * Directives_Type slang.c
+ */
+
+/* Note that that tokens corresponding to ^J, ^M, and ^Z should not be used.
+ * This is because a file that contains any of these characters will
+ * have an OS dependent interpretation, e.g., ^Z is EOF on MSDOS.
+ */
+
+/* Special tokens */
+#define EOF_TOKEN 0x01
+#define RPN_TOKEN 0x02
+#define NL_TOKEN 0x03
+#define NOP_TOKEN 0x05
+#define FARG_TOKEN 0x06
+
+#define RESERVED1_TOKEN 0x0A /* \n */
+#define RESERVED2_TOKEN 0x0D /* \r */
+
+/* Literal tokens */
+#define INT_TOKEN 0x10
+#define DOUBLE_TOKEN 0x11
+#define CHAR_TOKEN 0x12
+#define STRING_TOKEN 0x13
+#define COMPLEX_TOKEN 0x14
+#define ESC_STRING_TOKEN 0x15
+#define RESERVED3_TOKEN 0x1A /* ^Z */
+
+/* Tokens that can be LVALUES */
+#define IDENT_TOKEN 0x20
+#define ARRAY_TOKEN 0x21
+#define DOT_TOKEN 0x22
+#define IS_LVALUE_TOKEN (((t) <= DOT_TOKEN) && ((t) >= IDENT_TOKEN))
+
+/* do not use these values */
+#define RESERVED4_TOKEN 0x23
+#define RESERVED5_TOKEN 0x25
+
+/* Flags for struct fields */
+#define STATIC_TOKEN 0x26
+#define READONLY_TOKEN 0x27
+
+/* Punctuation tokens */
+#define OBRACKET_TOKEN 0x2a
+#define CBRACKET_TOKEN 0x2b
+#define OPAREN_TOKEN 0x2c
+#define CPAREN_TOKEN 0x2d
+#define OBRACE_TOKEN 0x2e
+#define CBRACE_TOKEN 0x2f
+#define POUND_TOKEN 0x30
+#define COMMA_TOKEN 0x31
+#define SEMICOLON_TOKEN 0x32
+#define COLON_TOKEN 0x33
+
+/* Operators */
+#define POW_TOKEN 0x38
+
+/* The order of the binary operators must match those in the
+ * binary_name_table in sltoken.c
+ */
+#define FIRST_BINARY_OP 0x39
+#define ADD_TOKEN 0x39
+#define SUB_TOKEN 0x3a
+#define MUL_TOKEN 0x3b
+#define DIV_TOKEN 0x3c
+#define LT_TOKEN 0x3d
+#define LE_TOKEN 0x3e
+#define GT_TOKEN 0x3f
+#define GE_TOKEN 0x40
+#define EQ_TOKEN 0x41
+#define NE_TOKEN 0x42
+#define AND_TOKEN 0x43
+#define OR_TOKEN 0x44
+#define MOD_TOKEN 0x45
+#define BAND_TOKEN 0x46
+#define SHL_TOKEN 0x47
+#define SHR_TOKEN 0x48
+#define BXOR_TOKEN 0x49
+#define BOR_TOKEN 0x4a
+#define LAST_BINARY_OP 0x4a
+#define IS_BINARY_OP(t) ((t >= FIRST_BINARY_OP) && (t <= LAST_BINARY_OP))
+
+/* unary tokens -- but not all of them (see grammar) */
+#define DEREF_TOKEN 0x4d
+#define NOT_TOKEN 0x4e
+#define BNOT_TOKEN 0x4f
+
+#define IS_INTERNAL_FUNC(t) ((t >= 0x50) && (t <= 0x56))
+#define POP_TOKEN 0x50
+#define CHS_TOKEN 0x51
+#define SIGN_TOKEN 0x52
+#define ABS_TOKEN 0x53
+#define SQR_TOKEN 0x54
+#define MUL2_TOKEN 0x55
+#define EXCH_TOKEN 0x56
+
+/* Assignment tokens. Note: these must appear with sequential values.
+ * The order here must match the specific lvalue assignments below.
+ * These tokens are used by rpn routines in slang.c. slparse.c maps them
+ * onto the specific lvalue tokens while parsing infix.
+ * Also the assignment _SLANG_BCST_ assumes this order
+ */
+#define ASSIGN_TOKEN 0x57
+#define PLUSEQS_TOKEN 0x58
+#define MINUSEQS_TOKEN 0x59
+#define PLUSPLUS_TOKEN 0x5A
+#define POST_PLUSPLUS_TOKEN 0x5B
+#define MINUSMINUS_TOKEN 0x5C
+#define POST_MINUSMINUS_TOKEN 0x5D
+#define IS_ASSIGNMENT_TOKEN(t) (((t) >= 0x57) && ((t) <= 0x5D))
+
+/* Directives */
+#define IS_BDIRECTIVE_TOKEN(t) ((t >= 0x61) && (t <= 0x73))
+#define FIRST_DIRECTIVE_TOKEN 0x61
+#define IFNOT_TOKEN 0x61
+#define IF_TOKEN 0x62
+#define ELSE_TOKEN 0x63
+#define FOREVER_TOKEN 0x64
+#define WHILE_TOKEN 0x65
+#define FOR_TOKEN 0x66
+#define _FOR_TOKEN 0x67
+#define LOOP_TOKEN 0x68
+#define SWITCH_TOKEN 0x69
+#define DOWHILE_TOKEN 0x6a
+#define ANDELSE_TOKEN 0x6b
+#define ORELSE_TOKEN 0x6c
+#define ERRBLK_TOKEN 0x6d
+#define EXITBLK_TOKEN 0x6e
+/* These must be sequential */
+#define USRBLK0_TOKEN 0x6f
+#define USRBLK1_TOKEN 0x70
+#define USRBLK2_TOKEN 0x71
+#define USRBLK3_TOKEN 0x72
+#define USRBLK4_TOKEN 0x73
+
+#define CONT_TOKEN 0x74
+#define BREAK_TOKEN 0x75
+#define RETURN_TOKEN 0x76
+
+#define CASE_TOKEN 0x78
+#define DEFINE_TOKEN 0x79
+#define DO_TOKEN 0x7a
+#define VARIABLE_TOKEN 0x7b
+#define GVARIABLE_TOKEN 0x7c
+#define _REF_TOKEN 0x7d
+#define PUSH_TOKEN 0x7e
+#define STRUCT_TOKEN 0x7f
+#define TYPEDEF_TOKEN 0x80
+
+/* Note: the order here must match the order of the assignment tokens.
+ * Also, the first token of each group must be the ?_ASSIGN_TOKEN.
+ * slparse.c exploits this order, as well as slang.h.
+ */
+#define _STRUCT_ASSIGN_TOKEN 0x91
+#define _STRUCT_PLUSEQS_TOKEN 0x92
+#define _STRUCT_MINUSEQS_TOKEN 0x93
+#define _STRUCT_PLUSPLUS_TOKEN 0x94
+#define _STRUCT_POST_PLUSPLUS_TOKEN 0x95
+#define _STRUCT_MINUSMINUS_TOKEN 0x96
+#define _STRUCT_POST_MINUSMINUS_TOKEN 0x97
+
+#define _ARRAY_ASSIGN_TOKEN 0x98
+#define _ARRAY_PLUSEQS_TOKEN 0x99
+#define _ARRAY_MINUSEQS_TOKEN 0x9A
+#define _ARRAY_PLUSPLUS_TOKEN 0x9B
+#define _ARRAY_POST_PLUSPLUS_TOKEN 0x9C
+#define _ARRAY_MINUSMINUS_TOKEN 0x9D
+#define _ARRAY_POST_MINUSMINUS_TOKEN 0x9E
+
+#define _SCALAR_ASSIGN_TOKEN 0x9F
+#define _SCALAR_PLUSEQS_TOKEN 0xA0
+#define _SCALAR_MINUSEQS_TOKEN 0xA1
+#define _SCALAR_PLUSPLUS_TOKEN 0xA2
+#define _SCALAR_POST_PLUSPLUS_TOKEN 0xA3
+#define _SCALAR_MINUSMINUS_TOKEN 0xA4
+#define _SCALAR_POST_MINUSMINUS_TOKEN 0xA5
+
+#define _DEREF_ASSIGN_TOKEN 0xA6
+
+#define _INLINE_ARRAY_TOKEN 0xE0
+#define _INLINE_IMPLICIT_ARRAY_TOKEN 0xE1
+#define _NULL_TOKEN 0xE2
+
+#define LINE_NUM_TOKEN 0xFC
+#define ARG_TOKEN 0xFD
+#define EARG_TOKEN 0xFE
+#define NO_OP_LITERAL 0xFF
+
+typedef struct
+{
+ /* sltoken.c */
+ /* SLang_eval_object */
+ SLang_Load_Type *llt;
+ SLPreprocess_Type *this_slpp;
+ /* prep_get_char() */
+ char *input_line;
+ char cchar;
+ /* get_token() */
+ int want_nl_token;
+
+ /* slparse.c */
+ _SLang_Token_Type ctok;
+ int block_depth;
+ int assignment_expression;
+
+ /* slang.c : SLcompile() */
+ _SLang_Token_Type save_token;
+ _SLang_Token_Type next_token;
+ void (*slcompile_ptr)(_SLang_Token_Type *);
+}
+_SLEval_Context;
+
+extern int _SLget_token (_SLang_Token_Type *);
+extern void _SLparse_error (char *, _SLang_Token_Type *, int);
+extern void _SLparse_start (SLang_Load_Type *);
+extern int _SLget_rpn_token (_SLang_Token_Type *);
+extern void _SLcompile_byte_compiled (void);
+
+#ifdef HAVE_VSNPRINTF
+#define _SLvsnprintf vsnprintf
+#else
+extern int _SLvsnprintf (char *, unsigned int, char *, va_list);
+#endif
+
+#ifdef HAVE_SNPRINTF
+#define _SLsnprintf snprintf
+#else
+extern int _SLsnprintf (char *, unsigned int, char *, ...);
+#endif
+
+#endif
diff --git a/minislang/config.h b/minislang/config.h
new file mode 100644
index 000000000..14f8552c3
--- /dev/null
+++ b/minislang/config.h
@@ -0,0 +1,113 @@
+/* src/sysconf.h. Generated automatically by configure. */
+/* -*- c -*- */
+/* Note: this is for unix only. */
+
+#ifndef SL_CONFIG_H
+#define SL_CONFIG_H
+
+/* define if you have stdlib.h */
+#define HAVE_STDLIB_H 1
+
+/* define if you have unistd.h */
+#define HAVE_UNISTD_H 1
+
+/* define if you have termios.h */
+#define HAVE_TERMIOS_H 1
+
+/* define if you have memory.h */
+#define HAVE_MEMORY_H 1
+
+/* define if you have malloc.h */
+#define HAVE_MALLOC_H 1
+
+/* define if you have memset */
+#define HAVE_MEMSET 1
+
+/* define if you have memcpy */
+#define HAVE_MEMCPY 1
+
+#define HAVE_VFSCANF 1
+
+/* define if you have fcntl.h */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the vsnprintf, snprintf functions and they return
+ * EOF upon failure.
+ */
+#define HAVE_VSNPRINTF 1
+#define HAVE_SNPRINTF 1
+
+/* define if you have sys/fcntl.h */
+#define HAVE_SYS_FCNTL_H 1
+
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_WAIT_H 1
+
+/* define if you have this. */
+#define HAVE_PUTENV 1
+#define HAVE_GETCWD 1
+#define HAVE_TCGETATTR 1
+#define HAVE_TCSETATTR 1
+#define HAVE_CFGETOSPEED 1
+#define HAVE_LSTAT 1
+#define HAVE_KILL 1
+#define HAVE_CHOWN 1
+#define HAVE_VSNPRINTF 1
+
+/* #undef USE_TERMCAP */
+
+/* #undef mode_t */
+/* #undef uid_t */
+/* #undef pid_t */
+/* #undef gid_t */
+
+/* Do we have posix signals? */
+#define HAVE_SIGACTION 1
+#define HAVE_SIGPROCMASK 1
+#define HAVE_SIGEMPTYSET 1
+#define HAVE_SIGADDSET 1
+
+#if defined(HAVE_SIGADDSET) && defined(HAVE_SIGEMPTYSET)
+# if defined(HAVE_SIGACTION) && defined(HAVE_SIGPROCMASK)
+# define SLANG_POSIX_SIGNALS
+# endif
+#endif
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+#ifdef _AIX
+# ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE 1
+# endif
+# ifndef _ALL_SOURCE
+# define _ALL_SOURCE
+# endif
+/* This may generate warnings but the fact is that without it, xlc will
+ * INCORRECTLY inline many str* functions. */
+/* # undef __STR__ */
+#endif
+
+/* define USE_TERMCAP if you want to use it instead of terminfo. */
+#if defined(sequent) || defined(NeXT)
+# ifndef USE_TERMCAP
+# define USE_TERMCAP
+# endif
+#endif
+
+#if defined(ultrix) && !defined(__GNUC__)
+# ifndef NO_PROTOTYPES
+# define NO_PROTOTYPES
+# endif
+#endif
+
+#ifndef unix
+# define unix 1
+#endif
+
+#ifndef __unix__
+# define __unix__ 1
+#endif
+
+#define _SLANG_SOURCE_ 1
+#endif /* SL_CONFIG_H */
diff --git a/minislang/jdmacros.h b/minislang/jdmacros.h
new file mode 100644
index 000000000..b80a263b0
--- /dev/null
+++ b/minislang/jdmacros.h
@@ -0,0 +1,76 @@
+#ifndef _JD_MACROS_H_
+#define _JD_MACROS_H_
+
+/* This file defines some macros that I use with programs that link to
+ * the slang library.
+ */
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_MALLOC_H
+# include <malloc.h>
+#endif
+
+#ifdef HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#ifndef SLMEMSET
+# ifdef HAVE_MEMSET
+# define SLMEMSET memset
+# else
+# define SLMEMSET SLmemset
+# endif
+#endif
+
+#ifndef SLMEMCHR
+# ifdef HAVE_MEMCHR
+# define SLMEMCHR memchr
+# else
+# define SLMEMCHR SLmemchr
+# endif
+#endif
+
+#ifndef SLMEMCPY
+# ifdef HAVE_MEMCPY
+# define SLMEMCPY memcpy
+# else
+# define SLMEMCPY SLmemcpy
+# endif
+#endif
+
+/* Note: HAVE_MEMCMP requires an unsigned memory comparison!!! */
+#ifndef SLMEMCMP
+# ifdef HAVE_MEMCMP
+# define SLMEMCMP memcmp
+# else
+# define SLMEMCMP SLmemcmp
+# endif
+#endif
+
+#if SLANG_VERSION < 9934
+# define SLmemcmp jed_memcmp
+# define SLmemcpy jed_memcpy
+# define SLmemset jed_memset
+# define SLmemchr jed_memchr
+#endif
+
+#ifndef SLFREE
+# define SLFREE free
+#endif
+
+#ifndef SLMALLOC
+# define SLMALLOC malloc
+#endif
+
+#ifndef SLCALLOC
+# define SLCALLOC calloc
+#endif
+
+#ifndef SLREALLOC
+# define SLREALLOC realloc
+#endif
+
+#endif /* _JD_MACROS_H_ */
diff --git a/minislang/sl-feat.h b/minislang/sl-feat.h
new file mode 100644
index 000000000..f4fe401e9
--- /dev/null
+++ b/minislang/sl-feat.h
@@ -0,0 +1,18 @@
+/* Set this to 1 to enable Kanji support */
+#define SLANG_HAS_KANJI_SUPPORT 0
+
+#define SLANG_HAS_COMPLEX 1
+#define SLANG_HAS_FLOAT 1
+
+#define _SLANG_OPTIMIZE_FOR_SPEED 1
+
+/* This is experimental. It adds extra information for tracking down
+ * errors.
+ */
+#define _SLANG_HAS_DEBUG_CODE 1
+
+/* Setting this to one will map 8 bit vtxxx terminals to 7 bit.
+ * This affects just input characters in the range 128-160 on non PC
+ * systems.
+ */
+#define _SLANG_MAP_VTXXX_8BIT 1
diff --git a/minislang/slang.h b/minislang/slang.h
new file mode 100644
index 000000000..f3a7ae909
--- /dev/null
+++ b/minislang/slang.h
@@ -0,0 +1,1547 @@
+#ifndef DAVIS_SLANG_H_
+#define DAVIS_SLANG_H_
+/* -*- mode: C; mode: fold; -*- */
+/* Copyright (c) 1992, 1998 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.
+ */
+#define SLANG_VERSION 10202
+/*{{{ System Dependent Macros and Typedefs */
+
+#if defined(__WATCOMC__) && defined(DOS)
+# ifndef __MSDOS__
+# define __MSDOS__
+# endif
+# ifndef DOS386
+# define DOS386
+# endif
+# ifndef IBMPC_SYSTEM
+# define IBMPC_SYSTEM
+# endif
+#endif /* __watcomc__ */
+
+#ifdef unix
+# ifndef __unix__
+# define __unix__ 1
+# endif
+#endif
+
+#if !defined(__GO32__)
+# ifdef __unix__
+# define REAL_UNIX_SYSTEM
+# endif
+#endif
+
+/* Set of the various defines for pc systems. This includes OS/2 */
+#ifdef __GO32__
+# ifndef __DJGPP__
+# define __DJGPP__ 1
+# endif
+# ifndef IBMPC_SYSTEM
+# define IBMPC_SYSTEM
+# endif
+#endif
+
+#ifdef __BORLANDC__
+# ifndef IBMPC_SYSTEM
+# define IBMPC_SYSTEM
+# endif
+#endif
+
+#ifdef __MSDOS__
+# ifndef IBMPC_SYSTEM
+# define IBMPC_SYSTEM
+# endif
+#endif
+
+#if defined(OS2) || defined(__os2__)
+# ifndef IBMPC_SYSTEM
+# define IBMPC_SYSTEM
+# endif
+# ifndef __os2__
+# define __os2__
+# endif
+#endif
+
+#if defined(__NT__) || defined(__MINGW32__) || defined(__CYGWIN32__)
+# ifndef IBMPC_SYSTEM
+# define IBMPC_SYSTEM
+# endif
+#endif
+
+#if defined(IBMPC_SYSTEM) || defined(VMS)
+# ifdef REAL_UNIX_SYSTEM
+# undef REAL_UNIX_SYSTEM
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+}
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+
+/* ---------------------------- Generic Macros ----------------------------- */
+
+/* __SC__ is defined for Symantec C++
+ DOS386 is defined for -mx memory model, 32 bit DOS extender. */
+
+#if defined(__SC__) && !defined(DOS386)
+# include <dos.h>
+#endif
+
+#if defined(__BORLANDC__)
+# include <alloc.h>
+#endif
+
+#if defined (__cplusplus) || defined(__STDC__)
+ typedef void *VOID_STAR;
+#else
+ typedef unsigned char *VOID_STAR;
+#endif
+
+typedef int (*FVOID_STAR)(void);
+
+#if defined(__MSDOS_) && defined(__BORLANDC__)
+# define SLFREE(buf) farfree((void far *)(buf))
+# define SLMALLOC(x) farmalloc((unsigned long) (x))
+# define SLREALLOC(buf, n) farrealloc((void far *) (buf), (unsigned long) (n))
+# define SLCALLOC(n, m) farcalloc((unsigned long) (n), (unsigned long) (m))
+#else
+# if defined(VMS) && !defined(__DECC)
+# define SLFREE VAXC$FREE_OPT
+# define SLMALLOC VAXC$MALLOC_OPT
+# define SLREALLOC VAXC$REALLOC_OPT
+# define SLCALLOC VAXC$CALLOC_OPT
+# else
+# define SLFREE(x) free((char *)(x))
+# define SLMALLOC malloc
+# if defined(__cplusplus) && !defined(__BEOS__)
+# define SLREALLOC(p,n) realloc((malloc_t) (p), (n))
+# else
+# define SLREALLOC realloc
+# endif
+# define SLCALLOC calloc
+# endif
+#endif
+
+ extern char *SLdebug_malloc (unsigned long);
+ extern char *SLdebug_calloc (unsigned long, unsigned long);
+ extern char *SLdebug_realloc (char *, unsigned long);
+ extern void SLdebug_free (char *);
+ extern void SLmalloc_dump_statistics (void);
+ extern char *SLstrcpy(register char *, register char *);
+ extern int SLstrcmp(register char *, register char *);
+ extern char *SLstrncpy(char *, register char *, register int);
+
+ extern void SLmemset (char *, char, int);
+ extern char *SLmemchr (register char *, register char, register int);
+ extern char *SLmemcpy (char *, char *, int);
+ extern int SLmemcmp (char *, char *, int);
+
+/*}}}*/
+
+/*{{{ Interpreter Typedefs */
+
+typedef struct _SLang_Name_Type
+{
+ char *name;
+ struct _SLang_Name_Type *next;
+ char name_type;
+#define SLANG_LVARIABLE 0x01
+#define SLANG_GVARIABLE 0x02
+#define SLANG_IVARIABLE 0x03 /* intrinsic variables */
+ /* Note!!! For Macro MAKE_VARIABLE below to work, SLANG_IVARIABLE Must
+ be 1 less than SLANG_RVARIABLE!!! */
+#define SLANG_RVARIABLE 0x04 /* read only variable */
+#define SLANG_INTRINSIC 0x05
+#define SLANG_FUNCTION 0x06
+#define SLANG_MATH_UNARY 0x07
+#define SLANG_APP_UNARY 0x08
+
+ /* Rest of fields depend on name type */
+}
+SLang_Name_Type;
+
+typedef struct
+{
+ char *name;
+ struct _SLang_Name_Type *next; /* this is for the hash table */
+ char name_type;
+
+ FVOID_STAR i_fun; /* address of object */
+
+ /* Do not change this without modifying slang.c:execute_intrinsic_fun */
+#define SLANG_MAX_INTRIN_ARGS 7
+ unsigned char arg_types [SLANG_MAX_INTRIN_ARGS];
+ unsigned char num_args;
+ unsigned char return_type;
+}
+SLang_Intrin_Fun_Type;
+
+typedef struct
+{
+ char *name;
+ SLang_Name_Type *next;
+ char name_type;
+
+ VOID_STAR addr;
+ unsigned char type;
+}
+SLang_Intrin_Var_Type;
+
+typedef struct
+{
+ char *name;
+ SLang_Name_Type *next;
+ char name_type;
+
+ int unary_op;
+}
+SLang_App_Unary_Type;
+
+typedef struct
+{
+ char *name;
+ SLang_Name_Type *next;
+ char name_type;
+
+ int unary_op;
+}
+SLang_Math_Unary_Type;
+
+
+
+extern int SLadd_intrin_fun_table (SLang_Intrin_Fun_Type *, char *);
+extern int SLadd_intrin_var_table (SLang_Intrin_Var_Type *, char *);
+extern int SLadd_app_unary_table (SLang_App_Unary_Type *, char *);
+extern int SLadd_math_unary_table (SLang_Math_Unary_Type *, char *);
+
+typedef struct SLang_Load_Type
+{
+ int type;
+
+ VOID_STAR client_data;
+ /* Pointer to data that client needs for loading */
+
+ int auto_declare_globals;
+ /* if non-zero, undefined global variables are declared */
+
+ char *(*read)(struct SLang_Load_Type *);
+ /* function to call to read next line from obj. */
+
+ unsigned int line_num;
+ /* Number of lines read, used for error reporting */
+
+ int parse_level;
+ /* 0 if at top level of parsing */
+
+ char *name;
+ /* Name of this object, e.g., filename */
+
+ unsigned long reserved[4];
+ /* For future expansion */
+} SLang_Load_Type;
+
+extern SLang_Load_Type *SLallocate_load_type (char *);
+extern void SLdeallocate_load_type (SLang_Load_Type *);
+extern int SLang_load_object (SLang_Load_Type *);
+extern int (*SLang_Load_File_Hook)(char *);
+
+/* Returns SLang_Error upon failure */
+
+#if defined(ultrix) && !defined(__GNUC__)
+# ifndef NO_PROTOTYPES
+# define NO_PROTOTYPES
+# endif
+#endif
+
+#ifndef NO_PROTOTYPES
+# define _PROTO(x) x
+#else
+# define _PROTO(x) ()
+#endif
+
+typedef struct SL_OOBinary_Type
+{
+ unsigned char data_type; /* partner type for binary op */
+
+ int (*binary_function)_PROTO((int,
+ unsigned char, VOID_STAR, unsigned int,
+ unsigned char, VOID_STAR, unsigned int,
+ VOID_STAR));
+
+ int (*binary_result) _PROTO((int, unsigned char, unsigned char, unsigned char *));
+ struct SL_OOBinary_Type *next;
+}
+SL_OOBinary_Type;
+
+typedef struct _SL_Typecast_Type
+{
+ unsigned char data_type; /* to_type */
+ int allow_implicit;
+
+ int (*typecast)_PROTO((unsigned char, VOID_STAR, unsigned int,
+ unsigned char, VOID_STAR));
+ struct _SL_Typecast_Type *next;
+}
+SL_Typecast_Type;
+
+#ifdef _SLANG_SOURCE_
+typedef struct _SLang_Struct_Type SLang_Struct_Type;
+#else
+typedef int SLang_Struct_Type;
+#endif
+
+typedef struct
+{
+ unsigned char cl_class_type;
+#define SLANG_CLASS_TYPE_MMT 0
+#define SLANG_CLASS_TYPE_SCALAR 1
+#define SLANG_CLASS_TYPE_VECTOR 2
+#define SLANG_CLASS_TYPE_PTR 3
+
+ unsigned int cl_data_type; /* SLANG_INTEGER_TYPE, etc... */
+ char *cl_name; /* slstring type */
+
+ unsigned int cl_sizeof_type;
+ VOID_STAR cl_transfer_buf; /* cl_sizeof_type bytes*/
+
+ /* Methods */
+
+ /* Most of the method functions are prototyped:
+ * int method (unsigned char type, VOID_STAR addr);
+ * Here, @type@ represents the type of object that the method is asked
+ * to deal with. The second parameter @addr@ will contain the ADDRESS of
+ * the object. For example, if type is SLANG_INT_TYPE, then @addr@ will
+ * actually be int *. Similary, if type is SLANG_STRING_TYPE,
+ * then @addr@ will contain the address of the string, i.e., char **.
+ */
+
+ void (*cl_destroy)_PROTO((unsigned char, VOID_STAR));
+ /* Prototype: void destroy(unsigned type, VOID_STAR val)
+ * Called to delete/free the object */
+
+ char *(*cl_string)_PROTO((unsigned char, VOID_STAR));
+ /* Prototype: char *to_string (unsigned char t, VOID_STAR p);
+ * Here p is a pointer to the object for which a string representation
+ * is to be returned. The returned pointer is to be a MALLOCED string.
+ */
+
+ /* Prototype: void push(unsigned char type, VOID_STAR v);
+ * Push a copy of the object of type @type@ at address @v@ onto the
+ * stack.
+ */
+ int (*cl_push)_PROTO((unsigned char, VOID_STAR));
+
+ /* Prototype: int pop(unsigned char type, VOID_STAR v);
+ * Pops value from stack and assign it to object, whose address is @v@.
+ */
+ int (*cl_pop)_PROTO((unsigned char, VOID_STAR));
+
+ int (*cl_unary_op_result_type)_PROTO((int, unsigned char, unsigned char *));
+ int (*cl_unary_op)_PROTO((int, unsigned char, VOID_STAR, unsigned int, VOID_STAR));
+
+ int (*cl_app_unary_op_result_type)_PROTO((int, unsigned char, unsigned char *));
+ int (*cl_app_unary_op)_PROTO((int, unsigned char, VOID_STAR, unsigned int, VOID_STAR));
+
+ /* If this function is non-NULL, it will be called for sin, cos, etc... */
+#define SLMATH_SIN 1
+#define SLMATH_COS 2
+#define SLMATH_TAN 3
+#define SLMATH_ATAN 4
+#define SLMATH_ASIN 5
+#define SLMATH_ACOS 6
+#define SLMATH_EXP 7
+#define SLMATH_LOG 8
+#define SLMATH_SQRT 9
+#define SLMATH_LOG10 10
+#define SLMATH_REAL 11
+#define SLMATH_IMAG 12
+#define SLMATH_SINH 13
+#define SLMATH_COSH 14
+#define SLMATH_TANH 15
+#define SLMATH_ATANH 16
+#define SLMATH_ASINH 17
+#define SLMATH_ACOSH 18
+#define SLMATH_TODOUBLE 19
+
+ int (*cl_math_op)_PROTO((int, unsigned char, VOID_STAR, unsigned int, VOID_STAR));
+ int (*cl_math_op_result_type)_PROTO((int, unsigned char, unsigned char *));
+
+ SL_OOBinary_Type *cl_binary_ops;
+ SL_Typecast_Type *cl_typecast_funs;
+
+ void (*cl_byte_code_destroy)_PROTO((unsigned char, VOID_STAR));
+ void (*cl_user_destroy_fun)_PROTO((unsigned char, VOID_STAR));
+ int (*cl_init_array_object)_PROTO((unsigned char, VOID_STAR));
+ int (*cl_datatype_deref)_PROTO((unsigned char));
+ SLang_Struct_Type *cl_struct_def;
+ int (*cl_dereference) _PROTO((unsigned char, VOID_STAR));
+ int (*cl_acopy) (unsigned char, VOID_STAR, VOID_STAR);
+ int (*cl_apop) _PROTO((unsigned char, VOID_STAR));
+ int (*cl_apush) _PROTO((unsigned char, VOID_STAR));
+ int (*cl_push_literal) _PROTO((unsigned char, VOID_STAR));
+ void (*cl_adestroy)_PROTO((unsigned char, VOID_STAR));
+ int (*cl_push_intrinsic)_PROTO((unsigned char, VOID_STAR));
+ int (*cl_void_typecast)_PROTO((unsigned char, VOID_STAR, unsigned int, unsigned char, VOID_STAR));
+} SLang_Class_Type;
+
+extern SLang_Class_Type *SLclass_allocate_class (char *);
+extern int SLclass_register_class (SLang_Class_Type *, unsigned char, unsigned int, unsigned char);
+extern int SLclass_set_string_function (SLang_Class_Type *, char *(*)(unsigned char, VOID_STAR));
+extern int SLclass_set_destroy_function (SLang_Class_Type *, void (*)(unsigned char, VOID_STAR));
+extern int SLclass_set_push_function (SLang_Class_Type *, int (*)(unsigned char, VOID_STAR));
+extern int SLclass_set_pop_function (SLang_Class_Type *, int (*)(unsigned char, VOID_STAR));
+
+extern int SLclass_add_unary_op (unsigned char,
+ int (*) (int,
+ unsigned char, VOID_STAR, unsigned int,
+ VOID_STAR),
+ int (*) (int, unsigned char, unsigned char *));
+
+extern int
+SLclass_add_app_unary_op (unsigned char,
+ int (*) (int,
+ unsigned char, VOID_STAR, unsigned int,
+ VOID_STAR),
+ int (*) (int, unsigned char, unsigned char *));
+
+extern int
+SLclass_add_binary_op (unsigned char, unsigned char,
+ int (*) (int,
+ unsigned char, VOID_STAR, unsigned int,
+ unsigned char, VOID_STAR, unsigned int,
+ VOID_STAR),
+ int (*) (int, unsigned char, unsigned char, unsigned char *));
+
+extern int
+SLclass_add_math_op (unsigned char,
+ int (*)(int,
+ unsigned char, VOID_STAR, unsigned int,
+ VOID_STAR),
+ int (*)(int, unsigned char, unsigned char *));
+
+extern int
+SLclass_add_typecast (unsigned char /* from */, unsigned char /* to */,
+ int (*)_PROTO((unsigned char, VOID_STAR, unsigned int,
+ unsigned char, VOID_STAR)),
+ int /* allow implicit typecasts */
+ );
+
+extern char *SLclass_get_datatype_name (unsigned char);
+
+extern double SLcomplex_abs (double *);
+extern double *SLcomplex_times (double *, double *, double *);
+extern double *SLcomplex_divide (double *, double *, double *);
+extern double *SLcomplex_sin (double *, double *);
+extern double *SLcomplex_cos (double *, double *);
+extern double *SLcomplex_tan (double *, double *);
+extern double *SLcomplex_asin (double *, double *);
+extern double *SLcomplex_acos (double *, double *);
+extern double *SLcomplex_atan (double *, double *);
+extern double *SLcomplex_exp (double *, double *);
+extern double *SLcomplex_log (double *, double *);
+extern double *SLcomplex_log10 (double *, double *);
+extern double *SLcomplex_sqrt (double *, double *);
+extern double *SLcomplex_sinh (double *, double *);
+extern double *SLcomplex_cosh (double *, double *);
+extern double *SLcomplex_tanh (double *, double *);
+extern double *SLcomplex_pow (double *, double *, double *);
+extern double SLmath_hypot (double x, double y);
+
+/* Not implemented yet */
+extern double *SLcomplex_asinh (double *, double *);
+extern double *SLcomplex_acosh (double *, double *);
+extern double *SLcomplex_atanh (double *, double *);
+
+#ifdef _SLANG_SOURCE_
+typedef struct _SLang_MMT_Type SLang_MMT_Type;
+#else
+typedef int SLang_MMT_Type;
+#endif
+
+extern void SLang_free_mmt (SLang_MMT_Type *);
+extern VOID_STAR SLang_object_from_mmt (SLang_MMT_Type *);
+extern SLang_MMT_Type *SLang_create_mmt (unsigned char, VOID_STAR);
+extern int SLang_push_mmt (SLang_MMT_Type *);
+extern SLang_MMT_Type *SLang_pop_mmt (unsigned char);
+extern void SLang_inc_mmt (SLang_MMT_Type *);
+/*}}}*/
+/*{{{ Interpreter Function Prototypes */
+
+ extern volatile int SLang_Error;
+/* Non zero if error occurs. Must be reset to zero to continue. */
+/* error codes, severe errors are less than 0 */
+#define SL_NOT_IMPLEMENTED -1
+#define SL_APPLICATION_ERROR -2
+#define SL_VARIABLE_UNINITIALIZED -3
+#define SL_MALLOC_ERROR -4
+#define SL_INTERNAL_ERROR -5
+#define SL_STACK_OVERFLOW -6
+#define SL_STACK_UNDERFLOW -7
+#define SL_UNDEFINED_NAME -8
+#define SL_SYNTAX_ERROR -9
+#define SL_DUPLICATE_DEFINITION -10
+#define SL_TYPE_MISMATCH -11
+#define SL_READONLY_ERROR -12
+#define SL_OBJ_UNKNOWN -13
+#define SL_UNKNOWN_ERROR -14
+#define SL_INVALID_PARM -15
+#define SL_TYPE_UNDEFINED_OP_ERROR -16
+
+#define SL_INTRINSIC_ERROR 1
+/* Intrinsic error is an error generated by intrinsic functions */
+#define SL_USER_BREAK 2
+#define SL_DIVIDE_ERROR 3
+#define SL_OBJ_NOPEN 4
+#define SL_USER_ERROR 5
+
+/* Compatibility */
+#define USER_BREAK SL_USER_BREAK
+#define INTRINSIC_ERROR SL_INTRINSIC_ERROR
+
+ extern int SLang_Traceback;
+ /* If non-zero, dump an S-Lang traceback upon error. Available as
+ _traceback in S-Lang. */
+
+ extern char *SLang_User_Prompt;
+ /* Prompt to use when reading from stdin */
+ extern int SLang_Version;
+
+extern void (*SLang_VMessage_Hook) (char *, va_list);
+extern void SLang_vmessage (char *, ...);
+
+ extern void (*SLang_Error_Hook)(char *);
+ /* Pointer to application dependent error messaging routine. By default,
+ messages are displayed on stderr. */
+
+ extern void (*SLang_Exit_Error_Hook)(char *, va_list);
+ extern void SLang_exit_error (char *, ...);
+ extern void (*SLang_Dump_Routine)(char *);
+ /* Called if S-Lang traceback is enabled as well as other debugging
+ routines (e.g., trace). By default, these messages go to stderr. */
+
+ extern void (*SLang_Interrupt)(void);
+ /* function to call whenever inner interpreter is entered. This is
+ a good place to set SLang_Error to USER_BREAK. */
+
+ extern void (*SLang_User_Clear_Error)(void);
+ /* function that gets called when '_clear_error' is called. */
+
+ /* If non null, these call C functions before and after a slang function. */
+ extern void (*SLang_Enter_Function)(char *);
+extern void (*SLang_Exit_Function)(char *);
+
+extern int SLang_Num_Function_Args;
+
+/* Functions: */
+
+ extern int SLang_init_slang (void);
+ /* This function is mandatory and must be called by all applications that
+ * use the interpreter
+ */
+ extern int SLang_init_slfile (void);
+ /* called if fputs, fgets, etc are need in S-Lang */
+ extern int SLang_init_slmath (void);
+ /* called if math functions sin, cos, etc... are needed. */
+ extern int SLang_init_slunix (void);
+ /* unix system functions chmod, stat, etc... */
+
+ extern int SLang_load_file (char *);
+ /* Load a file of S-Lang code for interpreting. If the parameter is
+ * NULL, input comes from stdin. */
+
+ extern void SLang_restart(int);
+ /* should be called if an error occurs. If the passed integer is
+ * non-zero, items are popped off the stack; otherwise, the stack is
+ * left intact. Any time the stack is believed to be trashed, this routine
+ * should be called with a non-zero argument (e.g., if setjmp/longjmp is
+ * called). */
+
+ extern int SLang_byte_compile_file(char *, int);
+ /* takes a file of S-Lang code and ``byte-compiles'' it for faster
+ * loading. The new filename is equivalent to the old except that a `c' is
+ * appended to the name. (e.g., init.sl --> init.slc). The second
+ * specified the method; currently, it is not used.
+ */
+
+ extern int SLang_autoload(char *, char *);
+ /* Automatically load S-Lang function p1 from file p2. This function
+ is also available via S-Lang */
+
+ extern int SLang_load_string(char *);
+ /* Like SLang_load_file except input is from a null terminated string. */
+
+ extern int SLdo_pop(void);
+ /* pops item off stack and frees any memory associated with it */
+ extern int SLdo_pop_n(unsigned int);
+ /* pops n items off stack and frees any memory associated with them */
+
+ extern int SLang_pop_integer(int *);
+ /* pops integer *p0 from the stack. Returns 0 upon success and non-zero
+ * if the stack is empty or a type mismatch occurs, setting SLang_Error.
+ */
+
+ extern int SLpop_string (char **);
+ extern int SLang_pop_string(char **, int *);
+ /* pops string *p0 from stack. If *p1 is non-zero, the string must be
+ * freed after its use. DO NOT FREE p0 if *p1 IS ZERO! Returns 0 upon
+ * success */
+
+ extern int SLang_pop_double(double *, int *, int *);
+ /* Pops double *p1 from stack. If *p3 is non-zero, *p1 was derived
+ from the integer *p2. Returns zero upon success. */
+
+ extern int SLang_pop_complex (double *, double *);
+ extern int SLang_push_complex (double, double);
+
+ extern int SLang_push_double(double);
+ /* Push double onto stack */
+
+ extern int SLang_push_string(char *);
+ /* Push string p1 onto stack */
+
+ extern int SLang_push_integer(int);
+ /* push integer p1 on stack */
+
+ extern int SLang_push_malloced_string(char *);
+ /* The normal SLang_push_string mallocs space for the string. This one
+ * does not. DO NOT FREE IT IF YOU USE THIS ROUTINE. Also do not
+ * use this routine if the string was a product of SLcreate_string.
+ * If -1 is returned, it failed and the original string is not freed.
+ */
+
+extern int SLang_push_null (void);
+extern int SLang_pop_null (void);
+
+extern int SLang_push_value (unsigned char type, VOID_STAR);
+extern int SLang_pop_value (unsigned char type, VOID_STAR);
+extern void SLang_free_value (unsigned char type, VOID_STAR);
+
+#ifdef _SLANG_SOURCE_
+typedef struct _SLang_Ref_Type SLang_Ref_Type;
+#else
+typedef int SLang_Ref_Type;
+#endif
+
+
+extern int SLang_pop_ref (SLang_Ref_Type **);
+extern void SLang_free_ref (SLang_Ref_Type *);
+extern int SLang_assign_to_ref (SLang_Ref_Type *, unsigned char, VOID_STAR);
+
+
+ extern int SLang_is_defined(char *);
+ /* Return non-zero is p1 is defined otherwise returns 0. */
+
+ extern int SLang_run_hooks(char *, unsigned int, ...);
+ /* calls S-Lang function p1 pushing p2 strings in the variable argument
+ * list onto the stack first.
+ * Returns -1 upon error, 1 if hooks exists and it ran,
+ * or 0 if hook does not exist. Thus it returns non-zero is hook was called.
+ */
+
+extern int SLexecute_function (SLang_Name_Type *);
+extern int SLang_execute_function(char *);
+extern int SLang_end_arg_list (void);
+extern int SLang_start_arg_list (void);
+
+extern void SLang_verror (int, char *, ...);
+
+extern void SLang_doerror(char *);
+ /* set SLang_Error and display p1 as error message */
+
+extern int SLang_add_intrinsic_array (char *, /* name */
+ unsigned char, /* type */
+ int, /* readonly */
+ VOID_STAR, /* data */
+ unsigned int, ...); /* num dims */
+
+
+extern int SLextract_list_element (char *, unsigned int, char,
+ char *, unsigned int);
+
+extern void SLexpand_escaped_string (register char *, register char *,
+ register char *);
+
+extern SLang_Name_Type *SLang_get_function (char *);
+
+extern int SLang_peek_at_stack (void);
+/* Returns type of next object on stack-- -1 upon stack underflow. */
+extern void SLmake_lut (unsigned char *, unsigned char *, unsigned char);
+
+ extern int SLang_guess_type (char *);
+
+/*}}}*/
+
+/*{{{ Misc Functions */
+
+extern char *SLmake_string (char *);
+extern char *SLmake_nstring (char *, unsigned int);
+/* Returns a null terminated string made from the first n characters of the
+ * string.
+ */
+
+/* The string created by this routine must be freed by SLang_free_slstring
+ * and nothing else!! Also these strings must not be modified. Use
+ * SLmake_string if you intend to modify them!!
+ */
+extern char *SLang_create_nslstring (char *, unsigned int);
+extern char *SLang_create_slstring (char *);
+extern void SLang_free_slstring (char *); /* handles NULL */
+extern int SLang_pop_slstring (char **); /* free with SLang_free_slstring */
+extern char *SLang_concat_slstrings (char *a, char *b);
+extern char *SLang_create_static_slstring (char *); /* adds a string that will not get deleted */
+extern void SLstring_dump_stats (void);
+
+extern char *SLmalloc (unsigned int);
+extern char *SLcalloc (unsigned int, unsigned int);
+extern void SLfree(char *); /* This function handles NULL */
+extern char *SLrealloc (char *, unsigned int);
+
+extern char *SLcurrent_time_string (void);
+
+extern int SLatoi(unsigned char *);
+
+extern int SLang_pop_fileptr (SLang_MMT_Type **, FILE **);
+
+/*}}}*/
+
+/*{{{ SLang getkey interface Functions */
+
+#ifdef REAL_UNIX_SYSTEM
+extern int SLang_TT_Baud_Rate;
+extern int SLang_TT_Read_FD;
+#endif
+
+extern int SLang_init_tty (int, int, int);
+/* Initializes the tty for single character input. If the first parameter *p1
+ * is in the range 0-255, it will be used for the abort character;
+ * otherwise, (unix only) if it is -1, the abort character will be the one
+ * used by the terminal. If the second parameter p2 is non-zero, flow
+ * control is enabled. If the last parmeter p3 is zero, output processing
+ * is NOT turned on. A value of zero is required for the screen management
+ * routines. Returns 0 upon success. In addition, if SLang_TT_Baud_Rate ==
+ * 0 when this function is called, SLang will attempt to determine the
+ * terminals baud rate. As far as the SLang library is concerned, if
+ * SLang_TT_Baud_Rate is less than or equal to zero, the baud rate is
+ * effectively infinite.
+ */
+
+extern void SLang_reset_tty (void);
+/* Resets tty to what it was prior to a call to SLang_init_tty */
+#ifdef REAL_UNIX_SYSTEM
+extern void SLtty_set_suspend_state (int);
+ /* If non-zero argument, terminal driver will be told to react to the
+ * suspend character. If 0, it will not.
+ */
+extern int (*SLang_getkey_intr_hook) (void);
+#endif
+
+#define SLANG_GETKEY_ERROR 0xFFFF
+extern unsigned int SLang_getkey (void);
+/* reads a single key from the tty. If the read fails, 0xFFFF is returned. */
+
+#ifdef IBMPC_SYSTEM
+extern int SLgetkey_map_to_ansi (int);
+#endif
+
+extern int SLang_ungetkey_string (unsigned char *, unsigned int);
+extern int SLang_buffer_keystring (unsigned char *, unsigned int);
+extern int SLang_ungetkey (unsigned char);
+extern void SLang_flush_input (void);
+extern int SLang_input_pending (int);
+extern int SLang_Abort_Char;
+/* The value of the character (0-255) used to trigger SIGINT */
+extern int SLang_Ignore_User_Abort;
+/* If non-zero, pressing the abort character will not result in USER_BREAK
+ * SLang_Error. */
+
+extern int SLang_set_abort_signal (void (*)(int));
+/* If SIGINT is generated, the function p1 will be called. If p1 is NULL
+ * the SLang_default signal handler is called. This sets SLang_Error to
+ * USER_BREAK. I suspect most users will simply want to pass NULL.
+ */
+extern unsigned int SLang_Input_Buffer_Len;
+
+extern volatile int SLKeyBoard_Quit;
+
+#ifdef VMS
+/* If this function returns -1, ^Y will be added to input buffer. */
+extern int (*SLtty_VMS_Ctrl_Y_Hook) (void);
+#endif
+/*}}}*/
+
+/*{{{ SLang Keymap routines */
+
+typedef struct SLKeymap_Function_Type
+{
+ char *name;
+ int (*f)(void);
+}
+SLKeymap_Function_Type;
+
+#define SLANG_MAX_KEYMAP_KEY_SEQ 14
+typedef struct SLang_Key_Type
+{
+ struct SLang_Key_Type *next;
+ union
+ {
+ char *s;
+ FVOID_STAR f;
+ unsigned int keysym;
+ }
+ f;
+ unsigned char type; /* type of function */
+#define SLKEY_F_INTERPRET 0x01
+#define SLKEY_F_INTRINSIC 0x02
+#define SLKEY_F_KEYSYM 0x03
+ unsigned char str[SLANG_MAX_KEYMAP_KEY_SEQ + 1];/* key sequence */
+}
+SLang_Key_Type;
+
+typedef struct SLKeyMap_List_Type
+{
+ char *name; /* hashed string */
+ SLang_Key_Type *keymap;
+ SLKeymap_Function_Type *functions; /* intrinsic functions */
+}
+SLKeyMap_List_Type;
+
+/* This is arbitrary but I have got to start somewhere */
+#define SLANG_MAX_KEYMAPS 30
+extern SLKeyMap_List_Type SLKeyMap_List[SLANG_MAX_KEYMAPS];
+
+extern char *SLang_process_keystring(char *);
+
+extern int SLkm_define_key (char *, FVOID_STAR, SLKeyMap_List_Type *);
+
+extern int SLang_define_key(char *, char *, SLKeyMap_List_Type *);
+/* Like define_key1 except that p2 is a string that is to be associated with
+ * a function in the functions field of p3. This routine calls define_key1.
+ */
+
+extern int SLkm_define_keysym (char *, unsigned int, SLKeyMap_List_Type *);
+
+extern void SLang_undefine_key(char *, SLKeyMap_List_Type *);
+
+extern SLKeyMap_List_Type *SLang_create_keymap(char *, SLKeyMap_List_Type *);
+/* create and returns a pointer to a new keymap named p1 created by copying
+ * keymap p2. If p2 is NULL, it is up to the calling routine to initialize
+ * the keymap.
+ */
+
+extern char *SLang_make_keystring(unsigned char *);
+
+extern SLang_Key_Type *SLang_do_key(SLKeyMap_List_Type *, int (*)(void));
+/* read a key using keymap p1 with getkey function p2 */
+
+extern
+ FVOID_STAR
+ SLang_find_key_function(char *, SLKeyMap_List_Type *);
+
+extern SLKeyMap_List_Type *SLang_find_keymap(char *);
+
+extern int SLang_Last_Key_Char;
+extern int SLang_Key_TimeOut_Flag;
+
+/*}}}*/
+
+/*{{{ SLang Readline Interface */
+
+typedef struct SLang_Read_Line_Type
+{
+ struct SLang_Read_Line_Type *prev, *next;
+ unsigned char *buf;
+ int buf_len; /* number of chars in the buffer */
+ int num; /* num and misc are application specific*/
+ int misc;
+} SLang_Read_Line_Type;
+
+/* Maximum size of display */
+#define SLRL_DISPLAY_BUFFER_SIZE 256
+
+typedef struct
+{
+ SLang_Read_Line_Type *root, *tail, *last;
+ unsigned char *buf; /* edit buffer */
+ int buf_len; /* sizeof buffer */
+ int point; /* current editing point */
+ int tab; /* tab width */
+ int len; /* current line size */
+
+ /* display variables */
+ int edit_width; /* length of display field */
+ int curs_pos; /* current column */
+ int start_column; /* column offset of display */
+ int dhscroll; /* amount to use for horiz scroll */
+ char *prompt;
+
+ FVOID_STAR last_fun; /* last function executed by rl */
+
+ /* These two contain an image of what is on the display */
+ unsigned char upd_buf1[SLRL_DISPLAY_BUFFER_SIZE];
+ unsigned char upd_buf2[SLRL_DISPLAY_BUFFER_SIZE];
+ unsigned char *old_upd, *new_upd; /* pointers to previous two buffers */
+ int new_upd_len, old_upd_len; /* length of output buffers */
+
+ SLKeyMap_List_Type *keymap;
+
+ /* tty variables */
+ unsigned int flags; /* */
+#define SL_RLINE_NO_ECHO 1
+#define SL_RLINE_USE_ANSI 2
+#define SL_RLINE_BLINK_MATCH 4
+ unsigned int (*getkey)(void); /* getkey function -- required */
+ void (*tt_goto_column)(int);
+ void (*tt_insert)(char);
+ void (*update_hook)(unsigned char *, int, int);
+ /* The update hook is called with a pointer to a buffer p1 that contains
+ * an image of what the update hook is suppoed to produce. The length
+ * of the buffer is p2 and after the update, the cursor is to be placed
+ * in column p3.
+ */
+ /* This function is only called when blinking matches */
+ int (*input_pending)(int);
+ unsigned long reserved[4];
+} SLang_RLine_Info_Type;
+
+extern int SLang_RL_EOF_Char;
+
+extern SLang_Read_Line_Type * SLang_rline_save_line (SLang_RLine_Info_Type *);
+extern int SLang_init_readline (SLang_RLine_Info_Type *);
+extern int SLang_read_line (SLang_RLine_Info_Type *);
+extern int SLang_rline_insert (char *);
+extern void SLrline_redraw (SLang_RLine_Info_Type *);
+extern int SLang_Rline_Quit;
+
+/*}}}*/
+
+/*{{{ Low Level Screen Output Interface */
+
+extern unsigned long SLtt_Num_Chars_Output;
+extern int SLtt_Baud_Rate;
+
+typedef unsigned long SLtt_Char_Type;
+
+#define SLTT_BOLD_MASK 0x01000000
+#define SLTT_BLINK_MASK 0x02000000
+#define SLTT_ULINE_MASK 0x04000000
+#define SLTT_REV_MASK 0x08000000
+#define SLTT_ALTC_MASK 0x10000000
+
+extern int SLtt_Screen_Rows;
+extern int SLtt_Screen_Cols;
+extern int SLtt_Term_Cannot_Insert;
+extern int SLtt_Term_Cannot_Scroll;
+extern int SLtt_Use_Ansi_Colors;
+extern int SLtt_Ignore_Beep;
+#if defined(REAL_UNIX_SYSTEM)
+extern int SLtt_Force_Keypad_Init;
+#endif
+
+#ifndef IBMPC_SYSTEM
+extern char *SLtt_Graphics_Char_Pairs;
+#endif
+
+#ifndef __GO32__
+#if defined(VMS) || defined(REAL_UNIX_SYSTEM)
+extern int SLtt_Blink_Mode;
+extern int SLtt_Use_Blink_For_ACS;
+extern int SLtt_Newline_Ok;
+extern int SLtt_Has_Alt_Charset;
+extern int SLtt_Has_Status_Line; /* if 0, NO. If > 0, YES, IF -1, ?? */
+# ifndef VMS
+extern int SLtt_Try_Termcap;
+# endif
+#endif
+#endif
+
+#if defined(IBMPC_SYSTEM)
+extern int SLtt_Msdos_Cheap_Video;
+#endif
+
+extern int SLtt_flush_output (void);
+extern void SLtt_set_scroll_region(int, int);
+extern void SLtt_reset_scroll_region(void);
+extern void SLtt_reverse_video (int);
+extern void SLtt_bold_video (void);
+extern void SLtt_begin_insert(void);
+extern void SLtt_end_insert(void);
+extern void SLtt_del_eol(void);
+extern void SLtt_goto_rc (int, int);
+extern void SLtt_delete_nlines(int);
+extern void SLtt_delete_char(void);
+extern void SLtt_erase_line(void);
+extern void SLtt_normal_video(void);
+extern void SLtt_cls(void);
+extern void SLtt_beep(void);
+extern void SLtt_reverse_index(int);
+extern void SLtt_smart_puts(unsigned short *, unsigned short *, int, int);
+extern void SLtt_write_string (char *);
+extern void SLtt_putchar(char);
+extern int SLtt_init_video (void);
+extern int SLtt_reset_video (void);
+extern void SLtt_get_terminfo(void);
+extern void SLtt_get_screen_size (void);
+extern int SLtt_set_cursor_visibility (int);
+
+extern int SLtt_set_mouse_mode (int, int);
+
+#if defined(VMS) || defined(REAL_UNIX_SYSTEM)
+extern int SLtt_initialize (char *);
+extern void SLtt_enable_cursor_keys(void);
+extern void SLtt_set_term_vtxxx(int *);
+extern void SLtt_set_color_esc (int, char *);
+extern void SLtt_wide_width(void);
+extern void SLtt_narrow_width(void);
+extern void SLtt_set_alt_char_set (int);
+extern int SLtt_write_to_status_line (char *, int);
+extern void SLtt_disable_status_line (void);
+# ifdef REAL_UNIX_SYSTEM
+ extern char *SLtt_tgetstr (char *);
+ extern int SLtt_tgetnum (char *);
+ extern int SLtt_tgetflag (char *);
+ extern char *SLtt_tigetent (char *);
+ extern char *SLtt_tigetstr (char *, char **);
+ extern int SLtt_tigetnum (char *, char **);
+# endif
+#endif
+
+extern SLtt_Char_Type SLtt_get_color_object (int);
+extern void SLtt_set_color_object (int, SLtt_Char_Type);
+extern void SLtt_set_color (int, char *, char *, char *);
+extern void SLtt_set_mono (int, char *, SLtt_Char_Type);
+extern void SLtt_add_color_attribute (int, SLtt_Char_Type);
+extern void SLtt_set_color_fgbg (int, SLtt_Char_Type, SLtt_Char_Type);
+
+/*}}}*/
+
+/*{{{ SLang Preprocessor Interface */
+
+typedef struct
+{
+ int this_level;
+ int exec_level;
+ int prev_exec_level;
+ char preprocess_char;
+ char comment_char;
+ unsigned char flags;
+#define SLPREP_BLANK_LINES_OK 1
+#define SLPREP_COMMENT_LINES_OK 2
+}
+SLPreprocess_Type;
+
+extern int SLprep_open_prep (SLPreprocess_Type *);
+extern void SLprep_close_prep (SLPreprocess_Type *);
+extern int SLprep_line_ok (char *, SLPreprocess_Type *);
+ extern int SLdefine_for_ifdef (char *);
+ /* Adds a string to the SLang #ifdef preparsing defines. SLang already
+ defines MSDOS, UNIX, and VMS on the appropriate system. */
+extern int (*SLprep_exists_hook) (char *, char);
+
+/*}}}*/
+
+/*{{{ SLsmg Screen Management Functions */
+
+extern void SLsmg_fill_region (int, int, unsigned int, unsigned int, unsigned char);
+extern void SLsmg_set_char_set (int);
+#ifndef IBMPC_SYSTEM
+extern int SLsmg_Scroll_Hash_Border;
+#endif
+extern int SLsmg_suspend_smg (void);
+extern int SLsmg_resume_smg (void);
+extern void SLsmg_erase_eol (void);
+extern void SLsmg_gotorc (int, int);
+extern void SLsmg_erase_eos (void);
+extern void SLsmg_reverse_video (void);
+extern void SLsmg_set_color (int);
+extern void SLsmg_normal_video (void);
+extern void SLsmg_printf (char *, ...);
+extern void SLsmg_vprintf (char *, va_list);
+extern void SLsmg_write_string (char *);
+extern void SLsmg_write_nstring (char *, unsigned int);
+extern void SLsmg_write_char (char);
+extern void SLsmg_write_nchars (char *, unsigned int);
+extern void SLsmg_write_wrapped_string (char *, int, int, unsigned int, unsigned int, int);
+extern void SLsmg_cls (void);
+extern void SLsmg_refresh (void);
+extern void SLsmg_touch_lines (int, unsigned int);
+extern int SLsmg_init_smg (void);
+extern void SLsmg_reset_smg (void);
+extern unsigned short SLsmg_char_at(void);
+extern void SLsmg_set_screen_start (int *, int *);
+extern void SLsmg_draw_hline (unsigned int);
+extern void SLsmg_draw_vline (int);
+extern void SLsmg_draw_object (int, int, unsigned char);
+extern void SLsmg_draw_box (int, int, unsigned int, unsigned int);
+extern int SLsmg_get_column(void);
+extern int SLsmg_get_row(void);
+extern void SLsmg_forward (int);
+extern void SLsmg_write_color_chars (unsigned short *, unsigned int);
+extern unsigned int SLsmg_read_raw (unsigned short *, unsigned int);
+extern unsigned int SLsmg_write_raw (unsigned short *, unsigned int);
+extern void SLsmg_set_color_in_region (int, int, int, unsigned int, unsigned int);
+extern int SLsmg_Display_Eight_Bit;
+extern int SLsmg_Tab_Width;
+
+#define SLSMG_NEWLINE_IGNORED 0 /* default */
+#define SLSMG_NEWLINE_MOVES 1 /* moves to next line, column 0 */
+#define SLSMG_NEWLINE_SCROLLS 2 /* moves but scrolls at bottom of screen */
+#define SLSMG_NEWLINE_PRINTABLE 3 /* prints as ^J */
+extern int SLsmg_Newline_Behavior;
+
+extern int SLsmg_Backspace_Moves;
+
+#ifdef IBMPC_SYSTEM
+# define SLSMG_HLINE_CHAR 0xC4
+# define SLSMG_VLINE_CHAR 0xB3
+# define SLSMG_ULCORN_CHAR 0xDA
+# define SLSMG_URCORN_CHAR 0xBF
+# define SLSMG_LLCORN_CHAR 0xC0
+# define SLSMG_LRCORN_CHAR 0xD9
+# define SLSMG_RTEE_CHAR 0xB4
+# define SLSMG_LTEE_CHAR 0xC3
+# define SLSMG_UTEE_CHAR 0xC2
+# define SLSMG_DTEE_CHAR 0xC1
+# define SLSMG_PLUS_CHAR 0xC5
+/* There are several to choose from: 0xB0, 0xB1, and 0xB2 */
+# define SLSMG_CKBRD_CHAR 0xB0
+#else
+# define SLSMG_HLINE_CHAR 'q'
+# define SLSMG_VLINE_CHAR 'x'
+# define SLSMG_ULCORN_CHAR 'l'
+# define SLSMG_URCORN_CHAR 'k'
+# define SLSMG_LLCORN_CHAR 'm'
+# define SLSMG_LRCORN_CHAR 'j'
+# define SLSMG_CKBRD_CHAR 'a'
+# define SLSMG_RTEE_CHAR 'u'
+# define SLSMG_LTEE_CHAR 't'
+# define SLSMG_UTEE_CHAR 'w'
+# define SLSMG_DTEE_CHAR 'v'
+# define SLSMG_PLUS_CHAR 'n'
+#endif
+
+#ifndef IBMPC_SYSTEM
+# define SLSMG_COLOR_BLACK 0x000000
+# define SLSMG_COLOR_RED 0x000001
+# define SLSMG_COLOR_GREEN 0x000002
+# define SLSMG_COLOR_BROWN 0x000003
+# define SLSMG_COLOR_BLUE 0x000004
+# define SLSMG_COLOR_MAGENTA 0x000005
+# define SLSMG_COLOR_CYAN 0x000006
+# define SLSMG_COLOR_LGRAY 0x000007
+# define SLSMG_COLOR_GRAY 0x000008
+# define SLSMG_COLOR_BRIGHT_RED 0x000009
+# define SLSMG_COLOR_BRIGHT_GREEN 0x00000A
+# define SLSMG_COLOR_BRIGHT_BROWN 0x00000B
+# define SLSMG_COLOR_BRIGHT_BLUE 0x00000C
+# define SLSMG_COLOR_BRIGHT_CYAN 0x00000D
+# define SLSMG_COLOR_BRIGHT_MAGENTA 0x00000E
+# define SLSMG_COLOR_BRIGHT_WHITE 0x00000F
+#endif
+
+typedef struct
+{
+ void (*tt_normal_video)(void);
+ void (*tt_set_scroll_region)(int, int);
+ void (*tt_goto_rc)(int, int);
+ void (*tt_reverse_index)(int);
+ void (*tt_reset_scroll_region)(void);
+ void (*tt_delete_nlines)(int);
+ void (*tt_cls) (void);
+ void (*tt_del_eol) (void);
+ void (*tt_smart_puts) (unsigned short *, unsigned short *, int, int);
+ int (*tt_flush_output) (void);
+ int (*tt_reset_video) (void);
+ int (*tt_init_video) (void);
+
+ int *tt_screen_rows;
+ int *tt_screen_cols;
+
+ int *tt_term_cannot_scroll;
+ int *tt_has_alt_charset;
+ int *tt_use_blink_for_acs;
+ char **tt_graphic_char_pairs;
+
+ long reserved[4];
+}
+SLsmg_Term_Type;
+extern void SLsmg_set_terminal_info (SLsmg_Term_Type *);
+
+/*}}}*/
+
+/*{{{ SLang Keypad Interface */
+
+#define SL_KEY_ERR 0xFFFF
+
+#define SL_KEY_UP 0x101
+#define SL_KEY_DOWN 0x102
+#define SL_KEY_LEFT 0x103
+#define SL_KEY_RIGHT 0x104
+#define SL_KEY_PPAGE 0x105
+#define SL_KEY_NPAGE 0x106
+#define SL_KEY_HOME 0x107
+#define SL_KEY_END 0x108
+#define SL_KEY_A1 0x109
+#define SL_KEY_A3 0x10A
+#define SL_KEY_B2 0x10B
+#define SL_KEY_C1 0x10C
+#define SL_KEY_C3 0x10D
+#define SL_KEY_REDO 0x10E
+#define SL_KEY_UNDO 0x10F
+#define SL_KEY_BACKSPACE 0x110
+#define SL_KEY_ENTER 0x111
+#define SL_KEY_IC 0x112
+#define SL_KEY_DELETE 0x113
+
+#define SL_KEY_F0 0x200
+#define SL_KEY_F(X) (SL_KEY_F0 + X)
+
+/* I do not intend to use keysymps > 0x1000. Applications can use those. */
+/* Returns 0 upon success or -1 upon error. */
+extern int SLkp_define_keysym (char *, unsigned int);
+
+/* This function must be called AFTER SLtt_get_terminfo and not before. */
+extern int SLkp_init (void);
+
+/* This function uses SLang_getkey and assumes that what ever initialization
+ * is required for SLang_getkey has been performed.
+ */
+extern int SLkp_getkey (void);
+
+/*}}}*/
+
+/*{{{ SLang Scroll Interface */
+
+typedef struct _SLscroll_Type
+{
+ struct _SLscroll_Type *next;
+ struct _SLscroll_Type *prev;
+ unsigned int flags;
+}
+SLscroll_Type;
+
+typedef struct
+{
+ unsigned int flags;
+ SLscroll_Type *top_window_line; /* list element at top of window */
+ SLscroll_Type *bot_window_line; /* list element at bottom of window */
+ SLscroll_Type *current_line; /* current list element */
+ SLscroll_Type *lines; /* first list element */
+ unsigned int nrows; /* number of rows in window */
+ unsigned int hidden_mask; /* applied to flags in SLscroll_Type */
+ unsigned int line_num; /* current line number (visible) */
+ unsigned int num_lines; /* total number of lines (visible) */
+ unsigned int window_row; /* row of current_line in window */
+ unsigned int border; /* number of rows that form scroll border */
+ int cannot_scroll; /* should window scroll or recenter */
+}
+SLscroll_Window_Type;
+
+extern int SLscroll_find_top (SLscroll_Window_Type *);
+extern int SLscroll_find_line_num (SLscroll_Window_Type *);
+extern unsigned int SLscroll_next_n (SLscroll_Window_Type *, unsigned int);
+extern unsigned int SLscroll_prev_n (SLscroll_Window_Type *, unsigned int);
+extern int SLscroll_pageup (SLscroll_Window_Type *);
+extern int SLscroll_pagedown (SLscroll_Window_Type *);
+
+/*}}}*/
+
+/*{{{ Signal Routines */
+
+typedef void SLSig_Fun_Type (int);
+extern SLSig_Fun_Type *SLsignal (int, SLSig_Fun_Type *);
+extern SLSig_Fun_Type *SLsignal_intr (int, SLSig_Fun_Type *);
+extern int SLsig_block_signals (void);
+extern int SLsig_unblock_signals (void);
+extern int SLsystem (char *);
+
+extern char *SLerrno_strerror (int);
+
+/*}}}*/
+
+/*{{{ Interpreter Macro Definitions */
+
+/* The definitions here are for objects that may be on the run-time stack.
+ * They are actually sub_types of literal and data main_types.
+ * Note that the return types for MAKE_INTRINSIC defined intrinsic functions
+ * must be numbered from 0x1 - 0x0F.
+ */
+#define SLANG_UNDEFINED_TYPE 0x00 /* MUST be 0 */
+#define SLANG_VOID_TYPE 0x01 /* also matches ANY type */
+#define SLANG_INT_TYPE 0x02
+#define SLANG_DOUBLE_TYPE 0x03
+#define SLANG_CHAR_TYPE 0x04
+#define SLANG_INTP_TYPE 0x05
+/* An object of SLANG_INTP_TYPE should never really occur on the stack. Rather,
+ * the integer to which it refers will be there instead. It is defined here
+ * because it is a valid type for MAKE_VARIABLE.
+ */
+#define SLANG_REF_TYPE 0x06
+/* SLANG_REF_TYPE refers to an object on the stack that is a pointer (reference)
+ * to some other object.
+ */
+#define SLANG_COMPLEX_TYPE 0x07
+#define SLANG_NULL_TYPE 0x08
+#define SLANG_STRING_TYPE 0x0F
+
+#define SLANG_STRUCT_TYPE 0x11
+#define SLANG_ARRAY_TYPE 0x20
+#define SLANG_DATATYPE_TYPE 0x21
+#define SLANG_FILE_PTR_TYPE 0x22
+
+/* Compatibility */
+#ifdef FLOAT_TYPE
+# undef FLOAT_TYPE
+#endif
+#define VOID_TYPE SLANG_VOID_TYPE
+#define INT_TYPE SLANG_INT_TYPE
+#define INTP_TYPE SLANG_INTP_TYPE
+#define FLOAT_TYPE SLANG_DOUBLE_TYPE
+#define ARRAY_TYPE SLANG_ARRAY_TYPE
+#define CHAR_TYPE SLANG_CHAR_TYPE
+#define STRING_TYPE SLANG_STRING_TYPE
+
+/* I am reserving values greater than or equal to 128 for user applications.
+ * The first 127 are reserved for S-Lang.
+ */
+
+/* Binary and Unary Subtypes */
+/* Since the application can define new types and can overload the binary
+ * and unary operators, these definitions must be present in this file.
+ * The current implementation assumes both unary and binary are distinct.
+ */
+#define SLANG_PLUS 0x01
+#define SLANG_MINUS 0x02
+#define SLANG_TIMES 0x03
+#define SLANG_DIVIDE 0x04
+#define SLANG_EQ 0x05
+#define SLANG_NE 0x06
+#define SLANG_GT 0x07
+#define SLANG_GE 0x08
+#define SLANG_LT 0x09
+#define SLANG_LE 0x0A
+#define SLANG_POW 0x0B
+#define SLANG_OR 0x0C
+#define SLANG_AND 0x0D
+#define SLANG_BAND 0x0E
+#define SLANG_BOR 0x0F
+#define SLANG_BXOR 0x10
+#define SLANG_SHL 0x11
+#define SLANG_SHR 0x12
+#define SLANG_MOD 0x13
+
+/* UNARY subtypes (may be overloaded) */
+#define SLANG_PLUSPLUS 0x20
+#define SLANG_MINUSMINUS 0x21
+#define SLANG_ABS 0x22
+#define SLANG_SIGN 0x23
+#define SLANG_SQR 0x24
+#define SLANG_MUL2 0x25
+#define SLANG_CHS 0x26
+#define SLANG_NOT 0x27
+#define SLANG_BNOT 0x28
+
+
+extern char *SLang_Error_Message;
+
+int SLadd_intrinsic_variable (char *, VOID_STAR, unsigned char, int);
+int SLadd_intrinsic_function (char *, FVOID_STAR, unsigned char, unsigned int,...);
+
+extern void SLadd_at_handler (long *, char *);
+
+#define MAKE_INTRINSIC_N(n,f,out,in,a1,a2,a3,a4,a5,a6,a7) \
+ {(n), NULL, SLANG_INTRINSIC, (FVOID_STAR) (f), \
+ {a1,a2,a3,a4,a5,a6,a7}, (in), (out)}
+
+#define MAKE_INTRINSIC_7(n,f,out,a1,a2,a3,a4,a5,a6,a7) \
+ MAKE_INTRINSIC_N(n,f,out,7,a1,a2,a3,a4,a5,a6,a7)
+#define MAKE_INTRINSIC_6(n,f,out,a1,a2,a3,a4,a5,a6) \
+ MAKE_INTRINSIC_N(n,f,out,6,a1,a2,a3,a4,a5,a6,0)
+#define MAKE_INTRINSIC_5(n,f,out,a1,a2,a3,a4,a5) \
+ MAKE_INTRINSIC_N(n,f,out,5,a1,a2,a3,a4,a5,0,0)
+#define MAKE_INTRINSIC_4(n,f,out,a1,a2,a3,a4) \
+ MAKE_INTRINSIC_N(n,f,out,4,a1,a2,a3,a4,0,0,0)
+#define MAKE_INTRINSIC_3(n,f,out,a1,a2,a3) \
+ MAKE_INTRINSIC_N(n,f,out,3,a1,a2,a3,0,0,0,0)
+#define MAKE_INTRINSIC_2(n,f,out,a1,a2) \
+ MAKE_INTRINSIC_N(n,f,out,2,a1,a2,0,0,0,0,0)
+#define MAKE_INTRINSIC_1(n,f,out,a1) \
+ MAKE_INTRINSIC_N(n,f,out,1,a1,0,0,0,0,0,0)
+#define MAKE_INTRINSIC_0(n,f,out) \
+ MAKE_INTRINSIC_N(n,f,out,0,0,0,0,0,0,0,0)
+
+
+
+#define MAKE_INTRINSIC_S(n,f,r) \
+ MAKE_INTRINSIC_1(n,f,r,SLANG_STRING_TYPE)
+#define MAKE_INTRINSIC_I(n,f,r) \
+ MAKE_INTRINSIC_1(n,f,r,SLANG_INT_TYPE)
+
+#define MAKE_INTRINSIC_SS(n,f,r) \
+ MAKE_INTRINSIC_2(n,f,r,SLANG_STRING_TYPE,SLANG_STRING_TYPE)
+#define MAKE_INTRINSIC_SI(n,f,r) \
+ MAKE_INTRINSIC_2(n,f,r,SLANG_STRING_TYPE,SLANG_INT_TYPE)
+#define MAKE_INTRINSIC_IS(n,f,r) \
+ MAKE_INTRINSIC_2(n,f,r,SLANG_INT_TYPE,SLANG_STRING_TYPE)
+#define MAKE_INTRINSIC_II(n,f,r) \
+ MAKE_INTRINSIC_2(n,f,r,SLANG_INT_TYPE,SLANG_INT_TYPE)
+
+#define MAKE_INTRINSIC_SSS(n,f,r) \
+ MAKE_INTRINSIC_3(n,f,r,SLANG_STRING_TYPE,SLANG_STRING_TYPE,SLANG_STRING_TYPE)
+#define MAKE_INTRINSIC_SSI(n,f,r) \
+ MAKE_INTRINSIC_3(n,f,r,SLANG_STRING_TYPE,SLANG_STRING_TYPE,SLANG_INT_TYPE)
+#define MAKE_INTRINSIC_SIS(n,f,r) \
+ MAKE_INTRINSIC_3(n,f,r,SLANG_STRING_TYPE,SLANG_INT_TYPE,SLANG_STRING_TYPE)
+#define MAKE_INTRINSIC_SII(n,f,r) \
+ MAKE_INTRINSIC_3(n,f,r,SLANG_STRING_TYPE,SLANG_INT_TYPE,SLANG_INT_TYPE)
+#define MAKE_INTRINSIC_ISS(n,f,r) \
+ MAKE_INTRINSIC_3(n,f,r,SLANG_INT_TYPE,SLANG_STRING_TYPE,SLANG_STRING_TYPE)
+#define MAKE_INTRINSIC_ISI(n,f,r) \
+ MAKE_INTRINSIC_3(n,f,r,SLANG_INT_TYPE,SLANG_STRING_TYPE,SLANG_INT_TYPE)
+#define MAKE_INTRINSIC_IIS(n,f,r) \
+ MAKE_INTRINSIC_3(n,f,r,SLANG_INT_TYPE,SLANG_INT_TYPE,SLANG_STRING_TYPE)
+#define MAKE_INTRINSIC_III(n,f,r) \
+ MAKE_INTRINSIC_3(n,f,r,SLANG_INT_TYPE,SLANG_INT_TYPE,SLANG_INT_TYPE)
+
+#define MAKE_INTRINSIC(n, f, out, in) \
+ MAKE_INTRINSIC_N(n,f,out,in,0,0,0,0,0,0,0)
+
+
+#define MAKE_VARIABLE(n, v, t, r) \
+ {n, NULL, SLANG_IVARIABLE + (r), (VOID_STAR)(v), (t)}
+
+#define MAKE_APP_UNARY(n,op) \
+ {(n), NULL, SLANG_APP_UNARY, (op)}
+
+#define MAKE_MATH_UNARY(n,op) \
+ {(n), NULL, SLANG_MATH_UNARY, (op)}
+
+#define SLANG_END_TABLE {NULL}
+
+/*}}}*/
+
+/*{{{ Upper/Lowercase Functions */
+
+extern void SLang_define_case(int *, int *);
+extern void SLang_init_case_tables (void);
+
+extern unsigned char _SLChg_UCase_Lut[256];
+extern unsigned char _SLChg_LCase_Lut[256];
+#define UPPER_CASE(x) (_SLChg_UCase_Lut[(unsigned char) (x)])
+#define LOWER_CASE(x) (_SLChg_LCase_Lut[(unsigned char) (x)])
+#define CHANGE_CASE(x) (((x) == _SLChg_LCase_Lut[(unsigned char) (x)]) ?\
+ _SLChg_UCase_Lut[(unsigned char) (x)] : _SLChg_LCase_Lut[(unsigned char) (x)])
+
+/*}}}*/
+
+/*{{{ Regular Expression Interface */
+
+typedef struct
+{
+ /* These must be set by calling routine. */
+ unsigned char *pat; /* regular expression pattern */
+ unsigned char *buf; /* buffer for compiled regexp */
+ unsigned int buf_len; /* length of buffer */
+ int case_sensitive; /* 1 if match is case sensitive */
+
+ /* The rest are set by SLang_regexp_compile */
+
+ int must_match; /* 1 if line must contain substring */
+ int must_match_bol; /* true if it must match beginning of line */
+ unsigned char must_match_str[16]; /* 15 char null term substring */
+ int osearch; /* 1 if ordinary search suffices */
+ unsigned int min_length; /* minimum length the match must be */
+ int beg_matches[10]; /* offset of start of \( */
+ unsigned int end_matches[10]; /* length of nth submatch
+ * Note that the entire match corresponds
+ * to \0
+ */
+ int offset; /* offset to be added to beg_matches */
+ int reserved[10];
+} SLRegexp_Type;
+
+extern unsigned char *SLang_regexp_match(unsigned char *,
+ unsigned int,
+ SLRegexp_Type *);
+
+/* Returns 0 upon success. If failure, the offset into the
+ * pattern is returned (start = 1).
+ */
+extern int SLang_regexp_compile (SLRegexp_Type *);
+extern char *SLregexp_quote_string (char *, char *, unsigned int);
+
+/*}}}*/
+
+/*{{{ SLang Command Interface */
+
+struct _SLcmd_Cmd_Type; /* Pre-declaration is needed below */
+typedef struct
+{
+ struct _SLcmd_Cmd_Type *table;
+ int argc;
+ /* Version 2.0 needs to use a union!! */
+ char **string_args;
+ int *int_args;
+ double *double_args;
+ unsigned char *arg_type;
+ unsigned long reserved[4];
+} SLcmd_Cmd_Table_Type;
+
+typedef struct _SLcmd_Cmd_Type
+{
+ int (*cmdfun)(int, SLcmd_Cmd_Table_Type *);
+ char *cmd;
+ char *arg_type;
+} SLcmd_Cmd_Type;
+
+extern int SLcmd_execute_string (char *, SLcmd_Cmd_Table_Type *);
+
+/*}}}*/
+
+/*{{{ SLang Search Interface */
+
+typedef struct
+{
+ int cs; /* case sensitive */
+ unsigned char key[256];
+ int ind[256];
+ int key_len;
+ int dir;
+} SLsearch_Type;
+
+extern int SLsearch_init (char *, int, int, SLsearch_Type *);
+/* This routine must first be called before any search can take place.
+ * The second parameter specifies the direction of the search: greater than
+ * zero for a forwrd search and less than zero for a backward search. The
+ * third parameter specifies whether the search is case sensitive or not.
+ * The last parameter is a pointer to a structure that is filled by this
+ * function and it is this structure that must be passed to SLsearch.
+ */
+
+extern unsigned char *SLsearch (unsigned char *, unsigned char *, SLsearch_Type *);
+/* To use this routine, you must first call 'SLsearch_init'. Then the first
+ * two parameters p1 and p2 serve to define the region over which the search
+ * is to take place. The third parameter is the structure that was previously
+ * initialized by SLsearch_init.
+ *
+ * The routine returns a pointer to the match if found otherwise it returns
+ * NULL.
+ */
+
+/*}}}*/
+
+#if 0
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DAVIS_SLANG_H_ */
diff --git a/minislang/sldisply.c b/minislang/sldisply.c
new file mode 100644
index 000000000..0d3428394
--- /dev/null
+++ b/minislang/sldisply.c
@@ -0,0 +1,2313 @@
+/* Copyright (c) 1992, 1998 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 "config.h"
+#include "sl-feat.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#if !defined(VMS) || (__VMS_VER >= 70000000)
+# include <sys/time.h>
+# ifdef __QNX__
+# include <sys/select.h>
+# endif
+# include <sys/types.h>
+#endif
+
+#ifdef __BEOS__
+/* Prototype for select */
+# include <net/socket.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+
+#ifdef VMS
+# include <unixlib.h>
+# include <unixio.h>
+# include <dvidef.h>
+# include <descrip.h>
+# include <lib$routines.h>
+# include <starlet.h>
+#else
+# if !defined(sun)
+# include <sys/ioctl.h>
+# endif
+#endif
+
+#ifdef SYSV
+# include <sys/termio.h>
+# include <sys/stream.h>
+# include <sys/ptem.h>
+# include <sys/tty.h>
+#endif
+
+#if defined (_AIX) && !defined (FD_SET)
+# include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
+#endif
+
+#include <errno.h>
+#include "slang.h"
+#include "_slang.h"
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if defined(__DECC) && defined(VMS)
+/* These get prototypes for write an sleep */
+# include <unixio.h>
+#endif
+#include <signal.h>
+
+/* Colors: These definitions are used for the display. However, the
+ * application only uses object handles which get mapped to this
+ * internal representation. The mapping is performed by the Color_Map
+ * structure below. */
+
+#define CHAR_MASK 0x000000FF
+#define FG_MASK 0x0000FF00
+#define BG_MASK 0x00FF0000
+#define ATTR_MASK 0x1F000000
+#define BGALL_MASK 0x0FFF0000
+
+/* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
+ * not include this attribute.
+ */
+
+#define GET_FG(color) ((color & FG_MASK) >> 8)
+#define GET_BG(color) ((color & BG_MASK) >> 16)
+#define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
+
+int SLtt_Screen_Cols;
+int SLtt_Screen_Rows;
+int SLtt_Term_Cannot_Insert;
+int SLtt_Term_Cannot_Scroll;
+int SLtt_Use_Ansi_Colors;
+int SLtt_Blink_Mode = 1;
+int SLtt_Use_Blink_For_ACS = 0;
+int SLtt_Newline_Ok = 0;
+int SLtt_Has_Alt_Charset = 0;
+int SLtt_Force_Keypad_Init = 0;
+
+/* -1 means unknown */
+int SLtt_Has_Status_Line = -1; /* hs */
+
+static int Automatic_Margins;
+/* static int No_Move_In_Standout; */
+static int Worthless_Highlight;
+#define HP_GLITCH_CODE
+#ifdef HP_GLITCH_CODE
+/* This glitch is exclusive to HP term. Basically it means that to clear
+ * attributes, one has to erase to the end of the line.
+ */
+static int Has_HP_Glitch;
+#endif
+
+static char *Reset_Color_String;
+
+static int Linux_Console;
+
+/* It is crucial that JMAX_COLORS must be less than 128 since the high bit
+ * is used to indicate a character from the ACS (alt char set). The exception
+ * to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
+ * the highbit is set, we interpret that as a blink character. This is
+ * exploited by DOSemu.
+ */
+#define JMAX_COLORS 256
+#define JNORMAL_COLOR 0
+
+typedef struct
+{
+ SLtt_Char_Type fgbg;
+ SLtt_Char_Type mono;
+ char *custom_esc;
+}
+Ansi_Color_Type;
+
+#define RGB1(r, g, b) ((r) | ((g) << 1) | ((b) << 2))
+#define RGB(r, g, b, br, bg, bb) ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
+
+static Ansi_Color_Type Ansi_Color_Map[JMAX_COLORS] =
+{
+ {RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL}, /* white/black */
+ {RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK, NULL}, /* green/black */
+ {RGB(1, 0, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* magenta/black */
+ {RGB(0, 1, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* cyan/black */
+ {RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK, NULL},
+ {RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
+ {RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
+ {RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK, NULL},
+ {RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK, NULL},
+ {RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK, NULL},
+ {RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
+ {RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
+ {RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
+ {RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK, NULL},
+ {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
+ {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
+ {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
+ {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL}
+};
+
+static char *Color_Fg_Str;
+static char *Color_Bg_Str;
+static char *Default_Color_Fg_Str = "\033[39m";
+static char *Default_Color_Bg_Str = "\033[49m";
+
+static int Max_Terminfo_Colors = 8; /* termcap Co */
+
+char *SLtt_Graphics_Char_Pairs; /* ac termcap string -- def is vt100 */
+
+/* 1 if terminal lacks the ability to do into insert mode or into delete
+ mode. Currently controlled by S-Lang but later perhaps termcap. */
+
+static char *UnderLine_Vid_Str;
+static char *Blink_Vid_Str;
+static char *Bold_Vid_Str;
+static char *Ins_Mode_Str; /* = "\033[4h"; */ /* ins mode (im) */
+static char *Eins_Mode_Str; /* = "\033[4l"; */ /* end ins mode (ei) */
+static char *Scroll_R_Str; /* = "\033[%d;%dr"; */ /* scroll region */
+static char *Cls_Str; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
+static char *Rev_Vid_Str; /* = "\033[7m"; */ /* mr,so termcap string */
+static char *Norm_Vid_Str; /* = "\033[m"; */ /* me,se termcap string */
+static char *Del_Eol_Str; /* = "\033[K"; */ /* ce */
+static char *Del_Char_Str; /* = "\033[P"; */ /* dc */
+static char *Del_N_Lines_Str; /* = "\033[%dM"; */ /* DL */
+static char *Add_N_Lines_Str; /* = "\033[%dL"; */ /* AL */
+static char *Rev_Scroll_Str;
+static char *Curs_Up_Str;
+static char *Curs_F_Str; /* RI termcap string */
+static char *Cursor_Visible_Str; /* ve termcap string */
+static char *Cursor_Invisible_Str; /* vi termcap string */
+
+static char *Start_Alt_Chars_Str; /* as */
+static char *End_Alt_Chars_Str; /* ae */
+static char *Enable_Alt_Char_Set; /* eA */
+
+static char *Term_Init_Str;
+static char *Keypad_Init_Str;
+static char *Term_Reset_Str;
+static char *Keypad_Reset_Str;
+
+/* status line functions */
+static char *Disable_Status_line_Str; /* ds */
+static char *Return_From_Status_Line_Str; /* fs */
+static char *Goto_Status_Line_Str; /* ts */
+static int Num_Status_Line_Columns; /* ws */
+static int Status_Line_Esc_Ok; /* es */
+
+/* static int Len_Curs_F_Str = 5; */
+
+/* cm string has %i%d since termcap numbers columns from 0 */
+/* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
+static char *Curs_Pos_Str; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
+
+/* scrolling region */
+static int Scroll_r1 = 0, Scroll_r2 = 23;
+static int Cursor_r, Cursor_c; /* 0 based */
+
+/* current attributes --- initialized to impossible value */
+static SLtt_Char_Type Current_Fgbg = 0xFFFFFFFFU;
+
+static int Cursor_Set; /* 1 if cursor position known, 0
+ * if not. -1 if only row is known
+ */
+
+#define MAX_OUTPUT_BUFFER_SIZE 4096
+
+static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];
+static unsigned char *Output_Bufferp = Output_Buffer;
+
+unsigned long SLtt_Num_Chars_Output;
+
+static int sl_usleep (unsigned long usecs)
+{
+#if !defined(VMS) || (__VMS_VER >= 70000000)
+ struct timeval tv;
+ tv.tv_sec = usecs / 1000000;
+ tv.tv_usec = usecs % 1000000;
+ return select(0, NULL, NULL, NULL, &tv);
+#else
+ return 0;
+#endif
+}
+
+int SLtt_flush_output (void)
+{
+ int nwrite = 0;
+ unsigned int total;
+ int n = (int) (Output_Bufferp - Output_Buffer);
+
+ SLtt_Num_Chars_Output += n;
+
+ total = 0;
+ while (n > 0)
+ {
+ nwrite = write (fileno(stdout), (char *) Output_Buffer + total, n);
+ if (nwrite == -1)
+ {
+ nwrite = 0;
+#ifdef EAGAIN
+ if (errno == EAGAIN)
+ {
+ sl_usleep (100000); /* 1/10 sec */
+ continue;
+ }
+#endif
+#ifdef EWOULDBLOCK
+ if (errno == EWOULDBLOCK)
+ {
+ sl_usleep (100000);
+ continue;
+ }
+#endif
+#ifdef EINTR
+ if (errno == EINTR) continue;
+#endif
+ break;
+ }
+ n -= nwrite;
+ total += nwrite;
+ }
+ Output_Bufferp = Output_Buffer;
+ return n;
+}
+
+int SLtt_Baud_Rate;
+static void tt_write(char *str, unsigned int n)
+{
+ static unsigned long last_time;
+ static int total;
+ unsigned long now;
+ unsigned int ndiff;
+
+ if ((str == NULL) || (n == 0)) return;
+ total += n;
+
+ while (1)
+ {
+ ndiff = MAX_OUTPUT_BUFFER_SIZE - (int) (Output_Bufferp - Output_Buffer);
+ if (ndiff < n)
+ {
+ SLMEMCPY ((char *) Output_Bufferp, (char *) str, ndiff);
+ Output_Bufferp += ndiff;
+ SLtt_flush_output ();
+ n -= ndiff;
+ str += ndiff;
+ }
+ else
+ {
+ SLMEMCPY ((char *) Output_Bufferp, str, n);
+ Output_Bufferp += n;
+ break;
+ }
+ }
+
+ if (((SLtt_Baud_Rate > 150) && (SLtt_Baud_Rate <= 9600))
+ && (10 * total > SLtt_Baud_Rate))
+ {
+ total = 0;
+ if ((now = (unsigned long) time(NULL)) - last_time <= 1)
+ {
+ SLtt_flush_output ();
+ sleep((unsigned) 1);
+ }
+ last_time = now;
+ }
+}
+
+static void tt_write_string (char *str)
+{
+ if (str != NULL) tt_write(str, strlen(str));
+}
+
+void SLtt_write_string (char *str)
+{
+ tt_write_string (str);
+ Cursor_Set = 0;
+}
+
+void SLtt_putchar (char ch)
+{
+ SLtt_normal_video ();
+ if (Cursor_Set == 1)
+ {
+ if (ch >= ' ') Cursor_c++;
+ else if (ch == '\b') Cursor_c--;
+ else if (ch == '\r') Cursor_c = 0;
+ else Cursor_Set = 0;
+
+ if ((Cursor_c + 1 == SLtt_Screen_Cols)
+ && Automatic_Margins) Cursor_Set = 0;
+ }
+
+ if (Output_Bufferp < Output_Buffer + MAX_OUTPUT_BUFFER_SIZE)
+ {
+ *Output_Bufferp++ = (unsigned char) ch;
+ }
+ else tt_write (&ch, 1);
+}
+
+static unsigned int tt_sprintf(char *buf, char *fmt, int x, int y)
+{
+ char *fmt_max;
+ register unsigned char *b, ch;
+ int offset;
+ int z, z1, parse_level;
+ int zero_pad;
+ int field_width;
+ int variables [26];
+ int stack [64];
+ unsigned int stack_len;
+ int parms [10];
+#define STACK_POP (stack_len ? stack[--stack_len] : 0)
+
+ if (fmt == NULL)
+ {
+ *buf = 0;
+ return 0;
+ }
+
+ stack [0] = y; /* pushed for termcap */
+ stack [1] = x;
+ stack_len = 2;
+
+ parms [1] = x; /* p1 */
+ parms [2] = y; /* p2 */
+
+ offset = 0;
+ zero_pad = 0;
+ field_width = 0;
+
+ b = (unsigned char *) buf;
+ fmt_max = fmt + strlen (fmt);
+
+ while (fmt < fmt_max)
+ {
+ ch = *fmt++;
+
+ if (ch != '%')
+ {
+ *b++ = ch;
+ continue;
+ }
+
+ if (fmt == fmt_max) break;
+ ch = *fmt++;
+
+ switch (ch)
+ {
+ default:
+ *b++ = ch;
+ break;
+
+ case 'p':
+
+ if (fmt == fmt_max) break;
+ ch = *fmt++;
+ if ((ch >= '0') && (ch <= '9'))
+ stack [stack_len++] = parms [ch - '0'];
+ break;
+
+ case '\'': /* 'x' */
+ if (fmt == fmt_max) break;
+ stack [stack_len++] = *fmt++;
+ if (fmt < fmt_max) fmt++; /* skip ' */
+ break;
+
+ case '{': /* literal constant, e.g. {30} */
+ z = 0;
+ while ((fmt < fmt_max) && ((ch = *fmt) <= '9') && (ch >= '0'))
+ {
+ z = z * 10 + (ch - '0');
+ fmt++;
+ }
+ stack [stack_len++] = z;
+ if ((ch == '}') && (fmt < fmt_max)) fmt++;
+ break;
+
+ case '0':
+ if (fmt == fmt_max) break;
+ ch = *fmt;
+ if ((ch != '2') && (ch != '3'))
+ break;
+ zero_pad = 1;
+ fmt++;
+ /* drop */
+
+ case '2':
+ case '3':
+ if (fmt == fmt_max)
+ if (*fmt == 'x')
+ {
+ char x_fmt_buf [4];
+ char *x_fmt_buf_ptr;
+
+ x_fmt_buf_ptr = x_fmt_buf;
+ if (zero_pad) *x_fmt_buf_ptr++ = '0';
+ *x_fmt_buf_ptr++ = ch;
+ *x_fmt_buf_ptr++ = 'X';
+ *x_fmt_buf_ptr = 0;
+
+ z = STACK_POP;
+ z += offset;
+
+ sprintf ((char *)b, x_fmt_buf, z);
+ b += strlen ((char *)b);
+ zero_pad = 0;
+ break;
+ }
+
+ field_width = (ch - '0');
+ /* drop */
+
+ case 'd':
+ z = STACK_POP;
+ z += offset;
+ if (z >= 100)
+ {
+ *b++ = z / 100 + '0';
+ z = z % 100;
+ zero_pad = 1;
+ field_width = 2;
+ }
+ else if (zero_pad && (field_width == 3))
+ *b++ = '0';
+
+ if (z >= 10)
+ {
+ *b++ = z / 10 + '0';
+ z = z % 10;
+ }
+ else if (zero_pad && (field_width >= 2))
+ *b++ = '0';
+
+ *b++ = z + '0';
+ field_width = zero_pad = 0;
+ break;
+
+ case 'x':
+ z = STACK_POP;
+ z += offset;
+ sprintf ((char *) b, "%X", z);
+ b += strlen ((char *)b);
+ break;
+
+ case 'i':
+ offset = 1;
+ break;
+
+ case '+':
+ /* Handling this depends upon whether or not we are parsing
+ * terminfo. Terminfo requires the stack so use it as an
+ * indicator.
+ */
+ if (stack_len > 2)
+ {
+ z = STACK_POP;
+ stack [stack_len - 1] += z;
+ }
+ else if (fmt < fmt_max)
+ {
+ ch = *fmt++;
+ if ((unsigned char) ch == 128) ch = 0;
+ ch = ch + (unsigned char) STACK_POP;
+ if (ch == '\n') ch++;
+ *b++ = ch;
+ }
+ break;
+
+ /* Binary operators */
+ case '-':
+ case '*':
+ case '/':
+ case 'm':
+ case '&':
+ case '|':
+ case '^':
+ case '=':
+ case '>':
+ case '<':
+ case 'A':
+ case 'O':
+ z1 = STACK_POP;
+ z = STACK_POP;
+ switch (ch)
+ {
+ case '-': z = (z - z1); break;
+ case '*': z = (z * z1); break;
+ case '/': z = (z / z1); break;
+ case 'm': z = (z % z1); break;
+ case '&': z = (z & z1); break;
+ case '|': z = (z | z1); break;
+ case '^': z = (z ^ z1); break;
+ case '=': z = (z == z1); break;
+ case '>': z = (z > z1); break;
+ case '<': z = (z < z1); break;
+ case 'A': z = (z && z1); break;
+ case 'O': z = (z || z1); break;
+ }
+ stack [stack_len++] = z;
+ break;
+
+ /* unary */
+ case '!':
+ z = STACK_POP;
+ stack [stack_len++] = !z;
+ break;
+
+ case '~':
+ z = STACK_POP;
+ stack [stack_len++] = ~z;
+ break;
+
+ case 'r': /* termcap -- swap parameters */
+ z = stack [0];
+ stack [0] = stack [1];
+ stack [1] = z;
+ break;
+
+ case '.': /* termcap */
+ case 'c':
+ ch = (unsigned char) STACK_POP;
+ if (ch == '\n') ch++;
+ *b++ = ch;
+ break;
+
+ case 'g':
+ if (fmt == fmt_max) break;
+ ch = *fmt++;
+ if ((ch >= 'a') && (ch <= 'z'))
+ stack [stack_len++] = variables [ch - 'a'];
+ break;
+
+ case 'P':
+ if (fmt == fmt_max) break;
+ ch = *fmt++;
+ if ((ch >= 'a') && (ch <= 'z'))
+ variables [ch - 'a'] = STACK_POP;
+ break;
+
+ /* If then else parsing. Actually, this is rather easy. The
+ * key is to notice that 'then' does all the work. 'if' simply
+ * there to indicate the start of a test and endif indicates
+ * the end of tests. If 'else' is seen, then skip to
+ * endif.
+ */
+ case '?': /* if */
+ case ';': /* endif */
+ break;
+
+ case 't': /* then */
+ z = STACK_POP;
+ if (z != 0)
+ break; /* good. Continue parsing. */
+
+ /* z == 0 and test has failed. So, skip past this entire if
+ * expression to the matching else or matching endif.
+ */
+ /* drop */
+ case 'e': /* else */
+
+ parse_level = 0;
+ while (fmt < fmt_max)
+ {
+ unsigned char ch1;
+
+ ch1 = *fmt++;
+ if ((ch1 != '%') || (fmt == fmt_max))
+ continue;
+
+ ch1 = *fmt++;
+
+ if (ch1 == '?') parse_level++; /* new if */
+ else if (ch1 == 'e')
+ {
+ if ((ch != 'e') && (parse_level == 0))
+ break;
+ }
+ else if (ch1 == ';')
+ {
+ if (parse_level == 0)
+ break;
+ parse_level--;
+ }
+ }
+ break;
+ }
+ }
+ *b = 0;
+ return (unsigned int) (b - (unsigned char *) buf);
+}
+
+static void tt_printf(char *fmt, int x, int y)
+{
+ char buf[1024];
+ unsigned int n;
+ if (fmt == NULL) return;
+ n = tt_sprintf(buf, fmt, x, y);
+ tt_write(buf, n);
+}
+
+void SLtt_set_scroll_region (int r1, int r2)
+{
+ Scroll_r1 = r1;
+ Scroll_r2 = r2;
+ tt_printf (Scroll_R_Str, Scroll_r1, Scroll_r2);
+ Cursor_Set = 0;
+}
+
+void SLtt_reset_scroll_region (void)
+{
+ SLtt_set_scroll_region(0, SLtt_Screen_Rows - 1);
+}
+
+int SLtt_set_cursor_visibility (int show)
+{
+ if ((Cursor_Visible_Str == NULL) || (Cursor_Invisible_Str == NULL))
+ return -1;
+
+ tt_write_string (show ? Cursor_Visible_Str : Cursor_Invisible_Str);
+ return 0;
+}
+
+/* the goto_rc function moves to row relative to scrolling region */
+void SLtt_goto_rc(int r, int c)
+{
+ char *s = NULL;
+ int n;
+ char buf[6];
+
+ if ((c < 0) || (r < 0))
+ {
+ Cursor_Set = 0;
+ return;
+ }
+
+ /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
+ r += Scroll_r1;
+
+ if ((Cursor_Set > 0) || ((Cursor_Set < 0) && !Automatic_Margins))
+ {
+ n = r - Cursor_r;
+ if ((n == -1) && (Cursor_Set > 0) && (Cursor_c == c)
+ && (Curs_Up_Str != NULL))
+ {
+ s = Curs_Up_Str;
+ }
+ else if ((n >= 0) && (n <= 4))
+ {
+ if ((n == 0) && (Cursor_Set == 1)
+ && ((c > 1) || (c == Cursor_c)))
+ {
+ if (Cursor_c == c) return;
+ if (Cursor_c == c + 1)
+ {
+ s = buf;
+ *s++ = '\b'; *s = 0;
+ s = buf;
+ }
+ }
+ else if (c == 0)
+ {
+ s = buf;
+ if ((Cursor_Set != 1) || (Cursor_c != 0)) *s++ = '\r';
+ while (n--) *s++ = '\n';
+#ifdef VMS
+ /* Need to add this after \n to start a new record. Sheesh. */
+ *s++ = '\r';
+#endif
+ *s = 0;
+ s = buf;
+ }
+ /* Will fail on VMS */
+#ifndef VMS
+ else if (SLtt_Newline_Ok && (Cursor_Set == 1) &&
+ (Cursor_c >= c) && (c + 3 > Cursor_c))
+ {
+ s = buf;
+ while (n--) *s++ = '\n';
+ n = Cursor_c - c;
+ while (n--) *s++ = '\b';
+ *s = 0;
+ s = buf;
+ }
+#endif
+ }
+ }
+ if (s != NULL) tt_write_string(s);
+ else tt_printf(Curs_Pos_Str, r, c);
+ Cursor_c = c; Cursor_r = r;
+ Cursor_Set = 1;
+}
+
+void SLtt_begin_insert (void)
+{
+ tt_write_string(Ins_Mode_Str);
+}
+
+void SLtt_end_insert (void)
+{
+ tt_write_string(Eins_Mode_Str);
+}
+
+void SLtt_delete_char (void)
+{
+ SLtt_normal_video ();
+ tt_write_string(Del_Char_Str);
+}
+
+void SLtt_erase_line (void)
+{
+ tt_write_string("\r");
+ Cursor_Set = 1; Cursor_c = 0;
+ SLtt_del_eol();
+}
+
+/* It appears that the Linux console, and most likely others do not
+ * like scrolling regions that consist of one line. So I have to
+ * resort to this stupidity to make up for that stupidity.
+ */
+static void delete_line_in_scroll_region (void)
+{
+ SLtt_goto_rc (Cursor_r - Scroll_r1, 0);
+ SLtt_del_eol ();
+}
+
+void SLtt_delete_nlines (int n)
+{
+ int r1, curs;
+ char buf[132];
+
+ if (n <= 0) return;
+ SLtt_normal_video ();
+
+ if (Scroll_r1 == Scroll_r2)
+ {
+ delete_line_in_scroll_region ();
+ return;
+ }
+
+ if (Del_N_Lines_Str != NULL) tt_printf(Del_N_Lines_Str,n, 0);
+ else
+ /* get a new terminal */
+ {
+ r1 = Scroll_r1;
+ curs = Cursor_r;
+ SLtt_set_scroll_region(curs, Scroll_r2);
+ SLtt_goto_rc(Scroll_r2 - Scroll_r1, 0);
+ SLMEMSET(buf, '\n', (unsigned int) n);
+ tt_write(buf, (unsigned int) n);
+ /* while (n--) tt_putchar('\n'); */
+ SLtt_set_scroll_region(r1, Scroll_r2);
+ SLtt_goto_rc(curs, 0);
+ }
+}
+
+void SLtt_cls (void)
+{
+ SLtt_normal_video();
+ SLtt_reset_scroll_region ();
+ tt_write_string(Cls_Str);
+}
+
+void SLtt_reverse_index (int n)
+{
+ if (!n) return;
+
+ SLtt_normal_video();
+
+ if (Scroll_r1 == Scroll_r2)
+ {
+ delete_line_in_scroll_region ();
+ return;
+ }
+
+ if (Add_N_Lines_Str != NULL) tt_printf(Add_N_Lines_Str,n, 0);
+ else
+ {
+ while(n--) tt_write_string(Rev_Scroll_Str);
+ }
+}
+
+int SLtt_Ignore_Beep = 1;
+static char *Visible_Bell_Str;
+
+void SLtt_beep (void)
+{
+ if (SLtt_Ignore_Beep & 0x1) SLtt_putchar('\007');
+
+ if (SLtt_Ignore_Beep & 0x2)
+ {
+ if (Visible_Bell_Str != NULL) tt_write_string (Visible_Bell_Str);
+#ifdef __linux__
+ else if (Linux_Console)
+ {
+ tt_write_string ("\033[?5h");
+ SLtt_flush_output ();
+ sl_usleep (50000);
+ tt_write_string ("\033[?5l");
+ }
+#endif
+ }
+ SLtt_flush_output ();
+}
+
+void SLtt_del_eol (void)
+{
+ if (Current_Fgbg != 0xFFFFFFFFU) SLtt_normal_video ();
+ tt_write_string(Del_Eol_Str);
+}
+
+typedef struct
+{
+ char *name;
+ SLtt_Char_Type color;
+}
+Color_Def_Type;
+
+#define MAX_COLOR_NAMES 17
+static Color_Def_Type Color_Defs [MAX_COLOR_NAMES] =
+{
+ {"black", SLSMG_COLOR_BLACK},
+ {"red", SLSMG_COLOR_RED},
+ {"green", SLSMG_COLOR_GREEN},
+ {"brown", SLSMG_COLOR_BROWN},
+ {"blue", SLSMG_COLOR_BLUE},
+ {"magenta", SLSMG_COLOR_MAGENTA},
+ {"cyan", SLSMG_COLOR_CYAN},
+ {"lightgray", SLSMG_COLOR_LGRAY},
+ {"gray", SLSMG_COLOR_GRAY},
+ {"brightred", SLSMG_COLOR_BRIGHT_RED},
+ {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN},
+ {"yellow", SLSMG_COLOR_BRIGHT_BROWN},
+ {"brightblue", SLSMG_COLOR_BRIGHT_BLUE},
+ {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN},
+ {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA},
+ {"white", SLSMG_COLOR_BRIGHT_WHITE},
+#define SLSMG_COLOR_DEFAULT 0xFF
+ {"default", SLSMG_COLOR_DEFAULT}
+};
+
+void SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
+{
+ (void) what;
+ if ((obj < 0) || (obj >= JMAX_COLORS))
+ {
+ return;
+ }
+ Ansi_Color_Map[obj].mono = mask & ATTR_MASK;
+}
+
+static char *check_color_for_digit_form (char *color)
+{
+ unsigned int i, ich;
+ char *s = color;
+
+ i = 0;
+ while ((ich = (int) *s) != 0)
+ {
+ if ((ich < '0') || (ich > '9'))
+ return color;
+
+ i = i * 10 + (ich - '0');
+ s++;
+ }
+
+ if (i < MAX_COLOR_NAMES)
+ color = Color_Defs[i].name;
+
+ return color;
+}
+
+static int get_default_colors (char **fgp, char **bgp)
+{
+ static char fg_buf[16], bg_buf[16], *bg, *fg;
+ static int already_parsed;
+ char *p, *pmax;
+
+ if (already_parsed == -1)
+ return -1;
+
+ if (already_parsed)
+ {
+ *fgp = fg;
+ *bgp = bg;
+ return 0;
+ }
+
+ already_parsed = -1;
+
+ bg = getenv ("COLORFGBG");
+
+ if (bg == NULL)
+ {
+ bg = getenv ("DEFAULT_COLORS");
+ if (bg == NULL)
+ return -1;
+ }
+
+ p = fg_buf;
+ pmax = p + (sizeof (fg_buf) - 1);
+
+ while ((*bg != 0) && (*bg != ';'))
+ {
+ if (p < pmax) *p++ = *bg;
+ bg++;
+ }
+ *p = 0;
+
+ if (*bg) bg++;
+
+ p = bg_buf;
+ pmax = p + (sizeof (bg_buf) - 1);
+
+ /* Mark suggested allowing for extra spplication specific stuff following
+ * the background color. That is what the check for the semi-colon is for.
+ */
+ while ((*bg != 0) && (*bg != ';'))
+ {
+ if (p < pmax) *p++ = *bg;
+ bg++;
+ }
+ *p = 0;
+
+ if (!strcmp (fg_buf, "default") || !strcmp(bg_buf, "default"))
+ {
+ *fgp = *bgp = fg = bg = "default";
+ }
+ else
+ {
+ *fgp = fg = check_color_for_digit_form (fg_buf);
+ *bgp = bg = check_color_for_digit_form (bg_buf);
+ }
+ already_parsed = 1;
+ return 0;
+}
+
+static unsigned char FgBg_Stats[JMAX_COLORS];
+
+static int Color_0_Modified = 0;
+
+void SLtt_set_color_object (int obj, SLtt_Char_Type attr)
+{
+ char *cust_esc;
+
+ if ((obj < 0) || (obj >= JMAX_COLORS)) return;
+
+ cust_esc = Ansi_Color_Map[obj].custom_esc;
+ if (cust_esc != NULL)
+ {
+ SLfree (cust_esc);
+ FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
+ Ansi_Color_Map[obj].custom_esc = NULL;
+ }
+
+ Ansi_Color_Map[obj].fgbg = attr;
+ if (obj == 0) Color_0_Modified = 1;
+}
+
+SLtt_Char_Type SLtt_get_color_object (int obj)
+{
+ if ((obj < 0) || (obj >= JMAX_COLORS)) return 0;
+ return Ansi_Color_Map[obj].fgbg;
+}
+
+void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
+{
+ if ((obj < 0) || (obj >= JMAX_COLORS)) return;
+
+ Ansi_Color_Map[obj].fgbg |= (attr & ATTR_MASK);
+ if (obj == 0) Color_0_Modified = 1;
+}
+
+static SLtt_Char_Type fb_to_fgbg (SLtt_Char_Type f, SLtt_Char_Type b)
+{
+ SLtt_Char_Type attr;
+
+ if (Max_Terminfo_Colors != 8)
+ {
+ if (f != SLSMG_COLOR_DEFAULT) f %= Max_Terminfo_Colors;
+ if (b != SLSMG_COLOR_DEFAULT) b %= Max_Terminfo_Colors;
+ return ((f << 8) | (b << 16));
+ }
+
+ /* Otherwise we have 8 ansi colors. Try to get bright versions
+ * by using the BOLD and BLINK attributes.
+ */
+
+ attr = 0;
+
+ /* Note: If f represents default, it will have the value 0xFF */
+ if (f != SLSMG_COLOR_DEFAULT)
+ {
+ if (f & 0x8) attr = SLTT_BOLD_MASK;
+ f &= 0x7;
+ }
+
+ if (b != SLSMG_COLOR_DEFAULT)
+ {
+ if (b & 0x8) attr |= SLTT_BLINK_MASK;
+ b &= 0x7;
+ }
+
+ return ((f << 8) | (b << 16) | attr);
+}
+
+/* This looks for colors with name form 'colorN'. If color is of this
+ * form, N is passed back via paramter list.
+ */
+static int parse_color_digit_name (char *color, SLtt_Char_Type *f)
+{
+ unsigned int i;
+ unsigned char ch;
+
+ if (strncmp (color, "color", 5))
+ return -1;
+
+ color += 5;
+ if (*color == 0)
+ return -1;
+
+ i = 0;
+ while (1)
+ {
+ ch = (unsigned char) *color++;
+ if (ch == 0)
+ break;
+ if ((ch > '9') || (ch < '0'))
+ return -1;
+ i = 10 * i + (ch - '0');
+ }
+
+ *f = (SLtt_Char_Type) i;
+ return 0;
+}
+
+static int make_color_fgbg (char *fg, char *bg, SLtt_Char_Type *fgbg)
+{
+ SLtt_Char_Type f = 0xFFFFFFFFU, b = 0xFFFFFFFFU;
+ char *dfg, *dbg;
+ unsigned int i;
+
+ if ((fg != NULL) && (*fg == 0)) fg = NULL;
+ if ((bg != NULL) && (*bg == 0)) bg = NULL;
+
+ if ((fg == NULL) || (bg == NULL))
+ {
+ if (-1 == get_default_colors (&dfg, &dbg))
+ return -1;
+
+ if (fg == NULL) fg = dfg;
+ if (bg == NULL) bg = dbg;
+ }
+
+ if (-1 == parse_color_digit_name (fg, &f))
+ {
+ for (i = 0; i < MAX_COLOR_NAMES; i++)
+ {
+ if (strcmp(fg, Color_Defs[i].name)) continue;
+ f = Color_Defs[i].color;
+ break;
+ }
+ }
+
+ if (-1 == parse_color_digit_name (bg, &b))
+ {
+ for (i = 0; i < MAX_COLOR_NAMES; i++)
+ {
+ if (strcmp(bg, Color_Defs[i].name)) continue;
+ b = Color_Defs[i].color;
+ break;
+ }
+ }
+
+ if ((f == 0xFFFFFFFFU) || (b == 0xFFFFFFFFU))
+ return -1;
+
+ *fgbg = fb_to_fgbg (f, b);
+ return 0;
+}
+
+void SLtt_set_color (int obj, char *what, char *fg, char *bg)
+{
+ SLtt_Char_Type fgbg;
+
+ (void) what;
+ if ((obj < 0) || (obj >= JMAX_COLORS))
+ return;
+
+ if (-1 != make_color_fgbg (fg, bg, &fgbg))
+ SLtt_set_color_object (obj, fgbg);
+}
+
+void SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
+{
+ SLtt_set_color_object (obj, fb_to_fgbg (f, b));
+}
+
+void SLtt_set_color_esc (int obj, char *esc)
+{
+ char *cust_esc;
+ SLtt_Char_Type fgbg = 0;
+ int i;
+
+ if ((obj < 0) || (obj >= JMAX_COLORS))
+ {
+ return;
+ }
+
+ cust_esc = Ansi_Color_Map[obj].custom_esc;
+ if (cust_esc != NULL)
+ {
+ SLfree (cust_esc);
+ FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
+ }
+
+ cust_esc = (char *) SLmalloc (strlen(esc) + 1);
+ if (cust_esc != NULL) strcpy (cust_esc, esc);
+
+ Ansi_Color_Map[obj].custom_esc = cust_esc;
+ if (cust_esc == NULL) fgbg = 0;
+ else
+ {
+ /* The whole point of this is to generate a unique fgbg */
+ for (i = 0; i < JMAX_COLORS; i++)
+ {
+ if (FgBg_Stats[i] == 0) fgbg = i;
+
+ if (obj == i) continue;
+ if ((Ansi_Color_Map[i].custom_esc) == NULL) continue;
+ if (!strcmp (Ansi_Color_Map[i].custom_esc, cust_esc))
+ {
+ fgbg = (Ansi_Color_Map[i].fgbg >> 8) & 0x7F;
+ break;
+ }
+ }
+ FgBg_Stats[fgbg] += 1;
+ }
+
+ fgbg |= 0x80;
+ Ansi_Color_Map[obj].fgbg = (fgbg | (fgbg << 8)) << 8;
+ if (obj == 0) Color_0_Modified = 1;
+}
+
+void SLtt_set_alt_char_set (int i)
+{
+ static int last_i;
+ if (SLtt_Has_Alt_Charset == 0) return;
+ if (i == last_i) return;
+ tt_write_string (i ? Start_Alt_Chars_Str : End_Alt_Chars_Str );
+ last_i = i;
+}
+
+static void write_attributes (SLtt_Char_Type fgbg)
+{
+ int bg0, fg0;
+
+ if (Worthless_Highlight) return;
+ if (fgbg == Current_Fgbg) return;
+
+ /* Before spitting out colors, fix attributes */
+ if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
+ {
+ if (Current_Fgbg & ATTR_MASK)
+ {
+ tt_write_string(Norm_Vid_Str);
+ /* In case normal video turns off ALL attributes: */
+ if (fgbg & SLTT_ALTC_MASK)
+ Current_Fgbg &= ~SLTT_ALTC_MASK;
+ SLtt_set_alt_char_set (0);
+ }
+
+ if ((fgbg & SLTT_ALTC_MASK)
+ != (Current_Fgbg & SLTT_ALTC_MASK))
+ {
+ SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
+ }
+
+ if (fgbg & SLTT_ULINE_MASK) tt_write_string (UnderLine_Vid_Str);
+ if (fgbg & SLTT_BOLD_MASK) SLtt_bold_video ();
+ if (fgbg & SLTT_REV_MASK) tt_write_string (Rev_Vid_Str);
+ if (fgbg & SLTT_BLINK_MASK)
+ {
+ /* Someday Linux will have a blink mode that set high intensity
+ * background. Lets be prepared.
+ */
+ if (SLtt_Blink_Mode) tt_write_string (Blink_Vid_Str);
+ }
+ }
+
+ if (SLtt_Use_Ansi_Colors)
+ {
+ fg0 = (int) GET_FG(fgbg);
+ bg0 = (int) GET_BG(fgbg);
+
+ if (fg0 == SLSMG_COLOR_DEFAULT)
+ tt_write_string (Default_Color_Fg_Str);
+ else
+ tt_printf (Color_Fg_Str, fg0, 0);
+
+ if (bg0 == SLSMG_COLOR_DEFAULT)
+ tt_write_string (Default_Color_Bg_Str);
+ else
+ tt_printf (Color_Bg_Str, bg0, 0);
+ }
+ Current_Fgbg = fgbg;
+}
+
+static int Video_Initialized;
+
+void SLtt_reverse_video (int color)
+{
+ SLtt_Char_Type fgbg;
+ char *esc;
+
+ if (Worthless_Highlight) return;
+ if ((color < 0) || (color >= JMAX_COLORS)) return;
+
+ if (Video_Initialized == 0)
+ {
+ if (color == JNORMAL_COLOR)
+ {
+ tt_write_string (Norm_Vid_Str);
+ }
+ else tt_write_string (Rev_Vid_Str);
+ Current_Fgbg = 0xFFFFFFFFU;
+ return;
+ }
+
+ if (SLtt_Use_Ansi_Colors)
+ {
+ fgbg = Ansi_Color_Map[color].fgbg;
+ if ((esc = Ansi_Color_Map[color].custom_esc) != NULL)
+ {
+ if (fgbg != Current_Fgbg)
+ {
+ Current_Fgbg = fgbg;
+ tt_write_string (esc);
+ return;
+ }
+ }
+ }
+ else fgbg = Ansi_Color_Map[color].mono;
+
+ if (fgbg == Current_Fgbg) return;
+ write_attributes (fgbg);
+}
+
+void SLtt_normal_video (void)
+{
+ SLtt_reverse_video(JNORMAL_COLOR);
+}
+
+void SLtt_narrow_width (void)
+{
+ tt_write_string("\033[?3l");
+}
+
+void SLtt_wide_width (void)
+{
+ tt_write_string("\033[?3h");
+}
+
+/* Highest bit represents the character set. */
+#define COLOR_MASK 0x7F00
+
+#define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
+/*
+#define COLOR_EQS(a, b) \
+ (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)
+*/
+
+#define COLOR_EQS(a, b) \
+ (SLtt_Use_Ansi_Colors \
+ ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
+ : (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
+
+#define CHAR_EQS(a, b) (((a) == (b))\
+ || ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
+ && COLOR_EQS((a), (b))))
+
+/* The whole point of this routine is to prevent writing to the last column
+ * and last row on terminals with automatic margins.
+ */
+static void write_string_with_care (char *str)
+{
+ unsigned int len;
+
+ if (str == NULL) return;
+
+ len = strlen (str);
+ if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
+ {
+ if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
+ {
+ /* For now, just do not write there. Later, something more
+ * sophisticated will be implemented.
+ */
+ if (SLtt_Screen_Cols > Cursor_c)
+ len = SLtt_Screen_Cols - Cursor_c - 1;
+ else len = 0;
+ }
+ }
+ tt_write (str, len);
+}
+
+static void send_attr_str (unsigned short *s)
+{
+ unsigned char out[256], ch, *p;
+ register SLtt_Char_Type attr;
+ register unsigned short sh;
+ int color, last_color = -1;
+
+ p = out;
+ while (0 != (sh = *s++))
+ {
+ ch = sh & 0xFF;
+ color = ((int) sh & 0xFF00) >> 8;
+ if (color != last_color)
+ {
+ if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
+ else attr = Ansi_Color_Map[color & 0x7F].mono;
+
+ if (sh & 0x8000) /* alternate char set */
+ {
+ if (SLtt_Use_Blink_For_ACS)
+ {
+ if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
+ }
+ else attr |= SLTT_ALTC_MASK;
+ }
+
+ if (attr != Current_Fgbg)
+ {
+ if ((ch != ' ') ||
+ /* it is a space so only consider it different if it
+ * has different attributes.
+ */
+ (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK))
+ {
+ if (p != out)
+ {
+ *p = 0;
+ write_string_with_care ((char *) out);
+ Cursor_c += (int) (p - out);
+ p = out;
+ }
+
+ if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
+ {
+ tt_write_string (Ansi_Color_Map[color & 0x7F].custom_esc);
+ /* Just in case the custom escape sequence screwed up
+ * the alt character set state...
+ */
+ if ((attr & SLTT_ALTC_MASK) != (Current_Fgbg & SLTT_ALTC_MASK))
+ SLtt_set_alt_char_set ((int) (attr & SLTT_ALTC_MASK));
+ Current_Fgbg = attr;
+ }
+ else write_attributes (attr);
+
+ last_color = color;
+ }
+ }
+ }
+ *p++ = ch;
+ }
+ *p = 0;
+ if (p != out) write_string_with_care ((char *) out);
+ Cursor_c += (int) (p - out);
+}
+
+static void forward_cursor (unsigned int n, int row)
+{
+ char buf [1024];
+
+ if (n <= 4)
+ {
+ SLtt_normal_video ();
+ SLMEMSET (buf, ' ', n);
+ buf[n] = 0;
+ write_string_with_care (buf);
+ Cursor_c += n;
+ }
+ else if (Curs_F_Str != NULL)
+ {
+ Cursor_c += n;
+ n = tt_sprintf(buf, Curs_F_Str, (int) n, 0);
+ tt_write(buf, n);
+ }
+ else SLtt_goto_rc (row, (int) (Cursor_c + n));
+}
+
+#define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 8))
+
+void SLtt_smart_puts(unsigned short *neww, unsigned short *oldd, int len, int row)
+{
+ register unsigned short *p, *q, *qmax, *pmax, *buf;
+ unsigned short buffer[256];
+ unsigned int n_spaces;
+ unsigned short *space_match, *last_buffered_match;
+#ifdef HP_GLITCH_CODE
+ int handle_hp_glitch = 0;
+#endif
+
+ q = oldd; p = neww;
+ qmax = oldd + len;
+ pmax = p + len;
+
+ /* Find out where to begin --- while they match, we are ok */
+ while (1)
+ {
+ if (q == qmax) return;
+#if SLANG_HAS_KANJI_SUPPORT
+ if (*p & 0x80)
+ { /* new is kanji */
+ if ((*q & 0x80) && ((q + 1) < qmax))
+ { /* old is also kanji */
+ if (((0xFF & *q) != (0xFF & *p))
+ || ((0xFF & q[1]) != (0xFF & p[1])))
+ break; /* both kanji, but not match */
+
+ else
+ { /* kanji match ! */
+ if (!COLOR_EQS(*q, *p)) break;
+ q++; p++;
+ if (!COLOR_EQS(*q, *p)) break;
+ /* really match! */
+ q++; p++;
+ continue;
+ }
+ }
+ else break; /* old is not kanji */
+ }
+ else
+ { /* new is not kanji */
+ if (*q & 0x80) break; /* old is kanji */
+ }
+#endif
+ if (!CHAR_EQS(*q, *p)) break;
+ q++; p++;
+ }
+
+ /*position the cursor */
+ SLtt_goto_rc (row, (int) (p - neww));
+
+#ifdef HP_GLITCH_CODE
+ if (Has_HP_Glitch)
+ {
+ unsigned short *qq = q;
+ while (qq < qmax)
+ {
+ if (*qq & 0xFF00)
+ {
+ SLtt_normal_video ();
+ SLtt_del_eol ();
+ qmax = q;
+ handle_hp_glitch = 1;
+ break;
+ }
+ qq++;
+ }
+ }
+#endif
+ /* Find where the last non-blank character on old/new screen is */
+
+ while (qmax > q)
+ {
+ qmax--;
+ if (!CHAR_EQS(*qmax, SPACE_CHAR))
+ {
+ qmax++;
+ break;
+ }
+ }
+
+ while (pmax > p)
+ {
+ pmax--;
+ if (!CHAR_EQS(*pmax, SPACE_CHAR))
+ {
+ pmax++;
+ break;
+ }
+ }
+
+ last_buffered_match = buf = buffer; /* buffer is empty */
+
+#ifdef HP_GLITCH_CODE
+ if (handle_hp_glitch)
+ {
+ while (p < pmax)
+ {
+ *buf++ = *p++;
+ }
+ }
+#endif
+
+ /* loop using overwrite then skip algorithm until done */
+ while (1)
+ {
+ /* while they do not match and we do not hit a space, buffer them up */
+ n_spaces = 0;
+ while (p < pmax)
+ {
+ if (CHAR_EQS(*q,SPACE_CHAR) && CHAR_EQS(*p, SPACE_CHAR))
+ {
+ /* If *q is not a space, we would have to overwrite it.
+ * However, if *q is a space, then while *p is also one,
+ * we only need to skip over the blank field.
+ */
+ space_match = p;
+ p++; q++;
+ while ((p < pmax)
+ && CHAR_EQS(*q,SPACE_CHAR)
+ && CHAR_EQS(*p, SPACE_CHAR))
+ {
+ p++;
+ q++;
+ }
+ n_spaces = (unsigned int) (p - space_match);
+ break;
+ }
+#if SLANG_HAS_KANJI_SUPPORT
+ if ((*p & 0x80) && ((p + 1) < pmax))
+ { /* new is kanji */
+ if (*q & 0x80)
+ { /* old is also kanji */
+ if (((0xFF & *q) != (0xFF & *p))
+ || ((0xFF & q[1]) != (0xFF & p[1])))
+ {
+ /* both kanji, but not match */
+ *buf++ = *p++;
+ *buf++ = *p++;
+ q += 2;
+ continue;
+ }
+ else
+ { /* kanji match ? */
+ if (!COLOR_EQS(*q, *p) || !COLOR_EQS(*(q+1), *(p+1)))
+ {
+ /* code is match ,but color is diff */
+ *buf++ = *p++;
+ *buf++ = *p++;
+ continue;
+ }
+ /* really match ! */
+ break;
+ }
+ }
+ else
+ { /* old is not kanji */
+ *buf++ = *p++;
+ *buf++ = *p++;
+ q += 2;
+ continue;
+ }
+ }
+ else
+ { /* new is not kanji */
+ if (*q & 0x80)
+ { /* old is kanji */
+ *buf++ = *p++;
+ q++;
+ continue;
+ }
+ }
+#endif
+
+ if (CHAR_EQS(*q, *p)) break;
+ *buf++ = *p++;
+ q++;
+ }
+ *buf = 0;
+
+ if (buf != buffer) send_attr_str (buffer);
+ buf = buffer;
+
+ if (n_spaces && (p < pmax))
+ {
+ forward_cursor (n_spaces, row);
+ }
+
+ /* Now we overwrote what we could and cursor is placed at position
+ * of a possible match of new and old. If this is the case, skip
+ * some more.
+ */
+#if !SLANG_HAS_KANJI_SUPPORT
+ while ((p < pmax) && CHAR_EQS(*p, *q))
+ {
+ *buf++ = *p++;
+ q++;
+ }
+#else
+ /* Kanji */
+ while (p < pmax)
+ {
+ if ((*p & 0x80) && ((p + 1) < pmax))
+ { /* new is kanji */
+ if (*q & 0x80)
+ { /* old is also kanji */
+ if (((0xFF & *q) == (0xFF & *p))
+ && ((0xFF & q[1]) == (0xFF & p[1])))
+ {
+ /* kanji match ? */
+ if (!COLOR_EQS(*q, *p)
+ || !COLOR_EQS(q[1], p[1]))
+ break;
+
+ *buf++ = *p++;
+ q++;
+ if (p >= pmax)
+ {
+ *buf++ = SPACE_CHAR;
+ p++;
+ break;
+ }
+ else
+ {
+ *buf++ = *p++;
+ q++;
+ continue;
+ }
+ }
+ else break; /* both kanji, but not match */
+ }
+ else break; /* old is not kanji */
+ }
+ else
+ { /* new is not kanji */
+ if (*q & 0x80) break; /* old is kanji */
+ if (!CHAR_EQS(*q, *p)) break;
+ *buf++ = *p++;
+ q++;
+ }
+ }
+#endif
+ last_buffered_match = buf;
+ if (p >= pmax) break;
+
+ /* jump to new position is it is greater than 5 otherwise
+ * let it sit in the buffer and output it later.
+ */
+ if ((int) (buf - buffer) >= 5)
+ {
+ forward_cursor ((unsigned int) (buf - buffer), row);
+ last_buffered_match = buf = buffer;
+ }
+ }
+
+ if (buf != buffer)
+ {
+ if (q < qmax)
+ {
+ if ((buf == last_buffered_match)
+ && ((int) (buf - buffer) >= 5))
+ {
+ forward_cursor ((unsigned int) (buf - buffer), row);
+ }
+ else
+ {
+ *buf = 0;
+ send_attr_str (buffer);
+ }
+ }
+ }
+ if (q < qmax) SLtt_del_eol ();
+ if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
+}
+
+static void get_color_info (void)
+{
+ char *fg, *bg;
+
+ if (SLtt_Use_Ansi_Colors == 0)
+ SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));
+
+ if (-1 == get_default_colors (&fg, &bg))
+ return;
+
+ /* Check to see if application has already set them. */
+ if (Color_0_Modified)
+ return;
+
+ SLtt_set_color (0, NULL, fg, bg);
+ SLtt_set_color (1, NULL, bg, fg);
+}
+
+/* termcap stuff */
+
+#ifdef __unix__
+
+# ifndef USE_TERMCAP
+static char *Tbuf;
+static char *Tstr_Buf;
+
+# define tgetstr SLtt_tigetstr
+# define tgetent SLtt_tigetent
+# define TGETNUM(x) SLtt_tigetnum((x), &Tbuf)
+# define TGETFLAG(x) SLtt_tigetflag((x), &Tbuf)
+# else
+
+extern char *tgetstr(char *, char **);
+extern int tgetent(char *, char *);
+extern int tgetnum(char *);
+extern int tgetflag(char *);
+static char Tstr_Buf[1024];
+static char Tbuf[4096];
+# define TGETNUM tgetnum
+# define TGETFLAG tgetflag
+# endif
+
+static char *my_tgetstr(char *what, char **p)
+{
+ register char *w, *w1;
+ char *wsave;
+ what = tgetstr(what, p);
+ if (what != NULL)
+ {
+ /* Check for AIX brain-damage */
+ if (*what == '@')
+ return NULL;
+
+ /* lose pad info --- with today's technology, term is a loser if
+ it is really needed */
+ while ((*what == '.') ||
+ ((*what >= '0') && (*what <= '9'))) what++;
+ if (*what == '*') what++;
+
+ /* lose terminfo padding--- looks like $<...> */
+ w = what;
+ while (*w) if ((*w++ == '$') && (*w == '<'))
+ {
+ w1 = w - 1;
+ while (*w && (*w != '>')) w++;
+ if (*w == 0) break;
+ w++;
+ wsave = w1;
+ while ((*w1++ = *w++) != 0);
+ w = wsave;
+ }
+ if (*what == 0) what = NULL;
+ }
+ return(what);
+}
+
+char *SLtt_tgetstr (char *s)
+{
+# ifdef USE_TERMCAP
+ static
+# endif
+ char *p = Tstr_Buf;
+ return my_tgetstr (s, &p);
+}
+
+int SLtt_tgetnum (char *s)
+{
+ return TGETNUM (s);
+}
+int SLtt_tgetflag (char *s)
+{
+ return TGETFLAG (s);
+}
+
+static int Vt100_Like = 0;
+
+void SLtt_get_terminfo (void)
+{
+ char *term;
+ int status;
+
+ term = getenv ("TERM");
+ if (term == NULL)
+ SLang_exit_error("TERM environment variable needs set.");
+
+ if (0 == (status = SLtt_initialize (term)))
+ return;
+
+ if (status == -1)
+ {
+ SLang_exit_error ("Unknown terminal: %s\n\
+Check the TERM environment variable.\n\
+Also make sure that the terminal is defined in the terminfo database.\n\
+Alternatively, set the TERMCAP environment variable to the desired\n\
+termcap entry.",
+ term);
+ }
+
+ if (status == -2)
+ {
+ SLang_exit_error ("\
+Your terminal lacks the ability to clear the screen or position the cursor.\n");
+ }
+}
+
+/* Returns 0 if all goes well, -1 if terminal capabilities cannot be deduced,
+ * or -2 if terminal cannot position the cursor.
+ */
+int SLtt_initialize (char *term)
+{
+ char *t, ch;
+ int is_xterm;
+ int almost_vtxxx;
+
+ if (term == NULL)
+ {
+ term = getenv ("TERM");
+ if (term == NULL)
+ return -1;
+ }
+
+ Linux_Console = (!strncmp (term, "linux", 5)
+# ifdef linux
+ || !strncmp(term, "con", 3)
+# endif
+ );
+
+ t = term;
+
+ if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
+ && (ch = *t, (ch >= '1') && (ch <= '9'))) Vt100_Like = 1;
+
+ is_xterm = !strncmp (term, "xterm", 5);
+ almost_vtxxx = (Vt100_Like
+ || Linux_Console
+ || is_xterm
+ || !strcmp (term, "screen"));
+
+# ifndef USE_TERMCAP
+ if (NULL == (Tbuf = tgetent (term)))
+ {
+ if (almost_vtxxx) /* Special cases. */
+ {
+ int vt102 = 1;
+ if (!strcmp (term, "vt100")) vt102 = 0;
+ SLtt_set_term_vtxxx (&vt102);
+ return 0;
+ }
+ return -1;
+ }
+ Tstr_Buf = Tbuf;
+# else /* USE_TERMCAP */
+ if (1 != tgetent(Tbuf, term))
+ return -1;
+# endif /* NOT USE_TERMCAP */
+
+ Cls_Str = SLtt_tgetstr ("cl");
+ Curs_Pos_Str = SLtt_tgetstr ("cm");
+
+ if ((NULL == (Ins_Mode_Str = SLtt_tgetstr("im")))
+ || ( NULL == (Eins_Mode_Str = SLtt_tgetstr("ei")))
+ || ( NULL == (Del_Char_Str = SLtt_tgetstr("dc"))))
+ SLtt_Term_Cannot_Insert = 1;
+
+ Visible_Bell_Str = SLtt_tgetstr ("vb");
+ Curs_Up_Str = SLtt_tgetstr ("up");
+ Rev_Scroll_Str = SLtt_tgetstr("sr");
+ Del_N_Lines_Str = SLtt_tgetstr("DL");
+ Add_N_Lines_Str = SLtt_tgetstr("AL");
+
+ /* Actually these are used to initialize terminals that use cursor
+ * addressing. Hard to believe.
+ */
+ Term_Init_Str = SLtt_tgetstr ("ti");
+ Term_Reset_Str = SLtt_tgetstr ("te");
+
+ /* If I do this for vtxxx terminals, arrow keys start sending ESC O A,
+ * which I do not want. This is mainly for HP terminals.
+ */
+ if ((almost_vtxxx == 0) || SLtt_Force_Keypad_Init)
+ {
+ Keypad_Init_Str = SLtt_tgetstr ("ks");
+ Keypad_Reset_Str = SLtt_tgetstr ("ke");
+ }
+
+ /* Make up for defective termcap/terminfo databases */
+ if ((Vt100_Like && (term[2] != '1'))
+ || Linux_Console
+ || is_xterm
+ )
+ {
+ if (Del_N_Lines_Str == NULL) Del_N_Lines_Str = "\033[%dM";
+ if (Add_N_Lines_Str == NULL) Add_N_Lines_Str = "\033[%dL";
+ }
+
+ Scroll_R_Str = SLtt_tgetstr("cs");
+
+ SLtt_get_screen_size ();
+
+ if ((Scroll_R_Str == NULL)
+ || (((NULL == Del_N_Lines_Str) || (NULL == Add_N_Lines_Str))
+ && (NULL == Rev_Scroll_Str)))
+ {
+ if (is_xterm
+ || Linux_Console
+ )
+ {
+ /* Defective termcap mode!!!! */
+ SLtt_set_term_vtxxx (NULL);
+ }
+ else SLtt_Term_Cannot_Scroll = 1;
+ }
+
+ Del_Eol_Str = SLtt_tgetstr("ce");
+
+ Rev_Vid_Str = SLtt_tgetstr("mr");
+ if (Rev_Vid_Str == NULL) Rev_Vid_Str = SLtt_tgetstr("so");
+
+ Bold_Vid_Str = SLtt_tgetstr("md");
+
+ /* Although xterm cannot blink, it does display the blinking characters
+ * as bold ones. Some Rxvt will display the background as high intensity.
+ */
+ if ((NULL == (Blink_Vid_Str = SLtt_tgetstr("mb")))
+ && is_xterm)
+ Blink_Vid_Str = "\033[5m";
+
+ UnderLine_Vid_Str = SLtt_tgetstr("us");
+
+ Start_Alt_Chars_Str = SLtt_tgetstr ("as"); /* smacs */
+ End_Alt_Chars_Str = SLtt_tgetstr ("ae"); /* rmacs */
+ Enable_Alt_Char_Set = SLtt_tgetstr ("eA"); /* enacs */
+ SLtt_Graphics_Char_Pairs = SLtt_tgetstr ("ac");
+
+ if (NULL == SLtt_Graphics_Char_Pairs)
+ {
+ /* make up for defective termcap/terminfo */
+ if (Vt100_Like)
+ {
+ Start_Alt_Chars_Str = "\016";
+ End_Alt_Chars_Str = "\017";
+ Enable_Alt_Char_Set = "\033)0";
+ }
+ }
+
+ /* aixterm added by willi */
+ if (is_xterm || !strncmp (term, "aixterm", 7))
+ {
+ Start_Alt_Chars_Str = "\016";
+ End_Alt_Chars_Str = "\017";
+ Enable_Alt_Char_Set = "\033(B\033)0";
+ }
+
+ if ((SLtt_Graphics_Char_Pairs == NULL) &&
+ ((Start_Alt_Chars_Str == NULL) || (End_Alt_Chars_Str == NULL)))
+ {
+ SLtt_Has_Alt_Charset = 0;
+ Enable_Alt_Char_Set = NULL;
+ }
+ else SLtt_Has_Alt_Charset = 1;
+
+ /* status line capabilities */
+ if ((SLtt_Has_Status_Line == -1)
+ && (0 != (SLtt_Has_Status_Line = TGETFLAG ("hs"))))
+ {
+ Disable_Status_line_Str = SLtt_tgetstr ("ds");
+ Return_From_Status_Line_Str = SLtt_tgetstr ("fs");
+ Goto_Status_Line_Str = SLtt_tgetstr ("ts");
+ Status_Line_Esc_Ok = TGETFLAG("es");
+ Num_Status_Line_Columns = TGETNUM("ws");
+ if (Num_Status_Line_Columns < 0) Num_Status_Line_Columns = 0;
+ }
+
+ if (NULL == (Norm_Vid_Str = SLtt_tgetstr("me")))
+ {
+ Norm_Vid_Str = SLtt_tgetstr("se");
+ }
+
+ Cursor_Invisible_Str = SLtt_tgetstr("vi");
+ Cursor_Visible_Str = SLtt_tgetstr("ve");
+
+ Curs_F_Str = SLtt_tgetstr("RI");
+
+# if 0
+ if (NULL != Curs_F_Str)
+ {
+ Len_Curs_F_Str = strlen(Curs_F_Str);
+ }
+ else Len_Curs_F_Str = strlen(Curs_Pos_Str);
+# endif
+
+ Automatic_Margins = TGETFLAG ("am");
+ /* No_Move_In_Standout = !TGETFLAG ("ms"); */
+# ifdef HP_GLITCH_CODE
+ Has_HP_Glitch = TGETFLAG ("xs");
+# else
+ Worthless_Highlight = TGETFLAG ("xs");
+# endif
+
+ if (Worthless_Highlight == 0)
+ { /* Magic cookie glitch */
+ Worthless_Highlight = (TGETNUM ("sg") > 0);
+ }
+
+ if (Worthless_Highlight)
+ SLtt_Has_Alt_Charset = 0;
+
+ Reset_Color_String = SLtt_tgetstr ("op");
+ Color_Fg_Str = SLtt_tgetstr ("AF");
+ Color_Bg_Str = SLtt_tgetstr ("AB");
+ if ((Color_Fg_Str == NULL) || (Color_Bg_Str == NULL))
+ {
+ Color_Fg_Str = SLtt_tgetstr ("Sf");
+ Color_Bg_Str = SLtt_tgetstr ("Sb");
+ }
+
+ if (-1 == (Max_Terminfo_Colors = SLtt_tgetnum ("Co")))
+ Max_Terminfo_Colors = 8;
+
+ if ((Color_Bg_Str != NULL) && (Color_Fg_Str != NULL))
+ SLtt_Use_Ansi_Colors = 1;
+ else
+ {
+#if 0
+ Color_Fg_Str = "%?%p1%{7}%>%t\033[1;3%p1%{8}%m%dm%e\033[3%p1%dm%;";
+ Color_Bg_Str = "%?%p1%{7}%>%t\033[5;4%p1%{8}%m%dm%e\033[4%p1%dm%;";
+ Max_Terminfo_Colors = 16;
+#else
+ Color_Fg_Str = "\033[3%dm";
+ Color_Bg_Str = "\033[4%dm";
+ Max_Terminfo_Colors = 8;
+#endif
+ }
+
+ get_color_info ();
+
+ if ((Cls_Str == NULL)
+ || (Curs_Pos_Str == NULL))
+ return -2;
+
+ return 0;
+}
+
+#endif
+/* Unix */
+
+/* specific to vtxxx only */
+void SLtt_enable_cursor_keys (void)
+{
+#ifdef __unix__
+ if (Vt100_Like)
+#endif
+ tt_write_string("\033=\033[?1l");
+}
+
+#ifdef VMS
+int SLtt_initialize (char *term)
+{
+ SLtt_get_terminfo ();
+ return 0;
+}
+
+void SLtt_get_terminfo ()
+{
+ int zero = 0;
+
+ get_color_info ();
+
+ SLtt_set_term_vtxxx(&zero);
+ Start_Alt_Chars_Str = "\016";
+ End_Alt_Chars_Str = "\017";
+ SLtt_Has_Alt_Charset = 1;
+ SLtt_Graphics_Char_Pairs = "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
+ Enable_Alt_Char_Set = "\033(B\033)0";
+ SLtt_get_screen_size ();
+}
+#endif
+
+/* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
+ * is non-zero, set terminal appropriate for a only vt100
+ * (no add line capability). */
+
+void SLtt_set_term_vtxxx(int *vt100)
+{
+ Norm_Vid_Str = "\033[m";
+
+ Scroll_R_Str = "\033[%i%d;%dr";
+ Cls_Str = "\033[2J\033[H";
+ Rev_Vid_Str = "\033[7m";
+ Bold_Vid_Str = "\033[1m";
+ Blink_Vid_Str = "\033[5m";
+ UnderLine_Vid_Str = "\033[4m";
+ Del_Eol_Str = "\033[K";
+ Rev_Scroll_Str = "\033M";
+ Curs_F_Str = "\033[%dC";
+ /* Len_Curs_F_Str = 5; */
+ Curs_Pos_Str = "\033[%i%d;%dH";
+ if ((vt100 == NULL) || (*vt100 == 0))
+ {
+ Ins_Mode_Str = "\033[4h";
+ Eins_Mode_Str = "\033[4l";
+ Del_Char_Str = "\033[P";
+ Del_N_Lines_Str = "\033[%dM";
+ Add_N_Lines_Str = "\033[%dL";
+ SLtt_Term_Cannot_Insert = 0;
+ }
+ else
+ {
+ Del_N_Lines_Str = NULL;
+ Add_N_Lines_Str = NULL;
+ SLtt_Term_Cannot_Insert = 1;
+ }
+ SLtt_Term_Cannot_Scroll = 0;
+ /* No_Move_In_Standout = 0; */
+}
+
+int SLtt_init_video (void)
+{
+ /* send_string_to_term("\033[?6h"); */
+ /* relative origin mode */
+ tt_write_string (Term_Init_Str);
+ tt_write_string (Keypad_Init_Str);
+ SLtt_reset_scroll_region();
+ SLtt_end_insert();
+ tt_write_string (Enable_Alt_Char_Set);
+ Video_Initialized = 1;
+ return 0;
+}
+
+int SLtt_reset_video (void)
+{
+ SLtt_goto_rc (SLtt_Screen_Rows - 1, 0);
+ Cursor_Set = 0;
+ SLtt_normal_video (); /* MSKermit requires this */
+ tt_write_string(Norm_Vid_Str);
+
+ Current_Fgbg = 0xFFFFFFFFU;
+ SLtt_set_alt_char_set (0);
+ if (SLtt_Use_Ansi_Colors)
+ {
+ if (Reset_Color_String == NULL)
+ {
+ SLtt_Char_Type attr;
+ if (-1 != make_color_fgbg (NULL, NULL, &attr))
+ write_attributes (attr);
+ else tt_write_string ("\033[0m\033[m");
+ }
+ else tt_write_string (Reset_Color_String);
+ Current_Fgbg = 0xFFFFFFFFU;
+ }
+ SLtt_erase_line ();
+ tt_write_string (Keypad_Reset_Str);
+ tt_write_string (Term_Reset_Str);
+ SLtt_flush_output ();
+ Video_Initialized = 0;
+ return 0;
+}
+
+void SLtt_bold_video (void)
+{
+ tt_write_string (Bold_Vid_Str);
+}
+
+int SLtt_set_mouse_mode (int mode, int force)
+{
+ char *term;
+
+ if (force == 0)
+ {
+ if (NULL == (term = (char *) getenv("TERM"))) return -1;
+ if (strncmp ("xterm", term, 5))
+ return -1;
+ }
+
+ if (mode)
+ tt_write_string ("\033[?9h");
+ else
+ tt_write_string ("\033[?9l");
+
+ return 0;
+}
+
+void SLtt_disable_status_line (void)
+{
+ if (SLtt_Has_Status_Line > 0)
+ tt_write_string (Disable_Status_line_Str);
+}
+
+int SLtt_write_to_status_line (char *s, int col)
+{
+ if ((SLtt_Has_Status_Line <= 0)
+ || (Goto_Status_Line_Str == NULL)
+ || (Return_From_Status_Line_Str == NULL))
+ return -1;
+
+ tt_printf (Goto_Status_Line_Str, col, 0);
+ tt_write_string (s);
+ tt_write_string (Return_From_Status_Line_Str);
+ return 0;
+}
+
+void SLtt_get_screen_size (void)
+{
+#ifdef VMS
+ int status, code;
+ unsigned short chan;
+ $DESCRIPTOR(dev_dsc, "SYS$INPUT:");
+#endif
+ int r = 0, c = 0;
+
+#ifdef TIOCGWINSZ
+ struct winsize wind_struct;
+
+ do
+ {
+ if ((ioctl(1,TIOCGWINSZ,&wind_struct) == 0)
+ || (ioctl(0, TIOCGWINSZ, &wind_struct) == 0)
+ || (ioctl(2, TIOCGWINSZ, &wind_struct) == 0))
+ {
+ c = (int) wind_struct.ws_col;
+ r = (int) wind_struct.ws_row;
+ break;
+ }
+ }
+ while (errno == EINTR);
+
+#endif
+
+#ifdef VMS
+ status = sys$assign(&dev_dsc,&chan,0,0,0);
+ if (status & 1)
+ {
+ code = DVI$_DEVBUFSIZ;
+ status = lib$getdvi(&code, &chan,0, &c, 0,0);
+ if (!(status & 1))
+ c = 80;
+ code = DVI$_TT_PAGE;
+ status = lib$getdvi(&code, &chan,0, &r, 0,0);
+ if (!(status & 1))
+ r = 24;
+ sys$dassgn(chan);
+ }
+#endif
+
+ if (r <= 0)
+ {
+ char *s = getenv ("LINES");
+ if (s != NULL) r = atoi (s);
+ }
+
+ if (c <= 0)
+ {
+ char *s = getenv ("COLUMNS");
+ if (s != NULL) c = atoi (s);
+ }
+
+ if ((r <= 0) || (r > 200)) r = 24;
+ if ((c <= 0) || (c > 250)) c = 80;
+
+ SLtt_Screen_Rows = r;
+ SLtt_Screen_Cols = c;
+}
diff --git a/minislang/slerr.c b/minislang/slerr.c
new file mode 100644
index 000000000..6d040cab5
--- /dev/null
+++ b/minislang/slerr.c
@@ -0,0 +1,182 @@
+/* error handling common to all routines. */
+/* Copyright (c) 1992, 1998 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 "config.h"
+#include "sl-feat.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#include "slang.h"
+#include "_slang.h"
+
+void (*SLang_VMessage_Hook) (char *, va_list);
+void (*SLang_Error_Hook)(char *);
+void (*SLang_Exit_Error_Hook)(char *, va_list);
+volatile int SLang_Error = 0;
+char *SLang_Error_Message;
+volatile int SLKeyBoard_Quit = 0;
+
+static char *get_error_string (void)
+{
+ char *str;
+
+ if (!SLang_Error) SLang_Error = SL_UNKNOWN_ERROR;
+ if (SLang_Error_Message != NULL) str = SLang_Error_Message;
+ else switch(SLang_Error)
+ {
+ case SL_NOT_IMPLEMENTED: str = "Not Implemented"; break;
+ case SL_APPLICATION_ERROR: str = "Application Error"; break;
+ case SL_VARIABLE_UNINITIALIZED: str = "Variable Uninitialized"; break;
+ case SL_MALLOC_ERROR : str = "Malloc Error"; break;
+ case SL_INTERNAL_ERROR: str = "Internal Error"; break;
+ case SL_STACK_OVERFLOW: str = "Stack Overflow"; break;
+ case SL_STACK_UNDERFLOW: str = "Stack Underflow"; break;
+ case SL_INTRINSIC_ERROR: str = "Intrinsic Error"; break;
+ case SL_USER_BREAK: str = "User Break"; break;
+ case SL_UNDEFINED_NAME: str = "Undefined Name"; break;
+ case SL_SYNTAX_ERROR: str = "Syntax Error"; break;
+ case SL_DUPLICATE_DEFINITION: str = "Duplicate Definition"; break;
+ case SL_TYPE_MISMATCH: str = "Type Mismatch"; break;
+ case SL_READONLY_ERROR: str = "Variable is read-only"; break;
+ case SL_DIVIDE_ERROR: str = "Divide by zero"; break;
+ case SL_OBJ_NOPEN: str = "Object not opened"; break;
+ case SL_OBJ_UNKNOWN: str = "Object unknown"; break;
+ case SL_INVALID_PARM: str = "Invalid Parameter"; break;
+ case SL_TYPE_UNDEFINED_OP_ERROR:
+ str = "Operation not defined for datatype"; break;
+ case SL_USER_ERROR:
+ str = "User Error"; break;
+ case SL_UNKNOWN_ERROR:
+ default: str = "Unknown Error Code";
+ }
+
+ SLang_Error_Message = NULL;
+ return str;
+}
+
+void SLang_doerror (char *error)
+{
+ char *str = NULL;
+ char *err;
+ char *malloced_err_buf;
+ char err_buf [1024];
+
+ malloced_err_buf = NULL;
+
+ if ((SLang_Error == SL_USER_ERROR)
+ && (error != NULL) && (*error != 0))
+ err = error;
+ else
+ {
+ char *sle = "S-Lang Error: ";
+ unsigned int len;
+ char *fmt;
+
+ str = get_error_string ();
+
+ fmt = "%s%s%s";
+ if ((error == NULL) || (*error == 0))
+ error = "";
+ else if (SLang_Error == SL_UNKNOWN_ERROR)
+ /* Do not display an unknown error message if error is non-NULL */
+ str = "";
+ else
+ fmt = "%s%s: %s";
+
+ len = strlen (sle) + strlen (str) + strlen(error) + 1;
+
+ err = err_buf;
+ if (len >= sizeof (err_buf))
+ {
+ if (NULL == (malloced_err_buf = SLmalloc (len)))
+ err = NULL;
+ else
+ err = malloced_err_buf;
+ }
+
+ if (err != NULL) sprintf (err, fmt, sle, str, error);
+ else err = "Out of memory";
+ }
+
+
+ if (SLang_Error_Hook == NULL)
+ {
+ fputs (err, stderr);
+ fputs("\r\n", stderr);
+ }
+ else
+ (*SLang_Error_Hook)(err);
+
+ SLfree (malloced_err_buf);
+}
+
+void SLang_verror (int err_code, char *fmt, ...)
+{
+ va_list ap;
+ char err [1024];
+
+ if (err_code == 0) err_code = SL_INTRINSIC_ERROR;
+ if (SLang_Error == 0) SLang_Error = err_code;
+
+ if (fmt != NULL)
+ {
+ va_start(ap, fmt);
+ (void) _SLvsnprintf (err, sizeof (err), fmt, ap);
+ fmt = err;
+ va_end(ap);
+ }
+
+ SLang_doerror (fmt);
+}
+
+void SLang_exit_error (char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ if (SLang_Exit_Error_Hook != NULL)
+ {
+ (*SLang_Exit_Error_Hook) (fmt, ap);
+ exit (1);
+ }
+
+ if (fmt != NULL)
+ {
+ vfprintf (stderr, fmt, ap);
+ fputs ("\r\n", stderr);
+ }
+ va_end (ap);
+
+ exit (1);
+}
+
+void SLang_vmessage (char *fmt, ...)
+{
+ va_list ap;
+
+ if (fmt == NULL)
+ return;
+
+ va_start (ap, fmt);
+
+ if (SLang_VMessage_Hook != NULL)
+ (*SLang_VMessage_Hook) (fmt, ap);
+ else
+ {
+ vfprintf (stdout, fmt, ap);
+ fputs ("\r\n", stdout);
+ }
+
+ va_end (ap);
+}
diff --git a/minislang/slgetkey.c b/minislang/slgetkey.c
new file mode 100644
index 000000000..5ec00b129
--- /dev/null
+++ b/minislang/slgetkey.c
@@ -0,0 +1,270 @@
+/* Copyright (c) 1992, 1998 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 "config.h"
+#include "sl-feat.h"
+
+#include <stdio.h>
+#include "slang.h"
+#include "_slang.h"
+
+unsigned int SLang_Input_Buffer_Len = 0;
+unsigned char SLang_Input_Buffer [SL_MAX_INPUT_BUFFER_LEN];
+
+int SLang_Abort_Char = 7;
+int SLang_Ignore_User_Abort = 0;
+
+/* This has the effect of mapping all characters in the range 128-169 to
+ * ESC [ something
+ */
+
+unsigned int SLang_getkey (void)
+{
+ unsigned int imax;
+ unsigned int ch;
+
+ if (SLang_Input_Buffer_Len)
+ {
+ ch = (unsigned int) *SLang_Input_Buffer;
+ SLang_Input_Buffer_Len--;
+ imax = SLang_Input_Buffer_Len;
+
+ SLMEMCPY ((char *) SLang_Input_Buffer,
+ (char *) (SLang_Input_Buffer + 1), imax);
+ }
+ else if (SLANG_GETKEY_ERROR == (ch = _SLsys_getkey ())) return ch;
+
+#if _SLANG_MAP_VTXXX_8BIT
+# if !defined(IBMPC_SYSTEM)
+ if (ch & 0x80)
+ {
+ unsigned char i;
+ i = (unsigned char) (ch & 0x7F);
+ if (i < ' ')
+ {
+ i += 64;
+ SLang_ungetkey (i);
+ ch = 27;
+ }
+ }
+# endif
+#endif
+ return(ch);
+}
+
+int SLang_ungetkey_string (unsigned char *s, unsigned int n)
+{
+ register unsigned char *bmax, *b, *b1;
+ if (SLang_Input_Buffer_Len + n + 3 > SL_MAX_INPUT_BUFFER_LEN)
+ return -1;
+
+ b = SLang_Input_Buffer;
+ bmax = (b - 1) + SLang_Input_Buffer_Len;
+ b1 = bmax + n;
+ while (bmax >= b) *b1-- = *bmax--;
+ bmax = b + n;
+ while (b < bmax) *b++ = *s++;
+ SLang_Input_Buffer_Len += n;
+ return 0;
+}
+
+int SLang_buffer_keystring (unsigned char *s, unsigned int n)
+{
+
+ if (n + SLang_Input_Buffer_Len + 3 > SL_MAX_INPUT_BUFFER_LEN) return -1;
+
+ SLMEMCPY ((char *) SLang_Input_Buffer + SLang_Input_Buffer_Len,
+ (char *) s, n);
+ SLang_Input_Buffer_Len += n;
+ return 0;
+}
+
+int SLang_ungetkey (unsigned char ch)
+{
+ return SLang_ungetkey_string(&ch, 1);
+}
+
+int SLang_input_pending (int tsecs)
+{
+ int n;
+ unsigned char c;
+ if (SLang_Input_Buffer_Len) return (int) SLang_Input_Buffer_Len;
+
+ n = _SLsys_input_pending (tsecs);
+
+ if (n <= 0) return 0;
+
+ c = (unsigned char) SLang_getkey ();
+ SLang_ungetkey_string (&c, 1);
+
+ return n;
+}
+
+void SLang_flush_input (void)
+{
+ int quit = SLKeyBoard_Quit;
+
+ SLang_Input_Buffer_Len = 0;
+ SLKeyBoard_Quit = 0;
+ while (_SLsys_input_pending (0) > 0)
+ {
+ (void) _SLsys_getkey ();
+ /* Set this to 0 because _SLsys_getkey may stuff keyboard buffer if
+ * key sends key sequence (OS/2, DOS, maybe VMS).
+ */
+ SLang_Input_Buffer_Len = 0;
+ }
+ SLKeyBoard_Quit = quit;
+}
+
+
+#ifdef IBMPC_SYSTEM
+static int Map_To_ANSI;
+int SLgetkey_map_to_ansi (int enable)
+{
+ Map_To_ANSI = enable;
+ return 0;
+}
+
+unsigned int _SLpc_convert_scancode (unsigned int scan)
+{
+ char *keystr;
+
+ if (Map_To_ANSI == 0)
+ {
+ SLang_ungetkey (scan);
+ return 0;
+ }
+
+
+ /* These mappings correspond to what rxvt produces under Linux */
+ switch (scan)
+ {
+ default:
+ return 0;
+
+ case 'G': /* home */
+ keystr = "[1~";
+ break;
+ case 'H': /* up */
+ keystr = "[A";
+ break;
+ case 'I': /* PgUp */
+ keystr = "[5~";
+ break;
+ case 'K': /* Left */
+ keystr = "[D";
+ break;
+ case 'M': /* Right */
+ keystr = "[C";
+ break;
+ case 'O': /* End */
+ keystr = "[4~";
+ break;
+ case 'P': /* Down */
+ keystr = "[B";
+ break;
+ case 'Q': /* PgDn */
+ keystr = "[6~";
+ break;
+ case 'R': /* Insert */
+ keystr = "[2~";
+ break;
+ case 'S': /* Delete */
+ keystr = "[3~";
+ break;
+
+ case ';': /* F1 */
+ case 'T': /* (shift) */
+ case '^': /* (ctrl) */
+ case 'h': /* (alt) */
+ keystr = "[11~";
+ break;
+
+ case '<': /* F2 */
+ case 'U': /* (shift) */
+ case '_': /* (ctrl) */
+ case 'i': /* (alt) */
+ keystr = "[12~";
+ break;
+
+ case '=': /* F3 */
+ case 'V': /* (shift) */
+ case '`': /* (ctrl) */
+ case 'j': /* (alt) */
+ keystr = "[13~";
+ break;
+
+ case '>': /* F4 */
+ case 'W': /* (shift) */
+ case 'a': /* (ctrl) */
+ case 'k': /* (alt) */
+ keystr = "[14~";
+ break;
+
+ case '?': /* F5 */
+ case 'X': /* (shift) */
+ case 'b': /* (ctrl) */
+ case 'l': /* (alt) */
+ keystr = "[15~";
+ break;
+
+ case '@': /* F6 */
+ case 'Y': /* (shift) */
+ case 'c': /* (ctrl) */
+ case 'm': /* (alt) */
+ keystr = "[17~";
+ break;
+
+ case 'A': /* F7 */
+ case 'Z': /* (shift) */
+ case 'd': /* (ctrl) */
+ case 'n': /* (alt) */
+ keystr = "[18~";
+ break;
+
+ case 'B': /* F8 */
+ case '[': /* (shift) */
+ case 'e': /* (ctrl) */
+ case 'o': /* (alt) */
+ keystr = "[19~";
+ break;
+
+ case 'C': /* F9 */
+ case '\\': /* (shift) */
+ case 'f': /* (ctrl) */
+ case 'p': /* (alt) */
+ keystr = "[20~";
+ break;
+
+ case 'D': /* F10 */
+ case ']': /* (shift) */
+ case 'g': /* (ctrl) */
+ case 'q': /* (alt) */
+ keystr = "[21~";
+ break;
+
+ case 133: /* F11 */
+ case 135: /* (shift) */
+ case 137: /* (ctrl) */
+ case 139: /* (alt) */
+ keystr = "[23~";
+ break;
+
+ case 134: /* F12 */
+ case 136: /* (shift) */
+ case 138: /* (ctrl) */
+ case 140: /* (alt) */
+ keystr = "[24~";
+ break;
+ }
+
+ (void) SLang_ungetkey_string ((unsigned char *)keystr, strlen (keystr));
+ return 27;
+}
+
+#endif
diff --git a/minislang/sllimits.h b/minislang/sllimits.h
new file mode 100644
index 000000000..972b59836
--- /dev/null
+++ b/minislang/sllimits.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 1998 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.
+ */
+/* sllimits.h */
+
+/* slstring.c: Size of the hash table used for strings (prime numbers) */
+#ifdef __MSDOS_16BIT__
+# define SLSTRING_HASH_TABLE_SIZE 601
+#else
+# define SLSTRING_HASH_TABLE_SIZE 2909
+#endif
+
+/* slang.c: maximum size of run time stack */
+#ifdef __MSDOS_16BIT__
+# define SLANG_MAX_STACK_LEN 500
+#else
+# define SLANG_MAX_STACK_LEN 2500
+#endif
+
+/* slang.c: This sets the size on the depth of function calls */
+#ifdef __MSDOS_16BIT__
+# define SLANG_MAX_RECURSIVE_DEPTH 50
+#else
+# define SLANG_MAX_RECURSIVE_DEPTH 250
+#endif
+
+/* slang.c: Size of the stack used for local variables */
+#ifdef __MSDOS_16BIT__
+# define SLANG_MAX_LOCAL_STACK 200
+#else
+# define SLANG_MAX_LOCAL_STACK 1024
+#endif
+
+/* slang.c: The size of the hash table used for local and global objects.
+ * These should be prime numbers
+ */
+#define SLGLOBALS_HASH_TABLE_SIZE 2909
+#define SLLOCALS_HASH_TABLE_SIZE 73
+
+/* Size of the keyboard buffer use by the ungetkey routines */
+#ifdef __MSDOS_16BIT__
+# define SL_MAX_INPUT_BUFFER_LEN 40
+#else
+# define SL_MAX_INPUT_BUFFER_LEN 1024
+#endif
+
+/* Maximum number of nested switch statements */
+#define SLANG_MAX_NESTED_SWITCH 10
+
+/* Maximum number of dimensions of an array. */
+#define SLARRAY_MAX_DIMS 7
+
+/* Size of the block stack (used in byte-compiling) */
+#define SLANG_MAX_BLOCK_STACK_LEN 50
+
+/* slfile.c: Max number of open file pointers */
+#ifdef __MSDOS_16BIT__
+# define SL_MAX_FILES 32
+#else
+# define SL_MAX_FILES 256
+#endif
+
diff --git a/minislang/slmisc.c b/minislang/slmisc.c
new file mode 100644
index 000000000..52196984e
--- /dev/null
+++ b/minislang/slmisc.c
@@ -0,0 +1,256 @@
+/* Copyright (c) 1992, 1998 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 "config.h"
+#include "sl-feat.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "slang.h"
+#include "_slang.h"
+
+#define DEBUG_MALLOC 0
+
+#if DEBUG_MALLOC
+# define SLREALLOC_FUN SLdebug_realloc
+# define SLMALLOC_FUN SLdebug_malloc
+# define SLFREE_FUN SLdebug_free
+#else
+# define SLREALLOC_FUN SLREALLOC
+# define SLMALLOC_FUN SLMALLOC
+# define SLFREE_FUN SLFREE
+#endif
+
+char *SLmake_string(char *str)
+{
+ return SLmake_nstring(str, strlen (str));
+}
+
+char *SLmake_nstring (char *str, unsigned int n)
+{
+ char *ptr;
+
+ if (NULL == (ptr = SLmalloc(n + 1)))
+ {
+ return NULL;
+ }
+ SLMEMCPY (ptr, str, n);
+ ptr[n] = 0;
+ return(ptr);
+}
+
+void SLmake_lut (unsigned char *lut, unsigned char *range, unsigned char reverse)
+{
+ register unsigned char *l = lut, *lmax = lut + 256;
+ int i, r1, r2;
+
+ while (l < lmax) *l++ = reverse;
+
+ while (*range)
+ {
+ r1 = *range;
+ if (*(range + 1) == '-')
+ {
+ range += 2;
+ r2 = *range;
+ }
+ else r2 = r1;
+
+ for (i = r1; i <= r2; i++) lut[i] = !reverse;
+ if (*range) range++;
+ }
+}
+
+char *SLmalloc (unsigned int len)
+{
+ char *p;
+
+ p = (char *) SLMALLOC_FUN (len);
+ if (p == NULL)
+ SLang_Error = SL_MALLOC_ERROR;
+
+ return p;
+}
+
+void SLfree (char *p)
+{
+ if (p != NULL) SLFREE_FUN (p);
+}
+
+char *SLrealloc (char *p, unsigned int len)
+{
+ if (len == 0)
+ {
+ SLfree (p);
+ return NULL;
+ }
+
+ if (p == NULL) p = SLmalloc (len);
+ else
+ {
+ p = SLREALLOC_FUN (p, len);
+ if (p == NULL)
+ SLang_Error = SL_MALLOC_ERROR;
+ }
+ return p;
+}
+
+char *SLcalloc (unsigned int nelems, unsigned int len)
+{
+ char *p;
+
+ len = nelems * len;
+ p = SLmalloc (len);
+ if (p != NULL) SLMEMSET (p, 0, len);
+ return p;
+}
+
+/* p and ch may point to the same buffer */
+char *_SLexpand_escaped_char(char *p, char *ch)
+{
+ int i = 0;
+ int max = 0, num, base = 0;
+ char ch1;
+
+ ch1 = *p++;
+
+ switch (ch1)
+ {
+ default: num = ch1; break;
+ case 'n': num = '\n'; break;
+ case 't': num = '\t'; break;
+ case 'v': num = '\v'; break;
+ case 'b': num = '\b'; break;
+ case 'r': num = '\r'; break;
+ case 'f': num = '\f'; break;
+ case 'E': case 'e': num = 27; break;
+ case 'a': num = 7;
+ break;
+
+ /* octal */
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ max = '7';
+ base = 8; i = 2; num = ch1 - '0';
+ break;
+
+ case 'd': /* decimal -- S-Lang extension */
+ base = 10;
+ i = 3;
+ max = '9';
+ num = 0;
+ break;
+
+ case 'x': /* hex */
+ base = 16;
+ max = '9';
+ i = 2;
+ num = 0;
+ break;
+ }
+
+ while (i--)
+ {
+ ch1 = *p;
+
+ if ((ch1 <= max) && (ch1 >= '0'))
+ {
+ num = base * num + (ch1 - '0');
+ }
+ else if (base == 16)
+ {
+ ch1 |= 0x20;
+ if ((ch1 < 'a') || ((ch1 > 'f'))) break;
+ num = base * num + 10 + (ch1 - 'a');
+ }
+ else break;
+ p++;
+ }
+
+ *ch = (char) num;
+ return p;
+}
+
+/* s and t could represent the same space */
+void SLexpand_escaped_string (register char *s, register char *t,
+ register char *tmax)
+{
+ char ch;
+
+ while (t < tmax)
+ {
+ ch = *t++;
+ if (ch == '\\')
+ {
+ t = _SLexpand_escaped_char (t, &ch);
+ }
+ *s++ = ch;
+ }
+ *s = 0;
+}
+
+int SLextract_list_element (char *list, unsigned int nth, char delim,
+ char *elem, unsigned int buflen)
+{
+ char *el, *elmax;
+ char ch;
+
+ while (nth > 0)
+ {
+ while ((0 != (ch = *list)) && (ch != delim))
+ list++;
+
+ if (ch == 0) return -1;
+
+ list++;
+ nth--;
+ }
+
+ el = elem;
+ elmax = el + (buflen - 1);
+
+ while ((0 != (ch = *list)) && (ch != delim) && (el < elmax))
+ *el++ = *list++;
+ *el = 0;
+
+ return 0;
+}
+
+#ifndef HAVE_VSNPRINTF
+int _SLvsnprintf (char *buf, unsigned int buflen, char *fmt, va_list ap)
+{
+ int status;
+
+ status = vsprintf (buf, fmt, ap);
+ if (status >= (int) buflen)
+ {
+ /* If we are lucky, we will get this far. The real solution is to
+ * provide a working version of vsnprintf
+ */
+ SLang_exit_error ("\
+Your system lacks the vsnprintf system call and vsprintf overflowed a buffer.\n\
+The integrity of this program has been violated.\n");
+ return EOF; /* NOT reached */
+ }
+ return status;
+}
+#endif
+
+#ifndef HAVE_SNPRINTF
+int _SLsnprintf (char *buf, unsigned int buflen, char *fmt, ...)
+{
+ int status;
+
+ va_list ap;
+
+ va_start (ap, fmt);
+ status = _SLvsnprintf (buf, buflen, fmt, ap);
+ va_end (ap);
+
+ return status;
+}
+#endif
diff --git a/minislang/slsignal.c b/minislang/slsignal.c
new file mode 100644
index 000000000..23863024d
--- /dev/null
+++ b/minislang/slsignal.c
@@ -0,0 +1,346 @@
+/* Copyright (c) 1998 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 "config.h"
+#include "sl-feat.h"
+
+#include <stdio.h>
+#include <signal.h>
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#include <errno.h>
+
+#include "slang.h"
+#include "_slang.h"
+
+/* Do not trust these environments */
+#if defined(__CYGWIN32__) || defined(__MINGW32__)
+# ifdef SLANG_POSIX_SIGNALS
+# undef SLANG_POSIX_SIGNALS
+# endif
+#endif
+
+/* This function will cause system calls to be restarted after signal if possible */
+SLSig_Fun_Type *SLsignal (int sig, SLSig_Fun_Type *f)
+{
+#if defined(SLANG_POSIX_SIGNALS)
+ struct sigaction old_sa, new_sa;
+
+# ifdef SIGALRM
+ /* We want system calls to be interrupted by SIGALRM. */
+ if (sig == SIGALRM) return SLsignal_intr (sig, f);
+# endif
+
+ sigemptyset (&new_sa.sa_mask);
+ new_sa.sa_handler = f;
+
+ new_sa.sa_flags = 0;
+# ifdef SA_RESTART
+ new_sa.sa_flags |= SA_RESTART;
+# endif
+
+ if (-1 == sigaction (sig, &new_sa, &old_sa))
+ return (SLSig_Fun_Type *) SIG_ERR;
+
+ return old_sa.sa_handler;
+#else
+ /* Not POSIX. */
+ return signal (sig, f);
+#endif
+}
+
+/* This function will NOT cause system calls to be restarted after
+ * signal if possible
+ */
+SLSig_Fun_Type *SLsignal_intr (int sig, SLSig_Fun_Type *f)
+{
+#ifdef SLANG_POSIX_SIGNALS
+ struct sigaction old_sa, new_sa;
+
+ sigemptyset (&new_sa.sa_mask);
+ new_sa.sa_handler = f;
+
+ new_sa.sa_flags = 0;
+# ifdef SA_INTERRUPT
+ new_sa.sa_flags |= SA_INTERRUPT;
+# endif
+
+ if (-1 == sigaction (sig, &new_sa, &old_sa))
+ return (SLSig_Fun_Type *) SIG_ERR;
+
+ return old_sa.sa_handler;
+#else
+ /* Not POSIX. */
+ return signal (sig, f);
+#endif
+}
+
+/* We are primarily interested in blocking signals that would cause the
+ * application to reset the tty. These include suspend signals and
+ * possibly interrupt signals.
+ */
+#ifdef SLANG_POSIX_SIGNALS
+static sigset_t Old_Signal_Mask;
+#endif
+
+static volatile unsigned int Blocked_Depth;
+
+int SLsig_block_signals (void)
+{
+#ifdef SLANG_POSIX_SIGNALS
+ sigset_t new_mask;
+#endif
+
+ Blocked_Depth++;
+ if (Blocked_Depth != 1)
+ {
+ return 0;
+ }
+
+#ifdef SLANG_POSIX_SIGNALS
+ sigemptyset (&new_mask);
+# ifdef SIGQUIT
+ sigaddset (&new_mask, SIGQUIT);
+# endif
+# ifdef SIGTSTP
+ sigaddset (&new_mask, SIGTSTP);
+# endif
+# ifdef SIGINT
+ sigaddset (&new_mask, SIGINT);
+# endif
+# ifdef SIGTTIN
+ sigaddset (&new_mask, SIGTTIN);
+# endif
+# ifdef SIGTTOU
+ sigaddset (&new_mask, SIGTTOU);
+# endif
+
+ (void) sigprocmask (SIG_BLOCK, &new_mask, &Old_Signal_Mask);
+ return 0;
+#else
+ /* Not implemented. */
+ return -1;
+#endif
+}
+
+int SLsig_unblock_signals (void)
+{
+ if (Blocked_Depth == 0)
+ return -1;
+
+ Blocked_Depth--;
+
+ if (Blocked_Depth != 0)
+ return 0;
+
+#ifdef SLANG_POSIX_SIGNALS
+ (void) sigprocmask (SIG_SETMASK, &Old_Signal_Mask, NULL);
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+
+#ifdef MSWINDOWS
+int SLsystem (char *cmd)
+{
+ SLang_verror (SL_NOT_IMPLEMENTED, "system not implemented");
+ return -1;
+}
+
+#else
+int SLsystem (char *cmd)
+{
+#ifdef SLANG_POSIX_SIGNALS
+ pid_t pid;
+ int status;
+ struct sigaction ignore;
+# ifdef SIGINT
+ struct sigaction save_intr;
+# endif
+# ifdef SIGQUIT
+ struct sigaction save_quit;
+# endif
+# ifdef SIGCHLD
+ sigset_t child_mask, save_mask;
+# endif
+
+ if (cmd == NULL) return 1;
+
+ ignore.sa_handler = SIG_IGN;
+ sigemptyset (&ignore.sa_mask);
+ ignore.sa_flags = 0;
+
+# ifdef SIGINT
+ if (-1 == sigaction (SIGINT, &ignore, &save_intr))
+ return -1;
+# endif
+
+# ifdef SIGQUIT
+ if (-1 == sigaction (SIGQUIT, &ignore, &save_quit))
+ {
+ (void) sigaction (SIGINT, &save_intr, NULL);
+ return -1;
+ }
+# endif
+
+# ifdef SIGCHLD
+ sigemptyset (&child_mask);
+ sigaddset (&child_mask, SIGCHLD);
+ if (-1 == sigprocmask (SIG_BLOCK, &child_mask, &save_mask))
+ {
+# ifdef SIGINT
+ (void) sigaction (SIGINT, &save_intr, NULL);
+# endif
+# ifdef SIGQUIT
+ (void) sigaction (SIGQUIT, &save_quit, NULL);
+# endif
+ return -1;
+ }
+# endif
+
+ pid = fork();
+
+ if (pid == -1)
+ status = -1;
+ else if (pid == 0)
+ {
+ /* Child */
+# ifdef SIGINT
+ (void) sigaction (SIGINT, &save_intr, NULL);
+# endif
+# ifdef SIGQUIT
+ (void) sigaction (SIGQUIT, &save_quit, NULL);
+# endif
+# ifdef SIGCHLD
+ (void) sigprocmask (SIG_SETMASK, &save_mask, NULL);
+# endif
+
+ execl ("/bin/sh", "sh", "-c", cmd, NULL);
+ _exit (127);
+ }
+ else
+ {
+ /* parent */
+ while (-1 == waitpid (pid, &status, 0))
+ {
+# ifdef EINTR
+ if (errno == EINTR)
+ continue;
+# endif
+# ifdef ERESTARTSYS
+ if (errno == ERESTARTSYS)
+ continue;
+# endif
+ status = -1;
+ break;
+ }
+ }
+# ifdef SIGINT
+ if (-1 == sigaction (SIGINT, &save_intr, NULL))
+ status = -1;
+# endif
+# ifdef SIGQUIT
+ if (-1 == sigaction (SIGQUIT, &save_quit, NULL))
+ status = -1;
+# endif
+# ifdef SIGCHLD
+ if (-1 == sigprocmask (SIG_SETMASK, &save_mask, NULL))
+ status = -1;
+# endif
+
+ return status;
+
+#else /* No POSIX Signals */
+# ifdef SIGINT
+ void (*sint)(int);
+# endif
+# ifdef SIGQUIT
+ void (*squit)(int);
+# endif
+ int status;
+
+# ifdef SIGQUIT
+ squit = SLsignal (SIGQUIT, SIG_IGN);
+# endif
+# ifdef SIGINT
+ sint = SLsignal (SIGINT, SIG_IGN);
+# endif
+ status = system (cmd);
+# ifdef SIGINT
+ SLsignal (SIGINT, sint);
+# endif
+# ifdef SIGQUIT
+ SLsignal (SIGQUIT, squit);
+# endif
+ return status;
+#endif /* POSIX_SIGNALS */
+}
+#endif
+
+
+#if 0
+#include <windows.h>
+static int msw_system (char *cmd)
+{
+ STARTUPINFO startup_info;
+ PROCESS_INFORMATION process_info;
+ int status;
+
+ if (cmd == NULL) return -1;
+
+ memset ((char *) &startup_info, 0, sizeof (STARTUPINFO));
+ startup_info.cb = sizeof(STARTUPINFO);
+ startup_info.dwFlags = STARTF_USESHOWWINDOW;
+ startup_info.wShowWindow = SW_SHOWDEFAULT;
+
+ if (FALSE == CreateProcess (NULL,
+ cmd,
+ NULL,
+ NULL,
+ FALSE,
+ NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE,
+ NULL,
+ NULL,
+ &startup_info,
+ &process_info))
+ {
+ SLang_verror (0, "%s: CreateProcess failed.", cmd);
+ return -1;
+ }
+
+
+ status = -1;
+
+ if (0xFFFFFFFFUL != WaitForSingleObject (process_info.hProcess, INFINITE))
+ {
+ DWORD exit_code;
+
+ if (TRUE == GetExitCodeProcess (process_info.hProcess, &exit_code))
+ status = (int) exit_code;
+ }
+
+ CloseHandle (process_info.hThread);
+ CloseHandle (process_info.hProcess);
+
+ return status;
+}
+#endif
diff --git a/minislang/slsmg.c b/minislang/slsmg.c
new file mode 100644
index 000000000..e90b8032e
--- /dev/null
+++ b/minislang/slsmg.c
@@ -0,0 +1,1395 @@
+/* SLang Screen management routines */
+/* Copyright (c) 1992, 1998 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 "config.h"
+#include "sl-feat.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "slang.h"
+#include "_slang.h"
+
+typedef struct Screen_Type
+ {
+ int n; /* number of chars written last time */
+ int flags; /* line untouched, etc... */
+ unsigned short *old, *neew;
+#ifndef IBMPC_SYSTEM
+ unsigned long old_hash, new_hash;
+#endif
+ }
+Screen_Type;
+
+#define TOUCHED 0x1
+#define TRASHED 0x2
+
+#if !defined(IBMPC_SYSTEM) || defined(__DJGPP__) || defined(__os2__)
+# define MAX_SCREEN_SIZE 256
+#else
+# define MAX_SCREEN_SIZE 75
+#endif
+
+Screen_Type SL_Screen[MAX_SCREEN_SIZE];
+static int Start_Col, Start_Row;
+static int Screen_Cols, Screen_Rows;
+static int This_Row, This_Col;
+static int This_Color; /* only the first 8 bits of this
+ * are used. The highest bit is used
+ * to indicate an alternate character
+ * set. This leaves 127 userdefineable
+ * color combination.
+ */
+
+#ifndef IBMPC_SYSTEM
+#define ALT_CHAR_FLAG 0x80
+#else
+#define ALT_CHAR_FLAG 0x00
+#endif
+
+int SLsmg_Newline_Behavior = 0;
+int SLsmg_Backspace_Moves = 0;
+/* Backward compatibility. Not used. */
+/* int SLsmg_Newline_Moves; */
+
+static void (*tt_normal_video)(void) = SLtt_normal_video;
+static void (*tt_goto_rc)(int, int) = SLtt_goto_rc;
+static void (*tt_cls) (void) = SLtt_cls;
+static void (*tt_del_eol) (void) = SLtt_del_eol;
+static void (*tt_smart_puts) (unsigned short *, unsigned short *, int, int) = SLtt_smart_puts;
+static int (*tt_flush_output) (void) = SLtt_flush_output;
+static int (*tt_reset_video) (void) = SLtt_reset_video;
+static int (*tt_init_video) (void) = SLtt_init_video;
+static int *tt_Screen_Rows = &SLtt_Screen_Rows;
+static int *tt_Screen_Cols = &SLtt_Screen_Cols;
+
+#ifndef IBMPC_SYSTEM
+static void (*tt_set_scroll_region)(int, int) = SLtt_set_scroll_region;
+static void (*tt_reverse_index)(int) = SLtt_reverse_index;
+static void (*tt_reset_scroll_region)(void) = SLtt_reset_scroll_region;
+static void (*tt_delete_nlines)(int) = SLtt_delete_nlines;
+#endif
+
+#ifndef IBMPC_SYSTEM
+static int *tt_Term_Cannot_Scroll = &SLtt_Term_Cannot_Scroll;
+static int *tt_Has_Alt_Charset = &SLtt_Has_Alt_Charset;
+static char **tt_Graphics_Char_Pairs = &SLtt_Graphics_Char_Pairs;
+static int *tt_Use_Blink_For_ACS = &SLtt_Use_Blink_For_ACS;
+#endif
+
+static void blank_line (unsigned short *p, int n, unsigned char ch)
+{
+ register unsigned short *pmax = p + n;
+ register unsigned short color_ch;
+
+ color_ch = (This_Color << 8) | (unsigned short) ch;
+
+ while (p < pmax)
+ {
+ *p++ = color_ch;
+ }
+}
+
+static void clear_region (int row, int n)
+{
+ int i;
+ int imax = row + n;
+
+ if (imax > Screen_Rows) imax = Screen_Rows;
+ for (i = row; i < imax; i++)
+ {
+ if (i >= 0)
+ {
+ blank_line (SL_Screen[i].neew, Screen_Cols, ' ');
+ SL_Screen[i].flags |= TOUCHED;
+ }
+ }
+}
+
+void SLsmg_erase_eol (void)
+{
+ int r, c;
+
+ c = This_Col - Start_Col;
+ r = This_Row - Start_Row;
+
+ if ((r < 0) || (r >= Screen_Rows)) return;
+ if (c < 0) c = 0; else if (c >= Screen_Cols) return;
+ blank_line (SL_Screen[This_Row].neew + c , Screen_Cols - c, ' ');
+ SL_Screen[This_Row].flags |= TOUCHED;
+}
+
+static void scroll_up (void)
+{
+ unsigned int i, imax;
+ unsigned short *neew;
+
+ neew = SL_Screen[0].neew;
+ imax = Screen_Rows - 1;
+ for (i = 0; i < imax; i++)
+ {
+ SL_Screen[i].neew = SL_Screen[i + 1].neew;
+ SL_Screen[i].flags |= TOUCHED;
+ }
+ SL_Screen[i].neew = neew;
+ SL_Screen[i].flags |= TOUCHED;
+ blank_line (neew, Screen_Cols, ' ');
+ This_Row--;
+}
+
+void SLsmg_gotorc (int r, int c)
+{
+ This_Row = r;
+ This_Col = c;
+}
+
+int SLsmg_get_row (void)
+{
+ return This_Row;
+}
+
+int SLsmg_get_column (void)
+{
+ return This_Col;
+}
+
+void SLsmg_erase_eos (void)
+{
+ SLsmg_erase_eol ();
+ clear_region (This_Row + 1, Screen_Rows);
+}
+
+static int This_Alt_Char;
+
+void SLsmg_set_char_set (int i)
+{
+#ifdef IBMPC_SYSTEM
+ (void) i;
+#else
+ if ((tt_Use_Blink_For_ACS != NULL)
+ && (*tt_Use_Blink_For_ACS != 0))
+ return;/* alt chars not used and the alt bit
+ * is used to indicate a blink.
+ */
+
+ if (i) This_Alt_Char = ALT_CHAR_FLAG;
+ else This_Alt_Char = 0;
+
+ This_Color &= 0x7F;
+ This_Color |= This_Alt_Char;
+#endif
+}
+
+void SLsmg_set_color (int color)
+{
+ if (color < 0) return;
+ This_Color = color | This_Alt_Char;
+}
+
+void SLsmg_reverse_video (void)
+{
+ SLsmg_set_color (1);
+}
+
+void SLsmg_normal_video (void)
+{
+ This_Color = This_Alt_Char; /* reset video but NOT char set. */
+}
+
+static int point_visible (int col_too)
+{
+ return ((This_Row >= Start_Row) && (This_Row < Start_Row + Screen_Rows)
+ && ((col_too == 0)
+ || ((This_Col >= Start_Col)
+ && (This_Col < Start_Col + Screen_Cols))));
+}
+
+
+void SLsmg_write_string (char *str)
+{
+ SLsmg_write_nchars (str, strlen (str));
+}
+
+void SLsmg_write_nstring (char *str, unsigned int n)
+{
+ unsigned int width;
+ char blank = ' ';
+
+ if (str == NULL) width = 0;
+ else
+ {
+ width = strlen (str);
+ if (width > n) width = n;
+ SLsmg_write_nchars (str, width);
+ }
+ while (width++ < n) SLsmg_write_nchars (&blank, 1);
+}
+
+void SLsmg_write_wrapped_string (char *s, int r, int c,
+ unsigned int dr, unsigned int dc,
+ int fill)
+{
+ register char ch, *p;
+ int maxc = (int) dc;
+
+ if ((dr == 0) || (dc == 0)) return;
+ p = s;
+ dc = 0;
+ while (1)
+ {
+ ch = *p++;
+ if ((ch == 0) || (ch == '\n'))
+ {
+ int diff;
+
+ diff = maxc - (int) dc;
+
+ SLsmg_gotorc (r, c);
+ SLsmg_write_nchars (s, dc);
+ if (fill && (diff > 0))
+ {
+ while (diff--) SLsmg_write_char (' ');
+ }
+ if ((ch == 0) || (dr == 1)) break;
+
+ r++;
+ dc = 0;
+ dr--;
+ s = p;
+ }
+ else if ((int) dc == maxc)
+ {
+ SLsmg_gotorc (r, c);
+ SLsmg_write_nchars (s, dc + 1);
+ if (dr == 1) break;
+
+ r++;
+ dc = 0;
+ dr--;
+ s = p;
+ }
+ else dc++;
+ }
+}
+
+int SLsmg_Tab_Width = 8;
+
+/* Minimum value for which eight bit char is displayed as is. */
+
+#ifndef IBMPC_SYSTEM
+int SLsmg_Display_Eight_Bit = 160;
+static unsigned char Alt_Char_Set[129];/* 129th is used as a flag */
+#else
+int SLsmg_Display_Eight_Bit = 128;
+#endif
+
+void SLsmg_write_nchars (char *str, unsigned int n)
+{
+ register unsigned short *p, old, neew, color;
+ unsigned char ch;
+ unsigned int flags;
+ int len, start_len, max_len;
+ char *str_max;
+ int newline_flag;
+#ifndef IBMPC_SYSTEM
+ int alt_char_set_flag;
+
+ alt_char_set_flag = ((This_Color & ALT_CHAR_FLAG)
+ && ((tt_Use_Blink_For_ACS == NULL)
+ || (*tt_Use_Blink_For_ACS == 0)));
+#endif
+
+ str_max = str + n;
+ color = This_Color << 8;
+
+ top: /* get here only on newline */
+
+ newline_flag = 0;
+ start_len = Start_Col;
+
+ if (point_visible (0) == 0) return;
+
+ len = This_Col;
+ max_len = start_len + Screen_Cols;
+
+ p = SL_Screen[This_Row].neew;
+ if (len > start_len) p += (len - start_len);
+
+ flags = SL_Screen[This_Row].flags;
+ while ((len < max_len) && (str < str_max))
+ {
+ ch = (unsigned char) *str++;
+
+#ifndef IBMPC_SYSTEM
+ if (alt_char_set_flag)
+ ch = Alt_Char_Set [ch & 0x7F];
+#endif
+ if (((ch >= ' ') && (ch < 127))
+ || (ch >= (unsigned char) SLsmg_Display_Eight_Bit)
+#ifndef IBMPC_SYSTEM
+ || alt_char_set_flag
+#endif
+ )
+ {
+ len += 1;
+ if (len > start_len)
+ {
+ old = *p;
+ neew = color | (unsigned short) ch;
+ if (old != neew)
+ {
+ flags |= TOUCHED;
+ *p = neew;
+ }
+ p++;
+ }
+ }
+
+ else if ((ch == '\t') && (SLsmg_Tab_Width > 0))
+ {
+ n = len;
+ n += SLsmg_Tab_Width;
+ n = SLsmg_Tab_Width - (n % SLsmg_Tab_Width);
+ if ((unsigned int) len + n > (unsigned int) max_len)
+ n = (unsigned int) (max_len - len);
+ neew = color | (unsigned short) ' ';
+ while (n--)
+ {
+ len += 1;
+ if (len > start_len)
+ {
+ if (*p != neew)
+ {
+ flags |= TOUCHED;
+ *p = neew;
+ }
+ p++;
+ }
+ }
+ }
+ else if ((ch == '\n')
+ && (SLsmg_Newline_Behavior != SLSMG_NEWLINE_PRINTABLE))
+ {
+ newline_flag = 1;
+ break;
+ }
+ else if ((ch == 0x8) && SLsmg_Backspace_Moves)
+ {
+ if (len != 0) len--;
+ }
+ else
+ {
+ if (ch & 0x80)
+ {
+ neew = color | (unsigned short) '~';
+ len += 1;
+ if (len > start_len)
+ {
+ if (*p != neew)
+ {
+ *p = neew;
+ flags |= TOUCHED;
+ }
+ p++;
+ if (len == max_len) break;
+ ch &= 0x7F;
+ }
+ }
+
+ len += 1;
+ if (len > start_len)
+ {
+ neew = color | (unsigned short) '^';
+ if (*p != neew)
+ {
+ *p = neew;
+ flags |= TOUCHED;
+ }
+ p++;
+ if (len == max_len) break;
+ }
+
+ if (ch == 127) ch = '?'; else ch = ch + '@';
+ len++;
+ if (len > start_len)
+ {
+ neew = color | (unsigned short) ch;
+ if (*p != neew)
+ {
+ *p = neew;
+ flags |= TOUCHED;
+ }
+ p++;
+ }
+ }
+ }
+
+ SL_Screen[This_Row].flags = flags;
+ This_Col = len;
+
+ if (SLsmg_Newline_Behavior == 0)
+ return;
+
+ if (newline_flag == 0)
+ {
+ while (str < str_max)
+ {
+ if (*str == '\n') break;
+ str++;
+ }
+ if (str == str_max) return;
+ str++;
+ }
+
+ This_Row++;
+ This_Col = 0;
+ if (This_Row == Start_Row + Screen_Rows)
+ {
+ if (SLsmg_Newline_Behavior == SLSMG_NEWLINE_SCROLLS) scroll_up ();
+ }
+ goto top;
+}
+
+void SLsmg_write_char (char ch)
+{
+ SLsmg_write_nchars (&ch, 1);
+}
+
+static int Cls_Flag;
+
+void SLsmg_cls (void)
+{
+ This_Color = 0;
+ clear_region (0, Screen_Rows);
+ This_Color = This_Alt_Char;
+ Cls_Flag = 1;
+}
+#if 0
+static void do_copy (unsigned short *a, unsigned short *b)
+{
+ unsigned short *amax = a + Screen_Cols;
+
+ while (a < amax) *a++ = *b++;
+}
+#endif
+
+#ifndef IBMPC_SYSTEM
+int SLsmg_Scroll_Hash_Border = 0;
+static unsigned long compute_hash (unsigned short *s, int n)
+{
+ register unsigned long h = 0, g;
+ register unsigned long sum = 0;
+ register unsigned short *smax, ch;
+ int is_blank = 2;
+
+ s += SLsmg_Scroll_Hash_Border;
+ smax = s + (n - SLsmg_Scroll_Hash_Border);
+ while (s < smax)
+ {
+ ch = *s++;
+ if (is_blank && ((ch & 0xFF) != 32)) is_blank--;
+
+ sum += ch;
+
+ h = sum + (h << 3);
+ if ((g = h & 0xE0000000UL) != 0)
+ {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ }
+ if (is_blank) return 0;
+ return h;
+}
+
+static unsigned long Blank_Hash;
+
+static int try_scroll_down (int rmin, int rmax)
+{
+ int i, r1, r2, di, j;
+ unsigned long hash;
+ int did_scroll;
+ int color;
+ unsigned short *tmp;
+ int ignore;
+
+ did_scroll = 0;
+ for (i = rmax; i > rmin; i--)
+ {
+ hash = SL_Screen[i].new_hash;
+ if (hash == Blank_Hash) continue;
+
+ if ((hash == SL_Screen[i].old_hash)
+#if 0
+ || ((i + 1 < Screen_Rows) && (hash == SL_Screen[i + 1].old_hash))
+ || ((i - 1 > rmin) && (SL_Screen[i].old_hash == SL_Screen[i - 1].new_hash))
+#endif
+ )
+ continue;
+
+ for (j = i - 1; j >= rmin; j--)
+ {
+ if (hash == SL_Screen[j].old_hash) break;
+ }
+ if (j < rmin) continue;
+
+ r2 = i; /* end scroll region */
+
+ di = i - j;
+ j--;
+ ignore = 0;
+ while ((j >= rmin) && (SL_Screen[j].old_hash == SL_Screen[j + di].new_hash))
+ {
+ if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
+ j--;
+ }
+ r1 = j + 1;
+
+ /* If this scroll only scrolls this line into place, don't do it.
+ */
+ if ((di > 1) && (r1 + di + ignore == r2)) continue;
+
+ /* If there is anything in the scrolling region that is ok, abort the
+ * scroll.
+ */
+
+ for (j = r1; j <= r2; j++)
+ {
+ if ((SL_Screen[j].old_hash != Blank_Hash)
+ && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
+ {
+ /* See if the scroll is happens to scroll this one into place. */
+ if ((j + di > r2) || (SL_Screen[j].old_hash != SL_Screen[j + di].new_hash))
+ break;
+ }
+ }
+ if (j <= r2) continue;
+
+ color = This_Color; This_Color = 0;
+ did_scroll = 1;
+ (*tt_normal_video) ();
+ (*tt_set_scroll_region) (r1, r2);
+ (*tt_goto_rc) (0, 0);
+ (*tt_reverse_index) (di);
+ (*tt_reset_scroll_region) ();
+ /* Now we have a hole in the screen. Make the virtual screen look
+ * like it.
+ */
+ for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
+
+ while (di--)
+ {
+ tmp = SL_Screen[r2].old;
+ for (j = r2; j > r1; j--)
+ {
+ SL_Screen[j].old = SL_Screen[j - 1].old;
+ SL_Screen[j].old_hash = SL_Screen[j - 1].old_hash;
+ }
+ SL_Screen[r1].old = tmp;
+ blank_line (SL_Screen[r1].old, Screen_Cols, ' ');
+ SL_Screen[r1].old_hash = Blank_Hash;
+ r1++;
+ }
+ This_Color = color;
+ }
+
+ return did_scroll;
+}
+
+static int try_scroll_up (int rmin, int rmax)
+{
+ int i, r1, r2, di, j;
+ unsigned long hash;
+ int did_scroll;
+ int color;
+ unsigned short *tmp;
+ int ignore;
+
+ did_scroll = 0;
+ for (i = rmin; i < rmax; i++)
+ {
+ hash = SL_Screen[i].new_hash;
+ if (hash == Blank_Hash) continue;
+ if (hash == SL_Screen[i].old_hash)
+ continue;
+ /* find a match further down screen */
+ for (j = i + 1; j <= rmax; j++)
+ {
+ if (hash == SL_Screen[j].old_hash) break;
+ }
+ if (j > rmax) continue;
+
+ r1 = i; /* beg scroll region */
+ di = j - i; /* number of lines to scroll */
+ j++; /* since we know this is a match */
+
+ /* find end of scroll region */
+ ignore = 0;
+ while ((j <= rmax) && (SL_Screen[j].old_hash == SL_Screen[j - di].new_hash))
+ {
+ if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
+ j++;
+ }
+ r2 = j - 1; /* end of scroll region */
+
+ /* If this scroll only scrolls this line into place, don't do it.
+ */
+ if ((di > 1) && (r1 + di + ignore == r2)) continue;
+
+ /* If there is anything in the scrolling region that is ok, abort the
+ * scroll.
+ */
+
+ for (j = r1; j <= r2; j++)
+ {
+ if ((SL_Screen[j].old_hash != Blank_Hash)
+ && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
+ {
+ if ((j - di < r1) || (SL_Screen[j].old_hash != SL_Screen[j - di].new_hash))
+ break;
+ }
+
+ }
+ if (j <= r2) continue;
+
+ did_scroll = 1;
+
+ color = This_Color; This_Color = 0;
+ (*tt_normal_video) ();
+ (*tt_set_scroll_region) (r1, r2);
+ (*tt_goto_rc) (0, 0); /* relative to scroll region */
+ (*tt_delete_nlines) (di);
+ (*tt_reset_scroll_region) ();
+ /* Now we have a hole in the screen. Make the virtual screen look
+ * like it.
+ */
+ for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
+
+ while (di--)
+ {
+ tmp = SL_Screen[r1].old;
+ for (j = r1; j < r2; j++)
+ {
+ SL_Screen[j].old = SL_Screen[j + 1].old;
+ SL_Screen[j].old_hash = SL_Screen[j + 1].old_hash;
+ }
+ SL_Screen[r2].old = tmp;
+ blank_line (SL_Screen[r2].old, Screen_Cols, ' ');
+ SL_Screen[r2].old_hash = Blank_Hash;
+ r2--;
+ }
+ This_Color = color;
+ }
+ return did_scroll;
+}
+
+
+static void try_scroll (void)
+{
+ int r1, rmin, rmax;
+ int num_up, num_down;
+ /* find region limits. */
+
+ for (rmax = Screen_Rows - 1; rmax > 0; rmax--)
+ {
+ if (SL_Screen[rmax].new_hash != SL_Screen[rmax].old_hash)
+ {
+ r1 = rmax - 1;
+ if ((r1 == 0)
+ || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
+ break;
+
+ rmax = r1;
+ }
+ }
+
+ for (rmin = 0; rmin < rmax; rmin++)
+ {
+ if (SL_Screen[rmin].new_hash != SL_Screen[rmin].old_hash)
+ {
+ r1 = rmin + 1;
+ if ((r1 == rmax)
+ || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
+ break;
+
+ rmin = r1;
+ }
+ }
+
+ /* Below, we have two scrolling algorithms. The first has the effect of
+ * scrolling lines down. This is usually appropriate when one moves
+ * up the display, e.g., with the UP arrow. The second algorithm is
+ * appropriate for going the other way. It is important to choose the
+ * correct one.
+ */
+
+ num_up = 0;
+ for (r1 = rmin; r1 < rmax; r1++)
+ {
+ if (SL_Screen[r1].new_hash == SL_Screen[r1 + 1].old_hash)
+ num_up++;
+ }
+
+ num_down = 0;
+ for (r1 = rmax; r1 > rmin; r1--)
+ {
+ if (SL_Screen[r1 - 1].old_hash == SL_Screen[r1].new_hash)
+ num_down++;
+ }
+
+ if (num_up > num_down)
+ {
+ if (try_scroll_up (rmin, rmax))
+ return;
+
+ (void) try_scroll_down (rmin, rmax);
+ }
+ else
+ {
+ if (try_scroll_down (rmin, rmax))
+ return;
+
+ (void) try_scroll_up (rmin, rmax);
+ }
+}
+#endif /* NOT IBMPC_SYSTEM */
+
+static int Smg_Inited;
+
+void SLsmg_refresh (void)
+{
+ int i;
+ int trashed;
+
+ if (Smg_Inited == 0) return;
+ trashed = 0;
+
+#ifndef IBMPC_SYSTEM
+ for (i = 0; i < Screen_Rows; i++)
+ {
+ if (SL_Screen[i].flags == 0) continue;
+ SL_Screen[i].new_hash = compute_hash (SL_Screen[i].neew, Screen_Cols);
+ trashed = 1;
+ }
+#endif
+
+ if (Cls_Flag)
+ {
+ (*tt_normal_video) (); (*tt_cls) ();
+ }
+#ifndef IBMPC_SYSTEM
+ else if (trashed && (*tt_Term_Cannot_Scroll == 0)) try_scroll ();
+#endif
+
+ for (i = 0; i < Screen_Rows; i++)
+ {
+ if (SL_Screen[i].flags == 0) continue;
+
+ if (SL_Screen[i].flags & TRASHED)
+ {
+ (*tt_goto_rc) (i, 0);
+
+ if (Cls_Flag == 0) (*tt_del_eol) ();
+ trashed = 1;
+ }
+ else trashed = 0;
+
+ if (Cls_Flag || trashed)
+ {
+ int color = This_Color;
+ This_Color = 0;
+ blank_line (SL_Screen[i].old, Screen_Cols, ' ');
+ This_Color = color;
+ }
+
+ SL_Screen[i].old[Screen_Cols] = 0;
+ SL_Screen[i].neew[Screen_Cols] = 0;
+
+ (*tt_smart_puts) (SL_Screen[i].neew, SL_Screen[i].old, Screen_Cols, i);
+
+ SLMEMCPY ((char *) SL_Screen[i].old, (char *) SL_Screen[i].neew,
+ Screen_Cols * sizeof (short));
+
+ SL_Screen[i].flags = 0;
+#ifndef IBMPC_SYSTEM
+ SL_Screen[i].old_hash = SL_Screen[i].new_hash;
+#endif
+ }
+
+ if (point_visible (1)) (*tt_goto_rc) (This_Row - Start_Row, This_Col - Start_Col);
+ (*tt_flush_output) ();
+ Cls_Flag = 0;
+}
+
+static int compute_clip (int row, int n, int box_start, int box_end,
+ int *rmin, int *rmax)
+{
+ int row_max;
+
+ if (n < 0) return 0;
+ if (row >= box_end) return 0;
+ row_max = row + n;
+ if (row_max <= box_start) return 0;
+
+ if (row < box_start) row = box_start;
+ if (row_max >= box_end) row_max = box_end;
+ *rmin = row;
+ *rmax = row_max;
+ return 1;
+}
+
+void SLsmg_touch_lines (int row, unsigned int n)
+{
+ int i;
+ int r1, r2;
+
+ if (0 == compute_clip (row, (int) n, Start_Row, Start_Row + Screen_Rows, &r1, &r2))
+ return;
+
+ r1 -= Start_Row;
+ r2 -= Start_Row;
+ for (i = r1; i < r2; i++)
+ {
+ SL_Screen[i].flags |= TRASHED;
+ }
+}
+
+#ifndef IBMPC_SYSTEM
+static char Fake_Alt_Char_Pairs [] = "a:j+k+l+m+q-t+u+v+w+x|";
+
+static void init_alt_char_set (void)
+{
+ int i;
+ unsigned char *p, *pmax, ch;
+
+ if (Alt_Char_Set[128] == 128) return;
+
+ i = 32;
+ memset ((char *)Alt_Char_Set, ' ', i);
+ while (i <= 128)
+ {
+ Alt_Char_Set [i] = i;
+ i++;
+ }
+
+ /* Map to VT100 */
+ if (*tt_Has_Alt_Charset)
+ {
+ if (tt_Graphics_Char_Pairs == NULL) p = NULL;
+ else p = (unsigned char *) *tt_Graphics_Char_Pairs;
+ if (p == NULL) return;
+ }
+ else p = (unsigned char *) Fake_Alt_Char_Pairs;
+ pmax = p + strlen ((char *) p);
+
+ /* Some systems have messed up entries for this */
+ while (p < pmax)
+ {
+ ch = *p++;
+ ch &= 0x7F; /* should be unnecessary */
+ Alt_Char_Set [ch] = *p;
+ p++;
+ }
+}
+#endif
+
+#ifndef IBMPC_SYSTEM
+# define BLOCK_SIGNALS SLsig_block_signals ();
+# define UNBLOCK_SIGNALS SLsig_unblock_signals ();
+#else
+# define BLOCK_SIGNALS
+# define UNBLOCK_SIGNALS
+#endif
+
+static int Smg_Suspended;
+int SLsmg_suspend_smg (void)
+{
+ BLOCK_SIGNALS
+
+ if (Smg_Suspended == 0)
+ {
+ (*tt_reset_video) ();
+ Smg_Suspended = 1;
+ }
+
+ UNBLOCK_SIGNALS
+ return 0;
+}
+
+int SLsmg_resume_smg (void)
+{
+ int i;
+ BLOCK_SIGNALS
+
+ if (Smg_Suspended == 0)
+ {
+ UNBLOCK_SIGNALS
+ return 0;
+ }
+
+ Smg_Suspended = 0;
+
+ if (-1 == (*tt_init_video) ())
+ {
+ UNBLOCK_SIGNALS
+ return -1;
+ }
+
+ Cls_Flag = 1;
+ for (i = 0; i < Screen_Rows; i++)
+ SL_Screen[i].flags |= TRASHED;
+ SLsmg_refresh ();
+
+ UNBLOCK_SIGNALS
+ return 0;
+}
+
+int SLsmg_init_smg (void)
+{
+ int i, len;
+ unsigned short *old, *neew;
+
+ BLOCK_SIGNALS
+
+ if (Smg_Inited) SLsmg_reset_smg ();
+ if (-1 == (*tt_init_video) ())
+ {
+ UNBLOCK_SIGNALS
+ return -1;
+ }
+
+ Screen_Rows = *tt_Screen_Rows;
+ Screen_Cols = *tt_Screen_Cols;
+
+ This_Col = This_Row = Start_Col = Start_Row = 0;
+
+ This_Color = 0;
+ This_Alt_Char = 0;
+ Cls_Flag = 1;
+#ifndef IBMPC_SYSTEM
+ init_alt_char_set ();
+#endif
+ len = Screen_Cols + 3;
+ for (i = 0; i < Screen_Rows; i++)
+ {
+ if ((NULL == (old = (unsigned short *) SLmalloc (sizeof(short) * len)))
+ || ((NULL == (neew = (unsigned short *) SLmalloc (sizeof(short) * len)))))
+ {
+ SLfree ((char *) old);
+ UNBLOCK_SIGNALS
+ return -1;
+ }
+ blank_line (old, len, ' ');
+ blank_line (neew, len, ' ');
+ SL_Screen[i].old = old;
+ SL_Screen[i].neew = neew;
+ SL_Screen[i].flags = 0;
+#ifndef IBMPC_SYSTEM
+ Blank_Hash = compute_hash (old, Screen_Cols);
+ SL_Screen[i].new_hash = SL_Screen[i].old_hash = Blank_Hash;
+#endif
+ }
+ Smg_Inited = 1;
+ UNBLOCK_SIGNALS
+ return 0;
+}
+
+void SLsmg_reset_smg (void)
+{
+ int i;
+ BLOCK_SIGNALS
+
+ if (Smg_Inited == 0)
+ {
+ UNBLOCK_SIGNALS
+ return;
+ }
+ for (i = 0; i < Screen_Rows; i++)
+ {
+ SLfree ((char *)SL_Screen[i].old);
+ SLfree ((char *)SL_Screen[i].neew);
+ SL_Screen[i].old = SL_Screen[i].neew = NULL;
+ }
+ (*tt_reset_video) ();
+ This_Alt_Char = This_Color = 0;
+ Smg_Inited = 0;
+
+ UNBLOCK_SIGNALS
+}
+
+unsigned short SLsmg_char_at (void)
+{
+ if (point_visible (1))
+ {
+ return SL_Screen[This_Row - Start_Row].neew[This_Col - Start_Col];
+ }
+ return 0;
+}
+
+void SLsmg_vprintf (char *fmt, va_list ap)
+{
+ char buf[1024];
+
+ (void) _SLvsnprintf (buf, sizeof (buf), fmt, ap);
+ SLsmg_write_string (buf);
+}
+
+
+void SLsmg_printf (char *fmt, ...)
+{
+ va_list ap;
+ unsigned int len;
+ char *f;
+
+ va_start(ap, fmt);
+
+ f = fmt;
+ while (*f && (*f != '%'))
+ f++;
+ len = (unsigned int) (f - fmt);
+ if (len) SLsmg_write_nchars (fmt, len);
+
+ if (*f != 0)
+ SLsmg_vprintf (f, ap);
+
+ va_end (ap);
+}
+
+void SLsmg_set_screen_start (int *r, int *c)
+{
+ int or = Start_Row, oc = Start_Col;
+
+ if (c == NULL) Start_Col = 0;
+ else
+ {
+ Start_Col = *c;
+ *c = oc;
+ }
+ if (r == NULL) Start_Row = 0;
+ else
+ {
+ Start_Row = *r;
+ *r = or;
+ }
+}
+
+void SLsmg_draw_object (int r, int c, unsigned char object)
+{
+ This_Row = r; This_Col = c;
+
+ if (point_visible (1))
+ {
+ int color = This_Color;
+ This_Color |= ALT_CHAR_FLAG;
+ SLsmg_write_char (object);
+ This_Color = color;
+ }
+
+ This_Col = c + 1;
+}
+
+void SLsmg_draw_hline (unsigned int n)
+{
+ static unsigned char hbuf[16];
+ int count;
+ int cmin, cmax;
+ int final_col = This_Col + (int) n;
+ int save_color;
+
+ if ((This_Row < Start_Row) || (This_Row >= Start_Row + Screen_Rows)
+ || (0 == compute_clip (This_Col, n, Start_Col, Start_Col + Screen_Cols,
+ &cmin, &cmax)))
+ {
+ This_Col = final_col;
+ return;
+ }
+
+ if (hbuf[0] == 0)
+ {
+ SLMEMSET ((char *) hbuf, SLSMG_HLINE_CHAR, 16);
+ }
+
+ n = (unsigned int)(cmax - cmin);
+ count = n / 16;
+
+ save_color = This_Color;
+ This_Color |= ALT_CHAR_FLAG;
+ This_Col = cmin;
+
+ SLsmg_write_nchars ((char *) hbuf, n % 16);
+ while (count-- > 0)
+ {
+ SLsmg_write_nchars ((char *) hbuf, 16);
+ }
+
+ This_Color = save_color;
+ This_Col = final_col;
+}
+
+void SLsmg_draw_vline (int n)
+{
+ unsigned char ch = SLSMG_VLINE_CHAR;
+ int c = This_Col, rmin, rmax;
+ int final_row = This_Row + n;
+ int save_color;
+
+ if (((c < Start_Col) || (c >= Start_Col + Screen_Cols)) ||
+ (0 == compute_clip (This_Row, n, Start_Row, Start_Row + Screen_Rows,
+ &rmin, &rmax)))
+ {
+ This_Row = final_row;
+ return;
+ }
+
+ save_color = This_Color;
+ This_Color |= ALT_CHAR_FLAG;
+
+ for (This_Row = rmin; This_Row < rmax; This_Row++)
+ {
+ This_Col = c;
+ SLsmg_write_nchars ((char *) &ch, 1);
+ }
+
+ This_Col = c; This_Row = final_row;
+ This_Color = save_color;
+}
+
+void SLsmg_draw_box (int r, int c, unsigned int dr, unsigned int dc)
+{
+ if (!dr || !dc) return;
+ This_Row = r; This_Col = c;
+ dr--; dc--;
+ SLsmg_draw_hline (dc);
+ SLsmg_draw_vline (dr);
+ This_Row = r; This_Col = c;
+ SLsmg_draw_vline (dr);
+ SLsmg_draw_hline (dc);
+ SLsmg_draw_object (r, c, SLSMG_ULCORN_CHAR);
+ SLsmg_draw_object (r, c + (int) dc, SLSMG_URCORN_CHAR);
+ SLsmg_draw_object (r + (int) dr, c, SLSMG_LLCORN_CHAR);
+ SLsmg_draw_object (r + (int) dr, c + (int) dc, SLSMG_LRCORN_CHAR);
+ This_Row = r; This_Col = c;
+}
+
+void SLsmg_fill_region (int r, int c, unsigned int dr, unsigned int dc, unsigned char ch)
+{
+ static unsigned char hbuf[16];
+ int count;
+ int dcmax, rmax;
+
+ SLsmg_gotorc (r, c);
+ r = This_Row; c = This_Col;
+
+ dcmax = Screen_Cols - This_Col;
+ if (dcmax < 0)
+ return;
+
+ if (dc > (unsigned int) dcmax) dc = (unsigned int) dcmax;
+
+ rmax = This_Row + dr;
+ if (rmax > Screen_Rows) rmax = Screen_Rows;
+
+#if 0
+ ch = Alt_Char_Set[ch];
+#endif
+ if (ch != hbuf[0]) SLMEMSET ((char *) hbuf, (char) ch, 16);
+
+ for (This_Row = r; This_Row < rmax; This_Row++)
+ {
+ This_Col = c;
+ count = dc / 16;
+ SLsmg_write_nchars ((char *) hbuf, dc % 16);
+ while (count-- > 0)
+ {
+ SLsmg_write_nchars ((char *) hbuf, 16);
+ }
+ }
+
+ This_Row = r;
+}
+
+void SLsmg_forward (int n)
+{
+ This_Col += n;
+}
+
+void SLsmg_write_color_chars (unsigned short *s, unsigned int len)
+{
+ unsigned short *smax, sh;
+ char buf[32], *b, *bmax;
+ int color, save_color;
+
+ smax = s + len;
+ b = buf;
+ bmax = b + sizeof (buf);
+
+ save_color = This_Color;
+
+ while (s < smax)
+ {
+ sh = *s++;
+
+ color = sh >> 8;
+ if ((color != This_Color) || (b == bmax))
+ {
+ if (b != buf)
+ {
+ SLsmg_write_nchars (buf, (int) (b - buf));
+ b = buf;
+ }
+ This_Color = color;
+ }
+ *b++ = (char) (sh & 0xFF);
+ }
+
+ if (b != buf)
+ SLsmg_write_nchars (buf, (unsigned int) (b - buf));
+
+ This_Color = save_color;
+}
+
+unsigned int SLsmg_read_raw (unsigned short *buf, unsigned int len)
+{
+ unsigned int r, c;
+
+ if (0 == point_visible (1)) return 0;
+
+ r = (unsigned int) (This_Row - Start_Row);
+ c = (unsigned int) (This_Col - Start_Col);
+
+ if (c + len > (unsigned int) Screen_Cols)
+ len = (unsigned int) Screen_Cols - c;
+
+ memcpy ((char *) buf, (char *) (SL_Screen[r].neew + c), len * sizeof (short));
+ return len;
+}
+
+unsigned int SLsmg_write_raw (unsigned short *buf, unsigned int len)
+{
+ unsigned int r, c;
+ unsigned short *dest;
+
+ if (0 == point_visible (1)) return 0;
+
+ r = (unsigned int) (This_Row - Start_Row);
+ c = (unsigned int) (This_Col - Start_Col);
+
+ if (c + len > (unsigned int) Screen_Cols)
+ len = (unsigned int) Screen_Cols - c;
+
+ dest = SL_Screen[r].neew + c;
+
+ if (0 != memcmp ((char *) dest, (char *) buf, len * sizeof (short)))
+ {
+ memcpy ((char *) dest, (char *) buf, len * sizeof (short));
+ SL_Screen[r].flags |= TOUCHED;
+ }
+ return len;
+}
+
+void
+SLsmg_set_color_in_region (int color, int r, int c, unsigned int dr, unsigned int dc)
+{
+ int cmax, rmax;
+ unsigned short char_mask;
+
+ c -= Start_Col;
+ r -= Start_Row;
+
+ cmax = c + (int) dc;
+ rmax = r + (int) dr;
+
+ if (cmax > Screen_Cols) cmax = Screen_Cols;
+ if (rmax > Screen_Rows) rmax = Screen_Rows;
+
+ if (c < 0) c = 0;
+ if (r < 0) r = 0;
+
+ color = color << 8;
+
+ char_mask = 0xFF;
+
+#ifndef IBMPC_SYSTEM
+ if (0 == *tt_Use_Blink_For_ACS)
+ char_mask = 0x80FF;
+#endif
+
+ while (r < rmax)
+ {
+ unsigned short *s, *smax;
+
+ SL_Screen[r].flags |= TOUCHED;
+ s = SL_Screen[r].neew;
+ smax = s + cmax;
+ s += c;
+
+ while (s < smax)
+ {
+ *s = (*s & char_mask) | color;
+ s++;
+ }
+ r++;
+ }
+}
+
+
+void SLsmg_set_terminal_info (SLsmg_Term_Type *tt)
+{
+ if (tt == NULL) /* use default */
+ return;
+
+ if ((tt->tt_normal_video == NULL)
+ || (tt->tt_goto_rc == NULL)
+ || (tt->tt_cls == NULL)
+ || (tt->tt_del_eol == NULL)
+ || (tt->tt_smart_puts == NULL)
+ || (tt->tt_flush_output == NULL)
+ || (tt->tt_reset_video == NULL)
+ || (tt->tt_init_video == NULL)
+#ifndef IBMPC_SYSTEM
+ || (tt->tt_set_scroll_region == NULL)
+ || (tt->tt_reverse_index == NULL)
+ || (tt->tt_reset_scroll_region == NULL)
+ || (tt->tt_delete_nlines == NULL)
+ /* Variables */
+ || (tt->tt_term_cannot_scroll == NULL)
+ || (tt->tt_has_alt_charset == NULL)
+#if 0 /* These can be NULL */
+ || (tt->tt_use_blink_for_acs == NULL)
+ || (tt->tt_graphic_char_pairs == NULL)
+#endif
+ || (tt->tt_screen_cols == NULL)
+ || (tt->tt_screen_rows == NULL)
+#endif
+ )
+ SLang_exit_error ("Terminal not powerful enough for SLsmg");
+
+ tt_normal_video = tt->tt_normal_video;
+ tt_goto_rc = tt->tt_goto_rc;
+ tt_cls = tt->tt_cls;
+ tt_del_eol = tt->tt_del_eol;
+ tt_smart_puts = tt->tt_smart_puts;
+ tt_flush_output = tt->tt_flush_output;
+ tt_reset_video = tt->tt_reset_video;
+ tt_init_video = tt->tt_init_video;
+
+#ifndef IBMPC_SYSTEM
+ tt_set_scroll_region = tt->tt_set_scroll_region;
+ tt_reverse_index = tt->tt_reverse_index;
+ tt_reset_scroll_region = tt->tt_reset_scroll_region;
+ tt_delete_nlines = tt->tt_delete_nlines;
+
+ tt_Term_Cannot_Scroll = tt->tt_term_cannot_scroll;
+ tt_Has_Alt_Charset = tt->tt_has_alt_charset;
+ tt_Use_Blink_For_ACS = tt->tt_use_blink_for_acs;
+ tt_Graphics_Char_Pairs = tt->tt_graphic_char_pairs;
+#endif
+
+ tt_Screen_Cols = tt->tt_screen_cols;
+ tt_Screen_Rows = tt->tt_screen_rows;
+}
diff --git a/minislang/sltermin.c b/minislang/sltermin.c
new file mode 100644
index 000000000..18765f6d6
--- /dev/null
+++ b/minislang/sltermin.c
@@ -0,0 +1,1128 @@
+/* This file contains enough terminfo reading capabilities sufficient for
+ * the slang SLtt interface.
+ */
+
+/* Copyright (c) 1992, 1998 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 "config.h"
+#include "sl-feat.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#include "slang.h"
+#include "_slang.h"
+
+/*
+ * The majority of the comments found in the file were taken from the
+ * term(4) man page on an SGI.
+ */
+
+/* Short integers are stored in two 8-bit bytes. The first byte contains
+ * the least significant 8 bits of the value, and the second byte contains
+ * the most significant 8 bits. (Thus, the value represented is
+ * 256*second+first.) The value -1 is represented by 0377,0377, and the
+ * value -2 is represented by 0376,0377; other negative values are illegal.
+ * The -1 generally means that a capability is missing from this terminal.
+ * The -2 means that the capability has been cancelled in the terminfo
+ * source and also is to be considered missing.
+ */
+
+static int make_integer (unsigned char *buf)
+{
+ register int lo, hi;
+ lo = (int) *buf++; hi = (int) *buf;
+ if (hi == 0377)
+ {
+ if (lo == 0377) return -1;
+ if (lo == 0376) return -2;
+ }
+ return lo + 256 * hi;
+}
+
+/*
+ * The compiled file is created from the source file descriptions of the
+ * terminals (see the -I option of infocmp) by using the terminfo compiler,
+ * tic, and read by the routine setupterm [see curses(3X).] The file is
+ * divided into six parts in the following order: the header, terminal
+ * names, boolean flags, numbers, strings, and string table.
+ *
+ * The header section begins the file. This section contains six short
+ * integers in the format described below. These integers are (1) the magic
+ * number (octal 0432); (2) the size, in bytes, of the names section; (3)
+ * the number of bytes in the boolean section; (4) the number of short
+ * integers in the numbers section; (5) the number of offsets (short
+ * integers) in the strings section; (6) the size, in bytes, of the string
+ * table.
+ */
+
+#define MAGIC 0432
+
+/* In this structure, all char * fields are malloced EXCEPT if the
+ * structure is SLTERMCAP. In that case, only terminal_names is malloced
+ * and the other fields are pointers into it.
+ */
+typedef struct
+{
+#define SLTERMINFO 1
+#define SLTERMCAP 2
+ unsigned int flags;
+
+ unsigned int name_section_size;
+ char *terminal_names;
+
+ unsigned int boolean_section_size;
+ unsigned char *boolean_flags;
+
+ unsigned int num_numbers;
+ unsigned char *numbers;
+
+ unsigned int num_string_offsets;
+ unsigned char *string_offsets;
+
+ unsigned int string_table_size;
+ char *string_table;
+
+} Terminfo_Type;
+
+static char *tcap_getstr (char *, Terminfo_Type *);
+static int tcap_getnum (char *, Terminfo_Type *);
+static int tcap_getflag (char *, Terminfo_Type *);
+static int tcap_getent (char *, Terminfo_Type *);
+
+static FILE *open_terminfo (char *file, Terminfo_Type *h)
+{
+ FILE *fp;
+ unsigned char buf[12];
+
+ fp = fopen (file, "rb");
+ if (fp == NULL) return NULL;
+
+ if ((12 == fread ((char *) buf, 1, 12, fp) && (MAGIC == make_integer (buf))))
+ {
+ h->name_section_size = make_integer (buf + 2);
+ h->boolean_section_size = make_integer (buf + 4);
+ h->num_numbers = make_integer (buf + 6);
+ h->num_string_offsets = make_integer (buf + 8);
+ h->string_table_size = make_integer (buf + 10);
+ }
+ else
+ {
+ fclose (fp);
+ fp = NULL;
+ }
+ return fp;
+}
+
+/*
+ * The terminal names section comes next. It contains the first line of the
+ * terminfo description, listing the various names for the terminal,
+ * separated by the bar ( | ) character (see term(5)). The section is
+ * terminated with an ASCII NUL character.
+ */
+
+/* returns pointer to malloced space */
+static unsigned char *read_terminfo_section (FILE *fp, unsigned int size)
+{
+ char *s;
+
+ if (NULL == (s = (char *) SLmalloc (size))) return NULL;
+ if (size != fread (s, 1, size, fp))
+ {
+ SLfree (s);
+ return NULL;
+ }
+ return (unsigned char *) s;
+}
+
+static char *read_terminal_names (FILE *fp, Terminfo_Type *t)
+{
+ return t->terminal_names = (char *) read_terminfo_section (fp, t->name_section_size);
+}
+
+/*
+ * The boolean flags have one byte for each flag. This byte is either 0 or
+ * 1 as the flag is present or absent. The value of 2 means that the flag
+ * has been cancelled. The capabilities are in the same order as the file
+ * <term.h>.
+ */
+
+static unsigned char *read_boolean_flags (FILE *fp, Terminfo_Type *t)
+{
+ /* Between the boolean section and the number section, a null byte is
+ * inserted, if necessary, to ensure that the number section begins on an
+ * even byte offset. All short integers are aligned on a short word
+ * boundary.
+ */
+
+ unsigned int size = (t->name_section_size + t->boolean_section_size) % 2;
+ size += t->boolean_section_size;
+
+ return t->boolean_flags = read_terminfo_section (fp, size);
+}
+
+/*
+ * The numbers section is similar to the boolean flags section. Each
+ * capability takes up two bytes, and is stored as a short integer. If the
+ * value represented is -1 or -2, the capability is taken to be missing.
+ */
+
+static unsigned char *read_numbers (FILE *fp, Terminfo_Type *t)
+{
+ return t->numbers = read_terminfo_section (fp, 2 * t->num_numbers);
+}
+
+/* The strings section is also similar. Each capability is stored as a
+ * short integer, in the format above. A value of -1 or -2 means the
+ * capability is missing. Otherwise, the value is taken as an offset from
+ * the beginning of the string table. Special characters in ^X or \c
+ * notation are stored in their interpreted form, not the printing
+ * representation. Padding information ($<nn>) and parameter information
+ * (%x) are stored intact in uninterpreted form.
+ */
+
+static unsigned char *read_string_offsets (FILE *fp, Terminfo_Type *t)
+{
+ return t->string_offsets = (unsigned char *) read_terminfo_section (fp, 2 * t->num_string_offsets);
+}
+
+/* The final section is the string table. It contains all the values of
+ * string capabilities referenced in the string section. Each string is
+ * null terminated.
+ */
+
+static char *read_string_table (FILE *fp, Terminfo_Type *t)
+{
+ return t->string_table = (char *) read_terminfo_section (fp, t->string_table_size);
+}
+
+/*
+ * Compiled terminfo(4) descriptions are placed under the directory
+ * /usr/share/lib/terminfo. In order to avoid a linear search of a huge
+ * UNIX system directory, a two-level scheme is used:
+ * /usr/share/lib/terminfo/c/name where name is the name of the terminal,
+ * and c is the first character of name. Thus, att4425 can be found in the
+ * file /usr/share/lib/terminfo/a/att4425. Synonyms for the same terminal
+ * are implemented by multiple links to the same compiled file.
+ */
+
+#define MAX_TI_DIRS 7
+static char *Terminfo_Dirs [MAX_TI_DIRS] =
+{
+ NULL, /* $HOME/.terminfo */
+ NULL, /* $TERMINFO */
+ "/usr/share/terminfo",
+ "/usr/lib/terminfo",
+ "/usr/share/lib/terminfo",
+ "/etc/terminfo",
+ "/usr/local/lib/terminfo"
+};
+
+char *SLtt_tigetent (char *term)
+{
+ char *tidir;
+ int i;
+ FILE *fp = NULL;
+ char file[1024];
+ static char home_ti [1024];
+ char *home;
+ Terminfo_Type *ti;
+
+ if (
+ (term == NULL)
+#ifdef SLANG_UNTIC
+ && (SLang_Untic_Terminfo_File == NULL)
+#endif
+ )
+ return NULL;
+
+ if (NULL == (ti = (Terminfo_Type *) SLmalloc (sizeof (Terminfo_Type))))
+ {
+ return NULL;
+ }
+
+#ifdef SLANG_UNTIC
+ if (SLang_Untic_Terminfo_File != NULL)
+ {
+ fp = open_terminfo (SLang_Untic_Terminfo_File, ti);
+ goto fp_open_label;
+ }
+ else
+#endif
+ /* If we are on a termcap based system, use termcap */
+ if (0 == tcap_getent (term, ti)) return (char *) ti;
+
+ if (NULL != (home = getenv ("HOME")))
+ {
+ strncpy (home_ti, home, sizeof (home_ti) - 11);
+ home_ti [sizeof(home_ti) - 11] = 0;
+ strcat (home_ti, "/.terminfo");
+ Terminfo_Dirs [0] = home_ti;
+ }
+
+ Terminfo_Dirs[1] = getenv ("TERMINFO");
+ i = 0;
+ while (i < MAX_TI_DIRS)
+ {
+ tidir = Terminfo_Dirs[i];
+ if ((tidir != NULL)
+ && (sizeof (file) > strlen (tidir) + 2 + strlen (term)))
+ {
+ sprintf (file, "%s/%c/%s", tidir, *term, term);
+ if (NULL != (fp = open_terminfo (file, ti)))
+ break;
+ }
+ i++;
+ }
+#ifdef SLANG_UNTIC
+ fp_open_label:
+#endif
+
+ if (fp != NULL)
+ {
+ if (NULL != read_terminal_names (fp, ti))
+ {
+ if (NULL != read_boolean_flags (fp, ti))
+ {
+ if (NULL != read_numbers (fp, ti))
+ {
+ if (NULL != read_string_offsets (fp, ti))
+ {
+ if (NULL != read_string_table (fp, ti))
+ {
+ /* success */
+ fclose (fp);
+ ti->flags = SLTERMINFO;
+ return (char *) ti;
+ }
+ SLfree ((char *)ti->string_offsets);
+ }
+ SLfree ((char *)ti->numbers);
+ }
+ SLfree ((char *)ti->boolean_flags);
+ }
+ SLfree ((char *)ti->terminal_names);
+ }
+ fclose (fp);
+ }
+
+ SLfree ((char *)ti);
+ return NULL;
+}
+
+#ifdef SLANG_UNTIC
+# define UNTIC_COMMENT(x) ,x
+#else
+# define UNTIC_COMMENT(x)
+#endif
+
+typedef struct
+{
+ char name[3];
+ int offset;
+#ifdef SLANG_UNTIC
+ char *comment;
+#endif
+}
+Tgetstr_Map_Type;
+
+/* I need to add: K1-5, %0-5(not important), @8, &8... */
+static Tgetstr_Map_Type Tgetstr_Map [] =
+{
+ {"!1", 212 UNTIC_COMMENT("shifted key")},
+ {"!2", 213 UNTIC_COMMENT("shifted key")},
+ {"!3", 214 UNTIC_COMMENT("shifted key")},
+ {"#1", 198 UNTIC_COMMENT("shifted key")},
+ {"#2", 199 UNTIC_COMMENT("Key S-Home")},
+ {"#3", 200 UNTIC_COMMENT("Key S-Insert")},
+ {"#4", 201 UNTIC_COMMENT("Key S-Left")},
+ {"%0", 177 UNTIC_COMMENT("redo key")},
+ {"%1", 168 UNTIC_COMMENT("help key")},
+ {"%2", 169 UNTIC_COMMENT("mark key")},
+ {"%3", 170 UNTIC_COMMENT("message key")},
+ {"%4", 171 UNTIC_COMMENT("move key")},
+ {"%5", 172 UNTIC_COMMENT("next key")},
+ {"%6", 173 UNTIC_COMMENT("open key")},
+ {"%7", 174 UNTIC_COMMENT("options key")},
+ {"%8", 175 UNTIC_COMMENT("previous key")},
+ {"%9", 176 UNTIC_COMMENT("print key")},
+ {"%a", 202 UNTIC_COMMENT("shifted key")},
+ {"%b", 203 UNTIC_COMMENT("shifted key")},
+ {"%c", 204 UNTIC_COMMENT("Key S-Next")},
+ {"%d", 205 UNTIC_COMMENT("shifted key")},
+ {"%e", 206 UNTIC_COMMENT("Key S-Previous")},
+ {"%f", 207 UNTIC_COMMENT("shifted key")},
+ {"%g", 208 UNTIC_COMMENT("shifted key")},
+ {"%h", 209 UNTIC_COMMENT("shifted key")},
+ {"%i", 210 UNTIC_COMMENT("Key S-Right")},
+ {"%j", 211 UNTIC_COMMENT("shifted key")},
+ {"&0", 187 UNTIC_COMMENT("shifted key")},
+ {"&1", 178 UNTIC_COMMENT("reference key")},
+ {"&2", 179 UNTIC_COMMENT("refresh key")},
+ {"&3", 180 UNTIC_COMMENT("replace key")},
+ {"&4", 181 UNTIC_COMMENT("restart key")},
+ {"&5", 182 UNTIC_COMMENT("resume key")},
+ {"&6", 183 UNTIC_COMMENT("save key")},
+ {"&7", 184 UNTIC_COMMENT("suspend key")},
+ {"&8", 185 UNTIC_COMMENT("undo key")},
+ {"&9", 186 UNTIC_COMMENT("shifted key")},
+ {"*0", 197 UNTIC_COMMENT("shifted key")},
+ {"*1", 188 UNTIC_COMMENT("shifted key")},
+ {"*2", 189 UNTIC_COMMENT("shifted key")},
+ {"*3", 190 UNTIC_COMMENT("shifted key")},
+ {"*4", 191 UNTIC_COMMENT("Key S-Delete")},
+ {"*5", 192 UNTIC_COMMENT("shifted key")},
+ {"*6", 193 UNTIC_COMMENT("select key")},
+ {"*7", 194 UNTIC_COMMENT("Key S-End")},
+ {"*8", 195 UNTIC_COMMENT("shifted key")},
+ {"*9", 196 UNTIC_COMMENT("shifted key")},
+ {"@0", 167 UNTIC_COMMENT("find key")},
+ {"@1", 158 UNTIC_COMMENT("begin key")},
+ {"@2", 159 UNTIC_COMMENT("cancel key")},
+ {"@3", 160 UNTIC_COMMENT("close key")},
+ {"@4", 161 UNTIC_COMMENT("command key")},
+ {"@5", 162 UNTIC_COMMENT("copy key")},
+ {"@6", 163 UNTIC_COMMENT("create key")},
+ {"@7", 164 UNTIC_COMMENT("Key End")},
+ {"@8", 165 UNTIC_COMMENT("enter/send key")},
+ {"@9", 166 UNTIC_COMMENT("exit key")},
+ {"AB", 360 UNTIC_COMMENT("set ANSI color background")},
+ {"AF", 359 UNTIC_COMMENT("set ANSI color foreground")},
+ {"AL", 110 UNTIC_COMMENT("parm_insert_line")},
+ {"CC", 9 UNTIC_COMMENT("terminal settable cmd character in prototype !?")},
+ {"CM", 15 UNTIC_COMMENT("memory relative cursor addressing")},
+ {"CW", 277 UNTIC_COMMENT("define a window #1 from #2, #3 to #4, #5")},
+ {"DC", 105 UNTIC_COMMENT("delete #1 chars")},
+ {"DI", 280 UNTIC_COMMENT("dial number #1")},
+ {"DK", 275 UNTIC_COMMENT("display clock at (#1,#2)")},
+ {"DL", 106 UNTIC_COMMENT("parm_delete_line")},
+ {"DO", 107 UNTIC_COMMENT("down #1 lines")},
+ {"F1", 216 UNTIC_COMMENT("key_f11")},
+ {"F2", 217 UNTIC_COMMENT("key_f12")},
+ {"F3", 218 UNTIC_COMMENT("key_f13")},
+ {"F4", 219 UNTIC_COMMENT("key_f14")},
+ {"F5", 220 UNTIC_COMMENT("key_f15")},
+ {"F6", 221 UNTIC_COMMENT("key_f16")},
+ {"F7", 222 UNTIC_COMMENT("key_f17")},
+ {"F8", 223 UNTIC_COMMENT("key_f18")},
+ {"F9", 224 UNTIC_COMMENT("key_f19")},
+ {"FA", 225 UNTIC_COMMENT("key_f20")},
+ {"FB", 226 UNTIC_COMMENT("F21 function key")},
+ {"FC", 227 UNTIC_COMMENT("F22 function key")},
+ {"FD", 228 UNTIC_COMMENT("F23 function key")},
+ {"FE", 229 UNTIC_COMMENT("F24 function key")},
+ {"FF", 230 UNTIC_COMMENT("F25 function key")},
+ {"FG", 231 UNTIC_COMMENT("F26 function key")},
+ {"FH", 232 UNTIC_COMMENT("F27 function key")},
+ {"FI", 233 UNTIC_COMMENT("F28 function key")},
+ {"FJ", 234 UNTIC_COMMENT("F29 function key")},
+ {"FK", 235 UNTIC_COMMENT("F30 function key")},
+ {"FL", 236 UNTIC_COMMENT("F31 function key")},
+ {"FM", 237 UNTIC_COMMENT("F32 function key")},
+ {"FN", 238 UNTIC_COMMENT("F33 function key")},
+ {"FO", 239 UNTIC_COMMENT("F34 function key")},
+ {"FP", 240 UNTIC_COMMENT("F35 function key")},
+ {"FQ", 241 UNTIC_COMMENT("F36 function key")},
+ {"FR", 242 UNTIC_COMMENT("F37 function key")},
+ {"FS", 243 UNTIC_COMMENT("F38 function key")},
+ {"FT", 244 UNTIC_COMMENT("F39 function key")},
+ {"FU", 245 UNTIC_COMMENT("F40 function key")},
+ {"FV", 246 UNTIC_COMMENT("F41 function key")},
+ {"FW", 247 UNTIC_COMMENT("F42 function key")},
+ {"FX", 248 UNTIC_COMMENT("F43 function key")},
+ {"FY", 249 UNTIC_COMMENT("F44 function key")},
+ {"FZ", 250 UNTIC_COMMENT("F45 function key")},
+ {"Fa", 251 UNTIC_COMMENT("F46 function key")},
+ {"Fb", 252 UNTIC_COMMENT("F47 function key")},
+ {"Fc", 253 UNTIC_COMMENT("F48 function key")},
+ {"Fd", 254 UNTIC_COMMENT("F49 function key")},
+ {"Fe", 255 UNTIC_COMMENT("F50 function key")},
+ {"Ff", 256 UNTIC_COMMENT("F51 function key")},
+ {"Fg", 257 UNTIC_COMMENT("F52 function key")},
+ {"Fh", 258 UNTIC_COMMENT("F53 function key")},
+ {"Fi", 259 UNTIC_COMMENT("F54 function key")},
+ {"Fj", 260 UNTIC_COMMENT("F55 function key")},
+ {"Fk", 261 UNTIC_COMMENT("F56 function key")},
+ {"Fl", 262 UNTIC_COMMENT("F57 function key")},
+ {"Fm", 263 UNTIC_COMMENT("F58 function key")},
+ {"Fn", 264 UNTIC_COMMENT("F59 function key")},
+ {"Fo", 265 UNTIC_COMMENT("F60 function key")},
+ {"Fp", 266 UNTIC_COMMENT("F61 function key")},
+ {"Fq", 267 UNTIC_COMMENT("F62 function key")},
+ {"Fr", 268 UNTIC_COMMENT("F63 function key")},
+ {"G1", 400 UNTIC_COMMENT("single upper right")},
+ {"G2", 398 UNTIC_COMMENT("single upper left")},
+ {"G3", 399 UNTIC_COMMENT("single lower left")},
+ {"G4", 401 UNTIC_COMMENT("single lower right")},
+ {"GC", 408 UNTIC_COMMENT("single intersection")},
+ {"GD", 405 UNTIC_COMMENT("tee pointing down")},
+ {"GH", 406 UNTIC_COMMENT("single horizontal line")},
+ {"GL", 403 UNTIC_COMMENT("tee pointing left")},
+ {"GR", 402 UNTIC_COMMENT("tee pointing right")},
+ {"GU", 404 UNTIC_COMMENT("tee pointing up")},
+ {"GV", 407 UNTIC_COMMENT("single vertical line")},
+ {"Gm", 358 UNTIC_COMMENT("Curses should get button events")},
+ {"HU", 279 UNTIC_COMMENT("hang-up phone")},
+ {"IC", 108 UNTIC_COMMENT("insert #1 chars")},
+ {"Ic", 299 UNTIC_COMMENT("initialize color #1 to (#2,#3,#4)")},
+ {"Ip", 300 UNTIC_COMMENT("Initialize color pair #1 to fg=(#2,#3,#4), bg=(#5,#6,#7)")},
+ {"K1", 139 UNTIC_COMMENT("upper left of keypad")},
+ {"K2", 141 UNTIC_COMMENT("center of keypad")},
+ {"K3", 140 UNTIC_COMMENT("upper right of keypad")},
+ {"K4", 142 UNTIC_COMMENT("lower left of keypad")},
+ {"K5", 143 UNTIC_COMMENT("lower right of keypad")},
+ {"Km", 355 UNTIC_COMMENT("Mouse event has occurred")},
+ {"LE", 111 UNTIC_COMMENT("move #1 chars to the left")},
+ {"LF", 157 UNTIC_COMMENT("turn off soft labels")},
+ {"LO", 156 UNTIC_COMMENT("turn on soft labels")},
+ {"Lf", 273 UNTIC_COMMENT("label format")},
+ {"MC", 270 UNTIC_COMMENT("clear right and left soft margins")},
+ {"ML", 271 UNTIC_COMMENT("set left soft margin")},
+ {"ML", 368 UNTIC_COMMENT("Set both left and right margins to #1, #2")},
+ {"MR", 272 UNTIC_COMMENT("set right soft margin")},
+ {"MT", 369 UNTIC_COMMENT("Sets both top and bottom margins to #1, #2")},
+ {"Mi", 356 UNTIC_COMMENT("Mouse status information")},
+ {"PA", 285 UNTIC_COMMENT("pause for 2-3 seconds")},
+ {"PU", 283 UNTIC_COMMENT("select pulse dialling")},
+ {"QD", 281 UNTIC_COMMENT("dial number #1 without checking")},
+ {"RA", 152 UNTIC_COMMENT("turn off automatic margins")},
+ {"RC", 276 UNTIC_COMMENT("remove clock")},
+ {"RF", 215 UNTIC_COMMENT("send next input char (for ptys)")},
+ {"RI", 112 UNTIC_COMMENT("parm_right_cursor")},
+ {"RQ", 357 UNTIC_COMMENT("Request mouse position")},
+ {"RX", 150 UNTIC_COMMENT("turn off xon/xoff handshaking")},
+ {"S1", 378 UNTIC_COMMENT("Display PC character")},
+ {"S2", 379 UNTIC_COMMENT("Enter PC character display mode")},
+ {"S3", 380 UNTIC_COMMENT("Exit PC character display mode")},
+ {"S4", 381 UNTIC_COMMENT("Enter PC scancode mode")},
+ {"S5", 382 UNTIC_COMMENT("Exit PC scancode mode")},
+ {"S6", 383 UNTIC_COMMENT("PC terminal options")},
+ {"S7", 384 UNTIC_COMMENT("Escape for scancode emulation")},
+ {"S8", 385 UNTIC_COMMENT("Alternate escape for scancode emulation")},
+ {"SA", 151 UNTIC_COMMENT("turn on automatic margins")},
+ {"SC", 274 UNTIC_COMMENT("set clock, #1 hrs #2 mins #3 secs")},
+ {"SF", 109 UNTIC_COMMENT("scroll forward #1 lines")},
+ {"SR", 113 UNTIC_COMMENT("scroll back #1 lines")},
+ {"SX", 149 UNTIC_COMMENT("turn on xon/xoff handshaking")},
+ {"Sb", 303 UNTIC_COMMENT("set background (color)")},
+ {"Sf", 302 UNTIC_COMMENT("set foreground (color)")},
+ {"TO", 282 UNTIC_COMMENT("select touch tone dialing")},
+ {"UP", 114 UNTIC_COMMENT("up #1 lines")},
+ {"WA", 286 UNTIC_COMMENT("wait for dial-tone")},
+ {"WG", 278 UNTIC_COMMENT("go to window #1")},
+ {"XF", 154 UNTIC_COMMENT("XOFF character")},
+ {"XN", 153 UNTIC_COMMENT("XON character")},
+ {"Xh", 386 UNTIC_COMMENT("Enter horizontal highlight mode")},
+ {"Xl", 387 UNTIC_COMMENT("Enter left highlight mode")},
+ {"Xo", 388 UNTIC_COMMENT("Enter low highlight mode")},
+ {"Xr", 389 UNTIC_COMMENT("Enter right highlight mode")},
+ {"Xt", 390 UNTIC_COMMENT("Enter top highlight mode")},
+ {"Xv", 391 UNTIC_COMMENT("Enter vertical highlight mode")},
+ {"Xy", 370 UNTIC_COMMENT("Repeat bit image cell #1 #2 times")},
+ {"YZ", 377 UNTIC_COMMENT("Set page length to #1 lines")},
+ {"Yv", 372 UNTIC_COMMENT("Move to beginning of same row")},
+ {"Yw", 373 UNTIC_COMMENT("Give name for color #1")},
+ {"Yx", 374 UNTIC_COMMENT("Define rectangualar bit image region")},
+ {"Yy", 375 UNTIC_COMMENT("End a bit-image region")},
+ {"Yz", 376 UNTIC_COMMENT("Change to ribbon color #1")},
+ {"ZA", 304 UNTIC_COMMENT("Change number of characters per inch")},
+ {"ZB", 305 UNTIC_COMMENT("Change number of lines per inch")},
+ {"ZC", 306 UNTIC_COMMENT("Change horizontal resolution")},
+ {"ZD", 307 UNTIC_COMMENT("Change vertical resolution")},
+ {"ZE", 308 UNTIC_COMMENT("Define a character")},
+ {"ZF", 309 UNTIC_COMMENT("Enter double-wide mode")},
+ {"ZG", 310 UNTIC_COMMENT("Enter draft-quality mode")},
+ {"ZH", 311 UNTIC_COMMENT("Enter italic mode")},
+ {"ZI", 312 UNTIC_COMMENT("Start leftward carriage motion")},
+ {"ZJ", 313 UNTIC_COMMENT("Start micro-motion mode")},
+ {"ZK", 314 UNTIC_COMMENT("Enter NLQ mode")},
+ {"ZL", 315 UNTIC_COMMENT("Wnter normal-quality mode")},
+ {"ZM", 316 UNTIC_COMMENT("Enter shadow-print mode")},
+ {"ZN", 317 UNTIC_COMMENT("Enter subscript mode")},
+ {"ZO", 318 UNTIC_COMMENT("Enter superscript mode")},
+ {"ZP", 319 UNTIC_COMMENT("Start upward carriage motion")},
+ {"ZQ", 320 UNTIC_COMMENT("End double-wide mode")},
+ {"ZR", 321 UNTIC_COMMENT("End italic mode")},
+ {"ZS", 322 UNTIC_COMMENT("End left-motion mode")},
+ {"ZT", 323 UNTIC_COMMENT("End micro-motion mode")},
+ {"ZU", 324 UNTIC_COMMENT("End shadow-print mode")},
+ {"ZV", 325 UNTIC_COMMENT("End subscript mode")},
+ {"ZW", 326 UNTIC_COMMENT("End superscript mode")},
+ {"ZX", 327 UNTIC_COMMENT("End reverse character motion")},
+ {"ZY", 328 UNTIC_COMMENT("Like column_address in micro mode")},
+ {"ZZ", 329 UNTIC_COMMENT("Like cursor_down in micro mode")},
+ {"Za", 330 UNTIC_COMMENT("Like cursor_left in micro mode")},
+ {"Zb", 331 UNTIC_COMMENT("Like cursor_right in micro mode")},
+ {"Zc", 332 UNTIC_COMMENT("Like row_address in micro mode")},
+ {"Zd", 333 UNTIC_COMMENT("Like cursor_up in micro mode")},
+ {"Ze", 334 UNTIC_COMMENT("Match software bits to print-head pins")},
+ {"Zf", 335 UNTIC_COMMENT("Like parm_down_cursor in micro mode")},
+ {"Zg", 336 UNTIC_COMMENT("Like parm_left_cursor in micro mode")},
+ {"Zh", 337 UNTIC_COMMENT("Like parm_right_cursor in micro mode")},
+ {"Zi", 338 UNTIC_COMMENT("Like parm_up_cursor in micro mode")},
+ {"Zj", 339 UNTIC_COMMENT("Select character set")},
+ {"Zk", 340 UNTIC_COMMENT("Set bottom margin at current line")},
+ {"Zl", 341 UNTIC_COMMENT("Set bottom margin at line #1 or #2 lines from bottom")},
+ {"Zm", 342 UNTIC_COMMENT("Set left (right) margin at column #1 (#2)")},
+ {"Zn", 343 UNTIC_COMMENT("Set right margin at column #1")},
+ {"Zo", 344 UNTIC_COMMENT("Set top margin at current line")},
+ {"Zp", 345 UNTIC_COMMENT("Set top (bottom) margin at row #1 (#2)")},
+ {"Zq", 346 UNTIC_COMMENT("Start printing bit image braphics")},
+ {"Zr", 347 UNTIC_COMMENT("Start character set definition")},
+ {"Zs", 348 UNTIC_COMMENT("Stop printing bit image graphics")},
+ {"Zt", 349 UNTIC_COMMENT("End definition of character aet")},
+ {"Zu", 350 UNTIC_COMMENT("List of subscriptable characters")},
+ {"Zv", 351 UNTIC_COMMENT("List of superscriptable characters")},
+ {"Zw", 352 UNTIC_COMMENT("Printing any of these chars causes CR")},
+ {"Zx", 353 UNTIC_COMMENT("No motion for subsequent character")},
+ {"Zy", 354 UNTIC_COMMENT("List of character set names")},
+ {"Zz", 371 UNTIC_COMMENT("Move to next row of the bit image")},
+ {"ac", 146 UNTIC_COMMENT("acs_chars")},
+ {"ae", 38 UNTIC_COMMENT("exit_alt_charset_mode")},
+ {"al", 53 UNTIC_COMMENT("insert line")},
+ {"as", 25 UNTIC_COMMENT("enter_alt_charset_mode")},
+ {"bc", 395 UNTIC_COMMENT("move left, if not ^H")},
+ {"bl", 1 UNTIC_COMMENT("audible signal (bell)")},
+ {"bt", 0 UNTIC_COMMENT("back tab")},
+ {"bx", 411 UNTIC_COMMENT("box chars primary set")},
+ {"cb", 269 UNTIC_COMMENT("Clear to beginning of line")},
+ {"cd", 7 UNTIC_COMMENT("clear to end of screen")},
+ {"ce", 6 UNTIC_COMMENT("clr_eol")},
+ {"ch", 8 UNTIC_COMMENT("horizontal position #1, absolute")},
+ {"ci", 363 UNTIC_COMMENT("Init sequence for multiple codesets")},
+ {"cl", 5 UNTIC_COMMENT("clear screen and home cursor")},
+ {"cm", 10 UNTIC_COMMENT("move to row #1 columns #2")},
+ {"cr", 2 UNTIC_COMMENT("carriage return")},
+ {"cs", 3 UNTIC_COMMENT("change region to line #1 to line #2")},
+ {"ct", 4 UNTIC_COMMENT("clear all tab stops")},
+ {"cv", 127 UNTIC_COMMENT("vertical position #1 absolute")},
+ {"dc", 21 UNTIC_COMMENT("delete character")},
+ {"dl", 22 UNTIC_COMMENT("delete line")},
+ {"dm", 29 UNTIC_COMMENT("enter delete mode")},
+ {"do", 11 UNTIC_COMMENT("down one line")},
+ {"ds", 23 UNTIC_COMMENT("disable status line")},
+ {"dv", 362 UNTIC_COMMENT("Indicate language/codeset support")},
+ {"eA", 155 UNTIC_COMMENT("enable alternate char set")},
+ {"ec", 37 UNTIC_COMMENT("erase #1 characters")},
+ {"ed", 41 UNTIC_COMMENT("end delete mode")},
+ {"ei", 42 UNTIC_COMMENT("exit insert mode")},
+ {"ff", 46 UNTIC_COMMENT("hardcopy terminal page eject")},
+ {"fh", 284 UNTIC_COMMENT("flash switch hook")},
+ {"fs", 47 UNTIC_COMMENT("return from status line")},
+ {"hd", 24 UNTIC_COMMENT("half a line down")},
+ {"ho", 12 UNTIC_COMMENT("home cursor (if no cup)")},
+ {"hu", 137 UNTIC_COMMENT("half a line up")},
+ {"i1", 48 UNTIC_COMMENT("initialization string")},
+ {"i2", 392 UNTIC_COMMENT("secondary initialization string")},
+ {"i3", 50 UNTIC_COMMENT("initialization string")},
+ {"iP", 138 UNTIC_COMMENT("path name of program for initialization")},
+ {"ic", 52 UNTIC_COMMENT("insert character")},
+ {"if", 51 UNTIC_COMMENT("name of initialization file")},
+ {"im", 31 UNTIC_COMMENT("enter insert mode")},
+ {"ip", 54 UNTIC_COMMENT("insert padding after inserted character")},
+ {"is", 49 UNTIC_COMMENT("initialization string")},
+ {"k0", 65 UNTIC_COMMENT("F0 function key")},
+ {"k1", 66 UNTIC_COMMENT("F1 function key")},
+ {"k2", 68 UNTIC_COMMENT("F2 function key")},
+ {"k3", 69 UNTIC_COMMENT("F3 function key")},
+ {"k4", 70 UNTIC_COMMENT("F4 function key")},
+ {"k5", 71 UNTIC_COMMENT("F5 function key")},
+ {"k6", 72 UNTIC_COMMENT("F6 function key")},
+ {"k7", 73 UNTIC_COMMENT("F7 function key")},
+ {"k8", 74 UNTIC_COMMENT("F8 fucntion key")},
+ {"k9", 75 UNTIC_COMMENT("F9 function key")},
+ {"k;", 67 UNTIC_COMMENT("F10 function key")},
+ {"kA", 78 UNTIC_COMMENT("insert-line key")},
+ {"kB", 148 UNTIC_COMMENT("back-tab key")},
+ {"kC", 57 UNTIC_COMMENT("clear-screen or erase key")},
+ {"kD", 59 UNTIC_COMMENT("delete-character key")},
+ {"kE", 63 UNTIC_COMMENT("clear-to-end-of-line key")},
+ {"kF", 84 UNTIC_COMMENT("scroll-forward key")},
+ {"kH", 80 UNTIC_COMMENT("last-line key")},
+ {"kI", 77 UNTIC_COMMENT("insert-character key")},
+ {"kL", 60 UNTIC_COMMENT("delete-line key")},
+ {"kM", 62 UNTIC_COMMENT("sent by rmir or smir in insert mode")},
+ {"kN", 81 UNTIC_COMMENT("next-page key")},
+ {"kP", 82 UNTIC_COMMENT("prev-page key")},
+ {"kR", 85 UNTIC_COMMENT("scroll-backward key")},
+ {"kS", 64 UNTIC_COMMENT("clear-to-end-of-screen key")},
+ {"kT", 86 UNTIC_COMMENT("set-tab key")},
+ {"ka", 56 UNTIC_COMMENT("clear-all-tabs key")},
+ {"kb", 55 UNTIC_COMMENT("backspace key")},
+ {"kd", 61 UNTIC_COMMENT("down-arrow key")},
+ {"ke", 88 UNTIC_COMMENT("leave 'keyboard_transmit' mode")},
+ {"kh", 76 UNTIC_COMMENT("home key")},
+ {"kl", 79 UNTIC_COMMENT("left-arrow key")},
+ {"ko", 396 UNTIC_COMMENT("list of self-mapped keycaps")},
+ {"kr", 83 UNTIC_COMMENT("right-arrow key")},
+ {"ks", 89 UNTIC_COMMENT("enter 'keyboard_transmit' mode")},
+ {"kt", 58 UNTIC_COMMENT("clear-tab key")},
+ {"ku", 87 UNTIC_COMMENT("up-arrow key")},
+ {"l0", 90 UNTIC_COMMENT("label on function key f0 if not f0")},
+ {"l1", 91 UNTIC_COMMENT("label on function key f1 if not f1")},
+ {"l2", 93 UNTIC_COMMENT("label on function key f2 if not f2")},
+ {"l3", 94 UNTIC_COMMENT("label on function key f3 if not f3")},
+ {"l4", 95 UNTIC_COMMENT("label on function key f4 if not f4")},
+ {"l5", 96 UNTIC_COMMENT("lable on function key f5 if not f5")},
+ {"l6", 97 UNTIC_COMMENT("label on function key f6 if not f6")},
+ {"l7", 98 UNTIC_COMMENT("label on function key f7 if not f7")},
+ {"l8", 99 UNTIC_COMMENT("label on function key f8 if not f8")},
+ {"l9", 100 UNTIC_COMMENT("label on function key f9 if not f9")},
+ {"la", 92 UNTIC_COMMENT("label on function key f10 if not f10")},
+ {"le", 14 UNTIC_COMMENT("move left one space")},
+ {"ll", 18 UNTIC_COMMENT("last line, first column (if no cup)")},
+ {"ma", 397 UNTIC_COMMENT("map arrow keys rogue(1) motion keys")},
+ {"mb", 26 UNTIC_COMMENT("turn on blinking")},
+ {"md", 27 UNTIC_COMMENT("turn on bold (extra bright) mode")},
+ {"me", 39 UNTIC_COMMENT("turn off all attributes")},
+ {"mh", 30 UNTIC_COMMENT("turn on half-bright mode")},
+ {"mk", 32 UNTIC_COMMENT("turn on blank mode (characters invisible)")},
+ {"ml", 409 UNTIC_COMMENT("memory lock above")},
+ {"mm", 102 UNTIC_COMMENT("turn on meta mode (8th-bit on)")},
+ {"mo", 101 UNTIC_COMMENT("turn off meta mode")},
+ {"mp", 33 UNTIC_COMMENT("turn on protected mode")},
+ {"mr", 34 UNTIC_COMMENT("turn on reverse video mode")},
+ {"mu", 410 UNTIC_COMMENT("memory unlock")},
+ {"nd", 17 UNTIC_COMMENT("move right one space")},
+ {"nl", 394 UNTIC_COMMENT("use to move down")},
+ {"nw", 103 UNTIC_COMMENT("newline (behave like cr followed by lf)")},
+ {"oc", 298 UNTIC_COMMENT("Set all color pairs to the original ones")},
+ {"op", 297 UNTIC_COMMENT("Set default pair to its original value")},
+ {"pO", 144 UNTIC_COMMENT("turn on printer for #1 bytes")},
+ {"pc", 104 UNTIC_COMMENT("padding char (instead of null)")},
+ {"pf", 119 UNTIC_COMMENT("turn off printer")},
+ {"pk", 115 UNTIC_COMMENT("program function key #1 to type string #2")},
+ {"pl", 116 UNTIC_COMMENT("program function key #1 to execute string #2")},
+ {"pn", 147 UNTIC_COMMENT("program label #1 to show string #2")},
+ {"po", 120 UNTIC_COMMENT("turn on printer")},
+ {"ps", 118 UNTIC_COMMENT("print contents of screen")},
+ {"px", 117 UNTIC_COMMENT("program function key #1 to transmit string #2")},
+ {"r1", 122 UNTIC_COMMENT("reset string")},
+ {"r2", 123 UNTIC_COMMENT("reset string")},
+ {"r3", 124 UNTIC_COMMENT("reset string")},
+ {"rP", 145 UNTIC_COMMENT("like ip but when in insert mode")},
+ {"rc", 126 UNTIC_COMMENT("restore cursor to last position of sc")},
+ {"rf", 125 UNTIC_COMMENT("name of reset file")},
+ {"rp", 121 UNTIC_COMMENT("repeat char #1 #2 times")},
+ {"rs", 393 UNTIC_COMMENT("terminal reset string")},
+ {"s0", 364 UNTIC_COMMENT("Shift to code set 0 (EUC set 0, ASCII)")},
+ {"s1", 365 UNTIC_COMMENT("Shift to code set 1")},
+ {"s2", 366 UNTIC_COMMENT("Shift to code set 2")},
+ {"s3", 367 UNTIC_COMMENT("Shift to code set 3")},
+ {"sa", 131 UNTIC_COMMENT("define video attributes #1-#9 (PG9)")},
+ {"sc", 128 UNTIC_COMMENT("save current cursor position")},
+ {"se", 43 UNTIC_COMMENT("exit standout mode")},
+ {"sf", 129 UNTIC_COMMENT("scroll text up")},
+ {"so", 35 UNTIC_COMMENT("begin standout mode")},
+ {"sp", 301 UNTIC_COMMENT("Set current color pair to #1")},
+ {"sr", 130 UNTIC_COMMENT("scroll text down")},
+ {"st", 132 UNTIC_COMMENT("set a tab in every row, current columns")},
+ {"ta", 134 UNTIC_COMMENT("tab to next 8-space hardware tab stop")},
+ {"te", 40 UNTIC_COMMENT("strings to end programs using cup")},
+ {"ti", 28 UNTIC_COMMENT("string to start programs using cup")},
+ {"ts", 135 UNTIC_COMMENT("move to status line")},
+ {"u0", 287 UNTIC_COMMENT("User string #0")},
+ {"u1", 288 UNTIC_COMMENT("User string #1")},
+ {"u2", 289 UNTIC_COMMENT("User string #2")},
+ {"u3", 290 UNTIC_COMMENT("User string #3")},
+ {"u4", 291 UNTIC_COMMENT("User string #4")},
+ {"u5", 292 UNTIC_COMMENT("User string #5")},
+ {"u6", 293 UNTIC_COMMENT("User string #6")},
+ {"u7", 294 UNTIC_COMMENT("User string #7")},
+ {"u8", 295 UNTIC_COMMENT("User string #8")},
+ {"u9", 296 UNTIC_COMMENT("User string #9")},
+ {"uc", 136 UNTIC_COMMENT("underline char and move past it")},
+ {"ue", 44 UNTIC_COMMENT("exit underline mode")},
+ {"up", 19 UNTIC_COMMENT("up one line")},
+ {"us", 36 UNTIC_COMMENT("begin underline mode")},
+ {"vb", 45 UNTIC_COMMENT("visible bell (may not move cursor)")},
+ {"ve", 16 UNTIC_COMMENT("make cursor appear normal (undo civis/cvvis)")},
+ {"vi", 13 UNTIC_COMMENT("make cursor invisible")},
+ {"vs", 20 UNTIC_COMMENT("make cursor very visible")},
+ {"wi", 133 UNTIC_COMMENT("current window is lines #1-#2 cols #3-#4")},
+ {"xl", 361 UNTIC_COMMENT("Program function key #1 to type string #2 and show string #3")},
+ {"", -1 UNTIC_COMMENT(NULL)}
+};
+
+static int compute_cap_offset (char *cap, Terminfo_Type *t, Tgetstr_Map_Type *map, unsigned int max_ofs)
+{
+ char cha, chb;
+
+ (void) t;
+ cha = *cap++; chb = *cap;
+
+ while (*map->name != 0)
+ {
+ if ((cha == *map->name) && (chb == *(map->name + 1)))
+ {
+ if (map->offset >= (int) max_ofs) return -1;
+ return map->offset;
+ }
+ map++;
+ }
+ return -1;
+}
+
+char *SLtt_tigetstr (char *cap, char **pp)
+{
+ int offset;
+ Terminfo_Type *t;
+
+ if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return NULL;
+
+ if (t->flags == SLTERMCAP) return tcap_getstr (cap, t);
+
+ offset = compute_cap_offset (cap, t, Tgetstr_Map, t->num_string_offsets);
+ if (offset < 0) return NULL;
+ offset = make_integer (t->string_offsets + 2 * offset);
+ if (offset < 0) return NULL;
+ return t->string_table + offset;
+}
+
+static Tgetstr_Map_Type Tgetnum_Map[] =
+{
+ {"BT", 30 UNTIC_COMMENT("number of buttons on mouse")},
+ {"Co", 13 UNTIC_COMMENT("maximum numbers of colors on screen")},
+ {"MW", 12 UNTIC_COMMENT("maxumum number of defineable windows")},
+ {"NC", 15 UNTIC_COMMENT("video attributes that can't be used with colors")},
+ {"Nl", 8 UNTIC_COMMENT("number of labels on screen")},
+ {"Ya", 16 UNTIC_COMMENT("numbers of bytes buffered before printing")},
+ {"Yb", 17 UNTIC_COMMENT("spacing of pins vertically in pins per inch")},
+ {"Yc", 18 UNTIC_COMMENT("spacing of dots horizontally in dots per inch")},
+ {"Yd", 19 UNTIC_COMMENT("maximum value in micro_..._address")},
+ {"Ye", 20 UNTIC_COMMENT("maximum value in parm_..._micro")},
+ {"Yf", 21 UNTIC_COMMENT("character size when in micro mode")},
+ {"Yg", 22 UNTIC_COMMENT("line size when in micro mode")},
+ {"Yh", 23 UNTIC_COMMENT("numbers of pins in print-head")},
+ {"Yi", 24 UNTIC_COMMENT("horizontal resolution in units per line")},
+ {"Yj", 25 UNTIC_COMMENT("vertical resolution in units per line")},
+ {"Yk", 26 UNTIC_COMMENT("horizontal resolution in units per inch")},
+ {"Yl", 27 UNTIC_COMMENT("vertical resolution in units per inch")},
+ {"Ym", 28 UNTIC_COMMENT("print rate in chars per second")},
+ {"Yn", 29 UNTIC_COMMENT("character step size when in double wide mode")},
+ {"Yo", 31 UNTIC_COMMENT("number of passed for each bit-image row")},
+ {"Yp", 32 UNTIC_COMMENT("type of bit-image device")},
+ {"co", 0 UNTIC_COMMENT("number of columns in aline")},
+ {"dB", 36 UNTIC_COMMENT("padding required for ^H")},
+ {"dC", 34 UNTIC_COMMENT("pad needed for CR")},
+ {"dN", 35 UNTIC_COMMENT("pad needed for LF")},
+ {"dT", 37 UNTIC_COMMENT("padding required for ^I")},
+ {"it", 1 UNTIC_COMMENT("tabs initially every # spaces")},
+ {"kn", 38 UNTIC_COMMENT("count of function keys")},
+ {"lh", 9 UNTIC_COMMENT("rows in each label")},
+ {"li", 2 UNTIC_COMMENT("number of lines on screen or page")},
+ {"lm", 3 UNTIC_COMMENT("lines of memory if > line. 0 => varies")},
+ {"lw", 10 UNTIC_COMMENT("columns in each label")},
+ {"ma", 11 UNTIC_COMMENT("maximum combined attributes terminal can handle")},
+ {"pa", 14 UNTIC_COMMENT("maximum number of color-pairs on the screen")},
+ {"pb", 5 UNTIC_COMMENT("lowest baud rate where padding needed")},
+ {"sg", 4 UNTIC_COMMENT("number of blank chars left by smso or rmso")},
+ {"ug", 33 UNTIC_COMMENT("number of blanks left by ul")},
+ {"vt", 6 UNTIC_COMMENT("virtual terminal number (CB/unix)")},
+ {"ws", 7 UNTIC_COMMENT("columns in status line")},
+ {"", -1 UNTIC_COMMENT(NULL)}
+};
+
+int SLtt_tigetnum (char *cap, char **pp)
+{
+ int offset;
+ Terminfo_Type *t;
+
+ if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return -1;
+
+ if (t->flags == SLTERMCAP) return tcap_getnum (cap, t);
+
+ offset = compute_cap_offset (cap, t, Tgetnum_Map, t->num_numbers);
+ if (offset < 0) return -1;
+ return make_integer (t->numbers + 2 * offset);
+}
+
+static Tgetstr_Map_Type Tgetflag_Map[] =
+{
+ {"5i", 22 UNTIC_COMMENT("printer won't echo on screen")},
+ {"HC", 23 UNTIC_COMMENT("cursor is hard to see")},
+ {"MT", 40 UNTIC_COMMENT("has meta key")},
+ {"ND", 26 UNTIC_COMMENT("scrolling region is non-destructive")},
+ {"NL", 41 UNTIC_COMMENT("move down with \n")},
+ {"NP", 25 UNTIC_COMMENT("pad character does not exist")},
+ {"NR", 24 UNTIC_COMMENT("smcup does not reverse rmcup")},
+ {"YA", 30 UNTIC_COMMENT("only positive motion for hpa/mhpa caps")},
+ {"YB", 31 UNTIC_COMMENT("using cr turns off micro mode")},
+ {"YC", 32 UNTIC_COMMENT("printer needs operator to change character set")},
+ {"YD", 33 UNTIC_COMMENT("only positive motion for vpa/mvpa caps")},
+ {"YE", 34 UNTIC_COMMENT("printing in last column causes cr")},
+ {"YF", 35 UNTIC_COMMENT("changing character pitch changes resolution")},
+ {"YG", 36 UNTIC_COMMENT("changing line pitch changes resolution")},
+ {"am", 1 UNTIC_COMMENT("terminal has automatic margins")},
+ {"bs", 37 UNTIC_COMMENT("uses ^H to move left")},
+ {"bw", 0 UNTIC_COMMENT("cub1 wraps from column 0 to last column")},
+ {"cc", 27 UNTIC_COMMENT("terminal can re-define existing colors")},
+ {"da", 11 UNTIC_COMMENT("display may be retained above the screen")},
+ {"db", 12 UNTIC_COMMENT("display may be retained below the screen")},
+ {"eo", 5 UNTIC_COMMENT("can erase overstrikes with a blank")},
+ {"es", 16 UNTIC_COMMENT("escape can be used on the status line")},
+ {"gn", 6 UNTIC_COMMENT("generic line type")},
+ {"hc", 7 UNTIC_COMMENT("hardcopy terminal")},
+ {"hl", 29 UNTIC_COMMENT("terminal uses only HLS color notation (tektronix)")},
+ {"hs", 9 UNTIC_COMMENT("has extra status line")},
+ {"hz", 18 UNTIC_COMMENT("can't print ~'s (hazeltine)")},
+ {"in", 10 UNTIC_COMMENT("insert mode distinguishes nulls")},
+ {"km", 8 UNTIC_COMMENT("Has a meta key, sets msb high")},
+ {"mi", 13 UNTIC_COMMENT("safe to move while in insert mode")},
+ {"ms", 14 UNTIC_COMMENT("safe to move while in standout mode")},
+ {"nc", 39 UNTIC_COMMENT("no way to go to start of line")},
+ {"ns", 38 UNTIC_COMMENT("crt cannot scroll")},
+ {"nx", 21 UNTIC_COMMENT("padding won't work, xon/xoff required")},
+ {"os", 15 UNTIC_COMMENT("terminal can overstrike")},
+ {"pt", 42 UNTIC_COMMENT("has 8-char tabs invoked with ^I")},
+ {"ul", 19 UNTIC_COMMENT("underline character overstrikes")},
+ {"ut", 28 UNTIC_COMMENT("screen erased with background color")},
+ {"xb", 2 UNTIC_COMMENT("beehive (f1=escape, f2=ctrl C)")},
+ {"xn", 4 UNTIC_COMMENT("newline ignored after 80 cols (concept)")},
+ {"xo", 20 UNTIC_COMMENT("terminal uses xon/xoff handshaking")},
+ {"xr", 43 UNTIC_COMMENT("return clears the line")},
+ {"xs", 3 UNTIC_COMMENT("standout not erased by overwriting (hp)")},
+ {"xt", 17 UNTIC_COMMENT("tabs destructive, magic so char (t1061)")},
+ {"", -1 UNTIC_COMMENT(NULL)}
+};
+
+int SLtt_tigetflag (char *cap, char **pp)
+{
+ int offset;
+ Terminfo_Type *t;
+
+ if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return -1;
+
+ if (t->flags == SLTERMCAP) return tcap_getflag (cap, t);
+
+ offset = compute_cap_offset (cap, t, Tgetflag_Map, t->boolean_section_size);
+
+ if (offset < 0) return -1;
+ return (int) *(t->boolean_flags + offset);
+}
+
+/* These are my termcap routines. They only work with the TERMCAP environment
+ * variable. This variable must contain the termcap entry and NOT the file.
+ */
+
+static int tcap_getflag (char *cap, Terminfo_Type *t)
+{
+ char a, b;
+ char *f = (char *) t->boolean_flags;
+ char *fmax;
+
+ if (f == NULL) return 0;
+ fmax = f + t->boolean_section_size;
+
+ a = *cap;
+ b = *(cap + 1);
+ while (f < fmax)
+ {
+ if ((a == f[0]) && (b == f[1]))
+ return 1;
+ f += 2;
+ }
+ return 0;
+}
+
+static char *tcap_get_cap (unsigned char *cap, unsigned char *caps, unsigned int len)
+{
+ unsigned char c0, c1;
+ unsigned char *caps_max;
+
+ c0 = cap[0];
+ c1 = cap[1];
+
+ if (caps == NULL) return NULL;
+ caps_max = caps + len;
+ while (caps < caps_max)
+ {
+ if ((c0 == caps[0]) && (c1 == caps[1]))
+ {
+ return (char *) caps + 3;
+ }
+ caps += (int) caps[2];
+ }
+ return NULL;
+}
+
+static int tcap_getnum (char *cap, Terminfo_Type *t)
+{
+ cap = tcap_get_cap ((unsigned char *) cap, t->numbers, t->num_numbers);
+ if (cap == NULL) return -1;
+ return atoi (cap);
+}
+
+static char *tcap_getstr (char *cap, Terminfo_Type *t)
+{
+ return tcap_get_cap ((unsigned char *) cap, (unsigned char *) t->string_table, t->string_table_size);
+}
+
+static int tcap_extract_field (unsigned char *t0)
+{
+ register unsigned char ch, *t = t0;
+ while (((ch = *t) != 0) && (ch != ':')) t++;
+ if (ch == ':') return (int) (t - t0);
+ return -1;
+}
+
+int SLtt_Try_Termcap = 1;
+static int tcap_getent (char *term, Terminfo_Type *ti)
+{
+ unsigned char *termcap, ch;
+ unsigned char *buf, *b;
+ unsigned char *t;
+ int len;
+
+ if (SLtt_Try_Termcap == 0) return -1;
+#if 1
+ /* XFREE86 xterm sets the TERMCAP environment variable to an invalid
+ * value. Specifically, it lacks the tc= string.
+ */
+ if (!strncmp (term, "xterm", 5))
+ return -1;
+#endif
+ termcap = (unsigned char *) getenv ("TERMCAP");
+ if ((termcap == NULL) || (*termcap == '/')) return -1;
+
+ /* We have a termcap so lets use it provided it does not have a reference
+ * to another terminal via tc=. In that case, user terminfo. The alternative
+ * would be to parse the termcap file which I do not want to do right now.
+ * Besides, this is a terminfo based system and if the termcap were parsed
+ * terminfo would almost never get a chance to run. In addition, the tc=
+ * thing should not occur if tset is used to set the termcap entry.
+ */
+ t = termcap;
+ while ((len = tcap_extract_field (t)) != -1)
+ {
+ if ((len > 3) && (t[0] == 't') && (t[1] == 'c') && (t[2] == '='))
+ return -1;
+ t += (len + 1);
+ }
+
+ /* malloc some extra space just in case it is needed. */
+ len = strlen ((char *) termcap) + 256;
+ if (NULL == (buf = (unsigned char *) SLmalloc ((unsigned int) len))) return -1;
+
+ b = buf;
+
+ /* The beginning of the termcap entry contains the names of the entry.
+ * It is terminated by a colon.
+ */
+
+ ti->terminal_names = (char *) b;
+ t = termcap;
+ len = tcap_extract_field (t);
+ if (len < 0)
+ {
+ SLfree ((char *)buf);
+ return -1;
+ }
+ strncpy ((char *) b, (char *) t, (unsigned int) len);
+ b[len] = 0;
+ b += len + 1;
+ ti->name_section_size = len;
+
+ /* Now, we are really at the start of the termcap entries. Point the
+ * termcap variable here since we want to refer to this a number of times.
+ */
+ termcap = t + (len + 1);
+
+ /* Process strings first. */
+ ti->string_table = (char *) b;
+ t = termcap;
+ while (-1 != (len = tcap_extract_field (t)))
+ {
+ unsigned char *b1;
+ unsigned char *tmax;
+
+ /* We are looking for: XX=something */
+ if ((len < 4) || (t[2] != '=') || (*t == '.'))
+ {
+ t += len + 1;
+ continue;
+ }
+ tmax = t + len;
+ b1 = b;
+
+ while (t < tmax)
+ {
+ ch = *t++;
+ if ((ch == '\\') && (t < tmax))
+ {
+ t = (unsigned char *) _SLexpand_escaped_char ((char *) t, (char *) &ch);
+ }
+ else if ((ch == '^') && (t < tmax))
+ {
+ ch = *t++;
+ if (ch == '?') ch = 127;
+ else ch = (ch | 0x20) - ('a' - 1);
+ }
+ *b++ = ch;
+ }
+ /* Null terminate it. */
+ *b++ = 0;
+ len = (int) (b - b1);
+ b1[2] = (unsigned char) len; /* replace the = by the length */
+ /* skip colon to next field. */
+ t++;
+ }
+ ti->string_table_size = (int) (b - (unsigned char *) ti->string_table);
+
+ /* Now process the numbers. */
+
+ t = termcap;
+ ti->numbers = b;
+ while (-1 != (len = tcap_extract_field (t)))
+ {
+ unsigned char *b1;
+ unsigned char *tmax;
+
+ /* We are looking for: XX#NUMBER */
+ if ((len < 4) || (t[2] != '#') || (*t == '.'))
+ {
+ t += len + 1;
+ continue;
+ }
+ tmax = t + len;
+ b1 = b;
+
+ while (t < tmax)
+ {
+ *b++ = *t++;
+ }
+ /* Null terminate it. */
+ *b++ = 0;
+ len = (int) (b - b1);
+ b1[2] = (unsigned char) len; /* replace the # by the length */
+ t++;
+ }
+ ti->num_numbers = (int) (b - ti->numbers);
+
+ /* Now process the flags. */
+ t = termcap;
+ ti->boolean_flags = b;
+ while (-1 != (len = tcap_extract_field (t)))
+ {
+ /* We are looking for: XX#NUMBER */
+ if ((len != 2) || (*t == '.') || (*t <= ' '))
+ {
+ t += len + 1;
+ continue;
+ }
+ b[0] = t[0];
+ b[1] = t[1];
+ t += 3;
+ b += 2;
+ }
+ ti->boolean_section_size = (int) (b - ti->boolean_flags);
+ ti->flags = SLTERMCAP;
+ return 0;
+}
diff --git a/minislang/slutty.c b/minislang/slutty.c
new file mode 100644
index 000000000..2cc87f1be
--- /dev/null
+++ b/minislang/slutty.c
@@ -0,0 +1,595 @@
+/* slutty.c --- Unix Low level terminal (tty) functions for S-Lang */
+/* Copyright (c) 1992, 1998 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 "config.h"
+#include "sl-feat.h"
+
+#include <stdio.h>
+#include <signal.h>
+/* sequent support thanks to Kenneth Lorber <keni@oasys.dt.navy.mil> */
+/* SYSV (SYSV ISC R3.2 v3.0) provided by iain.lea@erlm.siemens.de */
+
+#if defined (_AIX) && !defined (_ALL_SOURCE)
+# define _ALL_SOURCE /* so NBBY is defined in <sys/types.h> */
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+#ifdef SYSV
+# include <fcntl.h>
+# ifndef CRAY
+# include <sys/termio.h>
+# include <sys/stream.h>
+# include <sys/ptem.h>
+# include <sys/tty.h>
+# endif
+#endif
+
+#ifdef __BEOS__
+/* Prototype for select */
+# include <net/socket.h>
+#endif
+
+#include <sys/file.h>
+
+#ifndef sun
+# include <sys/ioctl.h>
+#endif
+
+#ifdef __QNX__
+# include <sys/select.h>
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+
+#if defined (_AIX) && !defined (FD_SET)
+# include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
+#endif
+
+#ifndef O_RDWR
+# include <fcntl.h>
+#endif
+
+#include "slang.h"
+#include "_slang.h"
+
+int SLang_TT_Read_FD = -1;
+int SLang_TT_Baud_Rate;
+
+#ifdef HAVE_TERMIOS_H
+# if !defined(HAVE_TCGETATTR) || !defined(HAVE_TCSETATTR)
+# undef HAVE_TERMIOS_H
+# endif
+#endif
+
+#ifndef HAVE_TERMIOS_H
+
+# if !defined(CBREAK) && defined(sun)
+# ifndef BSD_COMP
+# define BSD_COMP 1
+# endif
+# include <sys/ioctl.h>
+# endif
+
+typedef struct
+ {
+ struct tchars t;
+ struct ltchars lt;
+ struct sgttyb s;
+ }
+TTY_Termio_Type;
+#else
+# include <termios.h>
+typedef struct termios TTY_Termio_Type;
+#endif
+
+static TTY_Termio_Type Old_TTY;
+
+#ifdef HAVE_TERMIOS_H
+typedef struct
+{
+ unsigned int key;
+ unsigned int value;
+} Baud_Rate_Type;
+
+static Baud_Rate_Type Baud_Rates [] =
+{
+#ifdef B0
+ {B0, 0},
+#endif
+#ifdef B50
+ {B50, 50},
+#endif
+#ifdef B75
+ {B75, 75},
+#endif
+#ifdef B110
+ {B110, 110},
+#endif
+#ifdef B134
+ {B134, 134},
+#endif
+#ifdef B150
+ {B150, 150},
+#endif
+#ifdef B200
+ {B200, 200},
+#endif
+#ifdef B300
+ {B300, 300},
+#endif
+#ifdef B600
+ {B600, 600},
+#endif
+#ifdef B1200
+ {B1200, 1200},
+#endif
+#ifdef B1800
+ {B1800, 1800},
+#endif
+#ifdef B2400
+ {B2400, 2400},
+#endif
+#ifdef B4800
+ {B4800, 4800},
+#endif
+#ifdef B9600
+ {B9600, 9600},
+#endif
+#ifdef B19200
+ {B19200, 19200},
+#endif
+#ifdef B38400
+ {B38400, 38400},
+#endif
+#ifdef B57600
+ {B57600, 57600},
+#endif
+#ifdef B115200
+ {B115200, 115200},
+#endif
+#ifdef B230400
+ {B230400, 230400},
+#endif
+ {0, 0}
+};
+
+static void
+set_baud_rate (TTY_Termio_Type *tty)
+{
+#ifdef HAVE_CFGETOSPEED
+ unsigned int speed;
+ Baud_Rate_Type *b, *bmax;
+
+ if (SLang_TT_Baud_Rate)
+ return; /* already set */
+
+ speed = (unsigned int) cfgetospeed (tty);
+
+ b = Baud_Rates;
+ bmax = b + (sizeof (Baud_Rates)/sizeof(Baud_Rates[0]));
+ while (b < bmax)
+ {
+ if (b->key == speed)
+ {
+ SLang_TT_Baud_Rate = b->value;
+ return;
+ }
+ b++;
+ }
+#else
+ (void) tty;
+#endif
+}
+
+#endif /* HAVE_TERMIOS_H */
+
+#ifdef HAVE_TERMIOS_H
+# define GET_TERMIOS(fd, x) tcgetattr(fd, x)
+# define SET_TERMIOS(fd, x) tcsetattr(fd, TCSADRAIN, x)
+#else
+# ifdef TCGETS
+# define GET_TERMIOS(fd, x) ioctl(fd, TCGETS, x)
+# define SET_TERMIOS(fd, x) ioctl(fd, TCSETS, x)
+# else
+# define X(x,m) &(((TTY_Termio_Type *)(x))->m)
+# define GET_TERMIOS(fd, x) \
+ ((ioctl(fd, TIOCGETC, X(x,t)) || \
+ ioctl(fd, TIOCGLTC, X(x,lt)) || \
+ ioctl(fd, TIOCGETP, X(x,s))) ? -1 : 0)
+# define SET_TERMIOS(fd, x) \
+ ((ioctl(fd, TIOCSETC, X(x,t)) ||\
+ ioctl(fd, TIOCSLTC, X(x,lt)) || \
+ ioctl(fd, TIOCSETP, X(x,s))) ? -1 : 0)
+# endif
+#endif
+
+static int TTY_Inited = 0;
+static int TTY_Open = 0;
+
+#ifdef ultrix /* Ultrix gets _POSIX_VDISABLE wrong! */
+# define NULL_VALUE -1
+#else
+# ifdef _POSIX_VDISABLE
+# define NULL_VALUE _POSIX_VDISABLE
+# else
+# define NULL_VALUE 255
+# endif
+#endif
+
+int SLang_init_tty (int abort_char, int no_flow_control, int opost)
+{
+ TTY_Termio_Type newtty;
+
+ SLsig_block_signals ();
+
+ if (TTY_Inited)
+ {
+ SLsig_unblock_signals ();
+ return 0;
+ }
+
+ TTY_Open = 0;
+
+ if ((SLang_TT_Read_FD == -1)
+ || (1 != isatty (SLang_TT_Read_FD)))
+ {
+#ifdef O_RDWR
+# ifndef __BEOS__ /* I have been told that BEOS will HANG if passed /dev/tty */
+ if ((SLang_TT_Read_FD = open("/dev/tty", O_RDWR)) >= 0)
+ {
+ TTY_Open = 1;
+ }
+# endif
+#endif
+ if (TTY_Open == 0)
+ {
+ SLang_TT_Read_FD = fileno (stderr);
+ if (1 != isatty (SLang_TT_Read_FD))
+ {
+ SLang_TT_Read_FD = fileno (stdin);
+ if (1 != isatty (SLang_TT_Read_FD))
+ {
+ fprintf (stderr, "Failed to open terminal.");
+ return -1;
+ }
+ }
+ }
+ }
+
+ SLang_Abort_Char = abort_char;
+
+ /* Some systems may not permit signals to be blocked. As a result, the
+ * return code must be checked.
+ */
+ while (-1 == GET_TERMIOS(SLang_TT_Read_FD, &Old_TTY))
+ {
+ if (errno != EINTR)
+ {
+ SLsig_unblock_signals ();
+ return -1;
+ }
+ }
+
+ while (-1 == GET_TERMIOS(SLang_TT_Read_FD, &newtty))
+ {
+ if (errno != EINTR)
+ {
+ SLsig_unblock_signals ();
+ return -1;
+ }
+ }
+
+#ifndef HAVE_TERMIOS_H
+ newtty.s.sg_flags &= ~(ECHO);
+ newtty.s.sg_flags &= ~(CRMOD);
+ /* if (Flow_Control == 0) newtty.s.sg_flags &= ~IXON; */
+ newtty.t.t_eofc = 1;
+ if (abort_char == -1) SLang_Abort_Char = newtty.t.t_intrc;
+ newtty.t.t_intrc = SLang_Abort_Char; /* ^G */
+ newtty.t.t_quitc = 255;
+ newtty.lt.t_suspc = 255; /* to ignore ^Z */
+ newtty.lt.t_dsuspc = 255; /* to ignore ^Y */
+ newtty.lt.t_lnextc = 255;
+ newtty.s.sg_flags |= CBREAK; /* do I want cbreak or raw????? */
+#else
+
+ /* get baud rate */
+
+ newtty.c_iflag &= ~(ECHO | INLCR | ICRNL);
+#ifdef ISTRIP
+ /* newtty.c_iflag &= ~ISTRIP; */
+#endif
+ if (opost == 0) newtty.c_oflag &= ~OPOST;
+
+ set_baud_rate (&newtty);
+
+ if (no_flow_control) newtty.c_iflag &= ~IXON; else newtty.c_iflag |= IXON;
+
+ newtty.c_cc[VEOF] = 1;
+ newtty.c_cc[VMIN] = 1;
+ newtty.c_cc[VTIME] = 0;
+ newtty.c_lflag = ISIG | NOFLSH;
+ if (abort_char == -1) SLang_Abort_Char = newtty.c_cc[VINTR];
+ newtty.c_cc[VINTR] = SLang_Abort_Char; /* ^G */
+ newtty.c_cc[VQUIT] = NULL_VALUE;
+ newtty.c_cc[VSUSP] = NULL_VALUE; /* to ignore ^Z */
+#ifdef VDSUSP
+ newtty.c_cc[VDSUSP] = NULL_VALUE; /* to ignore ^Y */
+#endif
+#ifdef VLNEXT
+ newtty.c_cc[VLNEXT] = NULL_VALUE; /* to ignore ^V ? */
+#endif
+#ifdef VSWTCH
+ newtty.c_cc[VSWTCH] = NULL_VALUE; /* to ignore who knows what */
+#endif
+#endif /* NOT HAVE_TERMIOS_H */
+
+ while (-1 == SET_TERMIOS(SLang_TT_Read_FD, &newtty))
+ {
+ if (errno != EINTR)
+ {
+ SLsig_unblock_signals ();
+ return -1;
+ }
+ }
+
+ TTY_Inited = 1;
+ SLsig_unblock_signals ();
+ return 0;
+}
+
+void SLtty_set_suspend_state (int mode)
+{
+ TTY_Termio_Type newtty;
+
+ SLsig_block_signals ();
+
+ if (TTY_Inited == 0)
+ {
+ SLsig_unblock_signals ();
+ return;
+ }
+
+ while ((-1 == GET_TERMIOS (SLang_TT_Read_FD, &newtty))
+ && (errno == EINTR))
+ ;
+
+#ifndef HAVE_TERMIOS_H
+ /* I do not know if all systems define the t_dsuspc field */
+ if (mode == 0)
+ {
+ newtty.lt.t_suspc = 255;
+ newtty.lt.t_dsuspc = 255;
+ }
+ else
+ {
+ newtty.lt.t_suspc = Old_TTY.lt.t_suspc;
+ newtty.lt.t_dsuspc = Old_TTY.lt.t_dsuspc;
+ }
+#else
+ if (mode == 0)
+ {
+ newtty.c_cc[VSUSP] = NULL_VALUE;
+#ifdef VDSUSP
+ newtty.c_cc[VDSUSP] = NULL_VALUE;
+#endif
+ }
+ else
+ {
+ newtty.c_cc[VSUSP] = Old_TTY.c_cc[VSUSP];
+#ifdef VDSUSP
+ newtty.c_cc[VDSUSP] = Old_TTY.c_cc[VDSUSP];
+#endif
+ }
+#endif
+
+ while ((-1 == SET_TERMIOS (SLang_TT_Read_FD, &newtty))
+ && (errno == EINTR))
+ ;
+
+ SLsig_unblock_signals ();
+}
+
+void SLang_reset_tty (void)
+{
+ SLsig_block_signals ();
+
+ if (TTY_Inited == 0)
+ {
+ SLsig_unblock_signals ();
+ return;
+ }
+
+ while ((-1 == SET_TERMIOS(SLang_TT_Read_FD, &Old_TTY))
+ && (errno == EINTR))
+ ;
+
+ if (TTY_Open)
+ {
+ while ((-1 == close (SLang_TT_Read_FD))
+ && (errno == EINTR))
+ ;
+
+ TTY_Open = 0;
+ SLang_TT_Read_FD = -1;
+ }
+
+ TTY_Inited = 0;
+ SLsig_unblock_signals ();
+}
+
+static void default_sigint (int sig)
+{
+ sig = errno; /* use parameter */
+
+ SLKeyBoard_Quit = 1;
+ if (SLang_Ignore_User_Abort == 0) SLang_Error = SL_USER_BREAK;
+ SLsignal_intr (SIGINT, default_sigint);
+ errno = sig;
+}
+
+int SLang_set_abort_signal (void (*hand)(int))
+{
+ int save_errno = errno;
+ SLSig_Fun_Type *f;
+
+ if (hand == NULL) hand = default_sigint;
+ f = SLsignal_intr (SIGINT, hand);
+
+ errno = save_errno;
+
+ if (f == (SLSig_Fun_Type *) SIG_ERR)
+ return -1;
+
+ return 0;
+}
+
+#ifndef FD_SET
+#define FD_SET(fd, tthis) *(tthis) = 1 << (fd)
+#define FD_ZERO(tthis) *(tthis) = 0
+#define FD_ISSET(fd, tthis) (*(tthis) & (1 << fd))
+typedef int fd_set;
+#endif
+
+static fd_set Read_FD_Set;
+
+/* HACK: If > 0, use 1/10 seconds. If < 0, use 1/1000 seconds */
+
+int _SLsys_input_pending(int tsecs)
+{
+ struct timeval wait;
+ long usecs, secs;
+
+ if (TTY_Inited == 0) return -1;
+
+ if (tsecs >= 0)
+ {
+ secs = tsecs / 10;
+ usecs = (tsecs % 10) * 100000;
+ }
+ else
+ {
+ tsecs = -tsecs;
+ secs = tsecs / 1000;
+ usecs = (tsecs % 1000) * 1000;
+ }
+
+ wait.tv_sec = secs;
+ wait.tv_usec = usecs;
+
+ FD_ZERO(&Read_FD_Set);
+ FD_SET(SLang_TT_Read_FD, &Read_FD_Set);
+
+ return select(SLang_TT_Read_FD + 1, &Read_FD_Set, NULL, NULL, &wait);
+}
+
+int (*SLang_getkey_intr_hook) (void);
+
+static int handle_interrupt (void)
+{
+ if (SLang_getkey_intr_hook != NULL)
+ {
+ int save_tty_fd = SLang_TT_Read_FD;
+
+ if (-1 == (*SLang_getkey_intr_hook) ())
+ return -1;
+
+ if (save_tty_fd != SLang_TT_Read_FD)
+ return -1;
+ }
+
+ return 0;
+}
+
+unsigned int _SLsys_getkey (void)
+{
+ unsigned char c;
+
+ if (TTY_Inited == 0)
+ {
+ int ic = fgetc (stdin);
+ if (ic == EOF) return SLANG_GETKEY_ERROR;
+ return (unsigned int) ic;
+ }
+
+ while (1)
+ {
+ int ret;
+
+ if (SLKeyBoard_Quit)
+ return SLang_Abort_Char;
+
+ if (0 == (ret = _SLsys_input_pending (100)))
+ continue;
+
+ if (ret != -1)
+ break;
+
+ if (SLKeyBoard_Quit)
+ return SLang_Abort_Char;
+
+ if (errno == EINTR)
+ {
+ if (-1 == handle_interrupt ())
+ return SLANG_GETKEY_ERROR;
+
+ continue;
+ }
+
+ break; /* let read handle it */
+ }
+
+ while (-1 == read(SLang_TT_Read_FD, (char *) &c, 1))
+ {
+ if (errno == EINTR)
+ {
+ if (-1 == handle_interrupt ())
+ return SLANG_GETKEY_ERROR;
+
+ if (SLKeyBoard_Quit)
+ return SLang_Abort_Char;
+
+ continue;
+ }
+#ifdef EAGAIN
+ if (errno == EAGAIN)
+ {
+ sleep (1);
+ continue;
+ }
+#endif
+#ifdef EWOULDBLOCK
+ if (errno == EWOULDBLOCK)
+ {
+ sleep (1);
+ continue;
+ }
+#endif
+#ifdef EIO
+ if (errno == EIO)
+ {
+ SLang_exit_error ("_SLsys_getkey: EIO error.");
+ }
+#endif
+ return SLANG_GETKEY_ERROR;
+ }
+
+ return((unsigned int) c);
+}
+