about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-04-16 15:02:42 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-04-16 15:05:31 -0700
commitace7ffb714ce5314c665f28945ee0f3f1664f9ca (patch)
tree191088837e3a6c6fa6a38aae59431efa88c86cb9
parentef73b04e744a69973208096a49d4ae52ddbb84d2 (diff)
downloadmu-ace7ffb714ce5314c665f28945ee0f3f1664f9ca.tar.gz
3824 - experiment: stop buffering in termbox
Now it's much more apparent why things are slow. You can see each repaint
happening. Already I fixed one performance bug -- in clear-rest-of-screen.

Since this subverts Mu's fake screen there may be bugs.

Another salubrious side effect: I've finally internalized that switching
to raw mode doesn't have to clear the screen. That was just an artifact
of how termbox abstracted operations. Now I can conceive of using termbox
to build a repl as well.

(I was inspired to poke into termbox internals by
http://viewsourcecode.org/snaptoken/kilo and
https://github.com/antirez/linenoise)
-rw-r--r--080display.cc61
-rw-r--r--081print.mu23
-rw-r--r--100trace_browser.cc10
-rw-r--r--cannot_write_tests_for8
-rw-r--r--edit/001-editor.mu8
-rw-r--r--edit/004-programming-environment.mu17
-rw-r--r--edit/005-sandbox.mu4
-rw-r--r--edit/006-sandbox-copy.mu2
-rw-r--r--edit/007-sandbox-delete.mu2
-rw-r--r--edit/008-sandbox-edit.mu2
-rw-r--r--edit/009-sandbox-test.mu3
-rw-r--r--edit/010-sandbox-trace.mu3
-rw-r--r--sandbox/001-editor.mu2
-rw-r--r--sandbox/004-programming-environment.mu17
-rw-r--r--sandbox/005-sandbox.mu4
-rw-r--r--sandbox/006-sandbox-copy.mu2
-rw-r--r--sandbox/007-sandbox-delete.mu2
-rw-r--r--sandbox/008-sandbox-edit.mu2
-rw-r--r--sandbox/009-sandbox-test.mu3
-rw-r--r--sandbox/010-sandbox-trace.mu3
-rw-r--r--termbox/termbox.c151
-rw-r--r--termbox/termbox.h33
-rw-r--r--termbox/x.cc7
23 files changed, 25 insertions, 344 deletions
diff --git a/080display.cc b/080display.cc
index 7e95f8f0..17023e61 100644
--- a/080display.cc
+++ b/080display.cc
@@ -7,7 +7,6 @@
 :(before "End Globals")
 int Display_row = 0;
 int Display_column = 0;
-bool Autodisplay = true;
 
 :(before "End Includes")
 #define CHECK_SCREEN \
@@ -38,6 +37,7 @@ 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,21 +83,6 @@ case CLEAR_DISPLAY: {
 }
 
 :(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")
 CLEAR_LINE_ON_DISPLAY,
 :(before "End Primitive Recipe Numbers")
 put(Recipe_ordinal, "clear-line-on-display", CLEAR_LINE_ON_DISPLAY);
@@ -113,7 +98,6 @@ 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;
 }
 
@@ -152,7 +136,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_BLACK;
+  int color = TB_WHITE;
   if (SIZE(ingredients) > 1) {
     color = ingredients.at(1).at(0);
   }
@@ -167,7 +151,6 @@ case PRINT_CHARACTER_TO_DISPLAY: {
       Display_column = 0;
       ++Display_row;
       tb_set_cursor(Display_column, Display_row);
-      if (Autodisplay) tb_present();
     }
     break;
   }
@@ -176,7 +159,6 @@ 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;
   }
@@ -184,7 +166,6 @@ case PRINT_CHARACTER_TO_DISPLAY: {
     ++Display_column;
     tb_set_cursor(Display_column, Display_row);
   }
-  if (Autodisplay) tb_present();
   break;
 }
 
@@ -231,7 +212,6 @@ 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;
 }
 
@@ -251,7 +231,6 @@ 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;
 }
@@ -270,7 +249,6 @@ case MOVE_CURSOR_UP_ON_DISPLAY: {
   if (Display_row > 0) {
     --Display_row;
     tb_set_cursor(Display_column, Display_row);
-    if (Autodisplay) tb_present();
   }
   break;
 }
@@ -291,7 +269,6 @@ 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;
 }
@@ -310,7 +287,6 @@ case MOVE_CURSOR_LEFT_ON_DISPLAY: {
   if (Display_column > 0) {
     --Display_column;
     tb_set_cursor(Display_column, Display_row);
-    if (Autodisplay) tb_present();
   }
   break;
 }
@@ -326,7 +302,6 @@ 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")
@@ -391,37 +366,6 @@ case SHOW_CURSOR_ON_DISPLAY: {
   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")
@@ -551,6 +495,5 @@ case CLEAR_DISPLAY_FROM: {
       tb_change_cell(column, row, ' ', TB_WHITE, TB_BLACK);
     }
   }
-  if (Autodisplay) tb_present();
   break;
 }
diff --git a/081print.mu b/081print.mu
index 487696c5..f654a5ae 100644
--- a/081print.mu
+++ b/081print.mu
@@ -50,13 +50,6 @@ 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
@@ -620,22 +613,6 @@ def show-cursor screen:&:screen -> screen:&: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
diff --git a/100trace_browser.cc b/100trace_browser.cc
index 42a4d848..ffa66b41 100644
--- a/100trace_browser.cc
+++ b/100trace_browser.cc
@@ -276,7 +276,6 @@ 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();
@@ -294,25 +293,21 @@ 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) {
@@ -330,7 +325,6 @@ 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) {
@@ -339,7 +333,6 @@ 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);
@@ -349,7 +342,6 @@ 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
@@ -360,7 +352,6 @@ 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();
     }
   }
 }
@@ -444,7 +435,6 @@ 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) {
diff --git a/cannot_write_tests_for b/cannot_write_tests_for
index 1cdaa20a..5e10fa49 100644
--- a/cannot_write_tests_for
+++ b/cannot_write_tests_for
@@ -2,11 +2,9 @@
 1. assertion failures or errors inside scenarios
 2. screen background color
 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?)
+4. more touch event types
+5. sandbox isolation
+6. 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
diff --git a/edit/001-editor.mu b/edit/001-editor.mu
index 60042344..a6dde85b 100644
--- a/edit/001-editor.mu
+++ b/edit/001-editor.mu
@@ -6,10 +6,8 @@ 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
 ]
@@ -239,6 +237,12 @@ def clear-rest-of-screen screen:&:screen, row:num, left:num, right:num -> screen
   local-scope
   load-ingredients
   row <- add row, 1
+  # if it's the real screen, use the optimized primitive
+  {
+    break-if screen
+    clear-display-from row, left, left, right
+    return
+  }
   screen <- move-cursor screen, row, left
   screen-height:num <- screen-height screen
   {
diff --git a/edit/004-programming-environment.mu b/edit/004-programming-environment.mu
index 943b84f3..f33bfe6f 100644
--- a/edit/004-programming-environment.mu
+++ b/edit/004-programming-environment.mu
@@ -96,7 +96,6 @@ 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?
@@ -156,7 +155,6 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources:
       }
       +finish-event
       screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env
-      show-screen screen
     }
     loop
   }
@@ -435,7 +433,6 @@ 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
@@ -459,8 +456,6 @@ 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 [
@@ -514,18 +509,6 @@ 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
 
diff --git a/edit/005-sandbox.mu b/edit/005-sandbox.mu
index 94abe175..db5d692b 100644
--- a/edit/005-sandbox.mu
+++ b/edit/005-sandbox.mu
@@ -971,9 +971,7 @@ 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
-    show-screen screen
     jump +finish-event
   }
 ]
@@ -1002,9 +1000,7 @@ 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
-    show-screen screen
     jump +finish-event
   }
 ]
diff --git a/edit/006-sandbox-copy.mu b/edit/006-sandbox-copy.mu
index 9df5e625..d3f82e88 100644
--- a/edit/006-sandbox-copy.mu
+++ b/edit/006-sandbox-copy.mu
@@ -128,10 +128,8 @@ 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
   }
 ]
diff --git a/edit/007-sandbox-delete.mu b/edit/007-sandbox-delete.mu
index 4fa3c37d..5167b038 100644
--- a/edit/007-sandbox-delete.mu
+++ b/edit/007-sandbox-delete.mu
@@ -72,10 +72,8 @@ 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
   }
 ]
diff --git a/edit/008-sandbox-edit.mu b/edit/008-sandbox-edit.mu
index dd5c1bb9..2d591ad6 100644
--- a/edit/008-sandbox-edit.mu
+++ b/edit/008-sandbox-edit.mu
@@ -111,10 +111,8 @@ 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
   }
 ]
diff --git a/edit/009-sandbox-test.mu b/edit/009-sandbox-test.mu
index 39b58ecb..badd795b 100644
--- a/edit/009-sandbox-test.mu
+++ b/edit/009-sandbox-test.mu
@@ -130,11 +130,8 @@ 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
-    # no change in cursor
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/edit/010-sandbox-trace.mu b/edit/010-sandbox-trace.mu
index 65337127..8088577a 100644
--- a/edit/010-sandbox-trace.mu
+++ b/edit/010-sandbox-trace.mu
@@ -200,11 +200,8 @@ 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
-    # no change in cursor
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/sandbox/001-editor.mu b/sandbox/001-editor.mu
index 60042344..717e147c 100644
--- a/sandbox/001-editor.mu
+++ b/sandbox/001-editor.mu
@@ -6,10 +6,8 @@ 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
 ]
diff --git a/sandbox/004-programming-environment.mu b/sandbox/004-programming-environment.mu
index 79fa79c6..7f0b4a05 100644
--- a/sandbox/004-programming-environment.mu
+++ b/sandbox/004-programming-environment.mu
@@ -89,7 +89,6 @@ 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
       render?:bool <- handle-keyboard-event screen, current-sandbox, e:event
       # refresh screen only if no more events
       # if there are more events to process, wait for them to clear up, then make sure you render-all afterward.
@@ -117,7 +116,6 @@ def event-loop screen:&:screen, console:&:console, env:&:environment, resources:
       }
       +finish-event
       screen <- update-cursor screen, current-sandbox, env
-      show-screen screen
     }
     loop
   }
@@ -223,7 +221,6 @@ 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
@@ -239,8 +236,6 @@ 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
@@ -267,15 +262,3 @@ 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
-  }
-]
diff --git a/sandbox/005-sandbox.mu b/sandbox/005-sandbox.mu
index badd0d46..91826802 100644
--- a/sandbox/005-sandbox.mu
+++ b/sandbox/005-sandbox.mu
@@ -793,9 +793,7 @@ 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
-    show-screen screen
     jump +finish-event
   }
 ]
@@ -822,9 +820,7 @@ 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
-    show-screen screen
     jump +finish-event
   }
 ]
diff --git a/sandbox/006-sandbox-copy.mu b/sandbox/006-sandbox-copy.mu
index 995f4c7c..4835f02e 100644
--- a/sandbox/006-sandbox-copy.mu
+++ b/sandbox/006-sandbox-copy.mu
@@ -140,10 +140,8 @@ 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
   }
 ]
diff --git a/sandbox/007-sandbox-delete.mu b/sandbox/007-sandbox-delete.mu
index ddfbf692..107c861c 100644
--- a/sandbox/007-sandbox-delete.mu
+++ b/sandbox/007-sandbox-delete.mu
@@ -69,10 +69,8 @@ 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
   }
 ]
diff --git a/sandbox/008-sandbox-edit.mu b/sandbox/008-sandbox-edit.mu
index cb19ebc4..ec4fd578 100644
--- a/sandbox/008-sandbox-edit.mu
+++ b/sandbox/008-sandbox-edit.mu
@@ -111,10 +111,8 @@ 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
   }
 ]
diff --git a/sandbox/009-sandbox-test.mu b/sandbox/009-sandbox-test.mu
index 2ee45a1e..1c24bcb8 100644
--- a/sandbox/009-sandbox-test.mu
+++ b/sandbox/009-sandbox-test.mu
@@ -132,11 +132,8 @@ 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
-    # no change in cursor
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/sandbox/010-sandbox-trace.mu b/sandbox/010-sandbox-trace.mu
index 72f6fe03..27f2915a 100644
--- a/sandbox/010-sandbox-trace.mu
+++ b/sandbox/010-sandbox-trace.mu
@@ -190,11 +190,8 @@ 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
-    # no change in cursor
-    show-screen screen
     loop +next-event
   }
 ]
diff --git a/termbox/termbox.c b/termbox/termbox.c
index e7757f9a..7fff7d7c 100644
--- a/termbox/termbox.c
+++ b/termbox/termbox.c
@@ -23,20 +23,11 @@ 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;
 
@@ -57,11 +48,6 @@ 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);
@@ -121,14 +107,8 @@ int tb_init(void)
   bytebuffer_puts(&output_buffer, funcs[T_HIDE_CURSOR]);
   bytebuffer_puts(&output_buffer, funcs[T_ENTER_MOUSE]);
   bytebuffer_puts(&output_buffer, funcs[T_ENTER_BRACKETED_PASTE]);
-  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;
 }
 
@@ -151,8 +131,6 @@ 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;
@@ -163,65 +141,6 @@ 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);
@@ -233,22 +152,15 @@ void tb_set_cursor(int cx, int cy)
   cursor_y = cy;
   if (!IS_CURSOR_HIDDEN(cursor_x, cursor_y))
     write_cursor(cursor_x, cursor_y);
+  bytebuffer_flush(&output_buffer, inout);
 }
 
 void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg)
 {
   assert(termw != -1);
-  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;
+  send_attr(fg, bg);
+  send_char(x, y, ch);
+  bytebuffer_flush(&output_buffer, inout);
 }
 
 int tb_poll_event(struct tb_event *event)
@@ -285,7 +197,7 @@ void tb_clear(void)
     update_size();
     buffer_size_change_request = 0;
   }
-  cellbuf_clear(&back_buffer);
+  send_clear();
 }
 
 void tb_set_clear_attributes(uint16_t fg, uint16_t bg)
@@ -334,56 +246,6 @@ 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;
@@ -478,9 +340,6 @@ 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();
 }
 
diff --git a/termbox/termbox.h b/termbox/termbox.h
index c6cda6e1..a86bc6ca 100644
--- a/termbox/termbox.h
+++ b/termbox/termbox.h
@@ -9,18 +9,12 @@ 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 in tb_cell.fg and tb_cell.bg. */
+/* Names for some colors. */
 #define TB_BLACK 232
 #define TB_WHITE 255
 
-/* Colors in tb_cell can be combined using bitwise-OR with multiple
- * of the following attributes. */
+/* Some attributes of screen cells that can be combined with colors using bitwise-OR. */
 #define TB_BOLD      0x0100
 #define TB_UNDERLINE 0x0200
 #define TB_REVERSE   0x0400
@@ -44,34 +38,17 @@ int tb_is_active(void);
 int tb_width(void);
 int tb_height(void);
 
-/* 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(). */
+/* Clear the screen. */
 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. Don't forget to call tb_present() to
- * commit your changes. */
+/* Modify a specific cell of the screen. */
 void tb_change_cell(int x, int y, uint32_t ch, uint16_t fg, uint16_t bg);
 
 /*** 2. Controlling keyboard events. */
diff --git a/termbox/x.cc b/termbox/x.cc
index 73373818..5c7fb0a6 100644
--- a/termbox/x.cc
+++ b/termbox/x.cc
@@ -2,10 +2,11 @@
 #include"termbox.h"
 
 int main() {
-  tb_event event;
   tb_init();
-  tb_poll_event(&event);
+  tb_clear();
+  tb_change_cell(0, 0, 'a', TB_WHITE, TB_BLACK);
+  tb_event x;
+  tb_poll_event(&x);
   tb_shutdown();
-  std::cerr << (int)event.type << '\n';
   return 0;
 }