about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2021-01-23 08:45:51 -0800
committerKartik Agaram <vc@akkartik.com>2021-01-23 08:45:51 -0800
commit63be7b7d0d5bb6e728d9afbb68e238fcd3bda3a7 (patch)
tree7f26c1430c53e0aec3cbe889bf80e70078db8506
parent0f73127ef1eba0a8ea814c26115523da3590ffe2 (diff)
downloadmu-63be7b7d0d5bb6e728d9afbb68e238fcd3bda3a7.tar.gz
7548 - baremetal: better cursor management
-rw-r--r--baremetal/103grapheme.subx50
-rw-r--r--baremetal/400.mu3
-rw-r--r--baremetal/500text-screen.mu23
-rw-r--r--baremetal/501draw-text.mu33
-rw-r--r--baremetal/ex7.mu3
-rw-r--r--baremetal/rpn.mu5
6 files changed, 73 insertions, 44 deletions
diff --git a/baremetal/103grapheme.subx b/baremetal/103grapheme.subx
index b4750989..16a44fbc 100644
--- a/baremetal/103grapheme.subx
+++ b/baremetal/103grapheme.subx
@@ -104,17 +104,13 @@ $cursor-position-on-real-screen:end:
     5d/pop-to-ebp
     c3/return
 
-# Caller is responsible for tracking what was on the screen at this position
-# before, and making sure the cursor continues to show the same grapheme.
-set-cursor-position-on-real-screen:  # x: int, y: int, g: grapheme
+set-cursor-position-on-real-screen:  # x: int, y: int
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
     # . save registers
     50/push-eax
     #
-    (draw-grapheme-on-real-screen *(ebp+0x10) *(ebp+8) *(ebp+0xc) 0 7)
-    # TODO: support fake screen; we currently assume 'screen' is always 0 (real)
     8b/-> *(ebp+8) 0/r32/eax
     89/<- *Real-screen-cursor-x 0/r32/eax
     8b/-> *(ebp+0xc) 0/r32/eax
@@ -127,17 +123,47 @@ $set-cursor-position-on-real-screen:end:
     5d/pop-to-ebp
     c3/return
 
+# Draw cursor at current location. But this is rickety:
+#   - does not clear previous location cursor was shown at.
+#   - does not preserve what was at the cursor. Caller is responsible for
+#     tracking what was on the screen at this position before and passing it
+#     in again.
+show-cursor-on-real-screen:  # g: grapheme
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    50/push-eax
+    51/push-ecx
+    #
+    (cursor-position-on-real-screen)  # => eax, ecx
+    (draw-grapheme-on-real-screen *(ebp+8) %eax %ecx 0 7)
+$show-cursor-on-real-screen:end:
+    # . restore registers
+    59/pop-to-ecx
+    58/pop-to-eax
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
 == data
 
 # The cursor is where certain Mu functions (usually of the form
-# 'draw*cursor*') print to by default. It becomes visible on
-# set-cursor-position, but further drawing might overwrite it.
-# We don't bother displaying the cursor when drawing text. It's up to
-# applications to display the cursor before waiting for a key, and to ensure
-# its location appropriately suggests the effect keystrokes will have.
+# 'draw*cursor*') print to by default.
+#
+# We don't bother displaying the cursor when drawing. It only becomes visible
+# on show-cursor, which is quite rickety (see above)
+#
+# It's up to applications to manage cursor display:
+#   - clean up where it used to be
+#   - display the cursor before waiting for a key
+#   - ensure its location appropriately suggests the effect keystrokes will have
+#   - ensure its contents (and colors) appropriately reflect the state of the
+#     screen
 #
-# There's no low-level support for blinking, etc. We aren't using any
-# hardware-supported text mode here.
+# There's no blinking, etc. We aren't using any hardware-supported text mode
+# here.
 Real-screen-cursor-x:
   0/imm32
 Real-screen-cursor-y:
diff --git a/baremetal/400.mu b/baremetal/400.mu
index 5035042e..4cbac1d3 100644
--- a/baremetal/400.mu
+++ b/baremetal/400.mu
@@ -2,7 +2,8 @@
 sig pixel-on-real-screen x: int, y: int, color: int
 sig draw-grapheme-on-real-screen g: grapheme, x: int, y: int, color: int, background-color: int
 sig cursor-position-on-real-screen -> _/eax: int, _/ecx: int
-sig set-cursor-position-on-real-screen x: int, y: int, g: grapheme
+sig set-cursor-position-on-real-screen x: int, y: int
+sig show-cursor-on-real-screen g: grapheme
 
 # keyboard
 sig read-key kbd: (addr keyboard) -> _/eax: byte
diff --git a/baremetal/500text-screen.mu b/baremetal/500text-screen.mu
index fbc2ef43..f5cd4125 100644
--- a/baremetal/500text-screen.mu
+++ b/baremetal/500text-screen.mu
@@ -112,11 +112,11 @@ fn cursor-position screen: (addr screen) -> _/eax: int, _/ecx: int {
   return *cursor-x-addr, *cursor-y-addr
 }
 
-fn set-cursor-position screen: (addr screen), x: int, y: int, g: grapheme {
+fn set-cursor-position screen: (addr screen), x: int, y: int {
   {
     compare screen, 0
     break-if-!=
-    set-cursor-position-on-real-screen x, y, g
+    set-cursor-position-on-real-screen x, y
     return
   }
   # fake screen
@@ -157,11 +157,20 @@ fn set-cursor-position screen: (addr screen), x: int, y: int, g: grapheme {
   dest <- get screen-addr, cursor-y
   src <- copy y
   copy-to *dest, src
-  #
+}
+
+fn show-cursor screen: (addr screen), g: grapheme {
+  {
+    compare screen, 0
+    break-if-!=
+    show-cursor-on-real-screen g
+    return
+  }
+  # fake screen
   var cursor-x/eax: int <- copy 0
   var cursor-y/ecx: int <- copy 0
-  cursor-x, cursor-y <- cursor-position screen-addr
-  draw-grapheme screen-addr, g, cursor-x, cursor-y, 0  # cursor color not tracked for fake screen
+  cursor-x, cursor-y <- cursor-position screen
+  draw-grapheme screen, g, cursor-x, cursor-y, 0  # cursor color not tracked for fake screen
 }
 
 fn clear-screen screen: (addr screen) {
@@ -173,7 +182,7 @@ fn clear-screen screen: (addr screen) {
   }
   # fake screen
   var space/edi: grapheme <- copy 0x20
-  set-cursor-position screen, 0, 0, space
+  set-cursor-position screen, 0, 0
   var screen-addr/esi: (addr screen) <- copy screen
   var y/eax: int <- copy 1
   var height/ecx: (addr int) <- get screen-addr, height
@@ -192,7 +201,7 @@ fn clear-screen screen: (addr screen) {
     y <- increment
     loop
   }
-  set-cursor-position screen, 0, 0, space
+  set-cursor-position screen, 0, 0
 }
 
 # there's no grapheme that guarantees to cover every pixel, so we'll bump down
diff --git a/baremetal/501draw-text.mu b/baremetal/501draw-text.mu
index d7455829..0bb95dee 100644
--- a/baremetal/501draw-text.mu
+++ b/baremetal/501draw-text.mu
@@ -10,8 +10,7 @@ fn cursor-left screen: (addr screen) {
     return
   }
   cursor-x <- decrement
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, cursor-x, cursor-y, space
+  set-cursor-position screen, cursor-x, cursor-y
 }
 
 fn cursor-right screen: (addr screen) {
@@ -28,8 +27,7 @@ fn cursor-right screen: (addr screen) {
     return
   }
   cursor-x <- increment
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, cursor-x, cursor-y, space
+  set-cursor-position screen, cursor-x, cursor-y
 }
 
 fn cursor-up screen: (addr screen) {
@@ -42,8 +40,7 @@ fn cursor-up screen: (addr screen) {
     return
   }
   cursor-y <- decrement
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, cursor-x, cursor-y, space
+  set-cursor-position screen, cursor-x, cursor-y
 }
 
 fn cursor-down screen: (addr screen) {
@@ -60,8 +57,7 @@ fn cursor-down screen: (addr screen) {
     return
   }
   cursor-y <- increment
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, cursor-x, cursor-y, space
+  set-cursor-position screen, cursor-x, cursor-y
 }
 
 fn draw-grapheme-at-cursor screen: (addr screen), g: grapheme, color: int {
@@ -105,8 +101,7 @@ fn draw-text-rightward screen: (addr screen), text: (addr array byte), x: int, x
     xcurr <- increment
     loop
   }
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, xcurr, y, space  # we'll assume it's ok to clear the next grapheme
+  set-cursor-position screen, xcurr, y
   return xcurr
 }
 
@@ -167,8 +162,7 @@ fn draw-text-wrapping-right-then-down screen: (addr screen), text: (addr array b
     }
     loop
   }
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, xcurr, ycurr, space  # we'll assume it's ok to clear the next grapheme
+  set-cursor-position screen, xcurr, ycurr
   return xcurr, ycurr
 }
 
@@ -183,8 +177,7 @@ fn move-cursor-rightward-and-downward screen: (addr screen), xmin: int, xmax: in
     cursor-x <- copy xmin
     cursor-y <- increment
   }
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, cursor-x, cursor-y, space  # we'll assume it's ok to clear the grapheme at the cursor
+  set-cursor-position screen, cursor-x, cursor-y
 }
 
 fn draw-text-wrapping-right-then-down-over-full-screen screen: (addr screen), text: (addr array byte), x: int, y: int, color: int -> _/eax: int, _/ecx: int {
@@ -262,8 +255,7 @@ fn draw-int32-hex-wrapping-right-then-down screen: (addr screen), n: int, xmin:
     }
     loop
   }
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, xcurr, ycurr, space  # we'll assume it's ok to clear the next grapheme
+  set-cursor-position screen, xcurr, ycurr
   return xcurr, ycurr
 }
 
@@ -342,8 +334,7 @@ fn draw-int32-decimal-wrapping-right-then-down screen: (addr screen), n: int, xm
     }
     loop
   }
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, xcurr, ycurr, space  # we'll assume it's ok to clear the next grapheme
+  set-cursor-position screen, xcurr, ycurr
   return xcurr, ycurr
 }
 
@@ -413,8 +404,7 @@ fn draw-text-downward screen: (addr screen), text: (addr array byte), x: int, y:
     ycurr <- increment
     loop
   }
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, x, ycurr, space  # we'll assume it's ok to clear the next grapheme
+  set-cursor-position screen, x, ycurr
   return ycurr
 }
 
@@ -474,8 +464,7 @@ fn draw-text-wrapping-down-then-right screen: (addr screen), text: (addr array b
     }
     loop
   }
-  var space/esi: grapheme <- copy 0x20
-  set-cursor-position screen, xcurr, ycurr, space  # we'll assume it's ok to clear the next grapheme
+  set-cursor-position screen, xcurr, ycurr
   return xcurr, ycurr
 }
 
diff --git a/baremetal/ex7.mu b/baremetal/ex7.mu
index d604c95a..e50099c4 100644
--- a/baremetal/ex7.mu
+++ b/baremetal/ex7.mu
@@ -12,8 +12,9 @@
 
 fn main {
   var space/eax: grapheme <- copy 0x20
-  set-cursor-position 0, 0, 0, space
+  set-cursor-position 0, 0, 0
   {
+    show-cursor 0, space
     var key/eax: byte <- read-key 0
     {
       compare key, 0x68  # 'h'
diff --git a/baremetal/rpn.mu b/baremetal/rpn.mu
index df894cbc..0944b42b 100644
--- a/baremetal/rpn.mu
+++ b/baremetal/rpn.mu
@@ -26,10 +26,11 @@ fn main -> _/ebx: int {
   {
     # print prompt
     var x/eax: int <- draw-text-rightward 0, "> ", 0, 0x80, y, 3
-    set-cursor-position 0, x, y, space
+    set-cursor-position 0, x, y
     # read line from keyboard
     clear-stream in
     {
+      show-cursor 0, space
       var key/eax: byte <- read-key 0
       compare key, 0xa  # newline
       break-if-=
@@ -42,6 +43,8 @@ fn main -> _/ebx: int {
       cursor-right 0
       loop
     }
+    # clear cursor
+    draw-grapheme-at-cursor 0, space, 3  # 3=foreground color, which is never used
     # parse and eval
     var out/eax: int <- simplify in
     # print