mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-08-30 17:01:08 +02:00
yaft: convert into c++ class
Origin commit data
------------------
Branch: ni/coolstream
Commit: dbc9e6827b
Author: Stefan Seyfried <seife@tuxbox-git.slipkontur.de>
Date: 2018-01-24 (Wed, 24 Jan 2018)
------------------
No further description and justification available within origin commit message!
------------------
This commit was generated by Migit
This commit is contained in:
committed by
vanhofen
parent
609c17bfab
commit
7810c4556c
415
src/gui/widget/yaft/ctrlseq/csi.cpp
Normal file
415
src/gui/widget/yaft/ctrlseq/csi.cpp
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* yaft framebuffer terminal as C++ class for embedding in neutrino-MP
|
||||
* (C) 2018 Stefan Seyfried
|
||||
* License: GPL-2.0
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* derived from yaft/ctrlseq/csi.h
|
||||
* original code
|
||||
* Copyright (c) 2012 haru <uobikiemukot at gmail dot com>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the
|
||||
* following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*/
|
||||
#include "yaft_priv.h"
|
||||
#include <cstring>
|
||||
|
||||
/* function for csi sequence */
|
||||
void YaFT_p::insert_blank(struct parm_t *parm)
|
||||
{
|
||||
int i, num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
for (i = cols - 1; cursor.x <= i; i--) {
|
||||
if (cursor.x <= (i - num))
|
||||
copy_cell(cursor.y, i, cursor.y, i - num);
|
||||
else
|
||||
erase_cell(cursor.y, i);
|
||||
}
|
||||
}
|
||||
|
||||
void YaFT_p::curs_up(struct parm_t *parm)
|
||||
{
|
||||
int num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
move_cursor(-num, 0);
|
||||
}
|
||||
|
||||
void YaFT_p::curs_down(struct parm_t *parm)
|
||||
{
|
||||
int num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
move_cursor(num, 0);
|
||||
}
|
||||
|
||||
void YaFT_p::curs_forward(struct parm_t *parm)
|
||||
{
|
||||
int num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
move_cursor(0, num);
|
||||
}
|
||||
|
||||
void YaFT_p::curs_back(struct parm_t *parm)
|
||||
{
|
||||
int num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
move_cursor(0, -num);
|
||||
}
|
||||
|
||||
void YaFT_p::curs_nl(struct parm_t *parm)
|
||||
{
|
||||
int num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
move_cursor(num, 0);
|
||||
cr();
|
||||
}
|
||||
|
||||
void YaFT_p::curs_pl(struct parm_t *parm)
|
||||
{
|
||||
int num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
move_cursor(-num, 0);
|
||||
cr();
|
||||
}
|
||||
|
||||
void YaFT_p::curs_col(struct parm_t *parm)
|
||||
{
|
||||
int num;
|
||||
|
||||
num = (parm->argc <= 0) ? 0 : dec2num(parm->argv[parm->argc - 1]) - 1;
|
||||
set_cursor(cursor.y, num);
|
||||
}
|
||||
|
||||
void YaFT_p::curs_pos(struct parm_t *parm)
|
||||
{
|
||||
int line, col;
|
||||
|
||||
if (parm->argc <= 0) {
|
||||
line = col = 0;
|
||||
} else if (parm->argc == 2) {
|
||||
line = dec2num(parm->argv[0]) - 1;
|
||||
col = dec2num(parm->argv[1]) - 1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (line < 0)
|
||||
line = 0;
|
||||
if (col < 0)
|
||||
col = 0;
|
||||
|
||||
set_cursor(line, col);
|
||||
}
|
||||
|
||||
void YaFT_p::curs_line(struct parm_t *parm)
|
||||
{
|
||||
int num;
|
||||
|
||||
num = (parm->argc <= 0) ? 0 : dec2num(parm->argv[parm->argc - 1]) - 1;
|
||||
set_cursor(num, cursor.x);
|
||||
}
|
||||
|
||||
void YaFT_p::erase_display(struct parm_t *parm)
|
||||
{
|
||||
int i, j, pmode;
|
||||
|
||||
pmode = (parm->argc <= 0) ? 0 : dec2num(parm->argv[parm->argc - 1]);
|
||||
|
||||
if (pmode < 0 || 2 < pmode)
|
||||
return;
|
||||
|
||||
if (pmode == 0) {
|
||||
for (i = cursor.y; i < lines; i++)
|
||||
for (j = 0; j < cols; j++)
|
||||
if (i > cursor.y || (i == cursor.y && j >= cursor.x))
|
||||
erase_cell(i, j);
|
||||
} else if (pmode == 1) {
|
||||
for (i = 0; i <= cursor.y; i++)
|
||||
for (j = 0; j < cols; j++)
|
||||
if (i < cursor.y || (i == cursor.y && j <= cursor.x))
|
||||
erase_cell(i, j);
|
||||
} else if (pmode == 2) {
|
||||
for (i = 0; i < lines; i++)
|
||||
for (j = 0; j < cols; j++)
|
||||
erase_cell(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
void YaFT_p::erase_line(struct parm_t *parm)
|
||||
{
|
||||
int i, pmode;
|
||||
|
||||
pmode = (parm->argc <= 0) ? 0 : dec2num(parm->argv[parm->argc - 1]);
|
||||
|
||||
if (pmode < 0 || 2 < pmode)
|
||||
return;
|
||||
|
||||
if (pmode == 0) {
|
||||
for (i = cursor.x; i < cols; i++)
|
||||
erase_cell(cursor.y, i);
|
||||
} else if (pmode == 1) {
|
||||
for (i = 0; i <= cursor.x; i++)
|
||||
erase_cell(cursor.y, i);
|
||||
} else if (pmode == 2) {
|
||||
for (i = 0; i < cols; i++)
|
||||
erase_cell(cursor.y, i);
|
||||
}
|
||||
}
|
||||
|
||||
void YaFT_p::insert_line(struct parm_t *parm)
|
||||
{
|
||||
int num = sum(parm);
|
||||
|
||||
if (mode & MODE_ORIGIN) {
|
||||
if (cursor.y < scrollm.top
|
||||
|| cursor.y > scrollm.bottom)
|
||||
return;
|
||||
}
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
scroll(cursor.y, scrollm.bottom, -num);
|
||||
}
|
||||
|
||||
void YaFT_p::delete_line(struct parm_t *parm)
|
||||
{
|
||||
int num = sum(parm);
|
||||
|
||||
if (mode & MODE_ORIGIN) {
|
||||
if (cursor.y < scrollm.top
|
||||
|| cursor.y > scrollm.bottom)
|
||||
return;
|
||||
}
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
scroll(cursor.y, scrollm.bottom, num);
|
||||
}
|
||||
|
||||
void YaFT_p::delete_char(struct parm_t *parm)
|
||||
{
|
||||
int i, num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
|
||||
for (i = cursor.x; i < cols; i++) {
|
||||
if ((i + num) < cols)
|
||||
copy_cell(cursor.y, i, cursor.y, i + num);
|
||||
else
|
||||
erase_cell(cursor.y, i);
|
||||
}
|
||||
}
|
||||
|
||||
void YaFT_p::erase_char(struct parm_t *parm)
|
||||
{
|
||||
int i, num = sum(parm);
|
||||
|
||||
if (num <= 0)
|
||||
num = 1;
|
||||
else if (num + cursor.x > cols)
|
||||
num = cols - cursor.x;
|
||||
|
||||
for (i = cursor.x; i < cursor.x + num; i++)
|
||||
erase_cell(cursor.y, i);
|
||||
}
|
||||
|
||||
void YaFT_p::set_attr(struct parm_t *parm)
|
||||
{
|
||||
int i, num;
|
||||
|
||||
if (parm->argc <= 0) {
|
||||
attribute = ATTR_RESET;
|
||||
color_pair.fg = DEFAULT_FG;
|
||||
color_pair.bg = DEFAULT_BG;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < parm->argc; i++) {
|
||||
num = dec2num(parm->argv[i]);
|
||||
|
||||
if (num == 0) { /* reset all attribute and color */
|
||||
attribute = ATTR_RESET;
|
||||
color_pair.fg = DEFAULT_FG;
|
||||
color_pair.bg = DEFAULT_BG;
|
||||
} else if (1 <= num && num <= 7) { /* set attribute */
|
||||
attribute |= attr_mask[num];
|
||||
} else if (21 <= num && num <= 27) { /* reset attribute */
|
||||
attribute &= ~attr_mask[num - 20];
|
||||
} else if (30 <= num && num <= 37) { /* set foreground */
|
||||
color_pair.fg = (num - 30);
|
||||
} else if (num == 38) { /* set 256 color to foreground */
|
||||
if ((i + 2) < parm->argc && dec2num(parm->argv[i + 1]) == 5) {
|
||||
color_pair.fg = dec2num(parm->argv[i + 2]);
|
||||
i += 2;
|
||||
}
|
||||
} else if (num == 39) { /* reset foreground */
|
||||
color_pair.fg = DEFAULT_FG;
|
||||
} else if (40 <= num && num <= 47) { /* set background */
|
||||
color_pair.bg = (num - 40);
|
||||
} else if (num == 48) { /* set 256 color to background */
|
||||
if ((i + 2) < parm->argc && dec2num(parm->argv[i + 1]) == 5) {
|
||||
color_pair.bg = dec2num(parm->argv[i + 2]);
|
||||
i += 2;
|
||||
}
|
||||
} else if (num == 49) { /* reset background */
|
||||
color_pair.bg = DEFAULT_BG;
|
||||
} else if (90 <= num && num <= 97) { /* set bright foreground */
|
||||
color_pair.fg = (num - 90) + BRIGHT_INC;
|
||||
} else if (100 <= num && num <= 107) { /* set bright background */
|
||||
color_pair.bg = (num - 100) + BRIGHT_INC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void YaFT_p::status_report(struct parm_t *parm)
|
||||
{
|
||||
int i, num;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
for (i = 0; i < parm->argc; i++) {
|
||||
num = dec2num(parm->argv[i]);
|
||||
if (num == 5) { /* terminal response: ready */
|
||||
write(fd, "\033[0n", 4);
|
||||
} else if (num == 6) { /* cursor position report */
|
||||
snprintf(buf, BUFSIZE, "\033[%d;%dR", cursor.y + 1, cursor.x + 1);
|
||||
write(fd, buf, strlen(buf));
|
||||
} else if (num == 15) { /* terminal response: printer not connected */
|
||||
write(fd, "\033[?13n", 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void YaFT_p::device_attribute(struct parm_t *parm)
|
||||
{
|
||||
/* TODO: refer VT525 DA */
|
||||
(void) parm;
|
||||
write(fd, "\033[?6c", 5); /* "I am a VT102" */
|
||||
}
|
||||
|
||||
void YaFT_p::set_mode(struct parm_t *parm)
|
||||
{
|
||||
int i, pmode;
|
||||
|
||||
for (i = 0; i < parm->argc; i++) {
|
||||
pmode = dec2num(parm->argv[i]);
|
||||
if (esc.buf[1] != '?')
|
||||
continue; /* not supported */
|
||||
|
||||
if (pmode == 6) { /* private mode */
|
||||
mode |= MODE_ORIGIN;
|
||||
set_cursor(0, 0);
|
||||
} else if (pmode == 7) {
|
||||
mode |= MODE_AMRIGHT;
|
||||
} else if (pmode == 25) {
|
||||
mode |= MODE_CURSOR;
|
||||
} else if (pmode == 8901) {
|
||||
mode |= MODE_VWBS;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void YaFT_p::reset_mode(struct parm_t *parm)
|
||||
{
|
||||
int i, pmode;
|
||||
|
||||
for (i = 0; i < parm->argc; i++) {
|
||||
pmode = dec2num(parm->argv[i]);
|
||||
if (esc.buf[1] != '?')
|
||||
continue; /* not supported */
|
||||
|
||||
if (pmode == 6) { /* private mode */
|
||||
mode &= ~MODE_ORIGIN;
|
||||
set_cursor(0, 0);
|
||||
} else if (pmode == 7) {
|
||||
mode &= ~MODE_AMRIGHT;
|
||||
wrap_occured = false;
|
||||
} else if (pmode == 25) {
|
||||
mode &= ~MODE_CURSOR;
|
||||
} else if (pmode == 8901) {
|
||||
mode &= ~MODE_VWBS;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void YaFT_p::set_margin(struct parm_t *parm)
|
||||
{
|
||||
int top, bottom;
|
||||
|
||||
if (parm->argc <= 0) { /* CSI r */
|
||||
top = 0;
|
||||
bottom = lines - 1;
|
||||
} else if (parm->argc == 2) { /* CSI ; r -> use default value */
|
||||
top = parm->argv[0].empty() ? 0 : dec2num(parm->argv[0]) - 1;
|
||||
bottom = parm->argv[1].empty() ? lines - 1 : dec2num(parm->argv[1]) - 1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (top < 0 || top >= lines)
|
||||
top = 0;
|
||||
if (bottom < 0 || bottom >= lines)
|
||||
bottom = lines - 1;
|
||||
|
||||
if (top >= bottom)
|
||||
return;
|
||||
|
||||
scrollm.top = top;
|
||||
scrollm.bottom = bottom;
|
||||
|
||||
set_cursor(0, 0); /* move cursor to home */
|
||||
}
|
||||
|
||||
void YaFT_p::clear_tabstop(struct parm_t *parm)
|
||||
{
|
||||
int i, j, num;
|
||||
|
||||
if (parm->argc <= 0) {
|
||||
tabstop[cursor.x] = false;
|
||||
} else {
|
||||
for (i = 0; i < parm->argc; i++) {
|
||||
num = dec2num(parm->argv[i]);
|
||||
if (num == 0) {
|
||||
tabstop[cursor.x] = false;
|
||||
} else if (num == 3) {
|
||||
for (j = 0; j < cols; j++)
|
||||
tabstop[j] = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
127
src/gui/widget/yaft/ctrlseq/esc.cpp
Normal file
127
src/gui/widget/yaft/ctrlseq/esc.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* yaft framebuffer terminal as C++ class for embedding in neutrino-MP
|
||||
* (C) 2018 Stefan Seyfried
|
||||
* License: GPL-2.0
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* derived from yaft/ctrlseq/esc.h
|
||||
* original code
|
||||
* Copyright (c) 2012 haru <uobikiemukot at gmail dot com>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the
|
||||
* following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
#include "yaft_priv.h"
|
||||
|
||||
/* function for control character */
|
||||
void YaFT_p::bs(void)
|
||||
{
|
||||
if (mode & MODE_VWBS
|
||||
&& cursor.x - 1 >= 0
|
||||
&& cells[cursor.y][cursor.x - 1].width == NEXT_TO_WIDE)
|
||||
move_cursor(0, -2);
|
||||
else
|
||||
move_cursor(0, -1);
|
||||
}
|
||||
|
||||
void YaFT_p::tab(void)
|
||||
{
|
||||
int i;
|
||||
txt.back().append(" ");
|
||||
for (i = cursor.x + 1; i < cols; i++) {
|
||||
if (tabstop[i]) {
|
||||
set_cursor(cursor.y, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_cursor(cursor.y, cols - 1);
|
||||
}
|
||||
|
||||
void YaFT_p::nl(void)
|
||||
{
|
||||
nlseen = true;
|
||||
txt.push("");
|
||||
lines_available++;
|
||||
move_cursor(1, 0);
|
||||
}
|
||||
|
||||
void YaFT_p::cr(void)
|
||||
{
|
||||
set_cursor(cursor.y, 0);
|
||||
}
|
||||
|
||||
void YaFT_p::enter_esc(void)
|
||||
{
|
||||
esc.state = STATE_ESC;
|
||||
}
|
||||
|
||||
/* function for escape sequence */
|
||||
void YaFT_p::save_state(void)
|
||||
{
|
||||
state.mode = mode & MODE_ORIGIN;
|
||||
state.cursor = cursor;
|
||||
state.attribute = attribute;
|
||||
}
|
||||
|
||||
void YaFT_p::restore_state(void)
|
||||
{
|
||||
/* restore state */
|
||||
if (state.mode & MODE_ORIGIN)
|
||||
mode |= MODE_ORIGIN;
|
||||
else
|
||||
mode &= ~MODE_ORIGIN;
|
||||
cursor = state.cursor;
|
||||
attribute = state.attribute;
|
||||
}
|
||||
|
||||
void YaFT_p::crnl(void)
|
||||
{
|
||||
cr();
|
||||
nl();
|
||||
}
|
||||
|
||||
void YaFT_p::set_tabstop(void)
|
||||
{
|
||||
tabstop[cursor.x] = true;
|
||||
}
|
||||
|
||||
void YaFT_p::reverse_nl(void)
|
||||
{
|
||||
move_cursor(-1, 0);
|
||||
}
|
||||
|
||||
void YaFT_p::identify(void)
|
||||
{
|
||||
write(fd, "\033[?6c", 5); /* "I am a VT102" */
|
||||
}
|
||||
|
||||
void YaFT_p::enter_csi(void)
|
||||
{
|
||||
esc.state = STATE_CSI;
|
||||
}
|
||||
|
||||
void YaFT_p::enter_osc(void)
|
||||
{
|
||||
esc.state = STATE_OSC;
|
||||
}
|
||||
#if 0
|
||||
void YaFT_p::enter_dcs(void)
|
||||
{
|
||||
esc.state = STATE_DCS;
|
||||
}
|
||||
#endif
|
||||
void YaFT_p::ris(void)
|
||||
{
|
||||
reset();
|
||||
}
|
211
src/gui/widget/yaft/ctrlseq/osc.cpp
Normal file
211
src/gui/widget/yaft/ctrlseq/osc.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* yaft framebuffer terminal as C++ class for embedding in neutrino-MP
|
||||
* (C) 2018 Stefan Seyfried
|
||||
* License: GPL-2.0
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* derived from yaft/ctrlseq/osc.h,
|
||||
* original code
|
||||
* Copyright (c) 2012 haru <uobikiemukot at gmail dot com>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the
|
||||
* following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*/
|
||||
#include "yaft_priv.h"
|
||||
#include <cstring>
|
||||
|
||||
/* function for osc sequence */
|
||||
int32_t YaFT_p::parse_color1(std::string &seq)
|
||||
{
|
||||
/*
|
||||
format
|
||||
rgb:r/g/b
|
||||
rgb:rr/gg/bb
|
||||
rgb:rrr/ggg/bbb
|
||||
rgb:rrrr/gggg/bbbb
|
||||
*/
|
||||
int i, length, value;
|
||||
int32_t color;
|
||||
uint32_t rgb[3];
|
||||
struct parm_t parm;
|
||||
|
||||
reset_parm(&parm);
|
||||
parse_arg(seq, &parm, '/', isalnum);
|
||||
|
||||
for (i = 0; i < parm.argc; i++)
|
||||
logging(DEBUG, "parm.argv[%d]: %s\n", i, parm.argv[i].c_str());
|
||||
|
||||
if (parm.argc != 3)
|
||||
return -1;
|
||||
|
||||
length = parm.argv[0].length();
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
value = hex2num(parm.argv[i]);
|
||||
logging(DEBUG, "value:%d\n", value);
|
||||
|
||||
if (length == 1) /* r/g/b/ */
|
||||
rgb[i] = 0xFF & (value * 0xFF / 0x0F);
|
||||
else if (length == 2) /* rr/gg/bb */
|
||||
rgb[i] = 0xFF & value;
|
||||
else if (length == 3) /* rrr/ggg/bbb */
|
||||
rgb[i] = 0xFF & (value * 0xFF / 0xFFF);
|
||||
else if (length == 4) /* rrrr/gggg/bbbb */
|
||||
rgb[i] = 0xFF & (value * 0xFF / 0xFFFF);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
color = (rgb[0] << 16) + (rgb[1] << 8) + rgb[2];
|
||||
logging(DEBUG, "color:0x%.6X\n", color);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
int32_t YaFT_p::parse_color2(std::string &seq)
|
||||
{
|
||||
/*
|
||||
format
|
||||
#rgb
|
||||
#rrggbb
|
||||
#rrrgggbbb
|
||||
#rrrrggggbbbb
|
||||
*/
|
||||
int i, length;
|
||||
uint32_t rgb[3];
|
||||
int32_t color;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
length = seq.length();
|
||||
memset(buf, '\0', BUFSIZE);
|
||||
|
||||
if (length == 3) { /* rgb */
|
||||
for (i = 0; i < 3; i++) {
|
||||
rgb[i] = 0xFF & hex2num(seq.substr(i, 1)) * 0xFF / 0x0F;
|
||||
}
|
||||
} else if (length == 6) { /* rrggbb */
|
||||
for (i = 0; i < 3; i++) { /* rrggbb */
|
||||
//strncpy(buf, seq + i * 2, 2);
|
||||
rgb[i] = 0xFF & hex2num(seq.substr(i * 2, 2));
|
||||
}
|
||||
} else if (length == 9) { /* rrrgggbbb */
|
||||
for (i = 0; i < 3; i++) {
|
||||
//strncpy(buf, seq + i * 3, 3);
|
||||
rgb[i] = 0xFF & hex2num(seq.substr(i * 3, 3)) * 0xFF / 0xFFF;
|
||||
}
|
||||
} else if (length == 12) { /* rrrrggggbbbb */
|
||||
for (i = 0; i < 3; i++) {
|
||||
//strncpy(buf, seq + i * 4, 4);
|
||||
rgb[i] = 0xFF & hex2num(seq.substr(i * 4, 4)) * 0xFF / 0xFFFF;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
color = (rgb[0] << 16) + (rgb[1] << 8) + rgb[2];
|
||||
logging(DEBUG, "color:0x%.6X\n", color);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void YaFT_p::set_palette(struct parm_t *pt)
|
||||
{
|
||||
/*
|
||||
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
|
||||
|
||||
TODO: this function only works in 32bpp mode
|
||||
*/
|
||||
int i, argc = pt->argc, index;
|
||||
int32_t color;
|
||||
uint8_t rgb[3];
|
||||
std::string *argv = pt->argv;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
if (argc != 3)
|
||||
return;
|
||||
|
||||
index = dec2num(argv[1]);
|
||||
if (index < 0 || index >= COLORS)
|
||||
return;
|
||||
|
||||
if (argv[2].compare(0, 4, "rgb:") == 0) {
|
||||
std::string tmp = argv[2].substr(4); /* skip "rgb:" */
|
||||
if ((color = parse_color1(tmp)) != -1) {
|
||||
virtual_palette[index] = (uint32_t) color;
|
||||
palette_modified = true;
|
||||
}
|
||||
} else if (argv[2][0] == '#') {
|
||||
std::string tmp = argv[2].substr(1); /* skip "#" */
|
||||
if ((color = parse_color2(tmp)) != -1) {
|
||||
virtual_palette[index] = (uint32_t) color;
|
||||
palette_modified = true;
|
||||
}
|
||||
} else if (argv[2][0] == '?') {
|
||||
for (i = 0; i < 3; i++)
|
||||
rgb[i] = 0xFF & (virtual_palette[index] >> (8 * (2 - i)));
|
||||
|
||||
snprintf(buf, BUFSIZE, "\033]4;%d;rgb:%.2X/%.2X/%.2X\033\\",
|
||||
index, rgb[0], rgb[1], rgb[2]);
|
||||
write(fd, buf, strlen(buf));
|
||||
}
|
||||
}
|
||||
|
||||
void YaFT_p::reset_palette(struct parm_t *pt)
|
||||
{
|
||||
/*
|
||||
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\\
|
||||
*/
|
||||
int i, argc = pt->argc, c;
|
||||
std::string *argv = pt->argv;
|
||||
|
||||
if (argc < 2) { /* reset all color palette */
|
||||
for (i = 0; i < COLORS; i++)
|
||||
virtual_palette[i] = color_list[i];
|
||||
palette_modified = true;
|
||||
} else if (argc == 2) { /* reset color_palette[c] */
|
||||
c = dec2num(argv[1]);
|
||||
if (0 <= c && c < COLORS) {
|
||||
virtual_palette[c] = color_list[c];
|
||||
palette_modified = true;
|
||||
}
|
||||
}
|
||||
}
|
879
src/gui/widget/yaft/yaft_priv.cpp
Normal file
879
src/gui/widget/yaft/yaft_priv.cpp
Normal file
@@ -0,0 +1,879 @@
|
||||
/*
|
||||
* yaft framebuffer terminal as C++ class for embedding in neutrino-MP
|
||||
* (C) 2018 Stefan Seyfried
|
||||
* License: GPL-2.0
|
||||
*
|
||||
* this file contains the private YaFT_p class with "backend" functionality
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* derived from yaft https://github.com/uobikiemukot/yaft
|
||||
* original code
|
||||
* Copyright (c) 2012 haru <uobikiemukot at gmail dot com>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the
|
||||
* following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
#include "yaft_priv.h"
|
||||
#include "glyph.h"
|
||||
#include <driver/framebuffer.h>
|
||||
#include <driver/abstime.h>
|
||||
|
||||
/* parse_arg functions */
|
||||
void YaFT_p::reset_parm(parm_t *pt)
|
||||
{
|
||||
pt->argc = 0;
|
||||
for (int i = 0; i < MAX_ARGS; i++)
|
||||
pt->argv[i].clear();
|
||||
}
|
||||
|
||||
void add_parm(struct parm_t *pt, std::string cp)
|
||||
{
|
||||
if (pt->argc >= MAX_ARGS)
|
||||
return;
|
||||
|
||||
logging(DEBUG, "argv[%d]: %s\n", pt->argc, cp.c_str());
|
||||
|
||||
pt->argv[pt->argc] = cp;
|
||||
pt->argc++;
|
||||
}
|
||||
|
||||
void YaFT_p::parse_arg(std::string &buf, struct parm_t *pt, int delim, int (is_valid)(int c))
|
||||
{
|
||||
/*
|
||||
v..........v d v.....v d v.....v ... d
|
||||
(valid char) (delimiter)
|
||||
argv[0] argv[1] argv[2] ... argv[argc - 1]
|
||||
*/
|
||||
size_t length;
|
||||
size_t vp = std::string::npos;
|
||||
int c;
|
||||
|
||||
length = buf.length();
|
||||
logging(DEBUG, "parse_arg() length:%u\n", (unsigned) length);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
c = buf[i];
|
||||
|
||||
if (vp == std::string::npos && is_valid(c))
|
||||
vp = i;
|
||||
|
||||
if (c == delim) {
|
||||
add_parm(pt, buf.substr(vp, i - vp));
|
||||
vp = std::string::npos;
|
||||
}
|
||||
|
||||
if (i == (length - 1) && (vp != std::string::npos || c == 0))
|
||||
add_parm(pt, buf.substr(vp));
|
||||
}
|
||||
|
||||
logging(DEBUG, "argc:%d\n", pt->argc);
|
||||
}
|
||||
|
||||
/* constructor, Paint == false means "quiet mode, just execute
|
||||
* a command but don't display anything */
|
||||
YaFT_p::YaFT_p(bool Paint)
|
||||
{
|
||||
lines_available = 0;
|
||||
txt.push("");
|
||||
nlseen = false;
|
||||
paint = Paint;
|
||||
last_paint = 0;
|
||||
}
|
||||
|
||||
bool YaFT_p::init()
|
||||
{
|
||||
fb.cfb = CFrameBuffer::getInstance();
|
||||
fb.buf = (uint32_t *)fb.cfb->getBackBufferPointer();
|
||||
fb.width = fb.cfb->getScreenWidth();
|
||||
fb.height = fb.cfb->getScreenHeight();
|
||||
fb.xstart = fb.cfb->getScreenX();
|
||||
fb.ystart = fb.cfb->getScreenY();
|
||||
fb.line_length = width * sizeof(fb_pixel_t);
|
||||
fb.screen_size = fb.line_length * fb.height;
|
||||
fb.dy_min = fb.height;
|
||||
fb.dy_max = -1;
|
||||
screeninfo = fb.cfb->getScreenInfo();
|
||||
|
||||
return term_init(fb.width, fb.height);
|
||||
}
|
||||
|
||||
void YaFT_p::erase_cell(int y, int x)
|
||||
{
|
||||
struct cell_t *cellp;
|
||||
|
||||
cellp = &cells[y][x];
|
||||
cellp->glyphp = glyph[DEFAULT_CHAR];
|
||||
cellp->color_pair = color_pair; /* bce */
|
||||
cellp->attribute = ATTR_RESET;
|
||||
cellp->width = HALF;
|
||||
line_dirty[y] = true;
|
||||
}
|
||||
|
||||
void YaFT_p::copy_cell(int dst_y, int dst_x, int src_y, int src_x)
|
||||
{
|
||||
struct cell_t *dst, *src;
|
||||
|
||||
dst = &cells[dst_y][dst_x];
|
||||
src = &cells[src_y][src_x];
|
||||
|
||||
if (src->width == NEXT_TO_WIDE) {
|
||||
return;
|
||||
} else if (src->width == WIDE && dst_x == (cols - 1)) {
|
||||
erase_cell(dst_y, dst_x);
|
||||
} else {
|
||||
*dst = *src;
|
||||
if (src->width == WIDE) {
|
||||
dst = &cells[dst_y][dst_x + 1];
|
||||
*dst = *src;
|
||||
dst->width = NEXT_TO_WIDE;
|
||||
}
|
||||
line_dirty[dst_y] = true;
|
||||
}
|
||||
}
|
||||
|
||||
int YaFT_p::set_cell(int y, int x, const struct glyph_t *glyphp)
|
||||
{
|
||||
struct cell_t cell; //, *cellp;
|
||||
uint8_t color_tmp;
|
||||
|
||||
cell.glyphp = glyphp;
|
||||
|
||||
cell.color_pair.fg = (attribute & attr_mask[ATTR_BOLD] && color_pair.fg <= 7) ?
|
||||
color_pair.fg + BRIGHT_INC : color_pair.fg;
|
||||
cell.color_pair.bg = (attribute & attr_mask[ATTR_BLINK] && color_pair.bg <= 7) ?
|
||||
color_pair.bg + BRIGHT_INC : color_pair.bg;
|
||||
|
||||
if (attribute & attr_mask[ATTR_REVERSE]) {
|
||||
color_tmp = cell.color_pair.fg;
|
||||
cell.color_pair.fg = cell.color_pair.bg;
|
||||
cell.color_pair.bg = color_tmp;
|
||||
}
|
||||
|
||||
cell.attribute = attribute;
|
||||
cell.width = (glyph_width)glyphp->width;
|
||||
|
||||
cells[y][x] = cell;
|
||||
line_dirty[y] = true;
|
||||
|
||||
if (cell.width == WIDE && x + 1 < cols) {
|
||||
cell.width = NEXT_TO_WIDE;
|
||||
cells[y][x + 1] = cell;
|
||||
return WIDE;
|
||||
}
|
||||
|
||||
if (cell.width == HALF /* isolated NEXT_TO_WIDE cell */
|
||||
&& x + 1 < cols
|
||||
&& cells[y][x + 1].width == NEXT_TO_WIDE) {
|
||||
erase_cell(y, x + 1);
|
||||
}
|
||||
return HALF;
|
||||
}
|
||||
|
||||
void YaFT_p::swap_lines(int i, int j)
|
||||
{
|
||||
std::swap(cells[i], cells[j]);
|
||||
}
|
||||
|
||||
void YaFT_p::scroll(int from, int to, int offset)
|
||||
{
|
||||
int abs_offset, scroll_lines;
|
||||
|
||||
if (offset == 0 || from >= to)
|
||||
return;
|
||||
|
||||
logging(DEBUG, "scroll from:%d to:%d offset:%d\n", from, to, offset);
|
||||
|
||||
for (int y = from; y <= to; y++)
|
||||
line_dirty[y] = true;
|
||||
|
||||
abs_offset = abs(offset);
|
||||
scroll_lines = (to - from + 1) - abs_offset;
|
||||
|
||||
if (offset > 0) { /* scroll down */
|
||||
for (int y = from; y < from + scroll_lines; y++)
|
||||
swap_lines(y, y + offset);
|
||||
for (int y = (to - offset + 1); y <= to; y++)
|
||||
for (int x = 0; x < cols; x++)
|
||||
erase_cell(y, x);
|
||||
}
|
||||
else { /* scroll up */
|
||||
for (int y = to; y >= from + abs_offset; y--)
|
||||
swap_lines(y, y - abs_offset);
|
||||
for (int y = from; y < from + abs_offset; y++)
|
||||
for (int x = 0; x < cols; x++)
|
||||
erase_cell(y, x);
|
||||
}
|
||||
}
|
||||
|
||||
/* relative movement: cause scrolling */
|
||||
void YaFT_p::move_cursor(int y_offset, int x_offset)
|
||||
{
|
||||
int x, y, top, bottom;
|
||||
|
||||
x = cursor.x + x_offset;
|
||||
y = cursor.y + y_offset;
|
||||
|
||||
top = scrollm.top;
|
||||
bottom = scrollm.bottom;
|
||||
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
} else if (x >= cols) {
|
||||
if (mode & MODE_AMRIGHT)
|
||||
wrap_occured = true;
|
||||
x = cols - 1;
|
||||
}
|
||||
cursor.x = x;
|
||||
|
||||
y = (y < 0) ? 0:
|
||||
(y >= lines) ? lines - 1: y;
|
||||
|
||||
if (cursor.y == top && y_offset < 0) {
|
||||
y = top;
|
||||
scroll(top, bottom, y_offset);
|
||||
} else if (cursor.y == bottom && y_offset > 0) {
|
||||
y = bottom;
|
||||
scroll(top, bottom, y_offset);
|
||||
}
|
||||
cursor.y = y;
|
||||
|
||||
if (y_offset > 0 && !nlseen) {
|
||||
txt.push("");
|
||||
lines_available++;
|
||||
}
|
||||
}
|
||||
|
||||
/* absolute movement: never scroll */
|
||||
void YaFT_p::set_cursor(int y, int x)
|
||||
{
|
||||
int top, bottom;
|
||||
|
||||
if (mode & MODE_ORIGIN) {
|
||||
top = scrollm.top;
|
||||
bottom = scrollm.bottom;
|
||||
y += scrollm.top;
|
||||
} else {
|
||||
top = 0;
|
||||
bottom = lines - 1;
|
||||
}
|
||||
|
||||
x = (x < 0) ? 0: (x >= cols) ? cols - 1: x;
|
||||
y = (y < top) ? top: (y > bottom) ? bottom: y;
|
||||
|
||||
if (cursor.y != y && !nlseen) {
|
||||
txt.push("");
|
||||
lines_available++;
|
||||
}
|
||||
|
||||
cursor.x = x;
|
||||
cursor.y = y;
|
||||
wrap_occured = false;
|
||||
}
|
||||
|
||||
void YaFT_p::addch(uint32_t code)
|
||||
{
|
||||
int _width;
|
||||
const struct glyph_t *glyphp;
|
||||
|
||||
logging(DEBUG, "addch: U+%.4X\n", code);
|
||||
|
||||
_width = wcwidth(code);
|
||||
|
||||
if (code <= 0xff) { /* non-ascii not supported */
|
||||
char c = (char)code;
|
||||
txt.back().push_back(c);
|
||||
}
|
||||
if (_width <= 0) /* zero width: not support comibining character */
|
||||
return;
|
||||
else if (0x100000 <= code && code <= 0x10FFFD) /* unicode private area: plane 16 (DRCSMMv1) */
|
||||
glyphp = glyph[SUBSTITUTE_HALF];
|
||||
else if (code >= UCS2_CHARS /* yaft support only UCS2 */
|
||||
|| glyph[code] == NULL /* missing glyph */
|
||||
|| glyph[code]->width != _width) /* width unmatch */
|
||||
glyphp = (_width == 1) ? glyph[SUBSTITUTE_HALF] : glyph[SUBSTITUTE_WIDE];
|
||||
else
|
||||
glyphp = glyph[code];
|
||||
|
||||
if ((wrap_occured && cursor.x == cols - 1) /* folding */
|
||||
|| (glyphp->width == WIDE && cursor.x == cols - 1)) {
|
||||
set_cursor(cursor.y, 0);
|
||||
move_cursor(1, 0);
|
||||
}
|
||||
wrap_occured = false;
|
||||
|
||||
move_cursor(0, set_cell(cursor.y, cursor.x, glyphp));
|
||||
}
|
||||
|
||||
void YaFT_p::reset_esc(void)
|
||||
{
|
||||
logging(DEBUG, "*esc reset*\n");
|
||||
|
||||
esc.buf.clear();
|
||||
esc.bp = 0;
|
||||
esc.state = STATE_RESET;
|
||||
}
|
||||
|
||||
bool YaFT_p::push_esc(uint8_t ch)
|
||||
{
|
||||
/* ref: http://www.vt100.net/docs/vt102-ug/appendixd.html */
|
||||
esc.bp++;
|
||||
esc.buf.push_back(ch);
|
||||
if (esc.state == STATE_ESC) {
|
||||
/* format:
|
||||
ESC I.......I F
|
||||
' ' '/' '0' '~'
|
||||
0x1B 0x20-0x2F 0x30-0x7E
|
||||
*/
|
||||
if ('0' <= ch && ch <= '~') /* final char */
|
||||
return true;
|
||||
else if (SPACE <= ch && ch <= '/') /* intermediate char */
|
||||
return false;
|
||||
} else if (esc.state == STATE_CSI) {
|
||||
/* format:
|
||||
CSI P.......P I.......I F
|
||||
ESC '[' '0' '?' ' ' '/' '@' '~'
|
||||
0x1B 0x5B 0x30-0x3F 0x20-0x2F 0x40-0x7E
|
||||
*/
|
||||
if ('@' <= ch && ch <= '~')
|
||||
return true;
|
||||
else if (SPACE <= ch && ch <= '?')
|
||||
return false;
|
||||
} else {
|
||||
/* format:
|
||||
OSC I.....I F
|
||||
ESC ']' BEL or ESC '\'
|
||||
0x1B 0x5D unknown 0x07 or 0x1B 0x5C
|
||||
DCS I....I F
|
||||
ESC 'P' BEL or ESC '\'
|
||||
0x1B 0x50 unknown 0x07 or 0x1B 0x5C
|
||||
*/
|
||||
if (ch == BEL || (ch == BACKSLASH
|
||||
&& esc.bp >= 2 && esc.buf[esc.bp-2] == ESC))
|
||||
return true;
|
||||
else if ((ch == ESC || ch == CR || ch == LF || ch == BS || ch == HT)
|
||||
|| (SPACE <= ch && ch <= '~'))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* invalid sequence */
|
||||
reset_esc();
|
||||
return false;
|
||||
}
|
||||
|
||||
void YaFT_p::reset_charset(void)
|
||||
{
|
||||
charset.code = charset.count = charset.following_byte = 0;
|
||||
charset.is_valid = true;
|
||||
}
|
||||
|
||||
void YaFT_p::reset(void)
|
||||
{
|
||||
mode = MODE_RESET;
|
||||
mode |= MODE_AMRIGHT; //(MODE_CURSOR | MODE_AMRIGHT);
|
||||
wrap_occured = false;
|
||||
|
||||
scrollm.top = 0;
|
||||
scrollm.bottom = lines - 1;
|
||||
|
||||
cursor.x = cursor.y = 0;
|
||||
|
||||
state.mode = mode;
|
||||
state.cursor = cursor;
|
||||
state.attribute = ATTR_RESET;
|
||||
|
||||
color_pair.fg = DEFAULT_FG;
|
||||
color_pair.bg = DEFAULT_BG;
|
||||
|
||||
attribute = ATTR_RESET;
|
||||
|
||||
for (int line = 0; line < lines; line++) {
|
||||
for (int col = 0; col < cols; col++) {
|
||||
erase_cell(line, col);
|
||||
if ((col % TABSTOP) == 0)
|
||||
tabstop[col] = true;
|
||||
else
|
||||
tabstop[col] = false;
|
||||
}
|
||||
line_dirty[line] = true;
|
||||
}
|
||||
|
||||
reset_esc();
|
||||
reset_charset();
|
||||
}
|
||||
|
||||
void YaFT_p::term_die(void)
|
||||
{
|
||||
line_dirty.clear();
|
||||
tabstop.clear();
|
||||
esc.buf.clear();
|
||||
cells.clear();
|
||||
}
|
||||
|
||||
bool YaFT_p::term_init(int w, int h)
|
||||
{
|
||||
const glyph_t *_glyphs;
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
int j = 0;
|
||||
do {
|
||||
_glyphs = glyphs[j];
|
||||
CELL_WIDTH = _glyphs[0].code;
|
||||
CELL_HEIGHT = _glyphs[0].width;
|
||||
cols = width / CELL_WIDTH;
|
||||
if (cols > 79)
|
||||
break;
|
||||
j++;
|
||||
} while (glyphs[j]);
|
||||
|
||||
lines = height / CELL_HEIGHT;
|
||||
|
||||
logging(NORMAL, "terminal cols:%d lines:%d\n", cols, lines);
|
||||
|
||||
/* allocate memory */
|
||||
line_dirty.reserve(lines);
|
||||
tabstop.reserve(cols);
|
||||
esc.buf.reserve(1024);
|
||||
|
||||
cells.clear();
|
||||
std::vector<cell_t> line;
|
||||
line.resize(cols);
|
||||
for (int i = 0; i < lines; i++)
|
||||
cells.push_back(line);
|
||||
line.resize(0);
|
||||
|
||||
/* initialize palette */
|
||||
for (int i = 0; i < COLORS; i++)
|
||||
virtual_palette[i] = color_list[i];
|
||||
palette_modified = true; /* first refresh() will initialize real_palette[] */
|
||||
|
||||
/* initialize glyph map */
|
||||
for (uint32_t code = 0; code < UCS2_CHARS; code++)
|
||||
glyph[code] = NULL;
|
||||
|
||||
for (uint32_t gi = 1; _glyphs[gi].code > 0; gi++)
|
||||
glyph[_glyphs[gi].code] = &_glyphs[gi];
|
||||
|
||||
if (!glyph[DEFAULT_CHAR]
|
||||
|| !glyph[SUBSTITUTE_HALF]
|
||||
|| !glyph[SUBSTITUTE_WIDE]) {
|
||||
logging(NORMAL, "couldn't find essential glyph:\
|
||||
DEFAULT_CHAR(U+%.4X):%p SUBSTITUTE_HALF(U+%.4X):%p SUBSTITUTE_WIDE(U+%.4X):%p\n",
|
||||
DEFAULT_CHAR, glyph[DEFAULT_CHAR],
|
||||
SUBSTITUTE_HALF, glyph[SUBSTITUTE_HALF],
|
||||
SUBSTITUTE_WIDE, glyph[SUBSTITUTE_WIDE]);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* reset terminal */
|
||||
reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void YaFT_p::parse(uint8_t *buf, int size)
|
||||
{
|
||||
/*
|
||||
CTRL CHARS : 0x00 ~ 0x1F
|
||||
ASCII(printable): 0x20 ~ 0x7E
|
||||
CTRL CHARS(DEL) : 0x7F
|
||||
UTF-8 : 0x80 ~ 0xFF
|
||||
*/
|
||||
uint8_t ch;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
ch = buf[i];
|
||||
if (esc.state == STATE_RESET) {
|
||||
/* interrupted by illegal byte */
|
||||
if (charset.following_byte > 0 && (ch < 0x80 || ch > 0xBF)) {
|
||||
addch(REPLACEMENT_CHAR);
|
||||
reset_charset();
|
||||
}
|
||||
|
||||
if (ch <= 0x1F)
|
||||
control_character(ch);
|
||||
else if (ch <= 0x7F)
|
||||
addch(ch);
|
||||
else
|
||||
utf8_charset(ch);
|
||||
} else if (esc.state == STATE_ESC) {
|
||||
if (push_esc(ch))
|
||||
esc_sequence(ch);
|
||||
} else if (esc.state == STATE_CSI) {
|
||||
if (push_esc(ch))
|
||||
csi_sequence(ch);
|
||||
} else if (esc.state == STATE_OSC) {
|
||||
if (push_esc(ch))
|
||||
osc_sequence(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ctr char/esc sequence/charset function */
|
||||
void YaFT_p::control_character(uint8_t ch)
|
||||
{
|
||||
static const char *ctrl_char[] = {
|
||||
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
|
||||
"BS ", "HT ", "LF ", "VT ", "FF ", "CR ", "SO ", "SI ",
|
||||
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
|
||||
"CAN", "EM ", "SUB", "ESC", "FS ", "GS ", "RS ", "US ",
|
||||
};
|
||||
|
||||
logging(DEBUG, "ctl: %s\n", ctrl_char[ch]);
|
||||
|
||||
switch(ch) {
|
||||
case BS: bs(); break;
|
||||
case HT: tab(); break;
|
||||
case LF: nl(); break;
|
||||
case VT: nl(); break;
|
||||
case FF: nl(); break;
|
||||
case CR: cr(); break;
|
||||
case ESC: enter_esc(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void YaFT_p::esc_sequence(uint8_t ch)
|
||||
{
|
||||
logging(DEBUG, "esc: ESC %s\n", esc.buf.c_str());
|
||||
|
||||
if (esc.bp == 1)
|
||||
{
|
||||
switch(ch) {
|
||||
case '7': save_state(); break;
|
||||
case '8': restore_state(); break;
|
||||
case 'D': nl(); break;
|
||||
case 'E': crnl(); break;
|
||||
case 'H': set_tabstop(); break;
|
||||
case 'M': reverse_nl(); break;
|
||||
case 'Z': identify(); break;
|
||||
case '[': enter_csi(); break;
|
||||
case ']': enter_osc(); break;
|
||||
case 'c': ris(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/* not reset if csi/osc/dcs seqence */
|
||||
if (ch == '[' || ch == ']' || ch == 'P')
|
||||
return;
|
||||
|
||||
reset_esc();
|
||||
}
|
||||
|
||||
void YaFT_p::csi_sequence(uint8_t ch)
|
||||
{
|
||||
struct parm_t parm;
|
||||
|
||||
esc.buf.resize(esc.bp - 1);
|
||||
std::string csi = esc.buf.substr(1);
|
||||
logging(DEBUG, "csi: CSI %s\n", csi.c_str());
|
||||
|
||||
reset_parm(&parm);
|
||||
parse_arg(csi, &parm, ';', isdigit); /* skip '[' */
|
||||
|
||||
switch (ch) {
|
||||
case '@': insert_blank(&parm); break;
|
||||
case 'A': curs_up(&parm); break;
|
||||
case 'B': curs_down(&parm); break;
|
||||
case 'C': curs_forward(&parm); break;
|
||||
case 'D': curs_back(&parm); break;
|
||||
case 'E': curs_nl(&parm); break;
|
||||
case 'F': curs_pl(&parm); break;
|
||||
case 'G': curs_col(&parm); break;
|
||||
case 'H': curs_pos(&parm); break;
|
||||
case 'J': erase_display(&parm); break;
|
||||
case 'K': erase_line(&parm); break;
|
||||
case 'L': insert_line(&parm); break;
|
||||
case 'M': delete_line(&parm); break;
|
||||
case 'P': delete_char(&parm); break;
|
||||
case 'X': erase_char(&parm); break;
|
||||
case 'a': curs_forward(&parm); break;
|
||||
case 'c': device_attribute(&parm);break;
|
||||
case 'd': curs_line(&parm); break;
|
||||
case 'e': curs_down(&parm); break;
|
||||
case 'f': curs_pos(&parm); break;
|
||||
case 'g': clear_tabstop(&parm); break;
|
||||
case 'h': set_mode(&parm); break;
|
||||
case 'l': reset_mode(&parm); break;
|
||||
case 'm': set_attr(&parm); break;
|
||||
case 'n': status_report(&parm); break;
|
||||
case 'r': set_margin(&parm); break;
|
||||
/* XXX: not implemented because these sequences conflict DECSLRM/DECSHTS
|
||||
case 's': sco_save_state(&parm);break;
|
||||
case 'u': sco_restore_state(&parm); break;
|
||||
*/
|
||||
case '`': curs_col(&parm); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
reset_esc();
|
||||
}
|
||||
|
||||
static int is_osc_parm(int c)
|
||||
{
|
||||
if (isdigit(c) || isalpha(c) ||
|
||||
c == '?' || c == ':' || c == '/' || c == '#')
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void omit_string_terminator(char *bp, uint8_t ch)
|
||||
{
|
||||
if (ch == BACKSLASH) /* ST: ESC BACKSLASH */
|
||||
*(bp - 2) = '\0';
|
||||
else /* ST: BEL */
|
||||
*(bp - 1) = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
void YaFT_p::osc_sequence(uint8_t ch)
|
||||
{
|
||||
int osc_mode;
|
||||
struct parm_t parm;
|
||||
|
||||
if (ch == BACKSLASH) /* ST: ESC BACKSLASH */
|
||||
esc.buf.resize(esc.bp - 2);
|
||||
else /* ST: BEL */
|
||||
esc.buf.resize(esc.bp - 1);
|
||||
// omit_string_terminator(esc.bp, ch);
|
||||
|
||||
logging(DEBUG, "osc: OSC %s\n", esc.buf.c_str());
|
||||
|
||||
std::string osc = esc.buf.substr(1);
|
||||
reset_parm(&parm);
|
||||
parse_arg(osc, &parm, ';', is_osc_parm); /* skip ']' */
|
||||
|
||||
if (parm.argc > 0) {
|
||||
osc_mode = dec2num(parm.argv[0]);
|
||||
logging(DEBUG, "osc_mode:%d\n", osc_mode);
|
||||
|
||||
/* XXX: disable because this functions only work 24/32bpp
|
||||
-> support other bpp (including pseudo color) */
|
||||
if (osc_mode == 4)
|
||||
set_palette(&parm);
|
||||
else if (osc_mode == 104)
|
||||
reset_palette(&parm);
|
||||
#if 0
|
||||
if (osc_mode == 8900)
|
||||
glyph_width_report(&parm);
|
||||
#endif
|
||||
}
|
||||
reset_esc();
|
||||
}
|
||||
|
||||
void YaFT_p::utf8_charset(uint8_t ch)
|
||||
{
|
||||
if (0x80 <= ch && ch <= 0xBF) {
|
||||
/* check illegal UTF-8 sequence
|
||||
* ? byte sequence: first byte must be between 0xC2 ~ 0xFD
|
||||
* 2 byte sequence: first byte must be between 0xC2 ~ 0xDF
|
||||
* 3 byte sequence: second byte following 0xE0 must be between 0xA0 ~ 0xBF
|
||||
* 4 byte sequence: second byte following 0xF0 must be between 0x90 ~ 0xBF
|
||||
* 5 byte sequence: second byte following 0xF8 must be between 0x88 ~ 0xBF
|
||||
* 6 byte sequence: second byte following 0xFC must be between 0x84 ~ 0xBF
|
||||
*/
|
||||
if ((charset.following_byte == 0)
|
||||
|| (charset.following_byte == 1 && charset.count == 0 && charset.code <= 1)
|
||||
|| (charset.following_byte == 2 && charset.count == 0 && charset.code == 0 && ch < 0xA0)
|
||||
|| (charset.following_byte == 3 && charset.count == 0 && charset.code == 0 && ch < 0x90)
|
||||
|| (charset.following_byte == 4 && charset.count == 0 && charset.code == 0 && ch < 0x88)
|
||||
|| (charset.following_byte == 5 && charset.count == 0 && charset.code == 0 && ch < 0x84))
|
||||
charset.is_valid = false;
|
||||
|
||||
charset.code <<= 6;
|
||||
charset.code += ch & 0x3F;
|
||||
charset.count++;
|
||||
} else if (0xC0 <= ch && ch <= 0xDF) {
|
||||
charset.code = ch & 0x1F;
|
||||
charset.following_byte = 1;
|
||||
charset.count = 0;
|
||||
return;
|
||||
} else if (0xE0 <= ch && ch <= 0xEF) {
|
||||
charset.code = ch & 0x0F;
|
||||
charset.following_byte = 2;
|
||||
charset.count = 0;
|
||||
return;
|
||||
} else if (0xF0 <= ch && ch <= 0xF7) {
|
||||
charset.code = ch & 0x07;
|
||||
charset.following_byte = 3;
|
||||
charset.count = 0;
|
||||
return;
|
||||
} else if (0xF8 <= ch && ch <= 0xFB) {
|
||||
charset.code = ch & 0x03;
|
||||
charset.following_byte = 4;
|
||||
charset.count = 0;
|
||||
return;
|
||||
} else if (0xFC <= ch && ch <= 0xFD) {
|
||||
charset.code = ch & 0x01;
|
||||
charset.following_byte = 5;
|
||||
charset.count = 0;
|
||||
return;
|
||||
} else { /* 0xFE - 0xFF: not used in UTF-8 */
|
||||
addch(REPLACEMENT_CHAR);
|
||||
reset_charset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (charset.count >= charset.following_byte) {
|
||||
/* illegal code point (ref: http://www.unicode.org/reports/tr27/tr27-4.html)
|
||||
0xD800 ~ 0xDFFF : surrogate pair
|
||||
0xFDD0 ~ 0xFDEF : noncharacter
|
||||
0xnFFFE ~ 0xnFFFF: noncharacter (n: 0x00 ~ 0x10)
|
||||
0x110000 ~ : invalid (unicode U+0000 ~ U+10FFFF)
|
||||
*/
|
||||
if (!charset.is_valid
|
||||
|| (0xD800 <= charset.code && charset.code <= 0xDFFF)
|
||||
|| (0xFDD0 <= charset.code && charset.code <= 0xFDEF)
|
||||
|| ((charset.code & 0xFFFF) == 0xFFFE || (charset.code & 0xFFFF) == 0xFFFF)
|
||||
|| (charset.code > 0x10FFFF))
|
||||
addch(REPLACEMENT_CHAR);
|
||||
else
|
||||
addch(charset.code);
|
||||
|
||||
reset_charset();
|
||||
}
|
||||
}
|
||||
|
||||
int YaFT_p::sum(struct parm_t *parm)
|
||||
{
|
||||
int s = 0;
|
||||
for (int i = 0; i < parm->argc; i++)
|
||||
s += dec2num(parm->argv[i]);
|
||||
return s;
|
||||
}
|
||||
|
||||
static int my_ceil(int val, int div)
|
||||
{
|
||||
if (div == 0)
|
||||
return 0;
|
||||
else
|
||||
return (val + div - 1) / div;
|
||||
}
|
||||
|
||||
void YaFT_p::draw_line(int line)
|
||||
{
|
||||
int pos, bdf_padding, glyph_w, margin_right;
|
||||
int col, w, h;
|
||||
uint32_t pixel;
|
||||
struct color_pair_t col_pair;
|
||||
struct cell_t *cellp;
|
||||
|
||||
if (fb.dy_min > line * CELL_HEIGHT)
|
||||
fb.dy_min = line * CELL_HEIGHT;
|
||||
if (fb.dy_max < (line+1) * CELL_HEIGHT - 1)
|
||||
fb.dy_max = (line+1) * CELL_HEIGHT - 1;
|
||||
|
||||
//std::string s = "";
|
||||
for (col = cols - 1; col >= 0; col--) {
|
||||
margin_right = (cols - 1 - col) * CELL_WIDTH;
|
||||
|
||||
/* target cell */
|
||||
cellp = &cells[line][col];
|
||||
|
||||
/* copy current color_pair (maybe changed) */
|
||||
col_pair = cellp->color_pair;
|
||||
|
||||
/* check wide character or not */
|
||||
glyph_w = (cellp->width == HALF) ? CELL_WIDTH: CELL_WIDTH * 2;
|
||||
bdf_padding = my_ceil(glyph_w, BITS_PER_BYTE) * BITS_PER_BYTE - glyph_w;
|
||||
if (cellp->width == WIDE)
|
||||
bdf_padding += CELL_WIDTH;
|
||||
|
||||
/* check cursor positon */
|
||||
if ((mode & MODE_CURSOR && line == cursor.y)
|
||||
&& (col == cursor.x
|
||||
|| (cellp->width == WIDE && (col + 1) == cursor.x)
|
||||
|| (cellp->width == NEXT_TO_WIDE && (col - 1) == cursor.x))) {
|
||||
col_pair.fg = DEFAULT_BG;
|
||||
col_pair.bg = ACTIVE_CURSOR_COLOR;
|
||||
}
|
||||
|
||||
for (h = 0; h < CELL_HEIGHT; h++) {
|
||||
/* if UNDERLINE attribute on, swap bg/fg */
|
||||
if ((h == (CELL_HEIGHT - 1)) && (cellp->attribute & attr_mask[ATTR_UNDERLINE]))
|
||||
col_pair.bg = col_pair.fg;
|
||||
|
||||
pos = (width - 1 - margin_right/* - w*/)
|
||||
+ (line * CELL_HEIGHT + h) * fb.width;
|
||||
|
||||
for (w = 0; w < CELL_WIDTH; w++) {
|
||||
/* set color palette */
|
||||
if (cellp->glyphp->bitmap[h] & (0x01 << (bdf_padding + w)))
|
||||
pixel = fb.real_palette[col_pair.fg];
|
||||
else
|
||||
pixel = fb.real_palette[col_pair.bg];
|
||||
|
||||
/* update copy buffer only */
|
||||
//memcpy(fb.buf + pos, &pixel, fb.info.bytes_per_pixel);
|
||||
fb.buf[pos] = pixel;
|
||||
pos--;
|
||||
}
|
||||
}
|
||||
//s.insert(s.begin(), cellp->glyphp->code);
|
||||
}
|
||||
//printf("draw_line: %02d ", line);puts(s.c_str());
|
||||
|
||||
line_dirty[line] = ((mode & MODE_CURSOR) && cursor.y == line) ? true: false;
|
||||
}
|
||||
|
||||
static inline int color2pixel(uint32_t color, struct fb_var_screeninfo *var)
|
||||
{
|
||||
uint32_t r, g, b;
|
||||
r = (color >> 16) & 0x000000ff;
|
||||
g = (color >> 8) & 0x000000ff;
|
||||
b = (color >> 0) & 0x000000ff;
|
||||
return (0xff << var->transp.offset) |
|
||||
(r << var->red.offset) |
|
||||
(g << var->green.offset) |
|
||||
(b << var->blue.offset);
|
||||
}
|
||||
|
||||
/* actually update the framebuffer contents */
|
||||
void YaFT_p::refresh()
|
||||
{
|
||||
if (! paint)
|
||||
return;
|
||||
|
||||
if (palette_modified) {
|
||||
palette_modified = false;
|
||||
for (int i = 0; i < COLORS; i++)
|
||||
fb.real_palette[i] = color2pixel(virtual_palette[i], screeninfo);
|
||||
}
|
||||
|
||||
logging(DEBUG,"%s: mode %x cur: %x cursor.y %d\n", __func__, mode, MODE_CURSOR, cursor.y);
|
||||
if (mode & MODE_CURSOR)
|
||||
line_dirty[cursor.y] = true;
|
||||
|
||||
for (int line = 0; line < lines; line++) {
|
||||
if (line_dirty[line]) {
|
||||
draw_line(line);
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
if (fb.dy_max != -1) {
|
||||
int blit_height = fb.dy_max - fb.dy_min;
|
||||
uint32_t *blit_start = fb.buf + (fb.dy_min * fb.width);
|
||||
fb.cfb->blit2FB(blit_start, fb.width, blit_height, fb.xstart, fb.ystart+fb.dy_min, 0, 0);
|
||||
}
|
||||
#else
|
||||
fb.cfb->blit2FB(fb.buf, fb.width, fb.height, fb.xstart, fb.ystart, 0, 0);
|
||||
#endif
|
||||
fb.dy_min = fb.height;
|
||||
fb.dy_max = -1;
|
||||
last_paint = time_monotonic_ms();
|
||||
}
|
260
src/gui/widget/yaft/yaft_priv.h
Normal file
260
src/gui/widget/yaft/yaft_priv.h
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* yaft framebuffer terminal as C++ class for embedding in neutrino-MP
|
||||
* (C) 2018 Stefan Seyfried
|
||||
* License: GPL-2.0
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* private "backend" functions
|
||||
*
|
||||
* original code https://github.com/uobikiemukot/yaft
|
||||
* Copyright (c) 2012 haru <uobikiemukot at gmail dot com>
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the
|
||||
* following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> /* atoi(), strtol() */
|
||||
#include <unistd.h> /* write() */
|
||||
#include <stdio.h>
|
||||
//#include "glyph.h"
|
||||
|
||||
#include "color.h"
|
||||
|
||||
#include <system/debug.h>
|
||||
#define logging(a, message...) dprintf(DEBUG_ ## a, "YaFT: " message)
|
||||
|
||||
const uint8_t attr_mask[] = {
|
||||
0x00, 0x01, 0x00, 0x00, /* 0:none 1:bold 2:none 3:none */
|
||||
0x02, 0x04, 0x00, 0x08, /* 4:underline 5:blink 6:none 7:reverse */
|
||||
};
|
||||
|
||||
#define BUFSIZE 1024
|
||||
#define MAX_ARGS 16
|
||||
struct parm_t { /* for parse_arg() */
|
||||
int argc;
|
||||
std::string argv[MAX_ARGS];
|
||||
};
|
||||
|
||||
enum char_code {
|
||||
/* 7 bit */
|
||||
BEL = 0x07, BS = 0x08, HT = 0x09,
|
||||
LF = 0x0A, VT = 0x0B, FF = 0x0C,
|
||||
CR = 0x0D, ESC = 0x1B, DEL = 0x7F,
|
||||
/* others */
|
||||
SPACE = 0x20,
|
||||
BACKSLASH = 0x5C,
|
||||
};
|
||||
|
||||
class CFrameBuffer;
|
||||
class YaFT_p
|
||||
{
|
||||
/* color: index number of color_palette[] (see color.h) */
|
||||
enum {
|
||||
DEFAULT_FG = 7,
|
||||
DEFAULT_BG = 0,
|
||||
ACTIVE_CURSOR_COLOR = 2,
|
||||
PASSIVE_CURSOR_COLOR = 1,
|
||||
};
|
||||
|
||||
/* misc */
|
||||
enum {
|
||||
TABSTOP = 8, /* hardware tabstop */
|
||||
SUBSTITUTE_HALF = 0x0020, /* used for missing glyph(single width): U+0020 (SPACE) */
|
||||
SUBSTITUTE_WIDE = 0x3000, /* used for missing glyph(double width): U+3000 (IDEOGRAPHIC SPACE) */
|
||||
REPLACEMENT_CHAR = 0x003F, /* used for malformed UTF-8 sequence : U+003F (QUESTION MARK) */
|
||||
};
|
||||
|
||||
enum misc {
|
||||
BITS_PER_BYTE = 8, /* bits per byte */
|
||||
UCS2_CHARS = 0x10000, /* number of UCS2 glyphs */
|
||||
DEFAULT_CHAR = SPACE, /* used for erase char */
|
||||
BRIGHT_INC = 8, /* value used for brightening color */
|
||||
};
|
||||
|
||||
struct margin_t { uint16_t top, bottom; };
|
||||
struct point_t { uint16_t x, y; };
|
||||
struct color_pair_t { uint8_t fg, bg; };
|
||||
|
||||
struct state_t { /* for save, restore state */
|
||||
struct point_t cursor;
|
||||
int mode;
|
||||
int attribute;
|
||||
};
|
||||
|
||||
struct charset_t {
|
||||
uint32_t code; /* UCS4 code point: yaft only prints UCS2 and DRCSMMv1 */
|
||||
int following_byte, count;
|
||||
bool is_valid;
|
||||
};
|
||||
|
||||
enum esc_state {
|
||||
STATE_RESET = 0x00,
|
||||
STATE_ESC = 0x01, /* 0x1B, \033, ESC */
|
||||
STATE_CSI = 0x02, /* ESC [ */
|
||||
STATE_OSC = 0x04, /* ESC ] */
|
||||
STATE_DCS = 0x08, /* ESC P */
|
||||
};
|
||||
|
||||
enum char_attr {
|
||||
ATTR_RESET = 0,
|
||||
ATTR_BOLD = 1, /* brighten foreground */
|
||||
ATTR_UNDERLINE = 4,
|
||||
ATTR_BLINK = 5, /* brighten background */
|
||||
ATTR_REVERSE = 7,
|
||||
};
|
||||
|
||||
enum term_mode {
|
||||
MODE_RESET = 0x00,
|
||||
MODE_ORIGIN = 0x01, /* origin mode: DECOM */
|
||||
MODE_CURSOR = 0x02, /* cursor visible: DECTCEM */
|
||||
MODE_AMRIGHT = 0x04, /* auto wrap: DECAWM */
|
||||
MODE_VWBS = 0x08, /* variable-width backspace */
|
||||
};
|
||||
|
||||
struct esc_t {
|
||||
std::string buf;
|
||||
int bp; /* buffer position */
|
||||
enum esc_state state;
|
||||
};
|
||||
|
||||
enum glyph_width {
|
||||
NEXT_TO_WIDE = 0,
|
||||
HALF,
|
||||
WIDE,
|
||||
};
|
||||
|
||||
struct cell_t {
|
||||
const struct glyph_t *glyphp; /* pointer to glyph */
|
||||
struct color_pair_t color_pair; /* color (fg, bg) */
|
||||
int attribute; /* bold, underscore, etc... */
|
||||
enum glyph_width width; /* wide char flag: WIDE, NEXT_TO_WIDE, HALF */
|
||||
};
|
||||
|
||||
struct framebuffer_t {
|
||||
int fd; /* file descriptor of framebuffer */
|
||||
uint32_t *buf; /* copy of framebuffer */
|
||||
uint32_t real_palette[COLORS]; /* hardware specific color palette */
|
||||
int width, height; /* display resolution */
|
||||
int xstart, ystart; /* position of the window in the framebuffer */
|
||||
long screen_size; /* screen data size (byte) */
|
||||
int line_length; /* line length (byte) */
|
||||
int dy_min, dy_max; /* dirty region for blit */
|
||||
CFrameBuffer *cfb;
|
||||
};
|
||||
|
||||
private:
|
||||
int width, height; /* terminal size (pixel) */
|
||||
std::vector<std::vector<cell_t> > cells;
|
||||
struct margin_t scrollm; /* scroll margin */
|
||||
struct point_t cursor; /* cursor pos (x, y) */
|
||||
std::vector<bool> line_dirty; /* dirty flag */
|
||||
std::vector<bool> tabstop; /* tabstop flag */
|
||||
int mode; /* for set/reset mode */
|
||||
bool wrap_occured; /* whether auto wrap occured or not */
|
||||
struct state_t state; /* for restore */
|
||||
struct color_pair_t color_pair; /* color (fg, bg) */
|
||||
int attribute; /* bold, underscore, etc... */
|
||||
struct charset_t charset; /* store UTF-8 byte stream */
|
||||
struct esc_t esc; /* store escape sequence */
|
||||
uint32_t virtual_palette[COLORS]; /* virtual color palette: always 32bpp */
|
||||
bool palette_modified; /* true if palette changed by OSC 4/104 */
|
||||
const struct glyph_t *glyph[UCS2_CHARS]; /* array of pointer to glyphs[] */
|
||||
bool nlseen;
|
||||
int CELL_WIDTH, CELL_HEIGHT;
|
||||
struct framebuffer_t fb;
|
||||
struct fb_var_screeninfo *screeninfo;
|
||||
bool paint;
|
||||
public:
|
||||
int fd; /* master of pseudo terminal */
|
||||
int cols, lines; /* terminal size (cell) */
|
||||
time_t last_paint;
|
||||
std::queue<std::string> txt; /* contains "sanitized" (without control chars) output text */
|
||||
int lines_available; /* lines available in txt */
|
||||
|
||||
YaFT_p(bool paint = true);
|
||||
bool init();
|
||||
void parse(uint8_t *buf, int size);
|
||||
void refresh(void);
|
||||
private:
|
||||
void draw_line(int line);
|
||||
void erase_cell(int y, int x);
|
||||
void copy_cell(int dst_y, int dst_x, int src_y, int src_x);
|
||||
int set_cell(int y, int x, const struct glyph_t *glyphp);
|
||||
void swap_lines(int i, int j);
|
||||
void scroll(int from, int to, int offset);
|
||||
void move_cursor(int y_offset, int x_offset);
|
||||
void set_cursor(int y, int x);
|
||||
void addch(uint32_t code);
|
||||
bool push_esc(uint8_t ch);
|
||||
void reset_esc(void);
|
||||
void reset_charset(void);
|
||||
void reset(void);
|
||||
void term_die(void);
|
||||
bool term_init(int width, int height);
|
||||
void utf8_charset(uint8_t ch);
|
||||
void control_character(uint8_t ch);
|
||||
void esc_sequence(uint8_t ch);
|
||||
void csi_sequence(uint8_t ch);
|
||||
void osc_sequence(uint8_t ch);
|
||||
void bs(void);
|
||||
void nl(void);
|
||||
void cr(void);
|
||||
void ris(void);
|
||||
void crnl(void);
|
||||
void curs_up(parm_t *parm);
|
||||
void curs_down(parm_t *parm);
|
||||
void curs_back(parm_t *parm);
|
||||
void curs_forward(parm_t *parm);
|
||||
void curs_nl(parm_t *parm);
|
||||
void curs_pl(parm_t *parm);
|
||||
void curs_col(parm_t *parm);
|
||||
void curs_pos(parm_t *parm);
|
||||
void curs_line(parm_t *parm);
|
||||
void reverse_nl(void);
|
||||
void insert_blank(parm_t *parm);
|
||||
void erase_line(parm_t *parm);
|
||||
void insert_line(parm_t *parm);
|
||||
void delete_line(parm_t *parm);
|
||||
void erase_char(parm_t *parm);
|
||||
void delete_char(parm_t *parm);
|
||||
void device_attribute(parm_t *parm);
|
||||
void erase_display(parm_t *parm);
|
||||
void identify(void);
|
||||
void set_tabstop(void);
|
||||
void clear_tabstop(parm_t *parm);
|
||||
void set_mode(parm_t *parm);
|
||||
void reset_mode(parm_t *parm);
|
||||
void set_palette(parm_t *parm);
|
||||
void reset_palette(parm_t *parm);
|
||||
void set_attr(parm_t *parm);
|
||||
void status_report(parm_t *parm);
|
||||
void set_margin(parm_t *parm);
|
||||
void enter_esc(void);
|
||||
void enter_csi(void);
|
||||
void enter_osc(void);
|
||||
void save_state(void);
|
||||
void restore_state(void);
|
||||
void tab(void);
|
||||
int dec2num(std::string &s) { return atoi(s.c_str()); };
|
||||
int hex2num(std::string s) { return strtol(s.c_str(), NULL, 16); };
|
||||
int sum(parm_t *param);
|
||||
void parse_arg(std::string &buf, parm_t *pt, int delim, int (is_valid)(int c));
|
||||
void reset_parm(parm_t *parm);
|
||||
int32_t parse_color1(std::string &seq);
|
||||
int32_t parse_color2(std::string &seq);
|
||||
};
|
Reference in New Issue
Block a user