74f1512ff1
Convert comments about magic constants into metadata.
1442 lines
50 KiB
Forth
1442 lines
50 KiB
Forth
# Wrappers for real screen primitives that can be passed a fake screen.
|
|
# The tests here have been painstakingly validated against a real terminal
|
|
# emulator. I believe functionality here is broadly portable across terminal
|
|
# emulators.
|
|
#
|
|
# Remember: fake screen co-ordinates are 1-based, just like in real terminal
|
|
# emulators.
|
|
|
|
type screen {
|
|
num-rows: int
|
|
num-cols: int
|
|
data: (handle array screen-cell)
|
|
top-index: int # 0-indexed
|
|
cursor-row: int # 1-indexed
|
|
cursor-col: int # 1-indexed
|
|
cursor-hide?: boolean
|
|
curr-attributes: screen-cell
|
|
}
|
|
|
|
type screen-cell {
|
|
data: grapheme
|
|
color: int
|
|
background-color: int
|
|
bold?: boolean
|
|
underline?: boolean
|
|
reverse?: boolean
|
|
blink?: boolean
|
|
}
|
|
|
|
fn initialize-screen screen: (addr screen), nrows: int, ncols: int {
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var tmp/eax: int <- copy 0
|
|
var dest/edi: (addr int) <- copy 0
|
|
# screen->num-rows = nrows
|
|
dest <- get screen-addr, num-rows
|
|
tmp <- copy nrows
|
|
copy-to *dest, tmp
|
|
# screen->num-cols = ncols
|
|
dest <- get screen-addr, num-cols
|
|
tmp <- copy ncols
|
|
copy-to *dest, tmp
|
|
# screen->data = new screen-cell[nrows*ncols]
|
|
{
|
|
var data-addr/edi: (addr handle array screen-cell) <- get screen-addr, data
|
|
tmp <- multiply nrows
|
|
populate data-addr, tmp
|
|
}
|
|
# screen->cursor-row = 1
|
|
dest <- get screen-addr, cursor-row
|
|
copy-to *dest, 1
|
|
# screen->cursor-col = 1
|
|
dest <- get screen-addr, cursor-col
|
|
copy-to *dest, 1
|
|
# screen->curr-attributes->background-color = 7 (simulate light background)
|
|
var tmp2/eax: (addr screen-cell) <- get screen-addr, curr-attributes
|
|
dest <- get tmp2, background-color
|
|
copy-to *dest, 7
|
|
}
|
|
|
|
fn screen-size screen: (addr screen) -> _/eax: int, _/ecx: int {
|
|
var nrows/eax: int <- copy 0
|
|
var ncols/ecx: int <- copy 0
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
nrows, ncols <- real-screen-size
|
|
return nrows, ncols
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var tmp/edx: (addr int) <- get screen-addr, num-rows
|
|
nrows <- copy *tmp
|
|
tmp <- get screen-addr, num-cols
|
|
ncols <- copy *tmp
|
|
return nrows, ncols
|
|
}
|
|
|
|
fn clear-screen screen: (addr screen) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
clear-real-screen
|
|
return
|
|
}
|
|
# fake screen
|
|
var space/edi: grapheme <- copy 0x20
|
|
move-cursor screen, 1, 1
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var i/eax: int <- copy 1
|
|
var nrows/ecx: (addr int) <- get screen-addr, num-rows
|
|
{
|
|
compare i, *nrows
|
|
break-if->
|
|
var j/edx: int <- copy 1
|
|
var ncols/ebx: (addr int) <- get screen-addr, num-cols
|
|
{
|
|
compare j, *ncols
|
|
break-if->
|
|
print-grapheme screen, space
|
|
j <- increment
|
|
loop
|
|
}
|
|
i <- increment
|
|
loop
|
|
}
|
|
move-cursor screen, 1, 1
|
|
}
|
|
|
|
fn move-cursor screen: (addr screen), row: int, column: int {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
move-cursor-on-real-screen row, column
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
# row < 0 is ignored
|
|
{
|
|
compare row, 0
|
|
break-if->=
|
|
return
|
|
}
|
|
# row = 0 is treated same as 1
|
|
{
|
|
compare row, 0
|
|
break-if-!=
|
|
copy-to row, 1
|
|
}
|
|
# row > num-rows saturates to num-rows
|
|
{
|
|
var nrows-addr/eax: (addr int) <- get screen-addr, num-rows
|
|
var nrows/eax: int <- copy *nrows-addr
|
|
compare row, nrows
|
|
break-if-<=
|
|
copy-to row, nrows
|
|
}
|
|
# column < 0 is ignored
|
|
{
|
|
compare column, 0
|
|
break-if->=
|
|
return
|
|
}
|
|
# column = 0 is treated same as 1
|
|
{
|
|
compare column, 0
|
|
break-if-!=
|
|
copy-to column, 1
|
|
}
|
|
# column > num-cols saturates to num-cols+1 (so wrapping to next row)
|
|
{
|
|
var ncols-addr/eax: (addr int) <- get screen-addr, num-cols
|
|
var ncols/eax: int <- copy *ncols-addr
|
|
compare column, ncols
|
|
break-if-<=
|
|
copy-to column, ncols
|
|
increment column
|
|
}
|
|
# screen->cursor-row = row
|
|
var dest/edi: (addr int) <- get screen-addr, cursor-row
|
|
var src/eax: int <- copy row
|
|
copy-to *dest, src
|
|
# screen->cursor-col = column
|
|
dest <- get screen-addr, cursor-col
|
|
src <- copy column
|
|
copy-to *dest, src
|
|
}
|
|
|
|
fn print-string screen: (addr screen), s: (addr array byte) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen s
|
|
return
|
|
}
|
|
# fake screen
|
|
var s2: (stream byte 0x100)
|
|
var s2-addr/esi: (addr stream byte) <- address s2
|
|
write s2-addr, s
|
|
var screen-addr/edi: (addr screen) <- copy screen
|
|
{
|
|
var done?/eax: boolean <- stream-empty? s2-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var g/eax: grapheme <- read-grapheme s2-addr
|
|
print-grapheme screen, g
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn print-array-of-ints-in-decimal screen: (addr screen), _a: (addr array int) {
|
|
var a/esi: (addr array int) <- copy _a
|
|
var max/ecx: int <- length a
|
|
var i/eax: int <- copy 0
|
|
{
|
|
compare i, max
|
|
break-if->=
|
|
{
|
|
compare i, 0
|
|
break-if-=
|
|
print-string screen, " "
|
|
}
|
|
var x/ecx: (addr int) <- index a, i
|
|
print-int32-decimal screen, *x
|
|
i <- increment
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn print-grapheme screen: (addr screen), c: grapheme {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
print-grapheme-to-real-screen c
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var cursor-col-addr/edx: (addr int) <- get screen-addr, cursor-col
|
|
# adjust cursor if necessary
|
|
# to avoid premature scrolling it's important to do this lazily, at the last possible time
|
|
{
|
|
# next row
|
|
var num-cols-addr/ecx: (addr int) <- get screen-addr, num-cols
|
|
var num-cols/ecx: int <- copy *num-cols-addr
|
|
compare *cursor-col-addr, num-cols
|
|
break-if-<=
|
|
copy-to *cursor-col-addr, 1
|
|
var cursor-row-addr/ebx: (addr int) <- get screen-addr, cursor-row
|
|
increment *cursor-row-addr
|
|
# scroll
|
|
var num-rows-addr/eax: (addr int) <- get screen-addr, num-rows
|
|
var num-rows/eax: int <- copy *num-rows-addr
|
|
compare *cursor-row-addr, num-rows
|
|
break-if-<=
|
|
copy-to *cursor-row-addr, num-rows
|
|
# if (top-index > data size) top-index = 0, otherwise top-index += num-cols
|
|
$print-grapheme:perform-scroll: {
|
|
var top-index-addr/ebx: (addr int) <- get screen-addr, top-index
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var max-index/edi: int <- length data
|
|
compare *top-index-addr, max-index
|
|
{
|
|
break-if->=
|
|
add-to *top-index-addr, num-cols
|
|
break $print-grapheme:perform-scroll
|
|
}
|
|
{
|
|
break-if-<
|
|
copy-to *top-index-addr, 0
|
|
}
|
|
}
|
|
}
|
|
var idx/ecx: int <- current-screen-cell-index screen-addr
|
|
#? print-string-to-real-screen "printing grapheme at screen index "
|
|
#? print-int32-hex-to-real-screen idx
|
|
#? print-string-to-real-screen ": "
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
|
|
var dest-cell/ecx: (addr screen-cell) <- index data, offset
|
|
var src-cell/eax: (addr screen-cell) <- get screen-addr, curr-attributes
|
|
copy-object src-cell, dest-cell
|
|
var dest/eax: (addr grapheme) <- get dest-cell, data
|
|
var c2/ecx: grapheme <- copy c
|
|
#? print-grapheme-to-real-screen c2
|
|
#? print-string-to-real-screen "\n"
|
|
copy-to *dest, c2
|
|
increment *cursor-col-addr
|
|
}
|
|
|
|
fn current-screen-cell-index screen-on-stack: (addr screen) -> _/ecx: int {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var cursor-row-addr/ecx: (addr int) <- get screen, cursor-row
|
|
var cursor-col-addr/eax: (addr int) <- get screen, cursor-col
|
|
var result/ecx: int <- screen-cell-index screen, *cursor-row-addr, *cursor-col-addr
|
|
return result
|
|
}
|
|
|
|
fn screen-cell-index screen-on-stack: (addr screen), row: int, col: int -> _/ecx: int {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var num-cols-addr/eax: (addr int) <- get screen, num-cols
|
|
var num-cols/eax: int <- copy *num-cols-addr
|
|
var result/ecx: int <- copy row
|
|
result <- subtract 1
|
|
result <- multiply num-cols
|
|
result <- add col
|
|
result <- subtract 1
|
|
# result = (result + top-index) % data length
|
|
var top-index-addr/eax: (addr int) <- get screen, top-index
|
|
result <- add *top-index-addr
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var max-index/eax: int <- length data
|
|
compare result, max-index
|
|
{
|
|
break-if-<
|
|
result <- subtract max-index
|
|
}
|
|
return result
|
|
}
|
|
|
|
fn screen-grapheme-at screen-on-stack: (addr screen), row: int, col: int -> _/eax: grapheme {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen-addr, row, col
|
|
var result/eax: grapheme <- screen-grapheme-at-idx screen-addr, idx
|
|
return result
|
|
}
|
|
|
|
fn screen-grapheme-at-idx screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: grapheme {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var idx/ecx: int <- copy idx-on-stack
|
|
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
|
|
var cell/eax: (addr screen-cell) <- index data, offset
|
|
var src/eax: (addr grapheme) <- get cell, data
|
|
return *src
|
|
}
|
|
|
|
fn screen-color-at screen-on-stack: (addr screen), row: int, col: int -> _/eax: int {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen-addr, row, col
|
|
var result/eax: int <- screen-color-at-idx screen-addr, idx
|
|
return result
|
|
}
|
|
|
|
fn screen-color-at-idx screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: int {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var idx/ecx: int <- copy idx-on-stack
|
|
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
|
|
var cell/eax: (addr screen-cell) <- index data, offset
|
|
var src/eax: (addr int) <- get cell, color
|
|
var result/eax: int <- copy *src
|
|
return result
|
|
}
|
|
|
|
fn screen-background-color-at screen-on-stack: (addr screen), row: int, col: int -> _/eax: int {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen-addr, row, col
|
|
var result/eax: int <- screen-background-color-at-idx screen-addr, idx
|
|
return result
|
|
}
|
|
|
|
fn screen-background-color-at-idx screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: int {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var idx/ecx: int <- copy idx-on-stack
|
|
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
|
|
var cell/eax: (addr screen-cell) <- index data, offset
|
|
var src/eax: (addr int) <- get cell, background-color
|
|
return *src
|
|
}
|
|
|
|
fn screen-bold-at? screen-on-stack: (addr screen), row: int, col: int -> _/eax: boolean {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen-addr, row, col
|
|
var result/eax: boolean <- screen-bold-at-idx? screen-addr, idx
|
|
return result
|
|
}
|
|
|
|
fn screen-bold-at-idx? screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: boolean {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var idx/ecx: int <- copy idx-on-stack
|
|
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
|
|
var cell/eax: (addr screen-cell) <- index data, offset
|
|
var src/eax: (addr boolean) <- get cell, bold?
|
|
return *src
|
|
}
|
|
|
|
fn screen-underline-at? screen-on-stack: (addr screen), row: int, col: int -> _/eax: boolean {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen-addr, row, col
|
|
var result/eax: boolean <- screen-underline-at-idx? screen-addr, idx
|
|
return result
|
|
}
|
|
|
|
fn screen-underline-at-idx? screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: boolean {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var idx/ecx: int <- copy idx-on-stack
|
|
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
|
|
var cell/eax: (addr screen-cell) <- index data, offset
|
|
var src/eax: (addr boolean) <- get cell, underline?
|
|
return *src
|
|
}
|
|
|
|
fn screen-reverse-at? screen-on-stack: (addr screen), row: int, col: int -> _/eax: boolean {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen-addr, row, col
|
|
var result/eax: boolean <- screen-reverse-at-idx? screen-addr, idx
|
|
return result
|
|
}
|
|
|
|
fn screen-reverse-at-idx? screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: boolean {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var idx/ecx: int <- copy idx-on-stack
|
|
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
|
|
var cell/eax: (addr screen-cell) <- index data, offset
|
|
var src/eax: (addr boolean) <- get cell, reverse?
|
|
return *src
|
|
}
|
|
|
|
fn screen-blink-at? screen-on-stack: (addr screen), row: int, col: int -> _/eax: boolean {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen-addr, row, col
|
|
var result/eax: boolean <- screen-blink-at-idx? screen-addr, idx
|
|
return result
|
|
}
|
|
|
|
fn screen-blink-at-idx? screen-on-stack: (addr screen), idx-on-stack: int -> _/eax: boolean {
|
|
var screen-addr/esi: (addr screen) <- copy screen-on-stack
|
|
var data-ah/eax: (addr handle array screen-cell) <- get screen-addr, data
|
|
var data/eax: (addr array screen-cell) <- lookup *data-ah
|
|
var idx/ecx: int <- copy idx-on-stack
|
|
var offset/ecx: (offset screen-cell) <- compute-offset data, idx
|
|
var cell/eax: (addr screen-cell) <- index data, offset
|
|
var src/eax: (addr boolean) <- get cell, blink?
|
|
return *src
|
|
}
|
|
|
|
fn print-code-point screen: (addr screen), c: code-point {
|
|
var g/eax: grapheme <- to-grapheme c
|
|
print-grapheme screen, g
|
|
}
|
|
|
|
fn print-int32-hex screen: (addr screen), n: int {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
print-int32-hex-to-real-screen n
|
|
return
|
|
}
|
|
# fake screen
|
|
var s2: (stream byte 0x100)
|
|
var s2-addr/esi: (addr stream byte) <- address s2
|
|
write-int32-hex s2-addr, n
|
|
var screen-addr/edi: (addr screen) <- copy screen
|
|
{
|
|
var done?/eax: boolean <- stream-empty? s2-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var g/eax: grapheme <- read-grapheme s2-addr
|
|
print-grapheme screen, g
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn print-int32-hex-bits screen: (addr screen), n: int, bits: int {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
print-int32-hex-bits-to-real-screen n, bits
|
|
return
|
|
}
|
|
# fake screen
|
|
var s2: (stream byte 0x100)
|
|
var s2-addr/esi: (addr stream byte) <- address s2
|
|
write-int32-hex-bits s2-addr, n, bits
|
|
var screen-addr/edi: (addr screen) <- copy screen
|
|
{
|
|
var done?/eax: boolean <- stream-empty? s2-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var g/eax: grapheme <- read-grapheme s2-addr
|
|
print-grapheme screen, g
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn print-int32-decimal screen: (addr screen), n: int {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
print-int32-decimal-to-real-screen n
|
|
return
|
|
}
|
|
# fake screen
|
|
var s2: (stream byte 0x100)
|
|
var s2-addr/esi: (addr stream byte) <- address s2
|
|
write-int32-decimal s2-addr, n
|
|
var screen-addr/edi: (addr screen) <- copy screen
|
|
{
|
|
var done?/eax: boolean <- stream-empty? s2-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var g/eax: grapheme <- read-grapheme s2-addr
|
|
print-grapheme screen, g
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn reset-formatting screen: (addr screen) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
reset-formatting-on-real-screen
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var dest/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
|
|
var default-cell: screen-cell
|
|
var bg/eax: (addr int) <- get default-cell, background-color
|
|
copy-to *bg, 7
|
|
var default-cell-addr/eax: (addr screen-cell) <- address default-cell
|
|
copy-object default-cell-addr, dest
|
|
}
|
|
|
|
fn start-color screen: (addr screen), fg: int, bg: int {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
start-color-on-real-screen fg, bg
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
|
|
var dest/edx: (addr int) <- get attr, color
|
|
var src/eax: int <- copy fg
|
|
copy-to *dest, src
|
|
var dest/edx: (addr int) <- get attr, background-color
|
|
var src/eax: int <- copy bg
|
|
copy-to *dest, src
|
|
}
|
|
|
|
fn start-bold screen: (addr screen) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
start-bold-on-real-screen
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
|
|
var dest/edx: (addr boolean) <- get attr, bold?
|
|
copy-to *dest, 1
|
|
}
|
|
|
|
fn start-underline screen: (addr screen) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
start-underline-on-real-screen
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
|
|
var dest/edx: (addr boolean) <- get attr, underline?
|
|
copy-to *dest, 1
|
|
}
|
|
|
|
fn start-reverse-video screen: (addr screen) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
start-reverse-video-on-real-screen
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
|
|
var dest/edx: (addr boolean) <- get attr, reverse?
|
|
copy-to *dest, 1
|
|
}
|
|
|
|
fn start-blinking screen: (addr screen) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
start-blinking-on-real-screen
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var attr/ecx: (addr screen-cell) <- get screen-addr, curr-attributes
|
|
var dest/edx: (addr boolean) <- get attr, blink?
|
|
copy-to *dest, 1
|
|
}
|
|
|
|
fn hide-cursor screen: (addr screen) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
hide-cursor-on-real-screen
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var hide?/ecx: (addr boolean) <- get screen-addr, cursor-hide?
|
|
copy-to *hide?, 1
|
|
}
|
|
|
|
fn show-cursor screen: (addr screen) {
|
|
compare screen, 0
|
|
{
|
|
break-if-!=
|
|
show-cursor-on-real-screen
|
|
return
|
|
}
|
|
# fake screen
|
|
var screen-addr/esi: (addr screen) <- copy screen
|
|
var hide?/ecx: (addr boolean) <- get screen-addr, cursor-hide?
|
|
copy-to *hide?, 0
|
|
}
|
|
|
|
# validate data on screen regardless of attributes (color, bold, etc.)
|
|
# Mu doesn't have multi-line strings, so we provide functions for rows or portions of rows.
|
|
# Tab characters (that translate into multiple screen cells) not supported.
|
|
|
|
fn check-screen-row screen: (addr screen), row-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
check-screen-row-from screen, row-idx, 1, expected, msg
|
|
}
|
|
|
|
fn check-screen-row-from screen-on-stack: (addr screen), row-idx: int, col-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen, row-idx, col-idx
|
|
# compare 'expected' with the screen contents starting at 'idx', grapheme by grapheme
|
|
var e: (stream byte 0x100)
|
|
var e-addr/edx: (addr stream byte) <- address e
|
|
write e-addr, expected
|
|
{
|
|
var done?/eax: boolean <- stream-empty? e-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var _g/eax: grapheme <- screen-grapheme-at-idx screen, idx
|
|
var g/ebx: grapheme <- copy _g
|
|
var expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
|
# compare graphemes
|
|
$check-screen-row-from:compare-graphemes: {
|
|
# if expected-grapheme is space, null grapheme is also ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
compare g, 0
|
|
break-if-= $check-screen-row-from:compare-graphemes
|
|
}
|
|
# if (g == expected-grapheme) print "."
|
|
compare g, expected-grapheme
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-from:compare-graphemes
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") but observed '"
|
|
print-grapheme-to-real-screen g
|
|
print-string-to-real-screen "'\n"
|
|
}
|
|
idx <- increment
|
|
increment col-idx
|
|
loop
|
|
}
|
|
}
|
|
|
|
# various variants by screen-cell attribute; spaces in the 'expected' data should not match the attribute
|
|
|
|
fn check-screen-row-in-color screen: (addr screen), fg: int, row-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
check-screen-row-in-color-from screen, fg, row-idx, 1, expected, msg
|
|
}
|
|
|
|
fn check-screen-row-in-color-from screen-on-stack: (addr screen), fg: int, row-idx: int, col-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen, row-idx, col-idx
|
|
# compare 'expected' with the screen contents starting at 'idx', grapheme by grapheme
|
|
var e: (stream byte 0x100)
|
|
var e-addr/edx: (addr stream byte) <- address e
|
|
write e-addr, expected
|
|
{
|
|
var done?/eax: boolean <- stream-empty? e-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var _g/eax: grapheme <- screen-grapheme-at-idx screen, idx
|
|
var g/ebx: grapheme <- copy _g
|
|
var _expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
|
var expected-grapheme/edi: grapheme <- copy _expected-grapheme
|
|
$check-screen-row-in-color-from:compare-cells: {
|
|
# if expected-grapheme is space, null grapheme is also ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
compare g, 0
|
|
break-if-= $check-screen-row-in-color-from:compare-cells
|
|
}
|
|
# if expected-grapheme is space, a different color is ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
var color/eax: int <- screen-color-at-idx screen, idx
|
|
compare color, fg
|
|
break-if-!= $check-screen-row-in-color-from:compare-cells
|
|
}
|
|
# compare graphemes
|
|
$check-screen-row-in-color-from:compare-graphemes: {
|
|
# if (g == expected-grapheme) print "."
|
|
compare g, expected-grapheme
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-color-from:compare-graphemes
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") but observed '"
|
|
print-grapheme-to-real-screen g
|
|
print-string-to-real-screen "'\n"
|
|
}
|
|
$check-screen-row-in-color-from:compare-colors: {
|
|
var color/eax: int <- screen-color-at-idx screen, idx
|
|
compare fg, color
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-color-from:compare-colors
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") in color "
|
|
print-int32-hex-to-real-screen fg
|
|
print-string-to-real-screen " but observed color "
|
|
print-int32-hex-to-real-screen color
|
|
print-string-to-real-screen "\n"
|
|
}
|
|
}
|
|
idx <- increment
|
|
increment col-idx
|
|
loop
|
|
}
|
|
}
|
|
|
|
# background color is visible even for spaces, so 'expected' behaves as an array of booleans.
|
|
# non-space = given background must match; space = background must not match
|
|
fn check-screen-row-in-background-color screen: (addr screen), bg: int, row-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
check-screen-row-in-background-color-from screen, bg, row-idx, 1, expected, msg
|
|
}
|
|
|
|
fn check-screen-row-in-background-color-from screen-on-stack: (addr screen), bg: int, row-idx: int, col-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen, row-idx, col-idx
|
|
# compare 'expected' with the screen contents starting at 'idx', grapheme by grapheme
|
|
var e: (stream byte 0x100)
|
|
var e-addr/edx: (addr stream byte) <- address e
|
|
write e-addr, expected
|
|
{
|
|
var done?/eax: boolean <- stream-empty? e-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var _g/eax: grapheme <- screen-grapheme-at-idx screen, idx
|
|
var g/ebx: grapheme <- copy _g
|
|
var _expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
|
var expected-grapheme/edx: grapheme <- copy _expected-grapheme
|
|
$check-screen-row-in-background-color-from:compare-cells: {
|
|
# if expected-grapheme is space, null grapheme is also ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
compare g, 0
|
|
break-if-= $check-screen-row-in-background-color-from:compare-cells
|
|
}
|
|
# if expected-grapheme is space, a different color is ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
var color/eax: int <- screen-background-color-at-idx screen, idx
|
|
compare color, bg
|
|
break-if-!= $check-screen-row-in-background-color-from:compare-cells
|
|
}
|
|
# compare graphemes
|
|
$check-screen-row-in-background-color-from:compare-graphemes: {
|
|
# if (g == expected-grapheme) print "."
|
|
compare g, expected-grapheme
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-background-color-from:compare-graphemes
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") but observed '"
|
|
print-grapheme-to-real-screen g
|
|
print-string-to-real-screen "'\n"
|
|
}
|
|
$check-screen-row-in-background-color-from:compare-colors: {
|
|
var color/eax: int <- screen-background-color-at-idx screen, idx
|
|
compare bg, color
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-background-color-from:compare-colors
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") in background color "
|
|
print-int32-hex-to-real-screen bg
|
|
print-string-to-real-screen " but observed color "
|
|
print-int32-hex-to-real-screen color
|
|
print-string-to-real-screen "\n"
|
|
}
|
|
}
|
|
idx <- increment
|
|
increment col-idx
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn check-screen-row-in-bold screen: (addr screen), row-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
check-screen-row-in-bold-from screen, row-idx, 1, expected, msg
|
|
}
|
|
|
|
fn check-screen-row-in-bold-from screen-on-stack: (addr screen), row-idx: int, col-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen, row-idx, col-idx
|
|
# compare 'expected' with the screen contents starting at 'idx', grapheme by grapheme
|
|
var e: (stream byte 0x100)
|
|
var e-addr/edx: (addr stream byte) <- address e
|
|
write e-addr, expected
|
|
{
|
|
var done?/eax: boolean <- stream-empty? e-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var _g/eax: grapheme <- screen-grapheme-at-idx screen, idx
|
|
var g/ebx: grapheme <- copy _g
|
|
var _expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
|
var expected-grapheme/edx: grapheme <- copy _expected-grapheme
|
|
$check-screen-row-in-bold-from:compare-cells: {
|
|
# if expected-grapheme is space, null grapheme is also ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
compare g, 0
|
|
break-if-= $check-screen-row-in-bold-from:compare-cells
|
|
}
|
|
# if expected-grapheme is space, non-bold is ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
var bold?/eax: boolean <- screen-bold-at-idx? screen, idx
|
|
compare bold?, 1
|
|
break-if-!= $check-screen-row-in-bold-from:compare-cells
|
|
}
|
|
# compare graphemes
|
|
$check-screen-row-in-bold-from:compare-graphemes: {
|
|
# if (g == expected-grapheme) print "."
|
|
compare g, expected-grapheme
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-bold-from:compare-graphemes
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") but observed '"
|
|
print-grapheme-to-real-screen g
|
|
print-string-to-real-screen "'\n"
|
|
}
|
|
$check-screen-row-in-bold-from:compare-bold: {
|
|
var bold?/eax: boolean <- screen-bold-at-idx? screen, idx
|
|
compare bold?, 1
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-bold-from:compare-bold
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") to be in bold\n"
|
|
}
|
|
}
|
|
idx <- increment
|
|
increment col-idx
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn check-screen-row-in-underline screen: (addr screen), row-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
check-screen-row-in-underline-from screen, row-idx, 1, expected, msg
|
|
}
|
|
|
|
fn check-screen-row-in-underline-from screen-on-stack: (addr screen), row-idx: int, col-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen, row-idx, col-idx
|
|
# compare 'expected' with the screen contents starting at 'idx', grapheme by grapheme
|
|
var e: (stream byte 0x100)
|
|
var e-addr/edx: (addr stream byte) <- address e
|
|
write e-addr, expected
|
|
{
|
|
var done?/eax: boolean <- stream-empty? e-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var _g/eax: grapheme <- screen-grapheme-at-idx screen, idx
|
|
var g/ebx: grapheme <- copy _g
|
|
var _expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
|
var expected-grapheme/edx: grapheme <- copy _expected-grapheme
|
|
$check-screen-row-in-underline-from:compare-cells: {
|
|
# if expected-grapheme is space, null grapheme is also ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
compare g, 0
|
|
break-if-= $check-screen-row-in-underline-from:compare-cells
|
|
}
|
|
# if expected-grapheme is space, non-underline is ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
var underline?/eax: boolean <- screen-underline-at-idx? screen, idx
|
|
compare underline?, 1
|
|
break-if-!= $check-screen-row-in-underline-from:compare-cells
|
|
}
|
|
# compare graphemes
|
|
$check-screen-row-in-underline-from:compare-graphemes: {
|
|
# if (g == expected-grapheme) print "."
|
|
compare g, expected-grapheme
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-underline-from:compare-graphemes
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") but observed '"
|
|
print-grapheme-to-real-screen g
|
|
print-string-to-real-screen "'\n"
|
|
}
|
|
$check-screen-row-in-underline-from:compare-underline: {
|
|
var underline?/eax: boolean <- screen-underline-at-idx? screen, idx
|
|
compare underline?, 1
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-underline-from:compare-underline
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") to be underlined\n"
|
|
}
|
|
}
|
|
idx <- increment
|
|
increment col-idx
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn check-screen-row-in-reverse screen: (addr screen), row-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
check-screen-row-in-reverse-from screen, row-idx, 1, expected, msg
|
|
}
|
|
|
|
fn check-screen-row-in-reverse-from screen-on-stack: (addr screen), row-idx: int, col-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen, row-idx, col-idx
|
|
# compare 'expected' with the screen contents starting at 'idx', grapheme by grapheme
|
|
var e: (stream byte 0x100)
|
|
var e-addr/edx: (addr stream byte) <- address e
|
|
write e-addr, expected
|
|
{
|
|
var done?/eax: boolean <- stream-empty? e-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var _g/eax: grapheme <- screen-grapheme-at-idx screen, idx
|
|
var g/ebx: grapheme <- copy _g
|
|
var _expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
|
var expected-grapheme/edx: grapheme <- copy _expected-grapheme
|
|
$check-screen-row-in-reverse-from:compare-cells: {
|
|
# if expected-grapheme is space, null grapheme is also ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
compare g, 0
|
|
break-if-= $check-screen-row-in-reverse-from:compare-cells
|
|
}
|
|
# if expected-grapheme is space, non-reverse is ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
var reverse?/eax: boolean <- screen-reverse-at-idx? screen, idx
|
|
compare reverse?, 1
|
|
break-if-!= $check-screen-row-in-reverse-from:compare-cells
|
|
}
|
|
# compare graphemes
|
|
$check-screen-row-in-reverse-from:compare-graphemes: {
|
|
# if (g == expected-grapheme) print "."
|
|
compare g, expected-grapheme
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-reverse-from:compare-graphemes
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") but observed '"
|
|
print-grapheme-to-real-screen g
|
|
print-string-to-real-screen "'\n"
|
|
}
|
|
$check-screen-row-in-reverse-from:compare-reverse: {
|
|
var reverse?/eax: boolean <- screen-reverse-at-idx? screen, idx
|
|
compare reverse?, 1
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-reverse-from:compare-reverse
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") to be in reverse-video\n"
|
|
}
|
|
}
|
|
idx <- increment
|
|
increment col-idx
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn check-screen-row-in-blinking screen: (addr screen), row-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
check-screen-row-in-blinking-from screen, row-idx, 1, expected, msg
|
|
}
|
|
|
|
fn check-screen-row-in-blinking-from screen-on-stack: (addr screen), row-idx: int, col-idx: int, expected: (addr array byte), msg: (addr array byte) {
|
|
var screen/esi: (addr screen) <- copy screen-on-stack
|
|
var idx/ecx: int <- screen-cell-index screen, row-idx, col-idx
|
|
# compare 'expected' with the screen contents starting at 'idx', grapheme by grapheme
|
|
var e: (stream byte 0x100)
|
|
var e-addr/edx: (addr stream byte) <- address e
|
|
write e-addr, expected
|
|
{
|
|
var done?/eax: boolean <- stream-empty? e-addr
|
|
compare done?, 0
|
|
break-if-!=
|
|
var _g/eax: grapheme <- screen-grapheme-at-idx screen, idx
|
|
var g/ebx: grapheme <- copy _g
|
|
var _expected-grapheme/eax: grapheme <- read-grapheme e-addr
|
|
var expected-grapheme/edx: grapheme <- copy _expected-grapheme
|
|
$check-screen-row-in-blinking-from:compare-cells: {
|
|
# if expected-grapheme is space, null grapheme is also ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
compare g, 0
|
|
break-if-= $check-screen-row-in-blinking-from:compare-cells
|
|
}
|
|
# if expected-grapheme is space, non-blinking is ok
|
|
{
|
|
compare expected-grapheme, 0x20
|
|
break-if-!=
|
|
var blinking?/eax: boolean <- screen-blink-at-idx? screen, idx
|
|
compare blinking?, 1
|
|
break-if-!= $check-screen-row-in-blinking-from:compare-cells
|
|
}
|
|
# compare graphemes
|
|
$check-screen-row-in-blinking-from:compare-graphemes: {
|
|
# if (g == expected-grapheme) print "."
|
|
compare g, expected-grapheme
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-blinking-from:compare-graphemes
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") but observed '"
|
|
print-grapheme-to-real-screen g
|
|
print-string-to-real-screen "'\n"
|
|
}
|
|
$check-screen-row-in-blinking-from:compare-blinking: {
|
|
var blinking?/eax: boolean <- screen-blink-at-idx? screen, idx
|
|
compare blinking?, 1
|
|
{
|
|
break-if-!=
|
|
print-string-to-real-screen "."
|
|
break $check-screen-row-in-blinking-from:compare-blinking
|
|
}
|
|
# otherwise print an error
|
|
print-string-to-real-screen msg
|
|
print-string-to-real-screen ": expected '"
|
|
print-grapheme-to-real-screen expected-grapheme
|
|
print-string-to-real-screen "' at ("
|
|
print-int32-hex-to-real-screen row-idx
|
|
print-string-to-real-screen ", "
|
|
print-int32-hex-to-real-screen col-idx
|
|
print-string-to-real-screen ") to be blinking\n"
|
|
}
|
|
}
|
|
idx <- increment
|
|
increment col-idx
|
|
|
|
loop
|
|
}
|
|
}
|
|
|
|
fn test-print-single-grapheme {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
check-screen-row screen, 1/row, "a", "F - test-print-single-grapheme" # top-left corner of the screen
|
|
}
|
|
|
|
fn test-print-multiple-graphemes {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
print-string screen, "Hello, 世界"
|
|
check-screen-row screen, 1/row, "Hello, 世界", "F - test-print-multiple-graphemes"
|
|
}
|
|
|
|
fn test-move-cursor {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
move-cursor screen, 1, 4
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
check-screen-row screen, 1/row, " a", "F - test-move-cursor" # top row
|
|
}
|
|
|
|
fn test-move-cursor-zeroes {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
move-cursor screen, 0, 0
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
check-screen-row screen, 1/row, "a", "F - test-move-cursor-zeroes" # top-left corner of the screen
|
|
}
|
|
|
|
fn test-move-cursor-zero-row {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
move-cursor screen, 0, 2
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
check-screen-row screen, 1/row, " a", "F - test-move-cursor-zero-row" # top row
|
|
}
|
|
|
|
fn test-move-cursor-zero-column {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
move-cursor screen, 4, 0
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
check-screen-row screen, 4/row, "a", "F - test-move-cursor-zero-column"
|
|
}
|
|
|
|
fn test-move-cursor-negative-row {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5, 3
|
|
move-cursor screen, -1/row, 2/col
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
# no move
|
|
check-screen-row screen, 1/row, "a", "F - test-move-cursor-negative-row"
|
|
}
|
|
|
|
fn test-move-cursor-negative-column {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5, 3
|
|
move-cursor screen, 2/row, -1/col
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
# no move
|
|
check-screen-row screen, 1/row, "a", "F - test-move-cursor-negative-column"
|
|
}
|
|
|
|
fn test-move-cursor-column-too-large {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 3/cols
|
|
move-cursor screen, 1/row, 4/col
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
# top row is empty
|
|
check-screen-row screen, 1/row, " ", "F - test-move-cursor-column-too-large"
|
|
# character shows up on next row
|
|
check-screen-row screen, 2/row, "a", "F - test-move-cursor-column-too-large"
|
|
}
|
|
|
|
fn test-move-cursor-column-too-large-saturates {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 3/cols
|
|
move-cursor screen, 1/row, 6/col
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
# top row is empty
|
|
check-screen-row screen, 1/row, " ", "F - test-move-cursor-column-too-large-saturates" # top-left corner of the screen
|
|
# character shows up at the start of next row
|
|
check-screen-row screen, 2/row, "a", "F - test-move-cursor-column-too-large-saturates" # top-left corner of the screen
|
|
}
|
|
|
|
fn test-move-cursor-row-too-large {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 3/cols
|
|
move-cursor screen, 6/row, 2/col
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
# bottom row shows the character
|
|
check-screen-row screen, 5/row, " a", "F - test-move-cursor-row-too-large"
|
|
}
|
|
|
|
fn test-move-cursor-row-too-large-saturates {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 3/cols
|
|
move-cursor screen, 9/row, 2/col
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
# bottom row shows the character
|
|
check-screen-row screen, 5/row, " a", "F - test-move-cursor-row-too-large-saturates"
|
|
}
|
|
|
|
fn test-check-screen-row-from {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
move-cursor screen, 1, 4
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
check-screen-row screen, 1/row, " a", "F - test-check-screen-row-from/baseline"
|
|
check-screen-row-from screen, 1/row, 4/col, "a", "F - test-check-screen-row-from"
|
|
}
|
|
|
|
fn test-print-string-overflows-to-next-row {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
print-string screen, "abcdefg"
|
|
check-screen-row screen, 1/row, "abcd", "F - test-print-string-overflows-to-next-row"
|
|
check-screen-row screen, 2/row, "efg", "F - test-print-string-overflows-to-next-row"
|
|
}
|
|
|
|
fn test-check-screen-scrolls-on-overflow {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
# single character starting at bottom right
|
|
move-cursor screen, 5/rows, 4/cols
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
check-screen-row-from screen, 5/row, 4/col, "a", "F - test-check-screen-scrolls-on-overflow/baseline" # bottom-right corner of the screen
|
|
# multiple characters starting at bottom right
|
|
move-cursor screen, 5, 4
|
|
print-string screen, "ab"
|
|
# screen scrolled up one row
|
|
#? check-screen-row screen, 1/row, " ", "F - test-check-screen-scrolls-on-overflow/x1"
|
|
#? check-screen-row screen, 2/row, " ", "F - test-check-screen-scrolls-on-overflow/x2"
|
|
#? check-screen-row screen, 3/row, " ", "F - test-check-screen-scrolls-on-overflow/x3"
|
|
#? check-screen-row screen, 4/row, " a", "F - test-check-screen-scrolls-on-overflow/x4"
|
|
#? check-screen-row screen, 5/row, "b ", "F - test-check-screen-scrolls-on-overflow/x5"
|
|
check-screen-row-from screen, 4/row, 4/col, "a", "F - test-check-screen-scrolls-on-overflow/1"
|
|
check-screen-row-from screen, 5/row, 1/col, "b", "F - test-check-screen-scrolls-on-overflow/2"
|
|
}
|
|
|
|
fn test-check-screen-color {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
start-color screen, 1/fg, 0/bg
|
|
c <- copy 0x62/b
|
|
print-grapheme screen, c
|
|
start-color screen, 0/fg, 7/bg
|
|
c <- copy 0x63/c
|
|
print-grapheme screen, c
|
|
check-screen-row-in-color screen, 0/fg, 1/row, "a c", "F - test-check-screen-color"
|
|
}
|
|
|
|
fn test-check-screen-background-color {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
start-color screen, 0/fg, 1/bg
|
|
c <- copy 0x62/b
|
|
print-grapheme screen, c
|
|
start-color screen, 0/fg, 7/bg
|
|
c <- copy 0x63/c
|
|
print-grapheme screen, c
|
|
check-screen-row-in-background-color screen, 7/bg, 1/row, "a c", "F - test-check-screen-background-color"
|
|
}
|
|
|
|
fn test-check-screen-bold {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
start-bold screen
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
reset-formatting screen
|
|
c <- copy 0x62/b
|
|
print-grapheme screen, c
|
|
start-bold screen
|
|
c <- copy 0x63/c
|
|
print-grapheme screen, c
|
|
check-screen-row-in-bold screen, 1/row, "a c", "F - test-check-screen-bold"
|
|
}
|
|
|
|
fn test-check-screen-underline {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
start-underline screen
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
reset-formatting screen
|
|
c <- copy 0x62/b
|
|
print-grapheme screen, c
|
|
start-underline screen
|
|
c <- copy 0x63/c
|
|
print-grapheme screen, c
|
|
check-screen-row-in-underline screen, 1/row, "a c", "F - test-check-screen-underline"
|
|
}
|
|
|
|
fn test-check-screen-reverse {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
start-reverse-video screen
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
reset-formatting screen
|
|
c <- copy 0x62/b
|
|
print-grapheme screen, c
|
|
start-reverse-video screen
|
|
c <- copy 0x63/c
|
|
print-grapheme screen, c
|
|
check-screen-row-in-reverse screen, 1/row, "a c", "F - test-check-screen-reverse"
|
|
}
|
|
|
|
fn test-check-screen-blinking {
|
|
var screen-on-stack: screen
|
|
var screen/esi: (addr screen) <- address screen-on-stack
|
|
initialize-screen screen, 5/rows, 4/cols
|
|
start-blinking screen
|
|
var c/eax: grapheme <- copy 0x61/a
|
|
print-grapheme screen, c
|
|
reset-formatting screen
|
|
c <- copy 0x62/b
|
|
print-grapheme screen, c
|
|
start-blinking screen
|
|
c <- copy 0x63/c
|
|
print-grapheme screen, c
|
|
check-screen-row-in-blinking screen, 1/row, "a c", "F - test-check-screen-blinking"
|
|
}
|
|
|
|
#? fn main -> _/ebx: int {
|
|
#? #? test-check-screen-color
|
|
#? run-tests
|
|
#? return 0
|
|
#? }
|