Tab Stops™
This commit is contained in:
+27
-24
@@ -150,11 +150,14 @@ ansi_parser(char newchar)
|
|||||||
newchar = LF; // translate to LF, like VT100 / xterm do
|
newchar = LF; // translate to LF, like VT100 / xterm do
|
||||||
case CR:
|
case CR:
|
||||||
case LF:
|
case LF:
|
||||||
case TAB:
|
|
||||||
case BS:
|
case BS:
|
||||||
apars_handle_plainchar(newchar);
|
apars_handle_plainchar(newchar);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case TAB:
|
||||||
|
screen_tab_forward();
|
||||||
|
return;
|
||||||
|
|
||||||
// Select G0 or G1
|
// Select G0 or G1
|
||||||
case SI:
|
case SI:
|
||||||
screen_set_charset_n(1);
|
screen_set_charset_n(1);
|
||||||
@@ -202,7 +205,7 @@ ansi_parser(char newchar)
|
|||||||
|
|
||||||
// The parser
|
// The parser
|
||||||
|
|
||||||
/* #line 206 "user/ansi_parser.c" */
|
/* #line 209 "user/ansi_parser.c" */
|
||||||
{
|
{
|
||||||
const char *_acts;
|
const char *_acts;
|
||||||
unsigned int _nacts;
|
unsigned int _nacts;
|
||||||
@@ -488,7 +491,7 @@ execFuncs:
|
|||||||
while ( _nacts-- > 0 ) {
|
while ( _nacts-- > 0 ) {
|
||||||
switch ( *_acts++ ) {
|
switch ( *_acts++ ) {
|
||||||
case 0:
|
case 0:
|
||||||
/* #line 177 "user/ansi_parser.rl" */
|
/* #line 180 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
if ((*p) != 0) {
|
if ((*p) != 0) {
|
||||||
apars_handle_plainchar((*p));
|
apars_handle_plainchar((*p));
|
||||||
@@ -496,7 +499,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* #line 186 "user/ansi_parser.rl" */
|
/* #line 189 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
// Reset the CSI builder
|
// Reset the CSI builder
|
||||||
csi_leading = csi_char = 0;
|
csi_leading = csi_char = 0;
|
||||||
@@ -512,13 +515,13 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
/* #line 200 "user/ansi_parser.rl" */
|
/* #line 203 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
csi_leading = (*p);
|
csi_leading = (*p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
/* #line 204 "user/ansi_parser.rl" */
|
/* #line 207 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
if (csi_cnt == 0) csi_cnt = 1;
|
if (csi_cnt == 0) csi_cnt = 1;
|
||||||
// x10 + digit
|
// x10 + digit
|
||||||
@@ -528,7 +531,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
/* #line 212 "user/ansi_parser.rl" */
|
/* #line 215 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
if (csi_cnt == 0) csi_cnt = 1; // handle case when first arg is empty
|
if (csi_cnt == 0) csi_cnt = 1; // handle case when first arg is empty
|
||||||
csi_cnt++;
|
csi_cnt++;
|
||||||
@@ -536,7 +539,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* #line 218 "user/ansi_parser.rl" */
|
/* #line 221 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
csi_char = (*p);
|
csi_char = (*p);
|
||||||
apars_handle_CSI(csi_leading, csi_n, csi_cnt, csi_char);
|
apars_handle_CSI(csi_leading, csi_n, csi_cnt, csi_char);
|
||||||
@@ -544,7 +547,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
/* #line 224 "user/ansi_parser.rl" */
|
/* #line 227 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
ansi_warn("Parser error.");
|
ansi_warn("Parser error.");
|
||||||
apars_handle_badseq();
|
apars_handle_badseq();
|
||||||
@@ -552,7 +555,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
/* #line 242 "user/ansi_parser.rl" */
|
/* #line 245 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
csi_ni = 0;
|
csi_ni = 0;
|
||||||
|
|
||||||
@@ -570,7 +573,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
/* #line 259 "user/ansi_parser.rl" */
|
/* #line 262 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
osc_bi = 0;
|
osc_bi = 0;
|
||||||
osc_buffer[0] = '\0';
|
osc_buffer[0] = '\0';
|
||||||
@@ -579,7 +582,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
/* #line 266 "user/ansi_parser.rl" */
|
/* #line 269 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
|
apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]);
|
||||||
inside_osc = false;
|
inside_osc = false;
|
||||||
@@ -587,13 +590,13 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
/* #line 272 "user/ansi_parser.rl" */
|
/* #line 275 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
osc_buffer[osc_bi++] = (*p);
|
osc_buffer[osc_bi++] = (*p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
/* #line 276 "user/ansi_parser.rl" */
|
/* #line 279 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
osc_buffer[osc_bi++] = '\0';
|
osc_buffer[osc_bi++] = '\0';
|
||||||
apars_handle_OSC_SetTitle(osc_buffer);
|
apars_handle_OSC_SetTitle(osc_buffer);
|
||||||
@@ -602,7 +605,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
/* #line 283 "user/ansi_parser.rl" */
|
/* #line 286 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
osc_buffer[osc_bi++] = '\0';
|
osc_buffer[osc_bi++] = '\0';
|
||||||
apars_handle_OSC_SetButton(csi_n[0], osc_buffer);
|
apars_handle_OSC_SetButton(csi_n[0], osc_buffer);
|
||||||
@@ -611,28 +614,28 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
/* #line 316 "user/ansi_parser.rl" */
|
/* #line 319 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_hashCode((*p));
|
apars_handle_hashCode((*p));
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
/* #line 321 "user/ansi_parser.rl" */
|
/* #line 324 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_shortCode((*p));
|
apars_handle_shortCode((*p));
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
/* #line 326 "user/ansi_parser.rl" */
|
/* #line 329 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_setXCtrls((*p)); // weird control settings like 7 bit / 8 bit mode
|
apars_handle_setXCtrls((*p)); // weird control settings like 7 bit / 8 bit mode
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
/* #line 331 "user/ansi_parser.rl" */
|
/* #line 334 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
// abuse the buffer for storing the leading char
|
// abuse the buffer for storing the leading char
|
||||||
osc_buffer[0] = (*p);
|
osc_buffer[0] = (*p);
|
||||||
@@ -640,13 +643,13 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 17:
|
case 17:
|
||||||
/* #line 337 "user/ansi_parser.rl" */
|
/* #line 340 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_characterSet(osc_buffer[0], (*p));
|
apars_handle_characterSet(osc_buffer[0], (*p));
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* #line 650 "user/ansi_parser.c" */
|
/* #line 653 "user/ansi_parser.c" */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto _again;
|
goto _again;
|
||||||
@@ -664,7 +667,7 @@ _again:
|
|||||||
while ( __nacts-- > 0 ) {
|
while ( __nacts-- > 0 ) {
|
||||||
switch ( *__acts++ ) {
|
switch ( *__acts++ ) {
|
||||||
case 6:
|
case 6:
|
||||||
/* #line 224 "user/ansi_parser.rl" */
|
/* #line 227 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
ansi_warn("Parser error.");
|
ansi_warn("Parser error.");
|
||||||
apars_handle_badseq();
|
apars_handle_badseq();
|
||||||
@@ -673,7 +676,7 @@ _again:
|
|||||||
goto _again;}
|
goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* #line 677 "user/ansi_parser.c" */
|
/* #line 680 "user/ansi_parser.c" */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -681,7 +684,7 @@ goto _again;}
|
|||||||
_out: {}
|
_out: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #line 361 "user/ansi_parser.rl" */
|
/* #line 364 "user/ansi_parser.rl" */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -114,11 +114,14 @@ ansi_parser(char newchar)
|
|||||||
newchar = LF; // translate to LF, like VT100 / xterm do
|
newchar = LF; // translate to LF, like VT100 / xterm do
|
||||||
case CR:
|
case CR:
|
||||||
case LF:
|
case LF:
|
||||||
case TAB:
|
|
||||||
case BS:
|
case BS:
|
||||||
apars_handle_plainchar(newchar);
|
apars_handle_plainchar(newchar);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case TAB:
|
||||||
|
screen_tab_forward();
|
||||||
|
return;
|
||||||
|
|
||||||
// Select G0 or G1
|
// Select G0 or G1
|
||||||
case SI:
|
case SI:
|
||||||
screen_set_charset_n(1);
|
screen_set_charset_n(1);
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
|
|||||||
case 'M':
|
case 'M':
|
||||||
case '@':
|
case '@':
|
||||||
case 'P':
|
case 'P':
|
||||||
|
case 'I':
|
||||||
|
case 'Z':
|
||||||
if (n1 == 0) n1 = 1;
|
if (n1 == 0) n1 = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -257,14 +259,26 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
|
|||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
int n = params[i];
|
int n = params[i];
|
||||||
if (leadchar == '?') {
|
if (leadchar == '?') {
|
||||||
if (n == 25) {
|
if (n == 1) {
|
||||||
screen_cursor_visible(yn);
|
screen_set_cursors_alt_mode(yn);
|
||||||
|
}
|
||||||
|
else if (n == 6) {
|
||||||
|
// TODO origin mode (scrolling region)
|
||||||
}
|
}
|
||||||
else if (n == 7) {
|
else if (n == 7) {
|
||||||
screen_wrap_enable(yn);
|
screen_wrap_enable(yn);
|
||||||
}
|
}
|
||||||
else if (n == 1) {
|
else if (n == 8) {
|
||||||
screen_set_cursors_alt_mode(yn);
|
// TODO autorepeat mode
|
||||||
|
}
|
||||||
|
else if (n == 9) {
|
||||||
|
// TODO X10 mouse
|
||||||
|
}
|
||||||
|
else if (n == 1000) {
|
||||||
|
// TODo X11 mouse
|
||||||
|
}
|
||||||
|
else if (n == 25) {
|
||||||
|
screen_cursor_visible(yn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// ansi_warn("NOIMPL DEC opt %d", n);
|
// ansi_warn("NOIMPL DEC opt %d", n);
|
||||||
@@ -371,13 +385,23 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
// TODO clear tab
|
if (n1 == 3) {
|
||||||
// ansi_warn("NOIMPL clear tab");
|
screen_clear_all_tabs();
|
||||||
|
} else {
|
||||||
|
screen_clear_tab();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'Z':
|
case 'Z':
|
||||||
// TODO back tab
|
for(; n1 > 0; n1--) {
|
||||||
// ansi_warn("NOIMPL cursor back tab");
|
screen_tab_reverse();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
for(; n1 > 0; n1--) {
|
||||||
|
screen_tab_forward();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c': // CSI-c
|
case 'c': // CSI-c
|
||||||
@@ -438,8 +462,7 @@ void ICACHE_FLASH_ATTR apars_handle_shortCode(char c)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'H':
|
case 'H':
|
||||||
// TODO set tab
|
screen_set_tab();
|
||||||
// ansi_warn("NOIMPL set tab");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '>':
|
case '>':
|
||||||
|
|||||||
+125
-15
@@ -32,6 +32,13 @@ typedef struct __attribute__((packed)){
|
|||||||
*/
|
*/
|
||||||
static Cell screen[MAX_SCREEN_SIZE];
|
static Cell screen[MAX_SCREEN_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
#define TABSTOP_WORDS 5
|
||||||
|
/**
|
||||||
|
* Tab stops bitmap
|
||||||
|
*/
|
||||||
|
static u32 tab_stops[TABSTOP_WORDS];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Screen state structure
|
* Screen state structure
|
||||||
*/
|
*/
|
||||||
@@ -204,10 +211,126 @@ screen_reset(void)
|
|||||||
// size is left unchanged
|
// size is left unchanged
|
||||||
screen_clear(CLEAR_ALL);
|
screen_clear(CLEAR_ALL);
|
||||||
|
|
||||||
|
screen_clear_all_tabs();
|
||||||
|
|
||||||
NOTIFY_DONE();
|
NOTIFY_DONE();
|
||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
//region --- Tab stops ---
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_clear_all_tabs(void)
|
||||||
|
{
|
||||||
|
memset(tab_stops, 0, sizeof(tab_stops));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_set_tab(void)
|
||||||
|
{
|
||||||
|
tab_stops[cursor.x/32] |= (1<<(cursor.x%32));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_clear_tab(void)
|
||||||
|
{
|
||||||
|
tab_stops[cursor.x/32] &= ~(1<<(cursor.x%32));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find tab stop closest to cursor to the right
|
||||||
|
* @return X pos or -1
|
||||||
|
*/
|
||||||
|
static int ICACHE_FLASH_ATTR
|
||||||
|
next_tab_stop(void)
|
||||||
|
{
|
||||||
|
// cursor must never go past EOL
|
||||||
|
if (cursor.x >= W-1) return -1;
|
||||||
|
|
||||||
|
// find first word to inspect
|
||||||
|
int idx = (cursor.x+1)/32;
|
||||||
|
int offs = (cursor.x+1)%32;
|
||||||
|
int cp = cursor.x;
|
||||||
|
while (idx < TABSTOP_WORDS) {
|
||||||
|
u32 w = tab_stops[idx];
|
||||||
|
w >>= offs;
|
||||||
|
for(;offs<32;offs++) {
|
||||||
|
cp++;
|
||||||
|
if (cp >= W) return -1;
|
||||||
|
if (w & 1) return cp;
|
||||||
|
w >>= 1;
|
||||||
|
}
|
||||||
|
offs = 0;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find tab stop closest to cursor to the left
|
||||||
|
* @return X pos or -1
|
||||||
|
*/
|
||||||
|
static int ICACHE_FLASH_ATTR
|
||||||
|
prev_tab_stop(void)
|
||||||
|
{
|
||||||
|
// nowhere to go
|
||||||
|
if (cursor.x == 0) return -1;
|
||||||
|
|
||||||
|
// find first word to inspect
|
||||||
|
int idx = (cursor.x-1)/32;
|
||||||
|
int offs = (cursor.x-1)%32;
|
||||||
|
int cp = cursor.x;
|
||||||
|
while (idx >= 0) {
|
||||||
|
u32 w = tab_stops[idx];
|
||||||
|
w <<= 31-offs;
|
||||||
|
if (w == 0) {
|
||||||
|
cp -= cp%32;
|
||||||
|
if (cp < 0) return -1;
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
for(;offs>=0;offs--) {
|
||||||
|
cp--;
|
||||||
|
if (cp < 0) return -1;
|
||||||
|
if (w & (1<<31)) return cp;
|
||||||
|
w <<= 1;
|
||||||
|
}
|
||||||
|
next:
|
||||||
|
offs = 31;
|
||||||
|
idx--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_tab_forward(void)
|
||||||
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
|
int tab = next_tab_stop();
|
||||||
|
if (tab != -1) {
|
||||||
|
cursor.x = tab;
|
||||||
|
} else {
|
||||||
|
cursor.x = W-1;
|
||||||
|
}
|
||||||
|
NOTIFY_DONE();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
screen_tab_reverse(void)
|
||||||
|
{
|
||||||
|
NOTIFY_LOCK();
|
||||||
|
int tab = prev_tab_stop();
|
||||||
|
if (tab != -1) {
|
||||||
|
cursor.x = tab;
|
||||||
|
} else {
|
||||||
|
cursor.x = 0;
|
||||||
|
}
|
||||||
|
NOTIFY_DONE();
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
//region --- Clearing & inserting ---
|
//region --- Clearing & inserting ---
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -742,29 +865,16 @@ screen_putchar(const char *ch)
|
|||||||
|
|
||||||
case 8: // BS
|
case 8: // BS
|
||||||
if (cursor.x > 0) {
|
if (cursor.x > 0) {
|
||||||
|
// according to vttest, backspace should go to col 79 if "hanging" after 80
|
||||||
if (cursor.hanging) {
|
if (cursor.hanging) {
|
||||||
cursor.hanging = false;
|
cursor.hanging = false;
|
||||||
} else {
|
|
||||||
cursor.x--;
|
|
||||||
}
|
}
|
||||||
|
cursor.x--;
|
||||||
}
|
}
|
||||||
// we should not wrap around
|
// we should not wrap around
|
||||||
// and apparently backspace should not even clear the cell
|
// and apparently backspace should not even clear the cell
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
case 9: // TAB
|
|
||||||
// // TODO change to "go to next tab stop"
|
|
||||||
// if (cursor.x<((W-1)-(W-1)%4)) {
|
|
||||||
// c->c[0] = ' ';
|
|
||||||
// c->c[1] = 0;
|
|
||||||
// c->c[2] = 0;
|
|
||||||
// c->c[3] = 0;
|
|
||||||
// do {
|
|
||||||
// screen_putchar(" ");
|
|
||||||
// } while(cursor.x%4!=0);
|
|
||||||
// }
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (ch[0] < ' ') {
|
if (ch[0] < ' ') {
|
||||||
// Discard
|
// Discard
|
||||||
|
|||||||
@@ -193,6 +193,14 @@ void screen_set_cursors_alt_mode(bool app_mode);
|
|||||||
void screen_set_charset_n(int Gx);
|
void screen_set_charset_n(int Gx);
|
||||||
void screen_set_charset(int Gx, char charset);
|
void screen_set_charset(int Gx, char charset);
|
||||||
|
|
||||||
|
// tabs
|
||||||
|
|
||||||
|
void screen_clear_all_tabs(void);
|
||||||
|
void screen_set_tab(void);
|
||||||
|
void screen_clear_tab(void);
|
||||||
|
void screen_tab_forward(void);
|
||||||
|
void screen_tab_reverse(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a character in the cursor color, move to right with wrap.
|
* Set a character in the cursor color, move to right with wrap.
|
||||||
* The character may be ASCII (then only one char is used), or
|
* The character may be ASCII (then only one char is used), or
|
||||||
|
|||||||
Reference in New Issue
Block a user