📄 sldisply.c
字号:
/* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis * This file is part of the S-Lang library. * * You may distribute under the terms of either the GNU General Public * License or the Perl Artistic License. */#include "slinclud.h"#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>#if defined(__DECC) && defined(VMS)/* These get prototypes for write an sleep */# include <unixio.h>#endif#include <signal.h>#include "slang.h"#include "_slang.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;void (*_SLtt_color_changed_hook)(void);#if SLTT_HAS_NON_BCE_SUPPORTstatic int Bce_Color_Offset = 0;#endifstatic int Can_Background_Color_Erase = 1;/* -1 means unknown */int SLtt_Has_Status_Line = -1; /* hs */int SLang_TT_Write_FD = -1;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;#endifstatic char *Reset_Color_String;static int Is_Color_Terminal = 0;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 0typedef 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}};/* 0 if least significant bit is blue, not red */static int Is_Fg_BGR = 0;static int Is_Bg_BGR = 0;#define COLOR_ARG(color, is_bgr) ((is_bgr) ? RGB_to_BGR[(color)&0x7] : (color))static SLCONST int RGB_to_BGR[] ={ 0, 4, 2, 6, 1, 5, 3, 7};static char *Color_Fg_Str = "\033[3%dm";static char *Color_Bg_Str = "\033[4%dm";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 go 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_Bol_Str; /* = "\033[1K"; */ /* cb */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 */#if 0static char *Start_Mouse_Rpt_Str; /* Start mouse reporting mode */static char *End_Mouse_Rpt_Str; /* End mouse reporting mode */#endifstatic 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 4096static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];static unsigned char *Output_Bufferp = Output_Buffer;unsigned long SLtt_Num_Chars_Output;int _SLusleep (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 (SLang_TT_Write_FD, (char *) Output_Buffer + total, n); if (nwrite == -1) { nwrite = 0;#ifdef EAGAIN if (errno == EAGAIN) { _SLusleep (100000); /* 1/10 sec */ continue; }#endif#ifdef EWOULDBLOCK if (errno == EWOULDBLOCK) { _SLusleep (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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -