mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-09-01 09:51:13 +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