https://github.com/akkartik/mu/blob/master/apps/browse.mu
1
2
3
4
5
6
7
8
9 fn main args: (addr array (addr array byte)) -> exit-status/ebx: int {
10 var filename/eax: (addr array byte) <- first-arg args
11 var file/esi: (addr buffered-file) <- load-file filename
12 enable-screen-grid-mode
13 var nrows/eax: int <- copy 0
14 var ncols/ecx: int <- copy 0
15 nrows, ncols <- screen-size
16 enable-keyboard-immediate-mode
17 {
18 render file, nrows, ncols
19 var key/eax: byte <- read-key
20 compare key, 0x71
21 loop-if-!=
22 }
23 enable-keyboard-type-mode
24 enable-screen-type-mode
25 exit-status <- copy 0
26 }
27
28 type render-state {
29 current-state: int
30 }
31
32
33 fn render in: (addr buffered-file), nrows: int, ncols: int {
34
35
36
37
38
39
40
41
42
43 var _r: render-state
44 var r/edi: (addr render-state) <- address _r
45 var toprow/eax: int <- copy 2
46 var botrow/ecx: int <- copy nrows
47 var leftcol/edx: int <- copy 5
48 var rightcol/ebx: int <- copy leftcol
49 rightcol <- add 0x40
50 start-color 0xec, 7
51 {
52 compare rightcol, ncols
53 break-if->=
54 render-page in, toprow, leftcol, botrow, rightcol, r
55 leftcol <- copy rightcol
56 leftcol <- add 5
57 rightcol <- copy leftcol
58 rightcol <- add 0x40
59 loop
60 }
61 }
62
63 fn render-page in: (addr buffered-file), toprow: int, leftcol: int, botrow: int, rightcol: int, r: (addr render-state) {
64 clear toprow, leftcol, botrow, rightcol
65
66 var row/ecx: int <- copy toprow
67 $line-loop: {
68 compare row, botrow
69 break-if->=
70 var col/edx: int <- copy leftcol
71 move-cursor row, col
72 {
73 compare col, rightcol
74 break-if->=
75 var c/eax: byte <- read-byte-buffered in
76 compare c, 0xffffffff
77 break-if-= $line-loop
78 update-attributes c, r
79 compare c, 0xa
80 break-if-=
81 print-byte c
82 col <- increment
83 loop
84 }
85 row <- increment
86 loop
87 }
88 }
89
90 fn update-attributes c: byte, _r: (addr render-state) {
91 var r/edi: (addr render-state) <- copy _r
92 var state/esi: (addr int) <- get r, current-state
93 $update-attributes:check-state: {
94 compare *state, 0
95 {
96 break-if-!=
97 compare c, 0x2a
98 {
99 break-if-!=
100
101 start-bold
102 copy-to *state, 1
103 break $update-attributes:check-state
104 }
105 compare c, 0x5f
106 {
107 break-if-!=
108
109 start-bold
110 copy-to *state, 1
111 break $update-attributes:check-state
112 }
113 break $update-attributes:check-state
114 }
115 {
116 break-if-=
117 compare c, 0x2a
118 {
119 break-if-!=
120
121 reset-formatting
122 copy-to *state, 0
123 break $update-attributes:check-state
124 }
125 compare c, 0x5f
126 {
127 break-if-!=
128
129 reset-formatting
130 copy-to *state, 0
131 break $update-attributes:check-state
132 }
133 break $update-attributes:check-state
134 }
135 }
136 }
137
138 fn clear toprow: int, leftcol: int, botrow: int, rightcol: int {
139 var row/ecx: int <- copy toprow
140 {
141 compare row, botrow
142 break-if->=
143 var col/edx: int <- copy leftcol
144 move-cursor row, col
145 {
146 compare col, rightcol
147 break-if->=
148 print-string " "
149 col <- increment
150 loop
151 }
152 row <- increment
153 loop
154 }
155 }
156
157 fn first-arg args-on-stack: (addr array (addr array byte)) -> out/eax: (addr array byte) {
158 var args/eax: (addr array (addr array byte)) <- copy args-on-stack
159 var result/eax: (addr addr array byte) <- index args, 1
160 out <- copy *result
161 }
162
163 fn load-file filename: (addr array byte) -> out/esi: (addr buffered-file) {
164 var result: (handle buffered-file)
165 {
166 var tmp1/eax: (addr handle buffered-file) <- address result
167 open filename, 0, tmp1
168 }
169 var tmp2/eax: (addr buffered-file) <- lookup result
170 out <- copy tmp2
171 }
172
173 fn dump in: (addr buffered-file) {
174 var c/eax: byte <- read-byte-buffered in
175 compare c, 0xffffffff
176 break-if-=
177 print-byte c
178 loop
179 }