Revert commits 3824, 3850 and 3852. We'll redo them more carefully.
This commit is contained in:
Kartik K. Agaram 2017-05-13 12:42:17 -07:00
parent 8195ed4ee9
commit 0c0d1ea5cd
24 changed files with 402 additions and 115 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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) {

View File

@ -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:

View File

@ -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
]

View File

@ -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
]

View File

@ -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

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
]

View File

@ -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
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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
}
]

View File

@ -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();
}

View File

@ -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. */