Major terminal improvements.
* Speed improvements * Crash fixers * Significant overhaul to escape handling based on extensive use of the new serial console and a remote connection to a Linux box. * Updated included terminfo file to accurately reflect terminal behavior. Some fun facts: * vim runs great on a remote console (though the serial line slows a lot of things down, it still runs rather smoothly) * going to fix GNU screen, maybe in next commit, dunno * tested with htop, less, and a bunch of other stuff
This commit is contained in:
parent
c9448437dc
commit
c6daef72a3
@ -1,8 +1,15 @@
|
|||||||
toaru|toaruos framebuffer terminal,
|
toaru|toaruos framebuffer terminal,
|
||||||
|
mc5i,
|
||||||
cols#128, lines#45,
|
cols#128, lines#45,
|
||||||
colors#256, it#8, ncv#18, pairs#32767, npc, am,
|
colors#256, it#8, ncv#18, pairs#32767, npc, am,
|
||||||
ind=^J, cr=^M, cud1=^J, nel=^J, ht=^I,
|
ind=^J, cr=^M,
|
||||||
|
nel=^J, ht=^I,
|
||||||
|
cud1=^J,
|
||||||
|
cuf1=\E[C,
|
||||||
|
cuu1=\E[A,
|
||||||
|
cub1=^H,
|
||||||
home=\E[H, clear=\E[H\E[2J,
|
home=\E[H, clear=\E[H\E[2J,
|
||||||
|
hpa=\E[%i%p1%dG,
|
||||||
cup=\E[%i%p1%d;%p2%dH,
|
cup=\E[%i%p1%d;%p2%dH,
|
||||||
ed=\E[J, el=\E[K,
|
ed=\E[J, el=\E[K,
|
||||||
setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
|
setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
|
||||||
@ -10,11 +17,21 @@ toaru|toaruos framebuffer terminal,
|
|||||||
setb@,
|
setb@,
|
||||||
setf@,
|
setf@,
|
||||||
rev=\E[7m, sgr0=\E[0m,
|
rev=\E[7m, sgr0=\E[0m,
|
||||||
smso=\E[7m, rmso=\E[27m,
|
smso=\E[7m, rmso=\E[m,
|
||||||
sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
|
sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
|
||||||
op=\E[39;39m,
|
op=\E[39;49m,
|
||||||
bold=\E[1m,
|
bold=\E[1m,
|
||||||
kcuu1=\E[A,
|
kcuu1=\E[A,
|
||||||
kcud1=\E[B,
|
kcud1=\E[B,
|
||||||
kcub1=\E[D,
|
|
||||||
kcuf1=\E[C,
|
kcuf1=\E[C,
|
||||||
|
kcub1=\E[D,
|
||||||
|
kent=\E0M,
|
||||||
|
cuu=\E[%p1%dA,
|
||||||
|
cud=\E[%p1%dB,
|
||||||
|
cuf=\E[%p1%dC,
|
||||||
|
cub=\E[%p1%dD,
|
||||||
|
indn=\E[%p1%dS,
|
||||||
|
rin=\E[%p1%dT,
|
||||||
|
ri=\E[T,
|
||||||
|
sc=\E[s,
|
||||||
|
rc=\E[u,
|
||||||
|
@ -26,7 +26,6 @@ void *print_serial_stuff(void * garbage) {
|
|||||||
|
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
char x = buf[i];
|
char x = buf[i];
|
||||||
if (x == 13) continue;
|
|
||||||
fputc(x, stdout);
|
fputc(x, stdout);
|
||||||
}
|
}
|
||||||
if (size) fflush(stdout);
|
if (size) fflush(stdout);
|
||||||
|
@ -41,6 +41,14 @@ int mk_wcwidth_cjk(wchar_t ucs);
|
|||||||
#include "terminal-palette.h"
|
#include "terminal-palette.h"
|
||||||
#include "terminal-font.h"
|
#include "terminal-font.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If you're working on updating the terminal's handling of escapes,
|
||||||
|
* switch this option to 1 to have it print an escaped bit of output
|
||||||
|
* to the serial line, so you can examine exactly which codes were
|
||||||
|
* processed.
|
||||||
|
*/
|
||||||
|
#define DEBUG_TERMINAL_WITH_SERIAL 0
|
||||||
|
|
||||||
/* A terminal cell represents a single character on screen */
|
/* A terminal cell represents a single character on screen */
|
||||||
typedef struct _terminal_cell {
|
typedef struct _terminal_cell {
|
||||||
uint16_t c; /* codepoint */
|
uint16_t c; /* codepoint */
|
||||||
@ -96,6 +104,7 @@ size_t terminal_title_length = 0;
|
|||||||
gfx_context_t * ctx;
|
gfx_context_t * ctx;
|
||||||
volatile int needs_redraw = 1;
|
volatile int needs_redraw = 1;
|
||||||
static void render_decors();
|
static void render_decors();
|
||||||
|
void term_clear();
|
||||||
|
|
||||||
/* Trigger to exit the terminal when the child process dies or
|
/* Trigger to exit the terminal when the child process dies or
|
||||||
* we otherwise receive an exit signal */
|
* we otherwise receive an exit signal */
|
||||||
@ -145,6 +154,8 @@ volatile int exit_application = 0;
|
|||||||
|
|
||||||
#define ANSI_EXT_IOCTL 'z' /* These are special escapes only we support */
|
#define ANSI_EXT_IOCTL 'z' /* These are special escapes only we support */
|
||||||
|
|
||||||
|
#define MAX_ARGS 1024
|
||||||
|
|
||||||
/* Returns the lower of two shorts */
|
/* Returns the lower of two shorts */
|
||||||
uint16_t min(uint16_t a, uint16_t b) {
|
uint16_t min(uint16_t a, uint16_t b) {
|
||||||
return (a < b) ? a : b;
|
return (a < b) ? a : b;
|
||||||
@ -184,6 +195,7 @@ int (*ansi_get_csr_x)(void) = NULL;
|
|||||||
int (*ansi_get_csr_y)(void) = NULL;
|
int (*ansi_get_csr_y)(void) = NULL;
|
||||||
void (*ansi_set_cell)(int,int,uint16_t) = NULL;
|
void (*ansi_set_cell)(int,int,uint16_t) = NULL;
|
||||||
void (*ansi_cls)(int) = NULL;
|
void (*ansi_cls)(int) = NULL;
|
||||||
|
void (*ansi_scroll)(int) = NULL;
|
||||||
|
|
||||||
/* XXX: Needs verification, but I'm pretty sure this never gets called */
|
/* XXX: Needs verification, but I'm pretty sure this never gets called */
|
||||||
void (*redraw_cursor)(void) = NULL;
|
void (*redraw_cursor)(void) = NULL;
|
||||||
@ -252,7 +264,7 @@ ansi_put(
|
|||||||
/* Woah, woah, let's see here. */
|
/* Woah, woah, let's see here. */
|
||||||
char * pch; /* tokenizer pointer */
|
char * pch; /* tokenizer pointer */
|
||||||
char * save; /* strtok_r pointer */
|
char * save; /* strtok_r pointer */
|
||||||
char * argv[1024]; /* escape arguments */
|
char * argv[MAX_ARGS]; /* escape arguments */
|
||||||
/* Get rid of the front of the buffer */
|
/* Get rid of the front of the buffer */
|
||||||
strtok_r(state.buffer,"[",&save);
|
strtok_r(state.buffer,"[",&save);
|
||||||
pch = strtok_r(NULL,";",&save);
|
pch = strtok_r(NULL,";",&save);
|
||||||
@ -261,9 +273,10 @@ ansi_put(
|
|||||||
while (pch != NULL) {
|
while (pch != NULL) {
|
||||||
argv[argc] = (char *)pch;
|
argv[argc] = (char *)pch;
|
||||||
++argc;
|
++argc;
|
||||||
|
if (argc > MAX_ARGS)
|
||||||
|
break;
|
||||||
pch = strtok_r(NULL,";",&save);
|
pch = strtok_r(NULL,";",&save);
|
||||||
}
|
}
|
||||||
argv[argc] = NULL;
|
|
||||||
/* Alright, let's do this */
|
/* Alright, let's do this */
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case ANSI_EXT_IOCTL:
|
case ANSI_EXT_IOCTL:
|
||||||
@ -403,9 +416,11 @@ ansi_put(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ANSI_SHOW:
|
case ANSI_SHOW:
|
||||||
if (!strcmp(argv[0], "?1049")) {
|
if (argc > 0) {
|
||||||
ansi_cls(2);
|
if (!strcmp(argv[0], "?1049")) {
|
||||||
ansi_set_csr(0,0);
|
ansi_cls(2);
|
||||||
|
ansi_set_csr(0,0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ANSI_CUF:
|
case ANSI_CUF:
|
||||||
@ -447,16 +462,16 @@ ansi_put(
|
|||||||
case ANSI_CHA:
|
case ANSI_CHA:
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
ansi_set_csr(0,ansi_get_csr_y());
|
ansi_set_csr(0,ansi_get_csr_y());
|
||||||
break;
|
} else {
|
||||||
|
ansi_set_csr(min(max(atoi(argv[0]), 1), state.width) - 1, ansi_get_csr_y());
|
||||||
}
|
}
|
||||||
ansi_set_csr(min(max(atoi(argv[0]), 1), state.width) - 1, ansi_get_csr_y());
|
|
||||||
break;
|
break;
|
||||||
case ANSI_CUP:
|
case ANSI_CUP:
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
ansi_set_csr(0,0);
|
ansi_set_csr(0,0);
|
||||||
break;
|
} else {
|
||||||
|
ansi_set_csr(min(max(atoi(argv[1]), 1), state.width) - 1, min(max(atoi(argv[0]), 1), state.height) - 1);
|
||||||
}
|
}
|
||||||
ansi_set_csr(min(max(atoi(argv[1]), 1), state.width) - 1, min(max(atoi(argv[0]), 1), state.height) - 1);
|
|
||||||
break;
|
break;
|
||||||
case ANSI_ED:
|
case ANSI_ED:
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
@ -493,10 +508,28 @@ ansi_put(
|
|||||||
input_buffer_stuff(out);
|
input_buffer_stuff(out);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ANSI_SU:
|
||||||
|
{
|
||||||
|
int how_many = 1;
|
||||||
|
if (argc > 0) {
|
||||||
|
how_many = atoi(argv[0]);
|
||||||
|
}
|
||||||
|
ansi_scroll(how_many);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANSI_SD:
|
||||||
|
{
|
||||||
|
int how_many = 1;
|
||||||
|
if (argc > 0) {
|
||||||
|
how_many = atoi(argv[0]);
|
||||||
|
}
|
||||||
|
ansi_scroll(-how_many);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'X':
|
case 'X':
|
||||||
{
|
{
|
||||||
int how_many = 1;
|
int how_many = 1;
|
||||||
if (argc >= 1) {
|
if (argc > 0) {
|
||||||
how_many = atoi(argv[0]);
|
how_many = atoi(argv[0]);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < how_many; ++i) {
|
for (int i = 0; i < how_many; ++i) {
|
||||||
@ -535,7 +568,7 @@ ansi_put(
|
|||||||
/* Tokenize on semicolons, like we always do */
|
/* Tokenize on semicolons, like we always do */
|
||||||
char * pch; /* tokenizer pointer */
|
char * pch; /* tokenizer pointer */
|
||||||
char * save; /* strtok_r pointer */
|
char * save; /* strtok_r pointer */
|
||||||
char * argv[1024]; /* escape arguments */
|
char * argv[MAX_ARGS]; /* escape arguments */
|
||||||
/* Get rid of the front of the buffer */
|
/* Get rid of the front of the buffer */
|
||||||
strtok_r(state.buffer,"]",&save);
|
strtok_r(state.buffer,"]",&save);
|
||||||
pch = strtok_r(NULL,";",&save);
|
pch = strtok_r(NULL,";",&save);
|
||||||
@ -544,19 +577,21 @@ ansi_put(
|
|||||||
while (pch != NULL) {
|
while (pch != NULL) {
|
||||||
argv[argc] = (char *)pch;
|
argv[argc] = (char *)pch;
|
||||||
++argc;
|
++argc;
|
||||||
|
if (argc > MAX_ARGS) break;
|
||||||
pch = strtok_r(NULL,";",&save);
|
pch = strtok_r(NULL,";",&save);
|
||||||
}
|
}
|
||||||
argv[argc] = NULL;
|
|
||||||
/* Start testing the first argument for what command to use */
|
/* Start testing the first argument for what command to use */
|
||||||
if (!strcmp(argv[0], "1")) {
|
if (argv[0]) {
|
||||||
if (argc > 1) {
|
if (!strcmp(argv[0], "1")) {
|
||||||
int len = min(TERMINAL_TITLE_SIZE, strlen(argv[1])+1);
|
if (argc > 1) {
|
||||||
memcpy(terminal_title, argv[1], len);
|
int len = min(TERMINAL_TITLE_SIZE, strlen(argv[1])+1);
|
||||||
terminal_title[len-1] = '\0';
|
memcpy(terminal_title, argv[1], len);
|
||||||
terminal_title_length = len - 1;
|
terminal_title[len-1] = '\0';
|
||||||
render_decors();
|
terminal_title_length = len - 1;
|
||||||
}
|
render_decors();
|
||||||
} /* Currently, no other options */
|
}
|
||||||
|
} /* Currently, no other options */
|
||||||
|
}
|
||||||
/* Clear out the buffer */
|
/* Clear out the buffer */
|
||||||
state.buflen = 0;
|
state.buflen = 0;
|
||||||
state.escape = 0;
|
state.escape = 0;
|
||||||
@ -571,7 +606,7 @@ ansi_put(
|
|||||||
|
|
||||||
void ansi_init(void (*writer)(char), int w, int y, void (*setcolor)(unsigned char, unsigned char),
|
void ansi_init(void (*writer)(char), int w, int y, void (*setcolor)(unsigned char, unsigned char),
|
||||||
void (*setcsr)(int,int), int (*getcsrx)(void), int (*getcsry)(void), void (*setcell)(int,int,uint16_t),
|
void (*setcsr)(int,int), int (*getcsrx)(void), int (*getcsry)(void), void (*setcell)(int,int,uint16_t),
|
||||||
void (*cls)(int), void (*redraw_csr)(void)) {
|
void (*cls)(int), void (*redraw_csr)(void), void (*scroll_term)(int)) {
|
||||||
|
|
||||||
ansi_writer = writer;
|
ansi_writer = writer;
|
||||||
ansi_set_color = setcolor;
|
ansi_set_color = setcolor;
|
||||||
@ -581,6 +616,7 @@ void ansi_init(void (*writer)(char), int w, int y, void (*setcolor)(unsigned cha
|
|||||||
ansi_set_cell = setcell;
|
ansi_set_cell = setcell;
|
||||||
ansi_cls = cls;
|
ansi_cls = cls;
|
||||||
redraw_cursor = redraw_csr;
|
redraw_cursor = redraw_csr;
|
||||||
|
ansi_scroll = scroll_term;
|
||||||
|
|
||||||
/* Terminal Defaults */
|
/* Terminal Defaults */
|
||||||
state.fg = DEFAULT_FG; /* Light grey */
|
state.fg = DEFAULT_FG; /* Light grey */
|
||||||
@ -624,21 +660,6 @@ static inline void term_set_point(uint16_t x, uint16_t y, uint32_t color ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void term_set_point_alpha(uint16_t x, uint16_t y, uint32_t color, uint8_t alpha) {
|
|
||||||
if (_windowed) {
|
|
||||||
GFX(ctx, (x+decor_left_width),(y+decor_top_height)) = color | (alpha * 0x1000000);
|
|
||||||
} else {
|
|
||||||
if (ctx->depth == 32) {
|
|
||||||
GFX(ctx, x,y) = color | 0xFF000000;
|
|
||||||
} else if (ctx->depth == 24) {
|
|
||||||
ctx->backbuffer[((y) * ctx->width + x) * 3 + 2] = _RED(color);
|
|
||||||
ctx->backbuffer[((y) * ctx->width + x) * 3 + 1] = _GRE(color);
|
|
||||||
ctx->backbuffer[((y) * ctx->width + x) * 3 + 0] = _BLU(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* FreeType text rendering */
|
/* FreeType text rendering */
|
||||||
|
|
||||||
FT_Library library;
|
FT_Library library;
|
||||||
@ -656,7 +677,8 @@ void drawChar(FT_Bitmap * bitmap, int x, int y, uint32_t fg, uint32_t bg) {
|
|||||||
int y_max = y + bitmap->rows;
|
int y_max = y + bitmap->rows;
|
||||||
for (j = y, q = 0; j < y_max; j++, q++) {
|
for (j = y, q = 0; j < y_max; j++, q++) {
|
||||||
for ( i = x, p = 0; i < x_max; i++, p++) {
|
for ( i = x, p = 0; i < x_max; i++, p++) {
|
||||||
term_set_point(i,j, alpha_blend(bg, fg, rgb(bitmap->buffer[q * bitmap->width + p],0,0)));
|
uint32_t tmp = (fg & 0xFFFFFF) | 0x1000000 * bitmap->buffer[q * bitmap->width + p];
|
||||||
|
term_set_point(i,j, alpha_blend_rgba(bg, tmp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -729,7 +751,7 @@ term_write_char(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (val < 32) {
|
if (val < 32 || val == ' ') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int pen_x = x;
|
int pen_x = x;
|
||||||
@ -870,32 +892,72 @@ void term_redraw_all() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void term_term_scroll() {
|
void term_scroll(int how_much) {
|
||||||
/* Shirt terminal cells one row up */
|
if (how_much >= term_height || -how_much >= term_height) {
|
||||||
memmove(term_buffer, (void *)((uintptr_t)term_buffer + sizeof(t_cell) * term_width), sizeof(t_cell) * term_width * (term_height - 1));
|
term_clear();
|
||||||
/* Reset the "new" row to clean cells */
|
return;
|
||||||
memset((void *)((uintptr_t)term_buffer + sizeof(t_cell) * term_width * (term_height - 1)), 0x0, sizeof(t_cell) * term_width);
|
}
|
||||||
if (_vga_mode) {
|
if (how_much == 0) {
|
||||||
/* In VGA mode, we can very quickly just redraw everything */
|
return;
|
||||||
term_redraw_all();
|
}
|
||||||
} else {
|
if (how_much > 0) {
|
||||||
/* In graphical modes, we will shift the graphics buffer up as necessary */
|
/* Shift terminal cells one row up */
|
||||||
uintptr_t dst, src;
|
memmove(term_buffer, (void *)((uintptr_t)term_buffer + sizeof(t_cell) * term_width), sizeof(t_cell) * term_width * (term_height - how_much));
|
||||||
size_t siz = char_height * (term_height - 1) * GFX_W(ctx) * GFX_B(ctx);
|
/* Reset the "new" row to clean cells */
|
||||||
if (_windowed) {
|
memset((void *)((uintptr_t)term_buffer + sizeof(t_cell) * term_width * (term_height - how_much)), 0x0, sizeof(t_cell) * term_width * how_much);
|
||||||
/* Windowed mode must take borders into account */
|
if (_vga_mode) {
|
||||||
dst = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * decor_top_height) * GFX_B(ctx);
|
/* In VGA mode, we can very quickly just redraw everything */
|
||||||
src = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * (decor_top_height + char_height)) * GFX_B(ctx);
|
term_redraw_all();
|
||||||
} else {
|
} else {
|
||||||
/* While fullscreen mode does not */
|
/* In graphical modes, we will shift the graphics buffer up as necessary */
|
||||||
dst = (uintptr_t)ctx->backbuffer;
|
uintptr_t dst, src;
|
||||||
src = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * char_height) * GFX_B(ctx);
|
size_t siz = char_height * (term_height - how_much) * GFX_W(ctx) * GFX_B(ctx);
|
||||||
|
if (_windowed) {
|
||||||
|
/* Windowed mode must take borders into account */
|
||||||
|
dst = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * decor_top_height) * GFX_B(ctx);
|
||||||
|
src = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * (decor_top_height + char_height * how_much)) * GFX_B(ctx);
|
||||||
|
} else {
|
||||||
|
/* While fullscreen mode does not */
|
||||||
|
dst = (uintptr_t)ctx->backbuffer;
|
||||||
|
src = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * char_height * how_much) * GFX_B(ctx);
|
||||||
|
}
|
||||||
|
/* Perform the shift */
|
||||||
|
memmove((void *)dst, (void *)src, siz);
|
||||||
|
/* And redraw the new rows */
|
||||||
|
for (int i = 0; i < how_much; ++i) {
|
||||||
|
for (uint16_t x = 0; x < term_width; ++x) {
|
||||||
|
cell_redraw(x, term_height - how_much);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Perform the shift */
|
} else {
|
||||||
memmove((void *)dst, (void *)src, siz);
|
how_much = -how_much;
|
||||||
/* And redraw the new rows */
|
/* Shift terminal cells one row up */
|
||||||
for (uint16_t x = 0; x < term_width; ++x) {
|
memmove((void *)((uintptr_t)term_buffer + sizeof(t_cell) * term_width), term_buffer, sizeof(t_cell) * term_width * (term_height - how_much));
|
||||||
cell_redraw(x, term_height - 1);
|
/* Reset the "new" row to clean cells */
|
||||||
|
memset(term_buffer, 0x0, sizeof(t_cell) * term_width * how_much);
|
||||||
|
if (_vga_mode) {
|
||||||
|
/* In VGA mode, we can very quickly just redraw everything */
|
||||||
|
term_redraw_all();
|
||||||
|
} else {
|
||||||
|
uintptr_t dst, src;
|
||||||
|
size_t siz = char_height * (term_height - how_much) * GFX_W(ctx) * GFX_B(ctx);
|
||||||
|
if (_windowed) {
|
||||||
|
src = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * decor_top_height) * GFX_B(ctx);
|
||||||
|
dst = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * (decor_top_height + char_height * how_much)) * GFX_B(ctx);
|
||||||
|
} else {
|
||||||
|
/* While fullscreen mode does not */
|
||||||
|
src = (uintptr_t)ctx->backbuffer;
|
||||||
|
dst = (uintptr_t)ctx->backbuffer + (GFX_W(ctx) * char_height * how_much) * GFX_B(ctx);
|
||||||
|
}
|
||||||
|
/* Perform the shift */
|
||||||
|
memmove((void *)dst, (void *)src, siz);
|
||||||
|
/* And redraw the new rows */
|
||||||
|
for (int i = 0; i < how_much; ++i) {
|
||||||
|
for (uint16_t x = 0; x < term_width; ++x) {
|
||||||
|
cell_redraw(x, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -904,6 +966,7 @@ uint32_t codepoint;
|
|||||||
uint32_t unicode_state = 0;
|
uint32_t unicode_state = 0;
|
||||||
|
|
||||||
int is_wide(uint32_t codepoint) {
|
int is_wide(uint32_t codepoint) {
|
||||||
|
if (codepoint < 256) return 0;
|
||||||
return mk_wcwidth_cjk(codepoint) == 2;
|
return mk_wcwidth_cjk(codepoint) == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -915,13 +978,19 @@ void term_write(char c) {
|
|||||||
c = '?';
|
c = '?';
|
||||||
}
|
}
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
for (uint16_t i = csr_x; i < term_width; ++i) {
|
|
||||||
/* I like this behaviour */
|
|
||||||
cell_set(i, csr_y, ' ',current_fg, current_bg, state.flags);
|
|
||||||
cell_redraw(i, csr_y);
|
|
||||||
}
|
|
||||||
csr_x = 0;
|
csr_x = 0;
|
||||||
++csr_y;
|
++csr_y;
|
||||||
|
draw_cursor();
|
||||||
|
} else if (c == '\007') {
|
||||||
|
/* bell */
|
||||||
|
for (int i = 0; i < term_height; ++i) {
|
||||||
|
for (int j = 0; j < term_width; ++j) {
|
||||||
|
cell_redraw_inverted(j, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* XXX: sleep */
|
||||||
|
for (int i = 0; i < 10; ++i) syscall_yield();
|
||||||
|
term_redraw_all();
|
||||||
} else if (c == '\r') {
|
} else if (c == '\r') {
|
||||||
cell_redraw(csr_x,csr_y);
|
cell_redraw(csr_x,csr_y);
|
||||||
csr_x = 0;
|
csr_x = 0;
|
||||||
@ -929,10 +998,11 @@ void term_write(char c) {
|
|||||||
if (csr_x > 0) {
|
if (csr_x > 0) {
|
||||||
--csr_x;
|
--csr_x;
|
||||||
}
|
}
|
||||||
cell_set(csr_x, csr_y, ' ',current_fg, current_bg, state.flags);
|
|
||||||
cell_redraw(csr_x, csr_y);
|
cell_redraw(csr_x, csr_y);
|
||||||
|
draw_cursor();
|
||||||
} else if (c == '\t') {
|
} else if (c == '\t') {
|
||||||
csr_x = (csr_x + 8) & ~(8 - 1);
|
csr_x += (8 - csr_x % 8);
|
||||||
|
draw_cursor();
|
||||||
} else {
|
} else {
|
||||||
int wide = is_wide(codepoint);
|
int wide = is_wide(codepoint);
|
||||||
uint8_t flags = state.flags;
|
uint8_t flags = state.flags;
|
||||||
@ -958,7 +1028,7 @@ void term_write(char c) {
|
|||||||
++csr_y;
|
++csr_y;
|
||||||
}
|
}
|
||||||
if (csr_y == term_height) {
|
if (csr_y == term_height) {
|
||||||
term_term_scroll();
|
term_scroll(1);
|
||||||
csr_y = term_height - 1;
|
csr_y = term_height - 1;
|
||||||
}
|
}
|
||||||
} else if (unicode_state == UTF8_REJECT) {
|
} else if (unicode_state == UTF8_REJECT) {
|
||||||
@ -972,6 +1042,7 @@ term_set_csr(int x, int y) {
|
|||||||
cell_redraw(csr_x,csr_y);
|
cell_redraw(csr_x,csr_y);
|
||||||
csr_x = x;
|
csr_x = x;
|
||||||
csr_y = y;
|
csr_y = y;
|
||||||
|
draw_cursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1026,7 +1097,7 @@ void term_redraw_cell(int x, int y) {
|
|||||||
cell_redraw(x,y);
|
cell_redraw(x,y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void term_term_clear(int i) {
|
void term_clear(int i) {
|
||||||
if (i == 2) {
|
if (i == 2) {
|
||||||
/* Oh dear */
|
/* Oh dear */
|
||||||
csr_x = 0;
|
csr_x = 0;
|
||||||
@ -1057,28 +1128,6 @@ void term_term_clear(int i) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cat(char * file) {
|
|
||||||
FILE * f = fopen(file, "rb");
|
|
||||||
if (!f) {
|
|
||||||
ansi_print("Failed to open file, so skipping that part.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t len = 0;
|
|
||||||
fseek(f, 0, SEEK_END);
|
|
||||||
len = ftell(f);
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
|
|
||||||
char * buffer = (char *)malloc(sizeof(char) * len);
|
|
||||||
fread(buffer, 1, len, f);
|
|
||||||
fclose(f);
|
|
||||||
for (size_t i = 0; i < len; ++i) {
|
|
||||||
ansi_put(buffer[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
char * loadMemFont(char * name, char * ident, size_t * size) {
|
char * loadMemFont(char * name, char * ident, size_t * size) {
|
||||||
if (!_windowed) {
|
if (!_windowed) {
|
||||||
FILE * f = fopen(name, "r");
|
FILE * f = fopen(name, "r");
|
||||||
@ -1277,7 +1326,7 @@ void reinit() {
|
|||||||
}
|
}
|
||||||
/* XXX: Transfer values, cursor location, etc.? */
|
/* XXX: Transfer values, cursor location, etc.? */
|
||||||
term_buffer = malloc(sizeof(t_cell) * term_width * term_height);
|
term_buffer = malloc(sizeof(t_cell) * term_width * term_height);
|
||||||
ansi_init(&term_write, term_width, term_height, &term_set_colors, &term_set_csr, &term_get_csr_x, &term_get_csr_y, &term_set_cell, &term_term_clear, &term_redraw_cursor);
|
ansi_init(&term_write, term_width, term_height, &term_set_colors, &term_set_csr, &term_get_csr_x, &term_get_csr_y, &term_set_cell, &term_clear, &term_redraw_cursor, &term_scroll);
|
||||||
|
|
||||||
mouse_x = ctx->width / 2;
|
mouse_x = ctx->width / 2;
|
||||||
mouse_y = ctx->height / 2;
|
mouse_y = ctx->height / 2;
|
||||||
@ -1290,6 +1339,23 @@ void reinit() {
|
|||||||
ansi_print("\033[H\033[2J");
|
ansi_print("\033[H\033[2J");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG_TERMINAL_WITH_SERIAL
|
||||||
|
DEFN_SYSCALL1(serial, 44, int);
|
||||||
|
int serial_fd;
|
||||||
|
void serial_put(uint8_t c) {
|
||||||
|
if (c == '\033') {
|
||||||
|
char out[3] = {'\\', 'E', 0};
|
||||||
|
write(serial_fd, out, 2);
|
||||||
|
} else if (c < 32) {
|
||||||
|
char out[5] = {'\\', '0' + ((c / 8) / 8) % 8, '0' + (c / 8) % 8, '0' + c % 8, 0};
|
||||||
|
write(serial_fd, out, 4);
|
||||||
|
} else {
|
||||||
|
char out[2] = {c, 0};
|
||||||
|
write(serial_fd, out, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
|
|
||||||
_windowed = 1;
|
_windowed = 1;
|
||||||
@ -1360,6 +1426,10 @@ int main(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG_TERMINAL_WITH_SERIAL
|
||||||
|
serial_fd = syscall_serial(0x3F8);
|
||||||
|
#endif
|
||||||
|
|
||||||
putenv("TERM=toaru");
|
putenv("TERM=toaru");
|
||||||
|
|
||||||
if (_windowed) {
|
if (_windowed) {
|
||||||
@ -1546,6 +1616,9 @@ fail_mouse:
|
|||||||
int r = read(ofd, buf, min(_stat.st_size, 1024));
|
int r = read(ofd, buf, min(_stat.st_size, 1024));
|
||||||
for (uint32_t i = 0; i < r; ++i) {
|
for (uint32_t i = 0; i < r; ++i) {
|
||||||
ansi_put(buf[i]);
|
ansi_put(buf[i]);
|
||||||
|
#if DEBUG_TERMINAL_WITH_SERIAL
|
||||||
|
serial_put(buf[i]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user