add some runtime options, add some OSC (including glyph width report)
This commit is contained in:
parent
8fd4f4995d
commit
42a3fbdbe6
17 changed files with 8012 additions and 678 deletions
54
ChangeLog
54
ChangeLog
|
@ -91,3 +91,57 @@
|
|||
* LAZY_DRAW(データ量が多いときに描画を抑制する)を追加
|
||||
* BACKGROUND_DRAW(VT切り替え後も描画を続ける)を追加
|
||||
* struct terminalのoffsetを削除
|
||||
|
||||
2014-03-24
|
||||
* version 0.2.1
|
||||
* BACKGROUND_DRAW, ROTATEの設定をconf.hでなく環境変数YAFTでするようにした
|
||||
(実行時に変更する必要がないと思われるものは相変わらずconf.hで指定)
|
||||
* 環境変数YAFTで有効なオプション
|
||||
wall: 背景画像を有効にする
|
||||
background or bg: activeになっていないVTでも描画を続ける(2画面用)
|
||||
clockwise or cw: 90度描画を回転
|
||||
counter_clockwise or ccw: 270度描画を回転
|
||||
upside_down or ud: 180度描画を回転
|
||||
ex) YAFT="wall cw bg" yaft
|
||||
* 環境変数FRAMEBUFFER
|
||||
framebuffer deviceを指定する
|
||||
ex) FRAMEBUFFER="/dev/fb0" yaft
|
||||
* 幾つかのOSCを実装した
|
||||
OSC 4: color paletteの変更
|
||||
色の設定(rgbの指定は1-4桁)
|
||||
OSC 4 ; c ; rgb:rr/gg/bb ST
|
||||
OSC 4 ; c ; #rrggbb ST
|
||||
c番目の色設定の応答
|
||||
request
|
||||
OSC 4 ; c ; ? ST
|
||||
response
|
||||
OSC 4 ; c ; rgb:rr/gg/bb ST
|
||||
OSC 104: color paletteの初期化
|
||||
c番目の色を初期化
|
||||
OSC 104 ; c ST
|
||||
全ての色を初期化
|
||||
OSC 104 ST
|
||||
OSC 8900: glyph width report
|
||||
requestの際にwidth, from, toの指定を強制するようにした
|
||||
* request *
|
||||
OSC 8900 ; Ps ; ? : Pw : Pf : Pt ST
|
||||
Ps: reserved
|
||||
Pw: width (0 or 1 or 2)
|
||||
Pf: beginning of unicode code point
|
||||
Pt: end of unicode code point
|
||||
ST: BEL(0x07) or ESC(0x1B) BACKSLASH(0x5C)
|
||||
* answer *
|
||||
OSC 8900 ; Ps ; Pt ; Pf : Pt ; Pf : Pt ; ... ST
|
||||
Ps: responce code
|
||||
0: ok (default)
|
||||
1: recognized but not supported
|
||||
2: not recognized
|
||||
Pt: reserved (maybe East Asian Width Version)
|
||||
<!-- Pw: width (0 or 1 or 2) depricated -->
|
||||
Pf: beginning of unicode code point
|
||||
Pt: end of unicode code point
|
||||
ST: BEL(0x07) or ESC(0x1B) BACKSLASH(0x5C)
|
||||
(ref)
|
||||
http://uobikiemukot.github.io/yaft/glyph_width_report.html
|
||||
https://gist.github.com/saitoha/8767268
|
||||
* コードを色々整理した
|
||||
|
|
15
color.h
15
color.h
|
@ -4,22 +4,9 @@
|
|||
http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
*/
|
||||
const uint32_t color_list[COLORS] = {
|
||||
/* system color: 16
|
||||
*/
|
||||
/* system color: 16 */
|
||||
0x000000, 0xAA0000, 0x00AA00, 0xAA5500, 0x0000AA, 0xAA00AA, 0x00AAAA, 0xAAAAAA/* 0xAAAAAA */,
|
||||
0x555555, 0xFF5555, 0x55FF55, 0xFFFF55, 0x5555FF, 0xFF55FF, 0x55FFFF, 0xDFDFDF/* 0xFFFFFF */,
|
||||
/* dark system color
|
||||
0x000000, 0x660000, 0x006600, 0x661100, 0x000066, 0x660066, 0x006666, 0x666666,
|
||||
0x444444, 0x774444, 0x447744, 0x777744, 0x444477, 0x774477, 0x447777, 0x777777,
|
||||
*/
|
||||
/* solarized
|
||||
0x073642, 0xDC322F, 0x859900, 0xB58900, 0x268BD2, 0xD33682, 0x2AA198, 0xEEE8D5,
|
||||
0x002B36, 0xCB4B16, 0x586E75, 0x657B83, 0x839496, 0x6C71C4, 0x93A1A1, 0xFDF6E3,
|
||||
*/
|
||||
/* solarized fix
|
||||
0x000000, 0xDC322F, 0x859900, 0xB58900, 0x268BD2, 0xD33682, 0x2AA198, 0x93A1A1,
|
||||
0x555555, 0xEC423F, 0x95A910, 0xA59910, 0x6C71C4, 0xE34692, 0x3AB1A8, 0xCEC8B5,
|
||||
*/
|
||||
/* color cube: 216 */
|
||||
0x000000, 0x00005F, 0x000087, 0x0000AF, 0x0000D7, 0x0000FF, 0x005F00, 0x005F5F,
|
||||
0x005F87, 0x005FAF, 0x005FD7, 0x005FFF, 0x008700, 0x00875F, 0x008787, 0x0087AF,
|
||||
|
|
58
common.h
58
common.h
|
@ -4,9 +4,6 @@
|
|||
#include <errno.h>
|
||||
/* #include <execinfo.h> for DEBUG */
|
||||
#include <fcntl.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/kd.h>
|
||||
#include <locale.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -38,7 +35,7 @@ enum char_code {
|
|||
REPLACEMENT_CHARACTER = 0xFFFD,
|
||||
};
|
||||
|
||||
enum {
|
||||
enum misc {
|
||||
BITS_PER_BYTE = 8,
|
||||
BUFSIZE = 1024, /* read, esc, various buffer size */
|
||||
SELECT_TIMEOUT = 20000, /* used by select() */
|
||||
|
@ -50,6 +47,7 @@ enum {
|
|||
DEFAULT_CHAR = SPACE, /* used for erase char, cell_size */
|
||||
RESET = 0x00, /* reset for char_attr, term_mode, esc_state */
|
||||
BRIGHT_INC = 8, /* value used for brightening color */
|
||||
OSC_GWREPT = 8900, /* OSC Ps: mode number of yaft GWREPT */
|
||||
};
|
||||
|
||||
enum char_attr {
|
||||
|
@ -83,9 +81,12 @@ enum term_mode {
|
|||
};
|
||||
|
||||
enum esc_state {
|
||||
STATE_ESC = 1, /* 0x1B, \033, ESC */
|
||||
STATE_RESET = 0,
|
||||
STATE_ESC, /* 0x1B, \033, ESC */
|
||||
STATE_CSI, /* ESC [ */
|
||||
STATE_OSC, /* ESC ] */
|
||||
STATE_DCS, /* ESC P */
|
||||
STATE_DSCS,
|
||||
};
|
||||
|
||||
enum width_flag {
|
||||
|
@ -94,6 +95,13 @@ enum width_flag {
|
|||
WIDE,
|
||||
};
|
||||
|
||||
enum rotate_mode {
|
||||
NORMAL = 0,
|
||||
CLOCKWISE = 90,
|
||||
UPSIDE_DOWN = 180,
|
||||
COUNTER_CLOCKWISE = 270,
|
||||
};
|
||||
|
||||
#include "glyph.h"
|
||||
|
||||
struct tty_state {
|
||||
|
@ -101,6 +109,8 @@ struct tty_state {
|
|||
bool visible;
|
||||
bool redraw_flag;
|
||||
bool loop_flag;
|
||||
bool background_draw;
|
||||
bool lazy_draw;
|
||||
};
|
||||
|
||||
struct pair { int x, y; };
|
||||
|
@ -112,7 +122,7 @@ struct cell {
|
|||
const struct static_glyph_t *gp; /* pointer to glyph */
|
||||
struct color_pair color; /* color (fg, bg) */
|
||||
uint8_t attribute; /* bold, underscore, etc... */
|
||||
int wide; /* wide char flag: WIDE, NEXT_TO_WIDE, HALF */
|
||||
enum width_flag width; /* wide char flag: WIDE, NEXT_TO_WIDE, HALF */
|
||||
};
|
||||
|
||||
struct parm_t { /* for parse_arg() */
|
||||
|
@ -123,7 +133,7 @@ struct parm_t { /* for parse_arg() */
|
|||
struct esc_t {
|
||||
char buf[BUFSIZE];
|
||||
char *bp;
|
||||
int state; /* esc state */
|
||||
enum esc_state state; /* esc state */
|
||||
};
|
||||
|
||||
struct ucs_t {
|
||||
|
@ -133,14 +143,18 @@ struct ucs_t {
|
|||
};
|
||||
|
||||
struct state_t { /* for save, restore state */
|
||||
int mode;
|
||||
enum term_mode mode;
|
||||
struct pair cursor;
|
||||
uint8_t attribute;
|
||||
};
|
||||
|
||||
//struct drcs_t { /* for drcs */
|
||||
//int erase_mode;
|
||||
//uint8_t start_char;
|
||||
//};
|
||||
|
||||
struct terminal {
|
||||
int fd; /* master fd */
|
||||
//struct pair offset; /* window offset (x, y) */
|
||||
int width, height; /* terminal size (pixel) */
|
||||
int cols, lines; /* terminal size (cell) */
|
||||
struct cell *cells; /* pointer to each cell: cells[cols + lines * num_of_cols] */
|
||||
|
@ -148,26 +162,28 @@ struct terminal {
|
|||
struct pair cursor; /* cursor pos (x, y) */
|
||||
bool *line_dirty; /* dirty flag */
|
||||
bool *tabstop; /* tabstop flag */
|
||||
int mode; /* for set/reset mode */
|
||||
enum term_mode mode; /* for set/reset mode */
|
||||
bool wrap; /* whether auto wrap occured or not */
|
||||
struct state_t state; /* for restore */
|
||||
struct color_pair color; /* color (fg, bg) */
|
||||
uint8_t attribute; /* bold, underscore, etc... */
|
||||
struct esc_t esc; /* store escape sequence */
|
||||
struct ucs_t ucs; /* store UTF-8 sequence */
|
||||
uint32_t color_palette[COLORS]; /* 256 color palette */
|
||||
};
|
||||
|
||||
struct framebuffer {
|
||||
char *fp; /* pointer of framebuffer(read only) */
|
||||
char *wall; /* buffer for wallpaper */
|
||||
char *buf; /* copy of framebuffer */
|
||||
int fd; /* file descriptor of framebuffer */
|
||||
struct pair res; /* resolution (x, y) */
|
||||
long screen_size; /* screen data size (byte) */
|
||||
int line_length; /* line length (byte) */
|
||||
int bpp; /* BYTES per pixel */
|
||||
uint32_t color_palette[COLORS];
|
||||
struct fb_cmap *cmap, *cmap_org;
|
||||
//struct sixel {
|
||||
//uint8_t width; /* always 1 */
|
||||
//char *pixmap[CELL_HEIGHT]; /* size: 24bpp * cell width */
|
||||
//};
|
||||
|
||||
struct tty_state tty = {
|
||||
.save_tm = NULL,
|
||||
.visible = true,
|
||||
.redraw_flag = false,
|
||||
.loop_flag = true,
|
||||
.background_draw = false,
|
||||
.lazy_draw = true,
|
||||
};
|
||||
|
||||
#include "conf.h" /* user configuration */
|
||||
|
|
12
conf.h
12
conf.h
|
@ -1,9 +1,11 @@
|
|||
/* See LICENSE for licence details. */
|
||||
/* framubuffer device */
|
||||
const char *fb_path = "/dev/fb0";
|
||||
//const char *fb_path = "/dev/tty"; /* for FreeBSD */
|
||||
|
||||
/* shell */
|
||||
const char *shell_cmd = "/bin/bash";
|
||||
//const char *shell_cmd = "/bin/csh"; /* for FreeBSD */
|
||||
|
||||
/* TERM value */
|
||||
const char *term_name = "yaft-256color";
|
||||
|
@ -12,18 +14,16 @@ const char *term_name = "yaft-256color";
|
|||
enum {
|
||||
DEFAULT_FG = 7,
|
||||
DEFAULT_BG = 0,
|
||||
CURSOR_COLOR = 2,
|
||||
ACTIVE_CURSOR_COLOR = 2,
|
||||
PASSIVE_CURSOR_COLOR = 1,
|
||||
};
|
||||
|
||||
/* misc */
|
||||
enum {
|
||||
DEBUG = false,
|
||||
DEBUG = true,
|
||||
TABSTOP = 8,
|
||||
SUBSTITUTE_HALF = 0x20, /* used for missing glyph: SPACE (0x20) */
|
||||
SUBSTITUTE_WIDE = 0x3000, /* used for missing glyph: IDEOGRAPHIC SPACE(0x3000) */
|
||||
REPLACEMENT_CHAR = 0xFFFD, /* used for malformed UTF-8 sequence: REPLACEMENT CHARACTER */
|
||||
LAZY_DRAW = false,
|
||||
BACKGROUND_DRAW = false,
|
||||
NORMAL = 0, CLOCKWISE = 90, UPSIDE_DOWN = 180, COUNTER_CLOCKWISE = 270,
|
||||
ROTATE = CLOCKWISE, /* 0 or 90 or 180 or 270 (see above) */
|
||||
LAZY_DRAW = true,
|
||||
};
|
||||
|
|
124
draw.h
Normal file
124
draw.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/* See LICENSE for licence details. */
|
||||
int get_rotated_pos(struct framebuffer *fb, struct terminal *term, int x, int y)
|
||||
{
|
||||
int p, q;
|
||||
long pos;
|
||||
|
||||
if (fb->rotate == CLOCKWISE) {
|
||||
p = y;
|
||||
q = (term->width - 1) - x;
|
||||
}
|
||||
else if (fb->rotate == UPSIDE_DOWN) {
|
||||
p = (term->width - 1) - x;
|
||||
q = (term->height - 1) - y;
|
||||
}
|
||||
else if (fb->rotate == COUNTER_CLOCKWISE) {
|
||||
p = (term->height - 1) - y;
|
||||
q = x;
|
||||
}
|
||||
else { /* rotate: NORMAL */
|
||||
p = x;
|
||||
q = y;
|
||||
}
|
||||
|
||||
pos = p * fb->bpp + q * fb->line_length;
|
||||
if (pos < 0 || pos >= fb->screen_size) {
|
||||
fprintf(stderr, "(%d, %d) -> (%d, %d) term:(%d, %d) res:(%d, %d) pos:%ld\n",
|
||||
x, y, p, q, term->width, term->height, fb->res.x, fb->res.y, pos);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void draw_line(struct framebuffer *fb, struct terminal *term, int line)
|
||||
{
|
||||
int copy_size, pos, bit_shift, margin_right;
|
||||
|
||||
int col, glyph_width_offset, glyph_height_offset;
|
||||
uint32_t pixel;
|
||||
struct color_pair color;
|
||||
struct cell *cp;
|
||||
const struct static_glyph_t *gp;
|
||||
|
||||
copy_size = (fb->rotate == CLOCKWISE || fb->rotate == COUNTER_CLOCKWISE) ?
|
||||
CELL_HEIGHT * fb->bpp: CELL_HEIGHT * fb->line_length;
|
||||
|
||||
for (col = term->cols - 1; col >= 0; col--) {
|
||||
margin_right = (term->cols - 1 - col) * CELL_WIDTH;
|
||||
|
||||
/* get cell color and glyph */
|
||||
cp = &term->cells[col + line * term->cols];
|
||||
color = cp->color;
|
||||
gp = cp->gp;
|
||||
|
||||
/* check cursor positon */
|
||||
if ((term->mode & MODE_CURSOR && line == term->cursor.y)
|
||||
&& (col == term->cursor.x
|
||||
|| (cp->width == WIDE && (col + 1) == term->cursor.x)
|
||||
|| (cp->width == NEXT_TO_WIDE && (col - 1) == term->cursor.x))) {
|
||||
color.fg = DEFAULT_BG;
|
||||
color.bg = (!tty.visible && tty.background_draw) ? PASSIVE_CURSOR_COLOR: ACTIVE_CURSOR_COLOR;
|
||||
}
|
||||
|
||||
for (glyph_height_offset = 0; glyph_height_offset < CELL_HEIGHT; glyph_height_offset++) {
|
||||
if ((glyph_height_offset == (CELL_HEIGHT - 1)) && (cp->attribute & attr_mask[UNDERLINE]))
|
||||
color.bg = color.fg;
|
||||
|
||||
for (glyph_width_offset = 0; glyph_width_offset < CELL_WIDTH; glyph_width_offset++) {
|
||||
pos = get_rotated_pos(fb, term, term->width - 1 - margin_right - glyph_width_offset,
|
||||
line * CELL_HEIGHT + glyph_height_offset);
|
||||
|
||||
if (cp->width == WIDE)
|
||||
bit_shift = glyph_width_offset + CELL_WIDTH;
|
||||
else
|
||||
bit_shift = glyph_width_offset;
|
||||
|
||||
/* set color palette */
|
||||
if (gp->bitmap[glyph_height_offset] & (0x01 << bit_shift))
|
||||
pixel = term->color_palette[color.fg];
|
||||
else if (fb->wall && color.bg == DEFAULT_BG) /* wallpaper */
|
||||
memcpy(&pixel, fb->wall + pos, fb->bpp);
|
||||
else
|
||||
pixel = term->color_palette[color.bg];
|
||||
|
||||
memcpy(fb->buf + pos, &pixel, fb->bpp);
|
||||
}
|
||||
}
|
||||
|
||||
if (fb->rotate == CLOCKWISE) {
|
||||
for (glyph_width_offset = 0; glyph_width_offset < CELL_WIDTH; glyph_width_offset++) {
|
||||
pos = get_rotated_pos(fb, term, term->width - 1 - margin_right - glyph_width_offset, line * CELL_HEIGHT);
|
||||
memcpy(fb->fp + pos, fb->buf + pos, copy_size);
|
||||
}
|
||||
} else if (fb->rotate == COUNTER_CLOCKWISE) {
|
||||
for (glyph_width_offset = 0; glyph_width_offset < CELL_WIDTH; glyph_width_offset++) {
|
||||
pos = get_rotated_pos(fb, term, term->width - 1 - margin_right - glyph_width_offset, (line + 1) * CELL_HEIGHT - 1);
|
||||
memcpy(fb->fp + pos, fb->buf + pos, copy_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fb->rotate == NORMAL) {
|
||||
pos = get_rotated_pos(fb, term, 0, line * CELL_HEIGHT);
|
||||
memcpy(fb->fp + pos, fb->buf + pos, copy_size);
|
||||
} else if (fb->rotate == UPSIDE_DOWN) {
|
||||
pos = get_rotated_pos(fb, term, term->width - 1, (line + 1) * CELL_HEIGHT - 1);
|
||||
memcpy(fb->fp + pos, fb->buf + pos, copy_size);
|
||||
}
|
||||
|
||||
term->line_dirty[line] = ((term->mode & MODE_CURSOR) && term->cursor.y == line) ? true: false;
|
||||
}
|
||||
|
||||
void refresh(struct framebuffer *fb, struct terminal *term)
|
||||
{
|
||||
int line;
|
||||
|
||||
if (term->mode & MODE_CURSOR)
|
||||
term->line_dirty[term->cursor.y] = true;
|
||||
|
||||
for (line = 0; line < term->lines; line++) {
|
||||
if (term->line_dirty[line])
|
||||
draw_line(fb, term, line);
|
||||
}
|
||||
}
|
319
framebuffer.h
319
framebuffer.h
|
@ -1,319 +0,0 @@
|
|||
/* See LICENSE for licence details. */
|
||||
char *load_wallpaper(struct framebuffer *fb)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = (char *) emalloc(fb->screen_size);
|
||||
memcpy(ptr, fb->fp, fb->screen_size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
struct fb_cmap *cmap_create(struct fb_var_screeninfo *vinfo)
|
||||
{
|
||||
struct fb_cmap *cmap;
|
||||
|
||||
cmap = (struct fb_cmap *) emalloc(sizeof(struct fb_cmap));
|
||||
cmap->start = 0;
|
||||
cmap->len = COLORS;
|
||||
cmap->red = (uint16_t *) emalloc(sizeof(uint16_t) * COLORS);
|
||||
cmap->green = (uint16_t *) emalloc(sizeof(uint16_t) * COLORS);
|
||||
cmap->blue = (uint16_t *) emalloc(sizeof(uint16_t) * COLORS);
|
||||
cmap->transp = NULL;
|
||||
|
||||
return cmap;
|
||||
}
|
||||
|
||||
void cmap_die(struct fb_cmap *cmap)
|
||||
{
|
||||
if (cmap) {
|
||||
free(cmap->red);
|
||||
free(cmap->green);
|
||||
free(cmap->blue);
|
||||
free(cmap->transp);
|
||||
free(cmap);
|
||||
}
|
||||
}
|
||||
|
||||
void get_rgb(int i, struct color_t *color)
|
||||
{
|
||||
color->r = (color_list[i] >> 16) & bit_mask[8];
|
||||
color->g = (color_list[i] >> 8) & bit_mask[8];
|
||||
color->b = (color_list[i] >> 0) & bit_mask[8];
|
||||
}
|
||||
|
||||
uint32_t bit_reverse(uint32_t val, int bits)
|
||||
{
|
||||
uint32_t ret = val;
|
||||
int shift = bits - 1;
|
||||
|
||||
for (val >>= 1; val; val >>= 1) {
|
||||
ret <<= 1;
|
||||
ret |= val & 1;
|
||||
shift--;
|
||||
}
|
||||
|
||||
return ret <<= shift;
|
||||
}
|
||||
|
||||
void cmap_init(struct framebuffer *fb, struct fb_var_screeninfo *vinfo)
|
||||
{
|
||||
int i;
|
||||
uint16_t r, g, b;
|
||||
struct color_t color;
|
||||
|
||||
if (ioctl(fb->fd, FBIOGETCMAP, fb->cmap_org) < 0) { /* not fatal */
|
||||
cmap_die(fb->cmap_org);
|
||||
fb->cmap_org = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < COLORS; i++) {
|
||||
get_rgb(i, &color);
|
||||
r = (color.r << BITS_PER_BYTE) | color.r;
|
||||
g = (color.g << BITS_PER_BYTE) | color.g;
|
||||
b = (color.b << BITS_PER_BYTE) | color.b;
|
||||
|
||||
*(fb->cmap->red + i) = (vinfo->red.msb_right) ?
|
||||
bit_reverse(r, 16) & bit_mask[16]: r;
|
||||
*(fb->cmap->green + i) = (vinfo->green.msb_right) ?
|
||||
bit_reverse(g, 16) & bit_mask[16]: g;
|
||||
*(fb->cmap->blue + i) = (vinfo->blue.msb_right) ?
|
||||
bit_reverse(b, 16) & bit_mask[16]: b;
|
||||
}
|
||||
|
||||
if (ioctl(fb->fd, FBIOPUTCMAP, fb->cmap) < 0)
|
||||
fatal("ioctl: FBIOPUTCMAP failed");
|
||||
}
|
||||
|
||||
uint32_t get_color(struct fb_var_screeninfo *vinfo, int i)
|
||||
{
|
||||
uint32_t r, g, b;
|
||||
struct color_t color;
|
||||
|
||||
if (vinfo->bits_per_pixel == 8)
|
||||
return i;
|
||||
|
||||
get_rgb(i, &color);
|
||||
r = color.r >> (BITS_PER_BYTE - vinfo->red.length);
|
||||
g = color.g >> (BITS_PER_BYTE - vinfo->green.length);
|
||||
b = color.b >> (BITS_PER_BYTE - vinfo->blue.length);
|
||||
|
||||
if (vinfo->red.msb_right)
|
||||
r = bit_reverse(r, vinfo->red.length) & bit_mask[vinfo->red.length];
|
||||
if (vinfo->green.msb_right)
|
||||
g = bit_reverse(g, vinfo->green.length) & bit_mask[vinfo->green.length];
|
||||
if (vinfo->blue.msb_right)
|
||||
b = bit_reverse(b, vinfo->blue.length) & bit_mask[vinfo->blue.length];
|
||||
|
||||
return (r << vinfo->red.offset)
|
||||
+ (g << vinfo->green.offset)
|
||||
+ (b << vinfo->blue.offset);
|
||||
}
|
||||
|
||||
void fb_init(struct framebuffer *fb)
|
||||
{
|
||||
int i;
|
||||
char *path, *env;
|
||||
struct fb_fix_screeninfo finfo;
|
||||
struct fb_var_screeninfo vinfo;
|
||||
|
||||
if ((path = getenv("FRAMEBUFFER")) != NULL)
|
||||
fb->fd = eopen(path, O_RDWR);
|
||||
else
|
||||
fb->fd = eopen(fb_path, O_RDWR);
|
||||
|
||||
if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &finfo) < 0)
|
||||
fatal("ioctl: FBIOGET_FSCREENINFO failed");
|
||||
|
||||
if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
|
||||
fatal("ioctl: FBIOGET_VSCREENINFO failed");
|
||||
|
||||
fb->res.x = vinfo.xres;
|
||||
fb->res.y = vinfo.yres;
|
||||
fb->screen_size = finfo.smem_len;
|
||||
fb->line_length = finfo.line_length;
|
||||
|
||||
if ((finfo.visual == FB_VISUAL_TRUECOLOR || finfo.visual == FB_VISUAL_DIRECTCOLOR)
|
||||
&& (vinfo.bits_per_pixel == 15 || vinfo.bits_per_pixel == 16
|
||||
|| vinfo.bits_per_pixel == 24 || vinfo.bits_per_pixel == 32)) {
|
||||
fb->cmap = fb->cmap_org = NULL;
|
||||
fb->bpp = (vinfo.bits_per_pixel + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
|
||||
}
|
||||
else if (finfo.visual == FB_VISUAL_PSEUDOCOLOR
|
||||
&& vinfo.bits_per_pixel == 8) {
|
||||
fb->cmap = cmap_create(&vinfo);
|
||||
fb->cmap_org = cmap_create(&vinfo);
|
||||
cmap_init(fb, &vinfo);
|
||||
fb->bpp = 1;
|
||||
}
|
||||
else
|
||||
/* non packed pixel, mono color, grayscale: not implimented */
|
||||
fatal("unsupported framebuffer type");
|
||||
|
||||
for (i = 0; i < COLORS; i++) /* init color palette */
|
||||
fb->color_palette[i] = get_color(&vinfo, i);
|
||||
|
||||
fb->fp = (char *) emmap(0, fb->screen_size, PROT_WRITE | PROT_READ, MAP_SHARED, fb->fd, 0);
|
||||
fb->buf = (char *) emalloc(fb->screen_size);
|
||||
|
||||
if ((env = getenv("YAFT")) != NULL && strncmp(env, "wall", 4) == 0 && fb->bpp > 1)
|
||||
fb->wall = load_wallpaper(fb);
|
||||
else
|
||||
fb->wall = NULL;
|
||||
}
|
||||
|
||||
void fb_die(struct framebuffer *fb)
|
||||
{
|
||||
cmap_die(fb->cmap);
|
||||
if (fb->cmap_org) {
|
||||
ioctl(fb->fd, FBIOPUTCMAP, fb->cmap_org); /* not fatal */
|
||||
cmap_die(fb->cmap_org);
|
||||
}
|
||||
free(fb->wall);
|
||||
free(fb->buf);
|
||||
emunmap(fb->fp, fb->screen_size);
|
||||
eclose(fb->fd);
|
||||
}
|
||||
|
||||
int get_rotated_pos(struct framebuffer *fb, struct terminal *term, int x, int y)
|
||||
{
|
||||
int p, q;
|
||||
long pos;
|
||||
|
||||
if (ROTATE == CLOCKWISE) {
|
||||
p = y;
|
||||
q = (term->width - 1) - x;
|
||||
}
|
||||
else if (ROTATE == UPSIDE_DOWN) {
|
||||
p = (term->width - 1) - x;
|
||||
q = (term->height - 1) - y;
|
||||
}
|
||||
else if (ROTATE == COUNTER_CLOCKWISE) {
|
||||
p = (term->height - 1) - y;
|
||||
q = x;
|
||||
}
|
||||
else { /* rotate: NORMAL */
|
||||
p = x;
|
||||
q = y;
|
||||
}
|
||||
|
||||
pos = p * fb->bpp + q * fb->line_length;
|
||||
if (pos < 0 || pos >= fb->screen_size) {
|
||||
fprintf(stderr, "(%d, %d) -> (%d, %d) term:(%d, %d) res:(%d, %d) pos:%ld\n",
|
||||
x, y, p, q, term->width, term->height, fb->res.x, fb->res.y, pos);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void draw_line(struct framebuffer *fb, struct terminal *term, int line)
|
||||
{
|
||||
int copy_size, pos, bit_shift, margin_right;
|
||||
|
||||
int col, glyph_width_offset, glyph_height_offset;
|
||||
uint32_t pixel;
|
||||
struct color_pair color;
|
||||
struct cell *cp;
|
||||
const struct static_glyph_t *gp;
|
||||
|
||||
/*
|
||||
1280(width) x 1024(height) = 1310720 pixels
|
||||
|
||||
0 1279
|
||||
+-- ... --+
|
||||
| |
|
||||
1280 +-- ... --+2559
|
||||
| |
|
||||
. .
|
||||
. .
|
||||
+-- ... --+
|
||||
1309440 1310719
|
||||
|
||||
cell size: 8x16
|
||||
term cell: line 0 - 63 col 0 - 159
|
||||
*/
|
||||
|
||||
pos = get_rotated_pos(fb, term, term->width - 1, line * cell_height);
|
||||
copy_size = (ROTATE == CLOCKWISE || ROTATE == COUNTER_CLOCKWISE) ?
|
||||
cell_height * fb->bpp: cell_height * fb->line_length;
|
||||
|
||||
for (col = term->cols - 1; col >= 0; col--) {
|
||||
margin_right = (term->cols - 1 - col) * cell_width;
|
||||
|
||||
/* get cell color and glyph */
|
||||
cp = &term->cells[col + line * term->cols];
|
||||
color = cp->color;
|
||||
gp = cp->gp;
|
||||
|
||||
/* check cursor positon */
|
||||
if ((term->mode & MODE_CURSOR && line == term->cursor.y)
|
||||
&& (col == term->cursor.x
|
||||
|| (cp->wide == WIDE && (col + 1) == term->cursor.x)
|
||||
|| (cp->wide == NEXT_TO_WIDE && (col - 1) == term->cursor.x))) {
|
||||
color.fg = DEFAULT_BG;
|
||||
color.bg = CURSOR_COLOR;
|
||||
}
|
||||
|
||||
for (glyph_height_offset = 0; glyph_height_offset < cell_height; glyph_height_offset++) {
|
||||
if ((glyph_height_offset == (cell_height - 1)) && (cp->attribute & attr_mask[UNDERLINE]))
|
||||
color.bg = color.fg;
|
||||
|
||||
for (glyph_width_offset = 0; glyph_width_offset < cell_width; glyph_width_offset++) {
|
||||
pos = get_rotated_pos(fb, term, term->width - 1 - margin_right - glyph_width_offset,
|
||||
// min: 1280 - 1 - (160 - 1 - 0) * 8 - 7 = 0 / max: 1280 - 1 - (160 - 1 - 159) * 8 - 0 = 1279
|
||||
line * cell_height + glyph_height_offset);
|
||||
// min: 0 * 16 + 0 = 0 / max: (64 - 1) * 16 + 15 = 1023
|
||||
|
||||
if (cp->wide == WIDE)
|
||||
bit_shift = glyph_width_offset + cell_width;
|
||||
else
|
||||
bit_shift = glyph_width_offset;
|
||||
|
||||
/* set color palette */
|
||||
if (gp->bitmap[glyph_height_offset] & (0x01 << bit_shift))
|
||||
pixel = fb->color_palette[color.fg];
|
||||
else if (fb->wall && color.bg == DEFAULT_BG) /* wallpaper */
|
||||
memcpy(&pixel, fb->wall + pos, fb->bpp);
|
||||
else
|
||||
pixel = fb->color_palette[color.bg];
|
||||
|
||||
memcpy(fb->buf + pos, &pixel, fb->bpp);
|
||||
}
|
||||
}
|
||||
|
||||
if (ROTATE == CLOCKWISE || ROTATE == COUNTER_CLOCKWISE) {
|
||||
for (glyph_width_offset = 0; glyph_width_offset < cell_width; glyph_width_offset++) {
|
||||
pos = (ROTATE == CLOCKWISE) ?
|
||||
get_rotated_pos(fb, term, term->width - 1 - margin_right - glyph_width_offset, line * cell_height):
|
||||
// min: 1024 - 1 - (128 - 1 - 0) * 8 - 7 = 0 / max: 1024 - 1 - (128 - 1 - 127) * 8 - 0 = 1023
|
||||
// min: 0 * 16 = 0 / max: 79 * 16 = 1264
|
||||
get_rotated_pos(fb, term, term->width - 1 - margin_right - glyph_width_offset, (line + 1) * cell_height - 1);
|
||||
// min: 1 * 16 - 1 = 15 / max: 80 * 16 - 1 = 1279
|
||||
memcpy(fb->fp + pos, fb->buf + pos, copy_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ROTATE == NORMAL || ROTATE == UPSIDE_DOWN) {
|
||||
pos = (ROTATE == NORMAL) ?
|
||||
get_rotated_pos(fb, term, 0, line * cell_height):
|
||||
get_rotated_pos(fb, term, term->width - 1, (line + 1) * cell_height - 1);
|
||||
memcpy(fb->fp + pos, fb->buf + pos, copy_size);
|
||||
}
|
||||
|
||||
term->line_dirty[line] = ((term->mode & MODE_CURSOR) && term->cursor.y == line) ? true: false;
|
||||
}
|
||||
|
||||
void refresh(struct framebuffer *fb, struct terminal *term)
|
||||
{
|
||||
int line;
|
||||
|
||||
if (term->mode & MODE_CURSOR)
|
||||
term->line_dirty[term->cursor.y] = true;
|
||||
|
||||
for (line = 0; line < term->lines; line++) {
|
||||
if (term->line_dirty[line])
|
||||
draw_line(fb, term, line);
|
||||
}
|
||||
}
|
167
freebsd.h
Normal file
167
freebsd.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
/* See LICENSE for licence details. */
|
||||
#include <machine/param.h>
|
||||
#include <sys/consio.h>
|
||||
#include <sys/fbio.h>
|
||||
#include <sys/kbio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* some structs for FreeBSD */
|
||||
struct framebuffer {
|
||||
char *fp; /* pointer of framebuffer(read only) */
|
||||
char *wall; /* buffer for wallpaper */
|
||||
char *buf; /* copy of framebuffer */
|
||||
int fd; /* file descriptor of framebuffer */
|
||||
struct pair res; /* resolution (x, y) */
|
||||
long screen_size; /* screen data size (byte) */
|
||||
int line_length; /* line length (byte) */
|
||||
int bpp; /* BYTES per pixel */
|
||||
uint32_t color_palette[COLORS];
|
||||
video_color_palette_t *cmap, *cmap_org;
|
||||
enum rotate_mode rotate;
|
||||
};
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/* some functions for FreeBSD framebuffer */
|
||||
video_color_palette_t *cmap_create(video_info_t *video_info)
|
||||
{
|
||||
video_color_palette_t *cmap;
|
||||
|
||||
cmap = (video_color_palette_t *) emalloc(sizeof(video_color_palette_t));
|
||||
cmap->index = 0;
|
||||
cmap->count = COLORS;
|
||||
cmap->red = (u_char *) emalloc(sizeof(u_char) * COLORS);
|
||||
cmap->green = (u_char *) emalloc(sizeof(u_char) * COLORS);
|
||||
cmap->blue = (u_char *) emalloc(sizeof(u_char) * COLORS);
|
||||
cmap->transparent = NULL;
|
||||
|
||||
return cmap;
|
||||
}
|
||||
|
||||
void cmap_die(video_color_palette_t *cmap)
|
||||
{
|
||||
if (cmap) {
|
||||
free(cmap->red);
|
||||
free(cmap->green);
|
||||
free(cmap->blue);
|
||||
free(cmap->transparent);
|
||||
free(cmap);
|
||||
}
|
||||
}
|
||||
|
||||
void cmap_init(struct framebuffer *fb, video_info_t *video_info)
|
||||
{
|
||||
int i;
|
||||
struct color_t color;
|
||||
|
||||
if (ioctl(fb->fd, FBIOGETCMAP, fb->cmap_org) < 0) { /* not fatal */
|
||||
cmap_die(fb->cmap_org);
|
||||
fb->cmap_org = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < COLORS; i++) {
|
||||
/* where is endian info? */
|
||||
get_rgb(i, &color);
|
||||
*(fb->cmap->red + i) = color.r;
|
||||
*(fb->cmap->green + i) = color.g;
|
||||
*(fb->cmap->blue + i) = color.b;
|
||||
}
|
||||
|
||||
if (ioctl(fb->fd, FBIOPUTCMAP, fb->cmap) < 0)
|
||||
fatal("ioctl: FBIOPUTCMAP failed");
|
||||
}
|
||||
|
||||
uint32_t get_color(video_info_t *video_info, int i)
|
||||
{
|
||||
uint32_t r, g, b;
|
||||
struct color_t color;
|
||||
|
||||
if (video_info->vi_depth == 8)
|
||||
return i;
|
||||
|
||||
/* where is endian info? */
|
||||
get_rgb(i, &color);
|
||||
r = color.r >> (BITS_PER_BYTE - video_info->vi_pixel_fsizes[0]);
|
||||
g = color.g >> (BITS_PER_BYTE - video_info->vi_pixel_fsizes[1]);
|
||||
b = color.b >> (BITS_PER_BYTE - video_info->vi_pixel_fsizes[2]);
|
||||
|
||||
return (r << video_info->vi_pixel_fields[0])
|
||||
+ (g << video_info->vi_pixel_fields[1])
|
||||
+ (b << video_info->vi_pixel_fields[2]);
|
||||
}
|
||||
|
||||
void fb_init(struct framebuffer *fb)
|
||||
{
|
||||
int i, video_mode;
|
||||
char *path;
|
||||
video_info_t video_info;
|
||||
video_adapter_info_t video_adapter_info;
|
||||
|
||||
if ((path = getenv("FRAMEBUFFER")) != NULL)
|
||||
fb->fd = eopen(path, O_RDWR);
|
||||
else
|
||||
fb->fd = eopen(fb_path, O_RDWR);
|
||||
|
||||
if (ioctl(fb->fd, FBIO_GETMODE, &video_mode) < 0)
|
||||
fatal("ioctl: FBIO_GETMODE failed");
|
||||
|
||||
/*
|
||||
if (video_mode != VIDEO_MODE) {
|
||||
fprintf(stderr, "current mode:%d request mode:%d\n", video_mode, VIDEO_MODE);
|
||||
fatal("video mode unmatch");
|
||||
}
|
||||
*/
|
||||
|
||||
video_info.vi_mode = video_mode;
|
||||
if (ioctl(fb->fd, FBIO_MODEINFO, &video_info) < 0)
|
||||
fatal("ioctl: FBIO_MODEINFO failed");
|
||||
|
||||
if (ioctl(fb->fd, FBIO_ADPINFO, &video_adapter_info) < 0)
|
||||
fatal("ioctl: FBIO_ADPINFO failed");
|
||||
|
||||
fb->res.x = video_info.vi_width;
|
||||
fb->res.y = video_info.vi_height;
|
||||
|
||||
fb->screen_size = video_adapter_info.va_window_size;
|
||||
fb->line_length = video_adapter_info.va_line_width;
|
||||
|
||||
if ((video_info.vi_mem_model == V_INFO_MM_PACKED || video_info.vi_mem_model == V_INFO_MM_DIRECT)
|
||||
&& (video_info.vi_depth == 15 || video_info.vi_depth == 16
|
||||
|| video_info.vi_depth == 24 || video_info.vi_depth == 32)) {
|
||||
fb->cmap = fb->cmap_org = NULL;
|
||||
fb->bpp = (video_info.vi_depth + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
|
||||
}
|
||||
else if ((video_adapter_info.va_flags & V_ADP_PALETTE) &&
|
||||
video_info.vi_mem_model == V_INFO_MM_PACKED && video_info.vi_depth == 8) {
|
||||
fb->cmap = cmap_create(&video_info);
|
||||
fb->cmap_org = cmap_create(&video_info);
|
||||
cmap_init(fb, &video_info);
|
||||
fb->bpp = 1;
|
||||
}
|
||||
else
|
||||
/* non packed pixel, mono color, grayscale: not implimented */
|
||||
fatal("unsupported framebuffer type");
|
||||
|
||||
for (i = 0; i < COLORS; i++) /* init color palette */
|
||||
fb->color_palette[i] = get_color(&video_info, i);
|
||||
|
||||
fb->fp = (char *) emmap(0, fb->screen_size, PROT_WRITE | PROT_READ, MAP_SHARED, fb->fd, 0);
|
||||
fb->buf = (char *) emalloc(fb->screen_size);
|
||||
}
|
||||
|
||||
void fb_die(struct framebuffer *fb)
|
||||
{
|
||||
cmap_die(fb->cmap);
|
||||
if (fb->cmap_org) {
|
||||
ioctl(fb->fd, FBIOPUTCMAP, fb->cmap_org); // not fatal
|
||||
cmap_die(fb->cmap_org);
|
||||
}
|
||||
free(fb->wall);
|
||||
free(fb->buf);
|
||||
emunmap(fb->fp, fb->screen_size);
|
||||
eclose(fb->fd);
|
||||
}
|
||||
|
||||
#include "draw.h"
|
310
function.h
310
function.h
|
@ -93,6 +93,11 @@ void enter_osc(struct terminal *term, void *arg)
|
|||
term->esc.state = STATE_OSC;
|
||||
}
|
||||
|
||||
void enter_dcs(struct terminal *term, void *arg)
|
||||
{
|
||||
term->esc.state = STATE_DCS;
|
||||
}
|
||||
|
||||
void ris(struct terminal *term, void *arg)
|
||||
{
|
||||
reset(term);
|
||||
|
@ -489,4 +494,307 @@ void clear_tabstop(struct terminal *term, void *arg)
|
|||
}
|
||||
|
||||
/* function for osc sequence */
|
||||
/* not implemented */
|
||||
void set_palette(struct terminal *term, void *arg)
|
||||
{
|
||||
/*
|
||||
|
||||
OSC Ps ; Pt ST
|
||||
ref: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
ref: http://ttssh2.sourceforge.jp/manual/ja/about/ctrlseq.html#OSC
|
||||
|
||||
only recognize change color palette:
|
||||
Ps: 4
|
||||
Pt: c ; spec
|
||||
c: color index (from 0 to 255)
|
||||
spec:
|
||||
rgb:r/g/b
|
||||
rgb:rr/gg/bb
|
||||
rgb:rrr/ggg/bbb
|
||||
rgb:rrrr/gggg/bbbb
|
||||
#rgb
|
||||
#rrggbb
|
||||
#rrrgggbbb
|
||||
#rrrrggggbbbb
|
||||
this rgb format is "RGB Device String Specification"
|
||||
see http://xjman.dsl.gr.jp/X11R6/X11/CH06.html
|
||||
PT: c ; ?
|
||||
response rgb color
|
||||
OSC 4 ; c ; rgb:rr/gg/bb ST
|
||||
*/
|
||||
struct parm_t *pt = (struct parm_t *) arg, sub_parm;
|
||||
int i, argc = pt->argc, c, length;
|
||||
char **argv = pt->argv;
|
||||
long val;
|
||||
uint8_t rgb[3];
|
||||
uint32_t color;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
if (argc != 3)
|
||||
return;
|
||||
|
||||
if (strncmp(argv[2], "rgb:", 4) == 0) {
|
||||
/*
|
||||
rgb:r/g/b
|
||||
rgb:rr/gg/bb
|
||||
rgb:rrr/ggg/bbb
|
||||
rgb:rrrr/gggg/bbbb
|
||||
*/
|
||||
reset_parm(&sub_parm);
|
||||
parse_arg(argv[2] + 4, &sub_parm, '/', isalnum); /* skip "rgb:" */
|
||||
|
||||
if (DEBUG)
|
||||
for (i = 0; i < sub_parm.argc; i++)
|
||||
fprintf(stderr, "sub_parm.argv[%d]: %s\n", i, sub_parm.argv[i]);
|
||||
|
||||
if (sub_parm.argc != 3)
|
||||
return;
|
||||
|
||||
length = strlen(sub_parm.argv[0]);
|
||||
c = atoi(argv[1]);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
val = strtol(sub_parm.argv[i], NULL, 16);
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "val:%ld\n", val);
|
||||
|
||||
if (length == 1)
|
||||
rgb[i] = (double) val * 0xFF / 0x0F;
|
||||
else if (length == 2)
|
||||
rgb[i] = val;
|
||||
else if (length == 3)
|
||||
rgb[i] = (double) val * 0xFF / 0xFFF;
|
||||
else if (length == 4)
|
||||
rgb[i] = (double) val * 0xFF / 0xFFFF;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
color = (rgb[0] << 16) + (rgb[1] << 8) + rgb[2];
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "color:0x%.6X\n", color);
|
||||
|
||||
if (0 <= c && c < COLORS)
|
||||
term->color_palette[c] = color;
|
||||
}
|
||||
else if (strncmp(argv[2], "#", 1) == 0) {
|
||||
/*
|
||||
#rgb
|
||||
#rrggbb
|
||||
#rrrgggbbb
|
||||
#rrrrggggbbbb
|
||||
*/
|
||||
c = atoi(argv[1]);
|
||||
length = strlen(argv[2] + 1); /* skip '#' */
|
||||
memset(buf, '\0', BUFSIZE);
|
||||
|
||||
if (length == 3) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
strncpy(buf, argv[2] + 1 + i, 1);
|
||||
rgb[i] = (double) strtol(buf, NULL, 16) * 0xFF / 0x0F;
|
||||
}
|
||||
}
|
||||
else if (length == 6) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
strncpy(buf, argv[2] + 1 + i * 2, 2);
|
||||
rgb[i] = strtol(buf, NULL, 16);
|
||||
}
|
||||
}
|
||||
else if (length == 9) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
strncpy(buf, argv[2] + 1 + i * 3, 3);
|
||||
rgb[i] = (double) strtol(buf, NULL, 16) * 0xFF / 0xFFF;
|
||||
}
|
||||
}
|
||||
else if (length == 12) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
strncpy(buf, argv[2] + 1 + i * 4, 4);
|
||||
rgb[i] = (double) strtol(buf, NULL, 16) * 0xFF / 0xFFFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
color = (rgb[0] << 16) + (rgb[1] << 8) + rgb[2];
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "color:0x%.6X\n", color);
|
||||
|
||||
if (0 <= c && c < COLORS)
|
||||
term->color_palette[c] = color;
|
||||
}
|
||||
else if (strncmp(argv[2], "?", 1) == 0) {
|
||||
/*
|
||||
?
|
||||
*/
|
||||
c = atoi(argv[1]);
|
||||
|
||||
if (0 <= c && c < COLORS) {
|
||||
for (i = 2; i >= 0; i--)
|
||||
rgb[i] = (term->color_palette[c] >> (8 * i)) & 0xFF;
|
||||
snprintf(buf, BUFSIZE, "\033]4;%d;rgb:%.2X/%.2X/%.2X\033\\", c, rgb[0], rgb[1], rgb[2]);
|
||||
ewrite(term->fd, buf, strlen(buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reset_palette(struct terminal *term, void *arg)
|
||||
{
|
||||
/*
|
||||
reset color c
|
||||
OSC 104 ; c ST
|
||||
c: index of color
|
||||
ST: BEL or ESC \
|
||||
reset all color
|
||||
OSC 104 ST
|
||||
ST: BEL or ESC \
|
||||
|
||||
terminfo: oc=\E]104\E\\
|
||||
*/
|
||||
struct parm_t *pt = (struct parm_t *) arg;
|
||||
int i, argc = pt->argc, c;
|
||||
char **argv = pt->argv;
|
||||
|
||||
if (argc < 2) { /* reset all color palette */
|
||||
for (i = 0; i < COLORS; i++)
|
||||
term->color_palette[i] = color_list[i];
|
||||
}
|
||||
else if (argc == 2) { /* reset color_palette[c] */
|
||||
c = atoi(argv[1]);
|
||||
if (0 <= c && c < COLORS)
|
||||
term->color_palette[c] = color_list[c];
|
||||
}
|
||||
}
|
||||
|
||||
void glyph_width_report(struct terminal *term, void *arg)
|
||||
{
|
||||
/*
|
||||
glyph width report
|
||||
* request *
|
||||
OSC 8900 ; Ps ; ? : Pw : Pf : Pt ST
|
||||
Ps: reserved
|
||||
Pw: width (0 or 1 or 2)
|
||||
Pf: beginning of unicode code point
|
||||
Pt: end of unicode code point
|
||||
ST: BEL(0x07) or ESC(0x1B) BACKSLASH(0x5C)
|
||||
* answer *
|
||||
OSC 8900 ; Ps ; Pt ; Pf : Pt ; Pf : Pt ; ... ST
|
||||
Ps: responce code
|
||||
0: ok (default)
|
||||
1: recognized but not supported
|
||||
2: not recognized
|
||||
Pt: reserved (maybe East Asian Width Version)
|
||||
<!-- Pw: width (0 or 1 or 2) depricated -->
|
||||
Pf: beginning of unicode code point
|
||||
Pt: end of unicode code point
|
||||
ST: BEL(0x07) or ESC(0x1B) BACKSLASH(0x5C)
|
||||
ref
|
||||
http://uobikiemukot.github.io/yaft/glyph_width_report.html
|
||||
https://gist.github.com/saitoha/8767268
|
||||
*/
|
||||
struct parm_t *pt = (struct parm_t *) arg, sub_parm;
|
||||
int i, width, from, to, left, right, w; //reserved
|
||||
char **argv = pt->argv, buf[BUFSIZE];
|
||||
|
||||
reset_parm(&sub_parm);
|
||||
parse_arg(argv[2], &sub_parm, ':', isdigit_or_questionmark);
|
||||
|
||||
if (sub_parm.argc != 4 || *sub_parm.argv[0] != '?')
|
||||
return;
|
||||
|
||||
//reserved = atoi(argv[1]);
|
||||
width = atoi(sub_parm.argv[1]);
|
||||
from = atoi(sub_parm.argv[2]);
|
||||
to = atoi(sub_parm.argv[3]);
|
||||
|
||||
if ((from < 0 || to >= UCS2_CHARS) /* change here when implement DRCS */
|
||||
|| (width < 0 || width > 2))
|
||||
return;
|
||||
|
||||
ewrite(term->fd, "\033]8900;0;0;", 11); /* OSC 8900 ; Ps; Pt ; */
|
||||
|
||||
left = right = -1;
|
||||
for (i = from; i <= to; i++) {
|
||||
w = fonts[i].width;
|
||||
|
||||
if (w != width) {
|
||||
if (right != -1) {
|
||||
snprintf(buf, BUFSIZE, "%d:%d;", left, right);
|
||||
ewrite(term->fd, buf, strlen(buf));
|
||||
}
|
||||
else if (left != -1) {
|
||||
snprintf(buf, BUFSIZE, "%d:%d;", left, left);
|
||||
ewrite(term->fd, buf, strlen(buf));
|
||||
}
|
||||
|
||||
left = right = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (left == -1)
|
||||
left = i;
|
||||
else
|
||||
right = i;
|
||||
}
|
||||
|
||||
if (right != -1) {
|
||||
snprintf(buf, BUFSIZE, "%d:%d;", left, right);
|
||||
ewrite(term->fd, buf, strlen(buf));
|
||||
}
|
||||
else if (left != -1) {
|
||||
snprintf(buf, BUFSIZE, "%d:%d;", left, left);
|
||||
ewrite(term->fd, buf, strlen(buf));
|
||||
}
|
||||
|
||||
ewrite(term->fd, "\033\\", 2); /* ST (ESC BACKSLASH) */
|
||||
}
|
||||
|
||||
/* function for dcs sequence */
|
||||
void decdld_header(struct terminal *term, void *arg)
|
||||
{
|
||||
/*
|
||||
DECDLD header:
|
||||
(http://vt100.net/docs/vt510-rm/DECDLD#T5-2)
|
||||
DCS Pfn ; Pcn; Pe; Pcmw; Pss; Pt; Pcmh; Pcss {
|
||||
|
||||
Pfn: Font number (ignored)
|
||||
Pcn: Starting character (from 0 to 95 (0x20 - 0x7F))
|
||||
Pe: Erase control (0, 1, 2)
|
||||
Pcmw: Character matrix width (ignored)
|
||||
Pss: Font set size (ignored)
|
||||
Pt: Text or full cell (force "2": full cell mode)
|
||||
Pcmh: Character matrix height (ignored)
|
||||
Pcss: Character set size (force "1": 96 character set)
|
||||
|
||||
in yaft, DRCS font size must be the same as cell size.
|
||||
So some parameters (Pcmw, Pss, Pcmh, Pcss) are ignored.
|
||||
Pt force "2" (full cell mode) or "3" for sixel...(not implemented)
|
||||
|
||||
DRCS are mapped on UCS Private Area.
|
||||
|
||||
~~~
|
||||
DRCSMMv1
|
||||
(https://github.com/saitoha/drcsterm)
|
||||
|
||||
U+10XXYY (0x40 <= 0xXX <=0x7E, 0x20 <= 0xYY <= 0x7F)
|
||||
|
||||
Dcsc: from '@' (0x40) to '~' (0x7E)
|
||||
('0' (0x30) - '?' (0x3F) are not available)
|
||||
|
||||
each character set has 96 glyph (0x20 - 0x7F)
|
||||
|
||||
~~~
|
||||
ISO-2022-JP-MS
|
||||
~~~
|
||||
|
||||
*/
|
||||
struct parm_t *pt = (struct parm_t *) arg;
|
||||
int argc = pt->argc;
|
||||
char **argv = pt->argv;
|
||||
|
||||
if (argc != 7) /* invalid DECDLD header */
|
||||
return;
|
||||
|
||||
if (argv[0])
|
||||
;
|
||||
|
||||
term->esc.state = STATE_DSCS;
|
||||
}
|
||||
|
|
165
linux.h
Normal file
165
linux.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
/* See LICENSE for licence details. */
|
||||
#include <linux/fb.h>
|
||||
#include <linux/vt.h>
|
||||
#include <linux/kd.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* struct for Linux */
|
||||
struct framebuffer {
|
||||
char *fp; /* pointer of framebuffer(read only) */
|
||||
char *wall; /* buffer for wallpaper */
|
||||
char *buf; /* copy of framebuffer */
|
||||
int fd; /* file descriptor of framebuffer */
|
||||
struct pair res; /* resolution (x, y) */
|
||||
long screen_size; /* screen data size (byte) */
|
||||
int line_length; /* line length (byte) */
|
||||
int bpp; /* BYTES per pixel */
|
||||
struct fb_cmap *cmap, *cmap_org; /* cmap for legacy framebuffer (pseudocolor) */
|
||||
enum rotate_mode rotate; /* rotate mode: see "enum rotate mode" */
|
||||
};
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/* some functions for Linux framebuffer */
|
||||
struct fb_cmap *cmap_create(struct fb_var_screeninfo *vinfo)
|
||||
{
|
||||
struct fb_cmap *cmap;
|
||||
|
||||
cmap = (struct fb_cmap *) emalloc(sizeof(struct fb_cmap));
|
||||
cmap->start = 0;
|
||||
cmap->len = COLORS;
|
||||
cmap->red = (uint16_t *) emalloc(sizeof(uint16_t) * COLORS);
|
||||
cmap->green = (uint16_t *) emalloc(sizeof(uint16_t) * COLORS);
|
||||
cmap->blue = (uint16_t *) emalloc(sizeof(uint16_t) * COLORS);
|
||||
cmap->transp = NULL;
|
||||
|
||||
return cmap;
|
||||
}
|
||||
|
||||
void cmap_die(struct fb_cmap *cmap)
|
||||
{
|
||||
if (cmap) {
|
||||
free(cmap->red);
|
||||
free(cmap->green);
|
||||
free(cmap->blue);
|
||||
free(cmap->transp);
|
||||
free(cmap);
|
||||
}
|
||||
}
|
||||
|
||||
void cmap_init(struct framebuffer *fb, struct fb_var_screeninfo *vinfo)
|
||||
{
|
||||
int i;
|
||||
uint16_t r, g, b;
|
||||
struct color_t color;
|
||||
|
||||
if (ioctl(fb->fd, FBIOGETCMAP, fb->cmap_org) < 0) { /* not fatal */
|
||||
cmap_die(fb->cmap_org);
|
||||
fb->cmap_org = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < COLORS; i++) {
|
||||
get_rgb(i, &color);
|
||||
r = (color.r << BITS_PER_BYTE) | color.r;
|
||||
g = (color.g << BITS_PER_BYTE) | color.g;
|
||||
b = (color.b << BITS_PER_BYTE) | color.b;
|
||||
|
||||
*(fb->cmap->red + i) = (vinfo->red.msb_right) ?
|
||||
bit_reverse(r, 16) & bit_mask[16]: r;
|
||||
*(fb->cmap->green + i) = (vinfo->green.msb_right) ?
|
||||
bit_reverse(g, 16) & bit_mask[16]: g;
|
||||
*(fb->cmap->blue + i) = (vinfo->blue.msb_right) ?
|
||||
bit_reverse(b, 16) & bit_mask[16]: b;
|
||||
}
|
||||
|
||||
if (ioctl(fb->fd, FBIOPUTCMAP, fb->cmap) < 0)
|
||||
fatal("ioctl: FBIOPUTCMAP failed");
|
||||
}
|
||||
|
||||
uint32_t get_color(struct fb_var_screeninfo *vinfo, int i)
|
||||
{
|
||||
uint32_t r, g, b;
|
||||
struct color_t color;
|
||||
|
||||
if (vinfo->bits_per_pixel == 8)
|
||||
return i;
|
||||
|
||||
get_rgb(i, &color);
|
||||
r = color.r >> (BITS_PER_BYTE - vinfo->red.length);
|
||||
g = color.g >> (BITS_PER_BYTE - vinfo->green.length);
|
||||
b = color.b >> (BITS_PER_BYTE - vinfo->blue.length);
|
||||
|
||||
if (vinfo->red.msb_right)
|
||||
r = bit_reverse(r, vinfo->red.length) & bit_mask[vinfo->red.length];
|
||||
if (vinfo->green.msb_right)
|
||||
g = bit_reverse(g, vinfo->green.length) & bit_mask[vinfo->green.length];
|
||||
if (vinfo->blue.msb_right)
|
||||
b = bit_reverse(b, vinfo->blue.length) & bit_mask[vinfo->blue.length];
|
||||
|
||||
return (r << vinfo->red.offset)
|
||||
+ (g << vinfo->green.offset)
|
||||
+ (b << vinfo->blue.offset);
|
||||
}
|
||||
|
||||
void fb_init(struct framebuffer *fb, uint32_t *color_palette)
|
||||
{
|
||||
int i;
|
||||
char *path;
|
||||
struct fb_fix_screeninfo finfo;
|
||||
struct fb_var_screeninfo vinfo;
|
||||
|
||||
if ((path = getenv("FRAMEBUFFER")) != NULL)
|
||||
fb->fd = eopen(path, O_RDWR);
|
||||
else
|
||||
fb->fd = eopen(fb_path, O_RDWR);
|
||||
|
||||
if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &finfo) < 0)
|
||||
fatal("ioctl: FBIOGET_FSCREENINFO failed");
|
||||
|
||||
if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
|
||||
fatal("ioctl: FBIOGET_VSCREENINFO failed");
|
||||
|
||||
fb->res.x = vinfo.xres;
|
||||
fb->res.y = vinfo.yres;
|
||||
fb->screen_size = finfo.smem_len;
|
||||
fb->line_length = finfo.line_length;
|
||||
|
||||
if ((finfo.visual == FB_VISUAL_TRUECOLOR || finfo.visual == FB_VISUAL_DIRECTCOLOR)
|
||||
&& (vinfo.bits_per_pixel == 15 || vinfo.bits_per_pixel == 16
|
||||
|| vinfo.bits_per_pixel == 24 || vinfo.bits_per_pixel == 32)) {
|
||||
fb->cmap = fb->cmap_org = NULL;
|
||||
fb->bpp = (vinfo.bits_per_pixel + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
|
||||
}
|
||||
else if (finfo.visual == FB_VISUAL_PSEUDOCOLOR
|
||||
&& vinfo.bits_per_pixel == 8) {
|
||||
fb->cmap = cmap_create(&vinfo);
|
||||
fb->cmap_org = cmap_create(&vinfo);
|
||||
cmap_init(fb, &vinfo);
|
||||
fb->bpp = 1;
|
||||
}
|
||||
else
|
||||
/* non packed pixel, mono color, grayscale: not implimented */
|
||||
fatal("unsupported framebuffer type");
|
||||
|
||||
for (i = 0; i < COLORS; i++) /* init color palette */
|
||||
color_palette[i] = get_color(&vinfo, i);
|
||||
|
||||
fb->fp = (char *) emmap(0, fb->screen_size, PROT_WRITE | PROT_READ, MAP_SHARED, fb->fd, 0);
|
||||
fb->buf = (char *) emalloc(fb->screen_size);
|
||||
}
|
||||
|
||||
void fb_die(struct framebuffer *fb)
|
||||
{
|
||||
cmap_die(fb->cmap);
|
||||
if (fb->cmap_org) {
|
||||
ioctl(fb->fd, FBIOPUTCMAP, fb->cmap_org); /* not fatal */
|
||||
cmap_die(fb->cmap_org);
|
||||
}
|
||||
free(fb->wall);
|
||||
free(fb->buf);
|
||||
emunmap(fb->fp, fb->screen_size);
|
||||
eclose(fb->fd);
|
||||
}
|
||||
|
||||
#include "draw.h"
|
95
parse.h
95
parse.h
|
@ -16,6 +16,7 @@ void (*esc_func[ESC_CHARS])(struct terminal * term, void *arg) = {
|
|||
['E'] = crnl,
|
||||
['H'] = set_tabstop,
|
||||
['M'] = reverse_nl,
|
||||
['P'] = enter_dcs,
|
||||
['Z'] = identify,
|
||||
['['] = enter_csi,
|
||||
[']'] = enter_osc,
|
||||
|
@ -54,45 +55,9 @@ void (*csi_func[ESC_CHARS])(struct terminal * term, void *arg) = {
|
|||
['`'] = curs_col,
|
||||
};
|
||||
|
||||
void reset_parm(struct parm_t *pt)
|
||||
{
|
||||
int i;
|
||||
|
||||
pt->argc = 0;
|
||||
for (i = 0; i < ESC_PARAMS; i++)
|
||||
pt->argv[i] = NULL;
|
||||
}
|
||||
|
||||
void parse_arg(char *buf, struct parm_t *pt, int delim, int (is_valid)(int c))
|
||||
{
|
||||
int length;
|
||||
char *cp;
|
||||
|
||||
length = strlen(buf);
|
||||
cp = buf;
|
||||
|
||||
while (cp < &buf[length - 1]) {
|
||||
if (*cp == delim)
|
||||
*cp = '\0';
|
||||
cp++;
|
||||
}
|
||||
|
||||
cp = buf;
|
||||
start:
|
||||
if (pt->argc < ESC_PARAMS && is_valid(*cp)) {
|
||||
pt->argv[pt->argc] = cp;
|
||||
pt->argc++;
|
||||
}
|
||||
|
||||
while (is_valid(*cp))
|
||||
cp++;
|
||||
|
||||
while (!is_valid(*cp) && cp < &buf[length - 1])
|
||||
cp++;
|
||||
|
||||
if (cp < &buf[length - 1])
|
||||
goto start;
|
||||
}
|
||||
void (*dcs_func[ESC_CHARS])(struct terminal * term, void *arg) = {
|
||||
['{'] = decdld_header,
|
||||
};
|
||||
|
||||
void control_character(struct terminal *term, uint8_t ch)
|
||||
{
|
||||
|
@ -130,7 +95,7 @@ void csi_sequence(struct terminal *term, uint8_t ch)
|
|||
fprintf(stderr, "csi: CSI %s\n", term->esc.buf);
|
||||
|
||||
reset_parm(&parm);
|
||||
parse_arg(term->esc.buf, &parm, ';', isdigit);
|
||||
parse_arg(term->esc.buf + 1, &parm, ';', isdigit); /* skip '[' */
|
||||
*(term->esc.bp - 1) = '\0'; /* omit final character */
|
||||
|
||||
if (csi_func[ch])
|
||||
|
@ -141,9 +106,53 @@ void csi_sequence(struct terminal *term, uint8_t ch)
|
|||
|
||||
void osc_sequence(struct terminal *term, uint8_t ch)
|
||||
{
|
||||
int i, osc_mode;
|
||||
struct parm_t parm;
|
||||
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "osc: OSC %s\n", term->esc.buf);
|
||||
|
||||
reset_parm(&parm);
|
||||
parse_arg(term->esc.buf + 1, &parm, ';', is_osc_parm); /* skip ']' */
|
||||
if (*(term->esc.bp - 1) == BACKSLASH) /* ST: ESC BACKSLASH */
|
||||
*(term->esc.bp - 2) = '\0';
|
||||
*(term->esc.bp - 1) = '\0'; /* omit final character */
|
||||
|
||||
if (DEBUG)
|
||||
for (i = 0; i < parm.argc; i++)
|
||||
fprintf(stderr, "\targv[%d]: %s\n", i, parm.argv[i]);
|
||||
|
||||
if (parm.argc > 0) {
|
||||
osc_mode = atoi(parm.argv[0]);
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "osc_mode:%d\n", osc_mode);
|
||||
|
||||
if (osc_mode == 4)
|
||||
set_palette(term, &parm);
|
||||
else if (osc_mode == 104)
|
||||
reset_palette(term, &parm);
|
||||
else if (osc_mode == 8900)
|
||||
glyph_width_report(term, &parm);
|
||||
}
|
||||
|
||||
reset_esc(term);
|
||||
}
|
||||
|
||||
void dcs_sequence(struct terminal *term, uint8_t ch)
|
||||
{
|
||||
struct parm_t parm;
|
||||
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "dcs: DCS %s\n", term->esc.buf);
|
||||
|
||||
reset_parm(&parm);
|
||||
parse_arg(term->esc.buf, &parm, ';', isdigit);
|
||||
*(term->esc.bp - 1) = '\0'; /* omit final character */
|
||||
|
||||
if (dcs_func[ch])
|
||||
dcs_func[ch](term, &parm);
|
||||
|
||||
if (ch != '{')
|
||||
reset_esc(term);
|
||||
}
|
||||
|
||||
|
@ -239,7 +248,7 @@ void parse(struct terminal *term, uint8_t *buf, int size)
|
|||
|
||||
for (i = 0; i < size; i++) {
|
||||
ch = buf[i];
|
||||
if (term->esc.state == RESET) {
|
||||
if (term->esc.state == STATE_RESET) {
|
||||
if (term->ucs.following_byte > 0 && (ch < 0x80 || ch > 0xBF)) { /* interrupt */
|
||||
addch(term, REPLACEMENT_CHAR);
|
||||
reset_ucs(term);
|
||||
|
@ -264,5 +273,9 @@ void parse(struct terminal *term, uint8_t *buf, int size)
|
|||
if (push_esc(term, ch))
|
||||
osc_sequence(term, ch);
|
||||
}
|
||||
else if (term->esc.state == STATE_DCS) {
|
||||
if (push_esc(term, ch))
|
||||
dcs_sequence(term, ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
46
pos_test.c
46
pos_test.c
|
@ -1,46 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
enum {
|
||||
NORMAL = 0,
|
||||
CLOCKWISE = 90,
|
||||
UPSIDE_DOWN = 180,
|
||||
COUNTER_CLOCKWISE = 270,
|
||||
};
|
||||
|
||||
struct disp_t {
|
||||
int x, y;
|
||||
int bpp, line_length;
|
||||
};
|
||||
|
||||
|
||||
int get_rotated_pos(struct disp_t disp, int x, int y, int rotate)
|
||||
{
|
||||
if (rotate == CLOCKWISE)
|
||||
return y * disp.bpp + (disp.x - 1 - x) * disp.y * disp.bpp;
|
||||
else if (rotate == UPSIDE_DOWN)
|
||||
return (disp.x - 1 - x) * disp.bpp + (disp.y - 1 - y) * disp.line_length;
|
||||
else if (rotate == COUNTER_CLOCKWISE)
|
||||
return (disp.y - 1 - y) * disp.bpp + x * disp.y * disp.bpp;
|
||||
else /* rotate: NORMAL */
|
||||
return x * disp.bpp + y * disp.line_length;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i, j, pos;
|
||||
struct disp_t disp = {.x = 1280, .y = 1024, .bpp = 4, .line_length = 5120};
|
||||
|
||||
for (i = 0; i < disp.x; i++) {
|
||||
for (j = 0; j < disp.y; j++) {
|
||||
pos = get_rotated_pos(disp, i, j, COUNTER_CLOCKWISE);
|
||||
if (!(0 <= pos && pos < 5242880)) {
|
||||
printf("i:%d j:%d pos:%d\n", i, j, pos);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
printf("%d\n", pos);
|
||||
}
|
||||
}
|
||||
}
|
171
rotate.h
171
rotate.h
|
@ -1,171 +0,0 @@
|
|||
/* See LICENSE for licence details. */
|
||||
int my_ceil(int value, int division)
|
||||
{
|
||||
return ((value + division - 1) / division);
|
||||
}
|
||||
|
||||
void set_bit_normal(struct framebuffer *fb, struct terminal *term, int y, int x, int offset, char *src)
|
||||
{
|
||||
int i, shift, glyph_width;
|
||||
uint32_t pixel;
|
||||
struct color_pair color;
|
||||
struct cell *cp;
|
||||
const struct static_glyph_t *gp;
|
||||
|
||||
cp = &term->cells[x + y * term->cols];
|
||||
if (cp->wide == NEXT_TO_WIDE)
|
||||
return;
|
||||
|
||||
gp = cp->gp;
|
||||
glyph_width = gp->width * cell_width;
|
||||
shift = ((glyph_width + BITS_PER_BYTE - 1) / BITS_PER_BYTE) * BITS_PER_BYTE;
|
||||
color = cp->color;
|
||||
|
||||
if ((term->mode & MODE_CURSOR && y == term->cursor.y) /* cursor */
|
||||
&& (x == term->cursor.x || (cp->wide == WIDE && (x + 1) == term->cursor.x))) {
|
||||
color.fg = DEFAULT_BG;
|
||||
color.bg = CURSOR_COLOR;
|
||||
}
|
||||
|
||||
if ((offset == (cell_height - 1)) /* underline */
|
||||
&& (cp->attribute & attr_mask[UNDERLINE]))
|
||||
color.bg = color.fg;
|
||||
|
||||
for (i = 0; i < glyph_width; i++) {
|
||||
if (gp->bitmap[offset] & (0x01 << (shift - i - 1)))
|
||||
pixel = fb->color_palette[color.fg];
|
||||
else if (fb->wall && color.bg == DEFAULT_BG) /* wallpaper */
|
||||
memcpy(&pixel, fb->wall + (i + x * cell_width) * fb->bpp
|
||||
+ (offset + y * cell_height) * fb->line_length, fb->bpp);
|
||||
else
|
||||
pixel = fb->color_palette[color.bg];
|
||||
memcpy(src + i * fb->bpp, &pixel, fb->bpp);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_line_normal(struct framebuffer *fb, struct terminal *term, int y)
|
||||
{
|
||||
int offset, x, size, pos;
|
||||
char *src, *dst;
|
||||
|
||||
pos = (y * cell_height) * fb->line_length;
|
||||
size = fb->res.x * fb->bpp;
|
||||
|
||||
for (offset = 0; offset < cell_height; offset++) {
|
||||
for (x = 0; x < term->cols; x++)
|
||||
fb->set_bit(fb, term, y, x, offset,
|
||||
fb->buf + pos + x * cell_width * fb->bpp + offset * fb->line_length);
|
||||
src = fb->buf + pos + offset * fb->line_length;
|
||||
dst = fb->fp + pos + offset * fb->line_length;
|
||||
memcpy(dst, src, size);
|
||||
}
|
||||
term->line_dirty[y] = (term->mode & MODE_CURSOR && term->cursor.y == y) ? true: false;
|
||||
}
|
||||
|
||||
void draw_line_clockwise(struct framebuffer *fb, struct terminal *term, int line)
|
||||
{
|
||||
int y, pos, copy_size;
|
||||
char *src, *dst;
|
||||
|
||||
int col, glyph_width_offset, glyph_height_offset, glyph_width; //bits_per_glyph_width;
|
||||
uint32_t pixel;
|
||||
struct color_pair color;
|
||||
struct cell *cp;
|
||||
const struct static_glyph_t *gp;
|
||||
|
||||
/* calc address of framebuffer */
|
||||
/*
|
||||
terminal pos
|
||||
(fb->res.x, line * cell_height)
|
||||
framebuffer pos
|
||||
((line * cell_height), 0)
|
||||
*/
|
||||
pos = (line * cell_height) * fb->bpp;
|
||||
copy_size = cell_height * fb->bpp;
|
||||
|
||||
for (y = 0; y < fb->res.x; y++) {
|
||||
col = term->cols - 1 - (y / cell_width);
|
||||
for (glyph_height_offset = 0; glyph_height_offset < cell_height; glyph_height_offset++) {
|
||||
/* check cell */
|
||||
cp = &term->cells[col + line * term->cols];
|
||||
color = cp->color;
|
||||
if (cp->wide == NEXT_TO_WIDE)
|
||||
continue;
|
||||
|
||||
/* check glyph */
|
||||
gp = cp->gp;
|
||||
glyph_width = gp->width * cell_width; /* gp->width: 1 or 2 */
|
||||
//bits_per_glyph_width = my_ceil(glyph_width, BITS_PER_BYTE) * BITS_PER_BYTE;
|
||||
glyph_width_offset = (y / cell_width);
|
||||
|
||||
/* check cursor position */
|
||||
if ((term->mode & MODE_CURSOR && line == term->cursor.y)
|
||||
&& (col == term->cursor.x || (cp->wide == WIDE && (col + 1) == term->cursor.x))) {
|
||||
color.fg = DEFAULT_BG;
|
||||
color.bg = CURSOR_COLOR;
|
||||
}
|
||||
|
||||
/* set underline */
|
||||
if ((glyph_height_offset == (cell_height - 1)) && (cp->attribute & attr_mask[UNDERLINE]))
|
||||
color.bg = color.fg;
|
||||
|
||||
/* set color palette */
|
||||
if (gp->bitmap[glyph_height_offset] & (0x01 << glyph_width_offset))
|
||||
pixel = fb->color_palette[color.fg];
|
||||
else if (fb->wall && color.bg == DEFAULT_BG) /* wallpaper */
|
||||
memcpy(&pixel, fb->wall + (col * cell_width) * fb->bpp
|
||||
+ (glyph_height_offset + line * cell_height) * fb->line_length, fb->bpp);
|
||||
else
|
||||
pixel = fb->color_palette[color.bg];
|
||||
|
||||
memcpy(fb->buf + glyph_height_offset * fb->bpp + y * fb->line_length, &pixel, fb->bpp);
|
||||
}
|
||||
src = fb->buf + pos + y * fb->line_length;
|
||||
dst = fb->fp + pos + y * fb->line_length;
|
||||
memcpy(dst, src, copy_size);
|
||||
}
|
||||
}
|
||||
|
||||
void set_bit_upside_down(struct framebuffer *fb, struct terminal *term, int y, int x, int offset, char *src)
|
||||
{
|
||||
}
|
||||
|
||||
void draw_line_upside_down(struct framebuffer *fb, struct terminal *term, int y)
|
||||
{
|
||||
}
|
||||
|
||||
void set_bit_counter_clockwise(struct framebuffer *fb, struct terminal *term, int y, int x, int offset, char *src)
|
||||
{
|
||||
}
|
||||
|
||||
void draw_line_counter_clockwise(struct framebuffer *fb, struct terminal *term, int y)
|
||||
{
|
||||
}
|
||||
|
||||
void check_rotate(struct framebuffer *fb)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
if (ROTATE == CLOCKWISE || ROTATE == COUNTER_CLOCKWISE) {
|
||||
tmp = fb->res.x;
|
||||
fb->res.x = fb->res.y;
|
||||
fb->res.y = tmp;
|
||||
}
|
||||
|
||||
if (ROTATE == CLOCKWISE) {
|
||||
//fb->set_bit = set_bit_clockwise;
|
||||
fb->draw_line = draw_line_clockwise;
|
||||
}
|
||||
else if (ROTATE == UPSIDE_DOWN) {
|
||||
fb->set_bit = set_bit_upside_down;
|
||||
fb->draw_line = draw_line_upside_down;
|
||||
}
|
||||
else if (ROTATE == COUNTER_CLOCKWISE) {
|
||||
fb->set_bit = set_bit_counter_clockwise;
|
||||
fb->draw_line = draw_line_counter_clockwise;
|
||||
}
|
||||
else { /* rotate: NORMAL */
|
||||
fb->set_bit = set_bit_normal;
|
||||
fb->draw_line = draw_line_normal;
|
||||
}
|
||||
}
|
36
terminal.h
36
terminal.h
|
@ -7,7 +7,7 @@ void erase_cell(struct terminal *term, int y, int x)
|
|||
cp->gp = &fonts[DEFAULT_CHAR];
|
||||
cp->color = term->color; /* bce */
|
||||
cp->attribute = RESET;
|
||||
cp->wide = HALF;
|
||||
cp->width = HALF;
|
||||
|
||||
term->line_dirty[y] = true;
|
||||
}
|
||||
|
@ -19,15 +19,15 @@ void copy_cell(struct terminal *term, int dst_y, int dst_x, int src_y, int src_x
|
|||
dst = &term->cells[dst_x + dst_y * term->cols];
|
||||
src = &term->cells[src_x + src_y * term->cols];
|
||||
|
||||
if (src->wide == NEXT_TO_WIDE)
|
||||
if (src->width == NEXT_TO_WIDE)
|
||||
return;
|
||||
else if (src->wide == WIDE && dst_x == (term->cols - 1))
|
||||
else if (src->width == WIDE && dst_x == (term->cols - 1))
|
||||
erase_cell(term, dst_y, dst_x);
|
||||
else {
|
||||
*dst = *src;
|
||||
if (src->wide == WIDE) {
|
||||
if (src->width == WIDE) {
|
||||
*(dst + 1) = *src;
|
||||
(dst + 1)->wide = NEXT_TO_WIDE;
|
||||
(dst + 1)->width = NEXT_TO_WIDE;
|
||||
}
|
||||
term->line_dirty[dst_y] = true;
|
||||
}
|
||||
|
@ -57,15 +57,15 @@ int set_cell(struct terminal *term, int y, int x, const struct static_glyph_t *g
|
|||
swap_color(&nc.color);
|
||||
|
||||
nc.attribute = term->attribute;
|
||||
nc.wide = gp->width;
|
||||
nc.width = gp->width;
|
||||
|
||||
*cp = nc;
|
||||
term->line_dirty[y] = true;
|
||||
|
||||
if (nc.wide == WIDE && x + 1 < term->cols) {
|
||||
if (nc.width == WIDE && x + 1 < term->cols) {
|
||||
cp = &term->cells[x + 1 + y * term->cols];
|
||||
*cp = nc;
|
||||
cp->wide = NEXT_TO_WIDE;
|
||||
cp->width = NEXT_TO_WIDE;
|
||||
return WIDE;
|
||||
}
|
||||
|
||||
|
@ -224,6 +224,12 @@ bool push_esc(struct terminal *term, uint8_t ch)
|
|||
else if ((ch != ESC) && (' ' > ch || ch > '~'))
|
||||
reset_esc(term);
|
||||
}
|
||||
else if (term->esc.state == STATE_DCS) {
|
||||
if (ch == '{')
|
||||
return true;
|
||||
else if (ch != ';' && (ch < '0' || ch > '9'))
|
||||
reset_esc(term);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -278,7 +284,7 @@ void reset(struct terminal *term)
|
|||
reset_ucs(term);
|
||||
}
|
||||
|
||||
void swap(int *a, int *b)
|
||||
void swap_int(int *a, int *b)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
|
@ -287,18 +293,16 @@ void swap(int *a, int *b)
|
|||
*b = tmp;
|
||||
}
|
||||
|
||||
void term_init(struct terminal *term, struct pair res)
|
||||
void term_init(struct terminal *term, struct pair res, int rotate)
|
||||
{
|
||||
//term->offset.x = TERM_OFFSET_X;
|
||||
//term->offset.y = TERM_OFFSET_Y;
|
||||
term->width = res.x;
|
||||
term->height = res.y;
|
||||
|
||||
if (ROTATE == CLOCKWISE || ROTATE == COUNTER_CLOCKWISE)
|
||||
swap(&term->width, &term->height);
|
||||
if (rotate == CLOCKWISE || rotate == COUNTER_CLOCKWISE)
|
||||
swap_int(&term->width, &term->height);
|
||||
|
||||
term->cols = term->width / cell_width;
|
||||
term->lines = term->height / cell_height;
|
||||
term->cols = term->width / CELL_WIDTH;
|
||||
term->lines = term->height / CELL_HEIGHT;
|
||||
|
||||
if (DEBUG)
|
||||
fprintf(stderr, "width:%d height:%d cols:%d lines:%d\n",
|
||||
|
|
|
@ -138,8 +138,12 @@ void dump_fonts(struct glyph_t *fonts)
|
|||
"\tuint%d_t bitmap[%d];\n"
|
||||
"};\n\n", ((cell_width + BITS_PER_BYTE - 1) / BITS_PER_BYTE) * BITS_PER_BYTE * 2, cell_height);
|
||||
|
||||
/*
|
||||
fprintf(stdout, "static const uint8_t cell_width = %d, cell_height = %d;\n",
|
||||
cell_width, cell_height);
|
||||
*/
|
||||
fprintf(stdout, "enum {\n\tCELL_WIDTH = %d,\n\tCELL_HEIGHT = %d\n};\n\n",
|
||||
cell_width, cell_height);
|
||||
|
||||
fprintf(stdout, "static const struct static_glyph_t fonts[UCS2_CHARS] = {\n");
|
||||
for (i = 0; i < UCS2_CHARS; i++) {
|
||||
|
|
94
util.h
94
util.h
|
@ -1,4 +1,5 @@
|
|||
/* See LICENSE for licence details. */
|
||||
/* error functions */
|
||||
void error(char *str)
|
||||
{
|
||||
/* for DEBUG
|
||||
|
@ -18,6 +19,7 @@ void fatal(char *str)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* wrapper of C functions */
|
||||
int eopen(const char *path, int flag)
|
||||
{
|
||||
int fd;
|
||||
|
@ -99,7 +101,7 @@ void ewrite(int fd, void *buf, int size)
|
|||
void eforkpty(int *master, int lines, int cols)
|
||||
{
|
||||
int slave;
|
||||
char *name;
|
||||
char *name = NULL;
|
||||
pid_t pid;
|
||||
|
||||
if ((*master = posix_openpt(O_RDWR | O_NOCTTY)) < 0
|
||||
|
@ -149,3 +151,93 @@ void etcsetattr(int fd, int action, struct termios *tm)
|
|||
if (tcsetattr(fd, action, tm) < 0)
|
||||
error("tcgetattr");
|
||||
}
|
||||
|
||||
/* functions for framebuffer */
|
||||
char *load_wallpaper(struct framebuffer *fb)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = (char *) emalloc(fb->screen_size);
|
||||
memcpy(ptr, fb->fp, fb->screen_size);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void get_rgb(int i, struct color_t *color)
|
||||
{
|
||||
color->r = (color_list[i] >> 16) & bit_mask[8];
|
||||
color->g = (color_list[i] >> 8) & bit_mask[8];
|
||||
color->b = (color_list[i] >> 0) & bit_mask[8];
|
||||
}
|
||||
|
||||
uint32_t bit_reverse(uint32_t val, int bits)
|
||||
{
|
||||
uint32_t ret = val;
|
||||
int shift = bits - 1;
|
||||
|
||||
for (val >>= 1; val; val >>= 1) {
|
||||
ret <<= 1;
|
||||
ret |= val & 1;
|
||||
shift--;
|
||||
}
|
||||
|
||||
return ret <<= shift;
|
||||
}
|
||||
|
||||
/* parse arguments */
|
||||
void reset_parm(struct parm_t *pt)
|
||||
{
|
||||
int i;
|
||||
|
||||
pt->argc = 0;
|
||||
for (i = 0; i < ESC_PARAMS; i++)
|
||||
pt->argv[i] = NULL;
|
||||
}
|
||||
|
||||
void parse_arg(char *buf, struct parm_t *pt, int delim, int (is_valid)(int c))
|
||||
{
|
||||
int length;
|
||||
char *cp;
|
||||
|
||||
length = strlen(buf);
|
||||
cp = buf;
|
||||
|
||||
while (cp <= &buf[length - 1]) {
|
||||
if (*cp == delim)
|
||||
*cp = '\0';
|
||||
cp++;
|
||||
}
|
||||
|
||||
cp = buf;
|
||||
start:
|
||||
if (pt->argc < ESC_PARAMS && is_valid(*cp)) {
|
||||
pt->argv[pt->argc] = cp;
|
||||
pt->argc++;
|
||||
}
|
||||
|
||||
while (is_valid(*cp))
|
||||
cp++;
|
||||
|
||||
while (!is_valid(*cp) && cp <= &buf[length - 1])
|
||||
cp++;
|
||||
|
||||
if (cp <= &buf[length - 1])
|
||||
goto start;
|
||||
}
|
||||
|
||||
int isdigit_or_questionmark(int c)
|
||||
{
|
||||
if (isdigit(c) || c == '?')
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_osc_parm(int c)
|
||||
{
|
||||
if (isdigit(c) || isalpha(c) ||
|
||||
c == '?' || c == ':' || c == '/' || c == '#')
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
56
yaft.c
56
yaft.c
|
@ -1,18 +1,10 @@
|
|||
/* See LICENSE for licence details. */
|
||||
#include "common.h"
|
||||
#include "util.h"
|
||||
#include "framebuffer.h"
|
||||
#include "linux.h"
|
||||
//#include "freebsd.h"
|
||||
#include "terminal.h"
|
||||
#include "function.h"
|
||||
#include "parse.h"
|
||||
|
||||
struct tty_state tty = {
|
||||
.save_tm = NULL,
|
||||
.visible = true,
|
||||
.redraw_flag = false,
|
||||
.loop_flag = true,
|
||||
};
|
||||
|
||||
void handler(int signo)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
@ -25,7 +17,9 @@ void handler(int signo)
|
|||
ioctl(STDIN_FILENO, VT_RELDISP, 1);
|
||||
sigfillset(&sigset);
|
||||
sigdelset(&sigset, SIGUSR1);
|
||||
if (!BACKGROUND_DRAW)
|
||||
if (tty.background_draw)
|
||||
tty.redraw_flag = true;
|
||||
else
|
||||
sigsuspend(&sigset);
|
||||
}
|
||||
else {
|
||||
|
@ -51,11 +45,37 @@ void set_rawmode(int fd, struct termios *save_tm)
|
|||
etcsetattr(fd, TCSAFLUSH, &tm);
|
||||
}
|
||||
|
||||
void check_env(struct framebuffer *fb)
|
||||
{
|
||||
extern struct tty_state tty; /* global var */
|
||||
char *env;
|
||||
|
||||
if ((env = getenv("YAFT")) != NULL) {
|
||||
if (strstr(env, "wall") != NULL && fb->bpp > 1)
|
||||
fb->wall = load_wallpaper(fb);
|
||||
|
||||
if (strstr(env, "clockwise") != NULL || strstr(env, "cw") != NULL)
|
||||
fb->rotate = CLOCKWISE;
|
||||
else if (strstr(env, "upside_down") != NULL || strstr(env, "ud") != NULL)
|
||||
fb->rotate = UPSIDE_DOWN;
|
||||
else if (strstr(env, "counter_clockwise") != NULL || strstr(env, "ccw") != NULL)
|
||||
fb->rotate = COUNTER_CLOCKWISE;
|
||||
|
||||
if (strstr(env, "background") != NULL || strstr(env, "bg") != NULL)
|
||||
tty.background_draw = true;
|
||||
}
|
||||
else {
|
||||
fb->wall = NULL;
|
||||
fb->rotate = NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
void tty_init()
|
||||
{
|
||||
extern struct tty_state tty; /* global var */
|
||||
struct sigaction sigact;
|
||||
struct vt_mode vtm;
|
||||
char *env;
|
||||
|
||||
memset(&sigact, 0, sizeof(struct sigaction));
|
||||
sigact.sa_handler = handler;
|
||||
|
@ -74,6 +94,13 @@ void tty_init()
|
|||
tty.save_tm = (struct termios *) emalloc(sizeof(struct termios));
|
||||
set_rawmode(STDIN_FILENO, tty.save_tm);
|
||||
ewrite(STDIN_FILENO, "\033[?25l", 6); /* make cusor invisible */
|
||||
|
||||
if ((env = getenv("YAFT")) != NULL) {
|
||||
if (strstr(env, "background") != NULL)
|
||||
tty.background_draw = true;
|
||||
if (strstr(env, "lazy") != NULL)
|
||||
tty.lazy_draw = true;
|
||||
}
|
||||
}
|
||||
|
||||
void tty_die()
|
||||
|
@ -125,8 +152,9 @@ int main()
|
|||
fatal("atexit failed");
|
||||
|
||||
tty_init();
|
||||
fb_init(&fb);
|
||||
term_init(&term, fb.res);
|
||||
fb_init(&fb, term.color_palette);
|
||||
check_env(&fb);
|
||||
term_init(&term, fb.res, fb.rotate);
|
||||
|
||||
/* fork and exec shell */
|
||||
eforkpty(&term.fd, term.lines, term.cols);
|
||||
|
@ -151,7 +179,7 @@ int main()
|
|||
if (DEBUG)
|
||||
ewrite(STDOUT_FILENO, buf, size);
|
||||
parse(&term, buf, size);
|
||||
if (LAZY_DRAW && size == BUFSIZE)
|
||||
if (tty.lazy_draw && size == BUFSIZE)
|
||||
continue;
|
||||
refresh(&fb, &term);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue