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. # -# There's no low-level support for blinking, etc. We aren't using any -# hardware-supported text mode here. +# 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 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