📄 lycurses.c
字号:
#include "HTUtils.h"#include "tcp.h"#include "LYCurses.h"#include "LYStyle.h"#include "LYUtils.h"#include "LYGlobalDefs.h"#include "LYMainLoop.h"#include "LYSignal.h"#include "LYClean.h"#include "LYReadCFG.h"#include "LYStrings.h"#include "LYCharSets.h"#include "UCAux.h"#include "LYexit.h"#include "LYLeaks.h"#define FREE(x) if (x) {free(x); x = NULL;}#ifdef VMS#define DISPLAY "DECW$DISPLAY"#else#define DISPLAY "DISPLAY"#endif /* VMS */#if defined(VMS) && defined(__GNUC__)#include <gnu_hacks.h>#undef LINES#undef COLS#define LINES lines#define COLS colsextern int _NOSHARE(LINES);extern int _NOSHARE(COLS);#endif /* VMS && __GNUC__ */#ifdef USE_COLOR_STYLE#include "AttrList.h"#include "LYHash.h"#endif#if defined(COLOR_CURSES)int lynx_has_color = FALSE;#endif#define COLOR_BKGD ((COLOR_PAIRS >= 9) ? COLOR_PAIR(9) : A_NORMAL)/* * These are routines to start and stop curses and to cleanup * the screen at the end. */PRIVATE int dumbterm PARAMS((char *terminal));BOOLEAN LYCursesON = FALSE;#if USE_COLOR_TABLE || defined(USE_SLANG)PRIVATE int Current_Attr;#endif#ifdef USE_SLANGPUBLIC unsigned int Lynx_Color_Flags = 0;PUBLIC BOOLEAN FullRefresh = FALSE;PUBLIC int curscr = 0;#ifdef SLANG_MBCS_HACK/* * Will be set by size_change. - KW */PUBLIC int PHYSICAL_SLtt_Screen_Cols = 10;#endif /* SLANG_MBCS_HACK */PUBLIC void LY_SLrefresh NOARGS{ if (FullRefresh) { SLsmg_suspend_smg(); SLsmg_resume_smg(); FullRefresh = FALSE; } else { SLsmg_refresh(); } return;}/* the following renamed from LY_SLclear since it is more like erase() described in curses man pages than like clear(); but for USE_SLANG clear() is still a macro calling this, and will do the same thing as erase(). - kw */PUBLIC void LY_SLerase NOARGS{ SLsmg_gotorc (0, 0); SLsmg_erase_eos ();}#ifdef VMSPUBLIC void VTHome NOARGS{ printf("\033[;H"); return;}#endif /* VMS */PUBLIC void LYaddAttr ARGS1( int, a){ Current_Attr |= a; SLsmg_set_color(Current_Attr);}PUBLIC void LYsubAttr ARGS1( int, a){ Current_Attr &= ~a; SLsmg_set_color(Current_Attr);}PUBLIC void lynx_setup_colors NOARGS{ SLtt_set_color(0, NULL, DEFAULT_FG, DEFAULT_BG); SLtt_set_color(1, NULL, "blue", DEFAULT_BG); /* bold */ SLtt_set_color(2, NULL, "yellow", "blue"); /* reverse */ SLtt_set_color(4, NULL, "magenta", DEFAULT_BG); /* underline */ /* * The other objects are '|'ed together to get rest. */ SLtt_set_color(3, NULL, "green", DEFAULT_BG); /* bold-reverse */ SLtt_set_color(5, NULL, "blue", DEFAULT_BG); /* bold-underline */ SLtt_set_color(6, NULL, "red", DEFAULT_BG); /* reverse-underline */ SLtt_set_color(7, NULL, "magenta", "cyan"); /* reverse-underline-bold */ /* * Now set monochrome attributes. */ SLtt_set_mono(1, NULL, SLTT_BOLD_MASK); SLtt_set_mono(2, NULL, SLTT_REV_MASK); SLtt_set_mono(3, NULL, SLTT_REV_MASK | SLTT_BOLD_MASK); SLtt_set_mono(4, NULL, SLTT_ULINE_MASK); SLtt_set_mono(5, NULL, SLTT_ULINE_MASK | SLTT_BOLD_MASK); SLtt_set_mono(6, NULL, SLTT_ULINE_MASK | SLTT_REV_MASK); SLtt_set_mono(7, NULL, SLTT_ULINE_MASK | SLTT_BOLD_MASK | SLTT_REV_MASK);}PRIVATE void sl_suspend ARGS1( int, sig){#ifdef SIGSTOP#ifndef VMS int r, c; lynx_enable_mouse (0); if (sig == SIGTSTP) SLsmg_suspend_smg(); SLang_reset_tty(); kill(getpid(),SIGSTOP);#if SLANG_VERSION > 9929 SLang_init_tty(-1, 0, 1);#else SLang_init_tty(3, 0, 1);#endif /* SLANG_VERSION > 9929 */ signal(SIGTSTP, sl_suspend);#ifndef _WINDOWS SLtty_set_suspend_state(1);#endif if (sig == SIGTSTP) SLsmg_resume_smg(); /* * Get new window size in case it changed. */ r = SLtt_Screen_Rows; c = SLtt_Screen_Cols; size_change(0); if ((r != SLtt_Screen_Rows) || (c != SLtt_Screen_Cols)) { recent_sizechange = TRUE; } lynx_enable_mouse (1);#endif /* !VMS */#endif /* SIGSTOP */ return;}#else /* Not slang: */#ifdef VMS/*** This function boxes windows with graphic characters for** VMS curses. Pass it the window, it's height, and it's** width. - FM*/PUBLIC void VMSbox ARGS3( WINDOW *, win, int, height, int, width){ int i; wmove(win, 0, 0); waddstr(win, "\033)0\016l"); for (i = 1; i < width; i++) waddch(win, 'q'); waddch(win, 'k'); for (i = 1; i < height-1; i++) { wmove(win, i, 0); waddch(win, 'x'); wmove(win, i, width-1); waddch(win, 'x'); } wmove(win, i, 0); waddch(win, 'm'); for (i = 1; i < width; i++) waddch(win, 'q'); waddstr(win, "j\017");}#else/*** This function boxes windows for non-VMS (n)curses.** Pass it the window. - FM*/PUBLIC void LYbox ARGS2( WINDOW *, win, BOOLEAN, formfield){ /* * If the terminal is in UTF-8 mode, it probably cannot understand * box drawing characters as (n)curses handles them. (This may also * be true for other display character sets, but isn't currently * checked.) In that case, substitute ASCII characters for BOXVERT * and BOXHORI if they were defined to 0 for automatic use of box * drawing characters. They'll stay as they are otherwise. - KW & FM */ int boxvert, boxhori; UCSetBoxChars(current_char_set, &boxvert, &boxhori, BOXVERT, BOXHORI);#ifdef CSS if (formfield) wcurses_css(win, "frame", ABS_ON);#endif /* * If we don't have explicitly specified characters for either * vertical or horizontal lines, the characters that box() would * use for the corners probably also won't work well. So we * specify our own ASCII characters for the corners and call * wborder() instead of box(). - kw */#ifdef HAVE_WBORDER if (!boxvert || !boxhori) box(win, boxvert, boxhori); else if (boxvert == '*' || boxhori == '*') wborder(win, boxvert, boxvert, boxhori, boxhori, '*', '*', '*', '*'); else wborder(win, boxvert, boxvert, boxhori, boxhori, '/', '\\', '\\', '/');#else box(win, boxvert, boxhori);#endif#ifdef CSS if (formfield) wcurses_css(win, "frame", ABS_OFF);#endif}#endif /* VMS */#endif /* USE_SLANG */#if defined(USE_COLOR_STYLE)PRIVATE int last_styles[128];PRIVATE int last_ptr=0;#endif#if defined(USE_COLOR_STYLE)/* Ok, explanation of the USE_COLOR_STYLE styles. The basic styles (ie non * HTML) are set the same as the SLANG version for ease of programming. The * other styles are simply the HTML enum from HTMLDTD.h + 16. */PUBLIC HTCharStyle displayStyles[DSTYLE_ELEMENTS];/* * set a style's attributes - RP */PUBLIC void setStyle ARGS4(int,style,int,color,int,cattr,int,mono){ displayStyles[style].color=color; displayStyles[style].cattr=cattr; displayStyles[style].mono=mono;}PUBLIC void setHashStyle ARGS5(int,style,int,color,int,cattr,int,mono,char*,element){ bucket* ds=&hashStyles[style]; if (TRACE) fprintf(stderr, "CSS(SET): <%s> hash=%d, ca=%d, ma=%d\n", element, style, color, mono); ds->color=color; ds->cattr=cattr; ds->mono=mono; ds->code=style; FREE(ds->name); ds->name=malloc(sizeof(char)*(strlen(element)+2)); strcpy(ds->name, element);}/* * set the curses attributes to be color or mono - RP */PRIVATE int LYAttrset ARGS3(WINDOW*,win,int,color,int,mono){ if (TRACE) fprintf(stderr, "CSS:LYAttrset (%d, %d)\n", color, mono); if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON && color > -1) { wattrset(win,color); return color; } if (mono > -1) { wattrset(win,mono); return mono; } wattrset(win,A_NORMAL); return A_NORMAL;}PUBLIC void curses_w_style ARGS4(WINDOW*,win,int,style,int,dir,int,previous){ int YP,XP; bucket* ds=&hashStyles[style]; if (!ds->name) { if (TRACE) fprintf(stderr, "CSS.CS:Style %d not configured\n",style); return; } if (TRACE) fprintf(stderr, "CSS.CS:<%s%s> (%d)\n",(dir?"":"/"),ds->name,ds->code); getyx (win, YP, XP); if (style == s_normal && dir) { wattrset(win,A_NORMAL); if (win==stdscr) cached_styles[YP][XP]=s_normal; return; } switch (dir) { /* ABS_OFF is the same as STACK_OFF for the moment */ case STACK_OFF: if (last_ptr) LYAttrset(win,last_styles[--last_ptr],-1); else LYAttrset(win,A_NORMAL,-1); return; case STACK_ON: /* remember the current attributes */ if (last_ptr > 127) { if (TRACE) fprintf(stderr,"........... %s (0x%x) %s\r\n", "attribute cache FULL, dropping last", last_styles[last_ptr], "in LynxChangStyle(curses_w_style)"); last_ptr--; } last_styles[last_ptr++] = getattrs(stdscr); /* don't cache style changes for active links */ if (style != s_alink) { if (TRACE) fprintf(stderr, "CACHED: <%s> @(%d,%d)\n", ds->name, YP, XP); if (win==stdscr) cached_styles[YP][XP]=style; LYAttrset(win, ds->color, ds->mono); } else { LYAttrset(win, ds->color, ds->mono); } return; case ABS_ON: /* change without remembering the previous style */ /* don't cache style changes for active links */ if (style != s_alink) { if (TRACE) fprintf(stderr, "CACHED: <%s> @(%d,%d)\n", ds->name, YP, XP); if (win==stdscr) cached_styles[YP][XP]=style; LYAttrset(win, ds->color, ds->mono); } else { LYAttrset(win, ds->color, ds->mono); } return; }}/* * wrapper function to set on-screen styles - RP */PUBLIC void wcurses_css ARGS3(WINDOW *,win,char*,name,int,dir){ int try_again=1; while (try_again) { int tmpHash=hash_code(name); if (TRACE) fprintf(stderr, "CSSTRIM:trying to set [%s] style - ", name); if (tmpHash==NOSTYLE) { char *class=strrchr(name, '.'); if (TRACE) fprintf(stderr, "undefined, trimming at %p\n", class); if (class) *class='\0'; else try_again=0; } else { if (TRACE) fprintf(stderr, "ok (%d)\n", hash_code(name)); curses_w_style(win, hash_code(name), dir, 0); try_again=0; } }}PUBLIC void curses_css ARGS2(char *,name,int,dir){ wcurses_css(stdscr, name, dir);}PUBLIC void curses_style ARGS3(int,style,int,dir,int,previous){ curses_w_style(stdscr, style, dir, previous);}#ifdef NOT_USEDvoid attribute ARGS2(int,style,int,dir){ curses_style(style, dir, 0);}#endif#endif /* USE_COLOR_STYLE */#if USE_COLOR_TABLE && defined(COLOR_CURSES)/* * This block of code is designed to produce the same color effects using SVr4 * curses as the slang library's implementation in this module. That maps the * SGR codes into a 0-7 index into the color table, with special treatment for * backgrounds. There's a bit of convoluted (but necessary) code handling the * special case of initialization before 'initscr()' is called. * 1997/1/19 - T.E.Dickey <dickey@clark.net> */PRIVATE int lynx_called_initscr;PRIVATE struct { int fg, bg; chtype attr;} lynx_color_cfg[] = { /*0*/ { DEFAULT_FG, DEFAULT_BG, A_NORMAL}, /* A_NORMAL */ /*1*/ { COLOR_BLUE, DEFAULT_BG, A_NORMAL}, /* A_BOLD */ /*2*/ { COLOR_YELLOW, COLOR_BLUE, A_BOLD}, /* A_REVERSE */ /*3*/ { COLOR_GREEN, DEFAULT_BG, A_NORMAL}, /* A_REVERSE | A_BOLD */ /*4*/ { COLOR_MAGENTA, DEFAULT_BG, A_NORMAL}, /* A_UNDERLINE */ /*5*/ { COLOR_BLUE, DEFAULT_BG, A_NORMAL}, /* A_UNDERLINE | A_BOLD */ /*6*/ { COLOR_RED, DEFAULT_BG, A_NORMAL}, /* A_UNDERLINE | A_REVERSE */ /*7*/ { COLOR_MAGENTA, COLOR_CYAN, A_NORMAL} /* A_UNDERLINE | A_BOLD | A_REVERSE */};/* * Hold the codes for color-pairs here until 'initscr()' is called. */PRIVATE struct { int fg; int bg;} lynx_color_pairs[25];/* * Map the SGR attributes (0-7) into ANSI colors, modified with the actual BOLD * attribute we'll get 16 colors. */PRIVATE void LYsetWAttr ARGS1(WINDOW *, win){ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) { int code = 0; int attr = A_NORMAL; int offs = 1; static int have_underline = -1; static int no_color_video = -1; if (have_underline < 0) {#ifndef DOSPATH have_underline = tigetstr("smul") != 0;#else have_underline = 1;#endif /* DOSPATH */ }#if ( !defined(__DJGPP__) && !defined(_WINDOWS) ) if (no_color_video < 0) { no_color_video = tigetnum("ncv"); } if (no_color_video < 0) no_color_video = 0;#endif /* !__DJGPP__ and !_WINDOWS */ if (Current_Attr & A_BOLD) code |= 1; if (Current_Attr & A_REVERSE) code |= 2; if (Current_Attr & A_UNDERLINE) code |= 4; attr = lynx_color_cfg[code].attr; /* * FIXME: no_color_video isn't implemented (97/4/14) in ncurses 4.x, * but may be in SVr4 (which would make this redundant for the latter). */ if ((Current_Attr & A_BOLD) && !(no_color_video & 33)) { attr |= A_BOLD; } if ((Current_Attr == A_UNDERLINE) && !(no_color_video & 2)) { attr |= A_UNDERLINE; } if (code+offs < COLOR_PAIRS) { attr |= COLOR_PAIR(code+offs); } wattrset(win, attr); } else { wattrset(win, Current_Attr); }}PRIVATE void lynx_map_color ARGS1(int, n){ int m; lynx_color_pairs[n+1].fg = lynx_color_cfg[n].fg; lynx_color_pairs[n+1].bg = lynx_color_cfg[n].bg; lynx_color_pairs[n+9].fg = lynx_color_cfg[n].fg; lynx_color_pairs[n+9].bg = lynx_color_cfg[0].bg; lynx_color_pairs[n+17].fg = lynx_color_cfg[n].bg; lynx_color_pairs[n+17].bg = lynx_color_cfg[n].bg; if (lynx_called_initscr) { for (m = 0; m <= 16; m += 8) { int pair = n + m + 1; if (pair < COLOR_PAIRS) init_pair(pair, lynx_color_pairs[pair].fg, lynx_color_pairs[pair].bg); } if (n == 0 && LYShowColor >= SHOW_COLOR_ON) bkgd(COLOR_BKGD | ' '); }}PUBLIC int lynx_chg_color ARGS3( int, color, int, fg, int, bg ){ if (color >= 0 && color < 8) { lynx_color_cfg[color].fg = (fg > 7) ? (fg & 7) : fg; lynx_color_cfg[color].bg = (bg > 7) ? (bg & 7) : bg; lynx_color_cfg[color].attr = ((fg > 7) && (fg & 8)) ? A_BOLD : A_NORMAL; lynx_map_color(color); } else { return -1; } return 0;}PUBLIC void lynx_set_color ARGS1(int, a){ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) { attrset(lynx_color_cfg[a].attr | (((a+1) < COLOR_PAIRS) ? COLOR_PAIR(a+1) : A_NORMAL)); }}PUBLIC void lynx_standout ARGS1(int, flag){ if (flag) LYaddAttr(A_REVERSE); else LYsubAttr(A_REVERSE);}PRIVATE void lynx_init_colors NOARGS{ if (lynx_has_color) { size_t n, m; lynx_color_cfg[0].fg = default_fg; lynx_color_cfg[0].bg = default_bg; for (n = 0; n < sizeof(lynx_color_cfg)/sizeof(lynx_color_cfg[0]); n++) { for (m = 0; m <= 16; m += 8) { int pair = n + m + 1; if (pair < COLOR_PAIRS) init_pair(pair, lynx_color_pairs[pair].fg, lynx_color_pairs[pair].bg); } if (n == 0 && LYShowColor >= SHOW_COLOR_ON) bkgd(COLOR_BKGD | ' '); } } else if (LYShowColor != SHOW_COLOR_NEVER) { LYShowColor = SHOW_COLOR_OFF; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -