https://github.com/akkartik/mu/blob/master/405screen.mu
  1 # Wrappers for real screen primitives that can be passed in a fake screen.
  2 
  3 type screen {
  4   num-rows: int
  5   num-cols: int
  6   data: (handle array screen-cell)
  7   pending-scroll?: boolean
  8   top-index: int
  9   cursor-row: int
 10   cursor-col: int
 11   cursor-hide?: boolean
 12   curr-attributes: screen-cell
 13 }
 14 
 15 type screen-cell {
 16   color: int
 17   background-color: int
 18   bold?: boolean
 19   underline?: boolean
 20   reverse?: boolean
 21   blink?: boolean
 22 }
 23 
 24 fn initialize-screen screen: (addr screen), nrows: int, ncols: int {
 25   var screen-addr/esi: (addr screen) <- copy screen
 26   var tmp/eax: int <- copy 0
 27   var dest/edi: (addr int) <- copy 0
 28   # screen->num-rows = nrows
 29   dest <- get screen-addr, num-rows
 30   tmp <- copy nrows
 31   copy-to *dest, tmp
 32   # screen->num-cols = ncols
 33   dest <- get screen-addr, num-cols
 34   tmp <- copy ncols
 35   copy-to *dest, tmp
 36   # screen->data = new screen-cell[nrows*ncols]
 37   {
 38     var data-addr/edi: (addr handle array screen-cell) <- get screen-addr, data
 39     tmp <- multiply nrows
 40     populate data-addr, tmp
 41   }
 42   # screen->cursor-row = 1
 43   dest <- get screen-addr, cursor-row
 44   copy-to *dest, 1
 45   # screen->cursor-col = 1
 46   dest <- get screen-addr, cursor-col
 47   copy-to *dest, 1
 48   # screen->curr-attributes->background-color = 7  (simulate light background)
 49   var tmp2/eax: (addr screen-cell) <- get screen-addr, curr-attributes
 50   dest <- get tmp2, background-color
 51   copy-to *dest, 7
 52 }
 53 
 54 fn screen-size screen: (addr screen) -> nrows/eax: int, ncols/ecx: int {
 55 $screen-size:body: {
 56   compare screen, 0
 57   {
 58     break-if-!=
 59     nrows, ncols <- real-screen-size
 60     break $screen-size:body
 61   }
 62   {
 63     break-if-=
 64     # fake screen
 65     var screen-addr/esi: (addr screen) <- copy screen
 66     var tmp/edx: (addr int) <- get screen-addr, num-rows
 67     nrows <- copy *tmp
 68     tmp <- get screen-addr, num-cols
 69     ncols <- copy *tmp
 70   }
 71 }
 72 }
 73 
 74 fn clear-screen screen: (addr screen) {
 75 $clear-screen:body: {
 76   compare screen, 0
 77   {
 78     break-if-!=
 79     clear-real-screen
 80     break $clear-screen:body
 81   }
 82   {
 83     break-if-=
 84     # fake screen
 85     var space/edi: grapheme <- copy 0x20
 86     move-cursor screen, 1, 1
 87     var screen-addr/esi: (addr screen) <- copy screen
 88     var i/eax: int <- copy 1
 89     var nrows/ecx: (addr int) <- get screen-addr, num-rows
 90     {
 91       compare i, *nrows
 92       break-if->
 93       var j/edx: int <- copy 1
 94       var ncols/ebx: (addr int) <- get screen-addr, num-cols
 95       {
 96         compare j, *ncols
 97         break-if->
 98         print-grapheme screen, space
 99         j <- increment
100         loop
101       }
102       i <- increment
103       loop
104     }
105     move-cursor screen, 1, 1
106   }
107 }
108 }
109 
110 fn move-cursor screen: (addr screen), row: int, column: int {
111 $move-cursor:body: {
112   compare screen, 0
113   {
114     break-if-!=
115     move-cursor-on-real-screen row, column
116     break $move-cursor:body
117   }
118   {
119     break-if-=
120     # fake screen
121     var screen-addr/esi: (addr screen) <- copy screen
122     # screen->cursor-row = row
123     var dest/edi: (addr int) <- get screen-addr, cursor-row
124     var src/eax: int <- copy row
125     copy-to *dest, src
126     # screen->cursor-col = column
127     dest <- get screen-addr, cursor-col
128     src <- copy column
129     copy-to *dest, src
130   }
131 }
132 }
133 
134 fn print-string screen: (addr screen), s: (addr array byte) {
135 $print-string:body: {
136   compare screen, 0
137   {
138     break-if-!=
139     print-string-to-real-screen s
140     break $print-string:body
141   }
142   {
143     break-if-=
144     # fake screen
145   }
146 }
147 }
148 
149 fn print-grapheme screen: (addr screen), c: grapheme {
150 $print-grapheme:body: {
151   compare screen, 0
152   {
153     break-if-!=
154     print-grapheme-to-real-screen c
155     break $print-grapheme:body
156   }
157   {
158     break-if-=
159     # fake screen
160   }
161 }
162 }
163 
164 fn print-code-point screen: (addr screen), c: code-point {
165   var g/eax: grapheme <- to-grapheme c
166   print-grapheme screen, g
167 }
168 
169 fn print-int32-hex screen: (addr screen), n: int {
170 $print-int32-hex:body: {
171   compare screen, 0
172   {
173     break-if-!=
174     print-int32-hex-to-real-screen n
175     break $print-int32-hex:body
176   }
177   {
178     break-if-=
179     # fake screen
180   }
181 }
182 }
183 
184 fn reset-formatting screen: (addr screen) {
185 $reset-formatting:body: {
186   compare screen, 0
187   {
188     break-if-!=
189     reset-formatting-on-real-screen
190     break $reset-formatting:body
191   }
192   {
193     break-if-=
194     # fake screen
195   }
196 }
197 }
198 
199 fn start-color screen: (addr screen), fg: int, bg: int {
200 $start-color:body: {
201   compare screen, 0
202   {
203     break-if-!=
204     start-color-on-real-screen fg, bg
205     break $start-color:body
206   }
207   {
208     break-if-=
209     # fake screen
210   }
211 }
212 }
213 
214 fn start-bold screen: (addr screen) {
215 $start-bold:body: {
216   compare screen, 0
217   {
218     break-if-!=
219     start-bold-on-real-screen
220     break $start-bold:body
221   }
222   {
223     break-if-=
224     # fake screen
225   }
226 }
227 }
228 
229 fn start-underline screen: (addr screen) {
230 $start-underline:body: {
231   compare screen, 0
232   {
233     break-if-!=
234     start-underline-on-real-screen
235     break $start-underline:body
236   }
237   {
238     break-if-=
239     # fake screen
240   }
241 }
242 }
243 
244 fn start-reverse-video screen: (addr screen) {
245 $start-reverse-video:body: {
246   compare screen, 0
247   {
248     break-if-!=
249     start-reverse-video-on-real-screen
250     break $start-reverse-video:body
251   }
252   {
253     break-if-=
254     # fake screen
255   }
256 }
257 }
258 
259 fn start-blinking screen: (addr screen) {
260 $start-blinking:body: {
261   compare screen, 0
262   {
263     break-if-!=
264     start-blinking-on-real-screen
265     break $start-blinking:body
266   }
267   {
268     break-if-=
269     # fake screen
270   }
271 }
272 }
273 
274 fn hide-cursor screen: (addr screen) {
275 $hide-cursor:body: {
276   compare screen, 0
277   {
278     break-if-!=
279     hide-cursor-on-real-screen
280     break $hide-cursor:body
281   }
282   {
283     break-if-=
284     # fake screen
285   }
286 }
287 }
288 
289 fn show-cursor screen: (addr screen) {
290 $show-cursor:body: {
291   compare screen, 0
292   {
293     break-if-!=
294     show-cursor-on-real-screen
295     break $show-cursor:body
296   }
297   {
298     break-if-=
299     # fake screen
300   }
301 }
302 }