https://github.com/akkartik/mu/blob/main/browse-slack/environment.mu
1 type environment {
2 search-terms: (handle gap-buffer)
3 tabs: (handle array tab)
4 current-tab-index: int
5 dirty?: boolean
6
7 cursor-in-search?: boolean
8
9 cursor-in-channels?: boolean
10 channel-cursor-index: int
11 }
12
13 type tab {
14 type: int
15
16
17
18
19 item-index: int
20
21
22 channel-index: int
23
24 search-terms: (handle gap-buffer)
25 search-items: (handle array int)
26 search-items-first-free: int
27
28 root-index: int
29 }
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 fn initialize-environment _self: (addr environment), _items: (addr item-list) {
47 var self/esi: (addr environment) <- copy _self
48 var search-terms-ah/eax: (addr handle gap-buffer) <- get self, search-terms
49 allocate search-terms-ah
50 var search-terms/eax: (addr gap-buffer) <- lookup *search-terms-ah
51 initialize-gap-buffer search-terms, 0x30/search-capacity
52 var items/eax: (addr item-list) <- copy _items
53 var items-data-first-free-a/eax: (addr int) <- get items, data-first-free
54 var final-item/edx: int <- copy *items-data-first-free-a
55 final-item <- decrement
56 var tabs-ah/ecx: (addr handle array tab) <- get self, tabs
57 populate tabs-ah, 0x10/max-history
58
59 var tabs/eax: (addr array tab) <- lookup *tabs-ah
60 var first-tab/eax: (addr tab) <- index tabs, 0/current-tab-index
61 var dest/edi: (addr int) <- get first-tab, item-index
62 copy-to *dest, final-item
63 }
64
65
66
67 fn render-environment screen: (addr screen), _env: (addr environment), users: (addr array user), channels: (addr array channel), items: (addr item-list) {
68 var env/esi: (addr environment) <- copy _env
69 {
70 var dirty?/eax: (addr boolean) <- get env, dirty?
71 compare *dirty?, 0/false
72 break-if-!=
73
74 {
75 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
76 compare *cursor-in-search?, 0/false
77 break-if-=
78 render-search-input screen, env
79 clear-rect screen, 0/x 0x2f/y, 0x80/x 0x30/y, 0/bg
80 render-search-menu screen, env
81 return
82 }
83
84 {
85 var cursor-in-channels?/eax: (addr boolean) <- get env, cursor-in-channels?
86 compare *cursor-in-channels?, 0/false
87 break-if-=
88 render-channels screen, env, channels
89 clear-rect screen, 0/x 0x2f/y, 0x80/x 0x30/y, 0/bg
90 render-channels-menu screen, env
91 return
92 }
93 }
94
95 clear-screen screen
96 render-search-input screen, env
97 render-channels screen, env, channels
98 render-item-list screen, env, items, channels, users
99 render-menu screen, env
100 var dirty?/eax: (addr boolean) <- get env, dirty?
101 copy-to *dirty?, 0/false
102 }
103
104 fn render-channels screen: (addr screen), _env: (addr environment), _channels: (addr array channel) {
105 var env/esi: (addr environment) <- copy _env
106 var cursor-index/edi: int <- copy -1
107 {
108 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
109 compare *cursor-in-search?, 0/false
110 break-if-!=
111 var cursor-in-channels?/eax: (addr boolean) <- get env, cursor-in-channels?
112 compare *cursor-in-channels?, 0/false
113 break-if-=
114 var cursor-index-addr/eax: (addr int) <- get env, channel-cursor-index
115 cursor-index <- copy *cursor-index-addr
116 }
117 var channels/esi: (addr array channel) <- copy _channels
118 var y/ebx: int <- copy 2/search-space-ver
119 y <- add 1/item-padding-ver
120 var i/ecx: int <- copy 0
121 var max/edx: int <- length channels
122 {
123 compare i, max
124 break-if->=
125 var offset/eax: (offset channel) <- compute-offset channels, i
126 var curr/eax: (addr channel) <- index channels, offset
127 var name-ah/eax: (addr handle array byte) <- get curr, name
128 var name/eax: (addr array byte) <- lookup *name-ah
129 compare name, 0
130 break-if-=
131 set-cursor-position screen, 2/x y
132 {
133 compare cursor-index, i
134 break-if-=
135 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "#", 7/grey 0/black
136 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, name, 7/grey 0/black
137 }
138 {
139 compare cursor-index, i
140 break-if-!=
141
142 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "#", 0/black 0xf/white
143 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, name, 0/black 0xf/white
144 }
145 y <- add 2/channel-padding
146 i <- increment
147 loop
148 }
149 }
150
151 fn render-item-list screen: (addr screen), _env: (addr environment), items: (addr item-list), channels: (addr array channel), users: (addr array user) {
152 var env/esi: (addr environment) <- copy _env
153 var tmp-width/eax: int <- copy 0
154 var tmp-height/ecx: int <- copy 0
155 tmp-width, tmp-height <- screen-size screen
156 var screen-width: int
157 copy-to screen-width, tmp-width
158 var screen-height: int
159 copy-to screen-height, tmp-height
160
161 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
162 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
163 var tabs/edx: (addr array tab) <- copy _tabs
164 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
165 var current-tab-index/eax: int <- copy *current-tab-index-a
166 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
167 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
168 var show-cursor?: boolean
169 {
170 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
171 compare *cursor-in-search?, 0/false
172 break-if-!=
173 var cursor-in-channels?/eax: (addr boolean) <- get env, cursor-in-channels?
174 compare *cursor-in-channels?, 0/false
175 break-if-!=
176 copy-to show-cursor?, 1/true
177 }
178 render-tab screen, current-tab, show-cursor?, items, channels, users, screen-height
179 var top/eax: int <- copy screen-height
180 top <- subtract 2/menu-space-ver
181 clear-rect screen, 0 top, screen-width screen-height, 0/bg
182 }
183
184 fn render-tab screen: (addr screen), _current-tab: (addr tab), show-cursor?: boolean, items: (addr item-list), channels: (addr array channel), users: (addr array user), screen-height: int {
185 var current-tab/esi: (addr tab) <- copy _current-tab
186 var current-tab-type/eax: (addr int) <- get current-tab, type
187 compare *current-tab-type, 0/all-items
188 {
189 break-if-!=
190 render-all-items screen, current-tab, show-cursor?, items, users, screen-height
191 return
192 }
193 compare *current-tab-type, 1/channel
194 {
195 break-if-!=
196 render-channel-tab screen, current-tab, show-cursor?, items, channels, users, screen-height
197 return
198 }
199 compare *current-tab-type, 2/search
200 {
201 break-if-!=
202 render-search-tab screen, current-tab, show-cursor?, items, channels, users, screen-height
203 return
204 }
205 compare *current-tab-type, 3/thread
206 {
207 break-if-!=
208 render-thread-tab screen, current-tab, show-cursor?, items, channels, users, screen-height
209 return
210 }
211 }
212
213 fn render-all-items screen: (addr screen), _current-tab: (addr tab), show-cursor?: boolean, _items: (addr item-list), users: (addr array user), screen-height: int {
214 var current-tab/esi: (addr tab) <- copy _current-tab
215 var items/edi: (addr item-list) <- copy _items
216 var newest-item/eax: (addr int) <- get current-tab, item-index
217 var i/ebx: int <- copy *newest-item
218 var items-data-first-free-addr/eax: (addr int) <- get items, data-first-free
219 render-progress screen, i, *items-data-first-free-addr
220 var items-data-ah/eax: (addr handle array item) <- get items, data
221 var _items-data/eax: (addr array item) <- lookup *items-data-ah
222 var items-data/edi: (addr array item) <- copy _items-data
223 var y/ecx: int <- copy 2/search-space-ver
224 y <- add 1/item-padding-ver
225 {
226 compare i, 0
227 break-if-<
228 compare y, screen-height
229 break-if->=
230 var offset/eax: (offset item) <- compute-offset items-data, i
231 var curr-item/eax: (addr item) <- index items-data, offset
232 y <- render-item screen, curr-item, users, show-cursor?, y, screen-height
233
234 copy-to show-cursor?, 0/false
235 i <- decrement
236 loop
237 }
238 }
239
240 fn render-channel-tab screen: (addr screen), _current-tab: (addr tab), show-cursor?: boolean, _items: (addr item-list), _channels: (addr array channel), users: (addr array user), screen-height: int {
241 var current-tab/esi: (addr tab) <- copy _current-tab
242 var items/edi: (addr item-list) <- copy _items
243 var channels/ebx: (addr array channel) <- copy _channels
244 var channel-index-addr/eax: (addr int) <- get current-tab, channel-index
245 var channel-index/eax: int <- copy *channel-index-addr
246 var channel-offset/eax: (offset channel) <- compute-offset channels, channel-index
247 var current-channel/ecx: (addr channel) <- index channels, channel-offset
248 var current-channel-posts-ah/eax: (addr handle array int) <- get current-channel, posts
249 var _current-channel-posts/eax: (addr array int) <- lookup *current-channel-posts-ah
250 var current-channel-posts/edx: (addr array int) <- copy _current-channel-posts
251 var current-channel-first-channel-item-addr/eax: (addr int) <- get current-tab, item-index
252 var i/ebx: int <- copy *current-channel-first-channel-item-addr
253 var current-channel-posts-first-free-addr/eax: (addr int) <- get current-channel, posts-first-free
254 set-cursor-position 0/screen, 0x68/x 0/y
255 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "channel", 7/fg 0/bg
256 render-progress screen, i, *current-channel-posts-first-free-addr
257 var items-data-ah/eax: (addr handle array item) <- get items, data
258 var _items-data/eax: (addr array item) <- lookup *items-data-ah
259 var items-data/edi: (addr array item) <- copy _items-data
260 var y/ecx: int <- copy 2/search-space-ver
261 y <- add 1/item-padding-ver
262 {
263 compare i, 0
264 break-if-<
265 compare y, screen-height
266 break-if->=
267 var item-index-addr/eax: (addr int) <- index current-channel-posts, i
268 var item-index/eax: int <- copy *item-index-addr
269 var item-offset/eax: (offset item) <- compute-offset items-data, item-index
270 var curr-item/eax: (addr item) <- index items-data, item-offset
271 y <- render-item screen, curr-item, users, show-cursor?, y, screen-height
272
273 copy-to show-cursor?, 0/false
274 i <- decrement
275 loop
276 }
277 }
278
279 fn render-search-tab screen: (addr screen), _current-tab: (addr tab), show-cursor?: boolean, _items: (addr item-list), channels: (addr array channel), users: (addr array user), screen-height: int {
280 var current-tab/esi: (addr tab) <- copy _current-tab
281 var items/edi: (addr item-list) <- copy _items
282 var current-tab-search-items-ah/eax: (addr handle array int) <- get current-tab, search-items
283 var _current-tab-search-items/eax: (addr array int) <- lookup *current-tab-search-items-ah
284 var current-tab-search-items/ebx: (addr array int) <- copy _current-tab-search-items
285 var current-tab-top-item-addr/eax: (addr int) <- get current-tab, item-index
286 var i/edx: int <- copy *current-tab-top-item-addr
287 var current-tab-search-items-first-free-addr/eax: (addr int) <- get current-tab, search-items-first-free
288 set-cursor-position 0/screen, 0x68/x 0/y
289 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "search", 7/fg 0/bg
290 render-progress screen, i, *current-tab-search-items-first-free-addr
291 {
292 compare *current-tab-search-items-first-free-addr, 0x100/max-search-results
293 break-if-<
294 set-cursor-position 0/screen, 0x68/x 1/y
295 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "too many results", 4/fg 0/bg
296 }
297 var items-data-ah/eax: (addr handle array item) <- get items, data
298 var _items-data/eax: (addr array item) <- lookup *items-data-ah
299 var items-data/edi: (addr array item) <- copy _items-data
300 var y/ecx: int <- copy 2/search-space-ver
301 y <- add 1/item-padding-ver
302 {
303 compare i, 0
304 break-if-<
305 compare y, screen-height
306 break-if->=
307 var item-index-addr/eax: (addr int) <- index current-tab-search-items, i
308 var item-index/eax: int <- copy *item-index-addr
309 var item-offset/eax: (offset item) <- compute-offset items-data, item-index
310 var curr-item/eax: (addr item) <- index items-data, item-offset
311 y <- render-item screen, curr-item, users, show-cursor?, y, screen-height
312
313 copy-to show-cursor?, 0/false
314 i <- decrement
315 loop
316 }
317 }
318
319 fn render-thread-tab screen: (addr screen), _current-tab: (addr tab), show-cursor?: boolean, _items: (addr item-list), channels: (addr array channel), users: (addr array user), screen-height: int {
320 var current-tab/esi: (addr tab) <- copy _current-tab
321 var items/eax: (addr item-list) <- copy _items
322 var items-data-ah/eax: (addr handle array item) <- get items, data
323 var _items-data/eax: (addr array item) <- lookup *items-data-ah
324 var items-data/edi: (addr array item) <- copy _items-data
325 var post-index-addr/eax: (addr int) <- get current-tab, root-index
326 var post-index/eax: int <- copy *post-index-addr
327 var post-offset/eax: (offset item) <- compute-offset items-data, post-index
328 var post/ebx: (addr item) <- index items-data, post-offset
329 var current-tab-top-item-addr/eax: (addr int) <- get current-tab, item-index
330 var i/edx: int <- copy *current-tab-top-item-addr
331 var post-comments-first-free-addr/eax: (addr int) <- get post, comments-first-free
332 set-cursor-position 0/screen, 0x68/x 0/y
333 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "thread", 7/fg 0/bg
334 render-progress screen, i, *post-comments-first-free-addr
335 var post-comments-ah/eax: (addr handle array int) <- get post, comments
336 var post-comments/eax: (addr array int) <- lookup *post-comments-ah
337 var y/ecx: int <- copy 2/search-space-ver
338 y <- add 1/item-padding-ver
339 {
340 compare i, 0
341 break-if-<
342 compare y, screen-height
343 break-if->=
344 var item-index-addr/eax: (addr int) <- index post-comments, i
345 var item-index/eax: int <- copy *item-index-addr
346 var item-offset/eax: (offset item) <- compute-offset items-data, item-index
347 var curr-item/eax: (addr item) <- index items-data, item-offset
348 y <- render-item screen, curr-item, users, show-cursor?, y, screen-height
349
350 copy-to show-cursor?, 0/false
351 i <- decrement
352 loop
353 }
354
355 y <- render-item screen, post, users, 0/no-cursor, y, screen-height
356 }
357
358
359 fn render-progress screen: (addr screen), curr: int, max: int {
360 set-cursor-position 0/screen, 0x70/x 0/y
361 var top-index/eax: int <- copy max
362 top-index <- subtract curr
363 draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, top-index, 7/fg 0/bg
364 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "/", 7/fg 0/bg
365 draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen screen, max, 7/fg 0/bg
366 }
367
368 fn render-search-input screen: (addr screen), _env: (addr environment) {
369 var env/esi: (addr environment) <- copy _env
370 var cursor-in-search?/ecx: (addr boolean) <- get env, cursor-in-search?
371 set-cursor-position 0/screen, 0x22/x=search-position-x 1/y
372 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "search ", 7/fg 0/bg
373 var search-terms-ah/eax: (addr handle gap-buffer) <- get env, search-terms
374 var search-terms/eax: (addr gap-buffer) <- lookup *search-terms-ah
375 rewind-gap-buffer search-terms
376 var x/eax: int <- render-gap-buffer screen, search-terms, 0x2a/x 1/y, *cursor-in-search?, 0xf/fg 0/bg
377 {
378 compare x, 0x4a/end-search
379 break-if->
380 var y/ecx: int <- copy 0
381 x, y <- render-code-point screen, 0x5f/underscore, 0/xmin 1/ymin, 0x80/xmax, 1/ymax, x, 1/y, 0xf/fg 0/bg
382 loop
383 }
384 }
385
386
387 fn render-menu screen: (addr screen), _env: (addr environment) {
388 var env/edi: (addr environment) <- copy _env
389 {
390 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
391 compare *cursor-in-search?, 0/false
392 break-if-=
393 render-search-menu screen, env
394 return
395 }
396 var cursor-in-channels?/eax: (addr boolean) <- get env, cursor-in-channels?
397 compare *cursor-in-channels?, 0/false
398 {
399 break-if-=
400 render-channels-menu screen, env
401 return
402 }
403 render-main-menu screen, env
404 }
405
406 fn render-main-menu screen: (addr screen), _env: (addr environment) {
407 var width/eax: int <- copy 0
408 var y/ecx: int <- copy 0
409 width, y <- screen-size screen
410 y <- decrement
411 set-cursor-position screen, 2/x, y
412 {
413 var env/edi: (addr environment) <- copy _env
414 var num-tabs/edi: (addr int) <- get env, current-tab-index
415 compare *num-tabs, 0
416 break-if-<=
417 draw-text-rightward-from-cursor screen, " Esc ", width, 0/fg 0xf/bg
418 draw-text-rightward-from-cursor screen, " go back ", width, 0xf/fg, 0/bg
419 }
420 draw-text-rightward-from-cursor screen, " Enter ", width, 0/fg 0xf/bg
421 draw-text-rightward-from-cursor screen, " go to thread ", width, 0xf/fg, 0/bg
422 draw-text-rightward-from-cursor screen, " / ", width, 0/fg 0xf/bg
423 draw-text-rightward-from-cursor screen, " search ", width, 0xf/fg, 0/bg
424 draw-text-rightward-from-cursor screen, " Tab ", width, 0/fg 0xf/bg
425 draw-text-rightward-from-cursor screen, " go to channels ", width, 0xf/fg, 0/bg
426 draw-text-rightward-from-cursor screen, " ^b ", width, 0/fg 0xf/bg
427 draw-text-rightward-from-cursor screen, " << page ", width, 0xf/fg, 0/bg
428 draw-text-rightward-from-cursor screen, " ^f ", width, 0/fg 0xf/bg
429 draw-text-rightward-from-cursor screen, " page >> ", width, 0xf/fg, 0/bg
430 }
431
432 fn render-channels-menu screen: (addr screen), _env: (addr environment) {
433 var width/eax: int <- copy 0
434 var y/ecx: int <- copy 0
435 width, y <- screen-size screen
436 y <- decrement
437 set-cursor-position screen, 2/x, y
438 {
439 var env/edi: (addr environment) <- copy _env
440 var num-tabs/edi: (addr int) <- get env, current-tab-index
441 compare *num-tabs, 0
442 break-if-<=
443 draw-text-rightward-from-cursor screen, " Esc ", width, 0/fg 0xf/bg
444 draw-text-rightward-from-cursor screen, " go back ", width, 0xf/fg, 0/bg
445 }
446 draw-text-rightward-from-cursor screen, " / ", width, 0/fg 0xf/bg
447 draw-text-rightward-from-cursor screen, " search ", width, 0xf/fg, 0/bg
448 draw-text-rightward-from-cursor screen, " Tab ", width, 0/fg 0xf/bg
449 draw-text-rightward-from-cursor screen, " go to items ", width, 0xf/fg, 0/bg
450 draw-text-rightward-from-cursor screen, " Enter ", width, 0/fg 0xf/bg
451 draw-text-rightward-from-cursor screen, " select ", width, 0xf/fg, 0/bg
452 }
453
454 fn render-search-menu screen: (addr screen), _env: (addr environment) {
455 var width/eax: int <- copy 0
456 var y/ecx: int <- copy 0
457 width, y <- screen-size screen
458 y <- decrement
459 set-cursor-position screen, 2/x, y
460 draw-text-rightward-from-cursor screen, " Esc ", width, 0/fg 0xf/bg
461 draw-text-rightward-from-cursor screen, " cancel ", width, 0xf/fg, 0/bg
462 draw-text-rightward-from-cursor screen, " Enter ", width, 0/fg 0xf/bg
463 draw-text-rightward-from-cursor screen, " select ", width, 0xf/fg, 0/bg
464 draw-text-rightward-from-cursor screen, " ^a ", width, 0/fg, 0xf/bg
465 draw-text-rightward-from-cursor screen, " << ", width, 0xf/fg, 0/bg
466 draw-text-rightward-from-cursor screen, " ^b ", width, 0/fg, 0xf/bg
467 draw-text-rightward-from-cursor screen, " <word ", width, 0xf/fg, 0/bg
468 draw-text-rightward-from-cursor screen, " ^f ", width, 0/fg, 0xf/bg
469 draw-text-rightward-from-cursor screen, " word> ", width, 0xf/fg, 0/bg
470 draw-text-rightward-from-cursor screen, " ^e ", width, 0/fg, 0xf/bg
471 draw-text-rightward-from-cursor screen, " >> ", width, 0xf/fg, 0/bg
472 draw-text-rightward-from-cursor screen, " ^u ", width, 0/fg, 0xf/bg
473 draw-text-rightward-from-cursor screen, " clear ", width, 0xf/fg, 0/bg
474 }
475
476 fn render-item screen: (addr screen), _item: (addr item), _users: (addr array user), show-cursor?: boolean, y: int, screen-height: int -> _/ecx: int {
477 var item/esi: (addr item) <- copy _item
478 var users/edi: (addr array user) <- copy _users
479 var author-index-addr/ecx: (addr int) <- get item, by
480 var author-index/ecx: int <- copy *author-index-addr
481 var author-offset/ecx: (offset user) <- compute-offset users, author-index
482 var author/ecx: (addr user) <- index users, author-offset
483
484 var author-avatar-ah/eax: (addr handle image) <- get author, avatar
485 var _author-avatar/eax: (addr image) <- lookup *author-avatar-ah
486 var author-avatar/ebx: (addr image) <- copy _author-avatar
487 {
488 compare author-avatar, 0
489 break-if-=
490 var y/edx: int <- copy y
491 y <- shift-left 4/log2font-height
492 var x/eax: int <- copy 0x20/main-panel-hor
493 x <- shift-left 3/log2font-width
494 x <- add 0x18/item-padding-hor
495 render-image screen, author-avatar, x, y, 0x50/avatar-side, 0x50/avatar-side
496 }
497
498 var channel-name-ah/eax: (addr handle array byte) <- get item, channel
499 var channel-name/eax: (addr array byte) <- lookup *channel-name-ah
500 {
501 var x/eax: int <- copy 0x20/main-panel-hor
502 x <- add 0x40/channel-offset-x
503 set-cursor-position screen, x y
504 }
505 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, "#", 7/grey 0/black
506 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, channel-name, 7/grey 0/black
507
508 {
509 var author-real-name-ah/eax: (addr handle array byte) <- get author, real-name
510 var author-real-name/eax: (addr array byte) <- lookup *author-real-name-ah
511 var x/ecx: int <- copy 0x20/main-panel-hor
512 x <- add 0x10/avatar-space-hor
513 set-cursor-position screen, x y
514 draw-text-wrapping-right-then-down-from-cursor-over-full-screen screen, author-real-name, 0xf/white 0/black
515 }
516 increment y
517
518 var text-ah/eax: (addr handle array byte) <- get item, text
519 var _text/eax: (addr array byte) <- lookup *text-ah
520 var text/edx: (addr array byte) <- copy _text
521 var text-y/eax: int <- render-slack-message screen, text, show-cursor?, y, screen-height
522
523 add-to y, 6/avatar-space-ver
524 compare y, text-y
525 {
526 break-if-<
527 return y
528 }
529 return text-y
530 }
531
532 fn render-slack-message screen: (addr screen), text: (addr array byte), highlight?: boolean, ymin: int, ymax: int -> _/eax: int {
533 var x/eax: int <- copy 0x20/main-panel-hor
534 x <- add 0x10/avatar-space-hor
535 var y/ecx: int <- copy ymin
536 y <- add 1/author-name-padding-ver
537 $render-slack-message:draw: {
538 compare highlight?, 0/false
539 {
540 break-if-=
541 x, y <- draw-json-text-wrapping-right-then-down screen, text, x y, 0x70/xmax=post-right-coord ymax, x y, 0/fg 7/bg
542 break $render-slack-message:draw
543 }
544 x, y <- draw-json-text-wrapping-right-then-down screen, text, x y, 0x70/xmax=post-right-coord ymax, x y, 7/fg 0/bg
545 }
546 y <- add 2/item-padding-ver
547 return y
548 }
549
550
551
552
553
554 fn draw-json-text-wrapping-right-then-down screen: (addr screen), _text: (addr array byte), xmin: int, ymin: int, xmax: int, ymax: int, _x: int, _y: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
555 var stream-storage: (stream byte 0x4000/print-buffer-size)
556 var stream/edi: (addr stream byte) <- address stream-storage
557 var text/esi: (addr array byte) <- copy _text
558 var len/eax: int <- length text
559 compare len, 0x4000/print-buffer-size
560 {
561 break-if-<
562 write stream, "ERROR: stream too small in draw-text-wrapping-right-then-down"
563 }
564 compare len, 0x4000/print-buffer-size
565 {
566 break-if->=
567 write stream, text
568 }
569 var x/eax: int <- copy _x
570 var y/ecx: int <- copy _y
571 x, y <- draw-json-stream-wrapping-right-then-down screen, stream, xmin, ymin, xmax, ymax, x, y, color, background-color
572 return x, y
573 }
574
575
576
577
578
579 fn draw-json-stream-wrapping-right-then-down screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, x: int, y: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
580 var xcurr/eax: int <- copy x
581 var ycurr/ecx: int <- copy y
582 {
583 var c/ebx: code-point <- read-json-code-point stream
584 compare c, 0xffffffff/end-of-file
585 break-if-=
586 $draw-json-stream-wrapping-right-then-down:render-grapheme: {
587 compare c, 0x5c/backslash
588 {
589 break-if-!=
590 xcurr, ycurr <- render-json-escaped-code-point screen, stream, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
591 break $draw-json-stream-wrapping-right-then-down:render-grapheme
592 }
593 xcurr, ycurr <- render-code-point screen, c, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
594 }
595 loop
596 }
597 set-cursor-position screen, xcurr, ycurr
598 return xcurr, ycurr
599 }
600
601
602 fn read-json-code-point stream: (addr stream byte) -> _/ebx: code-point {
603 var g/eax: grapheme <- read-grapheme stream
604 var result/eax: code-point <- to-code-point g
605 return result
606 }
607
608
609
610 fn render-json-escaped-code-point screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, xcurr: int, ycurr: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
611 var g/ebx: code-point <- read-json-code-point stream
612 compare g, 0xffffffff/end-of-file
613 {
614 break-if-!=
615 return xcurr, ycurr
616 }
617
618 compare g, 0x6e/n
619 var x/eax: int <- copy xcurr
620 {
621 break-if-!=
622 increment ycurr
623 return xmin, ycurr
624 }
625
626 {
627 compare g, 0x74/t
628 break-if-!=
629 return xcurr, ycurr
630 }
631 {
632 compare g, 0x72/r
633 break-if-!=
634 return xcurr, ycurr
635 }
636 {
637 compare g, 0x66/f
638 break-if-!=
639 return xcurr, ycurr
640 }
641 {
642 compare g, 0x62/b
643 break-if-!=
644 return xcurr, ycurr
645 }
646 var y/ecx: int <- copy 0
647
648 {
649 compare g, 0x75/u
650 break-if-!=
651 x, y <- render-json-escaped-unicode-code-point screen, stream, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
652 return x, y
653 }
654
655 x, y <- render-code-point screen, g, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
656 return x, y
657 }
658
659
660 fn render-json-escaped-unicode-code-point screen: (addr screen), stream: (addr stream byte), xmin: int, ymin: int, xmax: int, ymax: int, xcurr: int, ycurr: int, color: int, background-color: int -> _/eax: int, _/ecx: int {
661 var hex-digits-storage: (array byte 4)
662 var hex-digits/esi: (addr array byte) <- address hex-digits-storage
663
664 var src/eax: byte <- read-byte stream
665 var dest/ecx: (addr byte) <- index hex-digits, 0
666 copy-byte-to *dest, src
667 src <- read-byte stream
668 dest <- index hex-digits, 1
669 copy-byte-to *dest, src
670 src <- read-byte stream
671 dest <- index hex-digits, 2
672 copy-byte-to *dest, src
673 src <- read-byte stream
674 dest <- index hex-digits, 3
675 copy-byte-to *dest, src
676
677 {
678 var endash?/eax: boolean <- string-equal? hex-digits, "2013"
679 compare endash?, 0/false
680 break-if-=
681 var x/eax: int <- copy 0
682 var y/ecx: int <- copy 0
683 x, y <- render-code-point screen, 0x2d/dash, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
684 return x, y
685 }
686
687 {
688 var emdash?/eax: boolean <- string-equal? hex-digits, "2014"
689 compare emdash?, 0/false
690 break-if-=
691 var x/eax: int <- copy 0
692 var y/ecx: int <- copy 0
693 x, y <- render-code-point screen, 0x2d/dash, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
694 return x, y
695 }
696
697 {
698 var left-quote?/eax: boolean <- string-equal? hex-digits, "2018"
699 compare left-quote?, 0/false
700 break-if-=
701 var x/eax: int <- copy 0
702 var y/ecx: int <- copy 0
703 x, y <- render-code-point screen, 0x27/quote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
704 return x, y
705 }
706
707 {
708 var right-quote?/eax: boolean <- string-equal? hex-digits, "2019"
709 compare right-quote?, 0/false
710 break-if-=
711 var x/eax: int <- copy 0
712 var y/ecx: int <- copy 0
713 x, y <- render-code-point screen, 0x27/quote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
714 return x, y
715 }
716
717 {
718 var left-dquote?/eax: boolean <- string-equal? hex-digits, "201c"
719 compare left-dquote?, 0/false
720 break-if-=
721 var x/eax: int <- copy 0
722 var y/ecx: int <- copy 0
723 x, y <- render-code-point screen, 0x22/dquote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
724 return x, y
725 }
726
727 {
728 var right-dquote?/eax: boolean <- string-equal? hex-digits, "201d"
729 compare right-dquote?, 0/false
730 break-if-=
731 var x/eax: int <- copy 0
732 var y/ecx: int <- copy 0
733 x, y <- render-code-point screen, 0x22/dquote, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
734 return x, y
735 }
736
737 {
738 var bullet?/eax: boolean <- string-equal? hex-digits, "2022"
739 compare bullet?, 0/false
740 break-if-=
741 var x/eax: int <- copy 0
742 var y/ecx: int <- copy 0
743 x, y <- render-code-point screen, 0x2a/asterisk, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
744 return x, y
745 }
746
747 {
748 var ellipses?/eax: boolean <- string-equal? hex-digits, "2026"
749 compare ellipses?, 0/false
750 break-if-=
751 var x/eax: int <- copy 0
752 var y/ecx: int <- copy 0
753 x, y <- draw-text-wrapping-right-then-down screen, "...", xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
754 return x, y
755 }
756 var n/eax: int <- parse-hex-int hex-digits
757 var c/edx: code-point <- copy n
758 var x/eax: int <- copy 0
759 var y/ecx: int <- copy 0
760 x, y <- render-code-point screen, c, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
761 return x, y
762 }
763
764
765
766 fn update-environment _env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
767 var env/edi: (addr environment) <- copy _env
768
769 {
770 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
771 compare *cursor-in-search?, 0/false
772 break-if-=
773 update-search env, key, users, channels, items
774 return
775 }
776 {
777 compare key, 0x2f/slash
778 break-if-!=
779
780 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
781 copy-to *cursor-in-search?, 1/true
782
783 var dirty?/eax: (addr boolean) <- get env, dirty?
784 copy-to *dirty?, 1/true
785 return
786 }
787 {
788 compare key, 0x1b/esc
789 break-if-!=
790
791 previous-tab env
792 return
793 }
794 var cursor-in-channels?/eax: (addr boolean) <- get env, cursor-in-channels?
795 {
796 compare key, 9/tab
797 break-if-!=
798
799 not *cursor-in-channels?
800
801 var dirty?/eax: (addr boolean) <- get env, dirty?
802 copy-to *dirty?, 1/true
803 return
804 }
805 {
806 compare *cursor-in-channels?, 0/false
807 break-if-!=
808 update-main-panel env, key, users, channels, items
809 return
810 }
811 {
812 compare *cursor-in-channels?, 0/false
813 break-if-=
814 update-channels-nav env, key, users, channels, items
815 return
816 }
817 }
818
819 fn update-main-panel env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
820 {
821 compare key, 0xa/newline
822 break-if-!=
823 new-thread-tab env, users, channels, items
824 return
825 }
826 {
827 compare key, 0x81/down-arrow
828 break-if-!=
829 next-item env, users, channels, items
830 return
831 }
832 {
833 compare key, 0x82/up-arrow
834 break-if-!=
835 previous-item env, users, channels, items
836 return
837 }
838 {
839 compare key, 6/ctrl-f
840 break-if-!=
841 page-down env, users, channels, items
842 return
843 }
844 {
845 compare key, 2/ctrl-b
846 break-if-!=
847 page-up env, users, channels, items
848 return
849 }
850 }
851
852
853 fn update-channels-nav _env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
854 var env/edi: (addr environment) <- copy _env
855 var channel-cursor-index/eax: (addr int) <- get env, channel-cursor-index
856 {
857 compare key, 0x81/down-arrow
858 break-if-!=
859 increment *channel-cursor-index
860 return
861 }
862 {
863 compare key, 0x82/up-arrow
864 break-if-!=
865 decrement *channel-cursor-index
866 return
867 }
868 {
869 compare key, 0xa/newline
870 break-if-!=
871 new-channel-tab env, *channel-cursor-index, channels
872 var cursor-in-channels?/eax: (addr boolean) <- get env, cursor-in-channels?
873 copy-to *cursor-in-channels?, 0/false
874 return
875 }
876 }
877
878 fn update-search _env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
879 var env/edi: (addr environment) <- copy _env
880 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
881 {
882 compare key 0x1b/esc
883 break-if-!=
884
885 copy-to *cursor-in-search?, 0/false
886 return
887 }
888 {
889 compare key, 0xa/newline
890 break-if-!=
891
892 new-search-tab env, items
893 copy-to *cursor-in-search?, 0/false
894 return
895 }
896
897 var search-terms-ah/eax: (addr handle gap-buffer) <- get env, search-terms
898 var search-terms/eax: (addr gap-buffer) <- lookup *search-terms-ah
899 var g/ecx: grapheme <- copy key
900 edit-gap-buffer search-terms, g
901 }
902
903 fn new-thread-tab _env: (addr environment), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
904 var env/edi: (addr environment) <- copy _env
905 var current-tab-index-a/ecx: (addr int) <- get env, current-tab-index
906 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
907 var tabs/eax: (addr array tab) <- lookup *tabs-ah
908 var current-tab-index/ecx: int <- copy *current-tab-index-a
909 var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
910 var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
911 var item-index/esi: int <- item-index current-tab, channels
912 var post-index/ecx: int <- post-index _items, item-index
913 var current-tab-index-addr/eax: (addr int) <- get env, current-tab-index
914 increment *current-tab-index-addr
915 var current-tab-index/edx: int <- copy *current-tab-index-addr
916 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
917 var tabs/eax: (addr array tab) <- lookup *tabs-ah
918 var max-tabs/ebx: int <- length tabs
919 compare current-tab-index, max-tabs
920 {
921 compare current-tab-index, max-tabs
922 break-if-<
923 abort "history overflow; grow max-history (we should probably improve this)"
924 }
925 var current-tab-offset/edi: (offset tab) <- compute-offset tabs, current-tab-index
926 var current-tab/edi: (addr tab) <- index tabs, current-tab-offset
927 clear-object current-tab
928 var current-tab-type/eax: (addr int) <- get current-tab, type
929 copy-to *current-tab, 3/thread
930 var current-tab-root-index/eax: (addr int) <- get current-tab, root-index
931 copy-to *current-tab-root-index, post-index
932 var items/eax: (addr item-list) <- copy _items
933 var items-data-ah/eax: (addr handle array item) <- get items, data
934 var items-data/eax: (addr array item) <- lookup *items-data-ah
935 var offset/ecx: (offset item) <- compute-offset items-data, post-index
936 var post/eax: (addr item) <- index items-data, offset
937 var post-comments-first-free-addr/ecx: (addr int) <- get post, comments-first-free
938
939
940
941 var final-post-comment-index/ecx: int <- copy *post-comments-first-free-addr
942 final-post-comment-index <- decrement
943 var post-comments-ah/eax: (addr handle array int) <- get post, comments
944 var post-comments/eax: (addr array int) <- lookup *post-comments-ah
945
946 var curr-post-comment-index/edx: int <- copy final-post-comment-index
947 {
948 compare curr-post-comment-index, 0
949 {
950 break-if->=
951
952
953
954 var tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
955 copy-to *tab-item-index-addr, curr-post-comment-index
956 return
957 }
958 var curr-comment-index/ecx: (addr int) <- index post-comments, curr-post-comment-index
959 compare *curr-comment-index, item-index
960 {
961 break-if-!=
962
963 var tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
964 copy-to *tab-item-index-addr, curr-post-comment-index
965 return
966 }
967 curr-post-comment-index <- decrement
968 loop
969 }
970 abort "new-thread-tab: should never leave previous loop without returning"
971 }
972
973 fn item-index _tab: (addr tab), _channels: (addr array channel) -> _/esi: int {
974 var tab/esi: (addr tab) <- copy _tab
975 var tab-type/eax: (addr int) <- get tab, type
976 {
977 compare *tab-type, 0/all-items
978 break-if-!=
979 var tab-item-index/eax: (addr int) <- get tab, item-index
980 return *tab-item-index
981 }
982 {
983 compare *tab-type, 1/channel
984 break-if-!=
985 var channel-index-addr/eax: (addr int) <- get tab, channel-index
986 var channel-index/eax: int <- copy *channel-index-addr
987 var channels/ecx: (addr array channel) <- copy _channels
988 var channel-offset/eax: (offset channel) <- compute-offset channels, channel-index
989 var current-channel/eax: (addr channel) <- index channels, channel-offset
990 var current-channel-posts-ah/eax: (addr handle array int) <- get current-channel, posts
991 var current-channel-posts/eax: (addr array int) <- lookup *current-channel-posts-ah
992 var channel-item-index-addr/ecx: (addr int) <- get tab, item-index
993 var channel-item-index/ecx: int <- copy *channel-item-index-addr
994 var channel-item-index/eax: (addr int) <- index current-channel-posts, channel-item-index
995 return *channel-item-index
996 }
997 {
998 compare *tab-type, 2/search
999 break-if-!=
1000 var tab-search-items-ah/eax: (addr handle array int) <- get tab, search-items
1001 var tab-search-items/eax: (addr array int) <- lookup *tab-search-items-ah
1002 var tab-search-items-index-addr/ecx: (addr int) <- get tab, item-index
1003 var tab-search-items-index/ecx: int <- copy *tab-search-items-index-addr
1004 var src/eax: (addr int) <- index tab-search-items, tab-search-items-index
1005 return *src
1006 }
1007 abort "item-index: unknown tab type"
1008 return -1
1009 }
1010
1011 fn post-index _items: (addr item-list), item-index: int -> _/ecx: int {
1012 var items/eax: (addr item-list) <- copy _items
1013 var items-data-ah/eax: (addr handle array item) <- get items, data
1014 var items-data/eax: (addr array item) <- lookup *items-data-ah
1015 var index/ecx: int <- copy item-index
1016 var offset/ecx: (offset item) <- compute-offset items-data, index
1017 var item/eax: (addr item) <- index items-data, offset
1018 var parent/eax: (addr int) <- get item, parent
1019 compare *parent, 0
1020 {
1021 break-if-=
1022 return *parent
1023 }
1024 return item-index
1025 }
1026
1027 fn new-channel-tab _env: (addr environment), channel-index: int, _channels: (addr array channel) {
1028 var env/edi: (addr environment) <- copy _env
1029 var current-tab-index-addr/eax: (addr int) <- get env, current-tab-index
1030 increment *current-tab-index-addr
1031 var current-tab-index/ecx: int <- copy *current-tab-index-addr
1032 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1033 var tabs/eax: (addr array tab) <- lookup *tabs-ah
1034 var max-tabs/edx: int <- length tabs
1035 compare current-tab-index, max-tabs
1036 {
1037 compare current-tab-index, max-tabs
1038 break-if-<
1039 abort "history overflow; grow max-history (we should probably improve this)"
1040 }
1041 var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
1042 var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
1043 clear-object current-tab
1044 var current-tab-type/eax: (addr int) <- get current-tab, type
1045 copy-to *current-tab, 1/channel
1046 var current-tab-channel-index/eax: (addr int) <- get current-tab, channel-index
1047 var curr-channel-index/edx: int <- copy channel-index
1048 copy-to *current-tab-channel-index, curr-channel-index
1049 var channels/esi: (addr array channel) <- copy _channels
1050 var curr-channel-offset/eax: (offset channel) <- compute-offset channels, curr-channel-index
1051 var curr-channel/eax: (addr channel) <- index channels, curr-channel-offset
1052 var curr-channel-posts-first-free-addr/eax: (addr int) <- get curr-channel, posts-first-free
1053 var curr-channel-final-post-index/eax: int <- copy *curr-channel-posts-first-free-addr
1054 curr-channel-final-post-index <- decrement
1055 var dest/edi: (addr int) <- get current-tab, item-index
1056 copy-to *dest, curr-channel-final-post-index
1057 }
1058
1059 fn new-search-tab _env: (addr environment), items: (addr item-list) {
1060 var env/edi: (addr environment) <- copy _env
1061 var current-tab-index-addr/eax: (addr int) <- get env, current-tab-index
1062 increment *current-tab-index-addr
1063 var current-tab-index/ecx: int <- copy *current-tab-index-addr
1064 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1065 var tabs/eax: (addr array tab) <- lookup *tabs-ah
1066 var max-tabs/edx: int <- length tabs
1067 compare current-tab-index, max-tabs
1068 {
1069 compare current-tab-index, max-tabs
1070 break-if-<
1071 abort "history overflow; grow max-history (we should probably improve this)"
1072 }
1073 var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
1074 var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
1075 clear-object current-tab
1076 var current-tab-type/eax: (addr int) <- get current-tab, type
1077 copy-to *current-tab, 2/search
1078 var current-tab-search-terms-ah/edx: (addr handle gap-buffer) <- get current-tab, search-terms
1079 allocate current-tab-search-terms-ah
1080 var current-tab-search-terms/eax: (addr gap-buffer) <- lookup *current-tab-search-terms-ah
1081 initialize-gap-buffer current-tab-search-terms, 0x30/search-capacity
1082 var search-terms-ah/ebx: (addr handle gap-buffer) <- get env, search-terms
1083 copy-gap-buffer search-terms-ah, current-tab-search-terms-ah
1084 var search-terms/eax: (addr gap-buffer) <- lookup *search-terms-ah
1085 search-items current-tab, items, search-terms
1086 }
1087
1088 fn search-items _tab: (addr tab), _items: (addr item-list), search-terms: (addr gap-buffer) {
1089 var tab/edi: (addr tab) <- copy _tab
1090 var tab-items-first-free-addr/esi: (addr int) <- get tab, search-items-first-free
1091 var tab-items-ah/eax: (addr handle array int) <- get tab, search-items
1092 populate tab-items-ah, 0x100/max-search-results
1093 var _tab-items/eax: (addr array int) <- lookup *tab-items-ah
1094 var tab-items/edi: (addr array int) <- copy _tab-items
1095
1096 var search-terms-stream-storage: (stream byte 0x100)
1097 var search-terms-stream-addr/ecx: (addr stream byte) <- address search-terms-stream-storage
1098 emit-gap-buffer search-terms, search-terms-stream-addr
1099 var search-terms-text-h: (handle array byte)
1100 var search-terms-text-ah/eax: (addr handle array byte) <- address search-terms-text-h
1101 stream-to-array search-terms-stream-addr, search-terms-text-ah
1102 var tmp/eax: (addr array byte) <- lookup *search-terms-text-ah
1103 var search-terms-text: (addr array byte)
1104 copy-to search-terms-text, tmp
1105
1106 var items/ecx: (addr item-list) <- copy _items
1107 var items-data-ah/eax: (addr handle array item) <- get items, data
1108 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1109 var items-data/ebx: (addr array item) <- copy _items-data
1110 var items-data-first-free-a/edx: (addr int) <- get items, data-first-free
1111 var i/ecx: int <- copy 0
1112 {
1113 compare i, *items-data-first-free-a
1114 break-if->=
1115 var curr-offset/eax: (offset item) <- compute-offset items-data, i
1116 var curr-item/eax: (addr item) <- index items-data, curr-offset
1117 var found?/eax: boolean <- search-terms-match? curr-item, search-terms-text
1118 compare found?, 0/false
1119 {
1120 break-if-=
1121 var tab-items-first-free/eax: int <- copy *tab-items-first-free-addr
1122 compare tab-items-first-free, 0x100/max-search-results
1123 break-if->=
1124 var dest/eax: (addr int) <- index tab-items, tab-items-first-free
1125 copy-to *dest, i
1126 increment *tab-items-first-free-addr
1127 }
1128 i <- increment
1129 loop
1130 }
1131 var tab/edi: (addr tab) <- copy _tab
1132 var tab-item-index-addr/edi: (addr int) <- get tab, item-index
1133 var tab-items-first-free/eax: int <- copy *tab-items-first-free-addr
1134 tab-items-first-free <- decrement
1135 copy-to *tab-item-index-addr, tab-items-first-free
1136 }
1137
1138 fn search-terms-match? _item: (addr item), search-terms: (addr array byte) -> _/eax: boolean {
1139 var item/esi: (addr item) <- copy _item
1140 var item-text-ah/eax: (addr handle array byte) <- get item, text
1141 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1142 var i/ecx: int <- copy 0
1143 var max/edx: int <- length item-text
1144 var search-terms2/ebx: (addr array byte) <- copy search-terms
1145 var slen/ebx: int <- length search-terms2
1146 max <- subtract slen
1147 {
1148 compare i, max
1149 break-if->
1150 var found?/eax: boolean <- substring-match? item-text, search-terms, i
1151 compare found?, 0/false
1152 {
1153 break-if-=
1154 return 1/true
1155 }
1156 i <- increment
1157 loop
1158 }
1159 return 0/false
1160 }
1161
1162 fn substring-match? _s: (addr array byte), _pat: (addr array byte), start: int -> _/eax: boolean {
1163 var s/esi: (addr array byte) <- copy _s
1164 var pat/edi: (addr array byte) <- copy _pat
1165 var s-idx/edx: int <- copy start
1166 var pat-idx/ebx: int <- copy 0
1167 var pat-len: int
1168 var tmp/eax: int <- length pat
1169 copy-to pat-len, tmp
1170 {
1171 compare pat-idx, pat-len
1172 break-if->=
1173 var s-ab/eax: (addr byte) <- index s, s-idx
1174 var s-b/eax: byte <- copy-byte *s-ab
1175 var pat-ab/ecx: (addr byte) <- index pat, pat-idx
1176 var pat-b/ecx: byte <- copy-byte *pat-ab
1177 compare s-b, pat-b
1178 {
1179 break-if-=
1180 return 0/false
1181 }
1182 s-idx <- increment
1183 pat-idx <- increment
1184 loop
1185 }
1186 return 1/true
1187 }
1188
1189 fn previous-tab _env: (addr environment) {
1190 var env/edi: (addr environment) <- copy _env
1191 var current-tab-index-addr/ecx: (addr int) <- get env, current-tab-index
1192 compare *current-tab-index-addr, 0
1193 {
1194 break-if-<=
1195 decrement *current-tab-index-addr
1196
1197 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1198 var tabs/eax: (addr array tab) <- lookup *tabs-ah
1199 var current-tab-index/ecx: int <- copy *current-tab-index-addr
1200 var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
1201 var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
1202 var current-tab-type/eax: (addr int) <- get current-tab, type
1203 compare *current-tab-type, 2/search
1204 break-if-!=
1205 var current-tab-search-terms-ah/ecx: (addr handle gap-buffer) <- get current-tab, search-terms
1206 var search-terms-ah/edx: (addr handle gap-buffer) <- get env, search-terms
1207 var search-terms/eax: (addr gap-buffer) <- lookup *search-terms-ah
1208 clear-gap-buffer search-terms
1209 copy-gap-buffer current-tab-search-terms-ah, search-terms-ah
1210 }
1211 }
1212
1213 fn next-item _env: (addr environment), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1214 var env/edi: (addr environment) <- copy _env
1215 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1216 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
1217 var tabs/edx: (addr array tab) <- copy _tabs
1218 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
1219 var current-tab-index/eax: int <- copy *current-tab-index-a
1220 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
1221 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
1222 var dest/eax: (addr int) <- get current-tab, item-index
1223 compare *dest, 0
1224 break-if-<=
1225 decrement *dest
1226 }
1227
1228 fn previous-item _env: (addr environment), users: (addr array user), _channels: (addr array channel), _items: (addr item-list) {
1229 var env/edi: (addr environment) <- copy _env
1230 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1231 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
1232 var tabs/edx: (addr array tab) <- copy _tabs
1233 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
1234 var current-tab-index/eax: int <- copy *current-tab-index-a
1235 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
1236 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
1237 var current-tab-type/eax: (addr int) <- get current-tab, type
1238 compare *current-tab-type, 0/all-items
1239 {
1240 break-if-!=
1241 var items/esi: (addr item-list) <- copy _items
1242 var items-data-first-free-a/ecx: (addr int) <- get items, data-first-free
1243 var final-item-index/ecx: int <- copy *items-data-first-free-a
1244 final-item-index <- decrement
1245 var dest/eax: (addr int) <- get current-tab, item-index
1246 compare *dest, final-item-index
1247 break-if->=
1248 increment *dest
1249 return
1250 }
1251 compare *current-tab-type, 1/channel
1252 {
1253 break-if-!=
1254 var current-channel-index-addr/eax: (addr int) <- get current-tab, channel-index
1255 var current-channel-index/eax: int <- copy *current-channel-index-addr
1256 var channels/esi: (addr array channel) <- copy _channels
1257 var current-channel-offset/eax: (offset channel) <- compute-offset channels, current-channel-index
1258 var current-channel/eax: (addr channel) <- index channels, current-channel-offset
1259 var current-channel-posts-first-free-addr/eax: (addr int) <- get current-channel, posts-first-free
1260 var final-item-index/ecx: int <- copy *current-channel-posts-first-free-addr
1261 final-item-index <- decrement
1262 var dest/eax: (addr int) <- get current-tab, item-index
1263 compare *dest, final-item-index
1264 break-if->=
1265 increment *dest
1266 return
1267 }
1268 compare *current-tab-type, 2/search
1269 {
1270 break-if-!=
1271 var current-tab-search-items-first-free-addr/eax: (addr int) <- get current-tab, search-items-first-free
1272 var final-item-index/ecx: int <- copy *current-tab-search-items-first-free-addr
1273 final-item-index <- decrement
1274 var dest/eax: (addr int) <- get current-tab, item-index
1275 compare *dest, final-item-index
1276 break-if->=
1277 increment *dest
1278 return
1279 }
1280 compare *current-tab-type, 3/thread
1281 {
1282 break-if-!=
1283 var items/eax: (addr item-list) <- copy _items
1284 var items-data-ah/eax: (addr handle array item) <- get items, data
1285 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1286 var items-data/esi: (addr array item) <- copy _items-data
1287 var current-tab-root-index-addr/eax: (addr int) <- get current-tab, root-index
1288 var current-tab-root-index/eax: int <- copy *current-tab-root-index-addr
1289 var current-tab-root-offset/eax: (offset item) <- compute-offset items-data, current-tab-root-index
1290 var post/eax: (addr item) <- index items-data, current-tab-root-offset
1291 var post-comments-first-free-addr/ecx: (addr int) <- get post, comments-first-free
1292 var final-item-index/ecx: int <- copy *post-comments-first-free-addr
1293 final-item-index <- decrement
1294 var dest/eax: (addr int) <- get current-tab, item-index
1295 compare *dest, final-item-index
1296 break-if->=
1297 increment *dest
1298 return
1299 }
1300 }
1301
1302 fn page-down _env: (addr environment), users: (addr array user), channels: (addr array channel), items: (addr item-list) {
1303 var env/edi: (addr environment) <- copy _env
1304 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1305 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
1306 var tabs/ecx: (addr array tab) <- copy _tabs
1307 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
1308 var current-tab-index/eax: int <- copy *current-tab-index-a
1309 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
1310 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
1311 var current-tab-type/eax: (addr int) <- get current-tab, type
1312 compare *current-tab-type, 0/all-items
1313 {
1314 break-if-!=
1315 all-items-page-down current-tab, users, channels, items
1316 return
1317 }
1318 compare *current-tab-type, 1/channel
1319 {
1320 break-if-!=
1321 channel-page-down current-tab, users, channels, items
1322 return
1323 }
1324 compare *current-tab-type, 2/search
1325 {
1326 break-if-!=
1327 search-page-down current-tab, users, channels, items
1328 return
1329 }
1330 compare *current-tab-type, 3/thread
1331 {
1332 break-if-!=
1333 thread-page-down current-tab, users, channels, items
1334 return
1335 }
1336 }
1337
1338 fn all-items-page-down _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1339 var items/esi: (addr item-list) <- copy _items
1340 var items-data-ah/eax: (addr handle array item) <- get items, data
1341 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1342 var items-data/ebx: (addr array item) <- copy _items-data
1343 var current-tab/eax: (addr tab) <- copy _current-tab
1344 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1345 var new-item-index/ecx: int <- copy *current-tab-item-index-addr
1346 var y/edx: int <- copy 2
1347 {
1348 compare new-item-index, 0
1349 break-if-<
1350 compare y, 0x28/screen-height-minus-menu
1351 break-if->=
1352 var offset/eax: (offset item) <- compute-offset items-data, new-item-index
1353 var item/eax: (addr item) <- index items-data, offset
1354 var item-text-ah/eax: (addr handle array byte) <- get item, text
1355 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1356 var h/eax: int <- estimate-height item-text
1357 y <- add h
1358 new-item-index <- decrement
1359 loop
1360 }
1361 new-item-index <- increment
1362 {
1363
1364
1365
1366
1367 compare new-item-index, *current-tab-item-index-addr
1368 break-if-!=
1369
1370 compare new-item-index, 0
1371 break-if-=
1372 new-item-index <- decrement
1373 }
1374 copy-to *current-tab-item-index-addr, new-item-index
1375 }
1376
1377 fn channel-page-down _current-tab: (addr tab), users: (addr array user), _channels: (addr array channel), _items: (addr item-list) {
1378 var current-tab/edi: (addr tab) <- copy _current-tab
1379 var current-channel-index-addr/eax: (addr int) <- get current-tab, channel-index
1380 var current-channel-index/eax: int <- copy *current-channel-index-addr
1381 var channels/esi: (addr array channel) <- copy _channels
1382 var current-channel-offset/eax: (offset channel) <- compute-offset channels, current-channel-index
1383 var current-channel/esi: (addr channel) <- index channels, current-channel-offset
1384 var current-channel-posts-ah/eax: (addr handle array int) <- get current-channel, posts
1385 var _current-channel-posts/eax: (addr array int) <- lookup *current-channel-posts-ah
1386 var current-channel-posts/esi: (addr array int) <- copy _current-channel-posts
1387 var items/eax: (addr item-list) <- copy _items
1388 var items-data-ah/eax: (addr handle array item) <- get items, data
1389 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1390 var items-data/ebx: (addr array item) <- copy _items-data
1391 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1392 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1393 var y/edx: int <- copy 2
1394 {
1395 compare new-tab-item-index, 0
1396 break-if-<
1397 compare y, 0x28/screen-height-minus-menu
1398 break-if->=
1399 var current-item-index-addr/eax: (addr int) <- index current-channel-posts, new-tab-item-index
1400 var current-item-index/eax: int <- copy *current-item-index-addr
1401 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1402 var item/eax: (addr item) <- index items-data, offset
1403 var item-text-ah/eax: (addr handle array byte) <- get item, text
1404 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1405 var h/eax: int <- estimate-height item-text
1406 y <- add h
1407 new-tab-item-index <- decrement
1408 loop
1409 }
1410 new-tab-item-index <- increment
1411 {
1412
1413
1414
1415
1416 compare new-tab-item-index, *current-tab-item-index-addr
1417 break-if-!=
1418
1419 compare new-tab-item-index, 0
1420 break-if-=
1421 new-tab-item-index <- decrement
1422 }
1423 copy-to *current-tab-item-index-addr, new-tab-item-index
1424 }
1425
1426 fn search-page-down _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1427 var current-tab/edi: (addr tab) <- copy _current-tab
1428 var current-tab-search-items-ah/eax: (addr handle array int) <- get current-tab, search-items
1429 var _current-tab-search-items/eax: (addr array int) <- lookup *current-tab-search-items-ah
1430 var current-tab-search-items/esi: (addr array int) <- copy _current-tab-search-items
1431 var items/eax: (addr item-list) <- copy _items
1432 var items-data-ah/eax: (addr handle array item) <- get items, data
1433 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1434 var items-data/ebx: (addr array item) <- copy _items-data
1435 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1436 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1437 var y/edx: int <- copy 2
1438 {
1439 compare new-tab-item-index, 0
1440 break-if-<
1441 compare y, 0x28/screen-height-minus-menu
1442 break-if->=
1443 var current-item-index-addr/eax: (addr int) <- index current-tab-search-items, new-tab-item-index
1444 var current-item-index/eax: int <- copy *current-item-index-addr
1445 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1446 var item/eax: (addr item) <- index items-data, offset
1447 var item-text-ah/eax: (addr handle array byte) <- get item, text
1448 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1449 var h/eax: int <- estimate-height item-text
1450 y <- add h
1451 new-tab-item-index <- decrement
1452 loop
1453 }
1454 new-tab-item-index <- increment
1455 {
1456
1457
1458
1459
1460 compare new-tab-item-index, *current-tab-item-index-addr
1461 break-if-!=
1462
1463 compare new-tab-item-index, 0
1464 break-if-=
1465 new-tab-item-index <- decrement
1466 }
1467 copy-to *current-tab-item-index-addr, new-tab-item-index
1468 }
1469
1470 fn thread-page-down _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1471 var current-tab/edi: (addr tab) <- copy _current-tab
1472 var items/eax: (addr item-list) <- copy _items
1473 var items-data-ah/eax: (addr handle array item) <- get items, data
1474 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1475 var items-data/esi: (addr array item) <- copy _items-data
1476 var current-tab-root-index-addr/eax: (addr int) <- get current-tab, root-index
1477 var current-tab-root-index/eax: int <- copy *current-tab-root-index-addr
1478 var current-tab-root-offset/eax: (offset item) <- compute-offset items-data, current-tab-root-index
1479 var post/eax: (addr item) <- index items-data, current-tab-root-offset
1480 var post-comments-ah/eax: (addr handle array int) <- get post, comments
1481 var _post-comments/eax: (addr array int) <- lookup *post-comments-ah
1482 var post-comments/ebx: (addr array int) <- copy _post-comments
1483 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1484 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1485 var y/edx: int <- copy 2
1486 {
1487 compare new-tab-item-index, 0
1488 break-if-<
1489 compare y, 0x28/screen-height-minus-menu
1490 break-if->=
1491 var current-item-index-addr/eax: (addr int) <- index post-comments, new-tab-item-index
1492 var current-item-index/eax: int <- copy *current-item-index-addr
1493 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1494 var item/eax: (addr item) <- index items-data, offset
1495 var item-text-ah/eax: (addr handle array byte) <- get item, text
1496 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1497 var h/eax: int <- estimate-height item-text
1498 y <- add h
1499 new-tab-item-index <- decrement
1500 loop
1501 }
1502 new-tab-item-index <- increment
1503 {
1504
1505
1506
1507
1508 compare new-tab-item-index, *current-tab-item-index-addr
1509 break-if-!=
1510
1511 compare new-tab-item-index, 0
1512 break-if-=
1513 new-tab-item-index <- decrement
1514 }
1515 copy-to *current-tab-item-index-addr, new-tab-item-index
1516 }
1517
1518 fn page-up _env: (addr environment), users: (addr array user), channels: (addr array channel), items: (addr item-list) {
1519 var env/edi: (addr environment) <- copy _env
1520 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1521 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
1522 var tabs/ecx: (addr array tab) <- copy _tabs
1523 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
1524 var current-tab-index/eax: int <- copy *current-tab-index-a
1525 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
1526 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
1527 var current-tab-type/eax: (addr int) <- get current-tab, type
1528 compare *current-tab-type, 0/all-items
1529 {
1530 break-if-!=
1531 all-items-page-up current-tab, users, channels, items
1532 return
1533 }
1534 compare *current-tab-type, 1/channel
1535 {
1536 break-if-!=
1537 channel-page-up current-tab, users, channels, items
1538 return
1539 }
1540 compare *current-tab-type, 2/search
1541 {
1542 break-if-!=
1543 search-page-up current-tab, users, channels, items
1544 return
1545 }
1546 compare *current-tab-type, 3/thread
1547 {
1548 break-if-!=
1549 thread-page-up current-tab, users, channels, items
1550 return
1551 }
1552 }
1553
1554 fn all-items-page-up _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1555 var items/esi: (addr item-list) <- copy _items
1556 var items-data-ah/eax: (addr handle array item) <- get items, data
1557 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1558 var items-data/ebx: (addr array item) <- copy _items-data
1559 var items-data-first-free-a/eax: (addr int) <- get items, data-first-free
1560 var final-item-index/esi: int <- copy *items-data-first-free-a
1561 final-item-index <- decrement
1562 var current-tab/eax: (addr tab) <- copy _current-tab
1563 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1564 var new-item-index/ecx: int <- copy *current-tab-item-index-addr
1565 var y/edx: int <- copy 2
1566 {
1567 compare new-item-index, final-item-index
1568 break-if->
1569 compare y, 0x28/screen-height-minus-menu
1570 break-if->=
1571 var offset/eax: (offset item) <- compute-offset items-data, new-item-index
1572 var item/eax: (addr item) <- index items-data, offset
1573 var item-text-ah/eax: (addr handle array byte) <- get item, text
1574 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1575 var h/eax: int <- estimate-height item-text
1576 y <- add h
1577 new-item-index <- increment
1578 loop
1579 }
1580 new-item-index <- decrement
1581 copy-to *current-tab-item-index-addr, new-item-index
1582 }
1583
1584 fn channel-page-up _current-tab: (addr tab), users: (addr array user), _channels: (addr array channel), _items: (addr item-list) {
1585 var current-tab/edi: (addr tab) <- copy _current-tab
1586 var current-channel-index-addr/eax: (addr int) <- get current-tab, channel-index
1587 var current-channel-index/eax: int <- copy *current-channel-index-addr
1588 var channels/esi: (addr array channel) <- copy _channels
1589 var current-channel-offset/eax: (offset channel) <- compute-offset channels, current-channel-index
1590 var current-channel/esi: (addr channel) <- index channels, current-channel-offset
1591 var current-channel-posts-first-free-addr/eax: (addr int) <- get current-channel, posts-first-free
1592 var tmp/eax: int <- copy *current-channel-posts-first-free-addr
1593 var final-tab-post-index: int
1594 copy-to final-tab-post-index, tmp
1595 decrement final-tab-post-index
1596 var current-channel-posts-ah/eax: (addr handle array int) <- get current-channel, posts
1597 var _current-channel-posts/eax: (addr array int) <- lookup *current-channel-posts-ah
1598 var current-channel-posts/esi: (addr array int) <- copy _current-channel-posts
1599 var items/esi: (addr item-list) <- copy _items
1600 var items-data-ah/eax: (addr handle array item) <- get items, data
1601 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1602 var items-data/ebx: (addr array item) <- copy _items-data
1603 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1604 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1605 var y/edx: int <- copy 2
1606 {
1607 compare new-tab-item-index, final-tab-post-index
1608 break-if->
1609 compare y, 0x28/screen-height-minus-menu
1610 break-if->=
1611 var offset/eax: (offset item) <- compute-offset items-data, new-tab-item-index
1612 var item/eax: (addr item) <- index items-data, offset
1613 var item-text-ah/eax: (addr handle array byte) <- get item, text
1614 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1615 var h/eax: int <- estimate-height item-text
1616 y <- add h
1617 new-tab-item-index <- increment
1618 loop
1619 }
1620 new-tab-item-index <- decrement
1621 copy-to *current-tab-item-index-addr, new-tab-item-index
1622 }
1623
1624 fn search-page-up _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1625 var current-tab/edi: (addr tab) <- copy _current-tab
1626 var current-tab-search-items-first-free-addr/eax: (addr int) <- get current-tab, search-items-first-free
1627 var final-tab-post-index: int
1628 var tmp/eax: int <- copy *current-tab-search-items-first-free-addr
1629 copy-to final-tab-post-index, tmp
1630 decrement final-tab-post-index
1631 var current-tab-search-items-ah/eax: (addr handle array int) <- get current-tab, search-items
1632 var _current-tab-search-items/eax: (addr array int) <- lookup *current-tab-search-items-ah
1633 var current-tab-search-items/esi: (addr array int) <- copy _current-tab-search-items
1634 var items/eax: (addr item-list) <- copy _items
1635 var items-data-ah/eax: (addr handle array item) <- get items, data
1636 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1637 var items-data/ebx: (addr array item) <- copy _items-data
1638 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1639 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1640 var y/edx: int <- copy 2
1641 {
1642 compare new-tab-item-index, final-tab-post-index
1643 break-if->
1644 compare y, 0x28/screen-height-minus-menu
1645 break-if->=
1646 var current-item-index-addr/eax: (addr int) <- index current-tab-search-items, new-tab-item-index
1647 var current-item-index/eax: int <- copy *current-item-index-addr
1648 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1649 var item/eax: (addr item) <- index items-data, offset
1650 var item-text-ah/eax: (addr handle array byte) <- get item, text
1651 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1652 var h/eax: int <- estimate-height item-text
1653 y <- add h
1654 new-tab-item-index <- increment
1655 loop
1656 }
1657 new-tab-item-index <- decrement
1658 copy-to *current-tab-item-index-addr, new-tab-item-index
1659 }
1660
1661 fn thread-page-up _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1662 var current-tab/edi: (addr tab) <- copy _current-tab
1663 var items/eax: (addr item-list) <- copy _items
1664 var items-data-ah/eax: (addr handle array item) <- get items, data
1665 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1666 var items-data/esi: (addr array item) <- copy _items-data
1667 var current-tab-root-index-addr/eax: (addr int) <- get current-tab, root-index
1668 var current-tab-root-index/eax: int <- copy *current-tab-root-index-addr
1669 var current-tab-root-offset/eax: (offset item) <- compute-offset items-data, current-tab-root-index
1670 var post/eax: (addr item) <- index items-data, current-tab-root-offset
1671 var post-comments-first-free-addr/ecx: (addr int) <- get post, comments-first-free
1672 var post-comments-ah/eax: (addr handle array int) <- get post, comments
1673 var _post-comments/eax: (addr array int) <- lookup *post-comments-ah
1674 var post-comments/ebx: (addr array int) <- copy _post-comments
1675 var final-tab-comment-index: int
1676 {
1677 var tmp/eax: int <- copy *post-comments-first-free-addr
1678 tmp <- decrement
1679 copy-to final-tab-comment-index, tmp
1680 }
1681 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1682 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1683 var y/edx: int <- copy 2
1684 {
1685 compare new-tab-item-index, final-tab-comment-index
1686 break-if->
1687 compare y, 0x28/screen-height-minus-menu
1688 break-if->=
1689 var current-item-index-addr/eax: (addr int) <- index post-comments, new-tab-item-index
1690 var current-item-index/eax: int <- copy *current-item-index-addr
1691 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1692 var item/eax: (addr item) <- index items-data, offset
1693 var item-text-ah/eax: (addr handle array byte) <- get item, text
1694 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1695 var h/eax: int <- estimate-height item-text
1696 y <- add h
1697 new-tab-item-index <- increment
1698 loop
1699 }
1700 new-tab-item-index <- decrement
1701 copy-to *current-tab-item-index-addr, new-tab-item-index
1702 }
1703
1704
1705 fn estimate-height _message-text: (addr array byte) -> _/eax: int {
1706 var message-text/esi: (addr array byte) <- copy _message-text
1707 var result/eax: int <- length message-text
1708 var remainder/edx: int <- copy 0
1709 result, remainder <- integer-divide result, 0x40/post-width
1710 compare remainder, 0
1711 {
1712 break-if-=
1713 result <- increment
1714 }
1715 result <- add 2/item-padding-ver
1716 compare result, 6/avatar-space-ver
1717 {
1718 break-if->
1719 return 6/avatar-space-ver
1720 }
1721 return result
1722 }