diff options
-rw-r--r-- | minislang/Makefile | 15 | ||||
-rw-r--r-- | minislang/_slang.h | 598 | ||||
-rw-r--r-- | minislang/config.h | 113 | ||||
-rw-r--r-- | minislang/jdmacros.h | 76 | ||||
-rw-r--r-- | minislang/sl-feat.h | 18 | ||||
-rw-r--r-- | minislang/slang.h | 1547 | ||||
-rw-r--r-- | minislang/sldisply.c | 2313 | ||||
-rw-r--r-- | minislang/slerr.c | 182 | ||||
-rw-r--r-- | minislang/slgetkey.c | 270 | ||||
-rw-r--r-- | minislang/sllimits.h | 65 | ||||
-rw-r--r-- | minislang/slmisc.c | 256 | ||||
-rw-r--r-- | minislang/slsignal.c | 346 | ||||
-rw-r--r-- | minislang/slsmg.c | 1395 | ||||
-rw-r--r-- | minislang/sltermin.c | 1128 | ||||
-rw-r--r-- | minislang/slutty.c | 595 |
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); +} + |