diff options
Diffstat (limited to 'linux/405screen.mu')
-rw-r--r-- | linux/405screen.mu | 1445 |
1 files changed, 1445 insertions, 0 deletions
diff --git a/linux/405screen.mu b/linux/405screen.mu new file mode 100644 index 00000000..c850df2a --- /dev/null +++ b/linux/405screen.mu @@ -0,0 +1,1445 @@ +# 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 stream-storage: (stream byte 0x100) + var stream/esi: (addr stream byte) <- address stream-storage + write stream, s + print-stream screen, stream +} + +fn print-stream _screen: (addr screen), s: (addr stream byte) { + var screen/edi: (addr screen) <- copy _screen + { + var done?/eax: boolean <- stream-empty? s + compare done?, 0 + break-if-!= + var g/eax: grapheme <- read-grapheme s + 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 +#? } |