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 ustream-storage: (stream byte 4)
662 var ustream/esi: (addr stream byte) <- address ustream-storage
663
664 var b/eax: byte <- read-byte stream
665 var b-int/eax: int <- copy b
666 append-byte ustream, b-int
667 var b/eax: byte <- read-byte stream
668 var b-int/eax: int <- copy b
669 append-byte ustream, b-int
670 var b/eax: byte <- read-byte stream
671 var b-int/eax: int <- copy b
672 append-byte ustream, b-int
673 var b/eax: byte <- read-byte stream
674 var b-int/eax: int <- copy b
675 append-byte ustream, b-int
676
677 {
678 var endash?/eax: boolean <- stream-data-equal? ustream, "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 <- stream-data-equal? ustream, "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 <- stream-data-equal? ustream, "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 <- stream-data-equal? ustream, "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 <- stream-data-equal? ustream, "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 <- stream-data-equal? ustream, "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 <- stream-data-equal? ustream, "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 <- stream-data-equal? ustream, "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
757 var x/eax: int <- copy 0
758 var y/ecx: int <- copy 0
759 x, y <- draw-stream-wrapping-right-then-down screen, ustream, xmin, ymin, xmax, ymax, xcurr, ycurr, color, background-color
760 return x, y
761 }
762
763
764
765 fn update-environment _env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
766 var env/edi: (addr environment) <- copy _env
767
768 {
769 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
770 compare *cursor-in-search?, 0/false
771 break-if-=
772 update-search env, key, users, channels, items
773 return
774 }
775 {
776 compare key, 0x2f/slash
777 break-if-!=
778
779 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
780 copy-to *cursor-in-search?, 1/true
781
782 var dirty?/eax: (addr boolean) <- get env, dirty?
783 copy-to *dirty?, 1/true
784 return
785 }
786 {
787 compare key, 0x1b/esc
788 break-if-!=
789
790 previous-tab env
791 return
792 }
793 var cursor-in-channels?/eax: (addr boolean) <- get env, cursor-in-channels?
794 {
795 compare key, 9/tab
796 break-if-!=
797
798 not *cursor-in-channels?
799
800 var dirty?/eax: (addr boolean) <- get env, dirty?
801 copy-to *dirty?, 1/true
802 return
803 }
804 {
805 compare *cursor-in-channels?, 0/false
806 break-if-!=
807 update-main-panel env, key, users, channels, items
808 return
809 }
810 {
811 compare *cursor-in-channels?, 0/false
812 break-if-=
813 update-channels-nav env, key, users, channels, items
814 return
815 }
816 }
817
818 fn update-main-panel env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
819 {
820 compare key, 0xa/newline
821 break-if-!=
822 new-thread-tab env, users, channels, items
823 return
824 }
825 {
826 compare key, 0x81/down-arrow
827 break-if-!=
828 next-item env, users, channels, items
829 return
830 }
831 {
832 compare key, 0x82/up-arrow
833 break-if-!=
834 previous-item env, users, channels, items
835 return
836 }
837 {
838 compare key, 6/ctrl-f
839 break-if-!=
840 page-down env, users, channels, items
841 return
842 }
843 {
844 compare key, 2/ctrl-b
845 break-if-!=
846 page-up env, users, channels, items
847 return
848 }
849 }
850
851
852 fn update-channels-nav _env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
853 var env/edi: (addr environment) <- copy _env
854 var channel-cursor-index/eax: (addr int) <- get env, channel-cursor-index
855 {
856 compare key, 0x81/down-arrow
857 break-if-!=
858 increment *channel-cursor-index
859 return
860 }
861 {
862 compare key, 0x82/up-arrow
863 break-if-!=
864 decrement *channel-cursor-index
865 return
866 }
867 {
868 compare key, 0xa/newline
869 break-if-!=
870 new-channel-tab env, *channel-cursor-index, channels
871 var cursor-in-channels?/eax: (addr boolean) <- get env, cursor-in-channels?
872 copy-to *cursor-in-channels?, 0/false
873 return
874 }
875 }
876
877 fn update-search _env: (addr environment), key: byte, users: (addr array user), channels: (addr array channel), items: (addr item-list) {
878 var env/edi: (addr environment) <- copy _env
879 var cursor-in-search?/eax: (addr boolean) <- get env, cursor-in-search?
880 {
881 compare key 0x1b/esc
882 break-if-!=
883
884 copy-to *cursor-in-search?, 0/false
885 return
886 }
887 {
888 compare key, 0xa/newline
889 break-if-!=
890
891 new-search-tab env, items
892 copy-to *cursor-in-search?, 0/false
893 return
894 }
895
896 var search-terms-ah/eax: (addr handle gap-buffer) <- get env, search-terms
897 var search-terms/eax: (addr gap-buffer) <- lookup *search-terms-ah
898 var g/ecx: grapheme <- copy key
899 edit-gap-buffer search-terms, g
900 }
901
902 fn new-thread-tab _env: (addr environment), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
903 var env/edi: (addr environment) <- copy _env
904 var current-tab-index-a/ecx: (addr int) <- get env, current-tab-index
905 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
906 var tabs/eax: (addr array tab) <- lookup *tabs-ah
907 var current-tab-index/ecx: int <- copy *current-tab-index-a
908 var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
909 var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
910 var item-index/esi: int <- item-index current-tab, channels
911 var post-index/ecx: int <- post-index _items, item-index
912 var current-tab-index-addr/eax: (addr int) <- get env, current-tab-index
913 increment *current-tab-index-addr
914 var current-tab-index/edx: int <- copy *current-tab-index-addr
915 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
916 var tabs/eax: (addr array tab) <- lookup *tabs-ah
917 var max-tabs/ebx: int <- length tabs
918 compare current-tab-index, max-tabs
919 {
920 compare current-tab-index, max-tabs
921 break-if-<
922 abort "history overflow; grow max-history (we should probably improve this)"
923 }
924 var current-tab-offset/edi: (offset tab) <- compute-offset tabs, current-tab-index
925 var current-tab/edi: (addr tab) <- index tabs, current-tab-offset
926 clear-object current-tab
927 var current-tab-type/eax: (addr int) <- get current-tab, type
928 copy-to *current-tab, 3/thread
929 var current-tab-root-index/eax: (addr int) <- get current-tab, root-index
930 copy-to *current-tab-root-index, post-index
931 var items/eax: (addr item-list) <- copy _items
932 var items-data-ah/eax: (addr handle array item) <- get items, data
933 var items-data/eax: (addr array item) <- lookup *items-data-ah
934 var offset/ecx: (offset item) <- compute-offset items-data, post-index
935 var post/eax: (addr item) <- index items-data, offset
936 var post-comments-first-free-addr/ecx: (addr int) <- get post, comments-first-free
937
938
939
940 var final-post-comment-index/ecx: int <- copy *post-comments-first-free-addr
941 final-post-comment-index <- decrement
942 var post-comments-ah/eax: (addr handle array int) <- get post, comments
943 var post-comments/eax: (addr array int) <- lookup *post-comments-ah
944
945 var curr-post-comment-index/edx: int <- copy final-post-comment-index
946 {
947 compare curr-post-comment-index, 0
948 {
949 break-if->=
950
951
952
953 var tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
954 copy-to *tab-item-index-addr, curr-post-comment-index
955 return
956 }
957 var curr-comment-index/ecx: (addr int) <- index post-comments, curr-post-comment-index
958 compare *curr-comment-index, item-index
959 {
960 break-if-!=
961
962 var tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
963 copy-to *tab-item-index-addr, curr-post-comment-index
964 return
965 }
966 curr-post-comment-index <- decrement
967 loop
968 }
969 abort "new-thread-tab: should never leave previous loop without returning"
970 }
971
972 fn item-index _tab: (addr tab), _channels: (addr array channel) -> _/esi: int {
973 var tab/esi: (addr tab) <- copy _tab
974 var tab-type/eax: (addr int) <- get tab, type
975 {
976 compare *tab-type, 0/all-items
977 break-if-!=
978 var tab-item-index/eax: (addr int) <- get tab, item-index
979 return *tab-item-index
980 }
981 {
982 compare *tab-type, 1/channel
983 break-if-!=
984 var channel-index-addr/eax: (addr int) <- get tab, channel-index
985 var channel-index/eax: int <- copy *channel-index-addr
986 var channels/ecx: (addr array channel) <- copy _channels
987 var channel-offset/eax: (offset channel) <- compute-offset channels, channel-index
988 var current-channel/eax: (addr channel) <- index channels, channel-offset
989 var current-channel-posts-ah/eax: (addr handle array int) <- get current-channel, posts
990 var current-channel-posts/eax: (addr array int) <- lookup *current-channel-posts-ah
991 var channel-item-index-addr/ecx: (addr int) <- get tab, item-index
992 var channel-item-index/ecx: int <- copy *channel-item-index-addr
993 var channel-item-index/eax: (addr int) <- index current-channel-posts, channel-item-index
994 return *channel-item-index
995 }
996 {
997 compare *tab-type, 2/search
998 break-if-!=
999 var tab-search-items-ah/eax: (addr handle array int) <- get tab, search-items
1000 var tab-search-items/eax: (addr array int) <- lookup *tab-search-items-ah
1001 var tab-search-items-index-addr/ecx: (addr int) <- get tab, item-index
1002 var tab-search-items-index/ecx: int <- copy *tab-search-items-index-addr
1003 var src/eax: (addr int) <- index tab-search-items, tab-search-items-index
1004 return *src
1005 }
1006 abort "item-index: unknown tab type"
1007 return -1
1008 }
1009
1010 fn post-index _items: (addr item-list), item-index: int -> _/ecx: int {
1011 var items/eax: (addr item-list) <- copy _items
1012 var items-data-ah/eax: (addr handle array item) <- get items, data
1013 var items-data/eax: (addr array item) <- lookup *items-data-ah
1014 var index/ecx: int <- copy item-index
1015 var offset/ecx: (offset item) <- compute-offset items-data, index
1016 var item/eax: (addr item) <- index items-data, offset
1017 var parent/eax: (addr int) <- get item, parent
1018 compare *parent, 0
1019 {
1020 break-if-=
1021 return *parent
1022 }
1023 return item-index
1024 }
1025
1026 fn new-channel-tab _env: (addr environment), channel-index: int, _channels: (addr array channel) {
1027 var env/edi: (addr environment) <- copy _env
1028 var current-tab-index-addr/eax: (addr int) <- get env, current-tab-index
1029 increment *current-tab-index-addr
1030 var current-tab-index/ecx: int <- copy *current-tab-index-addr
1031 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1032 var tabs/eax: (addr array tab) <- lookup *tabs-ah
1033 var max-tabs/edx: int <- length tabs
1034 compare current-tab-index, max-tabs
1035 {
1036 compare current-tab-index, max-tabs
1037 break-if-<
1038 abort "history overflow; grow max-history (we should probably improve this)"
1039 }
1040 var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
1041 var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
1042 clear-object current-tab
1043 var current-tab-type/eax: (addr int) <- get current-tab, type
1044 copy-to *current-tab, 1/channel
1045 var current-tab-channel-index/eax: (addr int) <- get current-tab, channel-index
1046 var curr-channel-index/edx: int <- copy channel-index
1047 copy-to *current-tab-channel-index, curr-channel-index
1048 var channels/esi: (addr array channel) <- copy _channels
1049 var curr-channel-offset/eax: (offset channel) <- compute-offset channels, curr-channel-index
1050 var curr-channel/eax: (addr channel) <- index channels, curr-channel-offset
1051 var curr-channel-posts-first-free-addr/eax: (addr int) <- get curr-channel, posts-first-free
1052 var curr-channel-final-post-index/eax: int <- copy *curr-channel-posts-first-free-addr
1053 curr-channel-final-post-index <- decrement
1054 var dest/edi: (addr int) <- get current-tab, item-index
1055 copy-to *dest, curr-channel-final-post-index
1056 }
1057
1058 fn new-search-tab _env: (addr environment), items: (addr item-list) {
1059 var env/edi: (addr environment) <- copy _env
1060 var current-tab-index-addr/eax: (addr int) <- get env, current-tab-index
1061 increment *current-tab-index-addr
1062 var current-tab-index/ecx: int <- copy *current-tab-index-addr
1063 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1064 var tabs/eax: (addr array tab) <- lookup *tabs-ah
1065 var max-tabs/edx: int <- length tabs
1066 compare current-tab-index, max-tabs
1067 {
1068 compare current-tab-index, max-tabs
1069 break-if-<
1070 abort "history overflow; grow max-history (we should probably improve this)"
1071 }
1072 var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
1073 var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
1074 clear-object current-tab
1075 var current-tab-type/eax: (addr int) <- get current-tab, type
1076 copy-to *current-tab, 2/search
1077 var current-tab-search-terms-ah/edx: (addr handle gap-buffer) <- get current-tab, search-terms
1078 allocate current-tab-search-terms-ah
1079 var current-tab-search-terms/eax: (addr gap-buffer) <- lookup *current-tab-search-terms-ah
1080 initialize-gap-buffer current-tab-search-terms, 0x30/search-capacity
1081 var search-terms-ah/ebx: (addr handle gap-buffer) <- get env, search-terms
1082 copy-gap-buffer search-terms-ah, current-tab-search-terms-ah
1083 var search-terms/eax: (addr gap-buffer) <- lookup *search-terms-ah
1084 search-items current-tab, items, search-terms
1085 }
1086
1087 fn search-items _tab: (addr tab), _items: (addr item-list), search-terms: (addr gap-buffer) {
1088 var tab/edi: (addr tab) <- copy _tab
1089 var tab-items-first-free-addr/esi: (addr int) <- get tab, search-items-first-free
1090 var tab-items-ah/eax: (addr handle array int) <- get tab, search-items
1091 populate tab-items-ah, 0x100/max-search-results
1092 var _tab-items/eax: (addr array int) <- lookup *tab-items-ah
1093 var tab-items/edi: (addr array int) <- copy _tab-items
1094
1095 var search-terms-stream-storage: (stream byte 0x100)
1096 var search-terms-stream-addr/ecx: (addr stream byte) <- address search-terms-stream-storage
1097 emit-gap-buffer search-terms, search-terms-stream-addr
1098 var search-terms-text-h: (handle array byte)
1099 var search-terms-text-ah/eax: (addr handle array byte) <- address search-terms-text-h
1100 stream-to-array search-terms-stream-addr, search-terms-text-ah
1101 var tmp/eax: (addr array byte) <- lookup *search-terms-text-ah
1102 var search-terms-text: (addr array byte)
1103 copy-to search-terms-text, tmp
1104
1105 var items/ecx: (addr item-list) <- copy _items
1106 var items-data-ah/eax: (addr handle array item) <- get items, data
1107 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1108 var items-data/ebx: (addr array item) <- copy _items-data
1109 var items-data-first-free-a/edx: (addr int) <- get items, data-first-free
1110 var i/ecx: int <- copy 0
1111 {
1112 compare i, *items-data-first-free-a
1113 break-if->=
1114 var curr-offset/eax: (offset item) <- compute-offset items-data, i
1115 var curr-item/eax: (addr item) <- index items-data, curr-offset
1116 var found?/eax: boolean <- search-terms-match? curr-item, search-terms-text
1117 compare found?, 0/false
1118 {
1119 break-if-=
1120 var tab-items-first-free/eax: int <- copy *tab-items-first-free-addr
1121 compare tab-items-first-free, 0x100/max-search-results
1122 break-if->=
1123 var dest/eax: (addr int) <- index tab-items, tab-items-first-free
1124 copy-to *dest, i
1125 increment *tab-items-first-free-addr
1126 }
1127 i <- increment
1128 loop
1129 }
1130 var tab/edi: (addr tab) <- copy _tab
1131 var tab-item-index-addr/edi: (addr int) <- get tab, item-index
1132 var tab-items-first-free/eax: int <- copy *tab-items-first-free-addr
1133 tab-items-first-free <- decrement
1134 copy-to *tab-item-index-addr, tab-items-first-free
1135 }
1136
1137 fn search-terms-match? _item: (addr item), search-terms: (addr array byte) -> _/eax: boolean {
1138 var item/esi: (addr item) <- copy _item
1139 var item-text-ah/eax: (addr handle array byte) <- get item, text
1140 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1141 var i/ecx: int <- copy 0
1142 var max/edx: int <- length item-text
1143 var search-terms2/ebx: (addr array byte) <- copy search-terms
1144 var slen/ebx: int <- length search-terms2
1145 max <- subtract slen
1146 {
1147 compare i, max
1148 break-if->
1149 var found?/eax: boolean <- substring-match? item-text, search-terms, i
1150 compare found?, 0/false
1151 {
1152 break-if-=
1153 return 1/true
1154 }
1155 i <- increment
1156 loop
1157 }
1158 return 0/false
1159 }
1160
1161 fn substring-match? _s: (addr array byte), _pat: (addr array byte), start: int -> _/eax: boolean {
1162 var s/esi: (addr array byte) <- copy _s
1163 var pat/edi: (addr array byte) <- copy _pat
1164 var s-idx/edx: int <- copy start
1165 var pat-idx/ebx: int <- copy 0
1166 var pat-len: int
1167 var tmp/eax: int <- length pat
1168 copy-to pat-len, tmp
1169 {
1170 compare pat-idx, pat-len
1171 break-if->=
1172 var s-ab/eax: (addr byte) <- index s, s-idx
1173 var s-b/eax: byte <- copy-byte *s-ab
1174 var pat-ab/ecx: (addr byte) <- index pat, pat-idx
1175 var pat-b/ecx: byte <- copy-byte *pat-ab
1176 compare s-b, pat-b
1177 {
1178 break-if-=
1179 return 0/false
1180 }
1181 s-idx <- increment
1182 pat-idx <- increment
1183 loop
1184 }
1185 return 1/true
1186 }
1187
1188 fn previous-tab _env: (addr environment) {
1189 var env/edi: (addr environment) <- copy _env
1190 var current-tab-index-addr/ecx: (addr int) <- get env, current-tab-index
1191 compare *current-tab-index-addr, 0
1192 {
1193 break-if-<=
1194 decrement *current-tab-index-addr
1195
1196 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1197 var tabs/eax: (addr array tab) <- lookup *tabs-ah
1198 var current-tab-index/ecx: int <- copy *current-tab-index-addr
1199 var current-tab-offset/ecx: (offset tab) <- compute-offset tabs, current-tab-index
1200 var current-tab/ecx: (addr tab) <- index tabs, current-tab-offset
1201 var current-tab-type/eax: (addr int) <- get current-tab, type
1202 compare *current-tab-type, 2/search
1203 break-if-!=
1204 var current-tab-search-terms-ah/ecx: (addr handle gap-buffer) <- get current-tab, search-terms
1205 var search-terms-ah/edx: (addr handle gap-buffer) <- get env, search-terms
1206 var search-terms/eax: (addr gap-buffer) <- lookup *search-terms-ah
1207 clear-gap-buffer search-terms
1208 copy-gap-buffer current-tab-search-terms-ah, search-terms-ah
1209 }
1210 }
1211
1212 fn next-item _env: (addr environment), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1213 var env/edi: (addr environment) <- copy _env
1214 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1215 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
1216 var tabs/edx: (addr array tab) <- copy _tabs
1217 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
1218 var current-tab-index/eax: int <- copy *current-tab-index-a
1219 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
1220 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
1221 var dest/eax: (addr int) <- get current-tab, item-index
1222 compare *dest, 0
1223 break-if-<=
1224 decrement *dest
1225 }
1226
1227 fn previous-item _env: (addr environment), users: (addr array user), _channels: (addr array channel), _items: (addr item-list) {
1228 var env/edi: (addr environment) <- copy _env
1229 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1230 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
1231 var tabs/edx: (addr array tab) <- copy _tabs
1232 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
1233 var current-tab-index/eax: int <- copy *current-tab-index-a
1234 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
1235 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
1236 var current-tab-type/eax: (addr int) <- get current-tab, type
1237 compare *current-tab-type, 0/all-items
1238 {
1239 break-if-!=
1240 var items/esi: (addr item-list) <- copy _items
1241 var items-data-first-free-a/ecx: (addr int) <- get items, data-first-free
1242 var final-item-index/ecx: int <- copy *items-data-first-free-a
1243 final-item-index <- decrement
1244 var dest/eax: (addr int) <- get current-tab, item-index
1245 compare *dest, final-item-index
1246 break-if->=
1247 increment *dest
1248 return
1249 }
1250 compare *current-tab-type, 1/channel
1251 {
1252 break-if-!=
1253 var current-channel-index-addr/eax: (addr int) <- get current-tab, channel-index
1254 var current-channel-index/eax: int <- copy *current-channel-index-addr
1255 var channels/esi: (addr array channel) <- copy _channels
1256 var current-channel-offset/eax: (offset channel) <- compute-offset channels, current-channel-index
1257 var current-channel/eax: (addr channel) <- index channels, current-channel-offset
1258 var current-channel-posts-first-free-addr/eax: (addr int) <- get current-channel, posts-first-free
1259 var final-item-index/ecx: int <- copy *current-channel-posts-first-free-addr
1260 final-item-index <- decrement
1261 var dest/eax: (addr int) <- get current-tab, item-index
1262 compare *dest, final-item-index
1263 break-if->=
1264 increment *dest
1265 return
1266 }
1267 compare *current-tab-type, 2/search
1268 {
1269 break-if-!=
1270 var current-tab-search-items-first-free-addr/eax: (addr int) <- get current-tab, search-items-first-free
1271 var final-item-index/ecx: int <- copy *current-tab-search-items-first-free-addr
1272 final-item-index <- decrement
1273 var dest/eax: (addr int) <- get current-tab, item-index
1274 compare *dest, final-item-index
1275 break-if->=
1276 increment *dest
1277 return
1278 }
1279 compare *current-tab-type, 3/thread
1280 {
1281 break-if-!=
1282 var items/eax: (addr item-list) <- copy _items
1283 var items-data-ah/eax: (addr handle array item) <- get items, data
1284 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1285 var items-data/esi: (addr array item) <- copy _items-data
1286 var current-tab-root-index-addr/eax: (addr int) <- get current-tab, root-index
1287 var current-tab-root-index/eax: int <- copy *current-tab-root-index-addr
1288 var current-tab-root-offset/eax: (offset item) <- compute-offset items-data, current-tab-root-index
1289 var post/eax: (addr item) <- index items-data, current-tab-root-offset
1290 var post-comments-first-free-addr/ecx: (addr int) <- get post, comments-first-free
1291 var final-item-index/ecx: int <- copy *post-comments-first-free-addr
1292 final-item-index <- decrement
1293 var dest/eax: (addr int) <- get current-tab, item-index
1294 compare *dest, final-item-index
1295 break-if->=
1296 increment *dest
1297 return
1298 }
1299 }
1300
1301 fn page-down _env: (addr environment), users: (addr array user), channels: (addr array channel), items: (addr item-list) {
1302 var env/edi: (addr environment) <- copy _env
1303 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1304 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
1305 var tabs/ecx: (addr array tab) <- copy _tabs
1306 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
1307 var current-tab-index/eax: int <- copy *current-tab-index-a
1308 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
1309 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
1310 var current-tab-type/eax: (addr int) <- get current-tab, type
1311 compare *current-tab-type, 0/all-items
1312 {
1313 break-if-!=
1314 all-items-page-down current-tab, users, channels, items
1315 return
1316 }
1317 compare *current-tab-type, 1/channel
1318 {
1319 break-if-!=
1320 channel-page-down current-tab, users, channels, items
1321 return
1322 }
1323 compare *current-tab-type, 2/search
1324 {
1325 break-if-!=
1326 search-page-down current-tab, users, channels, items
1327 return
1328 }
1329 compare *current-tab-type, 3/thread
1330 {
1331 break-if-!=
1332 thread-page-down current-tab, users, channels, items
1333 return
1334 }
1335 }
1336
1337 fn all-items-page-down _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1338 var items/esi: (addr item-list) <- copy _items
1339 var items-data-ah/eax: (addr handle array item) <- get items, data
1340 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1341 var items-data/ebx: (addr array item) <- copy _items-data
1342 var current-tab/eax: (addr tab) <- copy _current-tab
1343 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1344 var new-item-index/ecx: int <- copy *current-tab-item-index-addr
1345 var y/edx: int <- copy 2
1346 {
1347 compare new-item-index, 0
1348 break-if-<
1349 compare y, 0x28/screen-height-minus-menu
1350 break-if->=
1351 var offset/eax: (offset item) <- compute-offset items-data, new-item-index
1352 var item/eax: (addr item) <- index items-data, offset
1353 var item-text-ah/eax: (addr handle array byte) <- get item, text
1354 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1355 var h/eax: int <- estimate-height item-text
1356 y <- add h
1357 new-item-index <- decrement
1358 loop
1359 }
1360 new-item-index <- increment
1361 {
1362
1363
1364
1365
1366 compare new-item-index, *current-tab-item-index-addr
1367 break-if-!=
1368
1369 compare new-item-index, 0
1370 break-if-=
1371 new-item-index <- decrement
1372 }
1373 copy-to *current-tab-item-index-addr, new-item-index
1374 }
1375
1376 fn channel-page-down _current-tab: (addr tab), users: (addr array user), _channels: (addr array channel), _items: (addr item-list) {
1377 var current-tab/edi: (addr tab) <- copy _current-tab
1378 var current-channel-index-addr/eax: (addr int) <- get current-tab, channel-index
1379 var current-channel-index/eax: int <- copy *current-channel-index-addr
1380 var channels/esi: (addr array channel) <- copy _channels
1381 var current-channel-offset/eax: (offset channel) <- compute-offset channels, current-channel-index
1382 var current-channel/esi: (addr channel) <- index channels, current-channel-offset
1383 var current-channel-posts-ah/eax: (addr handle array int) <- get current-channel, posts
1384 var _current-channel-posts/eax: (addr array int) <- lookup *current-channel-posts-ah
1385 var current-channel-posts/esi: (addr array int) <- copy _current-channel-posts
1386 var items/eax: (addr item-list) <- copy _items
1387 var items-data-ah/eax: (addr handle array item) <- get items, data
1388 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1389 var items-data/ebx: (addr array item) <- copy _items-data
1390 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1391 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1392 var y/edx: int <- copy 2
1393 {
1394 compare new-tab-item-index, 0
1395 break-if-<
1396 compare y, 0x28/screen-height-minus-menu
1397 break-if->=
1398 var current-item-index-addr/eax: (addr int) <- index current-channel-posts, new-tab-item-index
1399 var current-item-index/eax: int <- copy *current-item-index-addr
1400 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1401 var item/eax: (addr item) <- index items-data, offset
1402 var item-text-ah/eax: (addr handle array byte) <- get item, text
1403 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1404 var h/eax: int <- estimate-height item-text
1405 y <- add h
1406 new-tab-item-index <- decrement
1407 loop
1408 }
1409 new-tab-item-index <- increment
1410 {
1411
1412
1413
1414
1415 compare new-tab-item-index, *current-tab-item-index-addr
1416 break-if-!=
1417
1418 compare new-tab-item-index, 0
1419 break-if-=
1420 new-tab-item-index <- decrement
1421 }
1422 copy-to *current-tab-item-index-addr, new-tab-item-index
1423 }
1424
1425 fn search-page-down _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1426 var current-tab/edi: (addr tab) <- copy _current-tab
1427 var current-tab-search-items-ah/eax: (addr handle array int) <- get current-tab, search-items
1428 var _current-tab-search-items/eax: (addr array int) <- lookup *current-tab-search-items-ah
1429 var current-tab-search-items/esi: (addr array int) <- copy _current-tab-search-items
1430 var items/eax: (addr item-list) <- copy _items
1431 var items-data-ah/eax: (addr handle array item) <- get items, data
1432 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1433 var items-data/ebx: (addr array item) <- copy _items-data
1434 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1435 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1436 var y/edx: int <- copy 2
1437 {
1438 compare new-tab-item-index, 0
1439 break-if-<
1440 compare y, 0x28/screen-height-minus-menu
1441 break-if->=
1442 var current-item-index-addr/eax: (addr int) <- index current-tab-search-items, new-tab-item-index
1443 var current-item-index/eax: int <- copy *current-item-index-addr
1444 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1445 var item/eax: (addr item) <- index items-data, offset
1446 var item-text-ah/eax: (addr handle array byte) <- get item, text
1447 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1448 var h/eax: int <- estimate-height item-text
1449 y <- add h
1450 new-tab-item-index <- decrement
1451 loop
1452 }
1453 new-tab-item-index <- increment
1454 {
1455
1456
1457
1458
1459 compare new-tab-item-index, *current-tab-item-index-addr
1460 break-if-!=
1461
1462 compare new-tab-item-index, 0
1463 break-if-=
1464 new-tab-item-index <- decrement
1465 }
1466 copy-to *current-tab-item-index-addr, new-tab-item-index
1467 }
1468
1469 fn thread-page-down _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1470 var current-tab/edi: (addr tab) <- copy _current-tab
1471 var items/eax: (addr item-list) <- copy _items
1472 var items-data-ah/eax: (addr handle array item) <- get items, data
1473 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1474 var items-data/esi: (addr array item) <- copy _items-data
1475 var current-tab-root-index-addr/eax: (addr int) <- get current-tab, root-index
1476 var current-tab-root-index/eax: int <- copy *current-tab-root-index-addr
1477 var current-tab-root-offset/eax: (offset item) <- compute-offset items-data, current-tab-root-index
1478 var post/eax: (addr item) <- index items-data, current-tab-root-offset
1479 var post-comments-ah/eax: (addr handle array int) <- get post, comments
1480 var _post-comments/eax: (addr array int) <- lookup *post-comments-ah
1481 var post-comments/ebx: (addr array int) <- copy _post-comments
1482 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1483 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1484 var y/edx: int <- copy 2
1485 {
1486 compare new-tab-item-index, 0
1487 break-if-<
1488 compare y, 0x28/screen-height-minus-menu
1489 break-if->=
1490 var current-item-index-addr/eax: (addr int) <- index post-comments, new-tab-item-index
1491 var current-item-index/eax: int <- copy *current-item-index-addr
1492 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1493 var item/eax: (addr item) <- index items-data, offset
1494 var item-text-ah/eax: (addr handle array byte) <- get item, text
1495 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1496 var h/eax: int <- estimate-height item-text
1497 y <- add h
1498 new-tab-item-index <- decrement
1499 loop
1500 }
1501 new-tab-item-index <- increment
1502 {
1503
1504
1505
1506
1507 compare new-tab-item-index, *current-tab-item-index-addr
1508 break-if-!=
1509
1510 compare new-tab-item-index, 0
1511 break-if-=
1512 new-tab-item-index <- decrement
1513 }
1514 copy-to *current-tab-item-index-addr, new-tab-item-index
1515 }
1516
1517 fn page-up _env: (addr environment), users: (addr array user), channels: (addr array channel), items: (addr item-list) {
1518 var env/edi: (addr environment) <- copy _env
1519 var tabs-ah/eax: (addr handle array tab) <- get env, tabs
1520 var _tabs/eax: (addr array tab) <- lookup *tabs-ah
1521 var tabs/ecx: (addr array tab) <- copy _tabs
1522 var current-tab-index-a/eax: (addr int) <- get env, current-tab-index
1523 var current-tab-index/eax: int <- copy *current-tab-index-a
1524 var current-tab-offset/eax: (offset tab) <- compute-offset tabs, current-tab-index
1525 var current-tab/edx: (addr tab) <- index tabs, current-tab-offset
1526 var current-tab-type/eax: (addr int) <- get current-tab, type
1527 compare *current-tab-type, 0/all-items
1528 {
1529 break-if-!=
1530 all-items-page-up current-tab, users, channels, items
1531 return
1532 }
1533 compare *current-tab-type, 1/channel
1534 {
1535 break-if-!=
1536 channel-page-up current-tab, users, channels, items
1537 return
1538 }
1539 compare *current-tab-type, 2/search
1540 {
1541 break-if-!=
1542 search-page-up current-tab, users, channels, items
1543 return
1544 }
1545 compare *current-tab-type, 3/thread
1546 {
1547 break-if-!=
1548 thread-page-up current-tab, users, channels, items
1549 return
1550 }
1551 }
1552
1553 fn all-items-page-up _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1554 var items/esi: (addr item-list) <- copy _items
1555 var items-data-ah/eax: (addr handle array item) <- get items, data
1556 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1557 var items-data/ebx: (addr array item) <- copy _items-data
1558 var items-data-first-free-a/eax: (addr int) <- get items, data-first-free
1559 var final-item-index/esi: int <- copy *items-data-first-free-a
1560 final-item-index <- decrement
1561 var current-tab/eax: (addr tab) <- copy _current-tab
1562 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1563 var new-item-index/ecx: int <- copy *current-tab-item-index-addr
1564 var y/edx: int <- copy 2
1565 {
1566 compare new-item-index, final-item-index
1567 break-if->
1568 compare y, 0x28/screen-height-minus-menu
1569 break-if->=
1570 var offset/eax: (offset item) <- compute-offset items-data, new-item-index
1571 var item/eax: (addr item) <- index items-data, offset
1572 var item-text-ah/eax: (addr handle array byte) <- get item, text
1573 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1574 var h/eax: int <- estimate-height item-text
1575 y <- add h
1576 new-item-index <- increment
1577 loop
1578 }
1579 new-item-index <- decrement
1580 copy-to *current-tab-item-index-addr, new-item-index
1581 }
1582
1583 fn channel-page-up _current-tab: (addr tab), users: (addr array user), _channels: (addr array channel), _items: (addr item-list) {
1584 var current-tab/edi: (addr tab) <- copy _current-tab
1585 var current-channel-index-addr/eax: (addr int) <- get current-tab, channel-index
1586 var current-channel-index/eax: int <- copy *current-channel-index-addr
1587 var channels/esi: (addr array channel) <- copy _channels
1588 var current-channel-offset/eax: (offset channel) <- compute-offset channels, current-channel-index
1589 var current-channel/esi: (addr channel) <- index channels, current-channel-offset
1590 var current-channel-posts-first-free-addr/eax: (addr int) <- get current-channel, posts-first-free
1591 var tmp/eax: int <- copy *current-channel-posts-first-free-addr
1592 var final-tab-post-index: int
1593 copy-to final-tab-post-index, tmp
1594 decrement final-tab-post-index
1595 var current-channel-posts-ah/eax: (addr handle array int) <- get current-channel, posts
1596 var _current-channel-posts/eax: (addr array int) <- lookup *current-channel-posts-ah
1597 var current-channel-posts/esi: (addr array int) <- copy _current-channel-posts
1598 var items/esi: (addr item-list) <- copy _items
1599 var items-data-ah/eax: (addr handle array item) <- get items, data
1600 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1601 var items-data/ebx: (addr array item) <- copy _items-data
1602 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1603 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1604 var y/edx: int <- copy 2
1605 {
1606 compare new-tab-item-index, final-tab-post-index
1607 break-if->
1608 compare y, 0x28/screen-height-minus-menu
1609 break-if->=
1610 var offset/eax: (offset item) <- compute-offset items-data, new-tab-item-index
1611 var item/eax: (addr item) <- index items-data, offset
1612 var item-text-ah/eax: (addr handle array byte) <- get item, text
1613 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1614 var h/eax: int <- estimate-height item-text
1615 y <- add h
1616 new-tab-item-index <- increment
1617 loop
1618 }
1619 new-tab-item-index <- decrement
1620 copy-to *current-tab-item-index-addr, new-tab-item-index
1621 }
1622
1623 fn search-page-up _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1624 var current-tab/edi: (addr tab) <- copy _current-tab
1625 var current-tab-search-items-first-free-addr/eax: (addr int) <- get current-tab, search-items-first-free
1626 var final-tab-post-index: int
1627 var tmp/eax: int <- copy *current-tab-search-items-first-free-addr
1628 copy-to final-tab-post-index, tmp
1629 decrement final-tab-post-index
1630 var current-tab-search-items-ah/eax: (addr handle array int) <- get current-tab, search-items
1631 var _current-tab-search-items/eax: (addr array int) <- lookup *current-tab-search-items-ah
1632 var current-tab-search-items/esi: (addr array int) <- copy _current-tab-search-items
1633 var items/eax: (addr item-list) <- copy _items
1634 var items-data-ah/eax: (addr handle array item) <- get items, data
1635 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1636 var items-data/ebx: (addr array item) <- copy _items-data
1637 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1638 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1639 var y/edx: int <- copy 2
1640 {
1641 compare new-tab-item-index, final-tab-post-index
1642 break-if->
1643 compare y, 0x28/screen-height-minus-menu
1644 break-if->=
1645 var current-item-index-addr/eax: (addr int) <- index current-tab-search-items, new-tab-item-index
1646 var current-item-index/eax: int <- copy *current-item-index-addr
1647 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1648 var item/eax: (addr item) <- index items-data, offset
1649 var item-text-ah/eax: (addr handle array byte) <- get item, text
1650 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1651 var h/eax: int <- estimate-height item-text
1652 y <- add h
1653 new-tab-item-index <- increment
1654 loop
1655 }
1656 new-tab-item-index <- decrement
1657 copy-to *current-tab-item-index-addr, new-tab-item-index
1658 }
1659
1660 fn thread-page-up _current-tab: (addr tab), users: (addr array user), channels: (addr array channel), _items: (addr item-list) {
1661 var current-tab/edi: (addr tab) <- copy _current-tab
1662 var items/eax: (addr item-list) <- copy _items
1663 var items-data-ah/eax: (addr handle array item) <- get items, data
1664 var _items-data/eax: (addr array item) <- lookup *items-data-ah
1665 var items-data/esi: (addr array item) <- copy _items-data
1666 var current-tab-root-index-addr/eax: (addr int) <- get current-tab, root-index
1667 var current-tab-root-index/eax: int <- copy *current-tab-root-index-addr
1668 var current-tab-root-offset/eax: (offset item) <- compute-offset items-data, current-tab-root-index
1669 var post/eax: (addr item) <- index items-data, current-tab-root-offset
1670 var post-comments-first-free-addr/ecx: (addr int) <- get post, comments-first-free
1671 var post-comments-ah/eax: (addr handle array int) <- get post, comments
1672 var _post-comments/eax: (addr array int) <- lookup *post-comments-ah
1673 var post-comments/ebx: (addr array int) <- copy _post-comments
1674 var final-tab-comment-index: int
1675 {
1676 var tmp/eax: int <- copy *post-comments-first-free-addr
1677 tmp <- decrement
1678 copy-to final-tab-comment-index, tmp
1679 }
1680 var current-tab-item-index-addr/edi: (addr int) <- get current-tab, item-index
1681 var new-tab-item-index/ecx: int <- copy *current-tab-item-index-addr
1682 var y/edx: int <- copy 2
1683 {
1684 compare new-tab-item-index, final-tab-comment-index
1685 break-if->
1686 compare y, 0x28/screen-height-minus-menu
1687 break-if->=
1688 var current-item-index-addr/eax: (addr int) <- index post-comments, new-tab-item-index
1689 var current-item-index/eax: int <- copy *current-item-index-addr
1690 var offset/eax: (offset item) <- compute-offset items-data, current-item-index
1691 var item/eax: (addr item) <- index items-data, offset
1692 var item-text-ah/eax: (addr handle array byte) <- get item, text
1693 var item-text/eax: (addr array byte) <- lookup *item-text-ah
1694 var h/eax: int <- estimate-height item-text
1695 y <- add h
1696 new-tab-item-index <- increment
1697 loop
1698 }
1699 new-tab-item-index <- decrement
1700 copy-to *current-tab-item-index-addr, new-tab-item-index
1701 }
1702
1703
1704 fn estimate-height _message-text: (addr array byte) -> _/eax: int {
1705 var message-text/esi: (addr array byte) <- copy _message-text
1706 var result/eax: int <- length message-text
1707 var remainder/edx: int <- copy 0
1708 result, remainder <- integer-divide result, 0x40/post-width
1709 compare remainder, 0
1710 {
1711 break-if-=
1712 result <- increment
1713 }
1714 result <- add 2/item-padding-ver
1715 compare result, 6/avatar-space-ver
1716 {
1717 break-if->
1718 return 6/avatar-space-ver
1719 }
1720 return result
1721 }