2015-04-29 07:22:20 +00:00
|
|
|
# Wrappers around print primitives that take a 'screen' object and are thus
|
|
|
|
# easier to test.
|
|
|
|
|
|
|
|
container screen [
|
2016-09-17 17:28:25 +00:00
|
|
|
num-rows:num
|
|
|
|
num-columns:num
|
|
|
|
cursor-row:num
|
|
|
|
cursor-column:num
|
2016-09-17 20:00:39 +00:00
|
|
|
data:&:@:screen-cell
|
2015-05-26 23:15:50 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
container screen-cell [
|
2016-09-17 07:31:55 +00:00
|
|
|
contents:char
|
2016-09-17 17:28:25 +00:00
|
|
|
color:num
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def new-fake-screen w:num, h:num -> result:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
|
|
|
result <- new screen:type
|
2016-09-17 17:28:25 +00:00
|
|
|
bufsize:num <- multiply w, h
|
2016-09-17 20:00:39 +00:00
|
|
|
data:&:@:screen-cell <- new screen-cell:type, bufsize
|
2016-04-16 18:57:20 +00:00
|
|
|
*result <- merge h/num-rows, w/num-columns, 0/cursor-row, 0/cursor-column, data
|
2015-11-19 05:36:36 +00:00
|
|
|
result <- clear-screen result
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def clear-screen screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
break-if screen
|
|
|
|
# real screen
|
|
|
|
clear-display
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
|
|
|
buf:&:@:screen-cell <- get *screen, data:offset
|
|
|
|
max:num <- length *buf
|
|
|
|
i:num <- copy 0
|
|
|
|
{
|
|
|
|
done?:bool <- greater-or-equal i, max
|
|
|
|
break-if done?
|
|
|
|
curr:screen-cell <- merge 0/empty, 7/white
|
|
|
|
*buf <- put-index *buf, i, curr
|
|
|
|
i <- add i, 1
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
# reset cursor
|
|
|
|
*screen <- put *screen, cursor-row:offset, 0
|
|
|
|
*screen <- put *screen, cursor-column:offset, 0
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def sync-screen screen:&:screen -> screen:&:screen [
|
2015-08-30 06:50:29 +00:00
|
|
|
local-scope
|
2016-01-13 06:10:38 +00:00
|
|
|
load-ingredients
|
2016-10-24 04:15:43 +00:00
|
|
|
return-if screen # do nothing for fake screens
|
|
|
|
sync-display
|
2015-08-30 06:50:29 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def fake-screen-is-empty? screen:&:screen -> result:bool [
|
2015-07-17 19:51:32 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-10-24 04:15:43 +00:00
|
|
|
return-unless screen, 1/true # do nothing for real screens
|
2016-09-17 20:00:39 +00:00
|
|
|
buf:&:@:screen-cell <- get *screen, data:offset
|
2016-09-17 17:28:25 +00:00
|
|
|
i:num <- copy 0
|
|
|
|
len:num <- length *buf
|
2015-07-17 19:51:32 +00:00
|
|
|
{
|
2016-09-17 17:32:57 +00:00
|
|
|
done?:bool <- greater-or-equal i, len
|
2015-07-29 21:37:57 +00:00
|
|
|
break-if done?
|
|
|
|
curr:screen-cell <- index *buf, i
|
2016-09-17 07:31:55 +00:00
|
|
|
curr-contents:char <- get curr, contents:offset
|
2015-07-29 21:37:57 +00:00
|
|
|
i <- add i, 1
|
|
|
|
loop-unless curr-contents
|
2015-07-17 19:51:32 +00:00
|
|
|
# not 0
|
2016-03-08 09:30:14 +00:00
|
|
|
return 0/false
|
2015-07-17 19:51:32 +00:00
|
|
|
}
|
2016-03-08 09:30:14 +00:00
|
|
|
return 1/true
|
2015-07-17 19:51:32 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def print screen:&:screen, c:char -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-09-17 17:32:57 +00:00
|
|
|
color:num, color-found?:bool <- next-ingredient
|
2015-05-26 23:15:50 +00:00
|
|
|
{
|
|
|
|
# default color to white
|
2015-07-29 21:37:57 +00:00
|
|
|
break-if color-found?
|
|
|
|
color <- copy 7/white
|
2015-05-26 23:15:50 +00:00
|
|
|
}
|
2016-09-17 17:32:57 +00:00
|
|
|
bg-color:num, bg-color-found?:bool <- next-ingredient
|
2015-07-05 03:46:50 +00:00
|
|
|
{
|
2015-07-05 06:08:08 +00:00
|
|
|
# default bg-color to black
|
2015-07-29 21:37:57 +00:00
|
|
|
break-if bg-color-found?
|
|
|
|
bg-color <- copy 0/black
|
2015-07-05 03:46:50 +00:00
|
|
|
}
|
2016-09-17 17:28:25 +00:00
|
|
|
c2:num <- character-to-code c
|
2016-09-17 06:35:32 +00:00
|
|
|
trace 90, [print-character], c2
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
# real screen
|
|
|
|
break-if screen
|
|
|
|
print-character-to-display c, color, bg-color
|
|
|
|
return
|
|
|
|
}
|
|
|
|
# fake screen
|
|
|
|
# (handle special cases exactly like in the real screen)
|
|
|
|
width:num <- get *screen, num-columns:offset
|
|
|
|
height:num <- get *screen, num-rows:offset
|
|
|
|
# if cursor is out of bounds, silently exit
|
|
|
|
row:num <- get *screen, cursor-row:offset
|
|
|
|
legal?:bool <- greater-or-equal row, 0
|
|
|
|
return-unless legal?
|
|
|
|
legal? <- lesser-than row, height
|
|
|
|
return-unless legal?
|
|
|
|
column:num <- get *screen, cursor-column:offset
|
|
|
|
legal? <- greater-or-equal column, 0
|
|
|
|
return-unless legal?
|
|
|
|
legal? <- lesser-than column, width
|
|
|
|
return-unless legal?
|
2016-04-16 22:50:56 +00:00
|
|
|
#? $print [print-character (], row, [, ], column, [): ], c, 10/newline
|
2016-10-24 04:15:43 +00:00
|
|
|
# special-case: newline
|
|
|
|
{
|
|
|
|
newline?:bool <- equal c, 10/newline
|
|
|
|
break-unless newline?
|
2015-05-10 15:34:12 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
# unless cursor is already at bottom
|
|
|
|
bottom:num <- subtract height, 1
|
|
|
|
at-bottom?:bool <- greater-or-equal row, bottom
|
|
|
|
break-if at-bottom?
|
|
|
|
# move it to the next row
|
|
|
|
column <- copy 0
|
|
|
|
*screen <- put *screen, cursor-column:offset, column
|
|
|
|
row <- add row, 1
|
|
|
|
*screen <- put *screen, cursor-row:offset, row
|
2015-05-10 15:34:12 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
# save character in fake screen
|
|
|
|
index:num <- multiply row, width
|
|
|
|
index <- add index, column
|
|
|
|
buf:&:@:screen-cell <- get *screen, data:offset
|
|
|
|
len:num <- length *buf
|
|
|
|
# special-case: backspace
|
|
|
|
{
|
|
|
|
backspace?:bool <- equal c, 8
|
|
|
|
break-unless backspace?
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
# unless cursor is already at left margin
|
|
|
|
at-left?:bool <- lesser-or-equal column, 0
|
|
|
|
break-if at-left?
|
|
|
|
# clear previous location
|
|
|
|
column <- subtract column, 1
|
2016-04-16 22:50:56 +00:00
|
|
|
*screen <- put *screen, cursor-column:offset, column
|
2016-10-24 04:15:43 +00:00
|
|
|
index <- subtract index, 1
|
|
|
|
cursor:screen-cell <- merge 32/space, 7/white
|
|
|
|
*buf <- put-index *buf, index, cursor
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
cursor:screen-cell <- merge c, color
|
|
|
|
*buf <- put-index *buf, index, cursor
|
|
|
|
# increment column unless it's already all the way to the right
|
|
|
|
{
|
|
|
|
right:num <- subtract width, 1
|
|
|
|
at-right?:bool <- greater-or-equal column, right
|
|
|
|
break-if at-right?
|
|
|
|
column <- add column, 1
|
|
|
|
*screen <- put *screen, cursor-column:offset, column
|
|
|
|
}
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2015-04-30 07:02:54 +00:00
|
|
|
scenario print-character-at-top-left [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
2015-04-30 07:02:54 +00:00
|
|
|
run [
|
2016-09-17 07:31:55 +00:00
|
|
|
a:char <- copy 97/a
|
|
|
|
fake-screen <- print fake-screen, a:char
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
1:@:screen-cell/raw <- copy *cell
|
2015-04-30 07:02:54 +00:00
|
|
|
]
|
2015-05-02 22:52:22 +00:00
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
1 <- 6 # width*height
|
|
|
|
2 <- 97 # 'a'
|
|
|
|
3 <- 7 # white
|
|
|
|
# rest of screen is empty
|
|
|
|
4 <- 0
|
2015-04-30 07:02:54 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2015-11-21 18:19:34 +00:00
|
|
|
scenario print-character-in-color [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
2015-05-27 02:30:27 +00:00
|
|
|
run [
|
2016-09-17 07:31:55 +00:00
|
|
|
a:char <- copy 97/a
|
|
|
|
fake-screen <- print fake-screen, a:char, 1/red
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
1:@:screen-cell/raw <- copy *cell
|
2015-05-27 02:30:27 +00:00
|
|
|
]
|
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
1 <- 6 # width*height
|
|
|
|
2 <- 97 # 'a'
|
|
|
|
3 <- 1 # red
|
|
|
|
# rest of screen is empty
|
|
|
|
4 <- 0
|
2015-05-27 02:30:27 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2015-05-10 15:34:12 +00:00
|
|
|
scenario print-backspace-character [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
|
|
|
a:char <- copy 97/a
|
|
|
|
fake-screen <- print fake-screen, a
|
2015-05-10 15:34:12 +00:00
|
|
|
run [
|
2016-09-17 07:31:55 +00:00
|
|
|
backspace:char <- copy 8/backspace
|
2016-05-26 23:46:38 +00:00
|
|
|
fake-screen <- print fake-screen, backspace
|
2016-09-17 17:28:25 +00:00
|
|
|
10:num/raw <- get *fake-screen, cursor-column:offset
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
11:@:screen-cell/raw <- copy *cell
|
2015-05-10 15:34:12 +00:00
|
|
|
]
|
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
10 <- 0 # cursor column
|
|
|
|
11 <- 6 # width*height
|
|
|
|
12 <- 32 # space, not 'a'
|
|
|
|
13 <- 7 # white
|
|
|
|
# rest of screen is empty
|
|
|
|
14 <- 0
|
2015-05-10 15:34:12 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2015-06-16 22:30:43 +00:00
|
|
|
scenario print-extra-backspace-character [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
|
|
|
a:char <- copy 97/a
|
|
|
|
fake-screen <- print fake-screen, a
|
2015-06-16 22:30:43 +00:00
|
|
|
run [
|
2016-09-17 07:31:55 +00:00
|
|
|
backspace:char <- copy 8/backspace
|
2016-05-26 23:46:38 +00:00
|
|
|
fake-screen <- print fake-screen, backspace
|
2016-09-29 02:48:56 +00:00
|
|
|
fake-screen <- print fake-screen, backspace # cursor already at left margin
|
2016-09-17 17:28:25 +00:00
|
|
|
1:num/raw <- get *fake-screen, cursor-column:offset
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
3:@:screen-cell/raw <- copy *cell
|
2015-06-16 22:30:43 +00:00
|
|
|
]
|
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
1 <- 0 # cursor column
|
|
|
|
3 <- 6 # width*height
|
|
|
|
4 <- 32 # space, not 'a'
|
|
|
|
5 <- 7 # white
|
|
|
|
# rest of screen is empty
|
|
|
|
6 <- 0
|
2015-06-16 22:30:43 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2015-11-21 18:19:34 +00:00
|
|
|
scenario print-character-at-right-margin [
|
2016-09-29 02:48:56 +00:00
|
|
|
# fill top row of screen with text
|
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 2/width, 2/height
|
|
|
|
a:char <- copy 97/a
|
|
|
|
fake-screen <- print fake-screen, a
|
|
|
|
b:char <- copy 98/b
|
|
|
|
fake-screen <- print fake-screen, b
|
2015-06-16 22:30:43 +00:00
|
|
|
run [
|
2016-09-29 02:48:56 +00:00
|
|
|
# cursor now at right margin
|
2016-09-17 07:31:55 +00:00
|
|
|
c:char <- copy 99/c
|
2016-05-26 23:46:38 +00:00
|
|
|
fake-screen <- print fake-screen, c
|
2016-09-17 17:28:25 +00:00
|
|
|
10:num/raw <- get *fake-screen, cursor-column:offset
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
11:@:screen-cell/raw <- copy *cell
|
2015-06-16 22:30:43 +00:00
|
|
|
]
|
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
10 <- 1 # cursor column
|
|
|
|
11 <- 4 # width*height
|
|
|
|
12 <- 97 # 'a'
|
|
|
|
13 <- 7 # white
|
|
|
|
14 <- 99 # 'c' over 'b'
|
|
|
|
15 <- 7 # white
|
|
|
|
# rest of screen is empty
|
|
|
|
16 <- 0
|
2015-06-16 22:30:43 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2015-05-10 15:34:12 +00:00
|
|
|
scenario print-newline-character [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
|
|
|
a:char <- copy 97/a
|
|
|
|
fake-screen <- print fake-screen, a
|
2015-05-10 15:34:12 +00:00
|
|
|
run [
|
2016-09-17 07:31:55 +00:00
|
|
|
newline:char <- copy 10/newline
|
2016-05-26 23:46:38 +00:00
|
|
|
fake-screen <- print fake-screen, newline
|
2016-09-17 17:28:25 +00:00
|
|
|
10:num/raw <- get *fake-screen, cursor-row:offset
|
|
|
|
11:num/raw <- get *fake-screen, cursor-column:offset
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
12:@:screen-cell/raw <- copy *cell
|
2015-05-10 15:34:12 +00:00
|
|
|
]
|
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
10 <- 1 # cursor row
|
|
|
|
11 <- 0 # cursor column
|
|
|
|
12 <- 6 # width*height
|
|
|
|
13 <- 97 # 'a'
|
|
|
|
14 <- 7 # white
|
|
|
|
# rest of screen is empty
|
|
|
|
15 <- 0
|
2015-05-10 15:34:12 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2015-06-16 22:30:43 +00:00
|
|
|
scenario print-newline-at-bottom-line [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
|
|
|
newline:char <- copy 10/newline
|
|
|
|
fake-screen <- print fake-screen, newline
|
|
|
|
fake-screen <- print fake-screen, newline
|
2015-06-16 22:30:43 +00:00
|
|
|
run [
|
2016-09-29 02:48:56 +00:00
|
|
|
# cursor now at bottom of screen
|
2016-05-26 23:46:38 +00:00
|
|
|
fake-screen <- print fake-screen, newline
|
2016-09-17 17:28:25 +00:00
|
|
|
10:num/raw <- get *fake-screen, cursor-row:offset
|
|
|
|
11:num/raw <- get *fake-screen, cursor-column:offset
|
2015-06-16 22:30:43 +00:00
|
|
|
]
|
2016-09-29 02:48:56 +00:00
|
|
|
# doesn't move further down
|
2015-06-16 22:30:43 +00:00
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
10 <- 1 # cursor row
|
|
|
|
11 <- 0 # cursor column
|
2015-06-16 22:30:43 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2015-11-21 18:19:34 +00:00
|
|
|
scenario print-character-at-bottom-right [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 2/width, 2/height
|
|
|
|
newline:char <- copy 10/newline
|
|
|
|
fake-screen <- print fake-screen, newline
|
|
|
|
a:char <- copy 97/a
|
|
|
|
fake-screen <- print fake-screen, a
|
|
|
|
b:char <- copy 98/b
|
|
|
|
fake-screen <- print fake-screen, b
|
|
|
|
c:char <- copy 99/c
|
|
|
|
fake-screen <- print fake-screen, c
|
|
|
|
fake-screen <- print fake-screen, newline
|
2015-06-16 22:30:43 +00:00
|
|
|
run [
|
2016-09-29 02:48:56 +00:00
|
|
|
# cursor now at bottom right
|
2016-09-17 07:31:55 +00:00
|
|
|
d:char <- copy 100/d
|
2016-05-26 23:46:38 +00:00
|
|
|
fake-screen <- print fake-screen, d
|
2016-09-17 17:28:25 +00:00
|
|
|
10:num/raw <- get *fake-screen, cursor-row:offset
|
|
|
|
11:num/raw <- get *fake-screen, cursor-column:offset
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
20:@:screen-cell/raw <- copy *cell
|
2015-06-16 22:30:43 +00:00
|
|
|
]
|
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
10 <- 1 # cursor row
|
|
|
|
11 <- 1 # cursor column
|
2015-12-28 16:44:36 +00:00
|
|
|
20 <- 4 # width*height
|
|
|
|
21 <- 0 # unused
|
|
|
|
22 <- 7 # white
|
|
|
|
23 <- 0 # unused
|
|
|
|
24 <- 7 # white
|
|
|
|
25 <- 97 # 'a'
|
|
|
|
26 <- 7 # white
|
|
|
|
27 <- 100 # 'd' over 'b' and 'c' and newline
|
|
|
|
28 <- 7 # white
|
2016-05-26 23:46:38 +00:00
|
|
|
# rest of screen is empty
|
2015-12-28 16:44:36 +00:00
|
|
|
29 <- 0
|
2015-06-16 22:30:43 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def clear-line screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-09-17 07:31:55 +00:00
|
|
|
space:char <- copy 0/nul
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
break-if screen
|
|
|
|
# real screen
|
|
|
|
clear-line-on-display
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
|
|
|
width:num <- get *screen, num-columns:offset
|
|
|
|
column:num <- get *screen, cursor-column:offset
|
|
|
|
original-column:num <- copy column
|
|
|
|
# space over the entire line
|
|
|
|
{
|
|
|
|
right:num <- subtract width, 1
|
|
|
|
done?:bool <- greater-or-equal column, right
|
|
|
|
break-if done?
|
|
|
|
print screen, space
|
|
|
|
column <- add column, 1
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
# now back to where the cursor was
|
|
|
|
*screen <- put *screen, cursor-column:offset, original-column
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def clear-line-until screen:&:screen, right:num/inclusive -> screen:&:screen [
|
2016-05-20 04:35:34 +00:00
|
|
|
local-scope
|
|
|
|
load-ingredients
|
2016-09-17 17:28:25 +00:00
|
|
|
_, column:num <- cursor-position screen
|
2016-09-17 07:31:55 +00:00
|
|
|
space:char <- copy 32/space
|
2016-09-17 17:32:57 +00:00
|
|
|
bg-color:num, bg-color-found?:bool <- next-ingredient
|
2016-05-20 04:35:34 +00:00
|
|
|
{
|
|
|
|
# default bg-color to black
|
|
|
|
break-if bg-color-found?
|
|
|
|
bg-color <- copy 0/black
|
|
|
|
}
|
|
|
|
{
|
2016-09-17 17:32:57 +00:00
|
|
|
done?:bool <- greater-than column, right
|
2016-05-20 04:35:34 +00:00
|
|
|
break-if done?
|
|
|
|
screen <- print screen, space, 7/white, bg-color # foreground color is mostly unused except if the cursor shows up at this cell
|
|
|
|
column <- add column, 1
|
|
|
|
loop
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def cursor-position screen:&:screen -> row:num, column:num [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
break-if screen
|
|
|
|
# real screen
|
|
|
|
row, column <- cursor-position-on-display
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
|
|
|
row:num <- get *screen, cursor-row:offset
|
|
|
|
column:num <- get *screen, cursor-column:offset
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def move-cursor screen:&:screen, new-row:num, new-column:num -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
break-if screen
|
|
|
|
# real screen
|
|
|
|
move-cursor-on-display new-row, new-column
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
|
|
|
*screen <- put *screen, cursor-row:offset, new-row
|
|
|
|
*screen <- put *screen, cursor-column:offset, new-column
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2015-04-30 17:12:36 +00:00
|
|
|
scenario clear-line-erases-printed-characters [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
|
|
|
# print a character
|
|
|
|
a:char <- copy 97/a
|
|
|
|
fake-screen <- print fake-screen, a
|
|
|
|
# move cursor to start of line
|
|
|
|
fake-screen <- move-cursor fake-screen, 0/row, 0/column
|
2015-04-30 17:12:36 +00:00
|
|
|
run [
|
2016-05-26 23:46:38 +00:00
|
|
|
fake-screen <- clear-line fake-screen
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
10:@:screen-cell/raw <- copy *cell
|
2015-04-30 17:12:36 +00:00
|
|
|
]
|
|
|
|
# screen should be blank
|
2015-05-02 22:52:22 +00:00
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
10 <- 6 # width*height
|
|
|
|
11 <- 0
|
|
|
|
12 <- 7
|
|
|
|
13 <- 0
|
|
|
|
14 <- 7
|
|
|
|
15 <- 0
|
|
|
|
16 <- 7
|
|
|
|
17 <- 0
|
|
|
|
18 <- 7
|
|
|
|
19 <- 0
|
|
|
|
20 <- 7
|
2015-12-28 16:44:36 +00:00
|
|
|
21 <- 0
|
|
|
|
22 <- 7
|
2015-04-30 17:12:36 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def cursor-down screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
break-if screen
|
|
|
|
# real screen
|
|
|
|
move-cursor-down-on-display
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
|
|
|
height:num <- get *screen, num-rows:offset
|
|
|
|
row:num <- get *screen, cursor-row:offset
|
|
|
|
max:num <- subtract height, 1
|
|
|
|
at-bottom?:bool <- greater-or-equal row, max
|
|
|
|
return-if at-bottom?
|
|
|
|
row <- add row, 1
|
|
|
|
*screen <- put *screen, cursor-row:offset, row
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def cursor-up screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
break-if screen
|
|
|
|
# real screen
|
|
|
|
move-cursor-up-on-display
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
|
|
|
row:num <- get *screen, cursor-row:offset
|
|
|
|
at-top?:bool <- lesser-or-equal row, 0
|
|
|
|
return-if at-top?
|
|
|
|
row <- subtract row, 1
|
|
|
|
*screen <- put *screen, cursor-row:offset, row
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def cursor-right screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
break-if screen
|
|
|
|
# real screen
|
|
|
|
move-cursor-right-on-display
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
|
|
|
width:num <- get *screen, num-columns:offset
|
|
|
|
column:num <- get *screen, cursor-column:offset
|
|
|
|
max:num <- subtract width, 1
|
|
|
|
at-bottom?:bool <- greater-or-equal column, max
|
|
|
|
return-if at-bottom?
|
|
|
|
column <- add column, 1
|
|
|
|
*screen <- put *screen, cursor-column:offset, column
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def cursor-left screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-04-29 07:22:20 +00:00
|
|
|
{
|
2016-10-24 04:15:43 +00:00
|
|
|
break-if screen
|
|
|
|
# real screen
|
|
|
|
move-cursor-left-on-display
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-04-29 07:22:20 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
|
|
|
column:num <- get *screen, cursor-column:offset
|
|
|
|
at-top?:bool <- lesser-or-equal column, 0
|
|
|
|
return-if at-top?
|
|
|
|
column <- subtract column, 1
|
|
|
|
*screen <- put *screen, cursor-column:offset, column
|
2015-04-29 07:22:20 +00:00
|
|
|
]
|
2015-05-06 19:13:04 +00:00
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def cursor-to-start-of-line screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-09-17 17:28:25 +00:00
|
|
|
row:num <- cursor-position screen
|
|
|
|
column:num <- copy 0
|
2015-11-19 05:36:36 +00:00
|
|
|
screen <- move-cursor screen, row, column
|
2015-05-06 19:13:04 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def cursor-to-next-line screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-07-29 21:37:57 +00:00
|
|
|
screen <- cursor-down screen
|
|
|
|
screen <- cursor-to-start-of-line screen
|
2015-05-06 19:13:04 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def move-cursor-to-column screen:&:screen, column:num -> screen:&:screen [
|
2016-05-20 04:35:34 +00:00
|
|
|
local-scope
|
|
|
|
load-ingredients
|
2016-09-17 17:28:25 +00:00
|
|
|
row:num, _ <- cursor-position screen
|
2016-05-20 04:35:34 +00:00
|
|
|
move-cursor screen, row, column
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def screen-width screen:&:screen -> width:num [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-06-08 19:25:25 +00:00
|
|
|
{
|
2015-11-19 05:36:36 +00:00
|
|
|
break-unless screen
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
2015-11-19 05:36:36 +00:00
|
|
|
width <- get *screen, num-columns:offset
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-06-08 19:25:25 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# real screen
|
2015-11-19 05:36:36 +00:00
|
|
|
width <- display-width
|
2015-06-08 19:25:25 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def screen-height screen:&:screen -> height:num [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2015-06-08 19:25:25 +00:00
|
|
|
{
|
2015-11-19 05:36:36 +00:00
|
|
|
break-unless screen
|
2016-10-24 04:15:43 +00:00
|
|
|
# fake screen
|
2015-11-19 05:36:36 +00:00
|
|
|
height <- get *screen, num-rows:offset
|
2016-03-08 09:30:14 +00:00
|
|
|
return
|
2015-06-08 19:25:25 +00:00
|
|
|
}
|
2016-10-24 04:15:43 +00:00
|
|
|
# real screen
|
2015-11-19 05:36:36 +00:00
|
|
|
height <- display-height
|
2015-06-08 19:25:25 +00:00
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def hide-cursor screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-10-24 04:15:43 +00:00
|
|
|
reply-if screen # fake screen; do nothing
|
|
|
|
# real screen
|
2015-06-25 16:25:49 +00:00
|
|
|
hide-cursor-on-display
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def show-cursor screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-10-24 04:15:43 +00:00
|
|
|
reply-if screen # fake screen; do nothing
|
|
|
|
# real screen
|
2015-06-25 16:25:49 +00:00
|
|
|
show-cursor-on-display
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def hide-screen screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-10-24 04:15:43 +00:00
|
|
|
reply-if screen # fake screen; do nothing
|
|
|
|
# real screen
|
2015-06-25 16:31:08 +00:00
|
|
|
hide-display
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def show-screen screen:&:screen -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-10-24 04:15:43 +00:00
|
|
|
reply-if screen # fake screen; do nothing
|
|
|
|
# real screen
|
2015-06-25 16:31:08 +00:00
|
|
|
show-display
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def print screen:&:screen, s:text -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-11-19 05:36:36 +00:00
|
|
|
load-ingredients
|
2016-09-17 17:32:57 +00:00
|
|
|
color:num, color-found?:bool <- next-ingredient
|
2015-06-06 17:25:39 +00:00
|
|
|
{
|
|
|
|
# default color to white
|
2015-07-29 21:37:57 +00:00
|
|
|
break-if color-found?
|
|
|
|
color <- copy 7/white
|
2015-06-06 17:25:39 +00:00
|
|
|
}
|
2016-09-17 17:32:57 +00:00
|
|
|
bg-color:num, bg-color-found?:bool <- next-ingredient
|
2015-07-05 03:46:50 +00:00
|
|
|
{
|
2015-07-05 06:08:08 +00:00
|
|
|
# default bg-color to black
|
2015-07-29 21:37:57 +00:00
|
|
|
break-if bg-color-found?
|
|
|
|
bg-color <- copy 0/black
|
2015-07-05 03:46:50 +00:00
|
|
|
}
|
2016-09-17 17:28:25 +00:00
|
|
|
len:num <- length *s
|
|
|
|
i:num <- copy 0
|
2015-05-06 19:13:04 +00:00
|
|
|
{
|
2016-09-17 17:32:57 +00:00
|
|
|
done?:bool <- greater-or-equal i, len
|
2015-07-29 21:37:57 +00:00
|
|
|
break-if done?
|
2016-09-17 07:31:55 +00:00
|
|
|
c:char <- index *s, i
|
2015-11-21 18:19:34 +00:00
|
|
|
print screen, c, color, bg-color
|
2015-07-29 21:37:57 +00:00
|
|
|
i <- add i, 1
|
2015-05-06 19:13:04 +00:00
|
|
|
loop
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
2015-11-21 18:01:12 +00:00
|
|
|
scenario print-text-stops-at-right-margin [
|
2016-09-29 02:48:56 +00:00
|
|
|
local-scope
|
|
|
|
fake-screen:&:screen <- new-fake-screen 3/width, 2/height
|
2015-06-16 21:21:00 +00:00
|
|
|
run [
|
2016-09-29 02:48:56 +00:00
|
|
|
fake-screen <- print fake-screen, [abcd]
|
2016-09-17 20:00:39 +00:00
|
|
|
cell:&:@:screen-cell <- get *fake-screen, data:offset
|
|
|
|
10:@:screen-cell/raw <- copy *cell
|
2015-06-16 21:21:00 +00:00
|
|
|
]
|
|
|
|
memory-should-contain [
|
2016-05-26 23:46:38 +00:00
|
|
|
10 <- 6 # width*height
|
|
|
|
11 <- 97 # 'a'
|
|
|
|
12 <- 7 # white
|
|
|
|
13 <- 98 # 'b'
|
|
|
|
14 <- 7 # white
|
|
|
|
15 <- 100 # 'd' overwrites 'c'
|
|
|
|
16 <- 7 # white
|
|
|
|
# rest of screen is empty
|
|
|
|
17 <- 0
|
2015-06-16 21:21:00 +00:00
|
|
|
]
|
|
|
|
]
|
|
|
|
|
2016-09-17 19:55:10 +00:00
|
|
|
def print-integer screen:&:screen, n:num -> screen:&:screen [
|
2015-07-14 05:43:16 +00:00
|
|
|
local-scope
|
2015-12-28 16:44:36 +00:00
|
|
|
load-ingredients
|
2016-09-17 17:32:57 +00:00
|
|
|
color:num, color-found?:bool <- next-ingredient
|
2015-06-06 17:25:39 +00:00
|
|
|
{
|
|
|
|
# default color to white
|
2015-07-29 21:37:57 +00:00
|
|
|
break-if color-found?
|
|
|
|
color <- copy 7/white
|
2015-06-06 17:25:39 +00:00
|
|
|
}
|
2016-09-17 17:32:57 +00:00
|
|
|
bg-color:num, bg-color-found?:bool <- next-ingredient
|
2015-07-05 03:46:50 +00:00
|
|
|
{
|
2015-07-05 06:08:08 +00:00
|
|
|
# default bg-color to black
|
2015-07-29 21:37:57 +00:00
|
|
|
break-if bg-color-found?
|
|
|
|
bg-color <- copy 0/black
|
2015-07-05 03:46:50 +00:00
|
|
|
}
|
2015-05-06 19:13:04 +00:00
|
|
|
# todo: other bases besides decimal
|
2016-09-12 07:06:40 +00:00
|
|
|
s:text <- to-text n
|
2015-11-21 18:01:12 +00:00
|
|
|
screen <- print screen, s, color, bg-color
|
2015-05-06 19:13:04 +00:00
|
|
|
]
|
2015-12-28 16:44:36 +00:00
|
|
|
|
|
|
|
# for now, we can only print integers
|
2016-09-17 19:55:10 +00:00
|
|
|
def print screen:&:screen, n:num -> screen:&:screen [
|
2015-12-28 16:44:36 +00:00
|
|
|
local-scope
|
|
|
|
load-ingredients
|
2016-09-17 17:32:57 +00:00
|
|
|
color:num, color-found?:bool <- next-ingredient
|
2016-01-21 21:51:50 +00:00
|
|
|
{
|
|
|
|
# default color to white
|
|
|
|
break-if color-found?
|
|
|
|
color <- copy 7/white
|
|
|
|
}
|
2016-09-17 17:32:57 +00:00
|
|
|
bg-color:num, bg-color-found?:bool <- next-ingredient
|
2016-01-21 21:51:50 +00:00
|
|
|
{
|
|
|
|
# default bg-color to black
|
|
|
|
break-if bg-color-found?
|
|
|
|
bg-color <- copy 0/black
|
|
|
|
}
|
|
|
|
screen <- print-integer screen, n, color, bg-color
|
2015-12-28 16:44:36 +00:00
|
|
|
]
|
2016-01-24 03:52:11 +00:00
|
|
|
|
|
|
|
# addresses
|
2016-09-17 19:55:10 +00:00
|
|
|
def print screen:&:screen, n:&:_elem -> screen:&:screen [
|
2016-01-24 03:52:11 +00:00
|
|
|
local-scope
|
|
|
|
load-ingredients
|
2016-09-17 17:32:57 +00:00
|
|
|
color:num, color-found?:bool <- next-ingredient
|
2016-01-24 03:52:11 +00:00
|
|
|
{
|
|
|
|
# default color to white
|
|
|
|
break-if color-found?
|
|
|
|
color <- copy 7/white
|
|
|
|
}
|
2016-09-17 17:32:57 +00:00
|
|
|
bg-color:num, bg-color-found?:bool <- next-ingredient
|
2016-01-24 03:52:11 +00:00
|
|
|
{
|
|
|
|
# default bg-color to black
|
|
|
|
break-if bg-color-found?
|
|
|
|
bg-color <- copy 0/black
|
|
|
|
}
|
2016-09-17 17:28:25 +00:00
|
|
|
n2:num <- copy n
|
2016-01-24 03:52:11 +00:00
|
|
|
screen <- print-integer screen, n2, color, bg-color
|
|
|
|
]
|