📄 screen.c
字号:
/* Terminal screen drawing routines. *//* $Id: screen.c,v 1.152.6.5 2005/04/05 21:08:43 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdlib.h>#include <string.h>#include "elinks.h"#include "config/options.h"#include "intl/charsets.h"#include "osdep/ascii.h"#include "osdep/osdep.h"#include "terminal/color.h"#include "terminal/draw.h"#include "terminal/hardio.h"#include "terminal/kbd.h"#include "terminal/screen.h"#include "terminal/terminal.h"#include "util/conv.h"#include "util/error.h"#include "util/memory.h"#include "util/string.h"/* TODO: We must use termcap/terminfo if available! --pasky */unsigned char frame_dumb[48] = " ||||++||++++++--|-+||++--|-+----++++++++ ";static unsigned char frame_vt100[48] = "aaaxuuukkuxkjjjkmvwtqnttmlvwtqnvvwwmmllnnjla ";/* For UTF8 I/O */static unsigned char frame_vt100_u[48] = { 177, 177, 177, 179, 180, 180, 180, 191, 191, 180, 179, 191, 217, 217, 217, 191, 192, 193, 194, 195, 196, 197, 195, 195, 192, 218, 193, 194, 195, 196, 197, 193, 193, 194, 194, 192, 192, 218, 218, 197, 197, 217, 218, 177, 32, 32, 32, 32};static unsigned char frame_freebsd[48] = { 130, 138, 128, 153, 150, 150, 150, 140, 140, 150, 153, 140, 139, 139, 139, 140, 142, 151, 152, 149, 146, 143, 149, 149, 142, 141, 151, 152, 149, 146, 143, 151, 151, 152, 152, 142, 142, 141, 141, 143, 143, 139, 141, 128, 128, 128, 128, 128,};static unsigned char frame_koi[48] = { 144, 145, 146, 129, 135, 178, 180, 167, 166, 181, 161, 168, 174, 173, 172, 131, 132, 137, 136, 134, 128, 138, 175, 176, 171, 165, 187, 184, 177, 160, 190, 185, 186, 182, 183, 170, 169, 162, 164, 189, 188, 133, 130, 141, 140, 142, 143, 139,};/* Most of this table is just 176 + <index in table>. */static unsigned char frame_restrict[48] = { 176, 177, 178, 179, 180, 179, 186, 186, 205, 185, 186, 187, 188, 186, 205, 191, 192, 193, 194, 195, 196, 197, 179, 186, 200, 201, 202, 203, 204, 205, 206, 205, 196, 205, 196, 186, 205, 205, 186, 186, 179, 217, 218, 219, 220, 221, 222, 223,};#define TERM_STRING(str) INIT_STRING(str, sizeof(str) - 1)#define add_term_string(str, tstr) \ add_bytes_to_string(str, (tstr).source, (tstr).length)static struct string m11_hack_frame_seqs[] = { /* end border: */ TERM_STRING("\033[10m"), /* begin border: */ TERM_STRING("\033[11m"),};static struct string vt100_frame_seqs[] = { /* end border: */ TERM_STRING("\x0f"), /* begin border: */ TERM_STRING("\x0e"),};static struct string underline_seqs[] = { /* begin underline: */ TERM_STRING("\033[24m"), /* end underline: */ TERM_STRING("\033[4m"),};/* Used in {add_char*()} and {redraw_screen()} to reduce the logic. It is * updated from terminal._template_.* using option change_hooks. *//* TODO: termcap/terminfo can maybe gradually be introduced via this * structure. We'll see. --jonas */struct screen_driver { LIST_HEAD(struct screen_driver); /* The terminal._template_.type. Together with the @name member the * uniquely identify the screen_driver. */ enum term_mode_type type; /* Charsets when doing UTF8 I/O. */ /* [0] is the common charset and [1] is the frame charset. * Test wether to use UTF8 I/O using the use_utf8_io() macro. */ int charsets[2]; /* The frame translation table. May be NULL. */ unsigned char *frame; /* The frame mode setup and teardown sequences. May be NULL. */ struct string *frame_seqs; /* The underline mode setup and teardown sequences. May be NULL. */ struct string *underline; /* The color mode */ enum color_mode color_mode; /* These are directly derived from the terminal options. */ unsigned int transparent:1; /* The terminal._template_ name. */ unsigned char name[1]; /* XXX: Keep last! */};static struct screen_driver dumb_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_DUMB, /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ frame_dumb, /* frame_seqs: */ NULL, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1,};static struct screen_driver vt100_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_VT100, /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ frame_vt100, /* frame_seqs: */ vt100_frame_seqs, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1,};static struct screen_driver linux_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_LINUX, /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ NULL, /* No restrict_852 */ /* frame_seqs: */ NULL, /* No m11_hack */ /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1,};static struct screen_driver koi8_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_KOI8, /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ frame_koi, /* frame_seqs: */ NULL, /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1,};static struct screen_driver freebsd_screen_driver = { NULL_LIST_HEAD, /* type: */ TERM_FREEBSD, /* charsets: */ { -1, -1 }, /* No UTF8 I/O */ /* frame: */ frame_freebsd, /* frame_seqs: */ NULL, /* No m11_hack */ /* underline: */ underline_seqs, /* color_mode: */ COLOR_MODE_16, /* transparent: */ 1,};/* XXX: Keep in sync with enum term_mode_type. */static struct screen_driver *screen_drivers[] = { /* TERM_DUMB: */ &dumb_screen_driver, /* TERM_VT100: */ &vt100_screen_driver, /* TERM_LINUX: */ &linux_screen_driver, /* TERM_KOI8: */ &koi8_screen_driver, /* TERM_FREEBSD: */ &freebsd_screen_driver,};static INIT_LIST_HEAD(active_screen_drivers);static voidupdate_screen_driver(struct screen_driver *driver, struct option *term_spec){ int utf8_io = get_opt_bool_tree(term_spec, "utf_8_io"); driver->color_mode = get_opt_int_tree(term_spec, "colors"); driver->transparent = get_opt_bool_tree(term_spec, "transparency"); if (get_opt_bool_tree(term_spec, "underline")) { driver->underline = underline_seqs; } else { driver->underline = NULL; } if (utf8_io) { driver->charsets[0] = get_opt_int_tree(term_spec, "charset"); if (driver->type == TERM_LINUX) { if (get_opt_bool_tree(term_spec, "restrict_852")) driver->frame = frame_restrict; driver->charsets[1] = get_cp_index("cp437"); } else if (driver->type == TERM_FREEBSD) { driver->charsets[1] = get_cp_index("cp437"); } else if (driver->type == TERM_VT100) { driver->frame = frame_vt100_u; driver->charsets[1] = get_cp_index("cp437"); } else if (driver->type == TERM_KOI8) { driver->charsets[1] = get_cp_index("koi8-r"); } else { driver->charsets[1] = driver->charsets[0]; } } else { driver->charsets[0] = -1; if (driver->type == TERM_LINUX) { if (get_opt_bool_tree(term_spec, "restrict_852")) driver->frame = frame_restrict; if (get_opt_bool_tree(term_spec, "m11_hack")) driver->frame_seqs = m11_hack_frame_seqs; } else if (driver->type == TERM_FREEBSD) { if (get_opt_bool_tree(term_spec, "m11_hack")) driver->frame_seqs = m11_hack_frame_seqs; } else if (driver->type == TERM_VT100) { driver->frame = frame_vt100; } }}static intscreen_driver_change_hook(struct session *ses, struct option *term_spec, struct option *changed){ enum term_mode_type type = get_opt_int_tree(term_spec, "type"); struct screen_driver *driver; unsigned char *name = term_spec->name; int len = strlen(name); foreach (driver, active_screen_drivers) if (driver->type == type && !memcmp(driver->name, name, len)) { update_screen_driver(driver, term_spec); break; } return 0;}static inline struct screen_driver *add_screen_driver(enum term_mode_type type, struct terminal *term, int env_len){ struct screen_driver *driver; /* One byte is reserved for name in struct screen_driver. */ driver = mem_alloc(sizeof(*driver) + env_len); if (!driver) return NULL; memcpy(driver, screen_drivers[type], sizeof(*driver) - 1); memcpy(driver->name, term->spec->name, env_len + 1); add_to_list(active_screen_drivers, driver); update_screen_driver(driver, term->spec); term->spec->change_hook = screen_driver_change_hook; return driver;}static inline struct screen_driver *get_screen_driver(struct terminal *term){ enum term_mode_type type = get_opt_int_tree(term->spec, "type"); unsigned char *name = term->spec->name; int len = strlen(name); struct screen_driver *driver; foreach (driver, active_screen_drivers) { if (driver->type != type) continue; if (memcmp(driver->name, name, len + 1)) continue; /* Some simple probably useless MRU ;) */ if (driver != active_screen_drivers.next) { del_from_list(driver); add_to_list(active_screen_drivers, driver); } return driver; } return add_screen_driver(type, term, len);}voiddone_screen_drivers(void){ free_list(active_screen_drivers);}/* Adds the term code for positioning the cursor at @x and @y to @string. * The template term code is: "\033[<@y>;<@x>H" */static inline struct string *add_cursor_move_to_string(struct string *screen, int y, int x){ /* 28 chars for both of the @y and @x numbers should be enough. */ unsigned char code[32]; int length = 2; int ret; code[0] = '\033'; code[1] = '['; ret = longcat(code, &length, y, 30, 0); /* Make sure theres atleast room for ';' and `some' number ;) */ if (ret < 0 || length > 30) return NULL; code[length++] = ';'; ret = longcat(code, &length, x, sizeof(code) - length, 0); if (ret < 0 || length > 31) return NULL; code[length++] = 'H'; return add_bytes_to_string(screen, code, length);}struct screen_state { unsigned char border; unsigned char underline; unsigned char bold; unsigned char attr; unsigned char color[2];};#ifdef CONFIG_256_COLORS#define compare_color(a, b) (!memcmp((a), (b), 2))#define copy_color(a, b) memcpy((a), (b), 2)#else#define compare_color(a, b) ((a)[0] == (b)[0])#define copy_color(a, b) ((a)[0] = (b)[0])#endif#define compare_bg_color(a, b) (TERM_COLOR_BACKGROUND(a) == TERM_COLOR_BACKGROUND(b))#define compare_fg_color(a, b) (TERM_COLOR_FOREGROUND(a) == TERM_COLOR_FOREGROUND(b))#define use_utf8_io(driver) ((driver)->charsets[0] != -1)static inline voidadd_char_data(struct string *screen, struct screen_driver *driver, unsigned char data, unsigned char border){ if (!isscreensafe(data)) { add_char_to_string(screen, ' '); return; } if (border && driver->frame && data >= 176 && data < 224) data = driver->frame[data - 176]; if (use_utf8_io(driver)) { int charset = driver->charsets[!!border]; add_to_string(screen, cp2utf_8(charset, data)); return; } add_char_to_string(screen, data);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -