fix bad terminology: grapheme -> code point
Unix text-mode terminals transparently support utf-8 these days, and so I treat utf-8 sequences (which I call graphemes in Mu) as fundamental. I then blindly carried over this state of affairs to bare-metal Mu, where it makes no sense. If you don't have a terminal handling font-rendering for you, fonts are most often indexed by code points and not utf-8 sequences.
This commit is contained in:
parent
4b90a26d71
commit
6e05a8fa27
|
@ -1,4 +1,9 @@
|
|||
# Use the built-in font to draw a grapheme to real screen.
|
||||
# Use the built-in font to draw glyphs to screen.
|
||||
# https://en.wikipedia.org/wiki/Glyph#Typography
|
||||
# The Mu computer can currently only render glyphs corresponding to single
|
||||
# code points. No combining characters.
|
||||
# https://en.wikipedia.org/wiki/Code_point
|
||||
# https://en.wikipedia.org/wiki/Combining_character
|
||||
#
|
||||
# We need to do this in machine code because Mu doesn't have global variables
|
||||
# yet (for the start of the font).
|
||||
|
@ -9,20 +14,20 @@
|
|||
# The Mu computer's font is 8px wide and 16px tall.
|
||||
# Therefore 'x' here is in [0, 128), and 'y' is in [0, 48)
|
||||
# Doesn't update the cursor; where the cursor should go after printing the
|
||||
# current grapheme is a higher-level concern.
|
||||
draw-grapheme-on-real-screen: # g: grapheme, x: int, y: int, color: int, background-color: int -> _/eax
|
||||
# current code-point is a higher-level concern.
|
||||
draw-code-point-on-real-screen: # c: code-point, x: int, y: int, color: int, background-color: int -> _/eax
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
#
|
||||
(draw-grapheme-on-screen-buffer *Video-memory-addr *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) 0x80 0x30) # => eax
|
||||
$draw-grapheme-on-real-screen:end:
|
||||
(draw-code-point-on-screen-buffer *Video-memory-addr *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) 0x80 0x30) # => eax
|
||||
$draw-code-point-on-real-screen:end:
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
draw-grapheme-on-screen-array: # screen-data: (addr array byte), g: grapheme, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int
|
||||
draw-code-point-on-screen-array: # screen-data: (addr array byte), c: code-point, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -39,17 +44,17 @@ draw-grapheme-on-screen-array: # screen-data: (addr array byte), g: grapheme, x
|
|||
8b/-> *(ebp+0x20) 0/r32/eax
|
||||
f7 4/subop/multiply-into-eax *(ebp+0x24)
|
||||
81 7/subop/compare %edx 0/imm32
|
||||
0f 85/jump-if-!= $draw-grapheme-on-screen-array:overflow/disp32
|
||||
0f 85/jump-if-!= $draw-code-point-on-screen-array:overflow/disp32
|
||||
# if (eax > ecx) abort
|
||||
39/compare %eax 1/r32/ecx
|
||||
0f 8f/jump-if-> $draw-grapheme-on-screen-array:abort/disp32
|
||||
0f 8f/jump-if-> $draw-code-point-on-screen-array:abort/disp32
|
||||
}
|
||||
# eax = screen-data+4 (skip length)
|
||||
8b/-> *(ebp+8) 0/r32/eax
|
||||
05/add-to-eax 4/imm32
|
||||
#
|
||||
(draw-grapheme-on-screen-buffer %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) # => eax
|
||||
$draw-grapheme-on-screen-array:end:
|
||||
(draw-code-point-on-screen-buffer %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24)) # => eax
|
||||
$draw-code-point-on-screen-array:end:
|
||||
# . restore registers
|
||||
5a/pop-to-edx
|
||||
59/pop-to-ecx
|
||||
|
@ -58,30 +63,30 @@ $draw-grapheme-on-screen-array:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
$draw-grapheme-on-screen-array:overflow:
|
||||
(abort "draw-grapheme-on-screen-array: screen dimensions too large")
|
||||
$draw-code-point-on-screen-array:overflow:
|
||||
(abort "draw-code-point-on-screen-array: screen dimensions too large")
|
||||
|
||||
$draw-grapheme-on-screen-array:abort:
|
||||
(abort "draw-grapheme-on-screen-array: coordinates are off the screen. Are the screen dimensions correct?")
|
||||
$draw-code-point-on-screen-array:abort:
|
||||
(abort "draw-code-point-on-screen-array: coordinates are off the screen. Are the screen dimensions correct?")
|
||||
|
||||
# 'buffer' here is not a valid Mu type: a naked address without a length.
|
||||
# returns number of 8x16 units printed to screen (1 or 2).
|
||||
draw-grapheme-on-screen-buffer: # buffer: (addr byte), g: grapheme, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int
|
||||
draw-code-point-on-screen-buffer: # buffer: (addr byte), c: code-point, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# . save registers
|
||||
56/push-esi
|
||||
# switch screen-width and screen-height from grapheme to pixel units
|
||||
# switch screen-width and screen-height from code-point to pixel units
|
||||
c1 4/subop/shift-left *(ebp+20) 3/imm8/log2-font-width
|
||||
c1 4/subop/shift-left *(ebp+24) 4/imm8/log2-font-height
|
||||
# esi = g
|
||||
# esi = c
|
||||
8b/-> *(ebp+0xc) 6/r32/esi
|
||||
# if (g >= 4352) return # unicode planes supported: latin, greek, cyrillic, armenian, hebrew, arabic, syriac, thaana, n'ko, indian (iscii), sinhala, thai, lao, tibetan, myanmar, georgian
|
||||
# if (c >= 4352) return # unicode planes supported: latin, greek, cyrillic, armenian, hebrew, arabic, syriac, thaana, n'ko, indian (iscii), sinhala, thai, lao, tibetan, myanmar, georgian
|
||||
# next few to support: CJK, ethiopic, cherokee, ...
|
||||
81 7/subop/compare %esi 0x1100/imm32
|
||||
0f 8d/jump-if->= $draw-grapheme-on-screen-buffer:end/disp32
|
||||
# var letter-bitmap/esi = font[g]
|
||||
0f 8d/jump-if->= $draw-code-point-on-screen-buffer:end/disp32
|
||||
# var letter-bitmap/esi = font[c]
|
||||
69/multiply %esi 0x21/imm32/glyph-size 6/r32/esi
|
||||
81 0/subop/add %esi 0x0010000c/imm32/Font # see boot.subx
|
||||
# dispatch based on letter-bitmap->size
|
||||
|
@ -91,13 +96,13 @@ draw-grapheme-on-screen-buffer: # buffer: (addr byte), g: grapheme, x: int, y:
|
|||
3d/compare-eax-and 8/imm32
|
||||
{
|
||||
75/jump-if-!= break/disp8
|
||||
(draw-narrow-grapheme-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))
|
||||
(draw-narrow-code-point-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))
|
||||
b8/copy-to-eax 1/imm32
|
||||
eb/jump $draw-grapheme-on-screen-buffer:end/disp8
|
||||
eb/jump $draw-code-point-on-screen-buffer:end/disp8
|
||||
}
|
||||
(draw-wide-grapheme-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))
|
||||
(draw-wide-code-point-on-screen-buffer *(ebp+8) %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))
|
||||
b8/copy-to-eax 2/imm32
|
||||
$draw-grapheme-on-screen-buffer:end:
|
||||
$draw-code-point-on-screen-buffer:end:
|
||||
# . restore registers
|
||||
5e/pop-to-esi
|
||||
# . epilogue
|
||||
|
@ -105,16 +110,16 @@ $draw-grapheme-on-screen-buffer:end:
|
|||
5d/pop-to-ebp
|
||||
c3/return
|
||||
|
||||
wide-grapheme?: # g: grapheme -> _/eax: boolean
|
||||
wide-code-point?: # c: code-point -> _/eax: boolean
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
# eax = g
|
||||
# eax = c
|
||||
8b/-> *(ebp+8) 0/r32/eax
|
||||
# if (g >= 128) return # characters beyond ASCII currently not supported
|
||||
# if (c >= 128) return # characters beyond ASCII currently not supported
|
||||
3d/compare-eax-and 0x80/imm32
|
||||
0f 8d/jump-if->= $wide-grapheme?:end/disp32
|
||||
# var letter-bitmap/eax = font[g]
|
||||
0f 8d/jump-if->= $wide-code-point?:end/disp32
|
||||
# var letter-bitmap/eax = font[c]
|
||||
69/multiply %eax 0x21/imm32/glyph-size 0/r32/eax
|
||||
05/add-to-eax 0x0010000c/imm32/Font # see boot.subx
|
||||
# dispatch based on letter-bitmap->size
|
||||
|
@ -122,7 +127,7 @@ wide-grapheme?: # g: grapheme -> _/eax: boolean
|
|||
25/and-eax-with 0xff/imm32
|
||||
3d/compare-eax-and 8/imm32
|
||||
0f 95/set-if-!= %eax
|
||||
$wide-grapheme?:end:
|
||||
$wide-code-point?:end:
|
||||
# . epilogue
|
||||
89/<- %esp 5/r32/ebp
|
||||
5d/pop-to-ebp
|
||||
|
@ -130,7 +135,7 @@ $wide-grapheme?:end:
|
|||
|
||||
# buffer: naked address to raw screen RAM without a length
|
||||
# letter-bitmap: naked address to 8-pixel wide font glyph
|
||||
draw-narrow-grapheme-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (addr byte), x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int
|
||||
draw-narrow-code-point-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (addr byte), x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -163,7 +168,7 @@ draw-narrow-grapheme-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (a
|
|||
#
|
||||
e9/jump loop/disp32
|
||||
}
|
||||
$draw-narrow-grapheme-on-screen-buffer:end:
|
||||
$draw-narrow-code-point-on-screen-buffer:end:
|
||||
# . restore registers
|
||||
5f/pop-to-edi
|
||||
5e/pop-to-esi
|
||||
|
@ -176,7 +181,7 @@ $draw-narrow-grapheme-on-screen-buffer:end:
|
|||
|
||||
# buffer: naked address to raw screen RAM without a length
|
||||
# letter-bitmap: naked address to 16-pixel wide font glyph
|
||||
draw-wide-grapheme-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (addr byte), x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int
|
||||
draw-wide-code-point-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (addr byte), x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -219,7 +224,7 @@ draw-wide-grapheme-on-screen-buffer: # buffer: (addr byte), letter-bitmap: (add
|
|||
#
|
||||
e9/jump loop/disp32
|
||||
}
|
||||
$draw-wide-grapheme-on-screen-buffer:end:
|
||||
$draw-wide-code-point-on-screen-buffer:end:
|
||||
# . restore registers
|
||||
5f/pop-to-edi
|
||||
5e/pop-to-esi
|
||||
|
@ -260,11 +265,11 @@ draw-run-of-pixels-from-glyph: # buffer: (addr byte), glyph-byte: byte, x: int,
|
|||
{
|
||||
73/jump-if-not-CF break/disp8
|
||||
(pixel-on-screen-buffer *(ebp+8) %eax *(ebp+0x14) *(ebp+0x18) *(ebp+0x20) *(ebp+0x24))
|
||||
eb/jump $draw-grapheme-on-screen-buffer:continue/disp8
|
||||
eb/jump $draw-code-point-on-screen-buffer:continue/disp8
|
||||
}
|
||||
# otherwise use the background color
|
||||
(pixel-on-screen-buffer *(ebp+8) %eax *(ebp+0x14) *(ebp+0x1c) *(ebp+0x20) *(ebp+0x24))
|
||||
$draw-grapheme-on-screen-buffer:continue:
|
||||
$draw-code-point-on-screen-buffer:continue:
|
||||
# --x
|
||||
48/decrement-eax
|
||||
#
|
||||
|
@ -318,7 +323,7 @@ $set-cursor-position-on-real-screen:end:
|
|||
# tracking what was on the screen at this position before and passing it
|
||||
# in again.
|
||||
# - does not stop showing the cursor at this location when the cursor moves
|
||||
draw-cursor-on-real-screen: # g: grapheme
|
||||
draw-cursor-on-real-screen: # c: code-point
|
||||
# . prologue
|
||||
55/push-ebp
|
||||
89/<- %ebp 4/r32/esp
|
||||
|
@ -327,7 +332,7 @@ draw-cursor-on-real-screen: # g: grapheme
|
|||
51/push-ecx
|
||||
#
|
||||
(cursor-position-on-real-screen) # => eax, ecx
|
||||
(draw-grapheme-on-real-screen *(ebp+8) %eax %ecx 0 7) # => eax
|
||||
(draw-code-point-on-real-screen *(ebp+8) %eax %ecx 0 7) # => eax
|
||||
$draw-cursor-on-real-screen:end:
|
||||
# . restore registers
|
||||
59/pop-to-ecx
|
|
@ -311,7 +311,7 @@ draw-slice-wrapping-right-then-down-from-cursor-over-full-screen: # screen: (ad
|
|||
73/jump-if-addr>= break/disp8
|
||||
# print *curr
|
||||
8a/byte-> *ecx 0/r32/eax
|
||||
(draw-grapheme-at-cursor-over-full-screen *(ebp+8) %eax *(ebp+0x14) *(ebp+0x18))
|
||||
(draw-code-point-at-cursor-over-full-screen *(ebp+8) %eax *(ebp+0x14) *(ebp+0x18))
|
||||
#
|
||||
41/increment-ecx
|
||||
#
|
||||
|
|
8
400.mu
8
400.mu
|
@ -1,11 +1,11 @@
|
|||
# screen
|
||||
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 -> _/eax: int
|
||||
sig draw-grapheme-on-screen-array screen-data: (addr array byte), g: grapheme, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int
|
||||
sig wide-grapheme? g: grapheme -> _/eax: boolean
|
||||
sig draw-code-point-on-real-screen c: code-point, x: int, y: int, color: int, background-color: int -> _/eax: int
|
||||
sig draw-code-point-on-screen-array screen-data: (addr array byte), c: code-point, x: int, y: int, color: int, background-color: int, screen-width: int, screen-height: int -> _/eax: int
|
||||
sig wide-code-point? c: code-point -> _/eax: boolean
|
||||
sig cursor-position-on-real-screen -> _/eax: int, _/ecx: int
|
||||
sig set-cursor-position-on-real-screen x: int, y: int
|
||||
sig draw-cursor-on-real-screen g: grapheme
|
||||
sig draw-cursor-on-real-screen c: code-point
|
||||
sig color-rgb color: int -> _/ecx: int, _/edx: int, _/ebx: int
|
||||
|
||||
# timer
|
||||
|
|
|
@ -7,18 +7,21 @@
|
|||
# Graphemes may consist of multiple code points.
|
||||
#
|
||||
# Mu graphemes are always represented in utf-8, and they are required to fit
|
||||
# in 4 bytes.
|
||||
# in 4 bytes. (This can be confusing if you focus just on ASCII, where Mu's
|
||||
# graphemes and code-points are identical.)
|
||||
#
|
||||
# Mu doesn't currently support combining code points, or graphemes made of
|
||||
# multiple code points. One day we will.
|
||||
# We also don't currently support code points that translate into multiple
|
||||
# or wide graphemes. (In particular, Tab will never be supported.)
|
||||
# https://en.wikipedia.org/wiki/Combining_character
|
||||
|
||||
fn to-code-point in: grapheme -> _/eax: code-point {
|
||||
var g/eax: grapheme <- copy in
|
||||
var result/eax: code-point <- copy g # TODO: support non-ASCII
|
||||
return result
|
||||
}
|
||||
|
||||
# transliterated from tb_utf8_unicode_to_char in https://github.com/nsf/termbox
|
||||
# https://wiki.tcl-lang.org/page/UTF%2D8+bit+by+bit explains the algorithm
|
||||
#
|
||||
# The day we want to support combining characters, this function will need to
|
||||
# take multiple code points. Or something.
|
||||
fn to-grapheme in: code-point -> _/eax: grapheme {
|
||||
var c/eax: int <- copy in
|
||||
var num-trailers/ecx: int <- copy 0
|
||||
|
|
|
@ -23,7 +23,7 @@ type screen {
|
|||
}
|
||||
|
||||
type screen-cell {
|
||||
data: grapheme
|
||||
data: code-point
|
||||
color: int
|
||||
background-color: int
|
||||
unused?: boolean
|
||||
|
@ -89,27 +89,27 @@ fn screen-size _screen: (addr screen) -> _/eax: int, _/ecx: int {
|
|||
|
||||
# testable screen primitive
|
||||
# return number of 8x16 units drawn
|
||||
fn draw-grapheme _screen: (addr screen), g: grapheme, x: int, y: int, color: int, background-color: int -> _/eax: int {
|
||||
fn draw-code-point _screen: (addr screen), c: code-point, x: int, y: int, color: int, background-color: int -> _/eax: int {
|
||||
var screen/esi: (addr screen) <- copy _screen
|
||||
{
|
||||
compare screen, 0
|
||||
break-if-!=
|
||||
var result/eax: int <- draw-grapheme-on-real-screen g, x, y, color, background-color
|
||||
var result/eax: int <- draw-code-point-on-real-screen c, x, y, color, background-color
|
||||
return result
|
||||
}
|
||||
# fake screen
|
||||
var wide?/eax: boolean <- wide-grapheme? g
|
||||
var wide?/eax: boolean <- wide-code-point? c
|
||||
compare wide?, 0/false
|
||||
{
|
||||
break-if-=
|
||||
draw-wide-grapheme-on-fake-screen screen, g, x, y, color, background-color
|
||||
draw-wide-code-point-on-fake-screen screen, c, x, y, color, background-color
|
||||
return 2
|
||||
}
|
||||
draw-narrow-grapheme-on-fake-screen screen, g, x, y, color, background-color
|
||||
draw-narrow-code-point-on-fake-screen screen, c, x, y, color, background-color
|
||||
return 1
|
||||
}
|
||||
|
||||
fn draw-narrow-grapheme-on-fake-screen _screen: (addr screen), g: grapheme, x: int, y: int, color: int, background-color: int {
|
||||
fn draw-narrow-code-point-on-fake-screen _screen: (addr screen), c: code-point, x: int, y: int, color: int, background-color: int {
|
||||
var screen/esi: (addr screen) <- copy _screen
|
||||
# ignore if out of bounds
|
||||
{
|
||||
|
@ -145,9 +145,9 @@ fn draw-narrow-grapheme-on-fake-screen _screen: (addr screen), g: grapheme, x: i
|
|||
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
||||
var offset/ecx: (offset screen-cell) <- compute-offset data, index
|
||||
var dest-cell/ecx: (addr screen-cell) <- index data, offset
|
||||
var dest-grapheme/eax: (addr grapheme) <- get dest-cell, data
|
||||
var g2/edx: grapheme <- copy g
|
||||
copy-to *dest-grapheme, g2
|
||||
var dest-code-point/eax: (addr code-point) <- get dest-cell, data
|
||||
var c2/edx: code-point <- copy c
|
||||
copy-to *dest-code-point, c2
|
||||
var dest-color/eax: (addr int) <- get dest-cell, color
|
||||
var src-color/edx: int <- copy color
|
||||
copy-to *dest-color, src-color
|
||||
|
@ -158,7 +158,7 @@ fn draw-narrow-grapheme-on-fake-screen _screen: (addr screen), g: grapheme, x: i
|
|||
copy-to *dest, 0/false
|
||||
}
|
||||
|
||||
fn draw-wide-grapheme-on-fake-screen _screen: (addr screen), g: grapheme, x: int, y: int, color: int, background-color: int {
|
||||
fn draw-wide-code-point-on-fake-screen _screen: (addr screen), c: code-point, x: int, y: int, color: int, background-color: int {
|
||||
var screen/esi: (addr screen) <- copy _screen
|
||||
# ignore if out of bounds
|
||||
{
|
||||
|
@ -169,7 +169,7 @@ fn draw-wide-grapheme-on-fake-screen _screen: (addr screen), g: grapheme, x: int
|
|||
{
|
||||
var xmax-addr/eax: (addr int) <- get screen, width
|
||||
var xmax/eax: int <- copy *xmax-addr
|
||||
xmax <- decrement # wide graphemes need an extra unit
|
||||
xmax <- decrement # wide code-points need an extra unit
|
||||
compare x, xmax
|
||||
break-if-<
|
||||
return
|
||||
|
@ -193,9 +193,9 @@ fn draw-wide-grapheme-on-fake-screen _screen: (addr screen), g: grapheme, x: int
|
|||
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
||||
var offset/ecx: (offset screen-cell) <- compute-offset data, index
|
||||
var dest-cell/ecx: (addr screen-cell) <- index data, offset
|
||||
var dest-grapheme/eax: (addr grapheme) <- get dest-cell, data
|
||||
var g2/edx: grapheme <- copy g
|
||||
copy-to *dest-grapheme, g2
|
||||
var dest-code-point/eax: (addr code-point) <- get dest-cell, data
|
||||
var c2/edx: code-point <- copy c
|
||||
copy-to *dest-code-point, c2
|
||||
var dest-color/eax: (addr int) <- get dest-cell, color
|
||||
var src-color/edx: int <- copy color
|
||||
copy-to *dest-color, src-color
|
||||
|
@ -217,14 +217,6 @@ fn draw-wide-grapheme-on-fake-screen _screen: (addr screen), g: grapheme, x: int
|
|||
}
|
||||
}
|
||||
|
||||
# we can't really render non-ASCII yet, but when we do we'll be ready
|
||||
# return number of 8x16 units drawn
|
||||
fn draw-code-point screen: (addr screen), c: code-point, x: int, y: int, color: int, background-color: int -> _/eax: int {
|
||||
var g/eax: grapheme <- copy c
|
||||
var result/eax: int <- draw-grapheme screen, g, x, y, color, background-color
|
||||
return result
|
||||
}
|
||||
|
||||
# fake screens only
|
||||
fn screen-cell-index _screen: (addr screen), x: int, y: int -> _/ecx: int {
|
||||
var screen/esi: (addr screen) <- copy _screen
|
||||
|
@ -298,18 +290,18 @@ fn set-cursor-position _screen: (addr screen), x: int, y: int {
|
|||
copy-to *dest, src
|
||||
}
|
||||
|
||||
fn draw-cursor screen: (addr screen), g: grapheme {
|
||||
fn draw-cursor screen: (addr screen), c: code-point {
|
||||
{
|
||||
compare screen, 0
|
||||
break-if-!=
|
||||
draw-cursor-on-real-screen g
|
||||
draw-cursor-on-real-screen c
|
||||
return
|
||||
}
|
||||
# fake screen
|
||||
var cursor-x/eax: int <- copy 0
|
||||
var cursor-y/ecx: int <- copy 0
|
||||
cursor-x, cursor-y <- cursor-position screen
|
||||
var dummy/eax: int <- draw-grapheme screen, g, cursor-x, cursor-y, 0/fg, 7/bg
|
||||
var dummy/eax: int <- draw-code-point screen, c, cursor-x, cursor-y, 0/fg, 7/bg
|
||||
}
|
||||
|
||||
fn clear-screen _screen: (addr screen) {
|
||||
|
@ -367,11 +359,11 @@ fn fake-screen-empty? _screen: (addr screen) -> _/eax: boolean {
|
|||
{
|
||||
compare x, *width
|
||||
break-if->=
|
||||
var g/eax: grapheme <- screen-grapheme-at screen, x, y
|
||||
var c/eax: code-point <- screen-code-point-at screen, x, y
|
||||
{
|
||||
compare g, 0
|
||||
compare c, 0
|
||||
break-if-=
|
||||
compare g, 0x20/space
|
||||
compare c, 0x20/space
|
||||
break-if-=
|
||||
return 0/false
|
||||
}
|
||||
|
@ -506,21 +498,21 @@ fn screen-cell-unused-at-index? _screen: (addr screen), _index: int -> _/eax: bo
|
|||
return *src
|
||||
}
|
||||
|
||||
fn screen-grapheme-at _screen: (addr screen), x: int, y: int -> _/eax: grapheme {
|
||||
fn screen-code-point-at _screen: (addr screen), x: int, y: int -> _/eax: code-point {
|
||||
var screen/esi: (addr screen) <- copy _screen
|
||||
var index/ecx: int <- screen-cell-index screen, x, y
|
||||
var result/eax: grapheme <- screen-grapheme-at-index screen, index
|
||||
var result/eax: code-point <- screen-code-point-at-index screen, index
|
||||
return result
|
||||
}
|
||||
|
||||
fn screen-grapheme-at-index _screen: (addr screen), _index: int -> _/eax: grapheme {
|
||||
fn screen-code-point-at-index _screen: (addr screen), _index: int -> _/eax: code-point {
|
||||
var screen/esi: (addr screen) <- copy _screen
|
||||
var data-ah/eax: (addr handle array screen-cell) <- get screen, data
|
||||
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
||||
var index/ecx: int <- copy _index
|
||||
var offset/ecx: (offset screen-cell) <- compute-offset data, index
|
||||
var cell/eax: (addr screen-cell) <- index data, offset
|
||||
var src/eax: (addr grapheme) <- get cell, data
|
||||
var src/eax: (addr code-point) <- get cell, data
|
||||
return *src
|
||||
}
|
||||
|
||||
|
@ -661,11 +653,11 @@ fn copy-pixels _screen: (addr screen), target-screen: (addr screen) {
|
|||
}
|
||||
}
|
||||
|
||||
# It turns out double-buffering graphemes is useless because rendering fonts
|
||||
# It turns out double-buffering screen-cells is useless because rendering fonts
|
||||
# takes too long. (At least under Qemu.)
|
||||
# So we'll instead convert graphemes to pixels when double-buffering.
|
||||
# So we'll instead convert screen-cells to pixels when double-buffering.
|
||||
# 'screen' must be a fake screen.
|
||||
fn convert-graphemes-to-pixels _screen: (addr screen) {
|
||||
fn convert-screen-cells-to-pixels _screen: (addr screen) {
|
||||
var screen/esi: (addr screen) <- copy _screen
|
||||
var width-a/ebx: (addr int) <- get screen, width
|
||||
var height-a/edx: (addr int) <- get screen, height
|
||||
|
@ -678,25 +670,25 @@ fn convert-graphemes-to-pixels _screen: (addr screen) {
|
|||
compare y, *height-a
|
||||
break-if->=
|
||||
var x/edi: int <- copy 0
|
||||
$convert-graphemes-to-pixels:loop-x: {
|
||||
$convert-screen-cells-to-pixels:loop-x: {
|
||||
compare x, *width-a
|
||||
break-if->=
|
||||
{
|
||||
var tmp/eax: grapheme <- screen-grapheme-at screen, x, y
|
||||
# skip null graphemes that only get created when clearing screen
|
||||
var tmp/eax: code-point <- screen-code-point-at screen, x, y
|
||||
# skip null code-points that only get created when clearing screen
|
||||
# there may be other pixels drawn there, and we don't want to clobber them
|
||||
# this is a situation where fake screens aren't faithful to real screens; we don't support overlap between graphemes and raw pixels
|
||||
# this is a situation where fake screens aren't faithful to real screens; we don't support overlap between screen-cells and raw pixels
|
||||
compare tmp, 0
|
||||
break-if-=
|
||||
var g: grapheme
|
||||
copy-to g, tmp
|
||||
var c: code-point
|
||||
copy-to c, tmp
|
||||
var tmp/eax: int <- screen-color-at screen, x, y
|
||||
var fg: int
|
||||
copy-to fg, tmp
|
||||
var bg/eax: int <- screen-background-color-at screen, x, y
|
||||
var offset/eax: int <- draw-grapheme-on-screen-array data, g, x, y, fg, bg, *width-a, *height-a
|
||||
var offset/eax: int <- draw-code-point-on-screen-array data, c, x, y, fg, bg, *width-a, *height-a
|
||||
x <- add offset
|
||||
loop $convert-graphemes-to-pixels:loop-x
|
||||
loop $convert-screen-cells-to-pixels:loop-x
|
||||
}
|
||||
x <- increment
|
||||
loop
|
||||
|
|
|
@ -81,11 +81,11 @@ fn move-cursor-to-left-margin-of-next-line screen: (addr screen) {
|
|||
set-cursor-position screen, cursor-x, cursor-y
|
||||
}
|
||||
|
||||
fn draw-grapheme-at-cursor-over-full-screen screen: (addr screen), g: grapheme, color: int, background-color: int {
|
||||
fn draw-code-point-at-cursor-over-full-screen screen: (addr screen), c: code-point, color: int, background-color: int {
|
||||
var cursor-x/eax: int <- copy 0
|
||||
var cursor-y/ecx: int <- copy 0
|
||||
cursor-x, cursor-y <- cursor-position screen
|
||||
var _offset/eax: int <- draw-grapheme screen, g, cursor-x, cursor-y, color, background-color
|
||||
var _offset/eax: int <- draw-code-point screen, c, cursor-x, cursor-y, color, background-color
|
||||
var offset/edx: int <- copy _offset
|
||||
var width/eax: int <- copy 0
|
||||
var dummy/ecx: int <- copy 0
|
||||
|
@ -100,11 +100,6 @@ fn draw-grapheme-at-cursor-over-full-screen screen: (addr screen), g: grapheme,
|
|||
}
|
||||
}
|
||||
|
||||
fn draw-code-point-at-cursor-over-full-screen screen: (addr screen), c: code-point, color: int, background-color: int {
|
||||
var g/eax: grapheme <- copy c
|
||||
draw-grapheme-at-cursor-over-full-screen screen, g, color, background-color
|
||||
}
|
||||
|
||||
# draw a single line of text from x, y to xmax
|
||||
# return the next 'x' coordinate
|
||||
# if there isn't enough space, truncate
|
||||
|
@ -125,7 +120,8 @@ fn draw-stream-rightward screen: (addr screen), stream: (addr stream byte), x: i
|
|||
var g/eax: grapheme <- read-grapheme stream
|
||||
compare g, 0xffffffff/end-of-file
|
||||
break-if-=
|
||||
var offset/eax: int <- draw-grapheme screen, g, xcurr, y, color, background-color
|
||||
var c/eax: code-point <- to-code-point g
|
||||
var offset/eax: int <- draw-code-point screen, c, xcurr, y, color, background-color
|
||||
xcurr <- add offset
|
||||
loop
|
||||
}
|
||||
|
@ -156,8 +152,8 @@ fn draw-text-rightward-from-cursor-over-full-screen screen: (addr screen), text:
|
|||
draw-text-rightward-from-cursor screen, text, width, color, background-color
|
||||
}
|
||||
|
||||
fn render-grapheme screen: (addr screen), g: grapheme, xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
|
||||
compare g, 0xa/newline
|
||||
fn render-code-point screen: (addr screen), c: code-point, xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
|
||||
compare c, 0xa/newline
|
||||
var x/ecx: int <- copy x
|
||||
{
|
||||
break-if-!=
|
||||
|
@ -167,7 +163,7 @@ fn render-grapheme screen: (addr screen), g: grapheme, xmin: int, ymin: int, xma
|
|||
increment y
|
||||
return x, y
|
||||
}
|
||||
var offset/eax: int <- draw-grapheme screen, g, x, y, color, background-color
|
||||
var offset/eax: int <- draw-code-point screen, c, x, y, color, background-color
|
||||
x <- add offset
|
||||
compare x, xmax
|
||||
{
|
||||
|
@ -210,15 +206,16 @@ fn draw-text-wrapping-right-then-down screen: (addr screen), _text: (addr array
|
|||
fn draw-stream-wrapping-right-then-down screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
|
||||
var xcurr/eax: int <- copy x
|
||||
var ycurr/ecx: int <- copy y
|
||||
var g/ebx: grapheme <- copy 0
|
||||
var c/ebx: code-point <- copy 0
|
||||
{
|
||||
{
|
||||
var _g/eax: grapheme <- read-grapheme stream
|
||||
g <- copy _g
|
||||
var g/eax: grapheme <- read-grapheme stream
|
||||
var _c/eax: code-point <- to-code-point g
|
||||
c <- copy _c
|
||||
}
|
||||
compare g, 0xffffffff/end-of-file
|
||||
compare c, 0xffffffff/end-of-file
|
||||
break-if-=
|
||||
xcurr, ycurr <- render-grapheme screen, g, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
xcurr, ycurr <- render-code-point screen, c, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
loop
|
||||
}
|
||||
set-cursor-position screen, xcurr, ycurr
|
||||
|
@ -301,7 +298,8 @@ fn draw-int32-hex-wrapping-right-then-down screen: (addr screen), n: int, xmin:
|
|||
var g/eax: grapheme <- read-grapheme stream
|
||||
compare g, 0xffffffff/end-of-file
|
||||
break-if-=
|
||||
var offset/eax: int <- draw-grapheme screen, g, xcurr, ycurr, color, background-color
|
||||
var c/eax: code-point <- to-code-point g
|
||||
var offset/eax: int <- draw-code-point screen, c, xcurr, ycurr, color, background-color
|
||||
xcurr <- add offset
|
||||
compare xcurr, xmax
|
||||
{
|
||||
|
@ -355,7 +353,8 @@ fn draw-int32-decimal-wrapping-right-then-down screen: (addr screen), n: int, xm
|
|||
var g/eax: grapheme <- read-grapheme stream
|
||||
compare g, 0xffffffff/end-of-file
|
||||
break-if-=
|
||||
var offset/eax: int <- draw-grapheme screen, g, xcurr, ycurr, color, background-color
|
||||
var c/eax: code-point <- to-code-point g
|
||||
var offset/eax: int <- draw-code-point screen, c, xcurr, ycurr, color, background-color
|
||||
xcurr <- add offset
|
||||
compare xcurr, xmax
|
||||
{
|
||||
|
@ -422,7 +421,8 @@ fn draw-stream-downward screen: (addr screen), stream: (addr stream byte), x: in
|
|||
var g/eax: grapheme <- read-grapheme stream
|
||||
compare g, 0xffffffff/end-of-file
|
||||
break-if-=
|
||||
var dummy/eax: int <- draw-grapheme screen, g, x, ycurr, color, background-color
|
||||
var c/eax: code-point <- to-code-point g
|
||||
var dummy/eax: int <- draw-code-point screen, c, x, ycurr, color, background-color
|
||||
ycurr <- increment
|
||||
loop
|
||||
}
|
||||
|
@ -463,7 +463,8 @@ fn draw-stream-wrapping-down-then-right screen: (addr screen), stream: (addr str
|
|||
var g/eax: grapheme <- read-grapheme stream
|
||||
compare g, 0xffffffff/end-of-file
|
||||
break-if-=
|
||||
var offset/eax: int <- draw-grapheme screen, g, xcurr, ycurr, color, background-color
|
||||
var c/eax: code-point <- to-code-point g
|
||||
var offset/eax: int <- draw-code-point screen, c, xcurr, ycurr, color, background-color
|
||||
ycurr <- increment
|
||||
compare ycurr, ymax
|
||||
{
|
||||
|
|
|
@ -24,32 +24,33 @@ fn check-screen-row-from _screen: (addr screen), x: int, y: int, expected: (addr
|
|||
var unused?/eax: boolean <- screen-cell-unused-at-index? screen, index
|
||||
compare unused?, 0/false
|
||||
break-if-!=
|
||||
var _g/eax: grapheme <- screen-grapheme-at-index screen, index
|
||||
var g/ebx: grapheme <- copy _g
|
||||
var _c/eax: code-point <- screen-code-point-at-index screen, index
|
||||
var c/ebx: code-point <- copy _c
|
||||
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
||||
var expected-code-point/eax: code-point <- to-code-point expected-grapheme
|
||||
# compare graphemes
|
||||
$check-screen-row-from:compare-graphemes: {
|
||||
# if expected-grapheme is space, null grapheme is also ok
|
||||
# if expected-code-point is space, null grapheme is also ok
|
||||
{
|
||||
compare expected-grapheme, 0x20
|
||||
compare expected-code-point, 0x20
|
||||
break-if-!=
|
||||
compare g, 0
|
||||
compare c, 0
|
||||
break-if-= $check-screen-row-from:compare-graphemes
|
||||
}
|
||||
# if (g == expected-grapheme) print "."
|
||||
compare g, expected-grapheme
|
||||
# if (c == expected-code-point) print "."
|
||||
compare c, expected-code-point
|
||||
break-if-=
|
||||
# otherwise print an error
|
||||
failure-count <- increment
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, msg, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ": expected '", 3/fg/cyan, 0/bg
|
||||
draw-grapheme-at-cursor-over-full-screen 0/screen, expected-grapheme, 3/cyan, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen 0/screen, expected-code-point, 3/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "' at (", 3/fg/cyan, 0/bg
|
||||
draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, x, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ", ", 3/fg/cyan, 0/bg
|
||||
draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, y, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ") but observed '", 3/fg/cyan, 0/bg
|
||||
draw-grapheme-at-cursor-over-full-screen 0/screen, g, 3/cyan, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen 0/screen, c, 3/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "'", 3/fg/cyan, 0/bg
|
||||
move-cursor-to-left-margin-of-next-line 0/screen
|
||||
}
|
||||
|
@ -90,21 +91,22 @@ fn check-screen-row-in-color-from _screen: (addr screen), fg: int, y: int, x: in
|
|||
var unused?/eax: boolean <- screen-cell-unused-at-index? screen, index
|
||||
compare unused?, 0/false
|
||||
break-if-!=
|
||||
var _g/eax: grapheme <- screen-grapheme-at-index screen, index
|
||||
var g/ebx: grapheme <- copy _g
|
||||
var _expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
||||
var expected-grapheme/edi: grapheme <- copy _expected-grapheme
|
||||
var _c/eax: code-point <- screen-code-point-at-index screen, index
|
||||
var c/ebx: code-point <- copy _c
|
||||
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
||||
var _expected-code-point/eax: code-point <- to-code-point expected-grapheme
|
||||
var expected-code-point/edi: code-point <- copy _expected-code-point
|
||||
$check-screen-row-in-color-from:compare-cells: {
|
||||
# if expected-grapheme is space, null grapheme is also ok
|
||||
# if expected-code-point is space, null grapheme is also ok
|
||||
{
|
||||
compare expected-grapheme, 0x20
|
||||
compare expected-code-point, 0x20
|
||||
break-if-!=
|
||||
compare g, 0
|
||||
compare c, 0
|
||||
break-if-= $check-screen-row-in-color-from:compare-cells
|
||||
}
|
||||
# if expected-grapheme is space, a different color is ok
|
||||
# if expected-code-point is space, a different color is ok
|
||||
{
|
||||
compare expected-grapheme, 0x20
|
||||
compare expected-code-point, 0x20
|
||||
break-if-!=
|
||||
var color/eax: int <- screen-color-at-index screen, index
|
||||
compare color, fg
|
||||
|
@ -112,8 +114,8 @@ fn check-screen-row-in-color-from _screen: (addr screen), fg: int, y: int, x: in
|
|||
}
|
||||
# compare graphemes
|
||||
$check-screen-row-in-color-from:compare-graphemes: {
|
||||
# if (g == expected-grapheme) print "."
|
||||
compare g, expected-grapheme
|
||||
# if (c == expected-code-point) print "."
|
||||
compare c, expected-code-point
|
||||
{
|
||||
break-if-!=
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg/cyan, 0/bg
|
||||
|
@ -123,13 +125,13 @@ fn check-screen-row-in-color-from _screen: (addr screen), fg: int, y: int, x: in
|
|||
count-test-failure
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, msg, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ": expected '", 3/fg/cyan, 0/bg
|
||||
draw-grapheme-at-cursor-over-full-screen 0/screen, expected-grapheme, 3/cyan, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen 0/screen, expected-code-point, 3/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "' at (", 3/fg/cyan, 0/bg
|
||||
draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, x, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ", ", 3/fg/cyan, 0/bg
|
||||
draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, y, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ") but observed '", 3/fg/cyan, 0/bg
|
||||
draw-grapheme-at-cursor-over-full-screen 0/screen, g, 3/cyan, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen 0/screen, c, 3/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "'", 3/fg/cyan, 0/bg
|
||||
move-cursor-to-left-margin-of-next-line 0/screen
|
||||
}
|
||||
|
@ -145,7 +147,7 @@ fn check-screen-row-in-color-from _screen: (addr screen), fg: int, y: int, x: in
|
|||
count-test-failure
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, msg, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ": expected '", 3/fg/cyan, 0/bg
|
||||
draw-grapheme-at-cursor-over-full-screen 0/screen, expected-grapheme, 3/cyan, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen 0/screen, expected-code-point, 3/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "' at (", 3/fg/cyan, 0/bg
|
||||
draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, x, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ", ", 3/fg/cyan, 0/bg
|
||||
|
@ -183,21 +185,22 @@ fn check-screen-row-in-background-color-from _screen: (addr screen), bg: int, y:
|
|||
var unused?/eax: boolean <- screen-cell-unused-at-index? screen, index
|
||||
compare unused?, 0/false
|
||||
break-if-!=
|
||||
var _g/eax: grapheme <- screen-grapheme-at-index screen, index
|
||||
var g/ebx: grapheme <- copy _g
|
||||
var _expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
||||
var expected-grapheme/edi: grapheme <- copy _expected-grapheme
|
||||
var _g/eax: code-point <- screen-code-point-at-index screen, index
|
||||
var g/ebx: code-point <- copy _g
|
||||
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
||||
var _expected-code-point/eax: code-point <- to-code-point expected-grapheme
|
||||
var expected-code-point/edi: code-point <- copy _expected-code-point
|
||||
$check-screen-row-in-background-color-from:compare-cells: {
|
||||
# if expected-grapheme is space, null grapheme is also ok
|
||||
# if expected-code-point is space, null grapheme is also ok
|
||||
{
|
||||
compare expected-grapheme, 0x20
|
||||
compare expected-code-point, 0x20
|
||||
break-if-!=
|
||||
compare g, 0
|
||||
break-if-= $check-screen-row-in-background-color-from:compare-cells
|
||||
}
|
||||
# if expected-grapheme is space, a different background-color is ok
|
||||
# if expected-code-point is space, a different background-color is ok
|
||||
{
|
||||
compare expected-grapheme, 0x20
|
||||
compare expected-code-point, 0x20
|
||||
break-if-!=
|
||||
var background-color/eax: int <- screen-background-color-at-index screen, index
|
||||
compare background-color, bg
|
||||
|
@ -205,8 +208,8 @@ fn check-screen-row-in-background-color-from _screen: (addr screen), bg: int, y:
|
|||
}
|
||||
# compare graphemes
|
||||
$check-screen-row-in-background-color-from:compare-graphemes: {
|
||||
# if (g == expected-grapheme) print "."
|
||||
compare g, expected-grapheme
|
||||
# if (g == expected-code-point) print "."
|
||||
compare g, expected-code-point
|
||||
{
|
||||
break-if-!=
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ".", 3/fg/cyan, 0/bg
|
||||
|
@ -216,13 +219,13 @@ fn check-screen-row-in-background-color-from _screen: (addr screen), bg: int, y:
|
|||
count-test-failure
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, msg, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ": expected '", 3/fg/cyan, 0/bg
|
||||
draw-grapheme-at-cursor-over-full-screen 0/screen, expected-grapheme, 3/cyan, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen 0/screen, expected-code-point, 3/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "' at (", 3/fg/cyan, 0/bg
|
||||
draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, x, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ", ", 3/fg/cyan, 0/bg
|
||||
draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, y, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ") but observed '", 3/fg/cyan, 0/bg
|
||||
draw-grapheme-at-cursor-over-full-screen 0/screen, g, 3/cyan, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen 0/screen, g, 3/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "'", 3/fg/cyan, 0/bg
|
||||
move-cursor-to-left-margin-of-next-line 0/screen
|
||||
break $check-screen-row-in-background-color-from:compare-graphemes
|
||||
|
@ -239,7 +242,7 @@ fn check-screen-row-in-background-color-from _screen: (addr screen), bg: int, y:
|
|||
count-test-failure
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, msg, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ": expected '", 3/fg/cyan, 0/bg
|
||||
draw-grapheme-at-cursor-over-full-screen 0/screen, expected-grapheme, 3/cyan, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen 0/screen, expected-code-point, 3/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, "' at (", 3/fg/cyan, 0/bg
|
||||
draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, x, 3/fg/cyan, 0/bg
|
||||
draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0/screen, ", ", 3/fg/cyan, 0/bg
|
||||
|
|
|
@ -98,7 +98,12 @@ fn render-stack-from-bottom-wrapping-right-then-down screen: (addr screen), _sel
|
|||
compare i, *top-addr
|
||||
break-if->=
|
||||
{
|
||||
var g/esi: (addr grapheme) <- index data, i
|
||||
var c: code-point
|
||||
{
|
||||
var g/eax: (addr grapheme) <- index data, i
|
||||
var tmp/eax: code-point <- to-code-point *g
|
||||
copy-to c, tmp
|
||||
}
|
||||
var fg: int
|
||||
{
|
||||
var tmp/eax: int <- copy color
|
||||
|
@ -109,7 +114,7 @@ fn render-stack-from-bottom-wrapping-right-then-down screen: (addr screen), _sel
|
|||
break-if-!=
|
||||
copy-to fg, 0xf/highlight
|
||||
}
|
||||
x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, fg, background-color
|
||||
x, y <- render-code-point screen, c, xmin, ymin, xmax, ymax, x, y, fg, background-color
|
||||
}
|
||||
i <- increment
|
||||
loop
|
||||
|
@ -152,8 +157,13 @@ fn render-stack-from-top-wrapping-right-then-down screen: (addr screen), _self:
|
|||
break-if-=
|
||||
compare i, 0
|
||||
break-if-<
|
||||
var g/esi: (addr grapheme) <- index data, i
|
||||
x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, background-color, color
|
||||
var c: code-point
|
||||
{
|
||||
var g/eax: (addr grapheme) <- index data, i
|
||||
var tmp/eax: code-point <- to-code-point *g
|
||||
copy-to c, tmp
|
||||
}
|
||||
x, y <- render-code-point screen, c, xmin, ymin, xmax, ymax, x, y, background-color, color
|
||||
i <- decrement
|
||||
}
|
||||
# remaining iterations
|
||||
|
@ -172,8 +182,13 @@ fn render-stack-from-top-wrapping-right-then-down screen: (addr screen), _self:
|
|||
copy-to fg, 0xf/highlight
|
||||
}
|
||||
#
|
||||
var g/esi: (addr grapheme) <- index data, i
|
||||
x, y <- render-grapheme screen, *g, xmin, ymin, xmax, ymax, x, y, fg, background-color
|
||||
var c: code-point
|
||||
{
|
||||
var g/eax: (addr grapheme) <- index data, i
|
||||
var tmp/eax: code-point <- to-code-point *g
|
||||
copy-to c, tmp
|
||||
}
|
||||
x, y <- render-code-point screen, c, xmin, ymin, xmax, ymax, x, y, fg, background-color
|
||||
i <- decrement
|
||||
loop
|
||||
}
|
||||
|
|
|
@ -409,8 +409,8 @@ fn render-gap-buffer-wrapping-right-then-down screen: (addr screen), _gap: (addr
|
|||
bg <- copy color
|
||||
}
|
||||
# print a grapheme either way so that cursor position doesn't affect printed width
|
||||
var space/edx: grapheme <- copy 0x20
|
||||
x2, y2 <- render-grapheme screen, space, xmin, ymin, xmax, ymax, x2, y2, fg, bg
|
||||
var space/edx: code-point <- copy 0x20
|
||||
x2, y2 <- render-code-point screen, space, xmin, ymin, xmax, ymax, x2, y2, fg, bg
|
||||
return x2, y2
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk)
|
|||
loop-if-=
|
||||
var key2/eax: int <- copy key
|
||||
append-byte in, key2
|
||||
var g/eax: grapheme <- copy key2
|
||||
draw-grapheme-at-cursor-over-full-screen screen, g, 0xf/fg, 0/bg
|
||||
var c/eax: code-point <- copy key2 # TODO: unicode input
|
||||
draw-code-point-at-cursor-over-full-screen screen, c, 0xf/fg, 0/bg
|
||||
loop
|
||||
}
|
||||
clear-screen screen
|
||||
|
|
|
@ -19,7 +19,7 @@ fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk)
|
|||
var in-storage: (stream byte 0x80)
|
||||
var in/esi: (addr stream byte) <- address in-storage
|
||||
var y/ecx: int <- copy 0
|
||||
var space/edx: grapheme <- copy 0x20
|
||||
var space/edx: code-point <- copy 0x20
|
||||
# read-eval-print loop
|
||||
{
|
||||
# print prompt
|
||||
|
@ -35,12 +35,12 @@ fn main screen: (addr screen), keyboard: (addr keyboard), data-disk: (addr disk)
|
|||
loop-if-=
|
||||
var key2/eax: int <- copy key
|
||||
append-byte in, key2
|
||||
var g/eax: grapheme <- copy key2
|
||||
draw-grapheme-at-cursor-over-full-screen screen, g, 0xf/fg, 0/bg
|
||||
var c/eax: code-point <- copy key2
|
||||
draw-code-point-at-cursor-over-full-screen screen, c, 0xf/fg, 0/bg
|
||||
loop
|
||||
}
|
||||
# clear cursor
|
||||
draw-grapheme-at-cursor-over-full-screen screen, space, 3/fg/never-used, 0/bg
|
||||
draw-code-point-at-cursor-over-full-screen screen, space, 3/fg/never-used, 0/bg
|
||||
# parse and eval
|
||||
var out/eax: int <- simplify in
|
||||
# print
|
||||
|
|
|
@ -378,7 +378,7 @@ fn render-search-input screen: (addr screen), _env: (addr environment) {
|
|||
compare x, 0x4a/end-search
|
||||
break-if->
|
||||
var y/ecx: int <- copy 0
|
||||
x, y <- render-grapheme screen, 0x5f/underscore, 0/xmin 1/ymin, 0x80/xmax, 1/ymax, x, 1/y, 0xf/fg 0/bg
|
||||
x, y <- render-code-point screen, 0x5f/underscore, 0/xmin 1/ymin, 0x80/xmax, 1/ymax, x, 1/y, 0xf/fg 0/bg
|
||||
loop
|
||||
}
|
||||
}
|
||||
|
@ -580,17 +580,17 @@ fn draw-json-stream-wrapping-right-then-down screen: (addr screen), stream: (add
|
|||
var xcurr/eax: int <- copy x
|
||||
var ycurr/ecx: int <- copy y
|
||||
{
|
||||
var g/ebx: grapheme <- read-json-grapheme stream
|
||||
compare g, 0xffffffff/end-of-file
|
||||
var c/ebx: code-point <- read-json-code-point stream
|
||||
compare c, 0xffffffff/end-of-file
|
||||
break-if-=
|
||||
$draw-json-stream-wrapping-right-then-down:render-grapheme: {
|
||||
compare g, 0x5c/backslash
|
||||
compare c, 0x5c/backslash
|
||||
{
|
||||
break-if-!=
|
||||
xcurr, ycurr <- render-json-escaped-grapheme screen, stream, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
xcurr, ycurr <- render-json-escaped-code-point screen, stream, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
break $draw-json-stream-wrapping-right-then-down:render-grapheme
|
||||
}
|
||||
xcurr, ycurr <- render-grapheme screen, g, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
xcurr, ycurr <- render-code-point screen, c, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
}
|
||||
loop
|
||||
}
|
||||
|
@ -599,15 +599,16 @@ fn draw-json-stream-wrapping-right-then-down screen: (addr screen), stream: (add
|
|||
}
|
||||
|
||||
# just return a different register
|
||||
fn read-json-grapheme stream: (addr stream byte) -> _/ebx: grapheme {
|
||||
var result/eax: grapheme <- read-grapheme stream
|
||||
fn read-json-code-point stream: (addr stream byte) -> _/ebx: code-point {
|
||||
var g/eax: grapheme <- read-grapheme stream
|
||||
var result/eax: code-point <- to-code-point g
|
||||
return result
|
||||
}
|
||||
|
||||
# '\' encountered
|
||||
# https://www.json.org/json-en.html
|
||||
fn render-json-escaped-grapheme screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, xcurr: int, ycurr: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
|
||||
var g/ebx: grapheme <- read-json-grapheme stream
|
||||
fn render-json-escaped-code-point screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, xcurr: int, ycurr: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
|
||||
var g/ebx: code-point <- read-json-code-point stream
|
||||
compare g, 0xffffffff/end-of-file
|
||||
{
|
||||
break-if-!=
|
||||
|
@ -647,16 +648,16 @@ fn render-json-escaped-grapheme screen: (addr screen), stream: (addr stream byte
|
|||
{
|
||||
compare g, 0x75/u
|
||||
break-if-!=
|
||||
x, y <- render-json-escaped-unicode-grapheme screen, stream, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-json-escaped-unicode-code-point screen, stream, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
# most characters escape to themselves
|
||||
x, y <- render-grapheme screen, g, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-code-point screen, g, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
|
||||
# '\u' encountered
|
||||
fn render-json-escaped-unicode-grapheme screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, xcurr: int, ycurr: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
|
||||
fn render-json-escaped-unicode-code-point screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, xcurr: int, ycurr: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
|
||||
var ustream-storage: (stream byte 4)
|
||||
var ustream/esi: (addr stream byte) <- address ustream-storage
|
||||
# slurp 4 bytes exactly
|
||||
|
@ -679,7 +680,7 @@ fn render-json-escaped-unicode-grapheme screen: (addr screen), stream: (addr str
|
|||
break-if-=
|
||||
var x/eax: int <- copy 0
|
||||
var y/ecx: int <- copy 0
|
||||
x, y <- render-grapheme screen, 0x2d/dash, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-code-point screen, 0x2d/dash, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
# \u2014 = -
|
||||
|
@ -689,7 +690,7 @@ fn render-json-escaped-unicode-grapheme screen: (addr screen), stream: (addr str
|
|||
break-if-=
|
||||
var x/eax: int <- copy 0
|
||||
var y/ecx: int <- copy 0
|
||||
x, y <- render-grapheme screen, 0x2d/dash, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-code-point screen, 0x2d/dash, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
# \u2018 = '
|
||||
|
@ -699,7 +700,7 @@ fn render-json-escaped-unicode-grapheme screen: (addr screen), stream: (addr str
|
|||
break-if-=
|
||||
var x/eax: int <- copy 0
|
||||
var y/ecx: int <- copy 0
|
||||
x, y <- render-grapheme screen, 0x27/quote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-code-point screen, 0x27/quote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
# \u2019 = '
|
||||
|
@ -709,7 +710,7 @@ fn render-json-escaped-unicode-grapheme screen: (addr screen), stream: (addr str
|
|||
break-if-=
|
||||
var x/eax: int <- copy 0
|
||||
var y/ecx: int <- copy 0
|
||||
x, y <- render-grapheme screen, 0x27/quote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-code-point screen, 0x27/quote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
# \u201c = "
|
||||
|
@ -719,7 +720,7 @@ fn render-json-escaped-unicode-grapheme screen: (addr screen), stream: (addr str
|
|||
break-if-=
|
||||
var x/eax: int <- copy 0
|
||||
var y/ecx: int <- copy 0
|
||||
x, y <- render-grapheme screen, 0x22/dquote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-code-point screen, 0x22/dquote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
# \u201d = "
|
||||
|
@ -729,7 +730,7 @@ fn render-json-escaped-unicode-grapheme screen: (addr screen), stream: (addr str
|
|||
break-if-=
|
||||
var x/eax: int <- copy 0
|
||||
var y/ecx: int <- copy 0
|
||||
x, y <- render-grapheme screen, 0x22/dquote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-code-point screen, 0x22/dquote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
# \u2022 = *
|
||||
|
@ -739,7 +740,7 @@ fn render-json-escaped-unicode-grapheme screen: (addr screen), stream: (addr str
|
|||
break-if-=
|
||||
var x/eax: int <- copy 0
|
||||
var y/ecx: int <- copy 0
|
||||
x, y <- render-grapheme screen, 0x2a/asterisk, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
x, y <- render-code-point screen, 0x2a/asterisk, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
|
||||
return x, y
|
||||
}
|
||||
# \u2026 = ...
|
||||
|
|
|
@ -11,14 +11,11 @@
|
|||
#
|
||||
# Mu doesn't currently support combining code points, or graphemes made of
|
||||
# multiple code points. One day we will.
|
||||
# We also don't currently support code points that translate into multiple
|
||||
# or wide graphemes. (In particular, Tab will never be supported.)
|
||||
# On Linux, we also don't currently support code points that translate into
|
||||
# multiple or wide graphemes. (In particular, Tab will never be supported.)
|
||||
|
||||
# transliterated from tb_utf8_unicode_to_char in https://github.com/nsf/termbox
|
||||
# https://wiki.tcl-lang.org/page/UTF%2D8+bit+by+bit explains the algorithm
|
||||
#
|
||||
# The day we want to support combining characters, this function will need to
|
||||
# take multiple code points. Or something.
|
||||
fn to-grapheme in: code-point -> _/eax: grapheme {
|
||||
var c/eax: int <- copy in
|
||||
var num-trailers/ecx: int <- copy 0
|
||||
|
|
|
@ -3493,7 +3493,7 @@ fn apply-blit _args-ah: (addr handle cell), out: (addr handle cell), trace: (add
|
|||
var dest-ah/eax: (addr handle screen) <- get second, screen-data
|
||||
var dest/eax: (addr screen) <- lookup *dest-ah
|
||||
#
|
||||
convert-graphemes-to-pixels src
|
||||
convert-screen-cells-to-pixels src
|
||||
copy-pixels src, dest
|
||||
}
|
||||
|
||||
|
|
|
@ -255,7 +255,7 @@ fn render-empty-screen screen: (addr screen), _target-screen: (addr screen), xmi
|
|||
|
||||
fn render-screen screen: (addr screen), _target-screen: (addr screen), xmin: int, ymin: int {
|
||||
var target-screen/esi: (addr screen) <- copy _target-screen
|
||||
convert-graphemes-to-pixels target-screen # might overwrite existing pixel data with graphemes
|
||||
convert-screen-cells-to-pixels target-screen # might overwrite existing pixel data with screen cells
|
||||
# overlapping the two is not supported
|
||||
# pixel data
|
||||
{
|
||||
|
@ -383,10 +383,10 @@ fn print-screen-cell-of-fake-screen screen: (addr screen), _target: (addr screen
|
|||
var index/ecx: int <- screen-cell-index target, x, y
|
||||
var offset/ecx: (offset screen-cell) <- compute-offset data, index
|
||||
var src-cell/esi: (addr screen-cell) <- index data, offset
|
||||
var src-grapheme/eax: (addr grapheme) <- get src-cell, data
|
||||
var src-code-point/eax: (addr code-point) <- get src-cell, data
|
||||
var src-color/ecx: (addr int) <- get src-cell, color
|
||||
var src-background-color/edx: (addr int) <- get src-cell, background-color
|
||||
draw-grapheme-at-cursor-over-full-screen screen, *src-grapheme, *src-color, *src-background-color
|
||||
draw-code-point-at-cursor-over-full-screen screen, *src-code-point, *src-color, *src-background-color
|
||||
}
|
||||
|
||||
fn render-sandbox-edit-menu screen: (addr screen), _self: (addr sandbox) {
|
||||
|
|
Loading…
Reference in New Issue