1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 998check_type_pointers.cc</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="cpp">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
a { text-decoration: none; }
a:hover { text-decoration: underline; }
* { font-size: 12pt; font-size: 1em; }
.Comment { color: #9090ff; }
.LineNr { color: #444444; }
.CommentedCode { color: #6c6c6c; }
-->
</style>
<script type='text/javascript'>
<!--
/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
var lineNum;
lineNum = window.location.hash;
lineNum = lineNum.substr(pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */## the basic editor data structure, and how it displays text to the screen
# temporary main for this layer: just render the given text at the given
# screen dimensions, then stop
def main text:text [
local-scope
load-inputs
open-console
clear-screen null/screen # non-scrolling app
e:&:editor <- new-editor text, 0/left, 5/right
render null/screen, e
wait-for-event null/console
close-console
]
scenario editor-renders-text-to-screen [
local-scope
assume-screen 10/width, 5/height
e:&:editor <- new-editor [abc], 0/left, 10/right
run [
render screen, e
]
screen-should-contain [
# top line of screen reserved for menu
. .
.abc .
. .
]
]
container editor [
# editable text: doubly linked list of characters (head contains a special sentinel)
data:&:duplex-list:char
top-of-screen:&:duplex-list:char
bottom-of-screen:&:duplex-list:char
# location before cursor inside data
before-cursor:&:duplex-list:char
# raw bounds of display area on screen
# always displays from row 1 (leaving row 0 for a menu) and at most until bottom of screen
left:num
right:num
bottom:num
# raw screen coordinates of cursor
cursor-row:num
cursor-column:num
]
# creates a new editor widget
# right is exclusive
def new-editor s:text, left:num, right:num -> result:&:editor [
local-scope
load-inputs
# no clipping of bounds
right <- subtract right, 1
result <- new editor:type
# initialize screen-related fields
*result <- put *result, left:offset, left
*result <- put *result, right:offset, right
# initialize cursor coordinates
*result <- put *result, cursor-row:offset, 1/top
*result <- put *result, cursor-column:offset, left
# initialize empty contents
init:&:duplex-list:char <- push 167/§, null
*result <- put *result, data:offset, init
*result <- put *result, top-of-screen:offset, init
*result <- put *result, before-cursor:offset, init
result <- insert-text result, s
<editor-initialization>
]
def insert-text editor:&:editor, text:text -> editor:&:editor [
local-scope
load-inputs
curr:&:duplex-list:char <- get *editor, data:offset
insert curr, text
]
scenario editor-initializes-without-data [
local-scope
assume-screen 5/width, 3/height
run [
e:&:editor <- new-editor null/data, 2/left, 5/right
1:editor/raw <- copy *e
]
memory-should-contain [
# 1,2 (data) <- just the § sentinel
# 3,4 (top of screen) <- the § sentinel
# 5 (bottom of screen) <- null since text fits on screen
5 <- 0
6 <- 0
# 7,8 (before cursor) <- the § sentinel
9 <- 2 # left
10 <- 4 # right (inclusive)
11 <- 0 # bottom (not set until render)
12 <- 1 # cursor row
13 <- 2 # cursor column
]
screen-should-contain [
. .
. .
. .
]
]
# Assumes cursor should be at coordinates (cursor-row, cursor-column) and
# updates before-cursor to match. Might also move coordinates if they're
# outside text.
def render screen:&:screen, editor:&:editor -> last-row:num, last-column:num, screen:&:screen, editor:&:editor [
local-scope
load-inputs
return-unless editor, 1/top, 0/left
left:num <- get *editor, left:offset
screen-height:num <- screen-height screen
right:num <- get *editor, right:offset
# traversing editor
curr:&:duplex-list:char <- get *editor, top-of-screen:offset
prev:&:duplex-list:char <- copy curr # just in case curr becomes null and we can't compute prev
curr <- next curr
# traversing screen
color:num <- copy 7/white
row:num <- copy 1/top
column:num <- copy left
cursor-row:num <- get *editor, cursor-row:offset
cursor-column:num <- get *editor, cursor-column:offset
before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset
screen <- move-cursor screen, row, column
{
+next-character
break-unless curr
off-screen?:bool <- greater-or-equal row, screen-height
break-if off-screen?
# update editor.before-cursor
# Doing so at the start of each iteration ensures it stays one step behind
# the current character.
{
at-cursor-row?:bool <- equal row, cursor-row
break-unless at-cursor-row?
at-cursor?:bool <- equal column, cursor-column
break-unless at-cursor?
before-cursor <- copy prev
}
c:char <- get *curr, value:offset
<character-c-received>
{
# newline? move to left rather than 0
newline?:bool <- equal c, 10/newline
break-unless newline?
# adjust cursor if necessary
{
at-cursor-row?:bool <- equal row, cursor-row
break-unless at-cursor-row?
left-of-cursor?:bool <- lesser-than column, cursor-column
break-unless left-of-cursor?
cursor-column <- copy column
before-cursor <- prev curr
}
# clear rest of line in this window
clear-line-until screen, right
# skip to next line
row <- add row, 1
column <- copy left
screen <- move-cursor screen, row, column
curr <- next curr
prev <- next prev
loop +next-character
}
{
# at right? wrap. even if there's only one more letter left; we need
# room for clicking on the cursor after it.
at-right?:bool <- equal column, right
break-unless at-right?
# print wrap icon
wrap-icon:char <- copy 8617/loop-back-to-left
print screen, wrap-icon, 245/grey
column <- copy left
row <- add row, 1
screen <- move-cursor screen, row, column
# don't increment curr
loop +next-character
}
print screen, c, color
curr <- next curr
prev <- next prev
column <- add column, 1
loop
}
# save first character off-screen
*editor <- put *editor, bottom-of-screen:offset, curr
# is cursor to the right of the last line? move to end
{
at-cursor-row?:bool <- equal row, cursor-row
cursor-outside-line?:bool <- lesser-or-equal column, cursor-column
before-cursor-on-same-line?:bool <- and at-cursor-row?, cursor-outside-line?
above-cursor-row?:bool <- lesser-than row, cursor-row
before-cursor?:bool <- or before-cursor-on-same-line?, above-cursor-row?
break-unless before-cursor?
cursor-row <- copy row
cursor-column <- copy column
before-cursor <- copy prev
}
*editor <- put *editor, bottom:offset, row
*editor <- put *editor, cursor-row:offset, cursor-row
*editor <- put *editor, cursor-column:offset, cursor-column
*editor <- put *editor, before-cursor:offset, before-cursor
clear-line-until screen, right
row <- add row, 1
return row, left/column
]
def clear-screen-from screen:&:screen, row:num, column:num, left:num, right:num -> screen:&:screen [
local-scope
load-inputs
# if it's the real screen, use the optimized primitive
{
break-if screen
clear-display-from row, column, left, right
return
}
# if not, go the slower route
screen <- move-cursor screen, row, column
clear-line-until screen, right
clear-rest-of-screen screen, row, left, right
]
def clear-rest-of-screen screen:&:screen, row:num, left:num, right:num -> screen:&:screen [
local-scope
load-inputs
row <- add row, 1
# if it's the real screen, use the optimized primitive
{
break-if screen
clear-display-from row, left, left, right
return
}
screen <- move-cursor screen, row, left
screen-height:num <- screen-height screen
{
at-bottom-of-screen?:bool <- greater-or-equal row, screen-height
break-if at-bottom-of-screen?
screen <- move-cursor screen, row, left
clear-line-until screen, right
row <- add row, 1
loop
}
]
scenario editor-prints-multiple-lines [
local-scope
assume-screen 5/width, 5/height
s:text <- new [abc
def]
e:&:editor <- new-editor s, 0/left, 5/right
run [
render screen, e
]
screen-should-contain [
. .
.abc .
.def .
. .
]
]
scenario editor-handles-offsets [
local-scope
assume-screen 5/width, 5/height
e:&:editor <- new-editor [abc], 1/left, 5/right
run [
render screen, e
]
screen-should-contain [
. .
. abc .
. .
]
]
scenario editor-prints-multiple-lines-at-offset [
local-scope
assume-screen 5/width, 5/height
s:text <- new [abc
def]
e:&:editor <- new-editor s, 1/left, 5/right
run [
render screen, e
]
screen-should-contain [
. .
. abc .
. def .
. .
]
]
scenario editor-wraps-long-lines [
local-scope
assume-screen 5/width, 5/height
e:&:editor <- new-editor [abc def], 0/left, 5/right
run [
render screen, e
]
screen-should-contain [
. .
.abc ↩.
.def .
. .
]
screen-should-contain-in-color 245/grey [
. .
. ↩.
. .
. .
]
]
scenario editor-wraps-barely-long-lines [
local-scope
assume-screen 5/width, 5/height
e:&:editor <- new-editor [abcde], 0/left, 5/right
run [
render screen, e
]
# still wrap, even though the line would fit. We need room to click on the
# end of the line
screen-should-contain [
. .
.abcd↩.
.e .
. .
]
screen-should-contain-in-color 245/grey [
. .
. ↩.
. .
. .
]
]
scenario editor-with-empty-text [
local-scope
assume-screen 5/width, 5/height
e:&:editor <- new-editor [], 0/left, 5/right
run [
render screen, e
3:num/raw <- get *e, cursor-row:offset
4:num/raw <- get *e, cursor-column:offset
]
screen-should-contain [
. .
. .
. .
]
memory-should-contain [
3 <- 1 # cursor row
4 <- 0 # cursor column
]
]
# just a little color for Mu code
scenario render-colors-comments [
local-scope
assume-screen 5/width, 5/height
s:text <- new [abc
# de
f]
e:&:editor <- new-editor s, 0/left, 5/right
run [
render screen, e
]
screen-should-contain [
. .
.abc .
.# de .
.f .
. .
]
screen-should-contain-in-color 12/lightblue, [
. .
. .
.# de .
. .
. .
]
screen-should-contain-in-color 7/white, [
. .
.abc .
. .
.f .
. .
]
]
after <character-c-received> [
color <- get-color color, c
]
# so far the previous color is all the information we need; that may change
def get-color color:num, c:char -> color:num [
local-scope
load-inputs
color-is-white?:bool <- equal color, 7/white
# if color is white and next character is '#', switch color to blue
{
break-unless color-is-white?
starting-comment?:bool <- equal c, 35/#
break-unless starting-comment?
trace 90, [app], [switch color back to blue]
return 12/lightblue
}
# if color is blue and next character is newline, switch color to white
{
color-is-blue?:bool <- equal color, 12/lightblue
break-unless color-is-blue?
ending-comment?:bool <- equal c, 10/newline
break-unless ending-comment?
trace 90, [app], [switch color back to white]
return 7/white
}
# if color is white (no comments) and next character is '<', switch color to red
{
break-unless color-is-white?
starting-assignment?:bool <- equal c, 60/<
break-unless starting-assignment?
return 1/red
}
# if color is red and next character is space, switch color to white
{
color-is-red?:bool <- equal color, 1/red
break-unless color-is-red?
ending-assignment?:bool <- equal c, 32/space
break-unless ending-assignment?
return 7/white
}
# otherwise no change
return color
]
scenario render-colors-assignment [
local-scope
assume-screen 8/width, 5/height
s:text <- new [abc
d <- e
f]
e:&:editor <- new-editor s, 0/left, 8/right
run [
render screen, e
]
screen-should-contain [
. .
.abc .
.d <- e .
.f .
. .
]
screen-should-contain-in-color 1/red, [
. .
. .
. <- .
. .
. .
]
]
|