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