support double lines

work
Ondřej Hruška 7 years ago
parent 5dbb592946
commit 78aaa949a3
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 3
      .gitignore
  2. 2
      front-end
  3. 24
      user/apars_short.c
  4. 112
      user/screen.c
  5. 7
      user/screen.h

3
.gitignore vendored

@ -20,4 +20,5 @@ cmake-build-debug/
.sass-cache .sass-cache
*.map *.map
.gitignore !.gitignore

@ -1 +1 @@
Subproject commit 30af1ad2f67cf100541e06ccd3760e9562f2f672 Subproject commit 0893b0a26886f64c0fa456a4cc69fef0992d7ad9

@ -94,21 +94,33 @@ apars_handle_space_cmd(char c)
void ICACHE_FLASH_ATTR apars_handle_hash_cmd(char c) void ICACHE_FLASH_ATTR apars_handle_hash_cmd(char c)
{ {
switch(c) { switch(c) {
case '1': // Double height, single width, top half (CUSTOM!)
screen_set_line_attr(1, 2, 1);
break;
case '2': // Double height, single width, bottom half (CUSTOM!)
screen_set_line_attr(1, 1, 2);
break;
case '3': // Double size, top half case '3': // Double size, top half
case '4': // Single size, bottom half screen_set_line_attr(2, 2, 1);
break;
case '4': // Double size, bottom half
screen_set_line_attr(2, 1, 2);
break;
case '5': // Single width, single height case '5': // Single width, single height
screen_set_line_attr(1, 1, 1);
break;
case '6': // Double width case '6': // Double width
ansi_noimpl("Double Size Line"); screen_set_line_attr(2, 1, 1);
break; break;
case '8': case '8':
screen_fill_with_E(); screen_fill_with_E();
break; break;
// development codes - do not use! // // development codes - do not use!
case '7': // case '7':
http_get("http://wtfismyip.com/text", NULL, http_callback_example); // http_get("http://wtfismyip.com/text", NULL, http_callback_example);
break; // break;
default: default:
ansi_noimpl("ESC # %c", c); ansi_noimpl("ESC # %c", c);

@ -39,6 +39,7 @@ static Cell screen[MAX_SCREEN_SIZE];
#define TABSTOP_WORDS 5 #define TABSTOP_WORDS 5
#define LINE_ATTRS_COUNT 64
/** /**
* Screen state structure * Screen state structure
*/ */
@ -57,9 +58,12 @@ static struct {
int vm1; int vm1;
u32 tab_stops[TABSTOP_WORDS]; // tab stops bitmap u32 tab_stops[TABSTOP_WORDS]; // tab stops bitmap
u8 line_attribs[LINE_ATTRS_COUNT]; // assume that's quite enough...
char last_char[4]; char last_char[4];
} scr; } scr;
#define IS_DOUBLE_WIDTH() (scr.line_attribs[cursor.y]&0b001)
#define TOP scr.vm0 #define TOP scr.vm0
#define BTM scr.vm1 #define BTM scr.vm1
#define RH (scr.vm1 - scr.vm0 + 1) #define RH (scr.vm1 - scr.vm0 + 1)
@ -551,7 +555,12 @@ screen_reset_sgr(void)
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
screen_reset_do(bool size, bool labels) screen_reset_do(bool size, bool labels)
{ {
ScreenNotifyTopics topics = TOPIC_CHANGE_SCREEN_OPTS | TOPIC_CHANGE_CURSOR | TOPIC_CHANGE_CONTENT_ALL; ScreenNotifyTopics topics =
TOPIC_CHANGE_SCREEN_OPTS
| TOPIC_CHANGE_CURSOR
| TOPIC_CHANGE_CONTENT_ALL
| TOPIC_DOUBLE_LINES;
NOTIFY_LOCK(); NOTIFY_LOCK();
// DECopts // DECopts
@ -588,6 +597,9 @@ screen_reset_do(bool size, bool labels)
scr.tab_stops[i] = 0x80808080; scr.tab_stops[i] = 0x80808080;
} }
// clear line attribs
memset(scr.line_attribs, 0, LINE_ATTRS_COUNT);
if (labels) { if (labels) {
strcpy(termconf_live.title, termconf->title); strcpy(termconf_live.title, termconf->title);
strcpy(termconf_live.backdrop, termconf->backdrop); strcpy(termconf_live.backdrop, termconf->backdrop);
@ -687,6 +699,32 @@ screen_swap_state(bool alternate)
//endregion //endregion
//region --- Double lines ---
void ICACHE_FLASH_ATTR
screen_set_line_attr(uint8_t double_w, uint8_t double_h_top, uint8_t double_h_bot)
{
NOTIFY_LOCK();
u8 attr = scr.line_attribs[cursor.y];
if (double_w==2) attr |= 0b001;
else if (double_w==1) attr &= ~0b001;
if (double_h_top==2) attr |= 0b010;
else if (double_h_top==1) attr &= ~0b010;
if (double_h_bot==2) attr |= 0b100;
else if (double_h_bot==1) attr &= ~0b100;
scr.line_attribs[cursor.y] = attr;
if (attr & 0b001) {
// if we're using double width - clamp cursor X position
// TODO this should happen in all cursor ops - now it can sometimes go offscreen
if (cursor.x >= W/2) cursor.x = W/2;
}
NOTIFY_DONE(TOPIC_DOUBLE_LINES);
}
//endregion
//region --- Tab stops --- //region --- Tab stops ---
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
@ -722,6 +760,7 @@ next_tab_stop(void)
{ {
// cursor must never go past EOL // cursor must never go past EOL
if (cursor.x >= W-1) return -1; if (cursor.x >= W-1) return -1;
if (IS_DOUBLE_WIDTH() && cursor.x >= W/2-1) return -1;
// find first word to inspect // find first word to inspect
int idx = (cursor.x+1)/32; int idx = (cursor.x+1)/32;
@ -733,6 +772,7 @@ next_tab_stop(void)
for(;offs<32;offs++) { for(;offs<32;offs++) {
cp++; cp++;
if (cp >= W) return -1; if (cp >= W) return -1;
if (IS_DOUBLE_WIDTH() && cp >= W/2) return -1;
if (w & 1) return cp; if (w & 1) return cp;
w >>= 1; w >>= 1;
} }
@ -790,6 +830,7 @@ screen_tab_forward(int count)
} }
else { else {
cursor.x = W - 1; cursor.x = W - 1;
if (IS_DOUBLE_WIDTH()) cursor.x = W/2 - 1;
} }
} }
NOTIFY_DONE(TOPIC_CHANGE_CURSOR); NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
@ -991,19 +1032,23 @@ screen_clear(ClearMode mode)
unicode_cache_clear(); unicode_cache_clear();
clear_range_noutf(0, W * H - 1); clear_range_noutf(0, W * H - 1);
scr.last_char[0] = 0; scr.last_char[0] = 0;
for (int i = 0; i < LINE_ATTRS_COUNT; i++) scr.line_attribs[i] = 0;
break; break;
case CLEAR_FROM_CURSOR: case CLEAR_FROM_CURSOR:
clear_range_utf((cursor.y * W) + cursor.x, W * H - 1); clear_range_utf((cursor.y * W) + cursor.x, W * H - 1);
expand_dirty(cursor.y, H-1, 0, W-1); expand_dirty(cursor.y, H-1, 0, W-1);
for (int i = cursor.y; i < LINE_ATTRS_COUNT; i++) scr.line_attribs[i] = 0;
break; break;
case CLEAR_TO_CURSOR: case CLEAR_TO_CURSOR:
clear_range_utf(0, (cursor.y * W) + cursor.x); clear_range_utf(0, (cursor.y * W) + cursor.x);
expand_dirty(0, cursor.y, 0, W-1); expand_dirty(0, cursor.y, 0, W-1);
for (int i = 0; i <= cursor.y; i++) scr.line_attribs[i] = 0;
break; break;
} }
NOTIFY_DONE(mode == CLEAR_ALL ? TOPIC_CHANGE_CONTENT_ALL : TOPIC_CHANGE_CONTENT_PART); NOTIFY_DONE((mode == CLEAR_ALL ? TOPIC_CHANGE_CONTENT_ALL : TOPIC_CHANGE_CONTENT_PART)
| TOPIC_DOUBLE_LINES);
} }
/** /**
@ -1055,11 +1100,15 @@ screen_insert_lines(unsigned int lines)
int targetStart = cursor.y + lines; int targetStart = cursor.y + lines;
if (targetStart > BTM) { if (targetStart > BTM) {
clear_range_utf(cursor.y*W, (BTM+1)*W-1); clear_range_utf(cursor.y*W, (BTM+1)*W-1);
for (int i = cursor.y; i <= BTM; i++) {
scr.line_attribs[i] = 0;
}
} else { } else {
// do the moving // do the moving
for (int i = BTM; i >= targetStart; i--) { for (int i = BTM; i >= targetStart; i--) {
utf_free_row(i); // release old characters utf_free_row(i); // release old characters
copy_row(i, i - lines); copy_row(i, i - lines);
scr.line_attribs[i] = scr.line_attribs[i-lines];
if (i != targetStart) utf_backup_row(i); if (i != targetStart) utf_backup_row(i);
} }
@ -1071,7 +1120,7 @@ screen_insert_lines(unsigned int lines)
} }
} }
expand_dirty(cursor.y, BTM, 0, W - 1); expand_dirty(cursor.y, BTM, 0, W - 1);
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART); NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART|TOPIC_DOUBLE_LINES);
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
@ -1086,18 +1135,26 @@ screen_delete_lines(unsigned int lines)
// clear the entire rest of the screen // clear the entire rest of the screen
movedBlockEnd = cursor.y; movedBlockEnd = cursor.y;
clear_range_utf(movedBlockEnd*W, (BTM+1)*W-1); clear_range_utf(movedBlockEnd*W, (BTM+1)*W-1);
for (int i = movedBlockEnd; i <= BTM; i++) {
scr.line_attribs[i] = 0;
}
} else { } else {
// move some lines up, clear the rest // move some lines up, clear the rest
for (int i = cursor.y; i <= movedBlockEnd; i++) { for (int i = cursor.y; i <= movedBlockEnd; i++) {
utf_free_row(i); utf_free_row(i);
copy_row(i, i+lines); copy_row(i, i+lines);
scr.line_attribs[i] = scr.line_attribs[i+lines];
if (i != movedBlockEnd) utf_backup_row(i); if (i != movedBlockEnd) utf_backup_row(i);
} }
clear_range_noutf((movedBlockEnd+1)*W, (BTM+1)*W-1); clear_range_noutf((movedBlockEnd+1)*W, (BTM+1)*W-1);
for (int i = movedBlockEnd+1; i <= BTM; i++) {
scr.line_attribs[i] = 0;
}
} }
expand_dirty(cursor.y, BTM, 0, W - 1); expand_dirty(cursor.y, BTM, 0, W - 1);
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART); NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART|TOPIC_DOUBLE_LINES);
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
@ -1304,6 +1361,9 @@ screen_scroll_up(unsigned int lines)
if (lines >= RH) { if (lines >= RH) {
// clear entire region // clear entire region
clear_range_utf(TOP * W, (BTM + 1) * W - 1); clear_range_utf(TOP * W, (BTM + 1) * W - 1);
for (int i = TOP; i <= BTM; i++) {
scr.line_attribs[i] = 0;
}
goto done; goto done;
} }
@ -1316,14 +1376,18 @@ screen_scroll_up(unsigned int lines)
for (y = TOP; y <= BTM - lines; y++) { for (y = TOP; y <= BTM - lines; y++) {
utf_free_row(y); utf_free_row(y);
copy_row(y, y+lines); copy_row(y, y+lines);
scr.line_attribs[y] = scr.line_attribs[y+lines];
if (y < BTM - lines) utf_backup_row(y); if (y < BTM - lines) utf_backup_row(y);
} }
clear_range_noutf(y * W, (BTM + 1) * W - 1); clear_range_noutf(y * W, (BTM + 1) * W - 1);
for (int i = y; i <= BTM; i++) {
scr.line_attribs[i] = 0;
}
done: done:
expand_dirty(TOP, BTM, 0, W - 1); expand_dirty(TOP, BTM, 0, W - 1);
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART); NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART|TOPIC_DOUBLE_LINES);
} }
/** /**
@ -1336,6 +1400,9 @@ screen_scroll_down(unsigned int lines)
if (lines >= RH) { if (lines >= RH) {
// clear entire region // clear entire region
clear_range_utf(TOP * W, (BTM + 1) * W - 1); clear_range_utf(TOP * W, (BTM + 1) * W - 1);
for (int i = TOP; i <= BTM; i++) {
scr.line_attribs[i] = 0;
}
goto done; goto done;
} }
@ -1348,13 +1415,17 @@ screen_scroll_down(unsigned int lines)
for (y = BTM; y >= TOP+lines; y--) { for (y = BTM; y >= TOP+lines; y--) {
utf_free_row(y); utf_free_row(y);
copy_row(y, y-lines); copy_row(y, y-lines);
scr.line_attribs[y] = scr.line_attribs[y-lines];
if (y > TOP + lines) utf_backup_row(y); if (y > TOP + lines) utf_backup_row(y);
} }
clear_range_noutf(TOP * W, TOP * W + lines * W - 1); clear_range_noutf(TOP * W, (TOP + lines) * W - 1);
for (int i = TOP; i < TOP + lines; i++) {
scr.line_attribs[i] = 0;
}
done: done:
expand_dirty(TOP, BTM, 0, W - 1); expand_dirty(TOP, BTM, 0, W - 1);
NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART); NOTIFY_DONE(TOPIC_CHANGE_CONTENT_PART|TOPIC_DOUBLE_LINES);
} }
/** Set scrolling region */ /** Set scrolling region */
@ -1459,6 +1530,9 @@ screen_cursor_set_x(int x)
// hanging happens when the cursor is virtually at col=81, which // hanging happens when the cursor is virtually at col=81, which
// cannot be set using the cursor-set commands. // cannot be set using the cursor-set commands.
cursor.hanging = false; cursor.hanging = false;
if (IS_DOUBLE_WIDTH() && cursor.x >= W/2) cursor.x = W/2-1;
NOTIFY_DONE(TOPIC_CHANGE_CURSOR); NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
} }
@ -1503,6 +1577,7 @@ screen_cursor_move(int dy, int dx, bool scroll)
cursor.x += dx; cursor.x += dx;
cursor.y += dy; cursor.y += dy;
if (cursor.x >= (int)W) cursor.x = W - 1; if (cursor.x >= (int)W) cursor.x = W - 1;
if (IS_DOUBLE_WIDTH() && cursor.x >= W/2) cursor.x = W/2-1;
if (cursor.x < (int)0) { if (cursor.x < (int)0) {
if (cursor.auto_wrap && cursor.reverse_wrap) { if (cursor.auto_wrap && cursor.reverse_wrap) {
// this is mimicking a behavior from xterm that allows any number of steps backwards with reverse wraparound enabled // this is mimicking a behavior from xterm that allows any number of steps backwards with reverse wraparound enabled
@ -1609,6 +1684,8 @@ screen_cursor_restore(bool withAttrs)
} }
} }
if (IS_DOUBLE_WIDTH() && cursor.x >= W/2) cursor.x = W/2-1;
NOTIFY_DONE(TOPIC_CHANGE_CURSOR); NOTIFY_DONE(TOPIC_CHANGE_CURSOR);
} }
@ -1977,6 +2054,10 @@ putchar_graphic(const char *ch)
cursor.hanging = true; // hanging - next typed char wraps around, but backspace and arrows still stay on the same line. cursor.hanging = true; // hanging - next typed char wraps around, but backspace and arrows still stay on the same line.
cursor.x = W - 1; cursor.x = W - 1;
} }
if (IS_DOUBLE_WIDTH() && cursor.x >= W/2) {
cursor.hanging = true; // hanging
cursor.x = W/2 - 1;
}
NOTIFY_DONE(topics); NOTIFY_DONE(topics);
return ch; return ch;
@ -2203,6 +2284,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, ScreenNotifyTopics topics,
#define TOPICMARK_CURSOR 'C' #define TOPICMARK_CURSOR 'C'
#define TOPICMARK_SCREEN 'S' #define TOPICMARK_SCREEN 'S'
#define TOPICMARK_BACKDROP 'W' #define TOPICMARK_BACKDROP 'W'
#define TOPICMARK_DBL_LINE 'H'
if (ss == NULL) { if (ss == NULL) {
// START! // START!
@ -2327,6 +2409,22 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, ScreenNotifyTopics topics,
bufput_utf8(termconf_live.font_size); bufput_utf8(termconf_live.font_size);
END_TOPIC END_TOPIC
BEGIN_TOPIC(TOPIC_DOUBLE_LINES, 70)
bufput_c(TOPICMARK_DBL_LINE);
int cnt = 0;
for (int i = 0; i < LINE_ATTRS_COUNT; i++) {
if (scr.line_attribs[i] != 0) cnt++;
}
bufput_utf8(cnt);
for (int i = 0; i < LINE_ATTRS_COUNT; i++) {
if (scr.line_attribs[i] != 0) {
bufput_utf8((i << 3) | (scr.line_attribs[i]&0b111));
}
}
END_TOPIC
BEGIN_TOPIC(TOPIC_CHANGE_TITLE, TERM_TITLE_LEN+4+1) BEGIN_TOPIC(TOPIC_CHANGE_TITLE, TERM_TITLE_LEN+4+1)
bufput_c(TOPICMARK_TITLE); bufput_c(TOPICMARK_TITLE);

@ -218,6 +218,7 @@ enum ScreenSerializeTopic {
TOPIC_BELL = (1<<7), // beep TOPIC_BELL = (1<<7), // beep
TOPIC_CHANGE_BACKDROP = (1<<8), TOPIC_CHANGE_BACKDROP = (1<<8),
TOPIC_CHANGE_STATIC_OPTS = (1<<9), TOPIC_CHANGE_STATIC_OPTS = (1<<9),
TOPIC_DOUBLE_LINES = (1<<10),
TOPIC_FLAG_NOCLEAN = (1<<15), // do not clean dirty extents TOPIC_FLAG_NOCLEAN = (1<<15), // do not clean dirty extents
// combos // combos
@ -228,7 +229,8 @@ enum ScreenSerializeTopic {
TOPIC_CHANGE_CURSOR | TOPIC_CHANGE_CURSOR |
TOPIC_CHANGE_TITLE | TOPIC_CHANGE_TITLE |
TOPIC_CHANGE_BACKDROP | TOPIC_CHANGE_BACKDROP |
TOPIC_CHANGE_BUTTONS, TOPIC_CHANGE_BUTTONS |
TOPIC_DOUBLE_LINES,
}; };
typedef u16 ScreenNotifyTopics; typedef u16 ScreenNotifyTopics;
@ -380,6 +382,9 @@ void screen_tab_reverse(int count);
/** Move left, shift right if at the boundary */ /** Move left, shift right if at the boundary */
void screen_back_index(int count); void screen_back_index(int count);
/** Set line attribs; 0-no change, 1,2 - single,double */
void screen_set_line_attr(uint8_t double_w, uint8_t double_h_top, uint8_t double_h_bot);
// --- Printing characters --- // --- Printing characters ---
/** /**

Loading…
Cancel
Save