3854
Revert commits 3824, 3850 and 3852. We'll redo them more carefully.
This commit is contained in:
parent
8195ed4ee9
commit
0c0d1ea5cd
|
@ -7,6 +7,7 @@
|
|||
:(before "End Globals")
|
||||
int Display_row = 0;
|
||||
int Display_column = 0;
|
||||
bool Autodisplay = true;
|
||||
|
||||
:(before "End Includes")
|
||||
#define CHECK_SCREEN \
|
||||
|
@ -37,7 +38,6 @@ case OPEN_CONSOLE: {
|
|||
:(before "End Primitive Recipe Implementations")
|
||||
case OPEN_CONSOLE: {
|
||||
tb_init();
|
||||
tb_clear();
|
||||
Display_row = Display_column = 0;
|
||||
int width = tb_width();
|
||||
int height = tb_height();
|
||||
|
@ -83,6 +83,21 @@ case CLEAR_DISPLAY: {
|
|||
break;
|
||||
}
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
SYNC_DISPLAY,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
put(Recipe_ordinal, "sync-display", SYNC_DISPLAY);
|
||||
:(before "End Primitive Recipe Checks")
|
||||
case SYNC_DISPLAY: {
|
||||
break;
|
||||
}
|
||||
:(before "End Primitive Recipe Implementations")
|
||||
case SYNC_DISPLAY: {
|
||||
CHECK_SCREEN;
|
||||
tb_sync();
|
||||
break;
|
||||
}
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
PRINT_CHARACTER_TO_DISPLAY,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
|
@ -118,7 +133,7 @@ case PRINT_CHARACTER_TO_DISPLAY: {
|
|||
int height = (h >= 0) ? h : 0;
|
||||
int width = (w >= 0) ? w : 0;
|
||||
int c = ingredients.at(0).at(0);
|
||||
int color = TB_WHITE;
|
||||
int color = TB_BLACK;
|
||||
if (SIZE(ingredients) > 1) {
|
||||
color = ingredients.at(1).at(0);
|
||||
}
|
||||
|
@ -133,6 +148,7 @@ case PRINT_CHARACTER_TO_DISPLAY: {
|
|||
Display_column = 0;
|
||||
++Display_row;
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -141,6 +157,7 @@ case PRINT_CHARACTER_TO_DISPLAY: {
|
|||
tb_change_cell(Display_column-1, Display_row, ' ', color, bg_color);
|
||||
--Display_column;
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -148,6 +165,7 @@ case PRINT_CHARACTER_TO_DISPLAY: {
|
|||
++Display_column;
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
}
|
||||
if (Autodisplay) tb_present();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -194,6 +212,7 @@ case MOVE_CURSOR_ON_DISPLAY: {
|
|||
Display_row = ingredients.at(0).at(0);
|
||||
Display_column = ingredients.at(1).at(0);
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -213,6 +232,7 @@ case MOVE_CURSOR_DOWN_ON_DISPLAY: {
|
|||
if (Display_row < height-1) {
|
||||
++Display_row;
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -231,6 +251,7 @@ case MOVE_CURSOR_UP_ON_DISPLAY: {
|
|||
if (Display_row > 0) {
|
||||
--Display_row;
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -251,6 +272,7 @@ case MOVE_CURSOR_RIGHT_ON_DISPLAY: {
|
|||
if (Display_column < width-1) {
|
||||
++Display_column;
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -269,6 +291,7 @@ case MOVE_CURSOR_LEFT_ON_DISPLAY: {
|
|||
if (Display_column > 0) {
|
||||
--Display_column;
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -284,6 +307,7 @@ void move_cursor_to_start_of_next_line_on_display() {
|
|||
else Display_row = 0;
|
||||
Display_column = 0;
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
}
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
|
@ -318,6 +342,67 @@ case DISPLAY_HEIGHT: {
|
|||
break;
|
||||
}
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
HIDE_CURSOR_ON_DISPLAY,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
put(Recipe_ordinal, "hide-cursor-on-display", HIDE_CURSOR_ON_DISPLAY);
|
||||
:(before "End Primitive Recipe Checks")
|
||||
case HIDE_CURSOR_ON_DISPLAY: {
|
||||
break;
|
||||
}
|
||||
:(before "End Primitive Recipe Implementations")
|
||||
case HIDE_CURSOR_ON_DISPLAY: {
|
||||
CHECK_SCREEN;
|
||||
tb_set_cursor(TB_HIDE_CURSOR, TB_HIDE_CURSOR);
|
||||
break;
|
||||
}
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
SHOW_CURSOR_ON_DISPLAY,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
put(Recipe_ordinal, "show-cursor-on-display", SHOW_CURSOR_ON_DISPLAY);
|
||||
:(before "End Primitive Recipe Checks")
|
||||
case SHOW_CURSOR_ON_DISPLAY: {
|
||||
break;
|
||||
}
|
||||
:(before "End Primitive Recipe Implementations")
|
||||
case SHOW_CURSOR_ON_DISPLAY: {
|
||||
CHECK_SCREEN;
|
||||
tb_set_cursor(Display_row, Display_column);
|
||||
break;
|
||||
}
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
HIDE_DISPLAY,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
put(Recipe_ordinal, "hide-display", HIDE_DISPLAY);
|
||||
:(before "End Primitive Recipe Checks")
|
||||
case HIDE_DISPLAY: {
|
||||
break;
|
||||
}
|
||||
:(before "End Primitive Recipe Implementations")
|
||||
case HIDE_DISPLAY: {
|
||||
CHECK_SCREEN;
|
||||
Autodisplay = false;
|
||||
break;
|
||||
}
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
SHOW_DISPLAY,
|
||||
:(before "End Primitive Recipe Numbers")
|
||||
put(Recipe_ordinal, "show-display", SHOW_DISPLAY);
|
||||
:(before "End Primitive Recipe Checks")
|
||||
case SHOW_DISPLAY: {
|
||||
break;
|
||||
}
|
||||
:(before "End Primitive Recipe Implementations")
|
||||
case SHOW_DISPLAY: {
|
||||
CHECK_SCREEN;
|
||||
Autodisplay = true;
|
||||
tb_present();
|
||||
break;
|
||||
}
|
||||
|
||||
//:: Keyboard/mouse management
|
||||
|
||||
:(before "End Primitive Recipe Declarations")
|
||||
|
@ -441,6 +526,7 @@ case CLEAR_LINE_ON_DISPLAY: {
|
|||
tb_change_cell(x, Display_row, ' ', TB_WHITE, TB_BLACK);
|
||||
}
|
||||
tb_set_cursor(Display_column, Display_row);
|
||||
if (Autodisplay) tb_present();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -466,5 +552,6 @@ case CLEAR_DISPLAY_FROM: {
|
|||
tb_change_cell(column, row, ' ', TB_WHITE, TB_BLACK);
|
||||
}
|
||||
}
|
||||
if (Autodisplay) tb_present();
|
||||
break;
|
||||
}
|
||||
|
|
59
081print.mu
59
081print.mu
|
@ -50,6 +50,13 @@ def clear-screen screen:&:screen -> screen:&:screen [
|
|||
*screen <- put *screen, cursor-column:offset, 0
|
||||
]
|
||||
|
||||
def sync-screen screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-if screen # do nothing for fake screens
|
||||
sync-display
|
||||
]
|
||||
|
||||
def fake-screen-is-empty? screen:&:screen -> result:bool [
|
||||
local-scope
|
||||
load-ingredients
|
||||
|
@ -101,27 +108,15 @@ def print screen:&:screen, c:char -> screen:&:screen [
|
|||
row:num <- get *screen, cursor-row:offset
|
||||
row <- round row
|
||||
legal?:bool <- greater-or-equal row, 0
|
||||
{
|
||||
break-if legal?
|
||||
row <- copy 0
|
||||
}
|
||||
return-unless legal?
|
||||
legal? <- lesser-than row, height
|
||||
{
|
||||
break-if legal?
|
||||
row <- subtract height, 1
|
||||
}
|
||||
return-unless legal?
|
||||
column:num <- get *screen, cursor-column:offset
|
||||
column <- round column
|
||||
legal? <- greater-or-equal column, 0
|
||||
{
|
||||
break-if legal?
|
||||
column <- copy 0
|
||||
}
|
||||
return-unless legal?
|
||||
legal? <- lesser-than column, width
|
||||
{
|
||||
break-if legal?
|
||||
column <- subtract width, 1
|
||||
}
|
||||
return-unless legal?
|
||||
#? $print [print-character (], row, [, ], column, [): ], c, 10/newline
|
||||
# special-case: newline
|
||||
{
|
||||
|
@ -609,6 +604,38 @@ def screen-height screen:&:screen -> height:num [
|
|||
height <- display-height
|
||||
]
|
||||
|
||||
def hide-cursor screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-if screen # fake screen; do nothing
|
||||
# real screen
|
||||
hide-cursor-on-display
|
||||
]
|
||||
|
||||
def show-cursor screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-if screen # fake screen; do nothing
|
||||
# real screen
|
||||
show-cursor-on-display
|
||||
]
|
||||
|
||||
def hide-screen screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-if screen # fake screen; do nothing
|
||||
# real screen
|
||||
hide-display
|
||||
]
|
||||
|
||||
def show-screen screen:&:screen -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
return-if screen # fake screen; do nothing
|
||||
# real screen
|
||||
show-display
|
||||
]
|
||||
|
||||
def print screen:&:screen, s:text -> screen:&:screen [
|
||||
local-scope
|
||||
load-ingredients
|
||||
|
|
|
@ -276,6 +276,7 @@ bool start_search_editor(search_direction dir) {
|
|||
tb_change_cell(col, bottom_screen_line, '/', TB_WHITE, TB_BLACK);
|
||||
++col;
|
||||
tb_set_cursor(col, bottom_screen_line);
|
||||
tb_present();
|
||||
string pattern;
|
||||
while (true) {
|
||||
int key = read_key();
|
||||
|
@ -293,21 +294,25 @@ bool start_search_editor(search_direction dir) {
|
|||
if (col > /*slash*/1) {
|
||||
--col;
|
||||
tb_set_cursor(col, bottom_screen_line);
|
||||
tb_present();
|
||||
}
|
||||
}
|
||||
else if (key == TB_KEY_ARROW_RIGHT) {
|
||||
if (col-/*slash*/1 < SIZE(pattern)) {
|
||||
++col;
|
||||
tb_set_cursor(col, bottom_screen_line);
|
||||
tb_present();
|
||||
}
|
||||
}
|
||||
else if (key == TB_KEY_HOME || key == TB_KEY_CTRL_A) {
|
||||
col = /*skip slash*/1;
|
||||
tb_set_cursor(col, bottom_screen_line);
|
||||
tb_present();
|
||||
}
|
||||
else if (key == TB_KEY_END || key == TB_KEY_CTRL_E) {
|
||||
col = SIZE(pattern)+/*skip slash*/1;
|
||||
tb_set_cursor(col, bottom_screen_line);
|
||||
tb_present();
|
||||
}
|
||||
else if (key == TB_KEY_BACKSPACE || key == TB_KEY_BACKSPACE2) {
|
||||
if (col > /*slash*/1) {
|
||||
|
@ -325,6 +330,7 @@ bool start_search_editor(search_direction dir) {
|
|||
tb_change_cell(SIZE(pattern)+/*skip slash*/1, bottom_screen_line, ' ', TB_WHITE, TB_BLACK);
|
||||
}
|
||||
tb_set_cursor(col, bottom_screen_line);
|
||||
tb_present();
|
||||
}
|
||||
}
|
||||
else if (key == TB_KEY_CTRL_K) {
|
||||
|
@ -333,6 +339,7 @@ bool start_search_editor(search_direction dir) {
|
|||
for (int x = col; x < old_pattern_size+/*slash*/1; ++x)
|
||||
tb_change_cell(x, bottom_screen_line, ' ', TB_WHITE, TB_BLACK);
|
||||
tb_set_cursor(col, bottom_screen_line);
|
||||
tb_present();
|
||||
}
|
||||
else if (key == TB_KEY_CTRL_U) {
|
||||
int old_pattern_size = SIZE(pattern);
|
||||
|
@ -342,6 +349,7 @@ bool start_search_editor(search_direction dir) {
|
|||
for (int x = SIZE(pattern)+/*slash*/1; x < old_pattern_size+/*skip slash*/1; ++x)
|
||||
tb_change_cell(x, bottom_screen_line, ' ', TB_WHITE, TB_BLACK);
|
||||
tb_set_cursor(/*start of pattern skipping slash*/1, bottom_screen_line);
|
||||
tb_present();
|
||||
}
|
||||
else if (key < 128) { // ascii only
|
||||
// update pattern
|
||||
|
@ -352,6 +360,7 @@ bool start_search_editor(search_direction dir) {
|
|||
tb_change_cell(x, bottom_screen_line, pattern.at(x-/*slash*/1), TB_WHITE, TB_BLACK);
|
||||
++col;
|
||||
tb_set_cursor(col, bottom_screen_line);
|
||||
tb_present();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -435,6 +444,7 @@ void render() {
|
|||
render_line(screen_row, "~", /*cursor_line?*/false);
|
||||
// move cursor back to display row at the end
|
||||
tb_set_cursor(0, Display_row);
|
||||
tb_present();
|
||||
}
|
||||
|
||||
int lines_hidden(int screen_row) {
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
0. main's ingredients
|
||||
1. assertion failures or errors inside scenarios
|
||||
2. screen background color
|
||||
3. more touch event types
|
||||
4. sandbox isolation
|
||||
5. errors in reading/writing files (missing directory, others?)
|
||||
6. has-more-events?
|
||||
3. has-more-events?
|
||||
4. hide/show screen
|
||||
5. more touch event types
|
||||
6. sandbox isolation
|
||||
7. errors in reading/writing files (missing directory, others?)
|
||||
|
||||
termbox issues are implementation-specific and not worth testing:
|
||||
whether we clear junk from other processes
|
||||
latency in interpreting low-level escape characters
|
||||
|
||||
calls to update-cursor are currently duplicated:
|
||||
|
|
|
@ -6,8 +6,10 @@ def main text:text [
|
|||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
hide-screen 0/screen
|
||||
e:&:editor <- new-editor text, 0/left, 5/right
|
||||
render 0/screen, e
|
||||
show-screen 0/screen
|
||||
wait-for-event 0/console
|
||||
close-console
|
||||
]
|
||||
|
|
|
@ -266,17 +266,10 @@ def editor-render screen:&:screen, editor:&:editor -> screen:&:screen, editor:&:
|
|||
left:num <- get *editor, left:offset
|
||||
right:num <- get *editor, right:offset
|
||||
row:num, column:num <- render screen, editor
|
||||
screen-height:num <- screen-height screen
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-line-until screen, right
|
||||
row <- add row, 1
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
draw-horizontal screen, row, left, right, 9480/horizontal-dotted
|
||||
row <- add row, 1
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources:
|
|||
}
|
||||
# if it's not global and not a touch event, send to appropriate editor
|
||||
{
|
||||
hide-screen screen
|
||||
sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset
|
||||
{
|
||||
break-if sandbox-in-focus?
|
||||
|
@ -115,6 +116,7 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources:
|
|||
screen <- render-all screen, env, render
|
||||
}
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
show-screen screen
|
||||
}
|
||||
loop
|
||||
}
|
||||
|
@ -393,6 +395,7 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr
|
|||
local-scope
|
||||
load-ingredients
|
||||
trace 10, [app], [render all]
|
||||
hide-screen screen
|
||||
# top menu
|
||||
trace 11, [app], [render top menu]
|
||||
width:num <- screen-width screen
|
||||
|
@ -416,6 +419,8 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr
|
|||
current-sandbox:&:editor <- get *env, current-sandbox:offset
|
||||
sandbox-in-focus?:bool <- get *env, sandbox-in-focus?:offset
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
#
|
||||
show-screen screen
|
||||
]
|
||||
|
||||
def render-recipes screen:&:screen, env:&:environment, {render-editor: (recipe (address screen) (address editor) -> number number (address screen) (address editor))} -> screen:&:screen, env:&:environment [
|
||||
|
@ -427,19 +432,12 @@ def render-recipes screen:&:screen, env:&:environment, {render-editor: (recipe (
|
|||
left:num <- get *recipes, left:offset
|
||||
right:num <- get *recipes, right:offset
|
||||
row:num, column:num, screen <- call render-editor, screen, recipes
|
||||
screen-height:num <- screen-height screen
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-line-until screen, right
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
<render-recipe-components-end>
|
||||
# draw dotted line after recipes
|
||||
draw-horizontal screen, row, left, right, 9480/horizontal-dotted
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
|
@ -451,18 +449,11 @@ def render-sandbox-side screen:&:screen, env:&:environment, {render-editor: (rec
|
|||
left:num <- get *current-sandbox, left:offset
|
||||
right:num <- get *current-sandbox, right:offset
|
||||
row:num, column:num, screen, current-sandbox <- call render-editor, screen, current-sandbox
|
||||
screen-height:num <- screen-height screen
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-line-until screen, right
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
# draw solid line after code (you'll see why in later layers)
|
||||
draw-horizontal screen, row, left, right
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
|
@ -483,6 +474,18 @@ def update-cursor screen:&:screen, recipes:&:editor, current-sandbox:&:editor, s
|
|||
screen <- move-cursor screen, cursor-row, cursor-column
|
||||
]
|
||||
|
||||
# ctrl-l - redraw screen (just in case it printed junk somehow)
|
||||
|
||||
after <global-type> [
|
||||
{
|
||||
redraw-screen?:bool <- equal c, 12/ctrl-l
|
||||
break-unless redraw-screen?
|
||||
screen <- render-all screen, env:&:environment, render
|
||||
sync-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
||||
# ctrl-n - switch focus
|
||||
# todo: test this
|
||||
|
||||
|
|
|
@ -245,26 +245,19 @@ def! render-sandbox-side screen:&:screen, env:&:environment, {render-editor: (re
|
|||
row:num, column:num <- copy 1, 0
|
||||
left:num <- get *current-sandbox, left:offset
|
||||
right:num <- get *current-sandbox, right:offset
|
||||
screen-height:num <- screen-height screen
|
||||
# render sandbox editor
|
||||
render-from:num <- get *env, render-from:offset
|
||||
{
|
||||
render-current-sandbox?:bool <- equal render-from, -1
|
||||
break-unless render-current-sandbox?
|
||||
row, column, screen, current-sandbox <- call render-editor, screen, current-sandbox
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-screen-from screen, row, column, left, right
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
}
|
||||
# render sandboxes
|
||||
draw-horizontal screen, row, left, right
|
||||
sandbox:&:sandbox <- get *env, sandbox:offset
|
||||
row, screen <- render-sandboxes screen, sandbox, left, right, row, render-from
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-rest-of-screen screen, row, left, right
|
||||
]
|
||||
|
||||
|
@ -280,22 +273,16 @@ def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, ro
|
|||
break-if hidden?
|
||||
# render sandbox menu
|
||||
row <- add row, 1
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
screen <- move-cursor screen, row, left
|
||||
screen <- render-sandbox-menu screen, idx, left, right
|
||||
# save menu row so we can detect clicks to it later
|
||||
*sandbox <- put *sandbox, starting-row-on-screen:offset, row
|
||||
# render sandbox contents
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
screen <- move-cursor screen, row, left
|
||||
sandbox-data:text <- get *sandbox, data:offset
|
||||
row, screen <- render-code screen, sandbox-data, left, right, row
|
||||
*sandbox <- put *sandbox, code-ending-row-on-screen:offset, row
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
# render sandbox warnings, screen or response, in that order
|
||||
sandbox-response:text <- get *sandbox, response:offset
|
||||
<render-sandbox-results>
|
||||
|
@ -311,8 +298,8 @@ def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, ro
|
|||
row, screen <- render-text screen, sandbox-response, left, right, 245/grey, row
|
||||
}
|
||||
+render-sandbox-end
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
at-bottom?:bool <- greater-or-equal row, screen-height
|
||||
return-if at-bottom?
|
||||
# draw solid line after sandbox
|
||||
draw-horizontal screen, row, left, right
|
||||
}
|
||||
|
@ -324,8 +311,6 @@ def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, ro
|
|||
<end-render-sandbox-reset-hidden>
|
||||
}
|
||||
# draw next sandbox
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
next-sandbox:&:sandbox <- get *sandbox, next-sandbox:offset
|
||||
next-idx:num <- add idx, 1
|
||||
row, screen <- render-sandboxes screen, next-sandbox, left, right, row, render-from, next-idx
|
||||
|
@ -426,8 +411,6 @@ def render-text screen:&:screen, s:text, left:num, right:num, color:num, row:num
|
|||
column <- add column, 1
|
||||
loop
|
||||
}
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
was-at-left?:bool <- equal column, left
|
||||
clear-line-until screen, right
|
||||
{
|
||||
|
@ -508,8 +491,6 @@ def render-code screen:&:screen, s:text, left:num, right:num, row:num -> row:num
|
|||
column <- add column, 1
|
||||
loop
|
||||
}
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
was-at-left?:bool <- equal column, left
|
||||
clear-line-until screen, right
|
||||
{
|
||||
|
@ -990,8 +971,10 @@ after <global-keypress> [
|
|||
render-from <- add render-from, 1
|
||||
*env <- put *env, render-from:offset, render-from
|
||||
}
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
@ -1020,8 +1003,10 @@ after <global-keypress> [
|
|||
break-if at-beginning?
|
||||
render-from <- subtract render-from, 1
|
||||
*env <- put *env, render-from:offset, render-from
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -128,8 +128,10 @@ after <global-touch> [
|
|||
break-unless copy?
|
||||
copy?, env <- try-copy-sandbox click-row, env
|
||||
break-unless copy?
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -72,8 +72,10 @@ after <global-touch> [
|
|||
break-unless delete?
|
||||
delete?, env <- try-delete-sandbox click-row, env
|
||||
break-unless delete?
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -111,8 +111,10 @@ after <global-touch> [
|
|||
break-unless edit?
|
||||
edit?, env <- try-edit-sandbox click-row, env
|
||||
break-unless edit?
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -130,8 +130,10 @@ after <global-touch> [
|
|||
# toggle its expected-response, and save session
|
||||
sandbox <- toggle-expected-response sandbox
|
||||
save-sandboxes env, resources
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -200,8 +200,10 @@ after <global-touch> [
|
|||
x:bool <- get *sandbox, display-trace?:offset
|
||||
x <- not x
|
||||
*sandbox <- put *sandbox, display-trace?:offset, x
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -6,8 +6,10 @@ def main text:text [
|
|||
local-scope
|
||||
load-ingredients
|
||||
open-console
|
||||
hide-screen 0/screen
|
||||
e:&:editor <- new-editor text, 0/left, 5/right
|
||||
render 0/screen, e
|
||||
show-screen 0/screen
|
||||
wait-for-event 0/console
|
||||
close-console
|
||||
]
|
||||
|
|
|
@ -266,17 +266,10 @@ def editor-render screen:&:screen, editor:&:editor -> screen:&:screen, editor:&:
|
|||
left:num <- get *editor, left:offset
|
||||
right:num <- get *editor, right:offset
|
||||
row:num, column:num <- render screen, editor
|
||||
screen-height:num <- screen-height screen
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-line-until screen, right
|
||||
row <- add row, 1
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
draw-horizontal screen, row, left, right, 9480/horizontal-dotted
|
||||
row <- add row, 1
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources:
|
|||
}
|
||||
# not global and not a touch event
|
||||
{
|
||||
hide-screen screen
|
||||
render?:bool <- handle-keyboard-event screen, current-sandbox, e:event
|
||||
break-unless render?
|
||||
# try to batch up rendering if there are more events queued up
|
||||
|
@ -89,6 +90,9 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources:
|
|||
break-unless render-all-on-no-more-events?
|
||||
screen <- render-all screen, env, render
|
||||
}
|
||||
+finish-event
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
show-screen screen
|
||||
}
|
||||
loop
|
||||
}
|
||||
|
@ -194,6 +198,7 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr
|
|||
local-scope
|
||||
load-ingredients
|
||||
trace 10, [app], [render all]
|
||||
hide-screen screen
|
||||
# top menu
|
||||
trace 11, [app], [render top menu]
|
||||
width:num <- screen-width screen
|
||||
|
@ -209,6 +214,8 @@ def render-all screen:&:screen, env:&:environment, {render-editor: (recipe (addr
|
|||
#
|
||||
current-sandbox:&:editor <- get *env, current-sandbox:offset
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
#
|
||||
show-screen screen
|
||||
]
|
||||
|
||||
# replaced in a later layer
|
||||
|
@ -219,18 +226,11 @@ def render-sandbox-side screen:&:screen, env:&:environment, {render-editor: (rec
|
|||
left:num <- get *current-sandbox, left:offset
|
||||
right:num <- get *current-sandbox, right:offset
|
||||
row:num, column:num, screen, current-sandbox <- call render-editor, screen, current-sandbox
|
||||
screen-height:num <- screen-height screen
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-line-until screen, right
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
# draw solid line after code (you'll see why in later layers)
|
||||
draw-horizontal screen, row, left, right
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-screen-from screen, row, left, left, right
|
||||
]
|
||||
|
||||
|
@ -242,3 +242,15 @@ def update-cursor screen:&:screen, current-sandbox:&:editor, env:&:environment -
|
|||
cursor-column:num <- get *current-sandbox, cursor-column:offset
|
||||
screen <- move-cursor screen, cursor-row, cursor-column
|
||||
]
|
||||
|
||||
# ctrl-l - redraw screen (just in case it printed junk somehow)
|
||||
|
||||
after <global-type> [
|
||||
{
|
||||
redraw-screen?:bool <- equal c, 12/ctrl-l
|
||||
break-unless redraw-screen?
|
||||
screen <- render-all screen, env:&:environment, render
|
||||
sync-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -234,26 +234,19 @@ def! render-sandbox-side screen:&:screen, env:&:environment, {render-editor: (re
|
|||
row:num, column:num <- copy 1, 0
|
||||
left:num <- get *current-sandbox, left:offset
|
||||
right:num <- get *current-sandbox, right:offset
|
||||
screen-height:num <- screen-height screen
|
||||
# render sandbox editor
|
||||
render-from:num <- get *env, render-from:offset
|
||||
{
|
||||
render-current-sandbox?:bool <- equal render-from, -1
|
||||
break-unless render-current-sandbox?
|
||||
row, column, screen, current-sandbox <- call render-editor, screen, current-sandbox
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-screen-from screen, row, column, left, right
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
}
|
||||
# render sandboxes
|
||||
draw-horizontal screen, row, left, right
|
||||
sandbox:&:sandbox <- get *env, sandbox:offset
|
||||
row, screen <- render-sandboxes screen, sandbox, left, right, row, render-from, 0, env
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
clear-rest-of-screen screen, row, left, right
|
||||
]
|
||||
|
||||
|
@ -270,22 +263,16 @@ def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, ro
|
|||
break-if hidden?
|
||||
# render sandbox menu
|
||||
row <- add row, 1
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
screen <- move-cursor screen, row, left
|
||||
screen <- render-sandbox-menu screen, idx, left, right
|
||||
# save menu row so we can detect clicks to it later
|
||||
*sandbox <- put *sandbox, starting-row-on-screen:offset, row
|
||||
# render sandbox contents
|
||||
row <- add row, 1
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
screen <- move-cursor screen, row, left
|
||||
sandbox-data:text <- get *sandbox, data:offset
|
||||
row, screen <- render-code screen, sandbox-data, left, right, row
|
||||
*sandbox <- put *sandbox, code-ending-row-on-screen:offset, row
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
# render sandbox warnings, screen or response, in that order
|
||||
sandbox-response:text <- get *sandbox, response:offset
|
||||
<render-sandbox-results>
|
||||
|
@ -301,8 +288,8 @@ def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, ro
|
|||
row, screen <- render-text screen, sandbox-response, left, right, 245/grey, row
|
||||
}
|
||||
+render-sandbox-end
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
at-bottom?:bool <- greater-or-equal row, screen-height
|
||||
return-if at-bottom?
|
||||
# draw solid line after sandbox
|
||||
draw-horizontal screen, row, left, right
|
||||
}
|
||||
|
@ -314,8 +301,6 @@ def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, ro
|
|||
<end-render-sandbox-reset-hidden>
|
||||
}
|
||||
# draw next sandbox
|
||||
space-left? <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
next-sandbox:&:sandbox <- get *sandbox, next-sandbox:offset
|
||||
next-idx:num <- add idx, 1
|
||||
row, screen <- render-sandboxes screen, next-sandbox, left, right, row, render-from, next-idx, env
|
||||
|
@ -416,8 +401,6 @@ def render-text screen:&:screen, s:text, left:num, right:num, color:num, row:num
|
|||
column <- add column, 1
|
||||
loop
|
||||
}
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
was-at-left?:bool <- equal column, left
|
||||
clear-line-until screen, right
|
||||
{
|
||||
|
@ -483,8 +466,6 @@ def render-code screen:&:screen, s:text, left:num, right:num, row:num -> row:num
|
|||
column <- add column, 1
|
||||
loop
|
||||
}
|
||||
space-left?:bool <- lesser-than row, screen-height
|
||||
return-unless space-left?
|
||||
was-at-left?:bool <- equal column, left
|
||||
clear-line-until screen, right
|
||||
{
|
||||
|
@ -812,9 +793,10 @@ after <global-keypress> [
|
|||
render-from <- add render-from, 1
|
||||
*env <- put *env, render-from:offset, render-from
|
||||
}
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
loop +next-event
|
||||
show-screen screen
|
||||
jump +finish-event
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -840,9 +822,10 @@ after <global-keypress> [
|
|||
break-if at-beginning?
|
||||
render-from <- subtract render-from, 1
|
||||
*env <- put *env, render-from:offset, render-from
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
loop +next-event
|
||||
show-screen screen
|
||||
jump +finish-event
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -140,8 +140,10 @@ after <global-touch> [
|
|||
break-unless copy?
|
||||
copy?, env <- try-copy-sandbox click-row, env
|
||||
break-unless copy?
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -69,8 +69,10 @@ after <global-touch> [
|
|||
break-unless delete?
|
||||
delete?, env <- try-delete-sandbox click-row, env
|
||||
break-unless delete?
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -111,8 +111,10 @@ after <global-touch> [
|
|||
break-unless edit?
|
||||
edit?, env <- try-edit-sandbox click-row, env
|
||||
break-unless edit?
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -132,8 +132,10 @@ after <global-touch> [
|
|||
# toggle its expected-response, and save session
|
||||
sandbox <- toggle-expected-response sandbox
|
||||
save-sandboxes env, resources
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -190,8 +190,10 @@ after <global-touch> [
|
|||
x:bool <- get *sandbox, display-trace?:offset
|
||||
x <- not x
|
||||
*sandbox <- put *sandbox, display-trace?:offset, x
|
||||
hide-screen screen
|
||||
screen <- render-sandbox-side screen, env, render
|
||||
screen <- update-cursor screen, current-sandbox, env
|
||||
show-screen screen
|
||||
loop +next-event
|
||||
}
|
||||
]
|
||||
|
|
|
@ -23,10 +23,20 @@ extern int wcwidth (wchar_t);
|
|||
#include "output.inl"
|
||||
#include "input.inl"
|
||||
|
||||
struct cellbuf {
|
||||
int width;
|
||||
int height;
|
||||
struct tb_cell *cells;
|
||||
};
|
||||
|
||||
#define CELL(buf, x, y) (buf)->cells[(y) * (buf)->width + (x)]
|
||||
#define IS_CURSOR_HIDDEN(cx, cy) (cx == -1 || cy == -1)
|
||||
#define LAST_COORD_INIT -1
|
||||
|
||||
static struct termios orig_tios;
|
||||
|
||||
static struct cellbuf back_buffer;
|
||||
static struct cellbuf front_buffer;
|
||||
static struct bytebuffer output_buffer;
|
||||
static struct bytebuffer input_buffer;
|
||||
|
||||
|
@ -47,6 +57,11 @@ static uint16_t foreground = TB_WHITE;
|
|||
static void write_cursor(int x, int y);
|
||||
static void write_sgr(uint16_t fg, uint16_t bg);
|
||||
|
||||
static void cellbuf_init(struct cellbuf *buf, int width, int height);
|
||||
static void cellbuf_resize(struct cellbuf *buf, int width, int height);
|
||||
static void cellbuf_clear(struct cellbuf *buf);
|
||||
static void cellbuf_free(struct cellbuf *buf);
|
||||
|
||||
static void update_size(void);
|
||||
static void update_term_size(void);
|
||||
static void send_attr(uint16_t fg, uint16_t bg);
|
||||
|
@ -104,9 +119,14 @@ int tb_init(void)
|
|||
bytebuffer_puts(&output_buffer, funcs[T_ENTER_KEYPAD]);
|
||||
bytebuffer_puts(&output_buffer, funcs[T_ENTER_MOUSE]);
|
||||
bytebuffer_puts(&output_buffer, funcs[T_ENTER_BRACKETED_PASTE]);
|
||||
bytebuffer_flush(&output_buffer, inout);
|
||||
send_clear();
|
||||
|
||||
update_term_size();
|
||||
cellbuf_init(&back_buffer, termw, termh);
|
||||
cellbuf_init(&front_buffer, termw, termh);
|
||||
cellbuf_clear(&back_buffer);
|
||||
cellbuf_clear(&front_buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -126,6 +146,8 @@ void tb_shutdown(void)
|
|||
close(winch_fds[0]);
|
||||
close(winch_fds[1]);
|
||||
|
||||
cellbuf_free(&back_buffer);
|
||||
cellbuf_free(&front_buffer);
|
||||
bytebuffer_free(&output_buffer);
|
||||
bytebuffer_free(&input_buffer);
|
||||
termw = termh = -1;
|
||||
|
@ -136,21 +158,88 @@ int tb_is_active(void)
|
|||
return termw != -1;
|
||||
}
|
||||
|
||||
static void tb_repaint(bool force) {
|
||||
int x,y,w,i;
|
||||
struct tb_cell *back, *front;
|
||||
|
||||
assert(termw != -1);
|
||||
|
||||
/* invalidate cursor position */
|
||||
lastx = LAST_COORD_INIT;
|
||||
lasty = LAST_COORD_INIT;
|
||||
|
||||
if (buffer_size_change_request) {
|
||||
update_size();
|
||||
buffer_size_change_request = 0;
|
||||
}
|
||||
|
||||
for (y = 0; y < front_buffer.height; ++y) {
|
||||
for (x = 0; x < front_buffer.width; ) {
|
||||
back = &CELL(&back_buffer, x, y);
|
||||
front = &CELL(&front_buffer, x, y);
|
||||
w = wcwidth(back->ch);
|
||||
if (w < 1) w = 1;
|
||||
if (!force && memcmp(back, front, sizeof(struct tb_cell)) == 0) {
|
||||
x += w;
|
||||
continue;
|
||||
}
|
||||
memcpy(front, back, sizeof(struct tb_cell));
|
||||
send_attr(back->fg, back->bg);
|
||||
if (w > 1 && x >= front_buffer.width - (w - 1)) {
|
||||
// Not enough room for wide ch, so send spaces
|
||||
for (i = x; i < front_buffer.width; ++i) {
|
||||
send_char(i, y, ' ');
|
||||
}
|
||||
} else {
|
||||
send_char(x, y, back->ch);
|
||||
for (i = 1; i < w; ++i) {
|
||||
front = &CELL(&front_buffer, x + i, y);
|
||||
front->ch = 0;
|
||||
front->fg = back->fg;
|
||||
front->bg = back->bg;
|
||||
}
|
||||
}
|
||||
x += w;
|
||||
}
|
||||
}
|
||||
if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y))
|
||||
write_cursor(cursor_x, cursor_y);
|
||||
bytebuffer_flush(&output_buffer, inout);
|
||||
}
|
||||
|
||||
void tb_present(void)
|
||||
{
|
||||
tb_repaint(false);
|
||||
}
|
||||
|
||||
void tb_sync(void)
|
||||
{
|
||||
tb_repaint(true);
|
||||
}
|
||||
|
||||
void tb_set_cursor(int cx, int cy)
|
||||
{
|
||||
assert(termw != -1);
|
||||
cursor_x = cx;
|
||||
cursor_y = cy;
|
||||
write_cursor(cursor_x, cursor_y);
|
||||
bytebuffer_flush(&output_buffer, inout);
|
||||
if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y))
|
||||
write_cursor(cursor_x, cursor_y);
|
||||
}
|
||||
|
||||
void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg)
|
||||
{
|
||||
assert(termw != -1);
|
||||
send_attr(fg, bg);
|
||||
send_char(x, y, ch);
|
||||
bytebuffer_flush(&output_buffer, inout);
|
||||
if ((unsigned)x >= (unsigned)back_buffer.width)
|
||||
return;
|
||||
if ((unsigned)y >= (unsigned)back_buffer.height)
|
||||
return;
|
||||
struct tb_cell c = {ch, fg, bg};
|
||||
CELL(&back_buffer, x, y) = c;
|
||||
}
|
||||
|
||||
struct tb_cell *tb_cell_buffer()
|
||||
{
|
||||
return back_buffer.cells;
|
||||
}
|
||||
|
||||
int tb_poll_event(struct tb_event *event)
|
||||
|
@ -187,7 +276,7 @@ void tb_clear(void)
|
|||
update_size();
|
||||
buffer_size_change_request = 0;
|
||||
}
|
||||
send_clear();
|
||||
cellbuf_clear(&back_buffer);
|
||||
}
|
||||
|
||||
void tb_set_clear_attributes(uint16_t fg, uint16_t bg)
|
||||
|
@ -236,6 +325,56 @@ static void write_sgr(uint16_t fg, uint16_t bg) {
|
|||
WRITE_LITERAL("m");
|
||||
}
|
||||
|
||||
static void cellbuf_init(struct cellbuf *buf, int width, int height)
|
||||
{
|
||||
buf->cells = (struct tb_cell*)malloc(sizeof(struct tb_cell) * width * height);
|
||||
assert(buf->cells);
|
||||
buf->width = width;
|
||||
buf->height = height;
|
||||
}
|
||||
|
||||
static void cellbuf_resize(struct cellbuf *buf, int width, int height)
|
||||
{
|
||||
if (buf->width == width && buf->height == height)
|
||||
return;
|
||||
|
||||
int oldw = buf->width;
|
||||
int oldh = buf->height;
|
||||
struct tb_cell *oldcells = buf->cells;
|
||||
|
||||
cellbuf_init(buf, width, height);
|
||||
cellbuf_clear(buf);
|
||||
|
||||
int minw = (width < oldw) ? width : oldw;
|
||||
int minh = (height < oldh) ? height : oldh;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < minh; ++i) {
|
||||
struct tb_cell *csrc = oldcells + (i * oldw);
|
||||
struct tb_cell *cdst = buf->cells + (i * width);
|
||||
memcpy(cdst, csrc, sizeof(struct tb_cell) * minw);
|
||||
}
|
||||
|
||||
free(oldcells);
|
||||
}
|
||||
|
||||
static void cellbuf_clear(struct cellbuf *buf)
|
||||
{
|
||||
int i;
|
||||
int ncells = buf->width * buf->height;
|
||||
|
||||
for (i = 0; i < ncells; ++i) {
|
||||
buf->cells[i].ch = ' ';
|
||||
buf->cells[i].fg = foreground;
|
||||
buf->cells[i].bg = background;
|
||||
}
|
||||
}
|
||||
|
||||
static void cellbuf_free(struct cellbuf *buf)
|
||||
{
|
||||
free(buf->cells);
|
||||
}
|
||||
|
||||
static void get_term_size(int *w, int *h)
|
||||
{
|
||||
struct winsize sz;
|
||||
|
@ -329,6 +468,9 @@ static void sigwinch_handler(int xxx)
|
|||
static void update_size(void)
|
||||
{
|
||||
update_term_size();
|
||||
cellbuf_resize(&back_buffer, termw, termh);
|
||||
cellbuf_resize(&front_buffer, termw, termh);
|
||||
cellbuf_clear(&front_buffer);
|
||||
send_clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,18 @@ extern "C" {
|
|||
/*** 1. Controlling the screen. */
|
||||
|
||||
/* The screen is a 2D array of cells. */
|
||||
struct tb_cell {
|
||||
uint32_t ch; /* unicode character */
|
||||
uint16_t fg; /* foreground color (0-255) and attributes */
|
||||
uint16_t bg; /* background color (0-255) and attributes */
|
||||
};
|
||||
|
||||
/* Names for some colors. */
|
||||
/* Names for some colors in tb_cell.fg and tb_cell.bg. */
|
||||
#define TB_BLACK 232
|
||||
#define TB_WHITE 255
|
||||
|
||||
/* Some attributes of screen cells that can be combined with colors using bitwise-OR. */
|
||||
/* Colors in tb_cell can be combined using bitwise-OR with multiple
|
||||
* of the following attributes. */
|
||||
#define TB_BOLD 0x0100
|
||||
#define TB_UNDERLINE 0x0200
|
||||
#define TB_REVERSE 0x0400
|
||||
|
@ -38,14 +44,34 @@ int tb_is_active(void);
|
|||
int tb_width(void);
|
||||
int tb_height(void);
|
||||
|
||||
/* Clear the screen. */
|
||||
/* Update the screen with internal state. Most methods below modify just the
|
||||
* internal state of the screen. Changes won't be visible until you call
|
||||
* tb_present(). */
|
||||
void tb_present(void);
|
||||
|
||||
/* Variant of tb_present() that always refreshes the entire screen. */
|
||||
void tb_sync(void);
|
||||
|
||||
/* Returns a pointer to the internal screen state: a 1D array of cells in
|
||||
* raster order. You'll need to call tb_width() and tb_height() for the
|
||||
* array's dimensions. The array stays valid until tb_clear() or tb_present()
|
||||
* are called. */
|
||||
struct tb_cell *tb_cell_buffer();
|
||||
|
||||
/* Clear the internal screen state using either TB_DEFAULT or the
|
||||
* color/attributes set by tb_set_clear_attributes(). */
|
||||
void tb_clear(void);
|
||||
void tb_set_clear_attributes(uint16_t fg, uint16_t bg);
|
||||
|
||||
/* Move the cursor. Upper-left character is (0, 0). */
|
||||
/* Move the cursor. Upper-left character is (0, 0).
|
||||
*/
|
||||
void tb_set_cursor(int cx, int cy);
|
||||
/* To hide the cursor, call tb_set_cursor(TB_HIDE_CURSOR, TB_HIDE_CURSOR).
|
||||
* Cursor starts out hidden. */
|
||||
#define TB_HIDE_CURSOR -1
|
||||
|
||||
/* Modify a specific cell of the screen. */
|
||||
/* Modify a specific cell of the screen. Don't forget to call tb_present() to
|
||||
* commit your changes. */
|
||||
void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg);
|
||||
|
||||
/*** 2. Controlling keyboard events. */
|
||||
|
|
Loading…
Reference in New Issue