( taro-ls: list mail, navigate mailboxes, and perform actions on mail ) ( message types ) %MBOX_LIST { #00 } %GET_MBOX { #01 } %MAIL_LIST { #02 } %MARK_ALL_READ { #03 } %SEARCH_MAIL { #05 } %REFILE_MAIL { #07 } %TRASH_MAIL { #09 } %READ_MAIL { #0b } %COMPOSE_MAIL { #0d } %UPDATE_UI { #0f } ( UI constants ) %TOP_SECTION { #0040 } %MID_SEPARATOR { #0008 } %BOTTOM_SECTION { #0040 } ( listbox helper macros ) %LB_DATA { #02 ADD } %LB_LEN { #04 ADD } %LB_OFFSET { #06 ADD } %LB_ELEM_OFFSET { #08 ADD } %LB_TOP { #09 ADD } %LB_HEIGHT { #0b ADD } %LB_SELECT_IDX { #0c ADD } %LB_SELECT_LEN { #0e ADD } %SB_LEN { #10 ADD } %SB_POS { #11 ADD } %SB_STEP { #13 ADD } ( entry modes ) %ENTRY_OFF { #00 } %ENTRY_REFILE { #01 } %ENTRY_SEARCH { #02 } |00 @System &vector $2 &wst $1 &rst $1 &eaddr $2 &ecode $1 &pad $1 &r $2 &g $2 &b $2 &debug $1 &halt $1 |10 @Console &vector $2 &read $1 &pad $5 &write $1 &error $1 |20 @Screen &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 |30 @Audio0 &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 |40 @Audio1 &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 |50 @Audio2 &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 |60 @Audio3 &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 |80 @Controller &vector $2 &button $1 &key $1 &func $1 |90 @Mouse &vector $2 &x $2 &y $2 &state $1 &pad $3 &scrollx $2 &scrolly $2 |a0 @File0 &vector $2 &success $2 &stat $2 &delete $1 &append $1 &name $2 &length $2 &read $2 &write $2 |b0 @File1 &vector $2 &success $2 &stat $2 &delete $1 &append $1 &name $2 &length $2 &read $2 &write $2 |c0 @DateTime &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ( variables ) |0000 @refresh [ &mboxes $1 &list $1 &fg $1 &btns $1 &textbox $1 &etc $1 ] @resizing [ $1 &x $2 &y $2 &dx $2 &dy $2 ] @decoding [ $1 &msg_type $1 &counting $1 &count $1 &count2 $1 &processed $2 ] @textbox [ &mode $1 &len $1 &cursor $1 &msg $2 &searching $1 ] @mboxes [ &bytes $2 &data $2 &len $2 &offset $2 &elem_offset $1 &top $2 &height $1 &select_index $2 &select_len $2 &sb_len $1 &sb_pos $2 &sb_step $2 ] @list [ &bytes $2 &data $2 &len $2 &offset $2 &elem_offset $1 &top $2 &height $1 &select_index $2 &select_len $2 &sb_len $1 &sb_pos $2 &sb_step $2 ] @btn_colors [ &compose $1 &refresh $1 &read_all $1 &search $1 &refile $1 &trash $1 ] @btn_fns [ &compose $2 &refresh $2 &read_all $2 &search $2 &refile $2 &trash $2 ] ( program ) |0100 ( -> ) ;metadata #06 DEO2 ( default theme ) #028d .System/r DEO2 #0a8d .System/g DEO2 #098d .System/b DEO2 load_theme load_font #0280 .Screen/width DEO2 #01c0 .Screen/height DEO2 ;list_data .list/data STZ2 ;mbox_data .mboxes/data STZ2 #0001 .list/select_len STZ2 #0001 .mboxes/select_len STZ2 .Screen/height DEI2 TOP_SECTION BOTTOM_SECTION ADD2 MID_SEPARATOR ADD2 SUB2 #03 SFT2 NIP .list/height STZ TOP_SECTION #03 SFT2 NIP .mboxes/height STZ #01 .refresh/btns STZ #01 .refresh/fg STZ #01 .refresh/etc STZ #03 .btn_colors/compose STZ #03 .btn_colors/refresh STZ #03 .btn_colors/read_all STZ #03 .btn_colors/search STZ #03 .btn_colors/refile STZ #03 .btn_colors/trash STZ ;send_compose .btn_fns/compose STZ2 ;send_get_mbox .btn_fns/refresh STZ2 ;send_mark_all_read .btn_fns/read_all STZ2 ;enter_search_mode .btn_fns/search STZ2 ;enter_refile_mode .btn_fns/refile STZ2 ;send_trash .btn_fns/trash STZ2 ;on_screen .Screen/vector DEO2 ;on_mouse .Mouse/vector DEO2 ;on_stdin .Console/vector DEO2 ;on_key .Controller/vector DEO2 BRK ( -== message in ==- ) @on_stdin ( -> ) .decoding LDZ #01 EQU ,&must_decode JCN #01 .decoding STZ #01 .decoding/counting STZ .Console/read DEI .decoding/msg_type STZ BRK &must_decode .decoding/counting LDZ #01 EQU ,&count_1 JCN .decoding/counting LDZ #02 EQU ,&count_2 JCN ( decode data ) .Console/read DEI .decoding/msg_type LDZ DUP MBOX_LIST NEQ ,&no_mbox_list JCN POP ;mbox_data .decoding/processed LDZ2 ADD2 STA decode_inc_count .mboxes/bytes STZ2 ,&count JMP &no_mbox_list DUP MAIL_LIST NEQ ,&no_mail_list JCN POP ;list_data .decoding/processed LDZ2 ADD2 STA decode_inc_count .list/bytes STZ2 ,&count JMP &no_mail_list POP &count decode_is_done ,&done JCN BRK &done #0000 DUP2 .decoding/count STZ2 .decoding/processed STZ2 #00 .decoding STZ BRK &count_1 .Console/read DEI .decoding/count STZ #02 .decoding/counting STZ BRK &count_2 .Console/read DEI .decoding/count2 STZ #00 .decoding/counting STZ ( handle empty payload ) .decoding/count LDZ2 #0000 NEQ2 ,&has_data JCN .decoding/msg_type LDZ DUP MBOX_LIST NEQ ,&no_mbox_empty JCN POP #0000 .mboxes/bytes STZ2 decode_is_done POP ,&done JMP &no_mbox_empty DUP MAIL_LIST NEQ ,&no_mail_empty JCN POP #0000 .list/bytes STZ2 decode_is_done POP ,&done JMP &no_mail_empty POP &has_data BRK @decode_inc_count ( -- current* ) .decoding/processed LDZ2 INC2 DUP2 .decoding/processed STZ2 JMP2r @decode_is_done ( -- bit ) .decoding/processed LDZ2 .decoding/count LDZ2 EQU2 DUP ,&refresh_ui JCN JMP2r &refresh_ui .list/bytes LDZ2 .decoding/count LDZ2 NEQ2 ,&no_list JCN #01 .refresh/list STZ &no_list .mboxes/bytes LDZ2 .decoding/count LDZ2 NEQ2 ,&no_mbox JCN #01 .refresh/mboxes STZ &no_mbox JMP2r ( -== message out ==- ) @send_get_mbox ( -- ) #01 .Console/write DEO ;selected_mbox strlen SWP .Console/write DEO .Console/write DEO ;selected_mbox send_str #0000 .list/select_index STZ2 #0001 .list/select_len STZ2 #0000 .list/top STZ2 .list update_sb_pos #00 .textbox/searching STZ #01 .refresh/etc STZ JMP2r @send_mark_all_read ( -- ) MARK_ALL_READ .Console/write DEO #00 .Console/write DEOk DEO ( message size is 0, no payload ) JMP2r @send_search ( -- ) SEARCH_MAIL .Console/write DEO ;textbox_text strlen SWP .Console/write DEO .Console/write DEO ;textbox_text send_str #01 .textbox/searching STZ #01 .refresh/etc STZ JMP2r @send_refile ( -- ) REFILE_MAIL .Console/write DEO #0004 ;textbox_text strlen ADD2 SWP .Console/write DEO .Console/write DEO .list selection_to_range SWP .Console/write DEO .Console/write DEO SWP .Console/write DEO .Console/write DEO ;textbox_text send_str JMP2r @send_trash ( -- ) TRASH_MAIL .Console/write DEO #0004 SWP .Console/write DEO .Console/write DEO .list selection_to_range SWP .Console/write DEO .Console/write DEO SWP .Console/write DEO .Console/write DEO JMP2r @send_reader ( -- ) ( reset the mouse state since if a window opens over the uxn window mid-click and steals focus, the click never releases until we click the button again ) #00 .Mouse/state DEO READ_MAIL .Console/write DEO #0002 SWP .Console/write DEO .Console/write DEO .list LB_SELECT_IDX LDZ2 INC2 SWP .Console/write DEO .Console/write DEO JMP2r @send_compose ( -- ) ( reset the mouse state since if a window opens over the uxn window mid-click and steals focus, the click never releases until we click the button again ) #00 .Mouse/state DEO COMPOSE_MAIL .Console/write DEO #00 .Console/write DEOk DEO ( message size is 0, no payload ) JMP2r @send_str ( str* -- ) &while LDAk .Console/write DEO INC2 LDAk ,&while JCN POP2 JMP2r @selection_to_range ( listbox -- end* start* ) DUP LB_SELECT_IDX LDZ2 INC2 STH2 LB_SELECT_LEN LDZ2 #0001 SUB2 STH2kr ADD2 STH2r JMP2r ( -== input ==- ) @on_key ( -> ) .textbox/mode LDZ #00 EQU ,&no_text_entry JCN handle_textbox BRK &no_text_entry ( check keys for shortcuts ) .Controller/key DEI DUP #7f NEQ ,&no_del JCN send_trash &no_del DUP #2f NEQ ,&no_search JCN enter_search_mode &no_search DUP #72 NEQ ,&no_refresh JCN send_get_mbox &no_refresh DUP #6d NEQ ,&no_refile JCN enter_refile_mode &no_refile DUP #6e NEQ ,&no_compose JCN send_compose &no_compose DUP #2e NEQ ,&no_all_read JCN send_mark_all_read &no_all_read DUP #0d NEQ ,&no_reader JCN send_reader &no_reader DUP #09 NEQ ,&no_tab JCN ;mbox_select_handler .mboxes [ .Controller/button DEI #04 AND ] nav_list_by_key &no_tab POP ( check buttons (LRUD, tab, shift, alt) for shortcuts ) .Controller/button DEI DUP #10 NEQ ,&no_up JCN ;noop_list_click .list #01 nav_list_by_key &no_up DUP #20 NEQ ,&no_down JCN ;noop_list_click .list #00 nav_list_by_key &no_down DUP #14 NEQ ,&no_select_up JCN #01 change_select_len_by_key #01 .refresh/list STZ &no_select_up DUP #24 NEQ ,&no_select_down JCN #00 change_select_len_by_key #01 .refresh/list STZ &no_select_down DUP #12 NEQ ,&no_dec_y JCN #10 resize_by_keyboard &no_dec_y DUP #22 NEQ ,&no_inc_y JCN #20 resize_by_keyboard &no_inc_y DUP #42 NEQ ,&no_dec_x JCN #40 resize_by_keyboard &no_dec_x DUP #82 NEQ ,&no_inc_x JCN #80 resize_by_keyboard &no_inc_x POP BRK @resize_by_keyboard ( dir -- ) DUP #10 NEQ ,&no_up JCN .Screen/height DEI2 #0100 EQU2 ,&no_down JCN .Screen/height DEI2 #0008 SUB2 .Screen/height DEO2 &no_up DUP #20 NEQ ,&no_down JCN .Screen/height DEI2 #0008 ADD2 .Screen/height DEO2 &no_down DUP #40 NEQ ,&no_left JCN .Screen/width DEI2 #0100 EQU2 ,&no_down JCN .Screen/width DEI2 #0008 SUB2 .Screen/width DEO2 &no_left DUP #80 NEQ ,&no_right JCN .Screen/width DEI2 #0008 ADD2 .Screen/width DEO2 &no_right POP #01 .refresh/list STZ #01 .refresh/mboxes STZ #01 .refresh/textbox STZ #01 .refresh/btns STZ #01 .refresh/etc STZ #01 .refresh/fg STZ JMP2r @change_select_len_by_key ( up? -- ) ,&back JCN ( fwd ) .list/select_index LDZ2 .list/select_len LDZ2 ADD2 .list/len LDZ2 LTH2 ,&inc_sel_len JCN JMP2r &inc_sel_len .list/select_len LDZ2 INC2 .list/select_len STZ2 .list/top LDZ2 #00 .list/height LDZ ADD2 .list/select_index LDZ2 .list/select_len LDZ2 ADD2 LTH2 ,&scroll_down JCN JMP2r &scroll_down .list/top LDZ2 INC2 .list/top STZ2 JMP2r &back .list/select_len LDZ2 #0001 GTH2 ,&dec_sel_len JCN JMP2r &dec_sel_len .list/select_len LDZ2 #0001 SUB2 .list/select_len STZ2 .list/top LDZ2 INC2 .list/select_index LDZ2 .list/select_len LDZ2 ADD2 GTH2 ,&scroll_up JCN JMP2r &scroll_up .list/top LDZ2 #0001 SUB2 .list/top STZ2 JMP2r @nav_list_by_key ( onchange* list up? -- ) ,&back JCN ( fwd ) STHk LB_SELECT_IDX LDZ2 INC2 STHkr LB_LEN LDZ2 NEQ2 ,&can_go_fwd JCN ( jump to first ) #0000 STHkr LB_SELECT_IDX STZ2 #0000 STHkr LB_TOP STZ2 ,&no_scroll_down JMP &can_go_fwd STHkr LB_SELECT_IDX LDZ2 INC2 STHkr LB_SELECT_IDX STZ2 STHkr LB_SELECT_IDX LDZ2 #00 STHkr LB_HEIGHT LDZ STHkr LB_TOP LDZ2 ADD2 LTH2 ,&no_scroll_down JCN STHkr LB_TOP LDZ2 INC2 STHkr LB_TOP STZ2 &no_scroll_down ,&end JMP &back STHk LB_SELECT_IDX LDZ2 #0000 NEQ2 ,&can_go_back JCN STHkr LB_LEN LDZ2 #0001 SUB2 STHkr LB_SELECT_IDX STZ2 ( if number of entries is less than height, don't scroll to bottom ) STHkr LB_LEN LDZ2 #0001 SUB2 #00 STHkr LB_HEIGHT LDZ LTH2 ,&end JCN STHkr LB_LEN LDZ2 #00 STHkr LB_HEIGHT LDZ SUB2 STHkr LB_TOP STZ2 ,&end JMP &can_go_back STHkr LB_SELECT_IDX LDZ2 #0001 SUB2 STHkr LB_SELECT_IDX STZ2 STHkr LB_SELECT_IDX LDZ2 INC2 STHkr LB_TOP LDZ2 GTH2 ,&no_scroll_up JCN STHkr LB_TOP LDZ2 #0001 SUB2 STHkr LB_TOP STZ2 &no_scroll_up &end STHrk update_sb_pos ( onchange ) STHr ROT ROT JSR2 #01 .refresh/mboxes STZ #01 .refresh/list STZ JMP2r @handle_textbox ( -- ) .Controller/key DEI DUP #00 EQU ,&no_key JCN DUP check_enter_or_esc #01 EQU ,&no_btn JCN DUP #08 NEQ ,&no_delete JCN POP ( handle backspace ) .textbox/cursor LDZ #00 EQU ,&done JCN delete_char ,&done JMP &no_delete ( ascii printable chars only ) DUP #20 LTH OVR #7e GTH ORA ,&no_btn JCN .textbox/len LDZ #fe EQU ,&no_btn JCN insert_char ,&done JMP &no_key POP .Controller/button DEI DUP #00 EQU ,&no_btn JCN DUP #40 AND #00 EQU ,&no_left JCN .textbox/cursor LDZ #00 EQU ,&no_btn JCN .textbox/cursor LDZ #01 SUB .textbox/cursor STZ &no_left DUP #80 AND #00 EQU ,&no_right JCN .textbox/cursor LDZ .textbox/len LDZ EQU ,&no_btn JCN .textbox/cursor LDZk INC SWP STZ &no_right &no_btn POP &done #01 .refresh/textbox STZ JMP2r @delete_char ( -- ) ( if cursor = len, then just decrement both and add null byte ) .textbox/cursor LDZ .textbox/len LDZ NEQ ,&its_complicated JCN .textbox/cursor LDZ #01 SUB .textbox/cursor STZ .textbox/len LDZ #01 SUB .textbox/len STZ #00 ;textbox_text #00 .textbox/cursor LDZ ADD2 STA JMP2r &its_complicated ( otherwise loop through characters from cursor to len, and copy them to their location - 1 ) .textbox/len LDZ INC .textbox/cursor LDZ &loop EQUk ,&end JCN #00 OVR ;textbox_text ADD2 LDA STH DUP #01 SUB STHr SWP #00 SWP ;textbox_text ADD2 STA INC ,&loop JMP &end POP2 ( and then decrement counters and set the null byte ) .textbox/cursor LDZ #01 SUB .textbox/cursor STZ .textbox/len LDZ #01 SUB .textbox/len STZ #00 ;textbox_text #00 .textbox/len LDZ ADD2 STA JMP2r @insert_char ( key -- ) STH ( if cursor = len, then add the charater, increment both counters, and add a null byte ) .textbox/cursor LDZ .textbox/len LDZ NEQ ,&its_complicated JCN STHr ;textbox_text #00 .textbox/cursor LDZ ADD2 STA .textbox/len LDZk INC SWP STZ #00 ;textbox_text #00 .textbox/len LDZ ADD2 STA .textbox/cursor LDZk INC SWP STZ JMP2r &its_complicated ( otherwise loop through characters from len to cursor, and copy them to their location + 1 ) .textbox/cursor LDZ #01 SUB .textbox/len LDZ &loop EQUk ,&end JCN #00 OVR ;textbox_text ADD2 LDA STH DUP INC STHr SWP #00 SWP ;textbox_text ADD2 STA #01 SUB ,&loop JMP &end POP2 STHr ( and put the character at the cursor locaton, then increment the counts ) ;textbox_text #00 .textbox/cursor LDZ ADD2 STA .textbox/len LDZk INC SWP STZ .textbox/cursor LDZk INC SWP STZ JMP2r @check_enter_or_esc ( key -- bit ) DUP #0d NEQ ,&no_enter JCN .textbox/mode LDZ ENTRY_SEARCH NEQ ,&no_search JCN send_search &no_search .textbox/mode LDZ ENTRY_REFILE NEQ ,&no_refile JCN send_refile &no_refile ENTRY_OFF reset_textbox #01 .refresh/textbox STZ #01 ,&done JMP &no_enter DUP #1b NEQ ,&no_esc JCN ENTRY_OFF reset_textbox #01 .refresh/textbox STZ #01 ,&done JMP &no_esc #00 &done NIP JMP2r @on_mouse ( -> ) ;noop_list_click ;mbox_select_handler .mboxes .refresh/mboxes #0000 #00 mouse_event_list ;right_click_mail_list ;noop_list_click .list .refresh/list TOP_SECTION MID_SEPARATOR ADD2 #04 mouse_event_list .btn_fns .btn_colors SUB mouse_event_buttons .resizing LDZ #00 EQU ,&resz_check JCN ( resizing ) .Mouse/x DEI2 .resizing/x LDZ2 SUB2 .resizing/dx STZ2 .Mouse/y DEI2 .resizing/y LDZ2 SUB2 .resizing/dy STZ2 handle_rsz #01 AND ,&done JCN ( btn1 release ) #00 .resizing STZ BRK &resz_check .Mouse/x DEI2 .Screen/width DEI2 #0008 SUB2 LTH2 ,&done JCN .Mouse/y DEI2 .Screen/height DEI2 #0008 SUB2 LTH2 ,&done JCN .Mouse/state DEI #01 EOR ,&done JCN #01 .resizing STZ .Mouse/x DEI2 .resizing/x STZ2 .Mouse/y DEI2 .resizing/y STZ2 &done #01 .refresh/fg STZ BRK @mouse_event_buttons ( numbtns -- ) STHk #00 &while EQUk ,&end JCN DUP .btn_colors ADD DUP LDZ #01 NEQ ,&continue JCN #01 .refresh/btns STZ &continue #03 SWP STZ INC ,&while JMP &end POP2 .Mouse/x DEI2 #0008 LTH2 ,&done JCN .Mouse/x DEI2 #0008 SUB2 [ #00 STHkr #40 SFT2 #0001 SUB2 ] GTH2 ,&done JCN .Mouse/y DEI2 .Screen/height DEI2 #0030 SUB2 LTH2 ,&done JCN .Mouse/y DEI2 .Screen/height DEI2 #0020 SUB2 GTH2 ,&done JCN #01 [ .Mouse/x DEI2 #0008 SUB2 #04 SFT2 NIP ] .btn_colors ADD STZ #01 .refresh/btns STZ .Mouse/state DEI #01 AND #00 EQU ,&done JCN .Mouse/x DEI2 #0008 SUB2 #04 SFT2 NIP #10 SFT .btn_fns ADD LDZ2 JSR2 &done POPr JMP2r @handle_rsz ( -- mousestate ) ( chk_x_rsz ) .Mouse/x DEI2 .Screen/width DEI2 #0002 SUB2 GTH2 ,&inc_x JCN #ffff .resizing/dx LDZ2 SUB2 #0008 GTH2 ,&dec_x JCN ,&chk_y_rsz JMP &dec_x .Screen/width DEI2 #0100 LTH2 ,&chk_y_rsz JCN .Screen/width DEI2 #0008 SUB2 .Screen/width DEO2 ,&chk_y_rsz JMP &inc_x .Screen/width DEI2 #0008 ADD2 .Screen/width DEO2 ,&chk_y_rsz JMP &chk_y_rsz .Mouse/y DEI2 .Screen/height DEI2 #0002 SUB2 GTH2 ,&inc_y JCN #ffff .resizing/dy LDZ2 SUB2 #0008 GTH2 ,&dec_y JCN ,&chk_release JMP &dec_y .Screen/height DEI2 #0100 LTH2 ,&chk_release JCN .Screen/height DEI2 #0008 SUB2 .Screen/height DEO2 ,&chk_release JMP &inc_y .Screen/height DEI2 #0008 ADD2 .Screen/height DEO2 ,&chk_release JMP &chk_release #01 .refresh/list STZ #01 .refresh/mboxes STZ #01 .refresh/btns STZ #01 .refresh/etc STZ .Screen/height DEI2 TOP_SECTION BOTTOM_SECTION ADD2 MID_SEPARATOR ADD2 SUB2 #03 SFT2 NIP .list/height STZ .Mouse/state DEI JMP2r @mouse_event_list ( rightclickhanlder* clickhandler* list refresh ypos* multiselect_mask -- ) ,&multi STR ,&y STR2 ,&r STR STH ( check bounds ) .Mouse/x DEI2 .Screen/width DEI2 #0008 SUB2 GTH2 ,&almost_done JCN .Mouse/y DEI2 ,&y LDR2 LTH2 ,&almost_done JCN .Mouse/y DEI2 [ [ ,&y LDR2 ] [ #00 STHkr LB_HEIGHT LDZ #30 SFT2 ] ADD2 #0001 SUB2 ] GTH2 ,&almost_done JCN .Mouse/y DEI2 [ [ ,&y LDR2 ] [ STHkr LB_LEN LDZ2 #30 SFT2 ] ADD2 #0001 SUB2 ] GTH2 ,&almost_done JCN ( check scrollwheel ) .Mouse/scrolly DEI2 #0000 EQU2 ,&no_scroll JCN .Mouse/scrolly DEI2 #0001 EQU2 ,&scroll_down JCN ( scroll_up ) STHkr try_scroll_up_mouse ,&no_scroll JMP &almost_done ,&done JMP ( data ) &multi $1 &y $2 &r $1 &scroll_down STHkr try_scroll_down_mouse &no_scroll .Mouse/state DEI #05 AND #00 EQU ,&done JCN ,&multi LDR ,&y LDR2 STHkr mouse_select_on_click .Mouse/state DEI #01 AND #00 EQU ,&no_left JCN ( leftclick ) STHr ROT ROT JSR2 POP2 #01 ,&r LDR STZ JMP2r &no_left .Mouse/state DEI #04 AND #00 EQU ,&no_right JCN ( rightclick ) STHr POP2 ROT ROT JSR2 #01 ,&r LDR STZ JMP2r &no_right &done #01 ,&r LDR STZ POPr POP2 POP2 JMP2r @mouse_select_on_click ( multi? ypos* list -- ) STH ,&y STR2 .Controller/button DEI #04 AND AND ,&multiselect JCN #0001 STHkr LB_SELECT_LEN STZ2 .Mouse/y DEI2 ,&y LDR2 SUB2 #03 SFT2 STHkr LB_TOP LDZ2 ADD2 STHkr LB_SELECT_IDX STZ2 POPr JMP2r &multiselect .Mouse/y DEI2 ,&y LDR2 SUB2 #03 SFT2 STHkr LB_TOP LDZ2 ADD2 DUP2 STHkr LB_SELECT_IDX LDZ2 LTH2 ,&last_to_first JCN ( first_to_last ) STHkr LB_SELECT_IDX LDZ2 SUB2 INC2 STHkr LB_SELECT_LEN STZ2 POPr JMP2r &last_to_first DUP2 STHkr LB_SELECT_IDX LDZ2 SWP2 SUB2 INC2 STHkr LB_SELECT_LEN STZ2 STHr LB_SELECT_IDX STZ2 JMP2r &y $2 @mbox_select_handler ( list -- ) #0000 ,&idx STR2 #00 ,&chr STR STHk ( clear the previous selection with null bytes ) #ff #00 &clear_mbox EQUk ,&ready JCN #00 OVR ;selected_mbox ADD2 #00 ROT ROT STA INC ,&clear_mbox JMP &ready POP2 ( get position of the current selection ) ( bytes ) LDZ2 #0000 &while EQU2k ,&end JCN STHkr LB_SELECT_IDX LDZ2 ,&idx LDR2 EQU2 ,&write_str JCN DUP2 STHkr LB_DATA LDZ2 ADD2 LDA #0a EQU ,&inc JCN INC2 ,&while JMP &inc ,&idx LDR2 INC2 ,&idx STR2 INC2 ,&while JMP ( data ) &idx $2 &chr $1 ( copy the current selection to the buffer ) &write_str STHkr LB_DATA LDZ2 ADD2 &loop LDAk #0a EQU ,&end JCN LDAk [ ;selected_mbox #00 ,&chr LDR ADD2 ] STA ,&chr LDR INC ,&chr STR INC2 ,&loop JMP &end POP2 POP2 POPr send_get_mbox JMP2r @enter_search_mode ( -- ) ENTRY_SEARCH reset_textbox ;search_lbl .textbox/msg STZ2 JMP2r @enter_refile_mode ( -- ) ENTRY_REFILE reset_textbox ;refile_lbl .textbox/msg STZ2 JMP2r @reset_textbox ( mode -- ) .textbox/mode STZ #00 .textbox/len STZ #00 .textbox/cursor STZ #00 ;textbox_text STA #01 .refresh/textbox STZ JMP2r @noop_list_click ( list -- ) POP JMP2r @right_click_mail_list ( list -- ) send_reader JMP2r @try_scroll_up_mouse ( list -- ) STHk LB_LEN LDZ2 #00 STHkr LB_HEIGHT LDZ LTH2 ,&no_scroll_up JCN STHkr LB_TOP LDZ2 #0000 EQU2 ,&no_scroll_up JCN STHkr LB_TOP LDZ2 #0001 SUB2 STHkr LB_TOP STZ2 STHkr update_sb_pos &no_scroll_up POPr JMP2r @try_scroll_down_mouse ( list -- ) STHk LB_LEN LDZ2 #00 STHkr LB_HEIGHT LDZ LTH2 ,&no_scroll_down JCN STHkr LB_TOP LDZ2 #00 STHkr LB_HEIGHT LDZ ADD2 STHkr LB_LEN LDZ2 EQU2 ,&no_scroll_down JCN STHkr LB_TOP LDZ2k INC2 ROT STZ2 STHkr update_sb_pos &no_scroll_down POPr JMP2r ( -== gfx ==- ) @on_screen ( -> ) .refresh/mboxes LDZ #00 EQU ,&no_mboxes JCN #0000 .mboxes/height LDZ clear_listbox .mboxes #0000 draw_listbox .mboxes #0000 draw_scrollbar #00 .refresh/mboxes STZ &no_mboxes .refresh/list LDZ #00 EQU ,&no_list JCN [ TOP_SECTION MID_SEPARATOR ADD2 ] .list/height LDZ clear_listbox .list [ TOP_SECTION MID_SEPARATOR ADD2 ] draw_listbox .list [ TOP_SECTION MID_SEPARATOR ADD2 ] draw_scrollbar #00 .refresh/list STZ &no_list .refresh/btns LDZ #00 EQU ,&no_btns JCN .btn_colors/compose LDZ ;compose_button #0008 .Screen/height DEI2 #0030 SUB2 draw_2x2 .btn_colors/refresh LDZ ;refresh_button #0018 .Screen/height DEI2 #0030 SUB2 draw_2x2 .btn_colors/read_all LDZ ;all_read_button #0028 .Screen/height DEI2 #0030 SUB2 draw_2x2 .btn_colors/search LDZ ;search_button #0038 .Screen/height DEI2 #0030 SUB2 draw_2x2 .btn_colors/refile LDZ ;refile_button #0048 .Screen/height DEI2 #0030 SUB2 draw_2x2 .btn_colors/trash LDZ ;trash_button #0058 .Screen/height DEI2 #0030 SUB2 draw_2x2 #00 .refresh/btns STZ &no_btns .refresh/textbox LDZ #00 EQU ,&no_textbox JCN clear_textbox .textbox/mode LDZ #00 EQU ,&no_textbox JCN ;textbox_text #0008 .Screen/height DEI2 #0018 SUB2 #03 draw_str draw_bone .textbox/msg LDZ2 #0008 .Screen/height DEI2 #0010 SUB2 #02 draw_str &no_textbox .refresh/etc LDZ #00 EQU ,&no_etc JCN draw_search_indicator draw_resize_handle #00 .refresh/etc STZ &no_etc .refresh/fg LDZ #00 EQU ,&no_fg JCN clear_fg draw_cursor #00 .refresh/fg STZ &no_fg BRK @draw_search_indicator ( -- ) .textbox/searching LDZ #00 EQU ,¬hing JCN ;search_indicator #0000 .Screen/height DEI2 #0008 SUB2 #01 draw_str JMP2r ¬hing #0000 .Screen/x DEO2 .Screen/height DEI2 #0008 SUB2 .Screen/y DEO2 ;blank .Screen/addr DEO2 #01 .Screen/sprite DEO JMP2r @draw_bone ( -- ) #0008 #00 .textbox/cursor LDZ #30 SFT2 ADD2 .Screen/x DEO2 .Screen/height DEI2 #0018 SUB2 .Screen/y DEO2 ;bone .Screen/addr DEO2 #05 .Screen/sprite DEO JMP2r @clear_textbox ( -- ) ;blank .Screen/addr DEO2 .Screen/width DEI2 #0008 &while EQU2k ,&end JCN DUP2 .Screen/x DEO2 .Screen/height DEI2 #0018 SUB2 .Screen/y DEO2 #01 .Screen/sprite DEO .Screen/height DEI2 #0010 SUB2 .Screen/y DEO2 #01 .Screen/sprite DEO #0008 ADD2 ,&while JMP &end POP2 POP2 JMP2r @clear_fg ( -- ) ;blank .Screen/addr DEO2 .Screen/width DEI2 #0000 &whilex EQU2k ,&endx JCN DUP2 ,&x STR2 .Screen/height DEI2 #0000 &whiley EQU2k ,&endy JCN DUP2 .Screen/y DEO2 ,&x LDR2 .Screen/x DEO2 #41 .Screen/sprite DEO #0008 ADD2 ,&whiley JMP &endy POP2 POP2 #0008 ADD2 ,&whilex JMP &endx POP2 POP2 JMP2r &x $2 @clear_listbox ( top* height -- ) #00 SWP #30 SFT2 ,&height STR2 ,&top STR2 ;blank .Screen/addr DEO2 .Screen/width DEI2 #0008 SUB2 #0000 &whilex EQU2k ,&endx JCN DUP2 ,&x STR2 ,&top LDR2 ,&height LDR2 ADD2 ,&top LDR2 &whiley EQU2k ,&endy JCN DUP2 .Screen/y DEO2 ,&x LDR2 .Screen/x DEO2 #00 .Screen/sprite DEO #0008 ADD2 ,&whiley JMP &endy POP2 POP2 #0008 ADD2 ,&whilex JMP &endx POP2 POP2 JMP2r &x $2 &top $2 &height $2 @draw_resize_handle ( -- ) .Screen/width DEI2 #0008 SUB2 .Screen/x DEO2 .Screen/height DEI2 #0008 SUB2 .Screen/y DEO2 ;resize_handle .Screen/addr DEO2 #02 .Screen/sprite DEO JMP2r @store_char ( char list_e_offset -- char ) SWP OVR LDZ #00 SWP ;word ADD2 STA LDZk INC SWP STZ JMP2r @shouldnt_draw_word ( list -- bit ) DUP LB_OFFSET LDZ2 ( above top of view ) STH2k ROT STHk LB_TOP LDZ2 LTH2 ,&clear_rtn JCN ( below bottom of view ) STHr DUP LB_TOP LDZ2 ROT LB_HEIGHT LDZ #00 SWP ADD2 #0001 SUB2 STH2r SWP2 GTH2 ,&no_draw JCN #00 JMP2r &clear_rtn POP2r POPr &no_draw #01 JMP2r @draw_list_elem ( list -- ) STHk get_entry_color STH [ ;word .Screen/x DEI2 .Screen/y DEI2 STHr ] draw_str STHr finish_line JMP2r @get_entry_color ( list -- colorbyte ) STHk LB_OFFSET LDZ2 STHkr LB_SELECT_IDX LDZ2 LTH2 ,&normal JCN STHkr LB_OFFSET LDZ2 STHkr LB_SELECT_IDX LDZ2 STHkr LB_SELECT_LEN LDZ2 ADD2 #0001 SUB2 GTH2 ,&normal JCN POPr ( selected ) #04 JMP2r &normal POPr #03 JMP2r @finish_line ( list -- ) STH ;blank .Screen/addr DEO2 &while .Screen/x DEI2 .Screen/width DEI2 #0010 SUB2 GTH2 ,&end JCN STHkr get_entry_color .Screen/sprite DEO .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 ,&while JMP &end POPr JMP2r @draw_listbox ( list ypos* -- ) #0000 .Screen/x DEO2 ( ypos ) .Screen/y DEO2 ( .list ) STH #0000 STHkr LB_OFFSET STZ2 STHkr LDZ2 #0000 &while EQU2k ,&end JCN DUP2 STHkr LB_DATA LDZ2 ADD2 LDA DUP #00 EQU ,&end JCN ( if not newline, store the character and increment the offsets ) DUP #0a EQU ,&inc_line JCN STHkr LB_ELEM_OFFSET store_char ,&continue JMP ( continue looping ) &inc_line POP #0000 STHkr LB_ELEM_OFFSET LDZ ;word ADD2 STA STHkr shouldnt_draw_word ,&no_draw JCN STHkr draw_list_elem #0000 .Screen/x DEO2 .Screen/y DEI2 #0008 ADD2 .Screen/y DEO2 &no_draw STHkr LB_OFFSET LDZ2 INC2 STHkr LB_OFFSET STZ2 #00 STHkr LB_ELEM_OFFSET STZ &continue INC2 ,&while JMP &end STHkr LB_OFFSET LDZ2 STHr LB_LEN STZ2 POP2 POP2 JMP2r @draw_cursor ( -- ) .Mouse/x DEI2 .Screen/x DEO2 .Mouse/y DEI2 .Screen/y DEO2 ;cursor .Screen/addr DEO2 #4f .Screen/sprite DEO JMP2r @draw_scrollbar ( list ypos* -- ) ,&y STR2 STH .Screen/width DEI2 #0008 SUB2 .Screen/x DEO2 ,&y LDR2 .Screen/y DEO2 ( draw the trough no matter what ) ;blank .Screen/addr DEO2 STHkr LB_HEIGHT LDZ #00 &while_trough EQUk ,&end_trough JCN #00 .Screen/sprite DEO .Screen/y DEI2 #0008 ADD2 .Screen/y DEO2 INC ,&while_trough JMP &end_trough POP2 ( stop here if there is no overflow ) STHkr LB_LEN LDZ2 #00 STHkr LB_HEIGHT LDZ INC2 LTH2 ,&no_handle JCN ,&draw_handle JMP &no_handle POPr JMP2r &y $2 ( if there are more entries than will fit in the view area, draw the handle ) &draw_handle ( store the number of entries per tile of the scrollbar ) STHkr LB_LEN LDZ2 #00 STHkr LB_HEIGHT LDZ DIV2 STHkr SB_STEP STZ2 ( set the length of the scrollbar ) STHkr LB_HEIGHT LDZ STHkr LB_LEN LDZ2 #00 STHkr LB_HEIGHT LDZ SUB2 STHkr SB_STEP LDZ2 DIV2 NIP SUB STHkr SB_LEN STZ ;scrollbar .Screen/addr DEO2 ,&y LDR2 STHkr SB_POS LDZ2 #30 SFT2 ADD2 .Screen/y DEO2 STHkr SB_LEN LDZ #00 &while_handle EQUk ,&end_handle JCN .Screen/y DEI2 .Screen/height DEI2 #0040 SUB2 EQU2 ,&end_handle JCN #01 .Screen/sprite DEO INC .Screen/y DEI2 #0008 ADD2 .Screen/y DEO2 ,&while_handle JMP &end_handle POP2 POPr JMP2r @update_sb_pos ( list -- ) DUP SB_STEP LDZ2 #0000 NEQ2 ,&safe_to_divide JCN POP JMP2r &safe_to_divide DUP DUP LB_TOP LDZ2 ROT SB_STEP LDZ2 DIV2 ROT SB_POS STZ2 JMP2r @draw_str ( addr* x* y* color -- ) STH ( save color ) .Screen/y DEO2 ( set y ) .Screen/x DEO2 ( set x ) ( now the string address is at the top of the stack ) LDAk #00 EQU ,&done JCN &loop .Screen/x DEI2 .Screen/width DEI2 #0010 SUB2 GTH2 ,&done JCN LDAk DUP #7f LTH ,&ascii JCN POP #3f ( replace non_ascii characters with ? ) &ascii DUP #00 NEQ #20 MUL SUB #00 SWP #30 SFT2 ;font ADD2 .Screen/addr DEO2 STHkr .Screen/sprite DEO .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 INC2 LDAk ,&loop JCN &done POP2 POPr JMP2r @draw_2x2 ( color sprite* x* y* -- ) .Screen/y DEO2 .Screen/x DEO2 #16 .Screen/auto DEO .Screen/addr DEO2 .Screen/sprite DEOk DEO #00 .Screen/auto DEO JMP2r ( -== util ==- ) @strlen ( addr* -- len* ) DUP2 &loop INC2 LDAk ,&loop JCN SWP2 SUB2 JMP2r @debug_u8 ( byte -- ) #00 SWP debug_u16 JMP2r @debug_u16 ( short* -- ) SWP ,&byte JSR &byte ( byte -- ) DUP #04 SFT ,&char JSR &char ( char -- ) #0f AND DUP #09 GTH #27 MUL ADD #30 ADD .Console/error DEO JMP2r @debug ( str* -- ) &while LDAk .Console/error DEO INC2 LDAk ,&while JCN POP2 JMP2r @load_theme ( -- ) ;theme_file .File0/name DEO2 #0006 .File0/length DEO2 ;theme_data .File0/read DEO2 .File0/success DEI2 #0006 NEQ2 ,&no_theme_file JCN ;theme_data/r LDA2 .System/r DEO2 ;theme_data/g LDA2 .System/g DEO2 ;theme_data/b LDA2 .System/b DEO2 &no_theme_file JMP2r @load_font ( -- ) ;font_file .File0/name DEO2 #0300 .File0/length DEO2 ;font .File0/read DEO2 JMP2r ( -== data ==- ) @search_indicator "$ 00 @theme_file ".theme 00 @font_file "font.icn 00 @search_lbl "SEARCHING: 20 "type 20 "query 20 "and 20 "press 20 "{enter}; 20 "{esc} 20 "to 20 "go 20 "back 00 @refile_lbl "REFILING: 20 "type 20 "destination 20 "and 20 "press 20 "{enter}; 20 "{esc} 20 "to 20 "go 20 "back 00 @resize_handle [ e2c2 aa1a 3a02 fe00 ] @cursor [ f8e0 e090 8804 0000 ] @scrollbar [ 0707 0707 0707 0707 ] @bone [ e040 4040 4040 40e0 ] @blank [ 0000 0000 0000 0000 ] @refresh_button [ 0000 0708 1010 1000 0000 e010 3e1c 0800 0010 387c 0807 0000 0008 0808 10e0 0000 ] @all_read_button [ 0000 0101 0905 003c 0000 8080 90a0 003c 3c00 0509 0101 0000 3c00 a090 8080 0000 ] @search_button [ 0000 0007 0810 2142 0000 00e0 1008 8442 4221 1008 0700 0000 4284 0810 e000 0000 ] @refile_button [ 0000 003f 202f 2024 0000 fe82 12fa 1202 2f24 203f 0000 0000 fa02 02fe 0000 0000 ] @trash_button [ 0003 021f 101f 080a 00c0 40f8 08f8 1050 0a0a 0a08 0f00 0000 5050 5010 f000 0000 ] @compose_button [ 0010 107c 1010 0102 0000 0020 5088 1020 0408 191e 1d00 0000 4080 00a8 5000 0000 ] @metadata [ 00 "taro 0a "v0.2.1 0a "GUI 20 "for 20 "mblaze 0a "Derek 20 "Stevens 20 " 0a 00 ] @selected_mbox "INBOX 00 $f9 ( default mailbox is INBOX, total space #06 + #f9 = #ff bytes ) @font $300 @theme_data [ &r $2 &g $2 &b $2 ] @textbox_text $ff @word $ff @mbox_data $1000 @list_data $8000