about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-06-23 19:47:09 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-06-23 19:47:09 -0700
commitb2eff9f97e02fe6f5f55133002c16116aac13ed4 (patch)
tree028a0b60dd4f7d7ff0cabad5beb8331ed27a0260
parentb1e558cfe42029df630e1c2d9399d4b52c187801 (diff)
downloadmu-b2eff9f97e02fe6f5f55133002c16116aac13ed4.tar.gz
3942
No, my conclusion in the previous commit was wrong. When you print a
character on the right margin, the cursor coordinates always wrap around
to the left margin on the next row. It's just that if you're at the
bottom of the screen, scrolling gives the impression that the row didn't
change.
-rw-r--r--081print.mu108
-rw-r--r--edit/001-editor.mu4
-rw-r--r--edit/002-typing.mu18
-rw-r--r--edit/004-programming-environment.mu4
-rw-r--r--edit/005-sandbox.mu10
5 files changed, 106 insertions, 38 deletions
diff --git a/081print.mu b/081print.mu
index ff6cf5c0..465d228a 100644
--- a/081print.mu
+++ b/081print.mu
@@ -1,5 +1,16 @@
 # Wrappers around print primitives that take a 'screen' object and are thus
 # easier to test.
+#
+# Screen objects are intended to exactly mimic the behavior of traditional
+# terminals. Moving a cursor too far write wraps it to the next line,
+# scrolling if necessary. The details are subtle:
+#
+# a) Rows can take unbounded values, and such values are preserved rather than
+# clamped or wrapped around.
+#
+# b) If you print to a square (row, right) on the right margin, the cursor
+# position depends on whether 'row' is in range. If it is, the new cursor
+# position is (row+1, 0). If it isn't, the new cursor position is (row, 0).
 
 container screen [
   num-rows:num
@@ -7,6 +18,7 @@ container screen [
   cursor-row:num
   cursor-column:num
   data:&:@:screen-cell  # capacity num-rows*num-columns
+  pending-scroll?:bool
   top-idx:num  # index inside data that corresponds to top-left of screen
                # modified on scroll, wrapping around to the top of data
 ]
@@ -16,6 +28,32 @@ container screen-cell [
   color:num
 ]
 
+def main [
+  local-scope
+  open-console
+  clear-screen
+  print 0/screen [a]
+#?   a:char <- copy 97
+#?   i:num <- copy 0
+#?   {
+#?     done?:bool <- greater-or-equal i, 6
+#?     break-if done?
+#?     move-cursor 0/screen i, 2527
+#?     print 0/screen a
+#?     a <- add a, 1
+#?     i <- add i, 1
+#?     loop
+#?   }
+  move-cursor 0/screen 5, 2527
+  a:num b:num <- cursor-position 0/screen
+  print 0/screen [f]
+  c:num d:num <- cursor-position 0/screen
+  wait-for-some-interaction
+  close-console
+  $print a [ ] b 10/newline
+  $print c [ ] d 10/newline
+]
+
 def new-fake-screen w:num, h:num -> result:&:screen [
   local-scope
   load-ingredients
@@ -26,14 +64,14 @@ def new-fake-screen w:num, h:num -> result:&:screen [
   assert non-zero-height?, [screen can't have zero height]
   bufsize:num <- multiply w, h
   data:&:@:screen-cell <- new screen-cell:type, bufsize
-  *result <- merge h/num-rows, w/num-columns, 0/cursor-row, 0/cursor-column, data, 0/top-idx
+  *result <- merge h/num-rows, w/num-columns, 0/cursor-row, 0/cursor-column, data, 0/pending-scroll?, 0/top-idx
   result <- clear-screen result
 ]
 
 def clear-screen screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [clear-screen]
+#?   stash [clear-screen]
   {
     break-if screen
     # real screen
@@ -61,7 +99,7 @@ def clear-screen screen:&:screen -> screen:&:screen [
 def fake-screen-is-empty? screen:&:screen -> result:bool [
   local-scope
   load-ingredients
-  stash [fake-screen-is-empty?]
+#?   stash [fake-screen-is-empty?]
   return-unless screen, 1/true  # do nothing for real screens
   buf:&:@:screen-cell <- get *screen, data:offset
   i:num <- copy 0
@@ -150,9 +188,13 @@ def print screen:&:screen, c:char -> screen:&:screen [
   {
     at-bottom?:bool <- equal row, height
     break-unless at-bottom?
+    $dump-screen
+    $print [scroll1] 10/newline
     scroll-fake-screen screen
     row <- subtract height, 1
     *screen <- put *screen, cursor-row:offset, row
+    *screen <- put *screen, pending-scroll?:offset, 0/false
+    $dump-screen
   }
   # if row is below bottom margin (error), reset to bottom margin
   {
@@ -162,6 +204,17 @@ def print screen:&:screen, c:char -> screen:&:screen [
     *screen <- put *screen, cursor-row:offset, row
   }
   # }
+  # if there's a pending scroll, perform it
+  {
+    pending-scroll?:bool <- get *screen, pending-scroll?:offset
+#?     $print pending-scroll? 10/newline
+    break-unless pending-scroll?
+    $print [scroll2] 10/newline
+    $dump-screen
+    scroll-fake-screen screen
+    *screen <- put *screen, pending-scroll?:offset, 0/false
+    $dump-screen
+  }
 #?   stash [print] row column
 #?     $print [print-character (], row, [, ], column, [): ], c, 10/newline
   # special-case: newline
@@ -195,16 +248,30 @@ def print screen:&:screen, c:char -> screen:&:screen [
   index:num <- data-index row, column, width, height, top-idx
   cursor:screen-cell <- merge c, color
   *buf <- put-index *buf, index, cursor
-  # move cursor to next character
+  # move cursor to next character, wrapping as necessary
+  # however, don't scroll just yet
   # (but don't bother making it valid; we'll do that before the next print)
   column <- add column, 1
+  {
+    past-right?:bool <- greater-or-equal column, width
+    break-unless past-right?
+    column <- copy 0
+    row <- add row, 1
+    past-bottom?:bool <- greater-or-equal row, height
+    break-unless past-bottom?
+    # queue up a scroll
+    $print [pending scroll] 10/newline
+    *screen <- put *screen, pending-scroll?:offset, 1/true
+    row <- subtract row, 1  # update cursor as if scroll already happened
+  }
+  *screen <- put *screen, cursor-row:offset, row
   *screen <- put *screen, cursor-column:offset, column
 ]
 
 def cursor-down-on-fake-screen screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [cursor-down]
+#?   stash [cursor-down]
   row:num <- get *screen, cursor-row:offset
   height:num <- get *screen, num-rows:offset
   bottom:num <- subtract height, 1
@@ -223,7 +290,7 @@ def cursor-down-on-fake-screen screen:&:screen -> screen:&:screen [
 def scroll-fake-screen screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [scroll-fake-screen]
+#?   stash [scroll-fake-screen]
   width:num <- get *screen, num-columns:offset
   height:num <- get *screen, num-rows:offset
   buf:&:@:screen-cell <- get *screen, data:offset
@@ -515,7 +582,7 @@ def assert-no-scroll screen:&:screen, old-top-idx:num [
 def clear-line screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [clear-line]
+#?   stash [clear-line]
   space:char <- copy 0/nul
   {
     break-if screen
@@ -545,7 +612,7 @@ def clear-line-until screen:&:screen, right:num/inclusive -> screen:&:screen [
   local-scope
   load-ingredients
   row:num, column:num <- cursor-position screen
-  stash [clear-line-until] row column
+#?   stash [clear-line-until] row column
   height:num <- screen-height screen
   past-bottom?:bool <- greater-or-equal row, height
   return-if past-bottom?
@@ -582,7 +649,7 @@ def cursor-position screen:&:screen -> row:num, column:num [
 def move-cursor screen:&:screen, new-row:num, new-column:num -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [move-cursor]
+#?   stash [move-cursor]
   {
     break-if screen
     # real screen
@@ -592,6 +659,8 @@ def move-cursor screen:&:screen, new-row:num, new-column:num -> screen:&:screen
   # fake screen
   *screen <- put *screen, cursor-row:offset, new-row
   *screen <- put *screen, cursor-column:offset, new-column
+  $print [move cursor ] new-row [ ] new-column 10/newline
+  *screen <- put *screen, pending-scroll?:offset, 0/false
 ]
 
 scenario clear-line-erases-printed-characters [
@@ -628,7 +697,7 @@ scenario clear-line-erases-printed-characters [
 def cursor-down screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [cursor-down]
+#?   stash [cursor-down]
   {
     break-if screen
     # real screen
@@ -671,7 +740,7 @@ scenario cursor-down-scrolls [
 def cursor-up screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [cursor-up]
+#?   stash [cursor-up]
   {
     break-if screen
     # real screen
@@ -689,7 +758,7 @@ def cursor-up screen:&:screen -> screen:&:screen [
 def cursor-right screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [cursor-right]
+#?   stash [cursor-right]
   {
     break-if screen
     # real screen
@@ -709,7 +778,7 @@ def cursor-right screen:&:screen -> screen:&:screen [
 def cursor-left screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [cursor-left]
+#?   stash [cursor-left]
   {
     break-if screen
     # real screen
@@ -727,16 +796,15 @@ def cursor-left screen:&:screen -> screen:&:screen [
 def cursor-to-start-of-line screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [cursor-to-start-of-line]
+#?   stash [cursor-to-start-of-line]
   row:num <- cursor-position screen
-  column:num <- copy 0
-  screen <- move-cursor screen, row, column
+  screen <- move-cursor screen, row, 0/column
 ]
 
 def cursor-to-next-line screen:&:screen -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [cursor-to-next-line]
+#?   stash [cursor-to-next-line]
   screen <- cursor-down screen
   screen <- cursor-to-start-of-line screen
 ]
@@ -745,14 +813,14 @@ def move-cursor-to-column screen:&:screen, column:num -> screen:&:screen [
   local-scope
   load-ingredients
   row:num, _ <- cursor-position screen
-  stash [move-cursor-to-column] row
+#?   stash [move-cursor-to-column] row
   move-cursor screen, row, column
 ]
 
 def screen-width screen:&:screen -> width:num [
   local-scope
   load-ingredients
-  stash [screen-width]
+#?   stash [screen-width]
   {
     break-unless screen
     # fake screen
@@ -766,7 +834,7 @@ def screen-width screen:&:screen -> width:num [
 def screen-height screen:&:screen -> height:num [
   local-scope
   load-ingredients
-  stash [screen-height]
+#?   stash [screen-height]
   {
     break-unless screen
     # fake screen
diff --git a/edit/001-editor.mu b/edit/001-editor.mu
index f7b7fb89..d4e0a479 100644
--- a/edit/001-editor.mu
+++ b/edit/001-editor.mu
@@ -207,7 +207,7 @@ def render screen:&:screen, editor:&:editor -> last-row:num, last-column:num, sc
 def clear-screen-from screen:&:screen, row:num, column:num, left:num, right:num -> screen:&:screen [
   local-scope
   load-ingredients
-  stash [clear-screen-from] row column [between] left [and] right
+#?   stash [clear-screen-from] row column [between] left [and] right
   # if it's the real screen, use the optimized primitive
   {
     break-if screen
@@ -218,7 +218,7 @@ def clear-screen-from screen:&:screen, row:num, column:num, left:num, right:num
   screen <- move-cursor screen, row, column
   clear-line-until screen, right
   clear-rest-of-screen screen, row, left, right
-  screen <- move-cursor screen, row, column
+#?   screen <- move-cursor screen, row, column
 ]
 
 def clear-rest-of-screen screen:&:screen, row:num, left:num, right:num -> screen:&:screen [
diff --git a/edit/002-typing.mu b/edit/002-typing.mu
index 05ace7c5..acb0a53c 100644
--- a/edit/002-typing.mu
+++ b/edit/002-typing.mu
@@ -1116,11 +1116,11 @@ after <handle-special-key> [
 def draw-horizontal screen:&:screen, row:num, x:num, right:num -> screen:&:screen [
   local-scope
   load-ingredients
-  a:num, b:num <- cursor-position screen
-  stash [draw-horizontal] row [--] a b
+#?   a:num, b:num <- cursor-position screen
+#?   stash [draw-horizontal] row [--] a b
   height:num <- screen-height screen
   past-bottom?:bool <- greater-or-equal row, height
-  stash [  past-bottom?] past-bottom?
+#?   stash [  past-bottom?] past-bottom?
   return-if past-bottom?
   style:char, style-found?:bool <- next-ingredient
   {
@@ -1138,18 +1138,18 @@ def draw-horizontal screen:&:screen, row:num, x:num, right:num -> screen:&:scree
     break-if bg-color-found?
     bg-color <- copy 0/black
   }
-  stash [aa] x
+#?   stash [aa] x
   screen <- move-cursor screen, row, x
   {
     continue?:bool <- lesser-or-equal x, right  # right is inclusive, to match editor semantics
     break-unless continue?
-  a b <- cursor-position screen
-  stash [bb] x [--] a b
+#?   a b <- cursor-position screen
+#?   stash [bb] x [--] a b
     print screen, style, color, bg-color
-  a b <- cursor-position screen
-  stash [cc] x [--] a b
+#?   a b <- cursor-position screen
+#?   stash [cc] x [--] a b
     x <- add x, 1
     loop
   }
-  stash [draw-horizontal done]
+#?   stash [draw-horizontal done]
 ]
diff --git a/edit/004-programming-environment.mu b/edit/004-programming-environment.mu
index bcd3b524..021d9d73 100644
--- a/edit/004-programming-environment.mu
+++ b/edit/004-programming-environment.mu
@@ -447,7 +447,7 @@ def render-recipes screen:&:screen, env:&:environment, render-editor:render-reci
   clear-screen-from screen, row, left, left, right
   #
   assert-no-scroll screen, old-top-idx
-  stash [render recipes done]
+#?   stash [render recipes done]
 ]
 
 # replaced in a later layer
@@ -468,7 +468,7 @@ def render-sandbox-side screen:&:screen, env:&:environment, render-editor:render
   clear-screen-from screen, row, left, left, right
   #
   assert-no-scroll screen, old-top-idx
-  stash [render sandbox side0 done]
+#?   stash [render sandbox side0 done]
 ]
 
 def update-cursor screen:&:screen, recipes:&:editor, current-sandbox:&:editor, sandbox-in-focus?:bool, env:&:environment -> screen:&:screen [
diff --git a/edit/005-sandbox.mu b/edit/005-sandbox.mu
index 2b17ecc2..f27c1a2c 100644
--- a/edit/005-sandbox.mu
+++ b/edit/005-sandbox.mu
@@ -270,15 +270,15 @@ def! render-sandbox-side screen:&:screen, env:&:environment, render-editor:rende
   clear-rest-of-screen screen, row, left, right
   #
   assert-no-scroll screen, old-top-idx
-  stash [render sandbox side done]
+#?   stash [render sandbox side done]
 ]
 
 def render-sandboxes screen:&:screen, sandbox:&:sandbox, left:num, right:num, row:num, render-from:num, idx:num -> row:num, screen:&:screen, sandbox:&:sandbox [
   local-scope
   load-ingredients
   return-unless sandbox
-  a:num b:num <- cursor-position screen
-  stash [render-sandboxes] idx [:] row [--] a b
+#?   a:num b:num <- cursor-position screen
+#?   stash [render-sandboxes] idx [:] row [--] a b
   screen-height:num <- screen-height screen
   at-bottom?:bool <- greater-or-equal row, screen-height
   return-if at-bottom?
@@ -361,11 +361,11 @@ scenario skip-rendering-sandbox-menu-past-bottom-row [
   # create two sandboxes such that the top one just barely fills the screen
   env:&:environment <- new-programming-environment resources, screen, []
   env <- restore-sandboxes env, resources
-  $clear-trace
+#?   $clear-trace
   run [
     render-all screen, env, render
   ]
-  $dump-trace [app]
+#?   $dump-trace [app]
   screen-should-contain [
     .                                                                                 run (F4)           .
     .                                                  ┊                                                 .