a2d/desktop/desktop_main.s

16396 lines
415 KiB
ArmAsm

;;; ============================================================
;;; DeskTop - Main Memory Segment
;;;
;;; Compiled as part of desktop.s
;;; ============================================================
;;; ============================================================
;;; Segment loaded into MAIN $4000-$BEFF
;;; ============================================================
.proc desktop_main
dst_path_buf := $1FC0
dynamic_routine_800 := $0800
dynamic_routine_5000 := $5000
dynamic_routine_7000 := $7000
dynamic_routine_9000 := $9000
dynamic_routine_disk_copy = 0
dynamic_routine_format_erase = 1
dynamic_routine_selector1 = 2
dynamic_routine_common = 3
dynamic_routine_file_copy = 4
dynamic_routine_file_delete = 5
dynamic_routine_selector2 = 6
dynamic_routine_restore5000 = 7
dynamic_routine_restore9000 = 8
.org $4000
;; Jump table
;; Entries marked with * are used by DAs
;; "Exported" by desktop.inc
JT_MAIN_LOOP: jmp enter_main_loop
JT_MGTK_RELAY: jmp MGTK_RELAY
JT_SIZE_STRING: jmp compose_blocks_string
JT_DATE_STRING: jmp compose_date_string
JT_SELECT_WINDOW: jmp select_and_refresh_window
JT_AUXLOAD: jmp AuxLoad
JT_EJECT: jmp cmd_eject
JT_REDRAW_ALL: jmp redraw_windows ; *
JT_ITK_RELAY: jmp ITK_RELAY
JT_LOAD_OVL: jmp load_dynamic_routine
JT_CLEAR_SELECTION: jmp clear_selection ; *
JT_MLI_RELAY: jmp MLI_RELAY ; *
JT_COPY_TO_BUF: jmp LoadWindowIconTable
JT_COPY_FROM_BUF: jmp StoreWindowIconTable
JT_NOOP: jmp cmd_noop
JT_FILE_TYPE_STRING: jmp compose_file_type_string
JT_SHOW_ALERT0: jmp ShowAlert
JT_SHOW_ALERT: jmp ShowAlertOption
JT_LAUNCH_FILE: jmp launch_file
JT_CUR_POINTER: jmp set_pointer_cursor ; *
JT_CUR_WATCH: jmp set_watch_cursor
JT_RESTORE_OVL: jmp restore_dynamic_routine
JT_COLOR_MODE: jmp set_color_mode ; *
JT_MONO_MODE: jmp set_mono_mode ; *
JT_RESTORE_SYS: jmp restore_system ; *
.assert JUMP_TABLE_MAIN_LOOP = JT_MAIN_LOOP, error, "Jump table mismatch"
.assert JUMP_TABLE_RESTORE_SYS = JT_RESTORE_SYS, error, "Jump table mismatch"
;; Main Loop
.proc enter_main_loop
cli
;; Add icons (presumably desktop ones?)
ldx #0
iloop: cpx cached_window_icon_count
beq skip
txa
pha
lda cached_window_icon_list,x
jsr icon_entry_lookup
ldy #IconTK::ADD_ICON
jsr ITK_RELAY ; icon entry addr in A,X
pla
tax
inx
jmp iloop
skip: copy #0, cached_window_id
jsr StoreWindowIconTable
;; Clear various flags
lda #0
sta LD2A9
sta double_click_flag
sta loop_counter
sta LE26F
;; Pending error message?
lda pending_alert
beq main_loop
tay
jsr ShowAlert
;; Main loop
main_loop:
jsr reset_grafport3
inc loop_counter
inc loop_counter
lda loop_counter
cmp machine_type ; for per-machine timing
bcc :+
copy #0, loop_counter
jsr show_clock
;; Poll drives for updates
jsr check_disk_inserted_ejected
beq :+
jsr L40E0 ; conditionally ???
: jsr L464E
;; Get an event
jsr get_event
lda event_kind
;; Is it a button-down event? (including w/ modifiers)
cmp #MGTK::EventKind::button_down
beq click
cmp #MGTK::EventKind::apple_key
bne :+
click: jsr handle_click
jmp main_loop
;; Is it a key down event?
: cmp #MGTK::EventKind::key_down
bne :+
jsr handle_keydown
jmp main_loop
;; Is it an update event?
: cmp #MGTK::EventKind::update
bne :+
jsr reset_grafport3
copy active_window_id, L40F0
copy #$80, L40F1
jsr L410D
: jmp main_loop
loop_counter:
.byte 0
;;; --------------------------------------------------
L40E0: tsx
stx saved_stack
sta menu_click_params::item_num
jsr cmd_check_single_drive_by_menu
copy #0, menu_click_params::item_num
rts
L40F0: .byte $00
L40F1: .byte $00
redraw_windows:
jsr reset_grafport3
copy active_window_id, L40F0
copy #$00, L40F1
L4100: jsr peek_event
lda event_kind
cmp #MGTK::EventKind::update
bne L412B
jsr get_event
L410D: jsr L4113
jmp L4100
L4113: MGTK_RELAY_CALL MGTK::BeginUpdate, event_window_id
bne L4151 ; did not really need updating
jsr update_window
MGTK_RELAY_CALL MGTK::EndUpdate
rts
L412B: jsr LoadDesktopIconTable
lda L40F0
sta active_window_id
beq L4143
bit running_da_flag
bmi L4143
jsr redraw_selected_icons
L4143: bit L40F1
bpl L4151
ITK_RELAY_CALL IconTK::REDRAW_ICONS
L4151: rts
.endproc
main_loop := enter_main_loop::main_loop
redraw_windows := enter_main_loop::redraw_windows
;;; ============================================================
draw_window_header_flag: .byte 0
.proc update_window
lda event_window_id
cmp #9 ; only handle windows 1...8
bcc L415B
rts
L415B: sta active_window_id
jsr LoadActiveWindowIconTable
copy #$80, draw_window_header_flag
copy cached_window_id, getwinport_params2::window_id
jsr get_port2
jsr draw_window_header
lda active_window_id
jsr copy_window_portbits
jsr OverwriteWindowPort
lda active_window_id
jsr window_lookup
stax $06
ldy #22
sub16in ($06),y, grafport2::viewloc::ycoord, L4242
cmp16 L4242, #15
bpl L41CB
jsr offset_grafport2
ldx #11
ldy #31
copy grafport2,x, ($06),y
dey
dex
copy grafport2,x, ($06),y
ldx #3
ldy #23
copy grafport2,x, ($06),y
dey
dex
copy grafport2,x, ($06),y
L41CB: ldx cached_window_id
dex
lda win_view_by_table,x
bpl by_icon
jsr L6C19
copy #0, draw_window_header_flag
lda active_window_id
jmp assign_window_portbits
by_icon:
copy cached_window_id, getwinport_params2::window_id
jsr get_set_port2
jsr cached_icons_screen_to_window
COPY_BLOCK grafport2::cliprect, tmp_rect
copy #0, L4241
L41FE: lda L4241
cmp cached_window_icon_count
beq L4227
tax
copy cached_window_icon_list,x, icon_param
ITK_RELAY_CALL IconTK::ICON_IN_RECT, icon_param
beq :+
ITK_RELAY_CALL IconTK::REDRAW_ICON, icon_param
: inc L4241
jmp L41FE
L4227: copy #0, draw_window_header_flag
copy cached_window_id, getwinport_params2::window_id
jsr get_set_port2
jsr cached_icons_window_to_screen
lda active_window_id
jsr assign_window_portbits
jmp reset_grafport3
L4241: .byte 0
L4242: .word 0
.endproc
;;; ============================================================
.proc redraw_selected_icons
lda selected_icon_count
bne :+
bail: rts
: copy #0, num
lda selected_window_index
beq desktop
cmp active_window_id
bne bail
copy active_window_id, getwinport_params2::window_id
jsr get_port2
cmp #MGTK::Error::window_obscured
beq done
jsr offset_grafport2_and_set
COPY_BLOCK grafport2::cliprect, tmp_rect
;; Redraw selected icons in window
window: lda num
cmp selected_icon_count
beq done
tax
copy selected_icon_list,x, icon_param
jsr icon_screen_to_window
ITK_RELAY_CALL IconTK::ICON_IN_RECT, icon_param
beq :+
ITK_RELAY_CALL IconTK::REDRAW_ICON, icon_param
: lda icon_param
jsr icon_window_to_screen
inc num
jmp window
done: jmp reset_grafport3
;; Redraw selected icons on desktop
desktop:
lda num
cmp selected_icon_count
beq done
tax
copy selected_icon_list,x, icon_param
ITK_RELAY_CALL IconTK::REDRAW_ICON, icon_param
inc num
jmp desktop
num: .byte 0
.endproc
;;; ============================================================
;;; Menu Dispatch
.proc handle_keydown_impl
;; Keep in sync with desktop_aux::menu_item_id_*
;; jump table for menu item handlers
dispatch_table:
;; Apple menu (1)
menu1_start := *
.addr cmd_about
.addr cmd_noop ; --------
.repeat ::max_desk_acc_count
.addr cmd_deskacc
.endrepeat
;; File menu (2)
menu2_start := *
.addr cmd_new_folder
.addr cmd_open
.addr cmd_close
.addr cmd_close_all
.addr cmd_select_all
.addr cmd_noop ; --------
.addr cmd_get_info
.addr cmd_rename_icon
.addr cmd_noop ; --------
.addr cmd_copy_file
.addr cmd_delete_file
.addr cmd_noop ; --------
.addr cmd_quit
;; Selector menu (3)
menu3_start := *
.addr cmd_selector_action
.addr cmd_selector_action
.addr cmd_selector_action
.addr cmd_selector_action
.addr cmd_noop ; --------
.addr cmd_selector_item
.addr cmd_selector_item
.addr cmd_selector_item
.addr cmd_selector_item
.addr cmd_selector_item
.addr cmd_selector_item
.addr cmd_selector_item
.addr cmd_selector_item
;; View menu (4)
menu4_start := *
.addr cmd_view_by_icon
.addr cmd_view_by_name
.addr cmd_view_by_date
.addr cmd_view_by_size
.addr cmd_view_by_type
;; Special menu (5)
menu5_start := *
.addr cmd_check_drives
.addr cmd_check_drive
.addr cmd_eject
.addr cmd_noop ; --------
.addr cmd_format_disk
.addr cmd_erase_disk
.addr cmd_disk_copy
.addr cmd_noop ; --------
.addr cmd_lock
.addr cmd_unlock
.addr cmd_get_size
;; 6/7 unused
menu6_start := *
menu7_start := *
;; Startup menu (8)
menu8_start := *
.addr cmd_startup_item
.addr cmd_startup_item
.addr cmd_startup_item
.addr cmd_startup_item
.addr cmd_startup_item
.addr cmd_startup_item
.addr cmd_startup_item
menu_end := *
;; indexed by menu id-1
offset_table:
.byte menu1_start - dispatch_table
.byte menu2_start - dispatch_table
.byte menu3_start - dispatch_table
.byte menu4_start - dispatch_table
.byte menu5_start - dispatch_table
.byte menu6_start - dispatch_table
.byte menu7_start - dispatch_table
.byte menu8_start - dispatch_table
.byte menu_end - dispatch_table
;; Set if there are open windows
flag: .byte $00
;; Handle accelerator keys
handle_keydown:
lda event_modifiers
bne :+ ; either OA or SA ?
jmp menu_accelerators ; nope
: cmp #3 ; both OA + SA ?
bne :+ ; nope
rts
;; Non-menu keys
: lda event_key
jsr upcase_char
cmp #'H' ; OA-H (Highlight Icon)
bne :+
jmp cmd_higlight
: bit flag
bpl menu_accelerators
cmp #'G' ; OA-G (Resize)
bne :+
jmp cmd_resize
: cmp #'M' ; OA-M (Move)
bne :+
jmp cmd_move
: cmp #'X' ; OA-X (Scroll)
bne :+
jmp cmd_scroll
: cmp #CHAR_DELETE ; OA-Delete (Delete)
bne :+
jmp cmd_delete_selection
: cmp #'`' ; OA-` (Cycle Windows)
beq cycle
cmp #CHAR_TAB ; OA-Tab (Cycle Windows)
bne menu_accelerators
cycle: jmp cmd_cycle_windows
menu_accelerators:
copy event_key, LE25C
lda event_modifiers
beq :+
lda #1
: sta LE25D
copy #$80, menu_kbd_flag ; note that source is keyboard
MGTK_RELAY_CALL MGTK::MenuKey, menu_click_params
menu_dispatch2:
ldx menu_click_params::menu_id
bne :+
rts
: dex ; x has top level menu id
lda offset_table,x
tax
ldy menu_click_params::item_num
dey
tya
asl a
sta proc_addr
txa
clc
adc proc_addr
tax
copy16 dispatch_table,x, proc_addr
jsr call_proc
MGTK_RELAY_CALL MGTK::HiliteMenu, menu_click_params
rts
call_proc:
tsx
stx saved_stack
proc_addr := *+1
jmp dummy1234 ; self-modified
.endproc
handle_keydown := handle_keydown_impl::handle_keydown
menu_dispatch2 := handle_keydown_impl::menu_dispatch2
menu_dispatch_flag := handle_keydown_impl::flag
;;; ============================================================
;;; Handle click
.proc handle_click
tsx
stx saved_stack
MGTK_RELAY_CALL MGTK::FindWindow, event_coords
lda findwindow_which_area
bne not_desktop
;; Click on desktop
jsr detect_double_click
sta double_click_flag
copy #0, findwindow_window_id
ITK_RELAY_CALL IconTK::FIND_ICON, event_coords
lda findicon_which_icon
beq :+
jmp handle_volume_icon_click
: jmp L68AA
not_desktop:
cmp #MGTK::Area::menubar ; menu?
bne not_menu
copy #0, menu_kbd_flag ; note that source is not keyboard
MGTK_RELAY_CALL MGTK::MenuSelect, menu_click_params
jmp menu_dispatch2
not_menu:
pha ; which window - active or not?
lda active_window_id
cmp findwindow_window_id
beq handle_active_window_click
pla
jmp handle_inactive_window_click
.endproc
;;; ============================================================
;;; Inputs: MGTK::Area pushed to stack
.proc handle_active_window_click
pla
cmp #MGTK::Area::content
bne :+
jsr detect_double_click
sta double_click_flag
jmp handle_client_click
: cmp #MGTK::Area::dragbar
bne :+
jmp handle_title_click
: cmp #MGTK::Area::grow_box
bne :+
jmp handle_resize_click
: cmp #MGTK::Area::close_box
bne :+
jmp handle_close_click
: rts
.endproc
;;; ============================================================
;;; Inputs: window_id to activate in findwindow_window_id
.proc handle_inactive_window_click
ptr := $6
jmp start
winid: .byte 0
start: jsr clear_selection
;; Select window's corresponding volume icon.
;; (Doesn't work for folder icons as only the active
;; window and desktop can have selections.)
ldx findwindow_window_id
dex
lda window_to_dir_icon_table,x
bmi continue ; $FF = dir icon freed
sta icon_param
lda icon_param
jsr icon_entry_lookup
stax ptr
ldy #IconEntry::state ; set state to open
lda (ptr),y
beq continue
ora #icon_entry_open_mask
sta (ptr),y
iny ; IconEntry::win_type
lda (ptr),y
and #icon_entry_winid_mask
sta winid
jsr zero_grafport5_coords
ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, icon_param
jsr reset_grafport3
copy winid, selected_window_index
copy #1, selected_icon_count
copy icon_param, selected_icon_list
;; Actually make the window active.
continue:
MGTK_RELAY_CALL MGTK::SelectWindow, findwindow_window_id
copy findwindow_window_id, active_window_id
jsr LoadActiveWindowIconTable
jsr L6C19
jsr LoadDesktopIconTable
copy #MGTK::checkitem_uncheck, checkitem_params::check
MGTK_RELAY_CALL MGTK::CheckItem, checkitem_params
ldx active_window_id
dex
lda win_view_by_table,x
and #$0F ; mask off menu item number
sta checkitem_params::menu_item
inc checkitem_params::menu_item
copy #MGTK::checkitem_check, checkitem_params::check
MGTK_RELAY_CALL MGTK::CheckItem, checkitem_params
rts
.endproc
;;; ============================================================
.proc get_set_port2
MGTK_RELAY_CALL MGTK::GetWinPort, getwinport_params2
MGTK_RELAY_CALL MGTK::SetPort, grafport2
rts
.endproc
.proc get_port2
MGTK_RELAY_CALL MGTK::GetWinPort, getwinport_params2
rts
.endproc
.proc reset_grafport3
MGTK_RELAY_CALL MGTK::InitPort, grafport3
MGTK_RELAY_CALL MGTK::SetPort, grafport3
rts
.endproc
;;; ============================================================
.proc redraw_windows_and_desktop
jsr redraw_windows
ITK_RELAY_CALL IconTK::REDRAW_ICONS
rts
.endproc
;;; ============================================================
;;; Update table tracking disk-in-device status, determine if
;;; there was a change (insertion or ejection).
;;; Output: 0 if no change,
.proc check_disk_inserted_ejected
lda disk_in_device_table
beq done
jsr check_disks_in_devices
ldx disk_in_device_table
: lda disk_in_device_table,x
cmp last_disk_in_devices_table,x
bne changed
dex
bne :-
done: return #0
changed:
copy disk_in_device_table,x, last_disk_in_devices_table,x
lda removable_device_table,x
ldy DEVCNT
: cmp DEVLST,y
beq :+
dey
bpl :-
rts
: tya
clc
adc #$03
rts
.endproc
;;; ============================================================
max_removable_devices = 8
removable_device_table:
.byte 0 ; num entries
.res max_removable_devices, 0
;;; Updated by check_disks_in_devices
disk_in_device_table:
.byte 0 ; num entries
.res max_removable_devices, 0
;;; Snapshot of previous results; used to detect changes.
last_disk_in_devices_table:
.byte 0 ; num entries
.res max_removable_devices, 0
;;; ============================================================
.proc check_disks_in_devices
ptr := $6
status_buffer := $800
ldx removable_device_table
beq done
stx disk_in_device_table
: lda removable_device_table,x
jsr check_disk_in_drive
sta disk_in_device_table,x
dex
bne :-
done: rts
check_disk_in_drive:
sta unit_number
txa
pha
tya
pha
sp_addr := $0A
lda unit_number
jsr find_smartport_dispatch_address
bne notsp ; not SmartPort
stx status_unit_num
;; Execute SmartPort call
jsr smartport_call
.byte $00 ; $00 = STATUS
.addr status_params
lda status_buffer
and #$10 ; general status byte, $10 = disk in drive
beq notsp
lda #$FF
bne finish
notsp: lda #0 ; not SmartPort (or no disk in drive)
finish: sta result
pla
tay
pla
tax
return result
smartport_call:
jmp (sp_addr)
unit_number:
.byte 0
result: .byte 0
;; params for call
.proc status_params
param_count: .byte 3
unit_num: .byte 1
list_ptr: .addr status_buffer
status_code: .byte 0
.endproc
status_unit_num := status_params::unit_num
.endproc
;;; ============================================================
.proc L464E
lda num_selector_list_items
beq :+
bit LD344
bmi L4666
jsr enable_selector_menu_items
jmp L4666
: bit LD344
bmi L4666
jsr disable_selector_menu_items
L4666: lda selected_icon_count
beq L46A8
lda selected_window_index
bne L4691
lda selected_icon_count
cmp #2
bcs L4697
lda selected_icon_list
cmp trash_icon_num
bne L468B
jsr disable_eject_menu_item
jsr disable_file_menu_items
copy #0, LE26F
rts
L468B: jsr enable_eject_menu_item
jmp L469A
L4691: jsr disable_eject_menu_item
jmp L469A
L4697: jsr enable_eject_menu_item
L469A: bit LE26F
bmi L46A7
jsr enable_file_menu_items
copy #$80, LE26F
L46A7: rts
L46A8: bit LE26F
bmi L46AE
rts
L46AE: jsr disable_eject_menu_item
jsr disable_file_menu_items
copy #$00, LE26F
rts
.endproc
.proc MLI_RELAY
sty call
stax params
sta ALTZPOFF
sta ROMIN2
jsr MLI
call: .byte $00
params: .addr dummy0000
sta ALTZPON
tax
lda LCBANK1
lda LCBANK1
txa
rts
.endproc
.macro MLI_RELAY_CALL call, addr
yax_call desktop_main::MLI_RELAY, call, addr
.endmacro
;;; ============================================================
;;; Launch file (double-click) ???
.proc launch_file
path := $220
jmp begin
DEFINE_GET_FILE_INFO_PARAMS get_file_info_params, path
begin:
jsr set_watch_cursor
;; Compose window path plus icon path
ldx #$FF
: inx
copy buf_win_path,x, path,x
cpx buf_win_path
bne :-
inx
copy #'/', path,x
ldy #0
: iny
inx
copy buf_filename2,y, path,x
cpy buf_filename2
bne :-
stx path
;; Get the file info to determine type.
MLI_RELAY_CALL GET_FILE_INFO, get_file_info_params
beq :+
jsr ShowAlert
rts
;; Check file type.
: copy get_file_info_params::file_type, fto_type
copy16 get_file_info_params::aux_type, fto_auxtype
copy16 get_file_info_params::blocks_used, fto_blocks
jsr check_file_type_overrides
cmp #FT_BASIC
bne :+
jsr check_basic_system ; Only launch if BASIC.SYSTEM is found
jmp launch
: cmp #FT_BINARY
bne :+
lda BUTN0 ; Only launch if a button is down
ora BUTN1 ; BUG: Never gets this far ???
bmi launch
jsr set_pointer_cursor
rts
: cmp #FT_SYSTEM
beq launch
cmp #APP_FILE_TYPE
beq launch
cmp #FT_GRAPHICS
bne :+
addr_jump invoke_desk_acc, str_preview_fot
: cmp #FT_TEXT
bne :+
addr_jump invoke_desk_acc, str_preview_txt
: cmp #FT_FONT
bne :+
addr_jump invoke_desk_acc, str_preview_fnt
: cmp #DA_FILE_TYPE
bne :+
addr_jump invoke_desk_acc, path
: lda #ERR_FILE_NOT_OPENABLE
jsr show_alert_and_fail
launch: ITK_RELAY_CALL IconTK::REMOVE_ALL, 0 ; volume icons
MGTK_RELAY_CALL MGTK::CloseAll
MGTK_RELAY_CALL MGTK::SetMenu, blank_menu
ldx buf_win_path
: copy buf_win_path,x, path,x
dex
bpl :-
ldx buf_filename2
: copy buf_filename2,x, INVOKER_FILENAME,x
dex
bpl :-
copy16 #INVOKER, reset_and_invoke_target
jmp reset_and_invoke
;;; --------------------------------------------------
.proc check_basic_system_impl
path := $1800
DEFINE_GET_FILE_INFO_PARAMS get_file_info_params2, path
start: ldx buf_win_path
stx path_length
: copy buf_win_path,x, path,x
dex
bpl :-
inc path
ldx path
copy #'/', path,x
loop:
;; Append BASIC.SYSTEM to path and check for file.
ldx path
ldy #0
: inx
iny
copy str_basic_system,y, path,x
cpy str_basic_system
bne :-
stx path
MLI_RELAY_CALL GET_FILE_INFO, get_file_info_params2
bne not_found
rts
;; Pop off a path segment and try again.
not_found:
ldx path_length
: lda path,x
cmp #'/'
beq found_slash
dex
bne :-
no_bs: lda #ERR_BASIC_SYS_NOT_FOUND
show_alert_and_fail:
jsr ShowAlert
pla ; pop caller address, return to its caller
pla
rts
found_slash:
cpx #$01
beq no_bs
stx path
dex
stx path_length
jmp loop
path_length:
.byte 0
str_basic_system:
PASCAL_STRING "Basic.system"
.endproc
check_basic_system := check_basic_system_impl::start
show_alert_and_fail := check_basic_system_impl::show_alert_and_fail
;;; --------------------------------------------------
.endproc
;;; ============================================================
.proc upcase_char
cmp #'a'
bcc done
cmp #'z'+1
bcs done
and #CASE_MASK
done: rts
.endproc
;;; ============================================================
L485D: .word $E000
L485F: .word $D000
;;; ============================================================
set_watch_cursor:
jsr hide_cursor
MGTK_RELAY_CALL MGTK::SetCursor, watch_cursor
jsr show_cursor
rts
set_pointer_cursor:
jsr hide_cursor
MGTK_RELAY_CALL MGTK::SetCursor, pointer_cursor
jsr show_cursor
rts
hide_cursor:
MGTK_RELAY_CALL MGTK::HideCursor
rts
show_cursor:
MGTK_RELAY_CALL MGTK::ShowCursor
rts
;;; ============================================================
.proc restore_device_list
ldx devlst_backup
inx
: copy devlst_backup,x, DEVLST-1,x
dex
bpl :-
rts
.endproc
.proc warning_dialog_proc_num
sta warning_dialog_num
yax_call invoke_dialog_proc, index_warning_dialog, warning_dialog_num
rts
.endproc
copy16 #main_loop, L48E4
L48E4 := *+1
jmp dummy1234 ; self-modified
get_event:
MGTK_RELAY_CALL MGTK::GetEvent, event_params
rts
peek_event:
MGTK_RELAY_CALL MGTK::PeekEvent, event_params
rts
set_penmode_xor:
MGTK_RELAY_CALL MGTK::SetPenMode, penXOR
rts
set_penmode_copy:
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
rts
;;; ============================================================
.proc cmd_noop
rts
.endproc
;;; ============================================================
.proc cmd_selector_action
jsr set_watch_cursor
lda #dynamic_routine_selector1
jsr load_dynamic_routine
bmi done
lda menu_click_params::item_num
cmp #3 ; 1 = Add, 2 = Edit (need more overlays)
bcs :+ ; 3 = Delete, 4 = Run (can skip)
lda #dynamic_routine_selector2
jsr load_dynamic_routine
bmi done
lda #dynamic_routine_common
jsr load_dynamic_routine
bmi done
: jsr set_pointer_cursor
;; Invoke routine
lda menu_click_params::item_num
jsr dynamic_routine_9000
sta result
jsr set_watch_cursor
;; Restore from overlays
lda #dynamic_routine_restore9000
jsr restore_dynamic_routine
lda menu_click_params::item_num
cmp #4 ; 4 = Run ?
bne done
;; "Run" command
lda result
bpl done
jsr make_ramcard_prefixed_path
jsr strip_path_segments
jsr get_copied_to_ramcard_flag
bpl L497A
jsr jt_run
bmi done
jsr L4968
done: jsr set_pointer_cursor
jsr redraw_windows_and_desktop
rts
.proc L4968
jsr make_ramcard_prefixed_path
COPY_STRING $840, buf_win_path
jmp launch_buf_win_path
.endproc
L497A: jsr make_ramcard_prefixed_path
COPY_STRING $800, buf_win_path
jsr launch_buf_win_path
jmp done
result: .byte 0
.endproc
;;; ============================================================
.proc cmd_selector_item_impl
DEFINE_GET_FILE_INFO_PARAMS get_file_info_params3, $220
start:
jmp L49A6
entry_num:
.byte 0
L49A6: lda menu_click_params::item_num
sec
sbc #6 ; 4 items + separator (and make 0 based)
sta entry_num
jsr a_times_16
addax #run_list_entries, $06
ldy #$0F ; flag byte following name
lda ($06),y
asl a
bmi not_downloaded ; bit 6
bcc L49E0 ; bit 7
jsr get_copied_to_ramcard_flag
beq not_downloaded
lda entry_num
jsr check_downloaded_path
beq L49ED
lda entry_num
jsr L4A47
jsr jt_run
bpl L49ED
jmp redraw_windows_and_desktop
L49E0: jsr get_copied_to_ramcard_flag
beq not_downloaded
lda entry_num
jsr check_downloaded_path ; was-downloaded flag check?
bne not_downloaded
L49ED: lda entry_num
jsr compose_downloaded_entry_path
stax $06
jmp L4A0A
not_downloaded:
lda entry_num
jsr a_times_64
addax #run_list_paths, $06
L4A0A: ldy #$00
lda ($06),y
tay
L4A0F: lda ($06),y
sta buf_win_path,y
dey
bpl L4A0F
;; fall through
.proc launch_buf_win_path
;; Find last '/'
ldy buf_win_path
: lda buf_win_path,y
cmp #'/'
beq :+
dey
bpl :-
: dey
sty slash_index
;; Copy filename to buf_filename2
ldx #0
iny
: iny
inx
lda buf_win_path,y
sta buf_filename2,x
cpy buf_win_path
bne :-
;; Truncate path
stx buf_filename2
lda slash_index
sta buf_win_path
lda #0
jmp launch_file
slash_index:
.byte 0
.endproc
;;; --------------------------------------------------
;; Copy entry path to $800
.proc L4A47
pha
jsr a_times_64
addax #run_list_paths, $06
ldy #0
lda ($06),y
tay
: lda ($06),y
sta $800,y
dey
bpl :-
pla
;; Copy "down loaded" path to $840
jsr compose_downloaded_entry_path
stax $08
ldy #0
lda ($08),y
tay
: lda ($08),y
sta $840,y
dey
bpl :-
;; fall through
.endproc
;; Strip segment off path at $800
.proc strip_path_segments
ldy $800
: lda $800,y
cmp #'/'
beq :+
dey
bne :-
: dey
sty $800
;; Strip segment off path at $840
ldy $840
: lda $840,y
cmp #'/'
beq :+
dey
bne :-
: dey
sty $840
;; Return addresses in $6 and $8
copy16 #$800, $06
copy16 #$840, $08
jsr copy_paths_and_split_name
rts
.endproc
;;; --------------------------------------------------
;;; Append last two path segments of buf_win_path to
;;; ramcard_prefix, result left at $840
.proc make_ramcard_prefixed_path
;; Copy window path to $800
ldy buf_win_path
: lda buf_win_path,y
sta $800,y
dey
bpl :-
addr_call copy_ramcard_prefix, $840
;; Find last '/' in path...
ldy $800
: lda $800,y
cmp #'/'
beq :+
dey
bne :-
;; And back up one more path segment...
: dey
: lda $800,y
cmp #'/'
beq :+
dey
bne :-
: dey
ldx $840
: iny
inx
lda $800,y
sta $840,x
cpy $800
bne :-
rts
.endproc
.proc check_downloaded_path
jsr compose_downloaded_entry_path
stax get_file_info_params3::pathname
MLI_RELAY_CALL GET_FILE_INFO, get_file_info_params3
rts
.endproc
.endproc
cmd_selector_item := cmd_selector_item_impl::start
launch_buf_win_path := cmd_selector_item_impl::launch_buf_win_path
strip_path_segments := cmd_selector_item_impl::strip_path_segments
make_ramcard_prefixed_path := cmd_selector_item_impl::make_ramcard_prefixed_path
;;; ============================================================
;;; Get "copied to RAM card" flag from Main LC Bank 2.
.proc get_copied_to_ramcard_flag
sta ALTZPOFF
lda LCBANK2
lda LCBANK2
lda copied_to_ramcard_flag
tax
sta ALTZPON
lda LCBANK1
lda LCBANK1
txa
rts
.endproc
.proc copy_ramcard_prefix
stax @destptr
sta ALTZPOFF
lda LCBANK2
lda LCBANK2
ldx ramcard_prefix
: lda ramcard_prefix,x
@destptr := *+1
sta dummy1234,x
dex
bpl :-
sta ALTZPON
lda LCBANK1
lda LCBANK1
rts
.endproc
.proc copy_desktop_orig_prefix
stax @destptr
sta ALTZPOFF
lda LCBANK2
lda LCBANK2
ldx desktop_orig_prefix
: lda desktop_orig_prefix,x
@destptr := *+1
sta dummy1234,x
dex
bpl :-
sta ALTZPON
lda LCBANK1
lda LCBANK1
rts
.endproc
;;; ============================================================
;;; For entry copied ("down loaded") to RAM card, compose path
;;; using RAM card prefix plus last two segments of path
;;; (e.g. "/RAM" + "/" + "MOUSEPAINT/MP.SYSTEM") into path_buffer
.proc compose_downloaded_entry_path
sta entry_num
;; Initialize buffer
addr_call copy_ramcard_prefix, path_buffer
;; Find entry path
lda entry_num
jsr a_times_64
addax #run_list_paths, $06
ldy #0
lda ($06),y
sta prefix_length
;; Walk back one segment
tay
: lda ($06),y
and #CHAR_MASK
cmp #'/'
beq :+
dey
bne :-
: dey
;; Walk back a second segment
: lda ($06),y
and #CHAR_MASK
cmp #'/'
beq :+
dey
bne :-
: dey
;; Append last two segments to path
ldx path_buffer
: inx
iny
lda ($06),y
sta path_buffer,x
cpy prefix_length
bne :-
stx path_buffer
ldax #path_buffer
rts
entry_num:
.byte 0
prefix_length:
.byte 0
.endproc
;;; ============================================================
.proc cmd_about
yax_call invoke_dialog_proc, index_about_dialog, $0000
jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
.proc cmd_deskacc_impl
ptr := $6
.define prefix "Desk.acc/"
prefix_length = .strlen(prefix)
str_desk_acc:
PASCAL_STRING prefix, prefix_length + 15
start: jsr reset_grafport3
jsr set_watch_cursor
;; Find DA name
lda menu_click_params::item_num ; menu item index (1-based)
sec
sbc #3 ; About and separator before first item
jsr a_times_16
addax #desk_acc_names, ptr
;; Compute total length
ldy #0
lda (ptr),y
tay
clc
adc #prefix_length
pha
tax
;; Append name to path
: lda ($06),y
sta str_desk_acc,x
dex
dey
bne :-
pla
sta str_desk_acc ; update length
;; Convert spaces to periods
ldx str_desk_acc
: lda str_desk_acc,x
cmp #' '
bne nope
lda #'.'
sta str_desk_acc,x
nope: dex
bne :-
ldax #str_desk_acc
;; fall through
.endproc
cmd_deskacc := cmd_deskacc_impl::start
;;; ============================================================
;;; Invoke Desk Accessory
;;; Input: A,X = address of pathnane buffer
.proc invoke_desk_acc
stax open_pathname
;; Load the DA
jsr open
bmi done
lda open_ref_num
sta read_ref_num
sta close_ref_num
jsr read
jsr close
copy #$80, running_da_flag
;; Invoke it
jsr set_pointer_cursor
jsr reset_grafport3
jsr DA_LOAD_ADDRESS
lda #0
sta running_da_flag
;; Restore state
jsr reset_grafport3
jsr redraw_windows_and_desktop
done: jsr set_pointer_cursor
rts
open: yax_call MLI_RELAY, OPEN, open_params
bne :+
rts
: lda #warning_msg_insert_system_disk
jsr warning_dialog_proc_num
beq open ; ok, so try again
return #$FF ; cancel, so fail
read: yax_jump MLI_RELAY, READ, read_params
close: yax_jump MLI_RELAY, CLOSE, close_params
zp_use_flag1:
.byte $80
DEFINE_OPEN_PARAMS open_params, 0, DA_IO_BUFFER
open_ref_num := open_params::ref_num
open_pathname := open_params::pathname
DEFINE_READ_PARAMS read_params, DA_LOAD_ADDRESS, DA_MAX_SIZE
read_ref_num := read_params::ref_num
DEFINE_CLOSE_PARAMS close_params
close_ref_num := close_params::ref_num
.endproc
;;; ============================================================
;; high bit set while a DA is running
running_da_flag:
.byte 0
;;; ============================================================
.proc cmd_copy_file
jsr set_watch_cursor
lda #dynamic_routine_common
jsr load_dynamic_routine
bmi L4CD6
lda #dynamic_routine_file_copy
jsr load_dynamic_routine
bmi L4CD6
jsr set_pointer_cursor
lda #$00
jsr dynamic_routine_5000
pha
jsr set_watch_cursor
lda #dynamic_routine_restore5000
jsr restore_dynamic_routine
jsr set_pointer_cursor
pla
bpl :+
jmp L4CD6
;; --------------------------------------------------
: jsr copy_paths_and_split_name
jsr redraw_windows_and_desktop
jsr jt_copy_file
L4CD6: pha
jsr set_pointer_cursor
pla
bpl :+
jmp redraw_windows_and_desktop
: addr_call find_window_for_path, path_buf4
beq :+
pha
jsr update_used_free_for_vol_windows
pla
jmp select_and_refresh_window
;; --------------------------------------------------
;; Update used/free for windows for same vol as path_buf4
: ldy #1
@loop: iny
lda path_buf4,y
cmp #'/'
beq :+
cpy path_buf4
bne @loop
iny
: dey
sty path_buf4
addr_call find_windows_for_prefix, path_buf4
ldax #path_buf4
ldy path_buf4
jsr update_vol_used_free_for_found_windows
jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
;;; Copy string at ($6) to path_buf3, string at ($8) to path_buf4,
;;; split filename off path_buf4 and store in filename_buf
.proc copy_paths_and_split_name
;; Copy string at $6 to path_buf3
ldy #0
lda ($06),y
tay
: lda ($06),y
sta path_buf3,y
dey
bpl :-
;; Copy string at $8 to path_buf4
ldy #0
lda ($08),y
tay
: lda ($08),y
sta path_buf4,y
dey
bpl :-
addr_call find_last_path_segment, path_buf4
;; Copy filename part to buf
ldx #1
iny
iny
: lda path_buf4,y
sta filename_buf,x
cpy path_buf4
beq :+
iny
inx
jmp :-
: stx filename_buf
;; And remove from path_buf4
lda path_buf4
sec
sbc filename_buf
sta path_buf4
dec path_buf4
rts
.endproc
;;; ============================================================
.proc cmd_delete_file
jsr set_watch_cursor
lda #dynamic_routine_common
jsr load_dynamic_routine
bmi L4D9D
lda #dynamic_routine_file_delete
jsr load_dynamic_routine
bmi L4D9D
jsr set_pointer_cursor
lda #$01
jsr dynamic_routine_5000
pha
jsr set_watch_cursor
lda #dynamic_routine_restore5000
jsr restore_dynamic_routine
jsr set_pointer_cursor
pla
bpl :+
jmp L4D9D
: ldy #0
lda ($06),y
tay
: lda ($06),y
sta path_buf3,y
dey
bpl :-
jsr redraw_windows_and_desktop
jsr jt_delete_file
L4D9D: pha
jsr set_pointer_cursor
pla
bpl :+
jmp redraw_windows_and_desktop
: addr_call find_last_path_segment, path_buf3
sty path_buf3
addr_call find_window_for_path, path_buf3
beq :+
pha
jsr update_used_free_for_vol_windows
pla
jmp select_and_refresh_window
;; --------------------------------------------------
;; Update used/free for windows for same vol as path_buf3
: ldy #1
@loop: iny
lda path_buf3,y
cmp #'/'
beq :+
cpy path_buf3
bne @loop
iny
: dey
sty path_buf3
addr_call find_windows_for_prefix, path_buf3
ldax #path_buf3
ldy path_buf3
jsr update_vol_used_free_for_found_windows
jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
;;; Helper for "Open" actions - if Apple-key is down, record
;;; the parent window to close.
.proc set_window_to_close_after_open
lda BUTN0 ; Modifier down?
ora BUTN1
bmi :+ ; Yep
lda #0
beq store ; always
: lda selected_window_index
store: sta window_id_to_close
rts
.endproc
;;; ============================================================
.proc cmd_open
ptr := $06
;; Source window to close?
jsr set_window_to_close_after_open
ldx #0
stx dir_count
L4DEC: cpx selected_icon_count
bne :+
;; Were any directories opened?
lda dir_count
beq done
jsr clear_selection
;; Close previous active window, depending on source/modifiers
bit menu_kbd_flag ; If keyboard (Apple-O) ignore. (see issue #9)
bmi done ; Yep, ignore.
jsr close_window_after_open
done: rts
: txa
pha
lda selected_icon_list,x
jsr icon_entry_lookup
stax ptr
ldy #IconEntry::win_type
lda (ptr),y
and #icon_entry_type_mask
cmp #icon_entry_type_trash
beq next_file
cmp #icon_entry_type_dir
bne maybe_open_file
;; Directory
ldy #0
lda (ptr),y
jsr open_folder_or_volume_icon
inc dir_count
next_file:
pla
tax
inx
jmp L4DEC
;; File (executable or data)
maybe_open_file:
sta L4E71
lda selected_icon_count
cmp #2 ; multiple files open?
bcs next_file ; don't try to invoke
pla
lda active_window_id
jsr window_path_lookup
stax $06
ldy #0
lda ($06),y
tay
L4E34: lda ($06),y
sta buf_win_path,y
dey
bpl L4E34
lda selected_icon_list
jsr icon_entry_lookup
stax $06
ldy #$09
lda ($06),y
tax
clc
adc #$09
tay
dex
dey
L4E51: lda ($06),y
sta buf_filename2-1,x
dey
dex
bne L4E51
ldy #$09
lda ($06),y
tax
dex
dex
stx buf_filename2
lda L4E71
cmp #$20
bcc L4E6E
lda L4E71
L4E6E: jmp launch_file
L4E71: .byte 0
;; Count of opened volumes/folders; if non-zero,
;; selection must be cleared before finishing.
dir_count:
.byte 0
last_active_window_id:
.byte 0
.endproc
;;; ============================================================
;;; Close parent window after open, if needed. Done by activating then closing.
;;; Modifies findwindow_window_id
.proc close_window_after_open
lda window_id_to_close
beq done
pha
sta findwindow_window_id
jsr handle_inactive_window_click
pla
jsr close_window
done: rts
.endproc
;;; ============================================================
.proc cmd_close
icon_ptr := $06
lda active_window_id
bne :+
rts
: jmp close_window
.endproc
;;; ============================================================
.proc cmd_close_all
lda active_window_id ; current window
beq done ; nope, done!
jsr close_window ; close it...
jmp cmd_close_all ; and try again
done: rts
.endproc
;;; ============================================================
.proc cmd_disk_copy
lda #dynamic_routine_disk_copy
jsr load_dynamic_routine
bmi fail
jmp dynamic_routine_800
fail: rts
.endproc
;;; ============================================================
.proc cmd_new_folder_impl
ptr := $06
.proc new_folder_dialog_params
phase: .byte 0 ; window_id?
win_path_ptr: .word 0
.endproc
;; access = destroy/rename/write/read
DEFINE_CREATE_PARAMS create_params, path_buffer, ACCESS_DEFAULT, FT_DIRECTORY,, ST_LINKED_DIRECTORY
path_buffer:
.res 65, 0 ; buffer is used elsewhere too
start: copy active_window_id, new_folder_dialog_params::phase
yax_call invoke_dialog_proc, index_new_folder_dialog, new_folder_dialog_params
L4FC6: lda active_window_id
beq L4FD4
jsr window_path_lookup
stax new_folder_dialog_params::win_path_ptr
L4FD4: copy #$80, new_folder_dialog_params::phase
yax_call invoke_dialog_proc, index_new_folder_dialog, new_folder_dialog_params
beq :+
jmp done ; Cancelled
: stx ptr+1
stx name_ptr+1
sty ptr
sty name_ptr
;; Copy path
ldy #0
lda (ptr),y
tay
: lda (ptr),y
sta path_buffer,y
dey
bpl :-
;; Create with current date
COPY_STRUCT DateTime, DATELO, create_params::create_date
;; Create folder
MLI_RELAY_CALL CREATE, create_params
beq success
;; Failure
jsr ShowAlert
copy16 name_ptr, new_folder_dialog_params::win_path_ptr
jmp L4FC6
success:
copy #$40, new_folder_dialog_params::phase
yax_call invoke_dialog_proc, index_new_folder_dialog, new_folder_dialog_params
addr_call find_last_path_segment, path_buffer
sty path_buffer
addr_call find_window_for_path, path_buffer
beq done
jsr select_and_refresh_window
;; TODO: Select new folder
;; * LoadActiveWindowIconTable
;; * Iterate icons
;; * Compare name w/ name from dialog
;; * If match, make it selected
;; TODO: Scroll into view
done: jmp redraw_windows_and_desktop
name_ptr:
.addr 0
.endproc
cmd_new_folder := cmd_new_folder_impl::start
path_buffer := cmd_new_folder_impl::path_buffer ; ???
;;; ============================================================
.proc cmd_check_or_eject
buffer := $1800
eject:
lda #$80
bne common ; always
check: lda #0
common: sta eject_flag
;; Ensure that volumes are selected
lda selected_window_index
beq :+
done: rts
;; And if there's only one, it's not Trash
: lda selected_icon_count
beq done
cmp #1 ; single selection
bne :+
lda selected_icon_list
cmp trash_icon_num ; if it's Trash, skip it
beq done
;; Record non-Trash selected volume icons to a buffer
: lda #0
tax
tay
loop1: lda selected_icon_list,y
cmp trash_icon_num
beq :+
sta buffer,x
inx
: iny
cpy selected_icon_count
bne loop1
dex
stx count
;; Do the ejection
bit eject_flag
bpl :+
jsr jt_eject
:
;; Check each of the recorded volumes
loop2: ldx count
lda buffer,x
sta drive_to_refresh ; icon number
jsr cmd_check_single_drive_by_icon_number
dec count
bpl loop2
;; And finish up nicely
jmp redraw_windows_and_desktop
count: .byte 0
eject_flag:
.byte 0
.endproc
cmd_eject := cmd_check_or_eject::eject
cmd_check_drive := cmd_check_or_eject::check
;;; ============================================================
.proc cmd_quit_impl
;; TODO: Assumes prefix is retained. Compose correct path.
quit_code_io := $800
quit_code_addr := $1000
quit_code_size := $400
DEFINE_OPEN_PARAMS open_params, str_quit_code, quit_code_io
DEFINE_READ_PARAMS read_params, quit_code_addr, quit_code_size
DEFINE_CLOSE_PARAMS close_params
str_quit_code: PASCAL_STRING "Quit.tmp"
reset_handler:
;; Restore DeskTop Main expected state...
sta ALTZPON
lda LCBANK1
lda LCBANK1
start:
MLI_RELAY_CALL OPEN, open_params
bne fail
lda open_params::ref_num
sta read_params::ref_num
sta close_params::ref_num
MLI_RELAY_CALL READ, read_params
MLI_RELAY_CALL CLOSE, close_params
;; Restore system state: devices, /RAM, ROM/ZP banks.
jsr restore_system
quit: jmp quit_code_addr
fail: jsr ShowAlert
rts
.endproc
cmd_quit := cmd_quit_impl::start
reset_handler := cmd_quit_impl::reset_handler
;;; ============================================================
;;; Exit DHR, restore device list, reformat /RAM.
;;; Returns with ALTZPOFF and ROM banked in.
.proc restore_system
jsr restore_device_list
;; Switch back to main ZP, preserving return address.
pla
tax
pla
sta ALTZPOFF
pha
txa
pha
;; Switch back to color DHR mode
jsr set_color_mode
;; Exit graphics mode entirely
lda ROMIN2
jsr SETVID
jsr SETKBD
jsr INIT
jsr HOME
sta TXTSET
sta LOWSCR
sta LORES
sta MIXCLR
sta DHIRESOFF
sta CLRALTCHAR
sta CLR80VID
sta CLR80COL
;; Restore /RAM if possible.
jmp maybe_reformat_ram
.endproc
;;; ============================================================
.proc cmd_view_by_icon
ldx active_window_id
bne :+
rts
: dex
lda win_view_by_table,x
bne :+ ; not by icon
rts
;; View by icon
entry:
: jsr LoadActiveWindowIconTable
ldx #$00
txa
: cpx cached_window_icon_count
beq :+
sta cached_window_icon_list,x
inx
jmp :-
: sta cached_window_icon_count
lda #0
ldx active_window_id
dex
sta win_view_by_table,x
jsr update_view_menu_check
copy active_window_id, getwinport_params2::window_id
jsr get_port2
jsr offset_grafport2_and_set
jsr set_penmode_copy
MGTK_RELAY_CALL MGTK::PaintRect, grafport2::cliprect
lda active_window_id
jsr compute_window_dimensions
stax L51EB
sty L51ED
lda active_window_id
jsr window_lookup
stax $06
ldy #$1F
lda #$00
L5162: sta ($06),y
dey
cpy #$1B
bne L5162
ldy #$23
ldx #$03
L516D: lda L51EB,x
sta ($06),y
dey
dex
bpl L516D
lda active_window_id
jsr create_file_icon_ep2
copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
jsr cached_icons_screen_to_window
copy #0, L51EF
L518D: lda L51EF
cmp cached_window_icon_count
beq L51A7
tax
lda cached_window_icon_list,x
jsr icon_entry_lookup
ldy #IconTK::ADD_ICON
jsr ITK_RELAY ; icon entry addr in A,X
inc L51EF
jmp L518D
L51A7: jsr reset_grafport3
jsr cached_icons_window_to_screen
jsr StoreWindowIconTable
jsr update_scrollbars
lda selected_window_index
beq finish
lda selected_icon_count
beq finish
sta L51EF
L51C0: ldx L51EF
lda selected_icon_count,x
sta icon_param
jsr icon_screen_to_window
jsr offset_grafport2_and_set
ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, icon_param
lda icon_param
jsr icon_window_to_screen
dec L51EF
bne L51C0
finish: jmp LoadDesktopIconTable
L51EB: .word 0
L51ED: .byte 0
.byte 0
L51EF: .byte 0
.endproc
;;; ============================================================
.proc view_by_nonicon_common
ldx active_window_id
dex
sta win_view_by_table,x
jsr LoadActiveWindowIconTable
jsr sort_records
jsr StoreWindowIconTable
copy active_window_id, getwinport_params2::window_id
jsr get_port2
jsr offset_grafport2_and_set
jsr set_penmode_copy
MGTK_RELAY_CALL MGTK::PaintRect, grafport2::cliprect
lda active_window_id
jsr compute_window_dimensions
stax L5263
sty L5265
lda active_window_id
jsr window_lookup
stax $06
ldy #$1F
lda #$00
L523B: sta ($06),y
dey
cpy #$1B
bne L523B
ldy #$23
ldx #$03
L5246: lda L5263,x
sta ($06),y
dey
dex
bpl L5246
copy #$80, draw_window_header_flag
jsr reset_grafport3
jsr L6C19
jsr update_scrollbars
copy #0, draw_window_header_flag
rts
L5263: .word 0
L5265: .byte 0
.byte 0
.endproc
;;; ============================================================
.proc cmd_view_by_name
ldx active_window_id
bne :+
rts
: dex
lda win_view_by_table,x
cmp #view_by_name
bne :+
rts
: cmp #$00
bne :+
jsr close_active_window
: jsr update_view_menu_check
lda #view_by_name
jmp view_by_nonicon_common
.endproc
;;; ============================================================
.proc cmd_view_by_date
ldx active_window_id
bne :+
rts
: dex
lda win_view_by_table,x
cmp #view_by_date
bne :+
rts
: cmp #$00
bne :+
jsr close_active_window
: jsr update_view_menu_check
lda #view_by_date
jmp view_by_nonicon_common
.endproc
;;; ============================================================
.proc cmd_view_by_size
ldx active_window_id
bne :+
rts
: dex
lda win_view_by_table,x
cmp #view_by_size
bne :+
rts
: cmp #$00
bne :+
jsr close_active_window
: jsr update_view_menu_check
lda #view_by_size
jmp view_by_nonicon_common
.endproc
;;; ============================================================
.proc cmd_view_by_type
ldx active_window_id
bne :+
rts
: dex
lda win_view_by_table,x
cmp #view_by_type
bne :+
rts
: cmp #$00
bne :+
jsr close_active_window
: jsr update_view_menu_check
lda #view_by_type
jmp view_by_nonicon_common
.endproc
;;; ============================================================
.proc update_view_menu_check
;; Uncheck last checked
lda #MGTK::checkitem_uncheck
sta checkitem_params::check
MGTK_RELAY_CALL MGTK::CheckItem, checkitem_params
;; Check the new one
lda menu_click_params::item_num ; index of View menu item to check
sta checkitem_params::menu_item
lda #MGTK::checkitem_check
sta checkitem_params::check
MGTK_RELAY_CALL MGTK::CheckItem, checkitem_params
rts
.endproc
;;; ============================================================
.proc close_active_window
ITK_RELAY_CALL IconTK::CLOSE_WINDOW, active_window_id
jsr LoadActiveWindowIconTable
lda icon_count
sec
sbc cached_window_icon_count
sta icon_count
jsr free_cached_window_icons
done: jsr StoreWindowIconTable
jmp LoadDesktopIconTable
.endproc
;;; ============================================================
.proc free_cached_window_icons
copy #0, index
loop: ldx index
cpx cached_window_icon_count
beq done
lda cached_window_icon_list,x
pha
jsr FreeIcon
pla
jsr find_window_for_dir_icon
bne :+
copy #$FF, window_to_dir_icon_table,x ; $FF = dir icon freed
: ldx index
copy #0, cached_window_icon_list,x
inc index
bne loop
done: rts
index: .byte 0
.endproc
;;; ============================================================
;;; Set after format, erase, failed open, etc.
;;; Used by 'cmd_check_single_drive_by_XXX'; may be unit number
;;; or device index depending on call site.
drive_to_refresh:
.byte 0
;;; ============================================================
.proc cmd_format_disk
lda #dynamic_routine_format_erase
jsr load_dynamic_routine
bmi fail
lda #$04
jsr dynamic_routine_800
bne :+
stx drive_to_refresh ; unit number
jsr redraw_windows_and_desktop
jsr cmd_check_single_drive_by_unit_number
: jmp redraw_windows_and_desktop
fail: rts
.endproc
;;; ============================================================
.proc cmd_erase_disk
lda #dynamic_routine_format_erase
jsr load_dynamic_routine
bmi done
lda #$05
jsr dynamic_routine_800
bne done
stx drive_to_refresh ; unit number
jsr redraw_windows_and_desktop
jsr cmd_check_single_drive_by_unit_number
done: jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
.proc cmd_get_info
jsr jt_get_info
jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
.proc cmd_get_size
jsr jt_get_size
jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
.proc cmd_unlock
jsr jt_unlock
jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
.proc cmd_lock
jsr jt_lock
jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
.proc cmd_delete_selection
copy trash_icon_num, drag_drop_param
jmp process_drop
.endproc
;;; ============================================================
.proc cmd_rename_icon
jsr jt_rename_icon
pha
jsr redraw_windows_and_desktop
pla
beq :+
rts
: lda selected_window_index
bne common
;; Volume icon on desktop
;; Copy selected icons (except Trash)
ldx #0
ldy #0
loop: lda selected_icon_list,x
cmp #1 ; Trash
beq :+
sta selected_vol_icon_list,y
iny
: inx
cpx selected_icon_count
bne loop
sty selected_vol_icon_count
common: copy #$FF, counter ; immediately incremented to 0
;; Loop over selection
next_icon:
inc counter
lda counter
cmp selected_icon_count
bne not_done
lda selected_window_index
bne :+
jmp finish_with_vols
: jmp select_and_refresh_window
not_done:
tax
lda selected_icon_list,x
jsr find_window_for_dir_icon
bne next_icon ; not found
inx ; 0-based index to 1-based window_id
txa
jsr window_path_lookup
stax $06
ldy #0
lda ($06),y
tay
lda $06
jsr find_windows_for_prefix
lda found_windows_count
beq next_icon
L53EF: dec found_windows_count
ldx found_windows_count
lda found_windows_list,x
cmp active_window_id
beq L5403
sta findwindow_window_id
jsr handle_inactive_window_click
L5403: jsr close_window
lda found_windows_count
bne L53EF
jmp next_icon
finish_with_vols:
ldx selected_vol_icon_count
jmp next_vol
: lda selected_vol_icon_list,x
sta drive_to_refresh ; icon number
jsr cmd_check_single_drive_by_icon_number
ldx selected_vol_icon_count
dec selected_vol_icon_count
next_vol:
dex
bpl :-
jmp redraw_windows_and_desktop
counter:
.byte 0
selected_vol_icon_count:
.byte 0
selected_vol_icon_list:
.res 9, 0
.endproc
;;; ============================================================
;;; Handle keyboard-based icon selection ("highlighting")
.proc cmd_higlight
jmp L544D
L5444: .byte 0
L5445: .byte 0
L5446: .byte 0
L5447: .byte 0
L5448: .byte 0
L5449: .byte 0
L544A: .byte 0
.byte 0
.byte 0
L544D:
copy #0, $1800
lda active_window_id
bne L545A
jmp L54C5
L545A: tax
dex
lda win_view_by_table,x
bpl L5464 ; by icon
jmp L54C5
;; View by icon
L5464: jsr LoadActiveWindowIconTable
lda active_window_id
jsr window_lookup
stax $06
ldy #MGTK::Winfo::port+MGTK::GrafPort::maprect
L5479: lda ($06),y
sta tmp_rect-(MGTK::Winfo::port+MGTK::GrafPort::maprect),y
iny
cpy #MGTK::Winfo::port+MGTK::GrafPort::maprect+8
bne L5479
ldx #$00
L5485: cpx cached_window_icon_count
beq L54BD
txa
pha
lda cached_window_icon_list,x
sta icon_param
jsr icon_screen_to_window
ITK_RELAY_CALL IconTK::ICON_IN_RECT, icon_param
pha
lda icon_param
jsr icon_window_to_screen
pla
beq L54B7
pla
pha
tax
lda cached_window_icon_list,x
ldx $1800
sta $1801,x
inc $1800
L54B7: pla
tax
inx
jmp L5485
;; No window icons
L54BD: jsr LoadDesktopIconTable
L54C5: ldx $1800
ldy #$00
L54CA: lda cached_window_icon_list,y
sta $1801,x
iny
inx
cpy cached_window_icon_count
bne L54CA
lda $1800
clc
adc cached_window_icon_count
sta $1800
copy #0, L544A
ldax #$03FF
L54EA: sta L5444,x
dex
bpl L54EA
L54F0: ldx L544A
L54F3: lda $1801,x
asl a
tay
copy16 icon_entry_address_table,y, $06
ldy #$06
lda ($06),y
cmp L5447
beq L5510
bcc L5532
jmp L5547
L5510: dey
lda ($06),y
cmp L5446
beq L551D
bcc L5532
jmp L5547
L551D: dey
lda ($06),y
cmp L5445
beq L552A
bcc L5532
jmp L5547
L552A: dey
lda ($06),y
cmp L5444
bcs L5547
L5532: lda $1801,x
stx L5449
sta L5448
ldy #$03
L553D: lda ($06),y
sta L5444-3,y
iny
cpy #$07
bne L553D
L5547: inx
cpx $1800
bne L54F3
ldx L544A
lda $1801,x
tay
lda L5448
sta $1801,x
ldx L5449
tya
sta $1801,x
ldax #$03FF
L5565: sta L5444,x
dex
bpl L5565
inc L544A
ldx L544A
cpx $1800
beq L5579
jmp L54F0
L5579: copy #0, L544A
jsr clear_selection
L5581: jsr L55F0
L5584: jsr get_event
lda event_kind
cmp #MGTK::EventKind::key_down
beq L5595
cmp #MGTK::EventKind::button_down
bne L5584
jmp L55D1
L5595: lda event_params+MGTK::Event::key
and #CHAR_MASK
cmp #CHAR_RETURN
beq L55D1
cmp #CHAR_ESCAPE
beq L55D1
cmp #CHAR_LEFT
beq L55BE
cmp #CHAR_RIGHT
bne L5584
ldx L544A
inx
cpx $1800
bne L55B5
ldx #$00
L55B5: stx L544A
jsr L562C
jmp L5581
L55BE: ldx L544A
dex
bpl L55C8
ldx $1800
dex
L55C8: stx L544A
jsr L562C
jmp L5581
L55D1: ldx L544A
lda $1801,x
sta selected_icon_list
jsr icon_entry_lookup
stax $06
ldy #IconEntry::win_type
lda ($06),y
and #icon_entry_winid_mask
sta selected_window_index
lda #1
sta selected_icon_count
rts
L55F0: ldx L544A
lda $1801,x
sta icon_param
jsr icon_entry_lookup
stax $06
ldy #IconEntry::win_type
lda ($06),y
and #icon_entry_winid_mask
sta getwinport_params2::window_id
beq L5614
jsr L56F9
lda icon_param
jsr icon_screen_to_window
L5614: ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, icon_param
lda getwinport_params2::window_id
beq L562B
lda icon_param
jsr icon_window_to_screen
jsr reset_grafport3
L562B: rts
L562C: lda icon_param
jsr icon_entry_lookup
stax $06
ldy #IconEntry::win_type
lda ($06),y
and #icon_entry_winid_mask
sta getwinport_params2::window_id
beq L564A
jsr L56F9
lda icon_param
jsr icon_screen_to_window
L564A: ITK_RELAY_CALL IconTK::UNHIGHLIGHT_ICON, icon_param
lda getwinport_params2::window_id
beq L5661
lda icon_param
jsr icon_window_to_screen
jsr reset_grafport3
L5661: rts
.endproc
;;; ============================================================
.proc cmd_select_all
lda selected_icon_count
beq L566A
jsr clear_selection
L566A: ldx active_window_id
beq L5676
dex
lda win_view_by_table,x
bpl L5676 ; view by icons
rts
L5676: jsr LoadActiveWindowIconTable
lda cached_window_icon_count
bne L5687
jmp L56F0
L5687: ldx cached_window_icon_count
dex
L568B: copy cached_window_icon_list,x, selected_icon_list,x
dex
bpl L568B
copy cached_window_icon_count, selected_icon_count
copy active_window_id, selected_window_index
copy selected_window_index, LE22C
beq L56AB
jsr L56F9
L56AB: lda selected_icon_count
sta L56F8
dec L56F8
L56B4: ldx L56F8
copy selected_icon_list,x, icon_param2
jsr icon_entry_lookup
stax $06
lda LE22C
beq L56CF
lda icon_param2
jsr icon_screen_to_window
L56CF: ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, icon_param2
lda LE22C
beq L56E3
lda icon_param2
jsr icon_window_to_screen
L56E3: dec L56F8
bpl L56B4
lda selected_window_index
beq L56F0
jsr reset_grafport3
L56F0: jmp LoadDesktopIconTable
L56F8: .byte 0
.endproc
;;; ============================================================
.proc L56F9
sta getwinport_params2::window_id
jsr get_port2
jmp offset_grafport2_and_set
.endproc
;;; ============================================================
;;; Initiate keyboard-based resizing
.proc cmd_resize
MGTK_RELAY_CALL MGTK::KeyboardMouse
jmp handle_resize_click
.endproc
;;; ============================================================
;;; Initiate keyboard-based window moving
.proc cmd_move
MGTK_RELAY_CALL MGTK::KeyboardMouse
jmp handle_title_click
.endproc
;;; ============================================================
;;; Cycle Through Windows
.proc cmd_cycle_windows
;; Need at least two windows to cycle.
lda num_open_windows
cmp #2
bcc done
ldx active_window_id
;; Search upwards through window-icon map to find next.
;; ID is 1-based, table is 0-based, so don't need to start
;; with an increment
loop: cpx #8
bne :+
ldx #0
: lda window_to_dir_icon_table,x
bne found ; 0 = window free
inx
bne loop ; always
found: inx
stx findwindow_window_id
jmp handle_inactive_window_click
done: rts
.endproc
;;; ============================================================
;;; Keyboard-based scrolling of window contents
.proc cmd_scroll
jsr get_active_window_scroll_info
loop: jsr get_event
lda event_kind
cmp #MGTK::EventKind::button_down
beq done
cmp #MGTK::EventKind::key_down
bne loop
lda event_key
cmp #CHAR_RETURN
beq done
cmp #CHAR_ESCAPE
bne :+
done: jmp LoadDesktopIconTable
;; Horizontal ok?
: bit horiz_scroll_flag
bmi :+
jmp vertical
: cmp #CHAR_RIGHT
bne :+
jsr scroll_right
jmp loop
: cmp #CHAR_LEFT
bne vertical
jsr scroll_left
jmp loop
;; Vertical ok?
vertical:
bit vert_scroll_flag
bmi :+
jmp loop
: cmp #CHAR_DOWN
bne :+
jsr scroll_down
jmp loop
: cmp #CHAR_UP
bne loop
jsr scroll_up
jmp loop
.endproc
;;; ============================================================
.proc get_active_window_scroll_info
jsr LoadActiveWindowIconTable
ldx active_window_id
dex
lda win_view_by_table,x
sta active_window_view_by
jsr get_active_window_hscroll_info
sta horiz_scroll_pos
stx horiz_scroll_max
sty horiz_scroll_flag
jsr get_active_window_vscroll_info
sta vert_scroll_pos
stx vert_scroll_max
sty vert_scroll_flag
rts
.endproc
;;; ============================================================
scroll_right: ; elevator right / contents left
lda horiz_scroll_pos
ldx horiz_scroll_max
jsr do_scroll_right
sta horiz_scroll_pos
rts
scroll_left: ; elevator left / contents right
lda horiz_scroll_pos
jsr do_scroll_left
sta horiz_scroll_pos
rts
scroll_down: ; elevator down / contents up
lda vert_scroll_pos
ldx vert_scroll_max
jsr do_scroll_down
sta vert_scroll_pos
rts
scroll_up: ; elevator up / contents down
lda vert_scroll_pos
jsr do_scroll_up
sta vert_scroll_pos
rts
horiz_scroll_flag: .byte 0 ; can scroll horiz?
vert_scroll_flag: .byte 0 ; can scroll vert?
horiz_scroll_pos: .byte 0
horiz_scroll_max: .byte 0
vert_scroll_pos: .byte 0
vert_scroll_max: .byte 0
.proc do_scroll_right
stx max
cmp max
beq :+
sta updatethumb_stash
inc updatethumb_stash
copy #MGTK::Ctl::horizontal_scroll_bar, updatethumb_which_ctl
jsr update_scroll_thumb
lda updatethumb_stash
: rts
max: .byte 0
.endproc
.proc do_scroll_left
beq :+
sta updatethumb_stash
dec updatethumb_stash
copy #MGTK::Ctl::horizontal_scroll_bar, updatethumb_which_ctl
jsr update_scroll_thumb
lda updatethumb_stash
: rts
.byte 0
.endproc
.proc do_scroll_down
stx max
cmp max
beq :+
sta updatethumb_stash
inc updatethumb_stash
copy #MGTK::Ctl::vertical_scroll_bar, updatethumb_which_ctl
jsr update_scroll_thumb
lda updatethumb_stash
: rts
max: .byte 0
.endproc
.proc do_scroll_up
beq :+
sta updatethumb_stash
dec updatethumb_stash
copy #MGTK::Ctl::vertical_scroll_bar, updatethumb_which_ctl
jsr update_scroll_thumb
lda updatethumb_stash
: rts
.byte 0
.endproc
;;; Output: A = hscroll pos, X = hscroll max, Y = hscroll active flag (high bit)
.proc get_active_window_hscroll_info
ptr := $06
lda active_window_id
jsr window_lookup
stax ptr
ldy #MGTK::Winfo::hthumbmax
lda (ptr),y
tax
iny ; hthumbpos
lda (ptr),y
pha
ldy #MGTK::Winfo::hscroll
lda (ptr),y
and #$01 ; active flag
clc
ror a
ror a ; shift to high bit
tay
pla
rts
.endproc
;;; Output: A = vscroll pos, X = vscroll max, Y = vscroll active flag (high bit)
.proc get_active_window_vscroll_info
ptr := $06
lda active_window_id
jsr window_lookup
stax ptr
ldy #MGTK::Winfo::vthumbmax
lda (ptr),y
tax
iny
lda (ptr),y
pha
ldy #MGTK::Winfo::vscroll
lda (ptr),y
and #$01 ; active flag
clc
ror a
ror a ; shift to high bit
tay
pla
rts
.endproc
;;; ============================================================
.proc cmd_check_drives
copy #0, pending_alert
jsr LoadDesktopIconTable
jsr cmd_close_all
jsr clear_selection
ldx cached_window_icon_count
dex
L5916: lda cached_window_icon_list,x
cmp trash_icon_num
beq L5942
txa
pha
lda cached_window_icon_list,x
sta icon_param
copy #0, cached_window_icon_list,x
ITK_RELAY_CALL IconTK::REMOVE_ICON, icon_param
lda icon_param
jsr FreeIcon
dec cached_window_icon_count
dec icon_count
pla
tax
L5942: dex
bpl L5916
;; Enumerate DEVLST in reverse order (most important volumes first)
ldy DEVCNT
sty devlst_index
@loop: ldy devlst_index
inc cached_window_icon_count
inc icon_count
lda #0
sta device_to_icon_map,y
lda DEVLST,y
ldx cached_window_icon_count
jsr create_volume_icon ; A = unit num, Y = device num, X = icon index
cmp #ERR_DUPLICATE_VOLUME
bne :+
lda #ERR_DUPLICATE_VOL_NAME
sta pending_alert
: dec devlst_index
lda devlst_index
bpl @loop
ldx #0
L5976: cpx cached_window_icon_count
bne L5986
lda pending_alert
beq L5983
jsr ShowAlert
L5983: jmp StoreWindowIconTable
L5986: txa
pha
lda cached_window_icon_list,x
cmp trash_icon_num
beq L5998
jsr icon_entry_lookup
ldy #IconTK::ADD_ICON
jsr ITK_RELAY ; icon entry addr in A,X
L5998: pla
tax
inx
jmp L5976
.endproc
;;; ============================================================
devlst_index:
.byte 0
pending_alert:
.byte 0
;;; ============================================================
;;; Check > [drive] command - obsolete, but core still used
;;; following Format (etc)
;;;
.proc cmd_check_single_drive
;; index in DEVLST
devlst_index := menu_click_params::item_num
;; Check Drive command
by_menu:
lda #$00
beq start
;; After format/erase
by_unit_number:
lda #$80
bne start
;; After open/eject/rename
by_icon_number:
lda #$C0
start: sta check_drive_flags
jsr LoadDesktopIconTable
bit check_drive_flags
bpl explicit_command
bvc after_format_erase
;;; --------------------------------------------------
;;; After an Open/Eject/Rename action
;; Map icon number to index in DEVLST
lda drive_to_refresh
ldy #15
: cmp device_to_icon_map,y
beq :+
dey
bpl :-
: sty previous_icon_count ; BUG: overwritten?
sty devlst_index
jmp common
;;; --------------------------------------------------
;;; After a Format/Erase action
after_format_erase:
;; Map unit number to index in DEVLST
ldy DEVCNT
lda drive_to_refresh
: cmp DEVLST,y
beq :+
dey
bpl :-
iny
: sty previous_icon_count ; BUG: overwritten?
sty devlst_index
jmp common
;;; --------------------------------------------------
;;; Check Drive command
explicit_command:
;; Map menu number to index in DEVLST
lda menu_click_params::item_num
sec
sbc #3
sta devlst_index
;;; --------------------------------------------------
common:
ldy devlst_index
lda device_to_icon_map,y
bne :+
jmp not_in_map
;; Close any associated windows.
;; A = icon number
: jsr icon_entry_lookup
addax #IconEntry::len, $06
ptr := $06
path_buf := $1F00
;; Copy volume path to $1F00
ldy #0
lda (ptr),y
tay
: lda (ptr),y
sta path_buf,y
dey
bpl :-
;; Find all windows with path as prefix, and close them.
dec path_buf
lda #'/'
sta path_buf+1
ldax #path_buf
ldy path_buf
jsr find_windows_for_prefix
lda found_windows_count
beq not_in_map
close_loop:
ldx found_windows_count
beq not_in_map
dex
lda found_windows_list,x
cmp active_window_id
beq :+
sta findwindow_window_id
jsr handle_inactive_window_click
: jsr close_window
dec found_windows_count
jmp close_loop
not_in_map:
jsr redraw_windows_and_desktop
jsr clear_selection
jsr LoadDesktopIconTable
lda devlst_index
tay
pha
lda device_to_icon_map,y
sta icon_param
beq :+
jsr remove_icon_from_window
dec icon_count
lda icon_param
jsr FreeIcon
jsr reset_grafport3
ITK_RELAY_CALL IconTK::REMOVE_ICON, icon_param
: lda cached_window_icon_count
sta previous_icon_count
inc cached_window_icon_count
inc icon_count
pla
tay
lda DEVLST,y
ldx icon_param ; preserve icon index if known
bne :+
ldx cached_window_icon_count
: jsr create_volume_icon ; A = unit num, Y = device num, X = icon index
bit check_drive_flags
bmi add_icon
;; Explicit command
and #$FF ; check create_volume_icon results
beq add_icon
cmp #$2F ; there was an error ($2F = ???)
beq add_icon
pha
jsr StoreWindowIconTable
pla
jsr ShowAlert
rts
add_icon:
lda cached_window_icon_count
cmp previous_icon_count
beq :+
;; If a new icon was added, more work is needed.
ldx cached_window_icon_count
dex
lda cached_window_icon_list,x
jsr icon_entry_lookup
ldy #IconTK::ADD_ICON
jsr ITK_RELAY ; icon entry addr in A,X
: jsr StoreWindowIconTable
jmp redraw_windows_and_desktop
previous_icon_count:
.byte 0
;;; 0 = command, $80 = format/erase, $C0 = open/eject/rename
check_drive_flags:
.byte 0
.endproc
cmd_check_single_drive_by_menu := cmd_check_single_drive::by_menu
cmd_check_single_drive_by_unit_number := cmd_check_single_drive::by_unit_number
cmd_check_single_drive_by_icon_number := cmd_check_single_drive::by_icon_number
;;; ============================================================
.proc cmd_startup_item
ldx menu_click_params::item_num
dex
txa
asl a
asl a
asl a
clc
adc #6
tax
lda startup_menu_item_1,x
sec
sbc #'0'
clc
adc #>$C000 ; compute $Cn00
sta reset_and_invoke_target+1
lda #<$0000
sta reset_and_invoke_target
;; fall through
.endproc
;; also invoked by launcher code
.proc reset_and_invoke
;; Restore system state: devices, /RAM, ROM/ZP banks.
jsr restore_system
;; also used by launcher code
target := *+1
jmp dummy0000 ; self-modified
.endproc
reset_and_invoke_target := reset_and_invoke::target
;;; ============================================================
active_window_view_by:
.byte 0
.proc handle_client_click
jsr LoadActiveWindowIconTable
ldx active_window_id
dex
lda win_view_by_table,x
sta active_window_view_by
;; Restore event coords (following detect_double_click)
COPY_STRUCT MGTK::Point, saved_event_coords, event_coords
MGTK_RELAY_CALL MGTK::FindControl, event_coords
lda findcontrol_which_ctl
bne :+
jmp handle_content_click ; 0 = ctl_not_a_control
: bit double_click_flag
bmi :+
jmp done_client_click ; ignore double click
: cmp #MGTK::Ctl::dead_zone
bne :+
rts
: cmp #MGTK::Ctl::vertical_scroll_bar
bne horiz
;; Vertical scrollbar
lda active_window_id
jsr window_lookup
stax $06
ldy #$05
lda ($06),y
and #$01
bne :+
jmp done_client_click
: jsr get_active_window_scroll_info
lda findcontrol_which_part
cmp #MGTK::Part::thumb
bne :+
jsr do_track_thumb
jmp done_client_click
: cmp #MGTK::Part::up_arrow
bne :+
up: jsr scroll_up
lda #MGTK::Part::up_arrow
jsr check_control_repeat
bpl up
jmp done_client_click
: cmp #MGTK::Part::down_arrow
bne :+
down: jsr scroll_down
lda #MGTK::Part::down_arrow
jsr check_control_repeat
bpl down
jmp done_client_click
: cmp #MGTK::Part::page_down
beq pgdn
pgup: jsr L638C
lda #MGTK::Part::page_up
jsr check_control_repeat
bpl pgup
jmp done_client_click
pgdn: jsr L63EC
lda #MGTK::Part::page_down
jsr check_control_repeat
bpl pgdn
jmp done_client_click
;; Horizontal scrollbar
horiz: lda active_window_id
jsr window_lookup
stax $06
ldy #$04
lda ($06),y
and #$01
bne :+
jmp done_client_click
: jsr get_active_window_scroll_info
lda findcontrol_which_part
cmp #MGTK::Part::thumb
bne :+
jsr do_track_thumb
jmp done_client_click
: cmp #MGTK::Part::left_arrow
bne :+
left: jsr scroll_left
lda #MGTK::Part::left_arrow
jsr check_control_repeat
bpl left
jmp done_client_click
: cmp #MGTK::Part::right_arrow
bne :+
rght: jsr scroll_right
lda #MGTK::Part::right_arrow
jsr check_control_repeat
bpl rght
jmp done_client_click
: cmp #MGTK::Part::page_right
beq pgrt
pglt: jsr L6451
lda #MGTK::Part::page_left
jsr check_control_repeat
bpl pglt
jmp done_client_click
pgrt: jsr L64B0
lda #MGTK::Part::page_right
jsr check_control_repeat
bpl pgrt
jmp done_client_click
done_client_click:
jsr StoreWindowIconTable
jmp LoadDesktopIconTable
.endproc
;;; ============================================================
.proc do_track_thumb
lda findcontrol_which_ctl
sta trackthumb_which_ctl
MGTK_RELAY_CALL MGTK::TrackThumb, trackthumb_params
lda trackthumb_thumbmoved
bne :+
rts
: jsr update_scroll_thumb
jsr StoreWindowIconTable
jmp LoadDesktopIconTable
.endproc
;;; ============================================================
.proc update_scroll_thumb
copy updatethumb_stash, updatethumb_thumbpos
MGTK_RELAY_CALL MGTK::UpdateThumb, updatethumb_params
jsr apply_active_winfo_to_grafport2
jsr L84D1
bit active_window_view_by
bmi :+ ; list view, no icons
jsr cached_icons_window_to_screen
: copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
MGTK_RELAY_CALL MGTK::PaintRect, grafport2::cliprect
jsr reset_grafport3
jmp L6C19
.endproc
;;; ============================================================
;;; Handle mouse held down on scroll arrow/pager
.proc check_control_repeat
sta ctl
jsr peek_event
lda event_kind
cmp #MGTK::EventKind::drag
beq :+
bail: return #$FF ; high bit set = not repeating
: MGTK_RELAY_CALL MGTK::FindControl, event_coords
lda findcontrol_which_ctl
beq bail
cmp #MGTK::Ctl::dead_zone
beq bail
lda findcontrol_which_part
cmp ctl
bne bail
return #0 ; high bit set = repeating
ctl: .byte 0
.endproc
;;; ============================================================
.proc handle_content_click
;; Subsequent action was not triggered by a menu, so hilite is not
;; necessary. https://github.com/inexorabletash/a2d/issues/139
copy #$FF, menu_click_params::menu_id
bit active_window_view_by
bpl :+
jmp clear_selection
: copy active_window_id, findicon_window_id
ITK_RELAY_CALL IconTK::FIND_ICON, findicon_params
lda findicon_which_icon
bne handle_file_icon_click
jsr L5F13
jmp swap_in_desktop_icon_table
.endproc
;;; ============================================================
.proc handle_file_icon_click_impl
icon_num: .byte 0
start: sta icon_num
ldx selected_icon_count
beq L5CFB
dex
lda icon_num
L5CE6: cmp selected_icon_list,x
beq L5CF0
dex
bpl L5CE6
bmi L5CFB
L5CF0: bit double_click_flag
bmi L5CF8
jmp handle_double_click
L5CF8: jmp start_icon_drag
;; Open-Apple: Extend selection (if in same window)
L5CFB: bit BUTN0
bpl replace
lda selected_window_index
cmp active_window_id ; same window?
beq :+ ; if so, retain selection
replace:
jsr clear_selection
: ldx selected_icon_count
lda icon_num
sta selected_icon_list,x
inc selected_icon_count
copy active_window_id, selected_window_index
copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
copy icon_num, icon_param
jsr icon_screen_to_window
jsr offset_grafport2_and_set
ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, icon_param
copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
lda icon_num
jsr icon_window_to_screen
jsr reset_grafport3
bit double_click_flag
bmi start_icon_drag
jmp handle_double_click
;; --------------------------------------------------
start_icon_drag:
copy icon_num, drag_drop_param
ITK_RELAY_CALL IconTK::DRAG_HIGHLIGHTED, drag_drop_param
tax
lda drag_drop_param
beq desktop
process_drop:
jsr jt_drop
;; Failed?
cmp #$FF
bne :+
jsr swap_in_desktop_icon_table
jmp redraw_windows_and_desktop
;; Was a move?
: bit move_flag
bpl :+
;; Update source vol's contents
jsr update_active_window
;; fall through
;; Dropped on trash?
: lda drag_drop_param
cmp trash_icon_num
bne :+
;; Update used/free for same-vol windows
jsr update_active_window
jmp redraw_windows_and_desktop
;; Dropped on icon?
: lda drag_drop_param
bmi :+
;; Update used/free for same-vol windows
jsr update_vol_free_used_for_icon
jmp redraw_windows_and_desktop
;; Dropped on window!
: and #$7F ; mask off window number
pha
jsr update_used_free_for_vol_windows
pla
jsr select_and_refresh_window
jmp redraw_windows_and_desktop
;; --------------------------------------------------
desktop:
cpx #$02
bne :+
jmp swap_in_desktop_icon_table
: cpx #$FF
beq L5DF7
copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
jsr cached_icons_screen_to_window
jsr offset_grafport2_and_set
ldx selected_icon_count
dex
: txa
pha
lda selected_icon_list,x
sta redraw_icon_param
ITK_RELAY_CALL IconTK::REDRAW_ICON, redraw_icon_param
pla
tax
dex
bpl :-
copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
jsr update_scrollbars
jsr cached_icons_window_to_screen
jsr reset_grafport3
;;; Used as additional entry point
swap_in_desktop_icon_table:
jsr StoreWindowIconTable
jmp LoadDesktopIconTable
L5DF7: ldx saved_stack
txs
rts
handle_double_click:
;; Source window to close?
jsr set_window_to_close_after_open
lda icon_num ; after a double-click (on file or folder)
jsr icon_entry_lookup
stax $06
ldy #IconEntry::win_type
lda ($06),y
and #icon_entry_type_mask
cmp #icon_entry_type_trash
beq done
cmp #icon_entry_type_dir
bne file
;; Directory
lda icon_num
jsr open_folder_or_volume_icon
bmi done
jsr swap_in_desktop_icon_table
;; If Option (Solid-Apple) key is down, close previous window.
jsr close_window_after_open
done: rts
;; File (executable or data)
file: sta L5E77
lda active_window_id
jsr window_path_lookup
stax $06
ldy #$00
lda ($06),y
tay
L5E3A: lda ($06),y
sta buf_win_path,y
dey
bpl L5E3A
lda icon_num
jsr icon_entry_lookup
stax $06
ldy #$09
lda ($06),y
tax
clc
adc #$09
tay
dex
dey
L5E57: lda ($06),y
sta buf_filename2-1,x
dey
dex
bne L5E57
ldy #$09
lda ($06),y
tax
dex
dex
stx buf_filename2
lda L5E77
cmp #$20
bcc L5E74
lda L5E77
L5E74: jmp launch_file ; when double-clicked
.proc update_active_window
lda active_window_id
jsr update_used_free_for_vol_windows
lda active_window_id
jmp select_and_refresh_window
.endproc
L5E77: .byte 0
.endproc
handle_file_icon_click := handle_file_icon_click_impl::start
swap_in_desktop_icon_table := handle_file_icon_click_impl::swap_in_desktop_icon_table
process_drop := handle_file_icon_click_impl::process_drop
;;; ============================================================
.proc select_and_refresh_window
sta window_id
jsr redraw_windows_and_desktop
jsr clear_selection
lda window_id
cmp active_window_id
beq :+
sta findwindow_window_id
jsr handle_inactive_window_click ; bring to front
: copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
jsr set_penmode_copy
MGTK_RELAY_CALL MGTK::PaintRect, grafport2::cliprect
ldx active_window_id
dex
lda window_to_dir_icon_table,x
;; BUG: What if dir icon is freed? ($FF)
pha
jsr L7345
lda window_id
tax
dex
lda win_view_by_table,x
bmi :+ ; list view, not icons
jsr close_active_window
: lda active_window_id
jsr window_path_lookup
ptr := $06
stax ptr
ldy #0
lda (ptr),y
tay
: lda (ptr),y
sta open_dir_path_buf,y
dey
bpl :-
pla
jsr open_directory
jsr cmd_view_by_icon::entry
jsr StoreWindowIconTable
jsr LoadActiveWindowIconTable
copy active_window_id, getwinport_params2::window_id
jsr get_port2
jsr draw_window_header
lda #0
ldx active_window_id
sta win_view_by_table-1,x
copy #1, menu_click_params::item_num
jsr update_view_menu_check
jmp LoadDesktopIconTable
window_id:
.byte 0
.endproc
;;; ============================================================
;;; Drag Selection
.proc L5F13_impl
pt1: DEFINE_POINT 0, 0
pt2: DEFINE_POINT 0, 0
start: copy16 #notpenXOR, $06
jsr L60D5
ldx #.sizeof(MGTK::Point)-1
L5F20: lda event_coords,x
sta pt1,x
sta pt2,x
dex
bpl L5F20
jsr peek_event
lda event_kind
cmp #MGTK::EventKind::drag
beq L5F3F
bit BUTN0
bmi L5F3E
jsr clear_selection
L5F3E: rts
L5F3F: jsr clear_selection
copy active_window_id, getwinport_params2::window_id
jsr get_port2
jsr offset_grafport2_and_set
ldx #$03
L5F50: lda pt1,x
sta tmp_rect::x1,x
lda pt2,x
sta tmp_rect::x2,x
dex
bpl L5F50
jsr set_penmode_xor
MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
L5F6B: jsr peek_event
lda event_kind
cmp #MGTK::EventKind::drag
beq L5FC5
MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
ldx #$00
L5F80: cpx cached_window_icon_count
bne L5F88
jmp reset_grafport3
L5F88: txa
pha
lda cached_window_icon_list,x
sta icon_param
jsr icon_screen_to_window
ITK_RELAY_CALL IconTK::ICON_IN_RECT, icon_param
beq L5FB9
ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, icon_param
ldx selected_icon_count
inc selected_icon_count
copy icon_param, selected_icon_list,x
copy active_window_id, selected_window_index
L5FB9: lda icon_param
jsr icon_window_to_screen
pla
tax
inx
jmp L5F80
L5FC5: jsr L60D5
sub16 event_xcoord, L60CF, L60CB
sub16 event_ycoord, L60D1, L60CD
lda L60CC
bpl L5FFE
lda L60CB
eor #$FF
sta L60CB
inc L60CB
L5FFE: lda L60CE
bpl L600E
lda L60CD
eor #$FF
sta L60CD
inc L60CD
L600E: lda L60CB
cmp #$05
bcs L601F
lda L60CD
cmp #$05
bcs L601F
jmp L5F6B
L601F: MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
COPY_STRUCT MGTK::Point, event_coords, L60CF
cmp16 event_xcoord, tmp_rect::x2
bpl L6068
cmp16 event_xcoord, tmp_rect::x1
bmi L6054
bit L60D3
bpl L6068
L6054: copy16 event_xcoord, tmp_rect::x1
copy #$80, L60D3
jmp L6079
L6068: copy16 event_xcoord, tmp_rect::x2
copy #0, L60D3
L6079: cmp16 event_ycoord, tmp_rect::y2
bpl L60AE
cmp16 event_ycoord, tmp_rect::y1
bmi L609A
bit L60D4
bpl L60AE
L609A: copy16 event_ycoord, tmp_rect::y1
copy #$80, L60D4
jmp L60BF
L60AE: copy16 event_ycoord, tmp_rect::y2
copy #0, L60D4
L60BF: MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
jmp L5F6B
L60CB: .byte 0
L60CC: .byte 0
L60CD: .byte 0
L60CE: .byte 0
L60CF: .word 0
L60D1: .word 0
L60D3: .byte 0
L60D4: .byte 0
L60D5: jsr push_pointers
jmp icon_ptr_screen_to_window
.endproc
L5F13 := L5F13_impl::start
;;; ============================================================
.proc handle_title_click
ptr := $06
jmp :+
: copy active_window_id, event_params
MGTK_RELAY_CALL MGTK::FrontWindow, active_window_id
lda active_window_id
jsr copy_window_portbits
MGTK_RELAY_CALL MGTK::DragWindow, event_params
lda active_window_id
jsr window_lookup
stax ptr
ldy #MGTK::Winfo::port + MGTK::GrafPort::viewloc + MGTK::Point::ycoord
lda (ptr),y
cmp #$19 ; ???
bcs :+
lda #$19
sta (ptr),y
: ldy #MGTK::Winfo::port + MGTK::GrafPort::viewloc + MGTK::Point::xcoord
sub16in (ptr),y, port_copy+MGTK::GrafPort::viewloc+MGTK::Point::xcoord, deltax
iny
sub16in (ptr),y, port_copy+MGTK::GrafPort::viewloc+MGTK::Point::ycoord, deltay
ldx active_window_id
dex
lda win_view_by_table,x
beq :+ ; view by icon
rts
;; Update icon positions
: jsr LoadActiveWindowIconTable
ldx #0
next: cpx cached_window_icon_count
bne :+
jsr StoreWindowIconTable
jsr LoadDesktopIconTable
jmp done
: txa
pha
lda cached_window_icon_list,x
jsr icon_entry_lookup
stax ptr
ldy #IconEntry::iconx
add16in (ptr),y, deltax, (ptr),y
iny
add16in (ptr),y, deltay, (ptr),y
pla
tax
inx
jmp next
done: rts
deltax: .word 0
deltay: .word 0
.endproc
;;; ============================================================
.proc handle_resize_click
copy active_window_id, event_params
MGTK_RELAY_CALL MGTK::GrowWindow, event_params
jsr redraw_windows_and_desktop
jsr LoadActiveWindowIconTable
jsr cached_icons_screen_to_window
jsr update_scrollbars
jsr cached_icons_window_to_screen
jsr LoadDesktopIconTable
jmp reset_grafport3
.endproc
;;; ============================================================
handle_close_click:
lda active_window_id
MGTK_RELAY_CALL MGTK::TrackGoAway, trackgoaway_params
lda trackgoaway_params::goaway
bne close_window
rts
.proc close_window
icon_ptr := $06
jsr LoadActiveWindowIconTable
jsr clear_selection
ldx active_window_id
dex
lda win_view_by_table,x
bmi iter ; list view, not icons
lda icon_count
sec
sbc cached_window_icon_count
sta icon_count
ITK_RELAY_CALL IconTK::CLOSE_WINDOW, active_window_id
jsr free_cached_window_icons
iter: dec num_open_windows
ldx #0
txa
: sta cached_window_icon_list,x
cpx cached_window_icon_count
beq cont
inx
jmp :-
cont: sta cached_window_icon_count
jsr StoreWindowIconTable
MGTK_RELAY_CALL MGTK::CloseWindow, active_window_id
;; Unhilight dir (vol/folder) icon, if present
ldx active_window_id
dex
lda window_to_dir_icon_table,x
bmi no_icon ; $FF = dir icon freed
sta icon_param
jsr icon_entry_lookup
stax icon_ptr
ldy #IconEntry::state
lda (icon_ptr),y
and #icon_entry_winid_mask
beq no_icon ; ???
ldy #IconEntry::win_type
lda (icon_ptr),y
and #AS_BYTE(~icon_entry_open_mask) ; clear open_flag
sta (icon_ptr),y
and #icon_entry_winid_mask
sta selected_window_index
jsr zero_grafport5_coords
ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, icon_param
jsr reset_grafport3
copy #1, selected_icon_count
copy icon_param, selected_icon_list
ldx active_window_id
dex
lda window_to_dir_icon_table,x
jsr L7345
;; Animate closing into dir (vol/folder) icon
ldx active_window_id
dex
lda window_to_dir_icon_table,x
inx
jsr animate_window_close
no_icon:
ldx active_window_id
dex
lda #0
sta window_to_dir_icon_table,x ; 0 = window free
sta win_view_by_table,x
MGTK_RELAY_CALL MGTK::FrontWindow, active_window_id
jsr LoadDesktopIconTable
lda #MGTK::checkitem_uncheck
sta checkitem_params::check
MGTK_RELAY_CALL MGTK::CheckItem, checkitem_params
jsr update_window_menu_items
jmp redraw_windows_and_desktop
.endproc
;;; ============================================================
.proc L62BC
cmp #$01
bcc L62C2
bne L62C5
L62C2: return #0
L62C5: sta L638B
stx L6386
sty L638A
cmp L6386
bcc L62D5
tya
rts
L62D5: lda #$00
sta L6385
sta L6389
clc
ror L6386
ror L6385
clc
ror L638A
ror L6389
lda #$00
sta L6383
sta L6387
sta L6384
sta L6388
L62F9: lda L6384
cmp L638B
beq L630F
bcc L6309
jsr L6319
jmp L62F9
L6309: jsr L634E
jmp L62F9
L630F: lda L6388
cmp #$01
bcs L6318
lda #$01
L6318: rts
L6319: sub16 L6383, L6385, L6383
sub16 L6387, L6389, L6387
clc
ror L6386
ror L6385
clc
ror L638A
ror L6389
rts
L634E: add16 L6383, L6385, L6383
add16 L6387, L6389, L6387
clc
ror L6386
ror L6385
clc
ror L638A
ror L6389
rts
L6383: .byte 0
L6384: .byte 0
L6385: .byte 0
L6386: .byte 0
L6387: .byte 0
L6388: .byte 0
L6389: .byte 0
L638A: .byte 0
L638B: .byte 0
.endproc
;;; ============================================================
.proc L638C
jsr L650F
sty L63E9
jsr L644C
sta L63E8
sub16_8 grafport2::cliprect::y1, L63E8, L63EA
cmp16 L63EA, iconbb_rect+MGTK::Rect::y1
bmi L63C1
ldax L63EA
jmp L63C7
L63C1: ldax iconbb_rect+MGTK::Rect::y1
L63C7: stax grafport2::cliprect::y1
add16_8 grafport2::cliprect::y1, L63E9, grafport2::cliprect::y2
jsr assign_active_window_cliprect
jsr update_scrollbars
jmp L6556
L63E8: .byte 0
L63E9: .byte 0
L63EA: .word 0
.endproc
;;; ============================================================
.proc L63EC
jsr L650F
sty L6449
jsr L644C
sta L6448
add16_8 grafport2::cliprect::y2, L6448, L644A
cmp16 L644A, iconbb_rect+MGTK::Rect::y2
bpl L6421
ldax L644A
jmp L6427
L6421: ldax iconbb_rect+MGTK::Rect::y2
L6427: stax grafport2::cliprect::y2
sub16_8 grafport2::cliprect::y2, L6449, grafport2::cliprect::y1
jsr assign_active_window_cliprect
jsr update_scrollbars
jmp L6556
L6448: .byte 0
L6449: .byte 0
L644A: .word 0
.endproc
;;; ============================================================
.proc L644C
tya
sec
sbc #$0E
rts
.endproc
;;; ============================================================
.proc L6451
jsr L650F
stax L64AC
sub16 grafport2::cliprect::x1, L64AC, L64AE
cmp16 L64AE, iconbb_rect+MGTK::Rect::x1
bmi L6484
ldax L64AE
jmp L648A
L6484: ldax iconbb_rect+MGTK::Rect::x1
L648A: stax grafport2::cliprect::x1
add16 grafport2::cliprect::x1, L64AC, grafport2::cliprect::x2
jsr assign_active_window_cliprect
jsr update_scrollbars
jmp L6556
L64AC: .word 0
L64AE: .word 0
.endproc
;;; ============================================================
.proc L64B0
jsr L650F
stax L650B
add16 grafport2::cliprect::x2, L650B, L650D
cmp16 L650D, iconbb_rect+MGTK::Rect::x2
bpl L64E3
ldax L650D
jmp L64E9
L64E3: ldax iconbb_rect+MGTK::Rect::x2
L64E9: stax grafport2::cliprect::x2
sub16 grafport2::cliprect::x2, L650B, grafport2::cliprect::x1
jsr assign_active_window_cliprect
jsr update_scrollbars
jmp L6556
L650B: .word 0
L650D: .word 0
.endproc
.proc L650F
bit active_window_view_by
bmi :+ ; list view, not icons
jsr cached_icons_screen_to_window
: jsr apply_active_winfo_to_grafport2
jsr compute_icons_bbox
lda active_window_id
jmp compute_window_dimensions
.endproc
.proc apply_active_winfo_to_grafport2
ptr := $06
lda active_window_id
jsr window_lookup
addax #MGTK::Winfo::port, ptr
ldy #.sizeof(MGTK::GrafPort) + 1 ; ???
: lda (ptr),y
sta grafport2,y
dey
bpl :-
rts
.endproc
.proc assign_active_window_cliprect
ptr := $6
lda active_window_id
jsr window_lookup
stax ptr
ldy #MGTK::Winfo::port + MGTK::GrafPort::maprect + 7
ldx #7
: lda grafport2::cliprect,x
sta (ptr),y
dey
dex
bpl :-
rts
.endproc
.proc L6556
bit active_window_view_by
bmi :+
jsr cached_icons_window_to_screen
: MGTK_RELAY_CALL MGTK::PaintRect, grafport2::cliprect
jsr reset_grafport3
jmp L6C19
.endproc
;;; ============================================================
.proc update_hthumb
winfo_ptr := $06
lda active_window_id
jsr compute_window_dimensions
stax win_width
lda active_window_id
jsr window_lookup
stax winfo_ptr
ldy #MGTK::Winfo::hthumbmax
lda (winfo_ptr),y
tay
sub16 iconbb_rect+MGTK::Rect::x2, iconbb_rect+MGTK::Rect::x1, delta
sub16 delta, win_width, delta
lsr16 delta ; / 2
ldx delta
sub16 grafport2::cliprect::x1, iconbb_rect+MGTK::Rect::x1, delta
bpl pos
lda #0
beq neg ; always
pos: cmp16 grafport2::cliprect::x2, iconbb_rect+MGTK::Rect::x2
bmi L65E2
tya
jmp L65EE
L65E2: lsr16 delta ; / 2
lda delta
neg: jsr L62BC
L65EE: sta updatethumb_thumbpos
lda #MGTK::Ctl::horizontal_scroll_bar
sta updatethumb_which_ctl
MGTK_RELAY_CALL MGTK::UpdateThumb, updatethumb_params
rts
win_width:
.word 0
delta: .word 0
.endproc
;;; ============================================================
.proc update_vthumb
winfo_ptr := $06
lda active_window_id
jsr compute_window_dimensions
sty win_height
lda active_window_id
jsr window_lookup
stax winfo_ptr
ldy #MGTK::Winfo::vthumbmax
lda (winfo_ptr),y
tay
sub16 iconbb_rect+MGTK::Rect::y2, iconbb_rect+MGTK::Rect::y1, delta
sub16_8 delta, win_height, delta
lsr16 delta ; / 4
lsr16 delta
ldx delta
sub16 grafport2::cliprect::y1, iconbb_rect+MGTK::Rect::y1, delta
bpl pos
lda #0
beq neg ; always
pos: cmp16 grafport2::cliprect::y2, iconbb_rect+MGTK::Rect::y2
bmi L667B
tya
jmp L668D
L667B: lsr16 delta ; / 4
lsr16 delta
lda delta
neg: jsr L62BC
L668D: sta updatethumb_thumbpos
lda #MGTK::Ctl::vertical_scroll_bar
sta updatethumb_which_ctl
MGTK_RELAY_CALL MGTK::UpdateThumb, updatethumb_params
rts
win_height:
.byte 0
delta: .word 0
.endproc
;;; ============================================================
.proc update_window_menu_items
ldx active_window_id
beq disable_menu_items
jmp check_view_menu_items
disable_menu_items:
copy #MGTK::disablemenu_disable, disablemenu_params::disable
MGTK_RELAY_CALL MGTK::DisableMenu, disablemenu_params
copy #MGTK::disableitem_disable, disableitem_params::disable
copy #menu_id_file, disableitem_params::menu_id
copy #desktop_aux::menu_item_id_new_folder, disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
copy #desktop_aux::menu_item_id_close, disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
copy #desktop_aux::menu_item_id_close_all, disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
copy #0, menu_dispatch_flag
rts
check_view_menu_items:
dex
lda win_view_by_table,x
and #$0F ; mask off menu item number
tax
inx
stx checkitem_params::menu_item
lda #MGTK::checkitem_check
sta checkitem_params::check
MGTK_RELAY_CALL MGTK::CheckItem, checkitem_params
rts
.endproc
;;; ============================================================
;;; Disable menu items for operating on a selected file
.proc disable_file_menu_items
copy #MGTK::disableitem_disable, disableitem_params::disable
;; File
copy #menu_id_file, disableitem_params::menu_id
lda #desktop_aux::menu_item_id_open
jsr disable_menu_item
lda #desktop_aux::menu_item_id_get_info
jsr disable_menu_item
lda #desktop_aux::menu_item_id_rename_icon
jsr disable_menu_item
;; Special
copy #menu_id_special, disableitem_params::menu_id
lda #desktop_aux::menu_item_id_lock
jsr disable_menu_item
lda #desktop_aux::menu_item_id_unlock
jsr disable_menu_item
lda #desktop_aux::menu_item_id_get_size
jsr disable_menu_item
rts
disable_menu_item:
sta disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
rts
.endproc
;;; ============================================================
.proc enable_file_menu_items
copy #MGTK::disableitem_enable, disableitem_params::disable
;; File
copy #menu_id_file, disableitem_params::menu_id
lda #desktop_aux::menu_item_id_open
jsr enable_menu_item
lda #desktop_aux::menu_item_id_get_info
jsr enable_menu_item
lda #desktop_aux::menu_item_id_rename_icon
jsr enable_menu_item
;; Special
copy #menu_id_special, disableitem_params::menu_id
lda #desktop_aux::menu_item_id_lock
jsr enable_menu_item
lda #desktop_aux::menu_item_id_unlock
jsr enable_menu_item
lda #desktop_aux::menu_item_id_get_size
jsr enable_menu_item
rts
enable_menu_item:
sta disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
rts
.endproc
;;; ============================================================
.proc toggle_eject_menu_item
enable:
copy #MGTK::disableitem_enable, disableitem_params::disable
jmp :+
disable:
copy #MGTK::disableitem_disable, disableitem_params::disable
: copy #menu_id_special, disableitem_params::menu_id
copy #desktop_aux::menu_item_id_eject, disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
copy #menu_id_special, disableitem_params::menu_id
copy #desktop_aux::menu_item_id_check_drive, disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
rts
.endproc
enable_eject_menu_item := toggle_eject_menu_item::enable
disable_eject_menu_item := toggle_eject_menu_item::disable
;;; ============================================================
.proc toggle_selector_menu_items
disable:
copy #MGTK::disableitem_disable, disableitem_params::disable
jmp :+
enable:
copy #MGTK::disableitem_enable, disableitem_params::disable
: copy #menu_id_selector, disableitem_params::menu_id
lda #menu_item_id_selector_edit
jsr configure_menu_item
lda #menu_item_id_selector_delete
jsr configure_menu_item
lda #menu_item_id_selector_run
jsr configure_menu_item
copy #$80, LD344
rts
configure_menu_item:
sta disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
rts
.endproc
enable_selector_menu_items := toggle_selector_menu_items::enable
disable_selector_menu_items := toggle_selector_menu_items::disable
;;; ============================================================
.proc handle_volume_icon_click
lda selected_icon_count
bne L67DF
jmp set_selection
L67DF: tax
dex
lda findicon_which_icon
L67E4: cmp selected_icon_list,x
beq L67EE
dex
bpl L67E4
bmi L67F6
L67EE: bit double_click_flag
bmi L6834
jmp L6880
L67F6: bit BUTN0
bpl replace_selection
;; Add clicked icon to selection
lda selected_window_index
bne replace_selection
ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, findicon_which_icon
ldx selected_icon_count
lda findicon_which_icon
sta selected_icon_list,x
inc selected_icon_count
jmp L6834
;; Replace selection with clicked icon
replace_selection:
jsr clear_selection
;; Set selection to clicked icon
set_selection:
ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, findicon_which_icon
copy #1, selected_icon_count
copy findicon_which_icon, selected_icon_list
copy #0, selected_window_index
L6834: bit double_click_flag
bpl L6880
;; Drag of volume icon
copy findicon_which_icon, drag_drop_param
ITK_RELAY_CALL IconTK::DRAG_HIGHLIGHTED, drag_drop_param
tax
lda drag_drop_param
beq L6878
jsr jt_drop
cmp #$FF
bne L6858
jmp redraw_windows_and_desktop
L6858: lda drag_drop_param
cmp trash_icon_num
bne L6863
jmp redraw_windows_and_desktop
L6863: lda drag_drop_param
bpl L6872
and #$7F
pha
jsr update_used_free_for_vol_windows
pla
jmp select_and_refresh_window
L6872: jsr update_vol_free_used_for_icon
jmp redraw_windows_and_desktop
L6878: txa
cmp #2
bne L688F
jmp redraw_windows_and_desktop
;; Double-click on volume icon
L6880: lda findicon_which_icon
cmp trash_icon_num
beq L688E
jsr open_folder_or_volume_icon
jsr StoreWindowIconTable
L688E: rts
L688F: ldx selected_icon_count
dex
L6893: txa
pha
copy selected_icon_list,x, icon_param3
ITK_RELAY_CALL IconTK::REDRAW_ICON, icon_param3
pla
tax
dex
bpl L6893
rts
.endproc
;;; ============================================================
.proc L68AA
jsr reset_grafport3
bit BUTN0
bpl L68B3
rts
L68B3: jsr clear_selection
ldx #3
L68B8: lda event_coords,x
sta tmp_rect::x1,x
sta tmp_rect::x2,x
dex
bpl L68B8
jsr peek_event
lda event_kind
cmp #MGTK::EventKind::drag
beq L68CF
rts
L68CF: MGTK_RELAY_CALL MGTK::SetPattern, checkerboard_pattern
jsr set_penmode_xor
MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
L68E4: jsr peek_event
lda event_kind
cmp #MGTK::EventKind::drag
beq L6932
MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
ldx #0
L68F9: cpx cached_window_icon_count
bne :+
lda #0
sta selected_window_index
rts
: txa
pha
copy cached_window_icon_list,x, icon_param
ITK_RELAY_CALL IconTK::ICON_IN_RECT, icon_param
beq L692C
ITK_RELAY_CALL IconTK::HIGHLIGHT_ICON, icon_param
ldx selected_icon_count
inc selected_icon_count
copy icon_param, selected_icon_list,x
L692C: pla
tax
inx
jmp L68F9
L6932: sub16 event_xcoord, L6A39, L6A35
sub16 event_ycoord, L6A3B, L6A37
lda L6A36
bpl L6968
lda L6A35
eor #$FF
sta L6A35
inc L6A35
L6968: lda L6A38
bpl L6978
lda L6A37
eor #$FF
sta L6A37
inc L6A37
L6978: lda L6A35
cmp #$05
bcs L6989
lda L6A37
cmp #$05
bcs L6989
jmp L68E4
L6989: MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
COPY_STRUCT MGTK::Point, event_coords, L6A39
cmp16 event_xcoord, tmp_rect::x2
bpl L69D2
cmp16 event_xcoord, tmp_rect::x1
bmi L69BE
bit L6A3D
bpl L69D2
L69BE: copy16 event_xcoord, tmp_rect::x1
copy #$80, L6A3D
jmp L69E3
L69D2: copy16 event_xcoord, tmp_rect::x2
copy #0, L6A3D
L69E3: cmp16 event_ycoord, tmp_rect::y2
bpl L6A18
cmp16 event_ycoord, tmp_rect::y1
bmi L6A04
bit L6A3E
bpl L6A18
L6A04: copy16 event_ycoord, tmp_rect::y1
copy #$80, L6A3E
jmp L6A29
L6A18: copy16 event_ycoord, tmp_rect::y2
copy #0, L6A3E
L6A29: MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
jmp L68E4
L6A35: .byte 0
L6A36: .byte 0
L6A37: .byte 0
L6A38: .byte 0
L6A39: .word 0
L6A3B: .word 0
L6A3D: .byte 0
L6A3E: .byte 0
.endproc
;;; ============================================================
;;; Update used/free values for windows related to volume icon
;;; Input: icon number in A
.proc update_vol_free_used_for_icon
ptr := $6
path_buf := $220
jsr find_window_for_dir_icon
beq L6A80 ; found
;; Not in the map. Look for related windows.
jsr icon_entry_lookup
addax #IconEntry::len, ptr
ldy #0
lda (ptr),y
tay
dey
L6A5C: lda (ptr),y
sta path_buf,y
dey
bpl L6A5C
dec path_buf
lda #'/'
sta path_buf+1
ldax #path_buf
ldy path_buf
jsr find_windows_for_prefix
ldax #path_buf
ldy path_buf
jmp update_vol_used_free_for_found_windows
;; Found it in the map.
L6A80: inx
txa
pha
jsr update_used_free_for_vol_windows
pla
jmp select_and_refresh_window
.endproc
;;; ============================================================
;;; Open a folder/volume icon
;;; Input: A = icon
;;; Note: stack will be restored via saved_stack on failure
.proc open_folder_or_volume_icon
ptr := $06
sta icon_params2
jsr StoreWindowIconTable
lda icon_params2
;; Already an open window for the icon?
ldx #7
: cmp window_to_dir_icon_table,x
beq found_win
dex
bpl :-
jmp no_linked_win
;; --------------------------------------------------
;; There is an existing window associated with icon.
found_win:
;; Is it the active window? If so, done!
inx
cpx active_window_id
bne :+
rts
;; Otherwise, bring the window to the front.
: stx cached_window_id
jsr LoadWindowIconTable
jsr update_icon
lda icon_params2
ldx window_icon_to_filerecord_list
dex
: cmp window_icon_to_filerecord_list+1,x
beq :+
dex
bpl :-
jsr open_directory
: MGTK_RELAY_CALL MGTK::SelectWindow, cached_window_id
lda cached_window_id
sta active_window_id
jsr L6C19
jsr redraw_windows
jmp LoadDesktopIconTable
;; --------------------------------------------------
;; No associated window - check for matching path.
no_linked_win:
;; Compute the path (will be needed anyway).
lda icon_params2
jsr icon_entry_lookup
stax ptr
jsr compose_icon_full_path
addr_call find_window_for_path, open_dir_path_buf
beq no_win
;; Found a match - associate the window.
tax
dex ; 1-based to 0-based
copy icon_params2, window_to_dir_icon_table,x
jmp found_win
;; --------------------------------------------------
;; No window - need to open one.
no_win:
;; Is there a free window?
lda num_open_windows
cmp #8
bcc :+
;; Nope, show error.
lda #warning_msg_too_many_windows
jsr warning_dialog_proc_num
ldx saved_stack
txs
rts
;; Search window-icon map to find an unused window.
: ldx #0
: lda window_to_dir_icon_table,x
beq :+ ; 0 = window free
inx
jmp :-
;; Map the window to its source icon
: lda icon_params2
sta window_to_dir_icon_table,x
inx ; 0-based to 1-based
stx cached_window_id
jsr LoadWindowIconTable
;; Update View and other menus
inc num_open_windows
ldx cached_window_id
dex
copy #0, win_view_by_table,x
lda num_open_windows ; Was there already a window open?
cmp #2
bcs :+ ; yes, no need to enable file menu
jsr enable_various_file_menu_items
jmp update_view
: copy #0, checkitem_params::check
jsr check_item
update_view:
lda #desktop_aux::menu_item_id_view_by_icon
sta checkitem_params::menu_item
sta checkitem_params::check
jsr check_item
jsr update_icon
;; Set path, size, contents, and volume free/used.
jsr prepare_new_window
;; Create the window
lda cached_window_id
jsr window_lookup ; A,X points at Winfo
ldy #MGTK::OpenWindow
jsr MGTK_RELAY
copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
jsr draw_window_header
;; Restore and add the icons
jsr cached_icons_screen_to_window
copy #0, num
: lda num
cmp cached_window_icon_count
beq done
tax
lda cached_window_icon_list,x
jsr icon_entry_lookup ; A,X points at IconEntry
ldy #IconTK::ADD_ICON
jsr ITK_RELAY ; icon entry addr in A,X
inc num
jmp :-
;; Finish up
done: copy cached_window_id, active_window_id
jsr update_scrollbars
jsr cached_icons_window_to_screen
jsr StoreWindowIconTable
jsr LoadDesktopIconTable
jmp reset_grafport3
;;; Common code to update the dir (vol/folder) icon.
.proc update_icon
lda icon_params2
jsr icon_entry_lookup
stax ptr
ldy #IconEntry::win_type
lda (ptr),y
ora #icon_entry_open_mask ; set open_flag
sta (ptr),y
ldy #IconEntry::win_type ; get window id
lda (ptr),y
and #icon_entry_winid_mask
sta getwinport_params2::window_id
beq :+ ; window 0 = desktop
cmp active_window_id ; prep to redraw windowed (file) icon
bne done ; but only if active window
jsr get_set_port2
jsr offset_grafport2_and_set
lda icon_params2
jsr icon_screen_to_window
: ITK_RELAY_CALL IconTK::REDRAW_ICON, icon_params2
lda getwinport_params2::window_id
beq done ; skip if on desktop
lda icon_params2 ; restore from drawing
jsr icon_window_to_screen
jsr reset_grafport3
done: rts
.endproc
num: .byte 0
.endproc
;;; ============================================================
.proc check_item
MGTK_RELAY_CALL MGTK::CheckItem, checkitem_params
rts
.endproc
;;; ============================================================
.proc L6C19
ldx cached_window_id
dex
lda win_view_by_table,x
bmi L6C25 ; list view, not icons
jmp L6CCD
;; List view
L6C25: jsr push_pointers
copy cached_window_id, getwinport_params2::window_id
jsr get_set_port2
bit draw_window_header_flag
bmi :+
jsr draw_window_header
: lda cached_window_id
sta getwinport_params2::window_id
jsr get_port2
bit draw_window_header_flag
bmi :+
jsr offset_grafport2_and_set
: ldx cached_window_id
dex
lda window_to_dir_icon_table,x
;; BUG: What if dir icon is freed? ($FF)
ldx #0
L6C53: cmp window_icon_to_filerecord_list+1,x
beq L6C5F
inx
cpx window_icon_to_filerecord_list
bne L6C53
rts
L6C5F: txa
asl a
tax
lda window_filerecord_table,x
sta LE71D
sta $06
lda window_filerecord_table+1,x
sta LE71D+1
sta $06+1
lda LCBANK2
lda LCBANK2
ldy #$00
lda ($06),y
tay
lda LCBANK1
lda LCBANK1
tya
sta LE71F
inc LE71D
bne L6C8F
inc LE71D+1
;; First row
.proc L6C8F
lda #16
sta pos_col_name::ycoord
sta pos_col_type::ycoord
sta pos_col_size::ycoord
sta pos_col_date::ycoord
lda #0
sta pos_col_name::ycoord+1
sta pos_col_type::ycoord+1
sta pos_col_size::ycoord+1
sta pos_col_date::ycoord+1
lda #0
sta rows_done
rloop: lda rows_done
cmp cached_window_icon_count
beq done
tax
lda cached_window_icon_list,x
jsr L813F
inc rows_done
jmp rloop
done: jsr reset_grafport3
jsr pop_pointers
rts
rows_done:
.byte 0
.endproc
;; Icon view
L6CCD: copy cached_window_id, getwinport_params2::window_id
jsr get_set_port2
bit draw_window_header_flag
bmi :+
jsr draw_window_header
: jsr cached_icons_screen_to_window
jsr offset_grafport2_and_set
COPY_BLOCK grafport2::cliprect, tmp_rect
ldx #0
txa
pha
L6CF3: cpx cached_window_icon_count
bne L6D09
pla
jsr reset_grafport3
copy cached_window_id, getwinport_params2::window_id
jsr get_set_port2
jsr cached_icons_window_to_screen
rts
L6D09: txa
pha
lda cached_window_icon_list,x
sta icon_param
ITK_RELAY_CALL IconTK::ICON_IN_RECT, icon_param
beq L6D25
ITK_RELAY_CALL IconTK::REDRAW_ICON, icon_param
L6D25: pla
tax
inx
jmp L6CF3
.endproc
;;; ============================================================
.proc clear_selection
lda selected_icon_count
bne L6D31
rts
L6D31: copy #0, L6DB0
copy selected_window_index, tmp_rect ; ???
beq L6D7D
cmp active_window_id
beq L6D4D
jsr zero_grafport5_coords
copy #0, tmp_rect
beq L6D56
L6D4D: sta getwinport_params2::window_id
jsr get_set_port2
jsr offset_grafport2_and_set
L6D56: lda L6DB0
cmp selected_icon_count
beq L6D9B
tax
lda selected_icon_list,x
sta icon_param
jsr icon_screen_to_window
ITK_RELAY_CALL IconTK::UNHIGHLIGHT_ICON, icon_param
lda icon_param
jsr icon_window_to_screen
inc L6DB0
jmp L6D56
L6D7D: lda L6DB0
cmp selected_icon_count
beq L6D9B
tax
lda selected_icon_list,x
sta icon_param
ITK_RELAY_CALL IconTK::UNHIGHLIGHT_ICON, icon_param
inc L6DB0
jmp L6D7D
L6D9B: lda #0
ldx selected_icon_count
dex
: sta selected_icon_list,x
dex
bpl :-
sta selected_icon_count
sta selected_window_index
jmp reset_grafport3
L6DB0: .byte 0
.endproc
;;; ============================================================
.proc update_scrollbars
ldx active_window_id
dex
lda win_view_by_table,x
bmi :+ ; list view, not icons
jsr compute_icons_bbox
jmp config_port
;; List view
: jsr cached_icons_screen_to_window
jsr compute_icons_bbox
jsr cached_icons_window_to_screen
config_port:
copy active_window_id, getwinport_params2::window_id
jsr get_set_port2
;; check horizontal bounds
cmp16 iconbb_rect+MGTK::Rect::x1, grafport2::cliprect::x1
bmi activate_hscroll
cmp16 grafport2::cliprect::x2, iconbb_rect+MGTK::Rect::x2
bmi activate_hscroll
;; deactivate horizontal scrollbar
copy #MGTK::Ctl::horizontal_scroll_bar, activatectl_which_ctl
copy #MGTK::activatectl_deactivate, activatectl_activate
jsr activate_ctl
jmp check_vscroll
activate_hscroll:
;; activate horizontal scrollbar
copy #MGTK::Ctl::horizontal_scroll_bar, activatectl_which_ctl
copy #MGTK::activatectl_activate, activatectl_activate
jsr activate_ctl
jsr update_hthumb
check_vscroll:
;; check vertical bounds
cmp16 iconbb_rect+MGTK::Rect::y1, grafport2::cliprect::y1
bmi activate_vscroll
cmp16 grafport2::cliprect::y2, iconbb_rect+MGTK::Rect::y2
bmi activate_vscroll
;; deactivate vertical scrollbar
copy #MGTK::Ctl::vertical_scroll_bar, activatectl_which_ctl
copy #MGTK::activatectl_deactivate, activatectl_activate
jsr activate_ctl
rts
activate_vscroll:
;; activate vertical scrollbar
copy #MGTK::Ctl::vertical_scroll_bar, activatectl_which_ctl
copy #MGTK::activatectl_activate, activatectl_activate
jsr activate_ctl
jmp update_vthumb
activate_ctl:
MGTK_RELAY_CALL MGTK::ActivateCtl, activatectl_params
rts
.endproc
;;; ============================================================
.proc cached_icons_screen_to_window
lda #0
sta count
loop: lda count
cmp cached_window_icon_count
beq done
tax
lda cached_window_icon_list,x
jsr icon_screen_to_window
inc count
jmp loop
done: rts
count: .byte 0
.endproc
;;; ============================================================
.proc cached_icons_window_to_screen
lda #0
sta index
loop: lda index
cmp cached_window_icon_count
beq done
tax
lda cached_window_icon_list,x
jsr icon_window_to_screen
inc index
jmp loop
done: rts
index: .byte 0
.endproc
;;; ============================================================
.proc offset_grafport2_impl
flag_clear:
lda #$80
beq :+
flag_set:
lda #0
: sta flag
add16 grafport2::viewloc::ycoord, #15, grafport2::viewloc::ycoord
add16 grafport2::cliprect::y1, #15, grafport2::cliprect::y1
bit flag
bmi done
MGTK_RELAY_CALL MGTK::SetPort, grafport2
done: rts
flag: .byte 0
.endproc
offset_grafport2 := offset_grafport2_impl::flag_clear
offset_grafport2_and_set := offset_grafport2_impl::flag_set
;;; ============================================================
.proc enable_various_file_menu_items
copy #MGTK::disablemenu_enable, disablemenu_params::disable
MGTK_RELAY_CALL MGTK::DisableMenu, disablemenu_params
copy #MGTK::disableitem_enable, disableitem_params::disable
copy #menu_id_file, disableitem_params::menu_id
copy #desktop_aux::menu_item_id_new_folder, disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
copy #desktop_aux::menu_item_id_close, disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
copy #desktop_aux::menu_item_id_close_all, disableitem_params::menu_item
MGTK_RELAY_CALL MGTK::DisableItem, disableitem_params
copy #$80, menu_dispatch_flag
rts
.endproc
;;; ============================================================
;;; Refresh vol used/free for windows of same volume as win in A.
;;; Input: A = window id
.proc update_used_free_for_vol_windows
ptr := $6
jsr window_path_lookup
sta ptr
sta pathptr
stx ptr+1
stx pathptr+1
ldy #0 ; length offset
lda (ptr),y
sta pathlen
iny
loop: iny ; start at 2nd character
lda (ptr),y
cmp #'/'
beq found
cpy pathlen
beq finish
jmp loop
found: dey
finish: sty pathlen
addr_call_indirect find_windows_for_prefix, ptr ; ???
ldax pathptr
ldy pathlen
jmp update_vol_used_free_for_found_windows
pathptr: .addr 0
pathlen: .byte 0
.endproc
;;; ============================================================
;;; Update used/free for results of find_window[s]_for_prefix
.proc update_vol_used_free_for_found_windows
ptr := $6
stax ptr
sty path_buffer
: lda (ptr),y
sta path_buffer,y
dey
bne :-
jsr get_vol_free_used
bne done
lda found_windows_count
beq done
loop: dec found_windows_count
bmi done
ldx found_windows_count
lda found_windows_list,x
sec
sbc #1
asl a
tax
copy16 vol_kb_used, window_k_used_table,x
copy16 vol_kb_free, window_k_free_table,x
jmp loop
done: rts
.endproc
;;; ============================================================
;;; Find position of last segment of path at (A,X), return in Y.
;;; For "/a/b", Y points at "/a"; if volume path, unchanged.
.proc find_last_path_segment
ptr := $A
stax ptr
;; Find last slash in string
ldy #0
lda (ptr),y
tay
: lda (ptr),y
cmp #'/'
beq slash
dey
bpl :-
;; Oops - no slash
ldy #1
;; Restore original string
restore:
dey
lda (ptr),y
tay
rts
;; Are we left with "/" ?
slash: cpy #1
beq restore
dey
rts
.endproc
;;; ============================================================
;; If 'set' version called, length in Y; otherwise use str len
.proc find_windows
ptr := $6
set: stax ptr
lda #$80
bne start
unset: stax ptr
lda #0
start: sta exact_match_flag
bit exact_match_flag
bpl :+
ldy #0 ; Use full length
lda (ptr),y
tay
: sty path_buffer
;; Copy ptr to path_buffer
: lda (ptr),y
sta path_buffer,y
dey
bne :-
lda #0
sta found_windows_count
sta window_num
loop: inc window_num
lda window_num
cmp #9 ; windows are 1-8
bcc check_window
bit exact_match_flag
bpl :+
lda #0
: rts
check_window:
jsr window_lookup
stax ptr
ldy #MGTK::Winfo::status
lda (ptr),y
beq loop
lda window_num
jsr window_path_lookup
stax ptr
ldy #0
lda (ptr),y
tay
cmp path_buffer
beq :+
bit exact_match_flag
bmi loop
ldy path_buffer
iny
lda (ptr),y
cmp #'/'
bne loop
dey
: lda (ptr),y
cmp path_buffer,y
bne loop
dey
bne :-
bit exact_match_flag
bmi done
ldx found_windows_count
lda window_num
sta found_windows_list,x
inc found_windows_count
jmp loop
done: return window_num
window_num:
.byte 0
exact_match_flag:
.byte 0
.endproc
find_window_for_path := find_windows::set
find_windows_for_prefix := find_windows::unset
found_windows_count:
.byte 0
found_windows_list:
.res 8
;;; ============================================================
.proc open_directory
jmp start
DEFINE_OPEN_PARAMS open_params, path_buffer, $800
DEFINE_READ_PARAMS read_params, $0C00, $200
DEFINE_CLOSE_PARAMS close_params
DEFINE_GET_FILE_INFO_PARAMS get_file_info_params4, path_buffer
.byte 0
vol_kb_free: .word 0
vol_kb_used: .word 0
entry_length:
.byte 0
L70C0: .byte $00
L70C1: .byte $00
L70C2: .byte $00
L70C3: .byte $00
L70C4: .byte $00
.proc start
sta L72A7
jsr push_pointers
COPY_BYTES 65, open_dir_path_buf, path_buffer
jsr do_open
lda open_params::ref_num
sta read_params::ref_num
sta close_params::ref_num
jsr do_read
jsr L72E2
ldx #0
: lda $0C00+SubdirectoryHeader::entry_length,x
sta entry_length,x
inx
cpx #4
bne :-
sub16 L485D, L485F, L72A8
ldx #$05
L710A: lsr16 L72A8
dex
cpx #$00
bne L710A
lda L70C2
bne L7147
lda icon_count
clc
adc L70C1
bcs L7147
cmp #$7C
bcs L7147
sub16_8 L72A8, DEVCNT, L72A8
cmp16 L72A8, L70C1
bcs L7169
L7147: lda num_open_windows
jsr mark_icons_not_opened_1
dec num_open_windows
jsr redraw_windows_and_desktop
jsr do_close
lda active_window_id
beq L715F
lda #$03
bne L7161
L715F: lda #warning_msg_window_must_be_closed2
L7161: jsr warning_dialog_proc_num
ldx saved_stack
txs
rts
record_ptr := $06
L7169: copy16 L485F, record_ptr
lda window_icon_to_filerecord_list
asl a
tax
copy16 record_ptr, window_filerecord_table,x
ldx window_icon_to_filerecord_list
lda L72A7
sta window_icon_to_filerecord_list+1,x
inc window_icon_to_filerecord_list
lda L70C1
;; Store entry count
pha
lda LCBANK2
lda LCBANK2
ldy #$00
pla
sta (record_ptr),y
lda LCBANK1
lda LCBANK1
copy #$FF, L70C4
copy #$00, L70C3
entry_ptr := $08
copy16 #$0C00 + SubdirectoryHeader::storage_type_name_length, entry_ptr
;; Advance past entry count
inc record_ptr
lda record_ptr
bne do_entry
inc record_ptr+1
;; Record is temporarily constructed at $1F00 then copied into place.
record := $1F00
record_size := $20
do_entry:
inc L70C4
lda L70C4
cmp L70C1
bne L71CB
jmp L7296
L71CB: inc L70C3
lda L70C3
cmp L70C0
beq L71E7
add16_8 entry_ptr, entry_length, entry_ptr
jmp L71F7
L71E7: copy #$00, L70C3
copy16 #$0C04, entry_ptr
jsr do_read
L71F7: ldx #$00
ldy #$00
lda (entry_ptr),y
and #$0F
sta record,x
bne L7223
inc L70C3
lda L70C3
cmp L70C0
bne L7212
jmp L71E7
L7212: add16_8 entry_ptr, entry_length, entry_ptr
jmp L71F7
L7223: iny
inx
;; See FileRecord struct for record structure
;; TODO: Determine if this case adjustment is necessary
txa
pha
tya
pha
addr_call_indirect adjust_fileentry_case, entry_ptr
pla
tay
pla
tax
;; name, file_type
: lda (entry_ptr),y
sta record,x
iny
inx
cpx #FileEntry::file_type+1 ; name and type
bne :-
;; blocks
ldy #FileEntry::blocks_used
lda (entry_ptr),y
sta record,x
inx
iny
lda (entry_ptr),y
sta record,x
;; creation date/time
ldy #FileEntry::creation_date
inx
: lda (entry_ptr),y
sta record,x
inx
iny
cpy #FileEntry::creation_date+4
bne :-
;; modification date/time
ldy #FileEntry::mod_date
: lda (entry_ptr),y
sta record,x
inx
iny
cpy #FileEntry::mod_date+4
bne :-
;; access
ldy #FileEntry::access
lda (entry_ptr),y
sta record,x
inx
;; header pointer
ldy #FileEntry::header_pointer
lda (entry_ptr),y
sta record,x
inx
iny
lda (entry_ptr),y
sta record,x
inx
;; aux type
ldy #FileEntry::aux_type
lda (entry_ptr),y
sta record,x
inx
iny
lda (entry_ptr),y
sta record,x
;; Copy entry composed at $1F00 to buffer in Aux LC Bank 2
lda LCBANK2
lda LCBANK2
ldx #record_size-1
ldy #record_size-1
: lda record,x
sta (record_ptr),y
dex
dey
bpl :-
lda LCBANK1
lda LCBANK1
lda #record_size
clc
adc record_ptr
sta record_ptr
bcc L7293
inc record_ptr+1
L7293: jmp do_entry
L7296: copy16 record_ptr, L485F
jsr do_close
jsr pop_pointers
rts
L72A7: .byte 0
L72A8: .word 0
.endproc
;;; --------------------------------------------------
.proc do_open
MLI_RELAY_CALL OPEN, open_params
beq done
jsr ShowAlert
jsr mark_icons_not_opened_2
lda selected_window_index
bne :+
lda icon_params2
sta drive_to_refresh ; icon number
jsr cmd_check_single_drive_by_icon_number
: ldx saved_stack
txs
done: rts
.endproc
;;; --------------------------------------------------
do_read:
MLI_RELAY_CALL READ, read_params
rts
do_close:
MLI_RELAY_CALL CLOSE, close_params
rts
;;; --------------------------------------------------
L72E2: lda $0C04
and #$F0
cmp #$F0
beq get_vol_free_used
rts
get_vol_free_used:
MLI_RELAY_CALL GET_FILE_INFO, get_file_info_params4
beq :+
rts
;; aux = total blocks
: copy16 get_file_info_params4::aux_type, vol_kb_used
;; total - used = free
sub16 get_file_info_params4::aux_type, get_file_info_params4::blocks_used, vol_kb_free
sub16 vol_kb_used, vol_kb_free, vol_kb_used ; total - free = used
lsr16 vol_kb_free
php
lsr16 vol_kb_used
plp
bcc :+
inc16 vol_kb_used
: return #0
.endproc
vol_kb_free := open_directory::vol_kb_free
vol_kb_used := open_directory::vol_kb_used
get_vol_free_used := open_directory::get_vol_free_used
;;; ============================================================
;;; ???
.proc L7345
sta L7445
ldx #0
L734A: lda window_icon_to_filerecord_list+1,x
cmp L7445
beq :+
inx
cpx #8
bne L734A
rts
: stx L7446
dex
: inx
lda window_icon_to_filerecord_list+2,x
sta window_icon_to_filerecord_list+1,x
cpx window_icon_to_filerecord_list
bne :-
dec window_icon_to_filerecord_list
lda L7446
cmp window_icon_to_filerecord_list
bne :+
ldx L7446
asl a
tax
copy16 window_filerecord_table,x, L485F
rts
: lda L7446
asl a
tax
copy16 window_filerecord_table,x, $06
inx
inx
copy16 window_filerecord_table,x, $08
ldy #$00
jsr push_pointers
L73A5: lda LCBANK2
lda LCBANK2
lda ($08),y
sta ($06),y
lda LCBANK1
lda LCBANK1
inc16 $06
inc16 $08
lda $08+1
cmp L485F+1
bne L73A5
lda $08
cmp L485F
bne L73A5
jsr pop_pointers
lda window_icon_to_filerecord_list
asl a
tax
sub16 L485F, window_filerecord_table,x, L7447
inc L7446
L73ED: lda L7446
cmp window_icon_to_filerecord_list
bne :+
jmp L7429
: lda L7446
asl a
tax
sub16 window_filerecord_table+2,x, window_filerecord_table,x, L7449
add16 window_filerecord_table-2,x, L7449, window_filerecord_table,x
inc L7446
jmp L73ED
L7429: lda window_icon_to_filerecord_list
sec
sbc #$01
asl a
tax
add16 window_filerecord_table,x, L7447, L485F
rts
L7445: .byte 0
L7446: .byte 0
L7447: .word 0
L7449: .word 0
.endproc
;;; ============================================================
;;; Compute full path for icon
;;; Inputs: IconEntry pointer in $06
;;; Outputs: open_dir_path_buf has full path
;;; Exceptions: if path too long, shows error and restores saved_stack
.proc compose_icon_full_path
icon_ptr := $06
name_ptr := $06
jsr push_pointers
ldy #IconEntry::win_type
lda (icon_ptr),y
pha
add16 icon_ptr, #IconEntry::len, name_ptr
pla
and #icon_entry_winid_mask
bne has_parent ; A = window_id
;; --------------------------------------------------
;; Desktop (volume) icon - no parent path
;; Copy name, including leading/trailing spaces
ldy #0
lda (name_ptr),y
tay ; Y = length
: lda (name_ptr),y
sta open_dir_path_buf,y
dey
bpl :-
copy #'/', open_dir_path_buf+1 ; Replace leading space with '/'
dec open_dir_path_buf ; Remove trailing space
jsr pop_pointers
rts
;; --------------------------------------------------
;; Windowed (folder) icon - has parent path
has_parent:
parent_path_ptr := $08
jsr window_path_lookup
stax parent_path_ptr
ldy #0
lda (parent_path_ptr),y
clc
adc (name_ptr),y
cmp #67 ; Max path length is 64; title has leading/trailing spaces
bcc :+
lda #ERR_INVALID_PATHNAME
jsr ShowAlert
jsr mark_icons_not_opened_2
dec num_open_windows
ldx saved_stack
txs
rts
;; Copy parent path to open_dir_path_buf
: ldy #0
lda (parent_path_ptr),y
tay
: lda (parent_path_ptr),y
sta open_dir_path_buf,y
dey
bpl :-
;; Suffix with '/'
lda #'/'
inc open_dir_path_buf
ldx open_dir_path_buf
sta open_dir_path_buf,x
;; Append icon name
ldy #0
lda (name_ptr),y
clc
adc open_dir_path_buf
sta open_dir_path_buf
dec open_dir_path_buf ; discount leading/trailing spaces
dec open_dir_path_buf
iny
: iny ; skip leading space immediately
inx
lda (name_ptr),y
sta open_dir_path_buf,x
cpx open_dir_path_buf
bne :-
jsr pop_pointers
rts
.endproc
;;; ============================================================
;;; Set up path and coords for new window, contents and free/used.
;;; Inputs: IconEntry pointer in $06, new window_id in cached_window_id,
;;; open_dir_path_buf has full path
;;; Outputs: Winfo configured, window path table entry set
.proc prepare_new_window
icon_ptr := $06
;; Copy icon name to window title (including leading/trailing spaces)
.scope
name_ptr := icon_ptr
title_ptr := $08
jsr push_pointers
lda cached_window_id
asl a
tax
copy16 window_title_addr_table,x, title_ptr
add16 icon_ptr, #IconEntry::len, name_ptr
ldy #0
lda (name_ptr),y
tay
: lda (name_ptr),y
sta (title_ptr),y
dey
bpl :-
jsr pop_pointers
.endscope
;; --------------------------------------------------
path_ptr := $08
;; Copy previously composed path into window path
lda cached_window_id
jsr window_path_lookup
stax path_ptr
ldy open_dir_path_buf
: lda open_dir_path_buf,y
sta (path_ptr),y
dey
bpl :-
;; --------------------------------------------------
winfo_ptr := $06
;; Set window coordinates
lda cached_window_id
jsr window_lookup
stax winfo_ptr
ldy #MGTK::Winfo::port
;; xcoord = (window_id-1) * 16 + 5
;; ycoord = (window_id-1) * 8 + 27
lda cached_window_id
sec
sbc #1 ; * 16
asl a
asl a
asl a
asl a
pha
adc #5
sta (winfo_ptr),y ; viewloc::xcoord
iny
lda #0
sta (winfo_ptr),y
iny
pla
lsr a ; / 2
clc
adc #27
sta (winfo_ptr),y ; viewloc::ycoord
iny
lda #0
sta (winfo_ptr),y
;; Map rect
lda #0
ldy #MGTK::Winfo::port + MGTK::GrafPort::maprect + 3
ldx #3
: sta (winfo_ptr),y
dey
dex
bpl :-
;; Scrollbars
ldy #MGTK::Winfo::hscroll
lda (winfo_ptr),y
and #AS_BYTE(~MGTK::Scroll::option_active)
sta (winfo_ptr),y
iny ; vscroll
lda (winfo_ptr),y
and #AS_BYTE(~MGTK::Scroll::option_active)
sta (winfo_ptr),y
lda #0
ldy #MGTK::Winfo::hthumbpos
sta (winfo_ptr),y
ldy #MGTK::Winfo::vthumbpos
sta (winfo_ptr),y
;; --------------------------------------------------
lda icon_params2
jsr open_directory
lda icon_params2
jsr icon_entry_lookup
stax icon_ptr
ldy #IconEntry::win_type
lda (icon_ptr),y
and #icon_entry_winid_mask
beq :+
;; Windowed (folder) icon
tax
dex
txa
asl a
tax
copy16 window_k_used_table,x, vol_kb_used
copy16 window_k_free_table,x, vol_kb_free
;; Desktop (volume) icon
: ldx cached_window_id
dex
txa
asl a
tax
copy16 vol_kb_used, window_k_used_table,x
copy16 vol_kb_free, window_k_free_table,x
lda cached_window_id
jsr create_file_icon_ep1
rts
.endproc
;;; ============================================================
;;; File Icon Entry Construction
.proc create_file_icon
icon_x_spacing = 80
icon_y_spacing = 32
window_id: .byte 0
iconbits: .addr 0
icon_type: .byte 0
icon_height: .word 0
L7625: .byte 0 ; ???
max_icon_height = 17
initial_coords: ; first icon in window
DEFINE_POINT 52,16 + max_icon_height, initial_coords
row_coords: ; first icon in current row
DEFINE_POINT 0, 0, row_coords
icons_per_row:
.byte 5
icons_this_row:
.byte 0
icon_coords:
DEFINE_POINT 0, 0, icon_coords
flag: .byte 0 ; ???
.proc ep1 ; entry point #1 ???
pha
lda #0
beq L7647
ep2: pha ; entry point #2 ???
ldx cached_window_id
dex
lda window_to_dir_icon_table,x
;; TODO: Guaranteed to exist?
sta icon_params2
lda #$80
L7647: sta flag
pla
sta window_id
jsr push_pointers
COPY_STRUCT MGTK::Point, initial_coords, row_coords
lda #0
sta icons_this_row
sta L7625
ldx #3
: sta icon_coords,x
dex
bpl :-
lda icon_params2
ldx window_icon_to_filerecord_list
dex
: cmp window_icon_to_filerecord_list+1,x
beq :+
dex
bpl :-
rts
: txa
asl a
tax
copy16 window_filerecord_table,x, $06
lda LCBANK2
lda LCBANK2
ldy #0
lda ($06),y
sta L7764
lda LCBANK1
lda LCBANK1
inc $06
lda $06
bne L76A4
inc $06+1
L76A4: lda cached_window_id
sta active_window_id
L76AA: lda L7625
cmp L7764
beq L76BB
jsr alloc_and_populate_file_icon
inc L7625
jmp L76AA
L76BB: bit flag
bpl :+
jsr pop_pointers
rts
: jsr compute_icons_bbox
lda window_id
jsr window_lookup
stax $06
ldy #$16
lda iconbb_rect+MGTK::Rect::y2
sec
sbc ($06),y
sta iconbb_rect+MGTK::Rect::y2
lda iconbb_rect+MGTK::Rect::y2+1
sbc #0
sta iconbb_rect+MGTK::Rect::y2+1
cmp16 iconbb_rect+MGTK::Rect::x2, #170
bmi L7705
cmp16 iconbb_rect+MGTK::Rect::x2, #450
bpl L770C
ldax iconbb_rect+MGTK::Rect::x2
jmp L7710
L7705: addr_jump L7710, $00AA
L770C: ldax #450
L7710: ldy #$20
sta ($06),y
txa
iny
sta ($06),y
cmp16 iconbb_rect+MGTK::Rect::y2, #50
bmi L7739
cmp16 iconbb_rect+MGTK::Rect::y2, #108
bpl L7740
ldax iconbb_rect+MGTK::Rect::y2
jmp L7744
L7739: addr_jump L7744, $0032
L7740: ldax #108
L7744: ldy #$22
sta ($06),y
txa
iny
sta ($06),y
lda L7767
ldy #$06
sta ($06),y
ldy #$08
sta ($06),y
lda icon_params2
ldx window_id
jsr animate_window_open
jsr pop_pointers
rts
L7764: .byte $00,$00,$00
L7767: .byte $14
.endproc
;;; ============================================================
;;; Create icon
.proc alloc_and_populate_file_icon
file_entry := $6
icon_entry := $8
name_tmp := $1800
inc icon_count
jsr AllocateIcon
ldx cached_window_icon_count
inc cached_window_icon_count
sta cached_window_icon_list,x
jsr icon_entry_lookup
stax icon_entry
lda LCBANK2
lda LCBANK2
;; Copy the name (offset by 2 for count and leading space)
ldy #FileRecord::name
lda (file_entry),y
sta name_tmp
iny
ldx #0
: lda (file_entry),y
sta name_tmp+2,x
inx
iny
cpx name_tmp
bne :-
inc name_tmp ; length += 2 for leading/trailing spaces
inc name_tmp
lda #' ' ; leading space
sta name_tmp+1
ldx name_tmp
sta name_tmp,x ; trailing space
;; Check file type
ldy #FileRecord::file_type
lda (file_entry),y
;; Handle several classes of overrides
sta fto_type
ldy #FileRecord::aux_type
copy16in (file_entry),y, fto_auxtype
ldy #FileRecord::blocks
copy16in (file_entry),y, fto_blocks
jsr check_file_type_overrides
;; Distinguish *.SYSTEM files as apps (use $01) from other
;; type=SYS files (use $FF).
cmp #FT_SYSTEM
bne got_type
ldy #FileRecord::name
lda (file_entry),y
tay
ldx str_sys_suffix
cloop: lda (file_entry),y
jsr upcase_char
cmp str_sys_suffix,x
bne not_app
dey
beq not_app
dex
bne cloop
is_app:
lda #APP_FILE_TYPE ; overloaded meaning in icon tables
bne got_type ; always
str_sys_suffix:
PASCAL_STRING ".SYSTEM"
not_app:
lda #$FF
;; fall through
got_type:
tay
;; Figure out icon type
lda LCBANK1
lda LCBANK1
tya
jsr find_icon_details_for_file_type
ldy #IconEntry::len
ldx #0
L77F0: lda name_tmp,x
sta (icon_entry),y
iny
inx
cpx name_tmp
bne L77F0
lda name_tmp,x
sta (icon_entry),y
;; Assign location
ldx #0
ldy #IconEntry::iconx
: lda row_coords,x
sta (icon_entry),y
inx
iny
cpx #.sizeof(MGTK::Point)
bne :-
;; Include y-offset
ldy #IconEntry::icony
sub16in (icon_entry),y, icon_height, (icon_entry),y
lda cached_window_icon_count
cmp icons_per_row
beq L781A
bcs L7826
L781A: copy16 row_coords::xcoord, icon_coords::xcoord
L7826: copy16 row_coords::ycoord, icon_coords::ycoord
inc icons_this_row
lda icons_this_row
cmp icons_per_row
bne L7862
;; Next row (and initial column) if necessary
add16 row_coords::ycoord, #32, row_coords::ycoord
copy16 initial_coords::xcoord, row_coords::xcoord
lda #0
sta icons_this_row
jmp L7870
;; Next column otherwise
L7862: lda row_coords::xcoord
clc
adc #icon_x_spacing
sta row_coords::xcoord
bcc L7870
inc row_coords::xcoord+1
L7870: lda cached_window_id
ora icon_type
ldy #IconEntry::win_type
sta (icon_entry),y
ldy #IconEntry::iconbits
copy16in iconbits, (icon_entry),y
ldx cached_window_icon_count
dex
lda cached_window_icon_list,x
jsr icon_window_to_screen
add16 file_entry, #icon_y_spacing, file_entry
rts
.endproc
;;; ============================================================
;;; Special case: $01 is used for App-like SYS files.
.proc find_icon_details_for_file_type
ptr := $6
sta file_type
jsr push_pointers
;; Find index of file type
copy16 #type_table, ptr
ldy #num_file_types-1
: lda (ptr),y
cmp file_type
beq found
dey
bpl :-
ldy #0 ; default is first entry (FT_TYPELESS)
found:
;; Look up icon type
copy16 #icon_type_table, ptr
lda (ptr),y
sta icon_type
tya
asl a
tay
;; Look up icon definition
copy16 #type_icons_table, ptr
copy16in (ptr),y, iconbits
;; Icon height will be needed too
copy16 iconbits, ptr
ldy #IconDefinition::maprect + MGTK::Rect::y2
copy16in (ptr),y, icon_height
jsr pop_pointers
rts
file_type:
.byte 0
.endproc
.endproc
create_file_icon_ep2 := create_file_icon::ep1::ep2
create_file_icon_ep1 := create_file_icon::ep1
;;; ============================================================
;;; Check file type for possible overrides
;;; Input: fto_type, fto_auxtype, fto_blocks populated
;;; Output: A is filetype to use (for icons, open/preview, etc)
.proc check_file_type_overrides
ptr := $06
jsr push_pointers
copy16 #fto_table, ptr
loop: ldy #0 ; type_mask, or $00 if done
lda (ptr),y
bne :+
jsr pop_pointers
lda fto_type
rts
;; Check type (with mask)
: and fto_type ; A = type & type_mask
iny ; ASSERT: Y = FTORecord::type
cmp (ptr),y ; type check
bne next
;; Flags
iny ; ASSERT: Y = FTORecord::flags
lda (ptr),y
sta flags
;; Does Aux Type matter, and if so does it match?
bit flags
bpl blocks ; bit 7 = compare aux
iny ; ASSERT: Y = FTORecord::aux
lda fto_auxtype
cmp (ptr),y
bne next
iny
lda fto_auxtype+1
cmp (ptr),y
bne next
;; Does Block Count matter, and if so does it match?
blocks: bit flags
bvc match ; bit 6 = compare blocks
ldy #FTORecord::blocks
lda fto_blocks
cmp (ptr),y
bne next
iny
lda fto_blocks+1
cmp (ptr),y
bne next
;; Have a match
match: ldy #FTORecord::newtype
lda (ptr),y
sta fto_type
;; Next entry
next: add16 ptr, #.sizeof(FTORecord), ptr
jmp loop
flags: .byte 0
.endproc
;;; ============================================================
;;; Draw header (items/k in disk/k available/lines)
.proc draw_window_header
;; Compute header coords
;; x coords
lda grafport2::cliprect::x1
sta header_line_left::xcoord
clc
adc #5
sta items_label_pos::xcoord
lda grafport2::cliprect::x1+1
sta header_line_left::xcoord+1
adc #0
sta items_label_pos::xcoord+1
;; y coords
lda grafport2::cliprect::y1
clc
adc #12
sta header_line_left::ycoord
sta header_line_right::ycoord
lda grafport2::cliprect::y1+1
adc #0
sta header_line_left::ycoord+1
sta header_line_right::ycoord+1
;; Draw top line
MGTK_RELAY_CALL MGTK::MoveTo, header_line_left
copy16 grafport2::cliprect::x2, header_line_right::xcoord
jsr set_penmode_xor
MGTK_RELAY_CALL MGTK::LineTo, header_line_right
;; Offset down by 2px
lda header_line_left::ycoord
clc
adc #2
sta header_line_left::ycoord
sta header_line_right::ycoord
lda header_line_left::ycoord+1
adc #0
sta header_line_left::ycoord+1
sta header_line_right::ycoord+1
;; Draw bottom line
MGTK_RELAY_CALL MGTK::MoveTo, header_line_left
MGTK_RELAY_CALL MGTK::LineTo, header_line_right
;; Baseline for header text
add16 grafport2::cliprect::y1, #10, items_label_pos::ycoord
;; Draw "XXX Items"
lda cached_window_icon_count
ldx #0
jsr int_to_string
lda cached_window_icon_count
cmp #2 ; plural?
bcs :+
dec str_items ; remove trailing s
: MGTK_RELAY_CALL MGTK::MoveTo, items_label_pos
jsr draw_int_string
addr_call draw_pascal_string, str_items
lda cached_window_icon_count
cmp #2
bcs :+
inc str_items ; restore trailing s
;; Draw "XXXK in disk"
: jsr calc_header_coords
ldx active_window_id
dex ; index 0 is window 1
txa
asl a
tax
lda window_k_used_table,x
tay
lda window_k_used_table+1,x
tax
tya
jsr int_to_string
MGTK_RELAY_CALL MGTK::MoveTo, pos_k_in_disk
jsr draw_int_string
addr_call draw_pascal_string, str_k_in_disk
;; Draw "XXXK available"
ldx active_window_id
dex ; index 0 is window 1
txa
asl a
tax
lda window_k_free_table,x
tay
lda window_k_free_table+1,x
tax
tya
jsr int_to_string
MGTK_RELAY_CALL MGTK::MoveTo, pos_k_available
jsr draw_int_string
addr_call draw_pascal_string, str_k_available
rts
;;; --------------------------------------------------
.proc calc_header_coords
;; Width of window
sub16 grafport2::cliprect::x2, grafport2::cliprect::x1, xcoord
;; Is there room to spread things out?
sub16 xcoord, width_items_label, xcoord
bpl :+
jmp skipcenter
: sub16 xcoord, width_right_labels, xcoord
bpl :+
jmp skipcenter
;; Yes - center "k in disk"
: add16 width_left_labels, xcoord, pos_k_available::xcoord
lda xcoord+1
beq :+
lda xcoord
cmp #24 ; threshold
bcc nosub
: sub16 pos_k_available::xcoord, #12, pos_k_available::xcoord
nosub: lsr16 xcoord ; divide by 2 to center
add16 width_items_label_padded, xcoord, pos_k_in_disk::xcoord
jmp finish
;; No - just squish things together
skipcenter:
copy16 width_items_label_padded, pos_k_in_disk::xcoord
copy16 width_left_labels, pos_k_available::xcoord
finish:
add16 pos_k_in_disk::xcoord, grafport2::cliprect::x1, pos_k_in_disk::xcoord
add16 pos_k_available::xcoord, grafport2::cliprect::x1, pos_k_available::xcoord
;; Update y coords
lda items_label_pos::ycoord
sta pos_k_in_disk::ycoord
sta pos_k_available::ycoord
lda items_label_pos::ycoord+1
sta pos_k_in_disk::ycoord+1
sta pos_k_available::ycoord+1
rts
.endproc ; calc_header_coords
draw_int_string:
addr_jump draw_pascal_string, str_from_int
xcoord:
.word 0
.endproc ; draw_window_header
;;; ============================================================
;;; Input: 16-bit unsigned number in A,X
;;; Output: length-prefixed string in str_from_int
.proc int_to_string
stax value
lda #0
sta nonzero_flag
ldy #0 ; y = position in string
ldx #0 ; x = which power index is subtracted (*2)
;; For each power of ten
loop: lda #0
sta digit
;; Keep subtracting/incrementing until zero is hit
sloop: cmp16 value, powers,x
bcc break
inc digit
sub16 value, powers,x, value
jmp sloop
break: lda digit
bne not_pad
bit nonzero_flag
bpl next
;; Convert to ASCII
not_pad:
ora #'0'
pha
copy #$80, nonzero_flag
pla
;; Place the character, move to next
iny
sta str_from_int,y
next: inx
inx
cpx #8 ; up to 4 digits (*2) via subtraction
beq done
jmp loop
done: lda value ; handle last digit
ora #'0'
iny
sta str_from_int,y
sty str_from_int
rts
powers: .word 10000, 1000, 100, 10
value: .word 0 ; remaining value as subtraction proceeds
digit: .byte 0 ; current digit being accumulated
nonzero_flag: ; high bit set once a non-zero digit seen
.byte 0
.endproc ; int_to_string
;;; ============================================================
;;; Compute bounding box for icons within cached window
iconbb_rect:
DEFINE_RECT 0,0,0,0,iconbb_rect
.proc compute_icons_bbox_impl
cur_icon_pos:
DEFINE_POINT 0,0,cur_icon_pos
entry_ptr := $06
kIntMax = $7FFF
kPadTop = 15
kPadLeft = 50
kPadBottom = 32
kPadRight = 50
start: ldx #3
lda #0
: sta iconbb_rect::x2,x
dex
bpl :-
sta icon_num
lda #<kIntMax
sta iconbb_rect::x1
sta iconbb_rect+MGTK::Rect::y1
lda #>kIntMax
sta iconbb_rect::x1+1
sta iconbb_rect+MGTK::Rect::y1+1
ldx cached_window_id
dex
lda win_view_by_table,x
bpl L7BCB ; icon view
;; List view
lda cached_window_icon_count
bne L7BA1
L7B96: ldax #$0300
L7B9A: sta iconbb_rect::x1,x
dex
bpl L7B9A
rts
;; iconbb_rect::x2 = 360
;; iconbb_rect::y2 = (A + 2) * 8
L7BA1: clc
adc #2
ldx #0
stx hi
asl a
rol hi
asl a
rol hi
asl a
rol hi
sta iconbb_rect::y2
lda hi
sta iconbb_rect::y2+1
copy16 #360, iconbb_rect::x2
jmp L7B96
;; Icon view
L7BCB: lda cached_window_icon_count
cmp #1
bne check_icon
;; First icon - copy coords
lda cached_window_icon_list
jsr icon_entry_lookup
stax entry_ptr
ldy #IconEntry::iconx+.sizeof(MGTK::Point)-1
ldx #.sizeof(MGTK::Point)-1
: lda (entry_ptr),y
sta iconbb_rect::x1,x
sta iconbb_rect::x2,x
dey
dex
bpl :-
jmp finish
check_icon:
lda icon_num
cmp cached_window_icon_count
bne more
finish: lda iconbb_rect::x2
clc
adc #kPadRight
sta iconbb_rect::x2
bcc :+
inc iconbb_rect::x2+1
: lda iconbb_rect::y2
clc
adc #kPadBottom
sta iconbb_rect::y2
bcc :+
inc iconbb_rect::y2+1
: sub16 iconbb_rect::x1, #kPadLeft, iconbb_rect::x1
sub16 iconbb_rect::y1, #kPadTop, iconbb_rect::y1
rts
more: tax
lda cached_window_icon_list,x
jsr icon_entry_lookup
stax entry_ptr
ldy #IconEntry::win_type
lda (entry_ptr),y
and #icon_entry_winid_mask
cmp hi ; BUG: from old code that iterated all icons???
bne :+
inc icon_num
jmp check_icon
: ldy #IconEntry::iconx+.sizeof(MGTK::Point)-1
ldx #.sizeof(MGTK::Point)-1
: lda (entry_ptr),y
sta cur_icon_pos::xcoord,x
dey
dex
bpl :-
;; --------------------------------------------------
;; Compare X coords
bit iconbb_rect::x1+1 ; negative?
bmi pt0x_neg
bit cur_icon_pos::xcoord+1
bmi adjust_pt0_x
;; X: cur and pt0 are positive
cmp16 cur_icon_pos::xcoord, iconbb_rect::x1
bmi adjust_pt0_x
cmp16 cur_icon_pos::xcoord, iconbb_rect::x2
bpl adjust_pt1_x
jmp compare_y
pt0x_neg:
bit cur_icon_pos::xcoord+1
bmi bothx_neg
;; X: cur positive, pt0 negative
bit iconbb_rect::x2+1
bmi compare_y
cmp16 cur_icon_pos::xcoord, iconbb_rect::x2
bmi compare_y
jmp adjust_pt1_x
;; X: cur and pt0 are negative
bothx_neg:
cmp16 cur_icon_pos::xcoord, iconbb_rect::x1
bmi adjust_pt0_x
cmp16 cur_icon_pos::xcoord, iconbb_rect::x2
bmi compare_y
adjust_pt1_x:
copy16 cur_icon_pos::xcoord, iconbb_rect::x2
jmp compare_y
adjust_pt0_x:
copy16 cur_icon_pos::xcoord, iconbb_rect::x1
;; --------------------------------------------------
;; Compare Y coords
compare_y:
bit iconbb_rect::y1+1
bmi pt0y_neg
bit cur_icon_pos::ycoord+1
bmi adjust_pt0_y
;; Y: cur and pt0 are positive
cmp16 cur_icon_pos::ycoord, iconbb_rect::y1
bmi adjust_pt0_y
cmp16 cur_icon_pos::ycoord, iconbb_rect::y2
bpl adjust_pt1_y
jmp next
pt0y_neg:
bit cur_icon_pos::ycoord+1
bmi bothy_neg
;; Y: cur positive, pt0 negative
bit iconbb_rect::y2+1
bmi next
cmp16 cur_icon_pos::ycoord, iconbb_rect::y2
bmi next
jmp adjust_pt1_y
;; Y: cur and pt0 are negative
bothy_neg:
cmp16 cur_icon_pos::ycoord, iconbb_rect::y1
bmi adjust_pt0_y
cmp16 cur_icon_pos::ycoord, iconbb_rect::y2
bmi next
adjust_pt1_y:
copy16 cur_icon_pos::ycoord, iconbb_rect::y2
jmp next
adjust_pt0_y:
copy16 cur_icon_pos::ycoord, iconbb_rect::y1
next: inc icon_num
jmp check_icon
icon_num:
.byte 0
hi: .byte 0
.endproc
compute_icons_bbox := compute_icons_bbox_impl::start
;;; ============================================================
;;; Compute dimensions of window
;;; Input: A = window
;;; Output: A,X = width, Y = height
.proc compute_window_dimensions
ptr := $06
jsr window_lookup
stax ptr
;; Copy window's maprect
ldy #MGTK::Winfo::port + MGTK::GrafPort::maprect + .sizeof(MGTK::Rect)-1
ldx #.sizeof(MGTK::Rect)-1
: lda (ptr),y
sta rect,x
dey
dex
bpl :-
;; Push delta-X
lda rect+MGTK::Rect::x2
sec
sbc rect+MGTK::Rect::x1
pha
lda rect+MGTK::Rect::x2+1
sbc rect+MGTK::Rect::x1+1
pha
;; Push delta-Y
lda rect+MGTK::Rect::y2
sec
sbc rect+MGTK::Rect::y1
pha
lda rect+MGTK::Rect::y2+1
sbc rect+MGTK::Rect::y1+1
;; high byte is discarded
pla
tay
pla
tax
pla
rts
rect: DEFINE_RECT 0,0,0,0
.endproc
;;; ============================================================
.proc sort_records
ptr := $06
record_num := $800
list_start_ptr := $801
num_records := $803
;; $804 = scratch byte
index := $805
jmp start
start: ldx cached_window_id
dex
lda window_to_dir_icon_table,x
;; BUG: What if dir icon is freed? ($FF)
ldx #0
: cmp window_icon_to_filerecord_list+1,x
beq found
inx
cpx window_icon_to_filerecord_list
bne :-
rts
found: txa
asl a
tax
lda window_filerecord_table,x ; Ptr points at start of record
sta ptr
sta list_start_ptr
lda window_filerecord_table+1,x
sta ptr+1
sta list_start_ptr+1
lda LCBANK2 ; Start copying records
lda LCBANK2
lda #0 ; Number copied
sta record_num
tay
lda (ptr),y ; Number to copy
sta num_records
inc ptr ; Point past number
inc list_start_ptr
bne loop
inc ptr+1
inc list_start_ptr+1
loop: lda record_num
cmp num_records
beq break
jsr ptr_calc
ldy #0
lda (ptr),y
and #$7F ; mask off high bit
sta (ptr),y ; mark as ???
ldy #FileRecord::modification_date ; ???
lda (ptr),y
bne next
iny
lda (ptr),y ; modification_date hi
bne next
lda #$01 ; if no mod date, set hi to 1 ???
sta (ptr),y
next: inc record_num
jmp loop
break: lda LCBANK1 ; Done copying records
lda LCBANK1
;; --------------------------------------------------
;; What sort order?
ldx cached_window_id
dex
lda win_view_by_table,x
cmp #view_by_name
beq :+
jmp check_date
:
;; By Name
;; Sorted in increasing lexicographical order
.scope
name := $807
name_size = $F
name_len := $804
lda LCBANK2
lda LCBANK2
;; Set up highest value ("ZZZZZZZZZZZZZZZ")
lda #'Z'
ldx #name_size
: sta name+1,x
dex
bpl :-
lda #0
sta index
sta record_num
loop: lda index
cmp num_records
bne iloop
jmp finish_view_change
iloop: jsr ptr_calc
;; Check record for mark
ldy #0
lda (ptr),y
bmi inext
;; Compare names
and #NAME_LENGTH_MASK
sta name_len
ldy #1
cloop: lda (ptr),y
jsr upcase_char
cmp name,y
beq :+
bcs inext
jmp place
: iny
cpy #$10
bne cloop
jmp inext
;; if less than
place: lda record_num
sta $0806
ldx #name_size
lda #' '
: sta name+1,x
dex
bpl :-
ldy name_len
: lda (ptr),y
jsr upcase_char
sta name,y
dey
bne :-
inext: inc record_num
lda record_num
cmp num_records
beq :+
jmp iloop
: inc index
lda $0806
sta record_num
jsr ptr_calc
;; Mark record
ldy #0
lda (ptr),y
ora #$80
sta (ptr),y
lda #'Z'
ldx #15
: sta $0808,x
dex
bpl :-
ldx index
dex
ldy $0806
iny
jsr L812B
lda #0
sta record_num
jmp loop
.endscope
;; --------------------------------------------------
check_date:
cmp #view_by_date
beq :+
jmp check_size
:
;; By Date
;; Sorted by decreasing date
.scope
date := $0808
lda LCBANK2
lda LCBANK2
lda #0
sta date
sta date+1
sta index
sta record_num
loop: lda index
cmp num_records
bne iloop
jmp finish_view_change
iloop: jsr ptr_calc
;; Check record for mark
ldy #0
lda (ptr),y
bmi inext
;; Compare dates
ldy #FileRecord::modification_date
copy16in (ptr),y, date_a
copy16 date, date_b
jsr compare_dates
beq inext
bcc inext
;; if greater than
place: ldy #FileRecord::modification_date+1
lda (ptr),y
sta date+1
dey
lda (ptr),y
sta date
lda record_num
sta $0806
inext: inc record_num
lda record_num
cmp num_records
beq next
jmp iloop
next: inc index
lda $0806
sta record_num
jsr ptr_calc
;; Mark record
ldy #0
lda (ptr),y
ora #$80
sta (ptr),y
lda #0
sta date
sta date+1
ldx index
dex
ldy $0806
iny
jsr L812B
copy #0, record_num
jmp loop
.endscope
;; --------------------------------------------------
check_size:
cmp #view_by_size
beq :+
jmp check_type
:
;; By Size
;; Sorted by decreasing size
.scope
size := $0808
lda LCBANK2
lda LCBANK2
lda #0
sta size
sta size+1
sta index
sta record_num
loop: lda index
cmp num_records
bne iloop
jmp finish_view_change
iloop: jsr ptr_calc
;; Check record for mark
ldy #0
lda (ptr),y
bmi inext
ldy #FileRecord::blocks+1
lda (ptr),y
cmp size+1 ; hi byte
beq :+
bcs place
: dey
lda (ptr),y
cmp size ; lo byte
beq place
bcc inext
;; if greater than
place: copy16in (ptr),y, size
lda record_num
sta $0806
inext: inc record_num
lda record_num
cmp num_records
beq next
jmp iloop
next: inc index
lda $0806
sta record_num
jsr ptr_calc
;; Mark record
ldy #0
lda (ptr),y
ora #$80
sta (ptr),y
lda #0
sta size
sta size+1
ldx index
dex
ldy $0806
iny
jsr L812B
lda #0
sta record_num
jmp loop
lda LCBANK1
lda LCBANK1
copy16 #84, pos_col_name::xcoord
copy16 #203, pos_col_type::xcoord
lda #0
sta pos_col_size::xcoord
sta pos_col_size::xcoord+1
copy16 #231, pos_col_date::xcoord
lda LCBANK2
lda LCBANK2
jmp finish_view_change
.endscope
;; --------------------------------------------------
check_type:
cmp #view_by_type
beq :+
rts
:
;; By Type
;; Types are ordered by type_table
.scope
type_table_copy := $807
;; Copy type_table prefixed by length to $807
copy16 #type_table, $08
copy #num_file_types, type_table_copy
ldy #num_file_types-1
: lda ($08),y
sta type_table_copy+1,y
dey
bne :-
lda LCBANK2
lda LCBANK2
lda #0
sta index
sta record_num
copy #$FF, $0806
loop: lda index
cmp num_records
bne iloop
jmp finish_view_change
iloop: jsr ptr_calc
;; Check record for mark
ldy #0
lda (ptr),y
bmi inext
;; Compare types
ldy #FileRecord::file_type
lda (ptr),y
ldx type_table_copy
cpx #0
beq place
cmp type_table_copy+1,x
bne inext
place: lda record_num
sta $0806
jmp L809E
inext: inc record_num
lda record_num
cmp num_records
beq next
jmp iloop
next: lda $0806
cmp #$FF
bne L809E
dec type_table_copy ; size of table
lda #0
sta record_num
jmp iloop
L809E: inc index
lda $0806
sta record_num
jsr ptr_calc
;; Mark record
ldy #0
lda (ptr),y
ora #$80
sta (ptr),y
ldx index
dex
ldy $0806
iny
jsr L812B
copy #0, record_num
copy #$FF, $0806
jmp loop
.endscope
;;; --------------------------------------------------
;;; ptr = list_start_ptr + ($800 * .sizeof(FileRecord))
.proc ptr_calc
ptr := $6
hi := $0804
lda #0
sta hi
lda record_num
asl a
rol hi
asl a
rol hi
asl a
rol hi
asl a
rol hi
asl a
rol hi
clc
adc list_start_ptr
sta ptr
lda list_start_ptr+1
adc hi
sta ptr+1
rts
.endproc
;;; --------------------------------------------------
date_a: .word 0
date_b: .word 0
.proc compare_dates
ptr := $0A
copy16 #parsed_a, ptr
ldax date_a
jsr parse_date
copy16 #parsed_b, ptr
ldax date_b
jsr parse_date
lda year_a+1
cmp year_b+1
bne done
lda year_a
cmp year_b
bne done
lda month_a
cmp month_b
bne done
lda day_a
cmp day_b
done: rts
parsed_a:
year_a: .word 0
month_a:.byte 0
day_a: .byte 0
parsed_b:
year_b: .word 0
month_b:.byte 0
day_b: .byte 0
.endproc
;;; --------------------------------------------------
;;; ???
.proc finish_view_change
ptr := $06
copy #0, record_num
loop: lda record_num
cmp num_records
beq done
jsr ptr_calc
ldy #$00
lda (ptr),y
and #$7F
sta (ptr),y
ldy #$17
lda (ptr),y
bne :+
iny
lda (ptr),y
cmp #$01
bne :+
lda #$00
sta (ptr),y
: inc record_num
jmp loop
done: lda LCBANK1
lda LCBANK1
rts
.endproc
;;; --------------------------------------------------
;;; ???
.proc L812B
lda LCBANK1
lda LCBANK1
tya
sta cached_window_icon_list,x
lda LCBANK2
lda LCBANK2
rts
.endproc
.endproc
;;; ============================================================
.proc L813F_impl
L813C: .byte 0
.byte 0
L813E: .byte 8
start: ldy #$00
tax
dex
txa
sty L813C
asl a
rol L813C
asl a
rol L813C
asl a
rol L813C
asl a
rol L813C
asl a
rol L813C
clc
adc LE71D
sta $06
lda LE71D+1
adc L813C
sta $06+1
lda LCBANK2
lda LCBANK2
ldy #$1F
L8171: lda ($06),y
sta LEC43,y
dey
bpl L8171
lda LCBANK1
lda LCBANK1
ldx #$31
lda #' '
L8183: sta text_buffer2::data-1,x
dex
bpl L8183
copy #0, text_buffer2::length
lda pos_col_type::ycoord
clc
adc L813E
sta pos_col_type::ycoord
bcc L819D
inc pos_col_type::ycoord+1
L819D: lda pos_col_size::ycoord
clc
adc L813E
sta pos_col_size::ycoord
bcc L81AC
inc pos_col_size::ycoord+1
L81AC: lda pos_col_date::ycoord
clc
adc L813E
sta pos_col_date::ycoord
bcc L81BB
inc pos_col_date::ycoord+1
L81BB: cmp16 pos_col_name::ycoord, grafport2::cliprect::y2
bmi L81D9
lda pos_col_name::ycoord
clc
adc L813E
sta pos_col_name::ycoord
bcc L81D8
inc pos_col_name::ycoord+1
L81D8: rts
L81D9: lda pos_col_name::ycoord
clc
adc L813E
sta pos_col_name::ycoord
bcc L81E8
inc pos_col_name::ycoord+1
L81E8: cmp16 pos_col_name::ycoord, grafport2::cliprect::y1
bpl L81F7
rts
L81F7: jsr prepare_col_name
addr_call SetPosDrawText, pos_col_name
jsr prepare_col_type
addr_call SetPosDrawText, pos_col_type
jsr prepare_col_size
addr_call SetPosDrawText, pos_col_size
jsr compose_date_string
addr_jump SetPosDrawText, pos_col_date
.endproc
L813F := L813F_impl::start
;;; ============================================================
.proc prepare_col_name
lda LEC43
and #$0F
sta text_buffer2::length
tax
loop: lda LEC43,x
sta text_buffer2::data,x
dex
bne loop
lda #' '
sta text_buffer2::data
inc text_buffer2::length
rts
.endproc
.proc prepare_col_type
lda LEC53
jsr compose_file_type_string
;; BUG: should be 4 not 5???
COPY_BYTES 5, str_file_type, text_buffer2::data-1
rts
.endproc
.proc prepare_col_size
ldax LEC54
;; fall through
.endproc
;;; ============================================================
;;; Populate text_buffer2 with " 12345 Blocks"
.proc compose_blocks_string
stax value
jsr int_to_string
;; Leading space
ldx #1
stx text_buffer2::length
copy #' ', text_buffer2::data
;; Append number
ldy #0
: lda str_from_int+1,y
sta text_buffer2::data,x ; data follows length
iny
inx
cpy str_from_int
bne :-
;; Append suffix
ldy #0
: lda suffix+1, y
sta text_buffer2::data,x
iny
inx
cpy suffix
bne :-
;; If singular, drop trailing 's'
;; Block or Blocks?
lda value+1
cmp #>1
bne :+
lda value
cmp #<1
bne :+
dex
: stx text_buffer2::length
done: rts
suffix: PASCAL_STRING " Blocks"
value: .word 0
.endproc
;;; ============================================================
.proc compose_date_string
ldx #21
lda #' '
: sta text_buffer2::data-1,x
dex
bpl :-
lda #1
sta text_buffer2::length
copy16 #text_buffer2::length, $8
lda date ; any bits set?
ora date+1
bne append_date_strings
sta month ; 0 is "no date" string
jmp append_month_string
append_date_strings:
copy16 #parsed_date, $0A
ldax date
jsr parse_date
jsr append_month_string
addr_call concatenate_date_part, str_space
jsr append_day_string
addr_call concatenate_date_part, str_space
jmp append_year_string
.proc append_day_string
lda day
ldx #0
jsr int_to_string
addr_jump concatenate_date_part, str_from_int
.endproc
.proc append_month_string
lda month
asl a
tay
lda month_table+1,y
tax
lda month_table,y
jmp concatenate_date_part
.endproc
.proc append_year_string
ldax year
jsr int_to_string
addr_jump concatenate_date_part, str_from_int
.endproc
parsed_date:
year: .word 0
month: .byte 0
day: .byte 0
month_table:
.addr str_no_date
.addr str_jan,str_feb,str_mar,str_apr,str_may,str_jun
.addr str_jul,str_aug,str_sep,str_oct,str_nov,str_dec
str_no_date:
PASCAL_STRING "no date"
str_jan:PASCAL_STRING "January"
str_feb:PASCAL_STRING "February"
str_mar:PASCAL_STRING "March"
str_apr:PASCAL_STRING "April"
str_may:PASCAL_STRING "May"
str_jun:PASCAL_STRING "June"
str_jul:PASCAL_STRING "July"
str_aug:PASCAL_STRING "August"
str_sep:PASCAL_STRING "September"
str_oct:PASCAL_STRING "October"
str_nov:PASCAL_STRING "November"
str_dec:PASCAL_STRING "December"
str_space:
PASCAL_STRING " "
.proc concatenate_date_part
stax $06
ldy #$00
lda ($08),y
sta concat_len
clc
adc ($06),y
sta ($08),y
lda ($06),y
sta @compare_y
: inc concat_len
iny
lda ($06),y
sty tmp
ldy concat_len
sta ($08),y
ldy tmp
@compare_y := *+1
cpy #0 ; self-modified
bcc :-
rts
tmp: .byte 0
concat_len:
.byte 0
.endproc
.endproc
;;; ============================================================
;;; Parse date
;;; Input: A,X = Date lo/hi
;;; $0A points at {year:.word, month:.byte, day:.byte} to be filled
.proc parse_date
ptr := $0A
;; TODO: Handle ProDOS 2.5 extended dates
;; (additional year bits packed into time bytes)
stax date
;; Null date? Leave as all zeros.
ora date+1 ; null date?
bne year
ldy #3
: sta (ptr),y
dey
bpl :-
rts
;; Year
year: lda date+1 ; First, calculate year-1900
lsr a
php ; Save Carry bit
cmp #40 ; Per ProDOS Tech Note #28, 0-39 is 2000-2039
bcs :+
adc #100
: adc #<1900
ldy #0
sta (ptr),y
iny
lda #0
adc #>1900
sta (ptr),y
;; Month
month: plp ; Restore Carry bit
lda date
ror a
lsr a
lsr a
lsr a
lsr a
ldy #2
sta (ptr),y
;; Day
day: lda date
and #%00011111
ldy #3
sta (ptr),y
rts
date: .word 0
.endproc
;;; ============================================================
.proc L84D1
jsr push_pointers
bit active_window_view_by
bmi L84DC
jsr cached_icons_screen_to_window
L84DC: sub16 grafport2::cliprect::x2, grafport2::cliprect::x1, L85F8
sub16 grafport2::cliprect::y2, grafport2::cliprect::y1, L85FA
lda event_kind
cmp #MGTK::EventKind::button_down
bne L850C
asl a
bne L850E
L850C: lda #$00
L850E: sta L85F1
lda active_window_id
jsr window_lookup
stax $06
lda #$06
clc
adc L85F1
tay
lda ($06),y
pha
jsr compute_icons_bbox
ldx L85F1
sub16 iconbb_rect::x2,x, iconbb_rect::x1,x, L85F2
ldx L85F1
sub16 L85F2, L85F8,x, L85F2
bpl L8562
lda L85F8,x
sta L85F2
lda L85F9,x
sta L85F3
L8562: lsr16 L85F2
lsr16 L85F2
lda L85F2
tay
pla
tax
lda event_params+1
jsr L62BC
ldx #$00
stx L85F2
asl a
rol L85F2
asl a
rol L85F2
ldx L85F1
clc
adc iconbb_rect::x1,x
sta grafport2::cliprect::x1,x
lda L85F2
adc iconbb_rect::x1+1,x
sta grafport2::cliprect::x1+1,x
lda active_window_id
jsr compute_window_dimensions
stax L85F4
sty L85F6
lda L85F1
beq L85C3
add16_8 grafport2::cliprect::y1, L85F6, grafport2::cliprect::y2
jmp L85D6
L85C3: add16 grafport2::cliprect::x1, L85F4, grafport2::cliprect::x2
L85D6: lda active_window_id
jsr window_lookup
stax $06
ldy #$23
ldx #$07
L85E4: lda grafport2::cliprect::x1,x
sta ($06),y
dey
dex
bpl L85E4
jsr pop_pointers
rts
L85F1: .byte 0
L85F2: .byte 0
L85F3: .byte 0
L85F4: .word 0
L85F6: .byte 0
.byte 0
L85F8: .byte 0
L85F9: .byte 0
L85FA: .word 0
.endproc
;;; ============================================================
;;; A = A * 16, high bits into X
.proc a_times_16
ldx #0
stx tmp
asl a
rol tmp
asl a
rol tmp
asl a
rol tmp
asl a
rol tmp
ldx tmp
rts
tmp: .byte 0
.endproc
;;; ============================================================
;;; A = A * 64, high bits into X
.proc a_times_64
ldx #$00
stx tmp
asl a
rol tmp
asl a
rol tmp
asl a
rol tmp
asl a
rol tmp
asl a
rol tmp
asl a
rol tmp
ldx tmp
rts
tmp: .byte 0
.endproc
;;; ============================================================
;;; Look up file address. Index in A, address in A,X.
.proc icon_entry_lookup
asl a
tax
lda icon_entry_address_table,x
pha
lda icon_entry_address_table+1,x
tax
pla
rts
.endproc
;;; ============================================================
;;; Look up window. Index in A, address in A,X.
.proc window_lookup
asl a
tax
lda win_table,x
pha
lda win_table+1,x
tax
pla
rts
.endproc
;;; ============================================================
;;; Look up window address. Index in A, address in A,X.
.proc window_path_lookup
asl a
tax
lda window_path_addr_table,x
pha
lda window_path_addr_table+1,x
tax
pla
rts
.endproc
;;; ============================================================
.proc compose_file_type_string
ptr := $06
sta file_type
copy16 #type_table, ptr
ldy #num_file_types-1
: lda (ptr),y
cmp file_type
beq found
dey
bpl :-
jmp not_found
;; Found - copy string from table
found: tya
asl a
asl a
tay
copy16 #type_names_table, ptr
ldx #0
: lda (ptr),y
sta str_file_type+1,x
iny
inx
cpx #4
bne :-
stx str_file_type
rts
;; Type not found - use generic " $xx"
not_found:
copy #4, str_file_type
copy #' ', str_file_type+1
copy #'$', str_file_type+2
lda file_type
lsr a
lsr a
lsr a
lsr a
tax
copy hex_digits,x, str_file_type+3
lda file_type
and #$0F
tax
copy hex_digits,x, str_file_type+4
rts
file_type:
.byte 0
.endproc
;;; ============================================================
;;; Draw text, pascal string address in A,X
.proc draw_pascal_string
params := $6
textptr := $6
textlen := $8
stax textptr
ldy #0
lda (textptr),y
beq exit
sta textlen
inc16 textptr
MGTK_RELAY_CALL MGTK::DrawText, params
exit: rts
.endproc
;;; ============================================================
;;; Measure text, pascal string address in A,X; result in A,X
.proc measure_text1
ptr := $6
len := $8
result := $9
stax ptr
ldy #0
lda (ptr),y
sta len
inc16 ptr
MGTK_RELAY_CALL MGTK::TextWidth, ptr
ldax result
rts
.endproc
;;; ============================================================
;;; Pushes two words from $6/$8 to stack
.proc push_pointers
ptr := $6
pla ; stash return address
sta addr
pla
sta addr+1
ldx #0 ; copy 4 bytes from $8 to stack
loop: lda ptr,x
pha
inx
cpx #4
bne loop
lda addr+1 ; restore return address
pha
lda addr
pha
rts
addr: .addr 0
.endproc
;;; ============================================================
;;; Pops two words from stack to $6/$8
.proc pop_pointers
ptr := $6
pla ; stash return address
sta addr
pla
sta addr+1
ldx #3 ; copy 4 bytes from stack to $6
loop: pla
sta ptr,x
dex
cpx #$FF ; why not bpl ???
bne loop
lda addr+1 ; restore return address to stack
pha
lda addr
pha
rts
addr: .addr 0
.endproc
;;; ============================================================
port_copy:
.res .sizeof(MGTK::GrafPort)+1, 0
.proc copy_window_portbits
ptr := $6
tay
jsr push_pointers
tya
jsr window_lookup
stax ptr
ldx #0
ldy #MGTK::Winfo::port
: lda (ptr),y
sta port_copy,x
iny
inx
cpx #.sizeof(MGTK::GrafPort)
bne :-
jsr pop_pointers
rts
.endproc
.proc assign_window_portbits
ptr := $6
tay
jsr push_pointers
tya
jsr window_lookup
stax ptr
ldx #0
ldy #MGTK::Winfo::port
: lda port_copy,x
sta (ptr),y
iny
inx
cpx #.sizeof(MGTK::GrafPort)
bne :-
jsr pop_pointers
rts
.endproc
;;; ============================================================
;;; Convert icon's coordinates from window to screen
;;; (icon index in A, active window)
.proc icon_window_to_screen
entry_ptr := $6
winfo_ptr := $8
tay
jsr push_pointers
tya
jsr icon_entry_lookup
stax entry_ptr
lda active_window_id
jsr window_lookup
stax winfo_ptr
;; Screen space
ldy #MGTK::Winfo::port + MGTK::GrafPort::viewloc + 3
ldx #3
: lda (winfo_ptr),y
sta pos_screen,x
dey
dex
bpl :-
;; Window space
ldy #MGTK::Winfo::port + MGTK::GrafPort::maprect + 3
ldx #3
: lda (winfo_ptr),y
sta pos_win,x
dey
dex
bpl :-
;; iconx
ldy #IconEntry::iconx
add16in (entry_ptr),y, pos_screen, (entry_ptr),y
iny
;; icony
add16in (entry_ptr),y, pos_screen+2, (entry_ptr),y
;; iconx
ldy #IconEntry::iconx
sub16in (entry_ptr),y, pos_win, (entry_ptr),y
iny
;; icony
sub16in (entry_ptr),y, pos_win+2, (entry_ptr),y
jsr pop_pointers
rts
pos_screen: .word 0, 0
pos_win: .word 0, 0
.endproc
;;; ============================================================
;;; Convert icon's coordinates from screen to window
;;; (icon index in A, active window)
.proc icon_screen_to_window
tay
jsr push_pointers
tya
jsr icon_entry_lookup
stax $06
;; fall through
.endproc
;;; Convert icon's coordinates from screen to window
;;; (icon entry pointer in $6, active window)
.proc icon_ptr_screen_to_window
entry_ptr := $6
winfo_ptr := $8
lda active_window_id
jsr window_lookup
stax winfo_ptr
ldy #MGTK::Winfo::port + MGTK::GrafPort::viewloc + 3
ldx #3
: lda (winfo_ptr),y
sta pos_screen,x
dey
dex
bpl :-
ldy #MGTK::Winfo::port + MGTK::GrafPort::maprect + 3
ldx #3
: lda (winfo_ptr),y
sta pos_win,x
dey
dex
bpl :-
;; iconx
ldy #IconEntry::iconx
sub16in (entry_ptr),y, pos_screen, (entry_ptr),y
iny
;; icony
sub16in (entry_ptr),y, pos_screen+2, (entry_ptr),y
;; iconx
ldy #IconEntry::iconx
add16in (entry_ptr),y, pos_win, (entry_ptr),y
iny
;; icony
add16in (entry_ptr),y, pos_win+2, (entry_ptr),y
jsr pop_pointers
rts
pos_screen: .word 0, 0
pos_win: .word 0, 0
.endproc
;;; ============================================================
.proc zero_grafport5_coords
lda #0
tax
: sta grafport5::cliprect::x1,x
sta grafport5::viewloc::xcoord,x
sta grafport5::cliprect::x2,x
inx
cpx #4
bne :-
MGTK_RELAY_CALL MGTK::SetPort, grafport5
rts
.endproc
;;; ============================================================
;;; Input: A = unit_number
;;; Output: A =
;;; 0 = Disk II
;;; 1 = SmartPort, RAM Disk
;;; 2 = SmartPort, Fixed (e.g. ProFile)
;;; 3 = SmartPort, Removable (e.g. UniDisk 3.5)
;;; 4 = AppleTalk file share
;;; 5 = unknown / RAM-based driver
device_type_to_icon_address_table:
.addr floppy140_icon
.addr ramdisk_icon
.addr profile_icon
.addr floppy800_icon
.addr fileshare_icon
.addr profile_icon ; unknown
.proc get_device_type
slot_addr := $0A
sta unit_number
cmp #$3E ; Glen E. Bredon's RAM.DRV.SYSTEM
beq ram
;; Look at "ID Nibble" (mostly bogus)
and #%00001111 ; look at low nibble
bne :+ ; 0 = Disk II
rts
;; Look up driver address
: lda unit_number
jsr device_driver_address
bne unk ; RAM-based driver: just use default
lda #$00
sta slot_addr ; point at $Cn00 for firmware lookups
;; Probe firmware ID bytes
ldy #$FF ; $CnFF: $00=Disk II, $FF=13-sector, else=block
lda (slot_addr),y
bne :+
rts ; 0 = Disk II
: ldy #$07 ; SmartPort signature byte ($Cn07)
lda (slot_addr),y ; $00 = SmartPort
bne unk
ldy #$FB ; SmartPort ID Type Byte ($CnFB)
lda (slot_addr),y ; bit 0 = is RAM Card?
and #%00000001
beq :+
ram: return #device_type_ramdisk
: lda unit_number ; low nibble is high nibble of $CnFE
;; Old heuristic. Invalid on UDC, etc.
;; and #%00001111
;; cmp #DT_REMOVABLE
;; Better heuristic, but still invalid on UDC, Virtual II, etc.
;; and #%00001000 ; bit 3 = is removable?
;; So instead, just assume <=1600 blocks is a 3.5" floppy
jsr get_block_count
bcs hd
stax blocks
cmp16 blocks, #1601
bcs hd
return #device_type_removable
;; Try AppleTalk
unk: MLI_RELAY_CALL READ_BLOCK, block_params
beq hd
cmp #ERR_NETWORK_ERROR
bne hd
return #device_type_fileshare
hd: return #device_type_profile
DEFINE_READ_BLOCK_PARAMS block_params, $800, 2
unit_number := block_params::unit_num
blocks: .word 0
.endproc
;;; ============================================================
;;; Get the block count for a given unit number.
;;; Input: A=unit_number
;;; Output: C=0, blocks in A,X on success, C=1 on error
.proc get_block_count_impl
DEFINE_ON_LINE_PARAMS on_line_params,, buffer
DEFINE_GET_FILE_INFO_PARAMS get_file_info_params, path
start: sta on_line_params::unit_num
MLI_RELAY_CALL ON_LINE, on_line_params
bne error
;; Prefix the path with '/'
lda buffer
and #%00001111 ; mask off name length
clc
adc #1 ; account for '/'
sta path
copy #'/', buffer
MLI_RELAY_CALL GET_FILE_INFO, get_file_info_params
bne error
ldax get_file_info_params::aux_type
clc
rts
error: sec
rts
path: .byte 0 ; becomes length-prefixed path
buffer: .res 16, 0 ; length overwritten with '/'
.endproc
get_block_count := get_block_count_impl::start
;;; ============================================================
;;; Create Volume Icon
;;; Input: A = unit number, X = icon num, Y = index in DEVLST
;;; Output: 0 on success, ProDOS error code on failure
cvi_data_buffer := $800
DEFINE_ON_LINE_PARAMS on_line_params,, cvi_data_buffer
.proc create_volume_icon
max_icon_width = 53
max_icon_height = 15
sta unit_number
dex ; icon numbers are 1-based, and Trash is #1,
dex ; so make this 0-based
stx icon_index
sty devlst_index
and #$F0
sta on_line_params::unit_num
MLI_RELAY_CALL ON_LINE, on_line_params
beq success
error: pha ; save error
ldy devlst_index ; remove unit from list
lda #0
sta device_to_icon_map,y
dec cached_window_icon_count
dec icon_count
pla
rts
success:
lda cvi_data_buffer ; dr/slot/name_len
and #NAME_LENGTH_MASK
bne create_icon
lda cvi_data_buffer+1 ; if name len is zero, second byte is error
jmp error
create_icon:
icon_ptr := $6
icon_defn_ptr := $8
jsr push_pointers
jsr AllocateIcon
ldy devlst_index
sta device_to_icon_map,y
jsr icon_entry_lookup
stax icon_ptr
;; Copy name, with leading/trailing space
lda cvi_data_buffer
and #NAME_LENGTH_MASK
sta cvi_data_buffer
addr_call adjust_volname_case, cvi_data_buffer
ldy #IconEntry::name
copy #' ', (icon_ptr),y ; leading space
iny
ldx #0
: lda cvi_data_buffer+1,x
sta (icon_ptr),y
iny
inx
cpx cvi_data_buffer
bne :-
copy #' ', (icon_ptr),y ; trailing space
inx ; for leading/trailing space
inx
txa
ldy #IconEntry::len
sta (icon_ptr),y
;; ----------------------------------------
;; Figure out icon
lda unit_number
jsr get_device_type
asl ; * 2
tax
ldy #IconEntry::iconbits
lda device_type_to_icon_address_table,x
sta icon_defn_ptr
sta (icon_ptr),y
iny
lda device_type_to_icon_address_table+1,x
sta icon_defn_ptr+1
sta (icon_ptr),y
;; ----------------------------------------
;; Assign icon type
ldy #IconEntry::win_type
lda #0
sta (icon_ptr),y
inc devlst_index
;; Assign icon coordinates
lda icon_index
asl ; * 4 = .sizeof(MGTK::Point)
asl
tax
ldy #IconEntry::iconx
: lda desktop_icon_coords_table,x
sta (icon_ptr),y
inx
iny
cpy #IconEntry::iconbits
bne :-
;; Center it horizontally
ldy #IconDefinition::maprect + MGTK::Rect::x2
sub16in #max_icon_width, (icon_defn_ptr),y, offset
lsr16 offset ; offset = (max_width - icon_width) / 2
ldy #IconEntry::iconx
add16in (icon_ptr),y, offset, (icon_ptr),y
;; Adjust vertically
ldy #IconDefinition::maprect + MGTK::Rect::y2
sub16in #max_icon_height, (icon_defn_ptr),y, offset
ldy #IconEntry::icony
add16in (icon_ptr),y, offset, (icon_ptr),y
;; Assign icon number
ldx cached_window_icon_count
dex
ldy #IconEntry::id
lda (icon_ptr),y
sta cached_window_icon_list,x
jsr pop_pointers
return #0
unit_number: .byte 0
devlst_index: .byte 0
icon_index: .byte 0
offset: .word 0
;;; Icons are placed places in order as specified by caller
;;; in X. (Reverse DEVLST order, so most important is first.)
;;;
;;; +-------------------------+
;;; | 1 |
;;; | 2 |
;;; | 3 |
;;; | 4 |
;;; | 13 12 11 5 |
;;; | 10 9 8 7 6 Trash |
;;; +-------------------------+
trash_iconx = 506
trash_icony = 160
deltay = 29
desktop_icon_coords_table:
DEFINE_POINT 490,15 + deltay*0 ; 1
DEFINE_POINT 490,15 + deltay*1 ; 2
DEFINE_POINT 490,15 + deltay*2 ; 3
DEFINE_POINT 490,15 + deltay*3 ; 4
DEFINE_POINT 490,15 + deltay*4 ; 5
DEFINE_POINT 400,trash_icony+2 ; 6
DEFINE_POINT 310,trash_icony+2 ; 7
DEFINE_POINT 220,trash_icony+2 ; 8
DEFINE_POINT 130,trash_icony+2 ; 9
DEFINE_POINT 40,trash_icony+2 ; 10
DEFINE_POINT 400,15 + deltay*4 ; 11
DEFINE_POINT 310,15 + deltay*4 ; 12
DEFINE_POINT 220,15 + deltay*4 ; 13
;; Maximum of 13 devices:
;; 7 slots * 2 drives = 14 (size of DEVLST)
;; ... but RAM in Slot 3 Drive 2 is disconnected.
.endproc
;;; ============================================================
.proc remove_icon_from_window
ldx cached_window_icon_count
dex
: cmp cached_window_icon_list,x
beq remove
dex
bpl :-
rts
remove: lda cached_window_icon_list+1,x
sta cached_window_icon_list,x
inx
cpx cached_window_icon_count
bne remove
dec cached_window_icon_count
ldx cached_window_icon_count
lda #0
sta cached_window_icon_list,x
rts
.endproc
;;; ============================================================
;;; Search the window->dir_icon mapping table.
;;; Inputs: A = icon number
;;; Outputs: Z=1 && N=0 if found, X = index (0-7), A unchanged
.proc find_window_for_dir_icon
ldx #7
: cmp window_to_dir_icon_table,x
beq done
dex
bpl :-
done: rts
.endproc
;;; ============================================================
.proc mark_icons_not_opened
ptr := $6
L8B19: jsr push_pointers
jmp start
L8B1F: lda icon_params2
bne :+
rts
: jsr push_pointers
lda icon_params2
jsr L7345 ; ???
;; fall through
;; Find open window for the icon
start: lda icon_params2
jsr find_window_for_dir_icon
bne skip ; not found
;; If found, remove from the table
;; TODO: should this be $FF instead?
copy #0, window_to_dir_icon_table,x
;; Update the icon and redraw
skip: lda icon_params2
jsr icon_entry_lookup
stax ptr
ldy #IconEntry::win_type
lda (ptr),y
and #AS_BYTE(~icon_entry_open_mask) ; clear open_flag
sta (ptr),y
jsr redraw_selected_icons
jsr pop_pointers
rts
.endproc
mark_icons_not_opened_1 := mark_icons_not_opened::L8B19
mark_icons_not_opened_2 := mark_icons_not_opened::L8B1F
;;; ============================================================
.proc animate_window
ptr := $06
rect_table := $800
close: ldy #$80
bne :+
open: ldy #$00
: sty close_flag
sta icon_id
stx window_id
txa
;; Get window rect
jsr window_lookup
stax ptr
lda #$14
clc
adc #$23
tay
ldx #.sizeof(MGTK::GrafPort)-1
: lda (ptr),y
sta grafport2,x
dey
dex
bpl :-
;; Get icon position
lda icon_id
jsr icon_entry_lookup
stax ptr
ldy #IconEntry::iconx
lda (ptr),y ; x lo
clc
adc #7
sta rect_table
sta rect_table+4
iny
lda (ptr),y
adc #0
sta rect_table+1
sta rect_table+5
iny
lda (ptr),y
clc
adc #7
sta rect_table+2
sta rect_table+6
iny
lda (ptr),y ; y hi
adc #0
sta rect_table+3
sta rect_table+7
ldy #11 * .sizeof(MGTK::Rect) + 3
ldx #3
: lda grafport2,x
sta rect_table,y
dey
dex
bpl :-
sub16 grafport2::cliprect::x2, grafport2::cliprect::x1, L8D54
sub16 grafport2::cliprect::y2, grafport2::cliprect::y1, L8D56
add16 $0858, L8D54, $085C
add16 $085A, L8D56, $085E
lda #$00
sta L8D4E
sta L8D4F
sta L8D4D
sub16 $0858, rect_table, L8D50
sub16 $085A, $0802, L8D52
bit L8D51
bpl L8C6A
copy #$80, L8D4E
lda L8D50
eor #$FF
sta L8D50
lda L8D51
eor #$FF
sta L8D51
inc16 L8D50
L8C6A: bit L8D53
bpl L8C8C
copy #$80, L8D4F
lda L8D52
eor #$FF
sta L8D52
lda L8D53
eor #$FF
sta L8D53
inc16 L8D52
L8C8C: lsr16 L8D50
lsr16 L8D52
lsr16 L8D54
lsr16 L8D56
lda #$0A
sec
sbc L8D4D
asl a
asl a
asl a
tax
bit L8D4E
bpl :+
sub16 rect_table, L8D50, rect_table,x
jmp L8CDC
: add16 rect_table, L8D50, rect_table,x
L8CDC: bit L8D4F
bpl L8CF7
sub16 $0802, L8D52, $0802,x
jmp L8D0A
L8CF7: add16 rect_table+2, L8D52, rect_table+2,x
L8D0A: add16 rect_table,x, L8D54, rect_table+4,x ; right
add16 rect_table+2,x, L8D56, rect_table+6,x ; bottom
inc L8D4D
lda L8D4D
cmp #10
beq :+
jmp L8C8C
: bit close_flag
bmi :+
jsr animate_window_open_impl
rts
: jsr animate_window_close_impl
rts
close_flag:
.byte 0
icon_id:
.byte 0
window_id:
.byte 0
L8D4D: .byte 0
L8D4E: .byte 0
L8D4F: .byte 0
L8D50: .byte 0
L8D51: .byte 0
L8D52: .byte 0
L8D53: .byte 0
L8D54: .word 0
L8D56: .word 0
.endproc
animate_window_close := animate_window::close
animate_window_open := animate_window::open
;;; ============================================================
.proc animate_window_open_impl
rect_table := $800
lda #0
sta step
jsr reset_grafport3
MGTK_RELAY_CALL MGTK::SetPattern, checkerboard_pattern
jsr set_penmode_xor
loop: lda step
cmp #12
bcs erase
;; Compute offset into rect table
asl a
asl a
asl a
clc
adc #7
tax
;; Copy rect to draw
ldy #7
: lda rect_table,x
sta tmp_rect,y
dex
dey
bpl :-
jsr draw_anim_window_rect
;; Compute offset into rect table
erase: lda step
sec
sbc #2
bmi next
asl a ; * 8 (size of Rect)
asl a
asl a
clc
adc #$07
tax
;; Copy rect to erase
ldy #.sizeof(MGTK::Rect)-1
: lda rect_table,x
sta tmp_rect,y
dex
dey
bpl :-
jsr draw_anim_window_rect
next: inc step
lda step
cmp #$0E
bne loop
rts
step: .byte 0
.endproc
;;; ============================================================
.proc animate_window_close_impl
rect_table := $800
lda #11
sta step
jsr reset_grafport3
MGTK_RELAY_CALL MGTK::SetPattern, checkerboard_pattern
jsr set_penmode_xor
loop: lda step
bmi erase
beq erase
;; Compute offset into rect table
asl a ; * 8 (size of Rect)
asl a
asl a
clc
adc #$07
tax
;; Copy rect to draw
ldy #.sizeof(MGTK::Rect)-1
: lda rect_table,x
sta tmp_rect,y
dex
dey
bpl :-
jsr draw_anim_window_rect
;; Compute offset into rect table
erase: lda step
clc
adc #2
cmp #13
bcs next
asl a
asl a
asl a
clc
adc #$07
tax
;; Copy rect to erase
ldy #.sizeof(MGTK::Rect)-1
: lda rect_table,x
sta tmp_rect,y
dex
dey
bpl :-
jsr draw_anim_window_rect
next: dec step
lda step
cmp #AS_BYTE(-3)
bne loop
rts
step: .byte 0
.endproc
;;; ============================================================
.proc draw_anim_window_rect
MGTK_RELAY_CALL MGTK::FrameRect, tmp_rect
rts
.endproc
;;; ============================================================
;;; Dynamically load parts of Desktop2
;;; Call load_dynamic_routine or restore_dynamic_routine
;;; with A set to routine number (0-8); routine is loaded
;;; from DeskTop2 file to target address. Returns with
;;; minus flag set on failure.
;;; Routines are:
;;; 0 = disk copy - A$ 800,L$ 200
;;; 1 = format/erase disk - A$ 800,L$1400 call w/ A = 4 = format, A = 5 = erase
;;; 2 = selector actions (all) - A$9000,L$1000
;;; 3 = common file dialog - A$5000,L$2000
;;; 4 = part of copy file - A$7000,L$ 800
;;; 5 = part of delete file - A$7000,L$ 800
;;; 6 = selector add/edit - L$7000,L$ 800
;;; 7 = restore 1 - A$5000,L$2800 (restore $5000...$77FF)
;;; 8 = restore 2 - A$9000,L$1000 (restore $9000...$9FFF)
;;;
;;; Routines 2-6 need appropriate "restore routines" applied when complete.
.proc load_dynamic_routine_impl
pos_table:
.dword $00012FE0,$000160E0,$000174E0,$000184E0,$0001A4E0
.dword $0001ACE0,$0001B4E0,$0000B780,$0000F780
len_table:
.word $0200,$1400,$1000,$2000,$0800,$0800,$0800,$2800,$1000
addr_table:
.addr $0800,$0800,$9000,$5000,$7000,$7000,$7000,$5000,$9000
DEFINE_OPEN_PARAMS open_params, str_desktop2, $1C00
str_desktop2:
PASCAL_STRING "DeskTop2"
DEFINE_SET_MARK_PARAMS set_mark_params, 0
DEFINE_READ_PARAMS read_params, 0, 0
DEFINE_CLOSE_PARAMS close_params
restore_flag:
.byte 0
;; Called with routine # in A
load: pha ; entry point with bit clear
copy #0, restore_flag
beq :+ ; always
restore:
pha
copy #$80, restore_flag ; entry point with bit set
: pla
asl a ; y = A * 2 (to index into word table)
tay
asl a ; x = A * 4 (to index into dword table)
tax
lda pos_table,x
sta set_mark_params::position
lda pos_table+1,x
sta set_mark_params::position+1
lda pos_table+2,x
sta set_mark_params::position+2
copy16 len_table,y, read_params::request_count
copy16 addr_table,y, read_params::data_buffer
open: MLI_RELAY_CALL OPEN, open_params
beq :+
lda #warning_msg_insert_system_disk
ora restore_flag ; high bit set = no cancel
jsr warning_dialog_proc_num
beq open
return #$FF ; failed
: lda open_params::ref_num
sta read_params::ref_num
sta set_mark_params::ref_num
MLI_RELAY_CALL SET_MARK, set_mark_params
MLI_RELAY_CALL READ, read_params
MLI_RELAY_CALL CLOSE, close_params
rts
.endproc
load_dynamic_routine := load_dynamic_routine_impl::load
restore_dynamic_routine := load_dynamic_routine_impl::restore
;;; ============================================================
.proc show_clock
lda MACHID
and #1 ; bit 0 = clock card
bne :+
rts
: MLI_RELAY_CALL GET_TIME, 0
;; Assumes call from main loop, where grafport3 is initialized.
MGTK_RELAY_CALL MGTK::SetTextBG, desktop_aux::textbg_white
MGTK_RELAY_CALL MGTK::MoveTo, pos_clock
;; --------------------------------------------------
;; Day of Week
lda DATEHI ; Year-1900 (bits 15-9)
lsr a
php ; Save Carry bit
cmp #40 ; Per ProDOS Tech Note #18, 0-39 is 2000-2039
bcs :+
adc #100
: tay
plp ; Restore Carry bit
lda DATELO ; Month (bits 8-5)
ror
lsr
lsr
lsr
lsr
tax
lda DATELO ; Day (bits 0-4)
and #%00011111
jsr day_of_week
asl ; * 4
asl
clc
adc #<dow_strings
sta dow_str_params::addr
lda #0
adc #>dow_strings
sta dow_str_params::addr+1
MGTK_RELAY_CALL MGTK::DrawText, dow_str_params
;; --------------------------------------------------
;; Time
lda TIMEHI ; Hours
and #%00011111
pha ; Save hours
bne :+ ; 0 -> 12
clc
adc #12
: cmp #13 ; make 12-hour
bcc :+
sec
sbc #12
: ldx #0
jsr int_to_string
addr_call draw_text1, str_from_int
addr_call draw_text1, str_colon
lda TIMELO
and #%00111111
pha
cmp #10
bcs :+
addr_call draw_text1, str_zero
: pla
ldx #0
jsr int_to_string
addr_call draw_text1, str_from_int
pla ; Restore hours
cmp #12
bcs :+
addr_jump draw_text1, str_am
: addr_jump draw_text1, str_pm
.endproc
;;; Day of the Week calculation (valid 1900-03-01 to 2155-12-31)
;;; c/o http://6502.org/source/misc/dow.htm
;;; Inputs: Y = year (0=1900), X = month (1=Jan), A = day (1...31)
;;; Output: A = weekday (0=Sunday)
.proc day_of_week
tmp := $06
cpx #3 ; Year starts in March to bypass
bcs :+ ; leap year problem
dey ; If Jan or Feb, decrement year
: eor #$7F ; Invert A so carry works right
cpy #200 ; Carry will be 1 if 22nd century
adc month_offset_table-1,X ; A is now day+month offset
sta tmp
tya ; Get the year
jsr mod7 ; Do a modulo to prevent overflow
sbc tmp ; Combine with day+month
sta tmp
tya ; Get the year again
lsr ; Divide it by 4
lsr
clc ; Add it to y+m+d and fall through
adc tmp
mod7: adc #7 ; Returns (A+3) modulo 7
bcc mod7 ; for A in 0..255
rts
.endproc
;;; ============================================================
.proc set_color_mode
;; AppleColor Card - Mode 2 (Color 140x192)
sta SET80VID
lda AN3_OFF
lda AN3_ON
lda AN3_OFF
lda AN3_ON
lda AN3_OFF
;; IIgs?
jsr test_iigs
bcc iigs
;; Le Chat Mauve - COL140 mode
;; (AN3 off, HR1 off, HR2 off, HR3 off)
;; Skip on IIgs since emulators (KEGS/GSport/GSplus) crash.
sta HR2_OFF
sta HR3_OFF
bcs done
;; Apple IIgs - DHR Color
iigs: lda NEWVIDEO
and #<~(1<<5) ; Color
sta NEWVIDEO
done: rts
.endproc
.proc set_mono_mode
;; AppleColor Card - Mode 1 (Monochrome 560x192)
sta CLR80VID
lda AN3_OFF
lda AN3_ON
lda AN3_OFF
lda AN3_ON
sta SET80VID
lda AN3_OFF
;; IIgs?
jsr test_iigs
bcc iigs
;; Le Chat Mauve - BW560 mode
;; (AN3 off, HR1 off, HR2 on, HR3 on)
;; Skip on IIgs since emulators (KEGS/GSport/GSplus) crash.
sta HR2_ON
sta HR3_ON
bcs done
;; Apple IIgs - DHR B&W
iigs: lda NEWVIDEO
ora #(1<<5) ; B&W
sta NEWVIDEO
done: rts
.endproc
;;; Returns with carry clear if IIgs, set otherwise.
.proc test_iigs
lda ROMIN2
sec
jsr ID_BYTE_FE1F
lda LCBANK1
lda LCBANK1
rts
.endproc
;;; ============================================================
;;; Operations performed on selection
;;;
;;; These operate on the entire selection recursively, e.g.
;;; computing size, deleting, copying, etc., and share common
;;; logic.
.enum PromptResult
ok = 0
cancel = 1
yes = 2
no = 3
all = 4
.endenum
;;; ============================================================
jt_drop: jmp do_drop
jt_get_info: jmp do_get_info ; cmd_get_info
jt_lock: jmp do_lock ; cmd_lock
jt_unlock: jmp do_unlock ; cmd_unlock
jt_rename_icon: jmp do_rename_icon ; cmd_rename_icon
jt_eject: jmp do_eject ; cmd_eject ???
jt_copy_file: jmp do_copy_file ; cmd_copy_file
jt_delete_file: jmp do_delete_file ; cmd_delete_file
jt_run: jmp do_run ; cmd_selector_action / Run
jt_get_size: jmp do_get_size ; cmd_get_size
;;; --------------------------------------------------
.enum DeleteDialogLifecycle
open = 0
populate = 1
confirm = 2 ; confirmation before deleting
show = 3
locked = 4 ; confirm deletion of locked file
close = 5
trash = 6 ; open, but from trash path ???
.endenum
;;; --------------------------------------------------
.proc operations
do_copy_file:
copy #0, operation_flags ; copy/delete
tsx
stx stack_stash
jsr prep_callbacks_for_size_or_count
jsr do_copy_dialog_phase
jsr size_or_count_process_selected_file
jsr prep_callbacks_for_copy
do_run2:
copy #$FF, LE05B
copy #0, delete_skip_decrement_flag
jsr copy_file_for_run
jsr done_dialog_phase1
.proc finish_operation
jsr redraw_desktop_and_windows
return #0
.endproc
do_delete_file:
copy #0, operation_flags ; copy/delete
tsx
stx stack_stash
jsr prep_callbacks_for_size_or_count
lda #DeleteDialogLifecycle::open
jsr do_delete_dialog_phase
jsr size_or_count_process_selected_file
jsr done_dialog_phase2
jsr prep_callbacks_for_delete
jsr delete_process_selected_file
jsr done_dialog_phase1
jmp finish_operation
do_run:
copy #$80, run_flag
copy #%11000000, operation_flags ; get size
tsx
stx stack_stash
jsr prep_callbacks_for_size_or_count
jsr do_download_dialog_phase
jsr size_or_count_process_selected_file
jsr L99BC
jmp do_run2
;;; --------------------------------------------------
;;; Lock
do_lock:
jsr L8FDD
jmp finish_operation
do_unlock:
jsr L8FE1
jmp finish_operation
.proc get_icon_entry_win_type
asl a
tay
copy16 icon_entry_address_table,y, $06
ldy #IconEntry::win_type
lda ($06),y
rts
.endproc
;;; --------------------------------------------------
.proc do_get_size
copy #0, run_flag
copy #%11000000, operation_flags ; get size
jmp L8FEB
.endproc
.proc do_drop
lda drag_drop_param
cmp #1 ; Trash (BUG: Should use trash_icon_num)
bne :+
lda #$80
bne set ; always
: lda #$00
set: sta delete_flag
copy #0, operation_flags ; copy/delete
jmp L8FEB
.endproc
;; common for lock/unlock
L8FDD: lda #$00 ; unlock
beq :+
L8FE1: lda #$80 ; lock
: sta unlock_flag
copy #%10000000, operation_flags ; lock/unlock
L8FEB: tsx
stx stack_stash
copy #0, delete_skip_decrement_flag
jsr prep_grafport3
lda operation_flags
beq :+ ; copy/delete
jmp begin_operation
;; Copy or delete
: bit delete_flag
bpl compute_target_prefix ; copy
;; Delete - is it a volume?
lda selected_window_index
beq :+
jmp begin_operation
;; Yes - eject it!
: pla
pla
jmp JT_EJECT
;;; --------------------------------------------------
;;; For drop onto window/icon, compute target prefix.
;; Is drop on a window or an icon?
;; hi bit clear = target is an icon
;; hi bit set = target is a window; get window number
compute_target_prefix:
lda drag_drop_param
bpl check_icon_drop_type
;; Drop is on a window
and #%01111111 ; get window id
asl a
tax
copy16 window_path_addr_table,x, $08
copy16 #empty_string, $06
jsr join_paths
jmp L9076
;; Drop is on an icon.
;; Is drop on a volume or a file?
;; (lower 4 bits are containing window id)
check_icon_drop_type:
jsr get_icon_entry_win_type
and #icon_entry_winid_mask
beq drop_on_volume_icon ; 0 = desktop (so, volume icon)
;; Drop is on a file icon.
asl a
tax
copy16 window_path_addr_table,x, $08
lda drag_drop_param
jsr icon_entry_name_lookup
jsr join_paths
jmp L9076
;; Drop is on a volume icon.
;;
drop_on_volume_icon:
lda drag_drop_param
;; Prefix name with '/'
jsr icon_entry_name_lookup
ldy #1
lda #'/'
sta ($06),y
;; Copy to path_buf3
dey
lda ($06),y
sta @compare
sta path_buf3,y
: iny
lda ($06),y
sta path_buf3,y
@compare := *+1
cpy #0 ; self-modified
bne :-
;; Restore ' ' to name prefix
ldy #1
lda #' '
sta ($06),y
L9076: ldy #$FF
: iny
copy path_buf3,y, path_buf4,y
cpy path_buf3
bne :-
lda path_buf4
beq begin_operation
dec path_buf4
;; fall through
;;; --------------------------------------------------
;;; Start the actual operation
.proc begin_operation
copy #0, L97E4
jsr prep_callbacks_for_size_or_count
bit operation_flags
bvs @size
bmi @lock
bit delete_flag
bmi @trash
;; Copy or Move - compare src/dst paths (etc)
jsr get_window_path_ptr
jsr check_move_or_copy
sta move_flag
jsr do_copy_dialog_phase
jmp iterate_selection
@trash: lda #DeleteDialogLifecycle::trash
jsr do_delete_dialog_phase
jmp iterate_selection
@lock: jsr do_lock_dialog_phase
jmp iterate_selection
@size: jsr do_get_size_dialog_phase
jmp iterate_selection
;;; Perform operation
L90BA: bit operation_flags
bvs @size
bmi @lock
bit delete_flag
bmi @trash
jsr prep_callbacks_for_copy
jmp iterate_selection
@trash: jsr prep_callbacks_for_delete
jmp iterate_selection
@lock: jsr prep_callbacks_for_lock
jmp iterate_selection
@size: jsr get_size_rts2 ; no-op ???
jmp iterate_selection
iterate_selection:
lda selected_icon_count
bne :+
jmp finish
: ldx #0
stx icon_count
loop: jsr get_window_path_ptr
ldx icon_count
lda selected_icon_list,x
cmp #1 ; icon #1 is always Trash (BUG: should use trash_icon_num)
beq next_icon
jsr icon_entry_name_lookup
jsr join_paths
;; Shrink name to remove trailing ' '
lda path_buf3
beq :+
dec path_buf3
:
lda L97E4
beq L913D
bit operation_flags
bmi @lock_or_size
bit delete_flag
bmi :+
jsr copy_process_selected_file
jmp next_icon
: jsr delete_process_selected_file
jmp next_icon
@lock_or_size:
bvs @size ; size?
jsr lock_process_selected_file
jmp next_icon
@size: jsr size_or_count_process_selected_file
jmp next_icon
L913D: jsr size_or_count_process_selected_file
next_icon:
inc icon_count
ldx icon_count
cpx selected_icon_count
bne loop
lda L97E4
bne finish
inc L97E4
bit operation_flags
bmi @lock_or_size
bit delete_flag
bpl not_trash
@lock_or_size:
jsr done_dialog_phase2
bit operation_flags
bvs finish
not_trash:
jmp L90BA
finish: jsr done_dialog_phase1
return #0
icon_count:
.byte 0
.endproc
empty_string:
.byte 0
.endproc ; operations
do_delete_file := operations::do_delete_file
do_run := operations::do_run
do_copy_file := operations::do_copy_file
do_lock := operations::do_lock
do_unlock := operations::do_unlock
do_get_size := operations::do_get_size
do_drop := operations::do_drop
;;; ============================================================
done_dialog_phase0:
dialog_phase0_callback := *+1
jmp dummy0000
done_dialog_phase1:
dialog_phase1_callback := *+1
jmp dummy0000
done_dialog_phase2:
dialog_phase2_callback := *+1
jmp dummy0000
done_dialog_phase3:
dialog_phase3_callback := *+1
jmp dummy0000
stack_stash:
.byte 0
;; $80 = lock/unlock
;; $C0 = get size/run (easily probed with oVerflow flag)
;; $00 = copy/delete
operation_flags:
.byte 0
;; high bit set = delete, clear = copy
delete_flag:
.byte 0
;; high bit set = move, clear = copy
move_flag:
.byte 0
;; high bit set = unlock, clear = lock
unlock_flag:
.byte 0
;; high bit set = from Selector > Run command (download???)
;; high bit clear = Get Size
run_flag:
.byte 0
all_flag:
.byte 0
;;; ============================================================
;;; For icon index in A, put pointer to name in $6
.proc icon_entry_name_lookup
asl a
tay
add16 icon_entry_address_table,y, #IconEntry::len, $06
rts
.endproc
;;; ============================================================
.proc join_paths
str1 := $8
str2 := $6
buf := path_buf3
ldx #0
ldy #0
lda (str1),y
beq do_str2
;; Copy $8 (str1)
sta @len
: iny
inx
lda (str1),y
sta buf,x
@len := *+1
cpy #0 ; self-modified
bne :-
do_str2:
;; Add path separator
inx
lda #'/'
sta buf,x
;; Append $6 (str2)
ldy #0
lda (str2),y
beq done
sta @len
iny
: iny
inx
lda (str2),y
sta buf,x
@len := *+1
cpy #0 ; self-modified
bne :-
done: stx buf
rts
.endproc
;;; ============================================================
.proc prep_grafport3
yax_call JT_MGTK_RELAY, MGTK::InitPort, grafport3
yax_call JT_MGTK_RELAY, MGTK::SetPort, grafport3
rts
.endproc
.proc redraw_desktop_and_windows
jsr JT_REDRAW_ALL
yax_call JT_ITK_RELAY, IconTK::REDRAW_ICONS, 0
rts
.endproc
.proc get_window_path_ptr
ptr := $08
copy16 #nullptr, ptr ; ptr to empty string???
lda selected_window_index
beq done
asl a
tax
copy16 window_path_addr_table,x, ptr
lda #0
done: rts
nullptr:
.addr 0
.endproc
;;; ============================================================
.proc do_eject
lda selected_icon_count
bne :+
rts
: ldx selected_icon_count
stx $800
dex
: lda selected_icon_list,x
sta $0801,x
dex
bpl :-
jsr JT_CLEAR_SELECTION
ldx #0
stx index
loop: ldx index
lda $0801,x
cmp #$01
beq :+
jsr smartport_eject
: inc index
ldx index
cpx $800
bne loop
rts
index: .byte 0
.endproc
;;; ============================================================
.proc smartport_eject
ptr := $6
sta @compare
ldy #0
: lda device_to_icon_map,y
@compare := *+1
cmp #0
beq found
cpy DEVCNT
beq exit
iny
bne :-
exit: rts
found: lda DEVLST,y ;
sta unit_number
;; Compute SmartPort dispatch address
smartport_addr := $0A
jsr find_smartport_dispatch_address
bne exit ; not SP
stx control_unit_number
;; Execute SmartPort call
jsr smartport_call
.byte $04 ; $04 = CONTROL
.addr control_params
rts
smartport_call:
jmp (smartport_addr)
.proc control_params
param_count: .byte 3
unit_number: .byte 0
control_list: .addr list
control_code: .byte 4 ; Eject disk
.endproc
control_unit_number := control_params::unit_number
list: .word 0 ; 0 items in list
unit_number:
.byte 0
.endproc
;;; ============================================================
;;; "Get Info" dialog state and logic
;;; ============================================================
DEFINE_GET_FILE_INFO_PARAMS get_file_info_params5, $220
DEFINE_READ_BLOCK_PARAMS block_params, $800, $A
.proc get_info_dialog_params
L92E3: .byte 0
L92E4: .word 0
L92E6: .byte 0
.endproc
;;; ============================================================
;;; Look up device driver address.
;;; Input: A = unit number
;;; Output: $0A/$0B ptr to driver; Z set if $CnXX
.proc device_driver_address
slot_addr := $0A
and #%11110000 ; mask off drive/slot
clc
ror ; 0DSSS000
ror ; 00DSSS00
ror ; 000DSSS0
tax ; = slot * 2 + (drive == 2 ? 0x10 + 0x00)
lda DEVADR,x
sta slot_addr
lda DEVADR+1,x
sta slot_addr+1
and #$F0 ; is it $Cn ?
cmp #$C0 ; leave Z flag set if so
rts
.endproc
;;; ============================================================
;;; Look up SmartPort dispatch address.
;;; Input: A = unit number
;;; Output: Z=1 if SP, $0A/$0B dispatch address, X = SP unit num
;;; Z=0 if not SP
.proc find_smartport_dispatch_address
sp_addr := $0A
sta unit_number ; DSSSnnnn
;; Get device driver address
jsr device_driver_address
bne exit ; RAM-based driver
;; Find actual address
copy #0, sp_addr ; point at $Cn00 for firmware lookups
ldy #$07 ; SmartPort signature byte ($Cn07)
lda (sp_addr),y ; $00 = SmartPort
bne exit
ldy #$FB ; SmartPort ID Type Byte ($CnFB)
lda (sp_addr),y
and #$7F ; bit 7 = is Extended
bne exit
;; Locate SmartPort entry point: $Cn00 + ($CnFF) + 3
ldy #$FF
lda (sp_addr),y
clc
adc #3
sta sp_addr
;; Figure out SmartPort control unit number in X
ldx #1 ; start with unit 1
bit unit_number ; high bit is D
bpl :+
inx ; X = 1 or 2 (for Drive 1 or 2)
: lda unit_number
and #%01110000 ; 0SSSnnnn
lsr
lsr
lsr
lsr
sta mapped_slot ; 00000SSS
lda sp_addr+1 ; $Cn
and #%00001111 ; $0n
cmp mapped_slot ; equal = not remapped
beq :+
inx ; now X = 3 or 4
inx
: lda #0 ; exit with Z set on success
exit: rts
unit_number:
.byte 0
mapped_slot: ; from unit_number, not driver
.byte 0
.endproc
;;; ============================================================
;;; Get Info
.proc do_get_info
path_buf := $220
ptr := $6
lda selected_icon_count
bne :+
rts
: copy #0, get_info_dialog_params::L92E6
jsr prep_grafport3
loop: ldx get_info_dialog_params::L92E6
cpx selected_icon_count
bne :+
jmp done
: lda selected_window_index
beq vol_icon
;; File icon
asl a
tax
copy16 window_path_addr_table,x, $08
ldx get_info_dialog_params::L92E6
lda selected_icon_list,x
jsr icon_entry_name_lookup
jsr join_paths
ldy #0 ; Copy name to path_buf
: lda path_buf3,y
sta path_buf,y
iny
cpy path_buf
bne :-
dec path_buf
jmp common
;; Volume icon
vol_icon:
ldx get_info_dialog_params::L92E6
lda selected_icon_list,x
cmp #1 ; trash icon?
bne :+
jmp next
: jsr icon_entry_name_lookup
ldy #0
: lda (ptr),y
sta path_buf,y
iny
cpy path_buf
bne :-
dec path_buf
lda #'/'
sta path_buf+1
;; Try to get file info
common: MLI_RELAY_CALL GET_FILE_INFO, get_file_info_params5
beq :+
jsr show_error_alert
beq common
:
lda selected_window_index
beq vol_icon2
;; File icon
copy #$80, get_info_dialog_params::L92E3
lda get_info_dialog_params::L92E6
clc
adc #1
cmp selected_icon_count
beq :+
inc get_info_dialog_params::L92E3
inc get_info_dialog_params::L92E3
: jsr run_get_info_dialog_proc
jmp common2
vol_icon2:
copy #$81, get_info_dialog_params::L92E3
lda get_info_dialog_params::L92E6
clc
adc #1
cmp selected_icon_count
beq :+
inc get_info_dialog_params::L92E3
inc get_info_dialog_params::L92E3
: jsr run_get_info_dialog_proc
copy #0, write_protected_flag
ldx get_info_dialog_params::L92E6
lda selected_icon_list,x
;; Map icon to unit number
ldy #15
: cmp device_to_icon_map,y
beq :+
dey
bpl :-
jmp common2
: lda DEVLST,y
sta block_params::unit_num
MLI_RELAY_CALL READ_BLOCK, block_params
bne common2
MLI_RELAY_CALL WRITE_BLOCK, block_params
cmp #ERR_WRITE_PROTECTED
bne common2
copy #$80, write_protected_flag
common2:
ldx get_info_dialog_params::L92E6
lda selected_icon_list,x
jsr icon_entry_name_lookup
copy #1, get_info_dialog_params::L92E3
copy16 ptr, get_info_dialog_params::L92E4
jsr run_get_info_dialog_proc
copy #2, get_info_dialog_params::L92E3
lda selected_window_index
bne is_file
bit write_protected_flag
bmi is_protected
copy #0, get_info_dialog_params::L92E4
beq L9428 ; always
is_protected:
copy #1, get_info_dialog_params::L92E4
bne L9428 ; always
is_file:
lda get_file_info_params5::access
and #ACCESS_DEFAULT
cmp #ACCESS_DEFAULT
beq L9423
copy #1, get_info_dialog_params::L92E4
bne L9428 ; always
L9423: copy #0, get_info_dialog_params::L92E4
L9428: jsr run_get_info_dialog_proc
jmp L942F
write_protected_flag:
.byte 0
L942F: copy #3, get_info_dialog_params::L92E3
;; Compose " 12345 Blocks" or " 12345 / 67890 Blocks" string
buf := $220
copy #0, buf
lda selected_window_index ; volume?
bne do_suffix ; nope
;; ProDOS TRM 4.4.5:
;; "When file information about a volume directory is requested, the
;; total number of blocks on the volume is returned in the aux_type
;; field and the total blocks for all files is returned in blocks_used.
lda get_file_info_params5::aux_type
sec
sbc get_file_info_params5::blocks_used
pha
lda get_file_info_params5::aux_type+1
sbc get_file_info_params5::blocks_used+1
tax
pla
jsr JT_SIZE_STRING
;; text_buffer2 now has " 12345 Blocks" (free space)
;; Copy number and leading/trailing space into buf
ldx buf
ldy #0
: inx
lda text_buffer2::data,y
cmp #'B' ; stop at 'B' in "Blocks"
beq slash
sta buf,x
iny
cpy text_buffer2::length
bne :-
;; Append '/' to buf
slash: lda #'/'
sta buf,x
stx buf
do_suffix:
lda selected_window_index ; volume?
bne :+ ; nope
;; Load up the total volume size...
ldax get_file_info_params5::aux_type
jmp compute_suffix
;; Load up the file size
: ldax get_file_info_params5::blocks_used
;; Compute " 12345 Blocks" (either result or suffix)
compute_suffix:
jsr JT_SIZE_STRING
;; Append latest to buffer
ldx buf
ldy #1
: inx
lda text_buffer2::data-1,y
sta buf,x
cpy text_buffer2::length
beq :+
iny
bne :-
: stx buf
;; TODO: Compose directly into path_buf4.
ldx buf
: lda buf,x
sta path_buf4,x
dex
bpl :-
copy16 #path_buf4, get_info_dialog_params::L92E4
jsr run_get_info_dialog_proc
copy #4, get_info_dialog_params::L92E3
copy16 get_file_info_params5::create_date, date
jsr JT_DATE_STRING
copy16 #text_buffer2::length, get_info_dialog_params::L92E4
jsr run_get_info_dialog_proc
copy #5, get_info_dialog_params::L92E3
copy16 get_file_info_params5::mod_date, date
jsr JT_DATE_STRING
copy16 #text_buffer2::length, get_info_dialog_params::L92E4
jsr run_get_info_dialog_proc
copy #6, get_info_dialog_params::L92E3
lda selected_window_index
bne L9519
COPY_STRING str_vol, str_file_type
bmi L951F ; always
L9519: lda get_file_info_params5::file_type
jsr JT_FILE_TYPE_STRING
L951F: copy16 #str_file_type, get_info_dialog_params::L92E4
jsr run_get_info_dialog_proc
bne done
next: inc get_info_dialog_params::L92E6
jmp loop
done: copy #0, path_buf4
rts
str_vol:
PASCAL_STRING " VOL"
.proc run_get_info_dialog_proc
yax_call invoke_dialog_proc, index_get_info_dialog, get_info_dialog_params
rts
.endproc
.endproc
;;; ============================================================
.proc do_rename_icon_impl
src_path_buf := $220
DEFINE_RENAME_PARAMS rename_params, src_path_buf, dst_path_buf
rename_dialog_params:
.byte 0
.addr $1F00
start:
copy #0, L9706
L9576: lda L9706
cmp selected_icon_count
bne L9581
return #0
L9581: ldx L9706
lda selected_icon_list,x
cmp #$01
bne L9591
inc L9706
jmp L9576
L9591: lda selected_window_index
beq L95C2
asl a
tax
copy16 window_path_addr_table,x, $08
ldx L9706
lda selected_icon_list,x
jsr icon_entry_name_lookup
jsr join_paths
ldy #$00
L95B0: lda path_buf3,y
sta src_path_buf,y
iny
cpy src_path_buf
bne L95B0
dec src_path_buf
jmp L95E0
L95C2: ldx L9706
lda selected_icon_list,x
jsr icon_entry_name_lookup
ldy #$00
L95CD: lda ($06),y
sta src_path_buf,y
iny
cpy src_path_buf
bne L95CD
dec src_path_buf
lda #'/'
sta src_path_buf+1
L95E0: ldx L9706
lda selected_icon_list,x
jsr icon_entry_name_lookup
ldy #$00
lda ($06),y
tay
L95EE: lda ($06),y
sta $1F12,y
dey
bpl L95EE
ldy #$00
lda ($06),y
tay
dey
sec
sbc #$02
sta $1F00
L9602: lda ($06),y
sta $1F00-1,y
dey
cpy #$01
bne L9602
lda #$00
jsr L96F8
L9611: lda #$80
jsr L96F8
beq L962F
L9618: ldx L9706
lda selected_icon_list,x
jsr icon_entry_name_lookup
ldy $1F12
L9624: lda $1F12,y
sta ($06),y
dey
bpl L9624
return #$FF
L962F: sty $08
sty L9707
stx $08+1
stx L9708
lda selected_window_index
beq L964D
asl a
tax
copy16 window_path_addr_table,x, $06
jmp L9655
L964D: copy16 #L9705, $06
L9655: ldy #$00
lda ($06),y
tay
L965A: lda ($06),y
sta dst_path_buf,y
dey
bpl L965A
inc dst_path_buf
ldx dst_path_buf
lda #'/'
sta dst_path_buf,x
ldy #$00
lda ($08),y
sta L9709
L9674: inx
iny
lda ($08),y
sta dst_path_buf,x
cpy L9709
bne L9674
stx dst_path_buf
MLI_RELAY_CALL RENAME, rename_params
beq L969E
jsr JT_SHOW_ALERT0
bne L9696
jmp L9611
L9696: lda #$40
jsr L96F8
jmp L9618
L969E: lda #$40
jsr L96F8
ldx L9706
lda selected_icon_list,x
sta icon_param2
yax_call JT_ITK_RELAY, IconTK::ERASE_ICON, icon_param2
copy16 L9707, $08
ldx L9706
lda selected_icon_list,x
jsr icon_entry_name_lookup
ldy #$00
lda ($08),y
clc
adc #$02
sta ($06),y
lda ($08),y
tay
inc16 $06
L96DA: lda ($08),y
sta ($06),y
dey
bne L96DA
dec $06
lda $06
cmp #$FF
bne L96EB
dec $06+1
L96EB: lda ($06),y
tay
lda #' '
sta ($06),y
inc L9706
jmp L9576
L96F8: sta rename_dialog_params
yax_call invoke_dialog_proc, index_rename_dialog, rename_dialog_params
rts
L9705: .byte $00
L9706: .byte $00
L9707: .byte $00
L9708: .byte $00
L9709: .byte $00
.endproc
do_rename_icon := do_rename_icon_impl::start
;;; ============================================================
src_path_buf := $220
DEFINE_OPEN_PARAMS open_src_dir_params, src_path_buf, $800
DEFINE_READ_PARAMS read_src_dir_header_params, pointers_buf, 4 ; dir header: skip block pointers
pointers_buf: .res 4, 0
DEFINE_CLOSE_PARAMS close_src_dir_params
DEFINE_READ_PARAMS read_src_dir_entry_params, file_entry_buf, .sizeof(FileEntry)
DEFINE_READ_PARAMS read_src_dir_skip5_params, skip5_buf, 5 ; ???
skip5_buf: .res 5, 0
buf_size = $AC0
DEFINE_CLOSE_PARAMS close_src_params
DEFINE_CLOSE_PARAMS close_dst_params
DEFINE_DESTROY_PARAMS destroy_params, src_path_buf
DEFINE_OPEN_PARAMS open_src_params, src_path_buf, $0D00
DEFINE_OPEN_PARAMS open_dst_params, dst_path_buf, $1100
DEFINE_READ_PARAMS read_src_params, $1500, buf_size
DEFINE_WRITE_PARAMS write_dst_params, $1500, buf_size
DEFINE_CREATE_PARAMS create_params3, dst_path_buf, ACCESS_DEFAULT
DEFINE_CREATE_PARAMS create_params2, dst_path_buf
.byte 0,0
DEFINE_GET_FILE_INFO_PARAMS src_file_info_params, src_path_buf
DEFINE_GET_FILE_INFO_PARAMS dst_file_info_params, dst_path_buf
DEFINE_SET_EOF_PARAMS set_eof_params, 0
DEFINE_SET_MARK_PARAMS mark_src_params, 0
DEFINE_SET_MARK_PARAMS mark_dst_params, 0
DEFINE_ON_LINE_PARAMS on_line_params2,, $800
;;; ============================================================
file_entry_buf: .res .sizeof(FileEntry), 0
;; overlayed indirect jump table
op_jt_addrs_size := 6
op_jt_addrs:
op_jt_addr1: .addr copy_process_directory_entry ; defaults are for copy
op_jt_addr2: .addr copy_pop_directory
op_jt_addr3: .addr do_nothing
do_nothing: rts
L97E4: .byte $00
.proc push_entry_count
ldx entry_count_stack_index
lda entries_to_skip
sta entry_count_stack,x
inx
stx entry_count_stack_index
rts
.endproc
.proc pop_entry_count
ldx entry_count_stack_index
dex
lda entry_count_stack,x
sta entries_to_skip
stx entry_count_stack_index
rts
.endproc
.proc open_src_dir
lda #0
sta entries_read
sta entries_read_this_block
@retry: MLI_RELAY_CALL OPEN, open_src_dir_params
beq :+
ldx #$80
jsr JT_SHOW_ALERT
beq @retry
jmp close_files_cancel_dialog
: lda open_src_dir_params::ref_num
sta op_ref_num
sta read_src_dir_header_params::ref_num
@retry2:MLI_RELAY_CALL READ, read_src_dir_header_params
beq :+
ldx #$80
jsr JT_SHOW_ALERT
beq @retry2
jmp close_files_cancel_dialog
: jmp read_file_entry
.endproc
.proc close_src_dir
lda op_ref_num
sta close_src_dir_params::ref_num
@retry: MLI_RELAY_CALL CLOSE, close_src_dir_params
beq :+
ldx #$80
jsr JT_SHOW_ALERT
beq @retry
jmp close_files_cancel_dialog
: rts
.endproc
.proc read_file_entry
inc entries_read
lda op_ref_num
sta read_src_dir_entry_params::ref_num
@retry: MLI_RELAY_CALL READ, read_src_dir_entry_params
beq :+
cmp #ERR_END_OF_FILE
beq eof
ldx #$80
jsr JT_SHOW_ALERT
beq @retry
jmp close_files_cancel_dialog
: inc entries_read_this_block
lda entries_read_this_block
cmp num_entries_per_block
bcc :+
copy #0, entries_read_this_block
copy op_ref_num, read_src_dir_skip5_params::ref_num
MLI_RELAY_CALL READ, read_src_dir_skip5_params
: return #0
eof: return #$FF
.endproc
;;; ============================================================
.proc prep_to_open_dir
lda entries_read
sta entries_to_skip
jsr close_src_dir
jsr push_entry_count
jsr append_to_src_path
jmp open_src_dir
.endproc
;;; Given this tree with b,c,e selected:
;;; b
;;; c/
;;; d/
;;; e
;;; f
;;; Visit call sequence:
;;; * op_jt1 c
;;; * op_jt1 c/d
;;; * op_jt3 c/d
;;; * op_jt2 c
;;;
;;; Visiting individual files is done via direct calls, not the
;;; overlayed jump table. Order is:
;;;
;;; * call: b
;;; * op_jt1 on c
;;; * call: c/d
;;; * op_jt1 on c/d
;;; * call: c/d/e
;;; * op_jt3 on c/d
;;; * op_jt2 on c
;;; * call: c
;;; * call: f
;;; (3x final calls ???)
.proc finish_dir
jsr close_src_dir
jsr op_jt3 ; third - called when exiting dir
jsr remove_src_path_segment
jsr pop_entry_count
jsr open_src_dir
jsr sub
jmp op_jt2 ; second - called when exited dir
sub: lda entries_read
cmp entries_to_skip
beq done
jsr read_file_entry
jmp sub
done: rts
.endproc
.proc process_dir
copy #0, process_depth
jsr open_src_dir
loop: jsr read_file_entry
bne end_dir
addr_call adjust_fileentry_case, file_entry_buf
lda file_entry_buf + FileEntry::storage_type_name_length
beq loop
and #NAME_LENGTH_MASK
sta file_entry_buf
copy #0, cancel_descent_flag
jsr op_jt1 ; first - called when visiting dir
lda cancel_descent_flag
bne loop
lda file_entry_buf + FileEntry::file_type
cmp #FT_DIRECTORY
bne loop
jsr prep_to_open_dir
inc process_depth
jmp loop
end_dir:
lda process_depth
beq L9920
jsr finish_dir
dec process_depth
jmp loop
L9920: jmp close_src_dir
.endproc
cancel_descent_flag: .byte 0
op_jt1: jmp (op_jt_addr1)
op_jt2: jmp (op_jt_addr2)
op_jt3: jmp (op_jt_addr3)
;;; ============================================================
;;; "Copy" (including Drag/Drop/Move) files state and logic
;;; ============================================================
;;; copy_process_selected_file
;;; - called for each file in selection; calls process_dir to recurse
;;; copy_process_directory_entry
;;; - c/o process_dir for each file in dir; skips if dir, copies otherwise
;;; copy_pop_directory
;;; - c/o process_dir when exiting dir; pops path segment
;;; maybe_finish_file_move
;;; - c/o process_dir after exiting; deletes dir if moving
;;; Overlays for copy operation (op_jt_addrs)
callbacks_for_copy:
.addr copy_process_directory_entry
.addr copy_pop_directory
.addr maybe_finish_file_move
.enum CopyDialogLifecycle
open = 0
populate = 1
show = 2
exists = 3 ; show "file exists" prompt
too_large = 4 ; show "too large" prompt
close = 5
.endenum
.proc copy_dialog_params
phase: .byte 0
count: .addr 0
.addr src_path_buf
.addr dst_path_buf
.endproc
.proc do_copy_dialog_phase
copy #CopyDialogLifecycle::open, copy_dialog_params::phase
copy16 #copy_dialog_phase0_callback1, dialog_phase0_callback
copy16 #copy_dialog_phase1_callback1, dialog_phase1_callback
jmp run_copy_dialog_proc
.endproc
.proc copy_dialog_phase0_callback1
stax copy_dialog_params::count
copy #CopyDialogLifecycle::populate, copy_dialog_params::phase
jmp run_copy_dialog_proc
.endproc
.proc prep_callbacks_for_copy
ldy #op_jt_addrs_size-1
: copy callbacks_for_copy,y, op_jt_addrs,y
dey
bpl :-
lda #0
sta LA425
sta all_flag
rts
.endproc
.proc copy_dialog_phase1_callback1
copy #CopyDialogLifecycle::close, copy_dialog_params::phase
jmp run_copy_dialog_proc
.endproc
.proc do_download_dialog_phase
copy #CopyDialogLifecycle::open, copy_dialog_params::phase
copy16 #copy_dialog_phase0_callback2, dialog_phase0_callback
copy16 #copy_dialog_phase1_callback2, dialog_phase1_callback
yax_call invoke_dialog_proc, index_download_dialog, copy_dialog_params
rts
.endproc
.proc copy_dialog_phase0_callback2
stax copy_dialog_params::count
copy #CopyDialogLifecycle::populate, copy_dialog_params::phase
yax_call invoke_dialog_proc, index_download_dialog, copy_dialog_params
rts
.endproc
.proc L99BC
copy #$80, all_flag
ldy #op_jt_addrs_size-1
: copy callbacks_for_copy,y, op_jt_addrs,y
dey
bpl :-
copy #0, LA425
copy16 #copy_dialog_phase3_callback, dialog_phase3_callback
rts
.endproc
.proc copy_dialog_phase1_callback2
copy #CopyDialogLifecycle::exists, copy_dialog_params::phase
yax_call invoke_dialog_proc, index_download_dialog, copy_dialog_params
rts
.endproc
.proc copy_dialog_phase3_callback
copy #CopyDialogLifecycle::too_large, copy_dialog_params::phase
yax_call invoke_dialog_proc, index_download_dialog, copy_dialog_params
cmp #PromptResult::yes
bne cancel
rts
.endproc
cancel: jmp close_files_cancel_dialog
;;; ============================================================
;;; Handle copying of a selected file.
;;; Calls into the recursion logic of |process_dir| as necessary.
.proc copy_process_selected_file
copy #$80, LE05B
copy #0, delete_skip_decrement_flag
beq :+ ; always
for_run:
lda #$FF
: sta is_run_flag
copy #CopyDialogLifecycle::show, copy_dialog_params::phase
jsr copy_paths_to_src_and_dst_paths
bit operation_flags
bvc @not_run
jsr check_vol_blocks_free ; dst is a volume path (RAM Card)
@not_run:
bit LE05B
bpl get_src_info ; never taken ???
bvs L9A50
lda is_run_flag
bne :+
lda selected_window_index ; dragging from window?
bne :+
jmp copy_dir
: ldx dst_path_buf
ldy src_path_slash_index
dey
: iny
inx
lda src_path_buf,y
sta dst_path_buf,x
cpy src_path_buf
bne :-
stx dst_path_buf
jmp get_src_info
;; Append filename to dst_path_buf
L9A50: ldx dst_path_buf
lda #'/'
sta dst_path_buf+1,x
inc dst_path_buf
ldy #0
ldx dst_path_buf
: iny
inx
lda filename_buf,y
sta dst_path_buf,x
cpy filename_buf
bne :-
stx dst_path_buf
get_src_info:
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
: lda src_file_info_params::storage_type
cmp #ST_VOLUME_DIRECTORY
beq is_dir
cmp #ST_LINKED_DIRECTORY
beq is_dir
lda #$00
beq store
is_dir: jsr decrement_op_file_count
lda #$FF
store: sta is_dir_flag
jsr dec_file_count_and_run_copy_dialog_proc
;; Copy access, file_type, aux_type, storage_type
ldy #7
: lda src_file_info_params,y
sta create_params2,y
dey
cpy #2
bne :-
copy #ACCESS_DEFAULT, create_params2::access
lda LE05B
beq create_ok ; never taken ???
jsr check_space_and_show_prompt
bcs done
;; Copy create_time/create_date
ldy #17
ldx #11
: lda src_file_info_params,y
sta create_params2,x
dex
dey
cpy #13
bne :-
;; If a volume, need to create a subdir instead
lda create_params2::storage_type
cmp #ST_VOLUME_DIRECTORY
bne do_create
lda #ST_LINKED_DIRECTORY
sta create_params2::storage_type
do_create:
MLI_RELAY_CALL CREATE, create_params2
beq create_ok
cmp #ERR_DUPLICATE_FILENAME
bne err
bit all_flag
bmi do_it
copy #CopyDialogLifecycle::exists, copy_dialog_params::phase
jsr run_copy_dialog_proc
pha
copy #CopyDialogLifecycle::show, copy_dialog_params::phase
pla
cmp #PromptResult::yes
beq do_it
cmp #PromptResult::no
beq done
cmp #PromptResult::all
bne cancel
copy #$80, all_flag
do_it: jsr apply_file_info_and_size
jmp create_ok
;; PromptResult::cancel
cancel: jmp close_files_cancel_dialog
err: jsr show_error_alert
jmp do_create ; retry
create_ok:
lda is_dir_flag
beq copy_file
copy_dir: ; also used when dragging a volume icon
jsr process_dir
jmp maybe_finish_file_move
done: rts
copy_file:
jsr do_file_copy
jmp maybe_finish_file_move
is_dir_flag:
.byte 0
is_run_flag:
.byte 0
.endproc
copy_file_for_run := copy_process_selected_file::for_run
;;; ============================================================
src_path_slash_index:
.byte 0
;;; ============================================================
copy_pop_directory:
jmp remove_dst_path_segment
;;; ============================================================
;;; If moving, delete src file/directory.
.proc maybe_finish_file_move
;; Copy or move?
bit move_flag
bpl done
;; Was a move - delete file
@retry: MLI_RELAY_CALL DESTROY, destroy_params
beq done
cmp #ERR_ACCESS_ERROR
bne :+
jsr unlock_src_file
beq @retry
bne done ; silently leave file
: jsr show_error_alert
jmp @retry
done: rts
.endproc
;;; ============================================================
;;; Called by |process_dir| to process a single file
.proc copy_process_directory_entry
jsr check_escape_key_down
beq :+
jmp close_files_cancel_dialog
: lda file_entry_buf + FileEntry::file_type
cmp #FT_DIRECTORY
bne regular_file
;; Directory
jsr append_to_src_path
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
: jsr append_to_dst_path
jsr dec_file_count_and_run_copy_dialog_proc
jsr decrement_op_file_count
jsr try_create_dst
bcs :+
jsr remove_src_path_segment
jmp done
: jsr remove_dst_path_segment
jsr remove_src_path_segment
copy #$FF, cancel_descent_flag
jmp done
;; File
regular_file:
jsr append_to_dst_path
jsr append_to_src_path
jsr dec_file_count_and_run_copy_dialog_proc
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
: jsr check_space_and_show_prompt
bcc :+
jmp close_files_cancel_dialog
: jsr remove_src_path_segment
jsr try_create_dst
bcs :+
jsr append_to_src_path
jsr do_file_copy
jsr maybe_finish_file_move
jsr remove_src_path_segment
: jsr remove_dst_path_segment
done: rts
.endproc
;;; ============================================================
.proc run_copy_dialog_proc
yax_call invoke_dialog_proc, index_copy_dialog, copy_dialog_params
rts
.endproc
;;; ============================================================
.proc check_vol_blocks_free
@retry: MLI_RELAY_CALL GET_FILE_INFO, dst_file_info_params
beq :+
jsr show_error_alert_dst
jmp @retry
: sub16 dst_file_info_params::aux_type, dst_file_info_params::blocks_used, blocks_free
cmp16 blocks_free, op_block_count
bcs :+
jmp done_dialog_phase3
: rts
blocks_free:
.word 0
.endproc
;;; ============================================================
.proc check_space_and_show_prompt
jsr check_space
bcc done
copy #CopyDialogLifecycle::too_large, copy_dialog_params::phase
jsr run_copy_dialog_proc
beq :+
jmp close_files_cancel_dialog
: copy #CopyDialogLifecycle::exists, copy_dialog_params::phase
sec
done: rts
.proc check_space
;; Size of source
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
;; If destination doesn't exist, 0 blocks will be reclaimed.
: lda #0
sta existing_size
sta existing_size+1
;; Does destination exist?
@retry2:MLI_RELAY_CALL GET_FILE_INFO, dst_file_info_params
beq got_exist_size
cmp #ERR_FILE_NOT_FOUND
beq :+
jsr show_error_alert_dst ; retry if destination not present
jmp @retry2
got_exist_size:
copy16 dst_file_info_params::blocks_used, existing_size
;; Compute destination volume path
: lda dst_path_buf
sta saved_length
ldy #1 ; search for second '/'
: iny
cpy dst_path_buf
bcs has_room
lda dst_path_buf,y
cmp #'/'
bne :-
tya
sta dst_path_buf
sta vol_path_length
;; Total blocks/used blocks on destination volume
@retry: MLI_RELAY_CALL GET_FILE_INFO, dst_file_info_params
beq got_info
pha ; on failure, restore path
lda saved_length ; in case copy is aborted
sta dst_path_buf
pla
jsr show_error_alert_dst
jmp @retry ; BUG: Does this need to assign length again???
got_info:
;; aux = total blocks
sub16 dst_file_info_params::aux_type, dst_file_info_params::blocks_used, blocks_free
add16 blocks_free, existing_size, blocks_free
cmp16 blocks_free, src_file_info_params::blocks_used
bcs has_room
;; not enough room
sec
bcs :+
has_room:
clc
: lda saved_length
sta dst_path_buf
rts
blocks_free:
.word 0
saved_length:
.byte 0
vol_path_length:
.byte 0
existing_size:
.word 0
.endproc
.endproc
;;; ============================================================
;;; Actual byte-for-byte file copy routine
.proc do_file_copy
jsr decrement_op_file_count
lda #0
sta src_dst_exclusive_flag
sta src_eof_flag
sta mark_src_params::position
sta mark_src_params::position+1
sta mark_src_params::position+2
sta mark_dst_params::position
sta mark_dst_params::position+1
sta mark_dst_params::position+2
jsr open_src
jsr copy_src_ref_num
jsr open_dst
beq :+
;; Destination not available; note it, can prompt later
copy #$FF, src_dst_exclusive_flag
bne read ; always
: jsr copy_dst_ref_num
;; Read
read: jsr read_src
bit src_dst_exclusive_flag
bpl write
jsr close_src ; swap if necessary
: jsr open_dst
bne :-
jsr copy_dst_ref_num
MLI_RELAY_CALL SET_MARK, mark_dst_params
;; Write
write: bit src_eof_flag
bmi eof
jsr write_dst
bit src_dst_exclusive_flag
bpl read
jsr close_dst ; swap if necessary
jsr open_src
jsr copy_src_ref_num
MLI_RELAY_CALL SET_MARK, mark_src_params
beq read
copy #$FF, src_eof_flag
jmp read
;; EOF
eof: jsr close_dst
bit src_dst_exclusive_flag
bmi :+
jsr close_src
: jsr copy_file_info
jmp set_dst_file_info
.proc open_src
@retry: MLI_RELAY_CALL OPEN, open_src_params
beq :+
jsr show_error_alert
jmp @retry
: rts
.endproc
.proc copy_src_ref_num
lda open_src_params::ref_num
sta read_src_params::ref_num
sta close_src_params::ref_num
sta mark_src_params::ref_num
rts
.endproc
.proc open_dst
@retry: MLI_RELAY_CALL OPEN, open_dst_params
beq done
cmp #ERR_VOL_NOT_FOUND
beq not_found
jsr show_error_alert_dst
jmp @retry
not_found:
jsr show_error_alert_dst
lda #ERR_VOL_NOT_FOUND
done: rts
.endproc
.proc copy_dst_ref_num
lda open_dst_params::ref_num
sta write_dst_params::ref_num
sta close_dst_params::ref_num
sta mark_dst_params::ref_num
rts
.endproc
.proc read_src
copy16 #buf_size, read_src_params::request_count
@retry: MLI_RELAY_CALL READ, read_src_params
beq :+
cmp #ERR_END_OF_FILE
beq eof
jsr show_error_alert
jmp @retry
: copy16 read_src_params::trans_count, write_dst_params::request_count
ora read_src_params::trans_count
bne :+
eof: copy #$FF, src_eof_flag
: MLI_RELAY_CALL GET_MARK, mark_src_params
rts
.endproc
.proc write_dst
@retry: MLI_RELAY_CALL WRITE, write_dst_params
beq :+
jsr show_error_alert_dst
jmp @retry
: MLI_RELAY_CALL GET_MARK, mark_dst_params
rts
.endproc
.proc close_dst
MLI_RELAY_CALL CLOSE, close_dst_params
rts
.endproc
.proc close_src
MLI_RELAY_CALL CLOSE, close_src_params
rts
.endproc
;; Set if src/dst can't be open simultaneously.
src_dst_exclusive_flag:
.byte 0
src_eof_flag:
.byte 0
.endproc
;;; ============================================================
.proc try_create_dst
;; Copy file_type, aux_type, storage_type
ldx #7
: lda src_file_info_params,x
sta create_params3,x
dex
cpx #3
bne :-
create: MLI_RELAY_CALL CREATE, create_params3
beq success
cmp #ERR_DUPLICATE_FILENAME
bne err
bit all_flag
bmi yes
copy #CopyDialogLifecycle::exists, copy_dialog_params::phase
yax_call invoke_dialog_proc, index_copy_dialog, copy_dialog_params
pha
copy #CopyDialogLifecycle::show, copy_dialog_params::phase
pla
cmp #PromptResult::yes
beq yes
cmp #PromptResult::no
beq failure
cmp #PromptResult::all
bne cancel
copy #$80, all_flag
yes: jsr apply_file_info_and_size
jmp success
cancel: jmp close_files_cancel_dialog
err: jsr show_error_alert_dst
jmp create
success:
clc
rts
failure:
sec
rts
.endproc
;;; ============================================================
;;; Delete/Trash files dialog state and logic
;;; ============================================================
;;; delete_process_selected_file
;;; - called for each file in selection; calls process_dir to recurse
;;; delete_process_directory_entry
;;; - c/o process_dir for each file in dir; skips if dir, deletes otherwise
;;; delete_finish_directory
;;; - c/o process_dir when exiting dir; deletes it
;;; Overlays for delete operation (op_jt_addrs)
callbacks_for_delete:
.addr delete_process_directory_entry
.addr do_nothing
.addr delete_finish_directory
.proc delete_dialog_params
phase: .byte 0
count: .word 0
.addr src_path_buf
.endproc
.proc do_delete_dialog_phase
sta delete_dialog_params::phase
copy16 #confirm_delete_dialog, dialog_phase2_callback
copy16 #populate_delete_dialog, dialog_phase0_callback
jsr run_delete_dialog_proc
copy16 #L9ED3, dialog_phase1_callback
rts
.proc populate_delete_dialog
stax delete_dialog_params::count
copy #DeleteDialogLifecycle::populate, delete_dialog_params::phase
jmp run_delete_dialog_proc
.endproc
.proc confirm_delete_dialog
copy #DeleteDialogLifecycle::confirm, delete_dialog_params::phase
jsr run_delete_dialog_proc
beq :+
jmp close_files_cancel_dialog
: rts
.endproc
.endproc
;;; ============================================================
.proc prep_callbacks_for_delete
ldy #op_jt_addrs_size-1
: copy callbacks_for_delete,y, op_jt_addrs,y
dey
bpl :-
lda #0
sta LA425
sta all_flag
rts
.endproc
.proc L9ED3
copy #DeleteDialogLifecycle::close, delete_dialog_params::phase
jmp run_delete_dialog_proc
.endproc
;;; ============================================================
;;; Handle deletion of a selected file.
;;; Calls into the recursion logic of |process_dir| as necessary.
.proc delete_process_selected_file
copy #DeleteDialogLifecycle::show, delete_dialog_params::phase
jsr copy_paths_to_src_and_dst_paths
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
;; Check if it's a regular file or directory
: lda src_file_info_params::storage_type
sta storage_type
cmp #ST_LINKED_DIRECTORY
beq :+
lda #0
beq store
: lda #$FF
store: sta is_dir_flag
beq do_destroy
;; Recurse, and process directory
jsr process_dir
;; Was it a directory?
lda storage_type
cmp #ST_LINKED_DIRECTORY
bne :+
copy #$FF, storage_type ; is this re-checked?
: jmp do_destroy
;; Written, not read???
is_dir_flag:
.byte 0
storage_type:
.byte 0
do_destroy:
bit delete_skip_decrement_flag
bmi :+
jsr dec_file_count_and_run_delete_dialog_proc
: jsr decrement_op_file_count
retry: MLI_RELAY_CALL DESTROY, destroy_params
beq done
cmp #ERR_ACCESS_ERROR
bne error
bit all_flag
bmi do_it
copy #DeleteDialogLifecycle::locked, delete_dialog_params::phase
jsr run_delete_dialog_proc
pha
copy #DeleteDialogLifecycle::show, delete_dialog_params::phase
pla
cmp #PromptResult::no
beq done
cmp #PromptResult::yes
beq do_it
cmp #PromptResult::all
bne :+
copy #$80, all_flag
bne do_it ; always
: jmp close_files_cancel_dialog
do_it: jsr unlock_src_file
bne done
jmp retry
done: rts
error: jsr show_error_alert
jmp retry
.endproc
.proc unlock_src_file
MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
lda src_file_info_params::access
and #$80
bne done
lda #ACCESS_DEFAULT
sta src_file_info_params::access
copy #7, src_file_info_params ; param count for SET_FILE_INFO
MLI_RELAY_CALL SET_FILE_INFO, src_file_info_params
copy #$A, src_file_info_params ; param count for GET_FILE_INFO
lda #0 ; success
done: rts
.endproc
;;; ============================================================
;;; Called by |process_dir| to process a single file
.proc delete_process_directory_entry
;; Cancel if escape pressed
jsr check_escape_key_down
beq :+
jmp close_files_cancel_dialog
: jsr append_to_src_path
bit delete_skip_decrement_flag
bmi :+
jsr dec_file_count_and_run_delete_dialog_proc
: jsr decrement_op_file_count
;; Check file type
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
;; Directories will be processed separately
: lda src_file_info_params::storage_type
cmp #ST_LINKED_DIRECTORY
beq next_file
loop: MLI_RELAY_CALL DESTROY, destroy_params
beq next_file
cmp #ERR_ACCESS_ERROR
bne err
bit all_flag
bmi unlock
copy #DeleteDialogLifecycle::locked, delete_dialog_params::phase
yax_call invoke_dialog_proc, index_delete_dialog, delete_dialog_params
pha
copy #DeleteDialogLifecycle::show, delete_dialog_params::phase
pla
cmp #PromptResult::no
beq next_file
cmp #PromptResult::yes
beq unlock
cmp #PromptResult::all
bne :+
copy #$80, all_flag
bne unlock ; always
;; PromptResult::cancel
: jmp close_files_cancel_dialog
unlock: copy #ACCESS_DEFAULT, src_file_info_params::access
copy #7, src_file_info_params ; param count for SET_FILE_INFO
MLI_RELAY_CALL SET_FILE_INFO, src_file_info_params
copy #$A,src_file_info_params ; param count for GET_FILE_INFO
jmp loop
err: jsr show_error_alert
jmp loop
next_file:
jmp remove_src_path_segment
.endproc
;;; ============================================================
;;; Delete directory when exiting via traversal
.proc delete_finish_directory
@retry: MLI_RELAY_CALL DESTROY, destroy_params
beq done
cmp #ERR_ACCESS_ERROR
beq done
jsr show_error_alert
jmp @retry
done: rts
.endproc
.proc run_delete_dialog_proc
yax_call invoke_dialog_proc, index_delete_dialog, delete_dialog_params
rts
.endproc
;;; ============================================================
;;; "Lock"/"Unlock" dialog state and logic
;;; ============================================================
;;; lock_process_selected_file
;;; - called for each file in selection; calls process_dir to recurse
;;; lock_process_directory_entry
;;; - c/o process_dir for each file in dir; skips if dir, locks otherwise
;;; Overlays for lock/unlock operation (op_jt_addrs)
callbacks_for_lock:
.addr lock_process_directory_entry
.addr do_nothing
.addr do_nothing
.enum LockDialogLifecycle
open = 0 ; opening window, initial label
populate = 1 ; show operation details (e.g. file count)
loop = 2 ; draw buttons, input loop
operation = 3 ; performing operation
close = 4 ; destroy window
.endenum
.proc lock_unlock_dialog_params
phase: .byte 0
files_remaining_count:
.word 0
.addr src_path_buf
.endproc
.proc do_lock_dialog_phase
copy #LockDialogLifecycle::open, lock_unlock_dialog_params::phase
bit unlock_flag
bpl :+
;; Unlock
copy16 #unlock_dialog_phase2_callback, dialog_phase2_callback
copy16 #unlock_dialog_phase0_callback, dialog_phase0_callback
jsr unlock_dialog_lifecycle
copy16 #close_unlock_dialog, dialog_phase1_callback
rts
;; Lock
: copy16 #lock_dialog_phase2_callback, dialog_phase2_callback
copy16 #lock_dialog_phase0_callback, dialog_phase0_callback
jsr lock_dialog_lifecycle
copy16 #close_lock_dialog, dialog_phase1_callback
rts
.endproc
.proc lock_dialog_phase0_callback
stax lock_unlock_dialog_params::files_remaining_count
copy #LockDialogLifecycle::populate, lock_unlock_dialog_params::phase
jmp lock_dialog_lifecycle
.endproc
.proc unlock_dialog_phase0_callback
stax lock_unlock_dialog_params::files_remaining_count
copy #LockDialogLifecycle::populate, lock_unlock_dialog_params::phase
jmp unlock_dialog_lifecycle
.endproc
.proc lock_dialog_phase2_callback
copy #LockDialogLifecycle::loop, lock_unlock_dialog_params::phase
jsr lock_dialog_lifecycle
beq :+
jmp close_files_cancel_dialog
: rts
.endproc
.proc unlock_dialog_phase2_callback
copy #LockDialogLifecycle::loop, lock_unlock_dialog_params::phase
jsr unlock_dialog_lifecycle
beq :+
jmp close_files_cancel_dialog
: rts
.endproc
.proc prep_callbacks_for_lock
copy #0, LA425
ldy #op_jt_addrs_size-1
: copy callbacks_for_lock,y, op_jt_addrs,y
dey
bpl :-
rts
.endproc
.proc close_lock_dialog
copy #LockDialogLifecycle::close, lock_unlock_dialog_params::phase
jmp lock_dialog_lifecycle
.endproc
.proc close_unlock_dialog
copy #LockDialogLifecycle::close, lock_unlock_dialog_params::phase
jmp unlock_dialog_lifecycle
.endproc
lock_dialog_lifecycle:
yax_call invoke_dialog_proc, index_lock_dialog, lock_unlock_dialog_params
rts
unlock_dialog_lifecycle:
yax_call invoke_dialog_proc, index_unlock_dialog, lock_unlock_dialog_params
rts
;;; ============================================================
;;; Handle locking of a selected file.
;;; Calls into the recursion logic of |process_dir| as necessary.
.proc lock_process_selected_file
copy #LockDialogLifecycle::operation, lock_unlock_dialog_params::phase
jsr copy_paths_to_src_and_dst_paths
ldx dst_path_buf
ldy src_path_slash_index
dey
LA123: iny
inx
lda src_path_buf,y
sta dst_path_buf,x
cpy src_path_buf
bne LA123
stx dst_path_buf
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
: lda src_file_info_params::storage_type
sta storage_type
cmp #ST_VOLUME_DIRECTORY
beq is_dir
cmp #ST_LINKED_DIRECTORY
beq is_dir
lda #$00
beq store
is_dir: lda #$FF
store: sta is_dir_flag
beq do_lock
;; Process files in directory
jsr process_dir
;; If this wasn't a volume directory, lock it too
lda storage_type
cmp #ST_VOLUME_DIRECTORY
bne do_lock
rts
;; Written, not read???
is_dir_flag:
.byte 0
storage_type:
.byte 0
do_lock:
jsr lock_file_common
jmp append_to_src_path
.endproc
;;; ============================================================
;;; Called by |process_dir| to process a single file
lock_process_directory_entry:
jsr append_to_src_path
;; fall through
.proc lock_file_common
jsr update_dialog
jsr decrement_op_file_count
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
: lda src_file_info_params::storage_type
cmp #ST_VOLUME_DIRECTORY
beq ok
cmp #ST_LINKED_DIRECTORY
beq ok
bit unlock_flag
bpl :+
lda #ACCESS_DEFAULT
bne set
: lda #ACCESS_LOCKED
set: sta src_file_info_params::access
: copy #7, src_file_info_params ; param count for SET_FILE_INFO
MLI_RELAY_CALL SET_FILE_INFO, src_file_info_params
pha
copy #$A, src_file_info_params ; param count for GET_FILE_INFO
pla
beq ok
jsr show_error_alert
jmp :-
ok: jmp remove_src_path_segment
update_dialog:
sub16 op_file_count, #1, lock_unlock_dialog_params::files_remaining_count
bit unlock_flag
bpl LA1DC
jmp unlock_dialog_lifecycle
LA1DC: jmp lock_dialog_lifecycle
.endproc
;;; ============================================================
;;; "Get Size" dialog state and logic
;;; ============================================================
;;; Logic also used for "count" operation which precedes most
;;; other operations (copy, delete, lock, unlock) to populate
;;; confirmation dialog.
.proc get_size_dialog_params
phase: .byte 0
.addr op_file_count, op_block_count
.endproc
do_get_size_dialog_phase:
copy #0, get_size_dialog_params::phase
copy16 #get_size_dialog_phase2_callback, dialog_phase2_callback
copy16 #get_size_dialog_phase0_callback, dialog_phase0_callback
yax_call invoke_dialog_proc, index_get_size_dialog, get_size_dialog_params
copy16 #get_size_dialog_phase1_callback, dialog_phase1_callback
rts
.proc get_size_dialog_phase0_callback
copy #1, get_size_dialog_params::phase
yax_call invoke_dialog_proc, index_get_size_dialog, get_size_dialog_params
;; fall through
.endproc
get_size_rts1:
rts
.proc get_size_dialog_phase2_callback
copy #2, get_size_dialog_params::phase
yax_call invoke_dialog_proc, index_get_size_dialog, get_size_dialog_params
beq get_size_rts1
jmp close_files_cancel_dialog
.endproc
.proc get_size_dialog_phase1_callback
copy #3, get_size_dialog_params::phase
yax_call invoke_dialog_proc, index_get_size_dialog, get_size_dialog_params
.endproc
get_size_rts2:
rts
;;; ============================================================
;;; Most operations start by doing a traversal to just count
;;; the files.
;;; Overlays for size operation (op_jt_addrs)
callbacks_for_size_or_count:
.addr size_or_count_process_directory_entry
.addr do_nothing
.addr do_nothing
.proc prep_callbacks_for_size_or_count
copy #0, LA425
ldy #op_jt_addrs_size-1
: copy callbacks_for_size_or_count,y, op_jt_addrs,y
dey
bpl :-
lda #0
sta op_file_count
sta op_file_count+1
sta op_block_count
sta op_block_count+1
rts
.endproc
;;; ============================================================
;;; Handle sizing (or just counting) of a selected file.
;;; Calls into the recursion logic of |process_dir| as necessary.
.proc size_or_count_process_selected_file
jsr copy_paths_to_src_and_dst_paths
@retry: MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
beq :+
jsr show_error_alert
jmp @retry
: copy src_file_info_params::storage_type, storage_type
cmp #ST_VOLUME_DIRECTORY
beq is_dir
cmp #ST_LINKED_DIRECTORY
beq is_dir
lda #0
beq store ; always
is_dir: lda #$FF
store: sta is_dir_flag
beq do_sum_file_size ; if not a dir
jsr process_dir
lda storage_type
cmp #ST_VOLUME_DIRECTORY
bne do_sum_file_size ; if a subdirectory
rts
;; Written, not read???
is_dir_flag:
.byte 0
storage_type:
.byte 0
do_sum_file_size:
jmp size_or_count_process_directory_entry
.endproc
;;; ============================================================
;;; Called by |process_dir| to process a single file
size_or_count_process_directory_entry:
bit operation_flags
bvc :+ ; not size
;; If operation is "get size", add the block count to the sum
jsr append_to_src_path
MLI_RELAY_CALL GET_FILE_INFO, src_file_info_params
bne :+
add16 op_block_count, src_file_info_params::blocks_used, op_block_count
: inc16 op_file_count
bit operation_flags
bvc :+ ; not size
jsr remove_src_path_segment
: ldax op_file_count
jmp done_dialog_phase0
op_file_count:
.word 0
op_block_count:
.word 0
;;; ============================================================
.proc decrement_op_file_count
dec16 op_file_count
rts
.endproc
;;; ============================================================
;;; Append name at file_entry_buf to path at src_path_buf
.proc append_to_src_path
path := src_path_buf
lda file_entry_buf
bne :+
rts
: ldx #0
ldy path
copy #'/', path+1,y
iny
loop: cpx file_entry_buf
bcs done
lda file_entry_buf+1,x
sta path+1,y
inx
iny
jmp loop
done: sty path
rts
.endproc
;;; ============================================================
;;; Remove segment from path at src_path_buf
.proc remove_src_path_segment
path := src_path_buf
ldx path ; length
bne :+
rts
: lda path,x
cmp #'/'
beq found
dex
bne :-
stx path
rts
found: dex
stx path
rts
.endproc
;;; ============================================================
;;; Append name at file_entry_buf to path at dst_path_buf
.proc append_to_dst_path
path := dst_path_buf
lda file_entry_buf
bne :+
rts
: ldx #0
ldy path
copy #'/', path+1,y
iny
loop: cpx file_entry_buf
bcs done
lda file_entry_buf+1,x
sta path+1,y
inx
iny
jmp loop
done: sty path
rts
.endproc
;;; ============================================================
;;; Remove segment from path at dst_path_buf
.proc remove_dst_path_segment
path := dst_path_buf
ldx path ; length
bne :+
rts
: lda path,x
cmp #'/'
beq found
dex
bne :-
stx path
rts
found: dex
stx path
rts
.endproc
;;; ============================================================
;;; Copy path_buf3 to src_path_buf, path_buf4 to dst_path_buf
;;; and note last '/' in src.
.proc copy_paths_to_src_and_dst_paths
ldy #0
sty src_path_slash_index
dey
;; Copy path_buf3 to src_path_buf
;; ... but record index of last '/'
loop: iny
lda path_buf3,y
cmp #'/'
bne :+
sty src_path_slash_index
: sta src_path_buf,y
cpy path_buf3
bne loop
;; Copy path_buf4 to dst_path_buf
ldy path_buf4
: lda path_buf4,y
sta dst_path_buf,y
dey
bpl :-
rts
.endproc
;;; ============================================================
;;; Closes dialog, closes all open files, and restores stack.
.proc close_files_cancel_dialog
jsr done_dialog_phase1
jmp :+
DEFINE_CLOSE_PARAMS close_params
: MLI_RELAY_CALL CLOSE, close_params
lda selected_window_index
beq :+
sta getwinport_params2::window_id
yax_call JT_MGTK_RELAY, MGTK::GetWinPort, getwinport_params2
yax_call JT_MGTK_RELAY, MGTK::SetPort, grafport2
: ldx stack_stash ; restore stack, in case recusion was aborted
txs
return #$FF
.endproc
;;; ============================================================
;;; Move or Copy? Compare src/dst paths, same vol = move.
;;; Output: A=high bit set if move, clear if copy
.proc check_move_or_copy
src_ptr := $08
dst_buf := path_buf4
bit BUTN0 ; Open-Apple overrides, forces copy
bmi no_match
ldy #0
lda (src_ptr),y
sta src_len
iny ; skip leading '/'
bne check ; always
;; Chars the same?
loop: lda (src_ptr),y
cmp dst_buf,y
bne no_match
;; Same and a slash?
cmp #'/'
beq match
;; End of src?
check: cpy src_len
bcc :+
cpy dst_buf ; dst also done?
bcs match
lda path_buf4+1,y ; is next char in dst a slash?
bne check_slash ; always
: cpy dst_buf ; src is not done, is dst?
bcc :+
iny
lda (src_ptr),y ; is next char in src a slash?
bne check_slash ; always
: iny ; next char
bne loop ; always
check_slash:
cmp #'/'
beq match ; if so, same vol
;; fall through
no_match:
return #0
match: return #$80
src_len:
.byte 0
.endproc
;;; ============================================================
.proc check_escape_key_down
yax_call JT_MGTK_RELAY, MGTK::GetEvent, event_params
lda event_kind
cmp #MGTK::EventKind::key_down
bne nope
lda event_key
cmp #CHAR_ESCAPE
bne nope
lda #$FF
bne done
nope: lda #$00
done: rts
.endproc
;;; ============================================================
.proc dec_file_count_and_run_delete_dialog_proc
sub16 op_file_count, #1, delete_dialog_params::count
yax_call invoke_dialog_proc, index_delete_dialog, delete_dialog_params
rts
.endproc
.proc dec_file_count_and_run_copy_dialog_proc
sub16 op_file_count, #1, copy_dialog_params::count
yax_call invoke_dialog_proc, index_copy_dialog, copy_dialog_params
rts
.endproc
LA425: .byte 0 ; ??? only written to (with 0)
;;; ============================================================
.proc apply_file_info_and_size
: jsr copy_file_info
copy #ACCESS_DEFAULT, dst_file_info_params::access
jsr set_dst_file_info
lda src_file_info_params::file_type
cmp #FT_DIRECTORY
beq done
;; If a regular file, open/set eof/close
MLI_RELAY_CALL OPEN, open_dst_params
beq :+
jsr show_error_alert_dst
jmp :- ; retry
: lda open_dst_params::ref_num
sta set_eof_params::ref_num
sta close_dst_params::ref_num
@retry: MLI_RELAY_CALL SET_EOF, set_eof_params
beq close
jsr show_error_alert_dst
jmp @retry
close: MLI_RELAY_CALL CLOSE, close_dst_params
done: rts
.endproc
.proc copy_file_info
COPY_BYTES 11, src_file_info_params::access, dst_file_info_params::access
rts
.endproc
.proc set_dst_file_info
: copy #7, dst_file_info_params ; SET_FILE_INFO param_count
MLI_RELAY_CALL SET_FILE_INFO, dst_file_info_params
pha
copy #$A, dst_file_info_params ; GET_FILE_INFO param_count
pla
beq done
jsr show_error_alert_dst
jmp :-
done: rts
.endproc
;;; ============================================================
;;; Show Alert Dialog
;;; A=error. If ERR_VOL_NOT_FOUND or ERR_FILE_NOT_FOUND, will
;;; show "please insert source disk" (or destination, if flag set)
.proc show_error_alert_impl
flag_set:
ldx #$80
bne :+
flag_clear:
ldx #0
: stx flag
cmp #ERR_VOL_NOT_FOUND ; if err is "not found"
beq not_found ; prompt specifically for src/dst disk
cmp #ERR_PATH_NOT_FOUND
beq not_found
jsr JT_SHOW_ALERT0
bne LA4C2 ; cancel???
rts
not_found:
bit flag
bpl :+
lda #ERR_INSERT_DST_DISK
jmp show
: lda #ERR_INSERT_SRC_DISK
show: jsr JT_SHOW_ALERT0
bne LA4C2
jmp do_on_line
LA4C2: jmp close_files_cancel_dialog
flag: .byte 0
do_on_line:
MLI_RELAY_CALL ON_LINE, on_line_params2
rts
.endproc
show_error_alert := show_error_alert_impl::flag_clear
show_error_alert_dst := show_error_alert_impl::flag_set
;;; ============================================================
;;; Reformat /RAM (Slot 3, Drive 2) if present
;;; Assumes ROM is banked in, restores it when complete. Also
;;; assumes hires screen (main and aux) are safe to destroy.
.proc maybe_reformat_ram
ram_unit_number = (1<<7 | 3<<4 | DT_RAM)
;; Search DEVLST to see if S3D2 RAM was restored
ldx DEVCNT
: lda DEVLST,x
cmp #ram_unit_number
beq format
dex
bpl :-
rts
;; NOTE: Assumes driver (in DEVADR) was not modified
;; when detached.
;; /RAM FORMAT call; see ProDOS 8 TRM 5.2.2.4 for details
format: copy #DRIVER_COMMAND_FORMAT, DRIVER_COMMAND
copy #ram_unit_number, DRIVER_UNIT_NUMBER
copy16 #$2000, DRIVER_BUFFER
lda LCBANK1
lda LCBANK1
jsr driver
sta ROMIN2
rts
RAMSLOT := DEVADR + $16 ; Slot 3, Drive 2
driver: jmp (RAMSLOT)
.endproc
;;; ============================================================
PAD_TO $A500
;;; ============================================================
;;; Dialog Launcher (or just proc handler???)
index_about_dialog = 0
index_copy_dialog = 1
index_delete_dialog = 2
index_new_folder_dialog = 3
index_get_info_dialog = 6
index_lock_dialog = 7
index_unlock_dialog = 8
index_rename_dialog = 9
index_download_dialog = 10
index_get_size_dialog = 11
index_warning_dialog = 12
invoke_dialog_proc:
.assert * = $A500, error, "Entry point used by overlay"
jmp invoke_dialog_proc_impl
dialog_proc_table:
.addr about_dialog_proc
.addr copy_dialog_proc
.addr delete_dialog_proc
.addr new_folder_dialog_proc
.addr rts1
.addr rts1
.addr get_info_dialog_proc
.addr lock_dialog_proc
.addr unlock_dialog_proc
.addr rename_dialog_proc
.addr download_dialog_proc
.addr get_size_dialog_proc
.addr warning_dialog_proc
dialog_param_addr:
.addr 0
.byte 0
.proc invoke_dialog_proc_impl
stax dialog_param_addr
tya
asl a
tax
copy16 dialog_proc_table,x, @jump_addr
lda #0
sta prompt_ip_flag
sta LD8EC
sta LD8F0
sta LD8F1
sta LD8F2
sta has_input_field_flag
sta LD8F5
sta format_erase_overlay_flag
sta cursor_ip_flag
copy #prompt_insertion_point_blink_count, prompt_ip_counter
copy16 #rts1, jump_relay+1
jsr set_cursor_pointer
@jump_addr := *+1
jmp dummy0000 ; self-modified
.endproc
;;; ============================================================
;;; Message handler for OK/Cancel dialog
.proc prompt_input_loop
lda has_input_field_flag
beq :+
;; Blink the insertion point
dec prompt_ip_counter
bne :+
jsr redraw_prompt_insertion_point
copy #prompt_insertion_point_blink_count, prompt_ip_counter
;; Dispatch event types - mouse down, key press
: MGTK_RELAY_CALL MGTK::GetEvent, event_params
lda event_kind
cmp #MGTK::EventKind::button_down
bne :+
jmp prompt_click_handler
: cmp #MGTK::EventKind::key_down
bne :+
jmp prompt_key_handler
;; Does the dialog have an input field?
: lda has_input_field_flag
beq prompt_input_loop
;; Check if mouse is over input field, change cursor appropriately.
MGTK_RELAY_CALL MGTK::FindWindow, event_coords
lda findwindow_which_area
bne :+
jmp prompt_input_loop
: lda findwindow_window_id
cmp winfo_alert_dialog
beq :+
jmp prompt_input_loop
: lda winfo_alert_dialog ; Is over this window... but where?
jsr set_port_from_window_id
copy winfo_alert_dialog, event_params
MGTK_RELAY_CALL MGTK::ScreenToWindow, screentowindow_params
MGTK_RELAY_CALL MGTK::MoveTo, screentowindow_windowx
MGTK_RELAY_CALL MGTK::InRect, name_input_rect
cmp #MGTK::inrect_inside
bne out
jsr set_cursor_insertion_point_with_flag
jmp done
out: jsr set_cursor_pointer_with_flag
done: jsr reset_grafport3a
jmp prompt_input_loop
.endproc
;;; Click handler for prompt dialog
.proc prompt_click_handler
MGTK_RELAY_CALL MGTK::FindWindow, event_coords
lda findwindow_which_area
bne :+
return #$FF
: cmp #MGTK::Area::content
bne :+
jmp content
: return #$FF
content:
lda findwindow_window_id
cmp winfo_alert_dialog
beq :+
return #$FF
: lda winfo_alert_dialog
jsr set_port_from_window_id
copy winfo_alert_dialog, event_params
MGTK_RELAY_CALL MGTK::ScreenToWindow, screentowindow_params
MGTK_RELAY_CALL MGTK::MoveTo, screentowindow_windowx
bit LD8E7
bvc :+
jmp check_button_yes
: MGTK_RELAY_CALL MGTK::InRect, desktop_aux::ok_button_rect
cmp #MGTK::inrect_inside
beq check_button_ok
jmp maybe_check_button_cancel
check_button_ok:
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::ok_button_rect
jsr button_loop_ok
bmi :+
lda #PromptResult::ok
: rts
check_button_yes:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::yes_button_rect
cmp #MGTK::inrect_inside
bne check_button_no
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::yes_button_rect
jsr button_loop_yes
bmi :+
lda #PromptResult::yes
: rts
check_button_no:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::no_button_rect
cmp #MGTK::inrect_inside
bne check_button_all
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::no_button_rect
jsr button_loop_no
bmi :+
lda #PromptResult::no
: rts
check_button_all:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::all_button_rect
cmp #MGTK::inrect_inside
bne maybe_check_button_cancel
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::all_button_rect
jsr button_loop_all
bmi :+
lda #PromptResult::all
: rts
maybe_check_button_cancel:
bit LD8E7
bpl check_button_cancel
return #$FF
check_button_cancel:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::cancel_button_rect
cmp #MGTK::inrect_inside
beq :+
jmp LA6ED
: jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::cancel_button_rect
jsr button_loop_cancel
bmi :+
lda #PromptResult::cancel
: rts
LA6ED: bit has_input_field_flag
bmi LA6F7
lda #$FF
jmp jump_relay
LA6F7: jsr LB9B8
return #$FF
.endproc
;;; Key handler for prompt dialog
.proc prompt_key_handler
lda event_modifiers
cmp #MGTK::event_modifier_solid_apple
bne no_mods
;; Modifier key down.
lda event_key
and #CHAR_MASK
cmp #CHAR_LEFT
bne :+
jmp left_with_mod
: cmp #CHAR_RIGHT
bne done
jmp right_with_mod
done: return #$FF
;; No modifier key down.
no_mods:
lda event_key
and #CHAR_MASK
cmp #CHAR_LEFT
bne LA72E
bit format_erase_overlay_flag
bpl :+
jmp format_erase_overlay_prompt_handle_key_left
: jmp handle_key_left
LA72E: cmp #CHAR_RIGHT
bne LA73D
bit format_erase_overlay_flag
bpl :+
jmp format_erase_overlay_prompt_handle_key_right
: jmp handle_key_right
LA73D: cmp #CHAR_RETURN
bne LA749
bit LD8E7
bvs done
jmp LA851
LA749: cmp #CHAR_ESCAPE
bne LA755
bit LD8E7
bmi done
jmp LA86F
LA755: cmp #CHAR_DELETE
bne LA75C
jmp LA88D
LA75C: cmp #CHAR_UP
bne LA76B
bit format_erase_overlay_flag
bmi :+
jmp done
: jmp format_erase_overlay_prompt_handle_key_up
LA76B: cmp #CHAR_DOWN
bne LA77A
bit format_erase_overlay_flag
bmi :+
jmp done
: jmp format_erase_overlay_prompt_handle_key_down
LA77A: bit LD8E7
bvc LA79B
cmp #'Y'
beq do_yes
cmp #'y'
beq do_yes
cmp #'N'
beq do_no
cmp #'n'
beq do_no
cmp #'A'
beq do_all
cmp #'a'
beq do_all
cmp #CHAR_RETURN
beq do_yes
LA79B: bit LD8F5
bmi LA7C8
cmp #'.'
beq LA7D8
cmp #'0'
bcs LA7AB
jmp done
LA7AB: cmp #'z'+1
bcc LA7B2
jmp done
LA7B2: cmp #'9'+1
bcc LA7D8
cmp #'A'
bcs LA7BD
jmp done
LA7BD: cmp #'Z'+1
bcc LA7DD
cmp #'a'
bcs LA7DD
jmp done
LA7C8: cmp #' '
bcs LA7CF
jmp done
LA7CF: cmp #'~'
beq LA7DD
bcc LA7DD
jmp done
LA7D8: ldx path_buf1
beq LA7E5
LA7DD: ldx has_input_field_flag
beq LA7E5
jsr LBB0B
LA7E5: return #$FF
do_yes: jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::yes_button_rect
return #PromptResult::yes
do_no: jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::no_button_rect
return #PromptResult::no
do_all: jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::all_button_rect
return #PromptResult::all
.proc left_with_mod
lda has_input_field_flag
beq :+
jsr input_field_ip_start
: return #$FF
.endproc
.proc right_with_mod
lda has_input_field_flag
beq :+
jsr input_field_ip_end
: return #$FF
.endproc
.proc handle_key_left
lda has_input_field_flag
beq done
bit format_erase_overlay_flag ; BUG? Should never be set here based on caller test.
bpl :+
jmp format_erase_overlay_prompt_handle_key_right
: jsr input_field_ip_left
done: return #$FF
.endproc
.proc handle_key_right
lda has_input_field_flag
beq done
bit format_erase_overlay_flag ; BUG? Should never be set here based on caller test.
bpl :+
jmp format_erase_overlay_prompt_handle_key_left
: jsr input_field_ip_right
done: return #$FF
.endproc
LA851: lda winfo_alert_dialog
jsr set_port_from_window_id
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::ok_button_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::ok_button_rect
return #0
LA86F: lda winfo_alert_dialog
jsr set_port_from_window_id
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::cancel_button_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::cancel_button_rect
return #1
LA88D: lda has_input_field_flag
beq LA895
jsr LBB63
LA895: return #$FF
.endproc
rts1:
rts
;;; ============================================================
jump_relay:
jmp dummy0000
;;; ============================================================
;;; "About" dialog
.proc about_dialog_proc
MGTK_RELAY_CALL MGTK::OpenWindow, winfo_about_dialog
lda winfo_about_dialog::window_id
jsr set_port_from_window_id
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::about_dialog_outer_rect
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::about_dialog_inner_rect
addr_call draw_dialog_title, desktop_aux::str_about1
yax_call draw_dialog_label, 1 | DDL_CENTER, desktop_aux::str_about2
yax_call draw_dialog_label, 2 | DDL_CENTER, desktop_aux::str_about3
yax_call draw_dialog_label, 3 | DDL_CENTER, desktop_aux::str_about4
yax_call draw_dialog_label, 5, desktop_aux::str_about5
yax_call draw_dialog_label, 6 | DDL_CENTER, desktop_aux::str_about6
yax_call draw_dialog_label, 7, desktop_aux::str_about7
yax_call draw_dialog_label, 9, desktop_aux::str_about8
copy16 #310 - (7 * .strlen(VERSION_SUFFIX)), dialog_label_pos
yax_call draw_dialog_label, 9, desktop_aux::str_about9
copy16 #dialog_label_default_x, dialog_label_pos
: MGTK_RELAY_CALL MGTK::GetEvent, event_params
lda event_kind
cmp #MGTK::EventKind::button_down
beq close
cmp #MGTK::EventKind::key_down
bne :-
lda event_key
and #CHAR_MASK
cmp #CHAR_ESCAPE
beq close
cmp #CHAR_RETURN
bne :-
jmp close
close: MGTK_RELAY_CALL MGTK::CloseWindow, winfo_about_dialog
jsr reset_grafport3a
jsr set_cursor_pointer_with_flag
rts
.endproc
;;; ============================================================
.proc copy_dialog_proc
ptr := $6
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda (ptr),y
cmp #CopyDialogLifecycle::populate
bne :+
jmp do1
: cmp #CopyDialogLifecycle::show
bne :+
jmp do2
: cmp #CopyDialogLifecycle::exists
bne :+
jmp do3
: cmp #CopyDialogLifecycle::too_large
bne :+
jmp do4
: cmp #CopyDialogLifecycle::close
bne :+
jmp do5
;; CopyDialogLifecycle::open
: copy #0, has_input_field_flag
jsr open_dialog_window
yax_call draw_dialog_label, 2, desktop_aux::str_copy_from
yax_call draw_dialog_label, 3, desktop_aux::str_copy_to
bit move_flag
bmi :+
addr_call draw_dialog_title, desktop_aux::str_copy_title
yax_call draw_dialog_label, 1, desktop_aux::str_copy_copying
yax_call draw_dialog_label, 4, desktop_aux::str_copy_remaining
rts
: addr_call draw_dialog_title, desktop_aux::str_move_title
yax_call draw_dialog_label, 1, desktop_aux::str_move_moving
yax_call draw_dialog_label, 4, desktop_aux::str_move_remaining
rts
;; CopyDialogLifecycle::populate
do1: ldy #1
copy16in (ptr),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::copy_file_count_pos
addr_call draw_text1, str_file_count
addr_call draw_text1, str_files
rts
;; CopyDialogLifecycle::exists
do2: ldy #1
copy16in (ptr),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
jsr clear_target_file_rect
jsr clear_dest_file_rect
jsr copy_dialog_param_addr_to_ptr
ldy #$03
lda (ptr),y
tax
iny
lda (ptr),y
sta ptr+1
stx ptr
jsr copy_name_to_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::current_target_file_pos
addr_call draw_text1, path_buf0
jsr copy_dialog_param_addr_to_ptr
ldy #$05
lda (ptr),y
tax
iny
lda (ptr),y
sta ptr+1
stx ptr
jsr copy_name_to_buf1
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::current_dest_file_pos
addr_call draw_text1, path_buf1
yax_call MGTK_RELAY, MGTK::MoveTo, desktop_aux::copy_file_count_pos2
addr_call draw_text1, str_file_count
rts
;; CopyDialogLifecycle::close
do5: jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
rts
;; CopyDialogLifecycle::exists
do3: jsr bell
lda winfo_alert_dialog
jsr set_port_from_window_id
yax_call draw_dialog_label, 6, desktop_aux::str_exists_prompt
jsr draw_yes_no_all_cancel_buttons
LAA7F: jsr prompt_input_loop
bmi LAA7F
pha
jsr erase_yes_no_all_cancel_buttons
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::prompt_rect
pla
rts
;; CopyDialogLifecycle::too_large
do4: jsr bell
lda winfo_alert_dialog
jsr set_port_from_window_id
yax_call draw_dialog_label, 6, desktop_aux::str_large_prompt
jsr draw_ok_cancel_buttons
: jsr prompt_input_loop
bmi :-
pha
jsr erase_ok_cancel_buttons
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::prompt_rect
pla
rts
.endproc
;;; ============================================================
;;; "DownLoad" dialog
.proc download_dialog_proc
ptr := $6
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda (ptr),y
cmp #1
bne :+
jmp do1
: cmp #2
bne :+
jmp do2
: cmp #3
bne :+
jmp do3
: cmp #4
bne else
jmp do4
else: copy #0, has_input_field_flag
jsr open_dialog_window
addr_call draw_dialog_title, desktop_aux::str_download
yax_call draw_dialog_label, 1, desktop_aux::str_copy_copying
yax_call draw_dialog_label, 2, desktop_aux::str_copy_from
yax_call draw_dialog_label, 3, desktop_aux::str_copy_to
yax_call draw_dialog_label, 4, desktop_aux::str_copy_remaining
rts
do1: ldy #1
copy16in (ptr),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::copy_file_count_pos
addr_call draw_text1, str_file_count
addr_call draw_text1, str_files
rts
do2: ldy #1
copy16in (ptr),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
jsr clear_target_file_rect
jsr copy_dialog_param_addr_to_ptr
ldy #3
lda (ptr),y
tax
iny
lda (ptr),y
sta ptr+1
stx ptr
jsr copy_name_to_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::current_target_file_pos
addr_call draw_text1, path_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::copy_file_count_pos2
addr_call draw_text1, str_file_count
rts
do3: jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
rts
do4: jsr bell
lda winfo_alert_dialog
jsr set_port_from_window_id
yax_call draw_dialog_label, 6, desktop_aux::str_ramcard_full
jsr draw_ok_button
: jsr prompt_input_loop
bmi :-
pha
jsr erase_ok_button
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::prompt_rect
pla
rts
.endproc
;;; ============================================================
;;; "Get Size" dialog
.proc get_size_dialog_proc
ptr := $6
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda (ptr),y
cmp #1
bne :+
jmp do1
: cmp #2
bne :+
jmp do2
: cmp #3
bne else
jmp do3
else: jsr open_dialog_window
addr_call draw_dialog_title, desktop_aux::str_size_title
yax_call draw_dialog_label, 1, desktop_aux::str_size_number
ldy #1
jsr draw_colon
yax_call draw_dialog_label, 2, desktop_aux::str_size_blocks
ldy #2
jsr draw_colon
rts
do1: ldy #1
lda (ptr),y
sta file_count
tax
iny
lda (ptr),y
sta ptr+1
stx ptr
ldy #0
copy16in (ptr),y, file_count
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
copy #165, dialog_label_pos
yax_call draw_dialog_label, 1, str_file_count
jsr copy_dialog_param_addr_to_ptr
ldy #3
lda (ptr),y
tax
iny
lda (ptr),y
sta ptr+1
stx ptr
ldy #0
copy16in (ptr),y, file_count
jsr compose_file_count_string
copy #165, dialog_label_pos
yax_call draw_dialog_label, 2, str_file_count
rts
do3: jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
rts
do2: lda winfo_alert_dialog
jsr set_port_from_window_id
jsr draw_ok_button
: jsr prompt_input_loop
bmi :-
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::clear_dialog_labels_rect
jsr erase_ok_button
return #0
.endproc
;;; ============================================================
;;; "Delete File" dialog
.proc delete_dialog_proc
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda ($06),y ; phase
cmp #DeleteDialogLifecycle::populate
bne :+
jmp do1
: cmp #DeleteDialogLifecycle::confirm
bne :+
jmp do2
: cmp #DeleteDialogLifecycle::show
bne :+
jmp do3
: cmp #DeleteDialogLifecycle::locked
bne :+
jmp do4
: cmp #DeleteDialogLifecycle::close
bne :+
jmp do5
;; DeleteDialogLifecycle::open or trash
: sta LAD1F
copy #0, has_input_field_flag
jsr open_dialog_window
addr_call draw_dialog_title, desktop_aux::str_delete_title
lda LAD1F
beq LAD20
yax_call draw_dialog_label, 4, desktop_aux::str_ok_empty
rts
LAD1F: .byte 0
LAD20: yax_call draw_dialog_label, 4, desktop_aux::str_delete_ok
rts
;; DeleteDialogLifecycle::populate
do1: ldy #1
copy16in ($06),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
lda LAD1F
bne LAD54
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::delete_file_count_pos
jmp LAD5D
LAD54: MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::delete_file_count_pos2
LAD5D: addr_call draw_text1, str_file_count
addr_call draw_text1, str_files
rts
;; DeleteDialogLifecycle::show
do3: ldy #1
copy16in ($06),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
jsr clear_target_file_rect
jsr copy_dialog_param_addr_to_ptr
ldy #3
lda ($06),y
tax
iny
lda ($06),y
sta $06+1
stx $06
jsr copy_name_to_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::current_target_file_pos
addr_call draw_text1, path_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::delete_remaining_count_pos
addr_call draw_text1, str_file_count
rts
;; DeleteDialogLifecycle::confirm
do2: lda winfo_alert_dialog
jsr set_port_from_window_id
jsr draw_ok_cancel_buttons
LADC4: jsr prompt_input_loop
bmi LADC4
bne LADF4
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::clear_dialog_labels_rect
jsr erase_ok_cancel_buttons
yax_call draw_dialog_label, 2, desktop_aux::str_file_colon
yax_call draw_dialog_label, 4, desktop_aux::str_delete_remaining
lda #$00
LADF4: rts
;; DeleteDialogLifecycle::close
do5: jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
rts
;; DeleteDialogLifecycle::locked
do4: lda winfo_alert_dialog
jsr set_port_from_window_id
yax_call draw_dialog_label, 6, desktop_aux::str_delete_locked_file
jsr draw_yes_no_all_cancel_buttons
LAE17: jsr prompt_input_loop
bmi LAE17
pha
jsr erase_yes_no_all_cancel_buttons
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy ; white
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::prompt_rect ; erase prompt
pla
rts
.endproc
;;; ============================================================
;;; "New Folder" dialog
.proc new_folder_dialog_proc
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda ($06),y
cmp #$80
bne LAE42
jmp LAE70
LAE42: cmp #$40
bne LAE49
jmp LAF16
LAE49: copy #$80, has_input_field_flag
jsr clear_path_buf2
lda #$00
jsr open_prompt_window
lda winfo_alert_dialog
jsr set_port_from_window_id
addr_call draw_dialog_title, desktop_aux::str_new_folder_title
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::FrameRect, name_input_rect
rts
LAE70: copy #$80, has_input_field_flag
copy #0, LD8E7
jsr clear_path_buf1
jsr copy_dialog_param_addr_to_ptr
ldy #1
copy16in ($06),y, $08
ldy #0
lda ($08),y
tay
LAE90: lda ($08),y
sta path_buf0,y
dey
bpl LAE90
lda winfo_alert_dialog
jsr set_port_from_window_id
yax_call draw_dialog_label, 2, desktop_aux::str_in_colon
copy #55, dialog_label_pos
yax_call draw_dialog_label, 2, path_buf0
copy #dialog_label_default_x, dialog_label_pos
yax_call draw_dialog_label, 4, desktop_aux::str_enter_folder_name
jsr draw_filename_prompt
LAEC6: jsr prompt_input_loop
bmi LAEC6
bne LAF16
jsr merge_path_buf1_path_buf2
lda path_buf1
beq LAEC6
cmp #16 ; max filename length
bcc LAEE1
LAED6: lda #ERR_NAME_TOO_LONG
jsr JT_SHOW_ALERT0
jsr draw_filename_prompt
jmp LAEC6
LAEE1: lda path_buf0
clc
adc path_buf1
clc
adc #$01
cmp #$41
bcs LAED6
inc path_buf0
ldx path_buf0
copy #'/', path_buf0,x
ldx path_buf0
ldy #0
LAEFF: inx
iny
copy path_buf1,y, path_buf0,x
cpy path_buf1
bne LAEFF
stx path_buf0
ldy #<path_buf0
ldx #>path_buf0
return #0
LAF16: jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
return #1
.endproc
;;; ============================================================
;;; "Get Info" dialog
.proc get_info_dialog_proc
ptr := $6
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda (ptr),y
bmi LAF34
jmp LAFB9
LAF34: copy #0, has_input_field_flag
lda (ptr),y
lsr a
lsr a
ror a
eor #$80
jsr open_prompt_window
lda winfo_alert_dialog
jsr set_port_from_window_id
addr_call draw_dialog_title, desktop_aux::str_info_title
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda (ptr),y
and #$7F
lsr a
ror a
sta LB01D
yax_call draw_dialog_label, 1, desktop_aux::str_info_name
bit LB01D
bmi LAF78
yax_call draw_dialog_label, 2, desktop_aux::str_info_locked
jmp LAF81
LAF78: yax_call draw_dialog_label, 2, desktop_aux::str_info_protected
LAF81: bit LB01D
bpl LAF92
yax_call draw_dialog_label, 3, desktop_aux::str_info_blocks
jmp LAF9B
LAF92: yax_call draw_dialog_label, 3, desktop_aux::str_info_size
LAF9B: yax_call draw_dialog_label, 4, desktop_aux::str_info_create
yax_call draw_dialog_label, 5, desktop_aux::str_info_mod
yax_call draw_dialog_label, 6, desktop_aux::str_info_type
jmp reset_grafport3a
LAFB9: lda winfo_alert_dialog
jsr set_port_from_window_id
jsr copy_dialog_param_addr_to_ptr
ldy #0
copy (ptr),y, row
tay
jsr draw_colon
copy #165, dialog_label_pos
jsr copy_dialog_param_addr_to_ptr
lda row
cmp #2
bne LAFF0
ldy #1
lda (ptr),y
beq :+
addr_jump LAFF8, desktop_aux::str_yes_label
: addr_jump LAFF8, desktop_aux::str_no_label
LAFF0: ldy #2
lda (ptr),y
tax
dey
lda (ptr),y
LAFF8: ldy row
jsr draw_dialog_label
lda row
cmp #6
beq :+
rts
: jsr prompt_input_loop
bmi :-
pha
jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer_with_flag
pla
rts
LB01D: .byte 0
row: .byte 0
.endproc
;;; ============================================================
;;; Draw ":" after dialog label
.proc draw_colon
copy #160, dialog_label_pos
addr_call draw_dialog_label, desktop_aux::str_colon
rts
.endproc
;;; ============================================================
;;; "Lock" dialog
.proc lock_dialog_proc
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda ($06),y
cmp #LockDialogLifecycle::populate
bne :+
jmp do1
: cmp #LockDialogLifecycle::loop
bne :+
jmp do2
: cmp #LockDialogLifecycle::operation
bne :+
jmp do3
: cmp #LockDialogLifecycle::close
bne :+
jmp do4
;; LockDialogLifecycle::open
: copy #0, has_input_field_flag
jsr open_dialog_window
addr_call draw_dialog_title, desktop_aux::str_lock_title
yax_call draw_dialog_label, 4, desktop_aux::str_lock_ok
rts
;; LockDialogLifecycle::populate
do1: ldy #1
copy16in ($06),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::lock_remaining_count_pos2
addr_call draw_text1, str_file_count
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::files_pos2
addr_call draw_text1, str_files
rts
;; LockDialogLifecycle::operation
do3: ldy #1
copy16in ($06),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
jsr clear_target_file_rect
jsr copy_dialog_param_addr_to_ptr
ldy #3
lda ($06),y
tax
iny
lda ($06),y
sta $06+1
stx $06
jsr copy_name_to_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::current_target_file_pos
addr_call draw_text1, path_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::lock_remaining_count_pos
addr_call draw_text1, str_file_count
rts
;; LockDialogLifecycle::loop
do2: lda winfo_alert_dialog
jsr set_port_from_window_id
jsr draw_ok_cancel_buttons
LB0FA: jsr prompt_input_loop
bmi LB0FA
bne LB139
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::clear_dialog_labels_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::ok_button_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::cancel_button_rect
yax_call draw_dialog_label, 2, desktop_aux::str_file_colon
yax_call draw_dialog_label, 4, desktop_aux::str_lock_remaining
lda #$00
LB139: rts
;; LockDialogLifecycle::close
do4: jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
rts
.endproc
;;; ============================================================
;;; "Unlock" dialog
.proc unlock_dialog_proc
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda ($06),y
cmp #LockDialogLifecycle::populate
bne :+
jmp do1
: cmp #LockDialogLifecycle::loop
bne :+
jmp do2
: cmp #LockDialogLifecycle::operation
bne :+
jmp do3
: cmp #LockDialogLifecycle::close
bne :+
jmp do4
;; LockDialogLifecycle::open
: copy #0, has_input_field_flag
jsr open_dialog_window
addr_call draw_dialog_title, desktop_aux::str_unlock_title
yax_call draw_dialog_label, 4, desktop_aux::str_unlock_ok
rts
;; LockDialogLifecycle::populate
do1: ldy #1
copy16in ($06),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::unlock_remaining_count_pos2
addr_call draw_text1, str_file_count
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::files_pos
addr_call draw_text1, str_files
rts
;; LockDialogLifecycle::operation
do3: ldy #1
copy16in ($06),y, file_count
jsr adjust_str_files_suffix
jsr compose_file_count_string
lda winfo_alert_dialog
jsr set_port_from_window_id
jsr clear_target_file_rect
jsr copy_dialog_param_addr_to_ptr
ldy #3
lda ($06),y
tax
iny
lda ($06),y
sta $06+1
stx $06
jsr copy_name_to_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::current_target_file_pos
addr_call draw_text1, path_buf0
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::unlock_remaining_count_pos
addr_call draw_text1, str_file_count
rts
;; LockDialogLifecycle::loop
do2: lda winfo_alert_dialog
jsr set_port_from_window_id
jsr draw_ok_cancel_buttons
LB218: jsr prompt_input_loop
bmi LB218
bne LB257
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::clear_dialog_labels_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::ok_button_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::cancel_button_rect
yax_call draw_dialog_label, 2, desktop_aux::str_file_colon
yax_call draw_dialog_label, 4, desktop_aux::str_unlock_remaining
lda #$00
LB257: rts
;; LockDialogLifecycle::close
do4: jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
rts
.endproc
;;; ============================================================
;;; "Rename" dialog
.proc rename_dialog_proc
jsr copy_dialog_param_addr_to_ptr
ldy #0
lda ($06),y
cmp #$80
bne LB276
jmp LB2ED
LB276: cmp #$40
bne LB27D
jmp LB313
LB27D: jsr clear_path_buf1
jsr copy_dialog_param_addr_to_ptr
copy #$80, has_input_field_flag
jsr clear_path_buf2
lda #$00
jsr open_prompt_window
lda winfo_alert_dialog
jsr set_port_from_window_id
addr_call draw_dialog_title, desktop_aux::str_rename_title
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::FrameRect, name_input_rect
yax_call draw_dialog_label, 2, desktop_aux::str_rename_old
copy #85, dialog_label_pos
jsr copy_dialog_param_addr_to_ptr
ldy #1
copy16in ($06),y, $08
ldy #0
lda ($08),y
tay
LB2CA: copy ($08),y, buf_filename,y
dey
bpl LB2CA
yax_call draw_dialog_label, 2, buf_filename
yax_call draw_dialog_label, 4, desktop_aux::str_rename_new
copy #0, path_buf1
jsr draw_filename_prompt
rts
LB2ED: copy16 #$8000, LD8E7
lda winfo_alert_dialog
jsr set_port_from_window_id
LB2FD: jsr prompt_input_loop
bmi LB2FD
bne LB313
lda path_buf1
beq LB2FD
jsr input_field_ip_end
ldy #<path_buf1
ldx #>path_buf1
return #0
LB313: jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
return #1
.endproc
;;; ============================================================
;;; "Warning!" dialog
;;; $6 ptr to message num
.proc warning_dialog_proc
ptr := $6
;; Create window
MGTK_RELAY_CALL MGTK::HideCursor
jsr open_alert_window
lda winfo_alert_dialog
jsr set_port_from_window_id
addr_call draw_dialog_title, desktop_aux::str_warning
MGTK_RELAY_CALL MGTK::ShowCursor
jsr copy_dialog_param_addr_to_ptr
;; Dig up message
ldy #0
lda (ptr),y
pha
bmi only_ok ; high bit set means no cancel
tax
lda warning_cancel_table,x
bne ok_and_cancel
only_ok: ; no cancel button
pla
and #$7F
pha
jsr draw_ok_button
jmp draw_string
ok_and_cancel: ; has cancel button
jsr draw_ok_cancel_buttons
draw_string:
;; First string
pla
pha
asl a ; * 2
asl a ; * 4, since there are two strings each
tay
lda warning_message_table+1,y
tax
lda warning_message_table,y
ldy #3 ; row
jsr draw_dialog_label
;; Second string
pla
asl a
asl a
tay
lda warning_message_table+2+1,y
tax
lda warning_message_table+2,y
ldy #4 ; row
jsr draw_dialog_label
;; Input loop
: jsr prompt_input_loop
bmi :-
pha
jsr reset_grafport3a
MGTK_RELAY_CALL MGTK::CloseWindow, winfo_alert_dialog
jsr set_cursor_pointer
pla
rts
;; high bit set if "cancel" should be an option
warning_cancel_table:
.byte $80,$00,$00,$80,$00,$00,$80
warning_message_table:
.addr desktop_aux::str_insert_system_disk,desktop_aux::str_1_space
.addr desktop_aux::str_selector_list_full,desktop_aux::str_before_new_entries
.addr desktop_aux::str_selector_list_full,desktop_aux::str_before_new_entries
.addr desktop_aux::str_window_must_be_closed,desktop_aux::str_1_space
.addr desktop_aux::str_window_must_be_closed,desktop_aux::str_1_space
.addr desktop_aux::str_too_many_windows,desktop_aux::str_1_space
.addr desktop_aux::str_save_selector_list,desktop_aux::str_on_system_disk
.endproc
warning_msg_insert_system_disk = 0
warning_msg_selector_list_full = 1
warning_msg_selector_list_full2 = 2
warning_msg_window_must_be_closed = 3
warning_msg_window_must_be_closed2 = 4
warning_msg_too_many_windows = 5
warning_msg_save_selector_list = 6
;;; ============================================================
.proc copy_dialog_param_addr_to_ptr
copy16 dialog_param_addr, $06
rts
.endproc
;;; ============================================================
.proc set_cursor_pointer_with_flag
bit cursor_ip_flag
bpl :+
jsr set_cursor_pointer
copy #0, cursor_ip_flag
: rts
.endproc
.proc set_cursor_insertion_point_with_flag
bit cursor_ip_flag
bmi :+
jsr set_cursor_insertion_point
copy #$80, cursor_ip_flag
: rts
.endproc
cursor_ip_flag: ; high bit set if IP, clear if pointer
.byte 0
;;; ============================================================
;;;
;;; Routines beyond this point are used by overlays
;;;
;;; ============================================================
.assert * >= $A000, error, "Routine used by overlays in overlay zone"
.proc bell
sta ALTZPOFF
sta ROMIN2
jsr BELL1
sta ALTZPON
lda LCBANK1
lda LCBANK1
rts
.endproc
.proc set_cursor_watch
MGTK_RELAY_CALL MGTK::HideCursor
MGTK_RELAY_CALL MGTK::SetCursor, watch_cursor
MGTK_RELAY_CALL MGTK::ShowCursor
rts
.endproc
.proc set_cursor_pointer
MGTK_RELAY_CALL MGTK::HideCursor
MGTK_RELAY_CALL MGTK::SetCursor, pointer_cursor
MGTK_RELAY_CALL MGTK::ShowCursor
rts
.endproc
.proc set_cursor_insertion_point
MGTK_RELAY_CALL MGTK::HideCursor
MGTK_RELAY_CALL MGTK::SetCursor, insertion_point_cursor
MGTK_RELAY_CALL MGTK::ShowCursor
rts
.endproc
set_penmode_xor2:
MGTK_RELAY_CALL MGTK::SetPenMode, penXOR
rts
;;; ============================================================
;;; Double Click Detection
;;; Returns with A=0 if double click, A=$FF otherwise.
.proc detect_double_click
double_click_deltax = 5
double_click_deltay = 4
;; Stash initial coords
ldx #3
: copy event_coords,x, coords,x
sta saved_event_coords,x ; for double-click in windows
dex
bpl :-
lda #0
sta counter+1
lda machine_type ; Speed of mouse driver? ($96=IIe,$FA=IIc,$FD=IIgs)
asl a ; * 2
rol counter+1 ; So IIe = $12C, IIc = $1F4, IIgs = $1FA
sta counter
;; Decrement counter, bail if time delta exceeded
loop: dec counter
bne :+
dec counter+1
bne exit
: MGTK_RELAY_CALL MGTK::PeekEvent, event_params
;; Check coords, bail if pixel delta exceeded
jsr check_delta
bmi exit ; moved past delta; no double-click
lda event_kind
cmp #MGTK::EventKind::no_event
beq loop
cmp #MGTK::EventKind::drag
beq loop
cmp #MGTK::EventKind::button_up
bne :+
MGTK_RELAY_CALL MGTK::GetEvent, event_params
jmp loop
: cmp #MGTK::EventKind::button_down
beq :+
cmp #MGTK::EventKind::apple_key ; modified-click
bne exit
: MGTK_RELAY_CALL MGTK::GetEvent, event_params
return #0 ; double-click
exit: return #$FF ; not double-click
;; Is the new coord within range of the old coord?
.proc check_delta
;; compute x delta
lda event_xcoord
sec
sbc xcoord
sta delta
lda event_xcoord+1
sbc xcoord+1
bpl :+
;; is -delta < x < 0 ?
lda delta
cmp #AS_BYTE(-double_click_deltax)
bcs check_y
fail: return #$FF
;; is 0 < x < delta ?
: lda delta
cmp #double_click_deltax
bcs fail
;; compute y delta
check_y:
lda event_ycoord
sec
sbc ycoord
sta delta
lda event_ycoord+1
sbc ycoord+1
bpl :+
;; is -delta < y < 0 ?
lda delta
cmp #AS_BYTE(-double_click_deltay)
bcs ok
;; is 0 < y < delta ?
: lda delta
cmp #double_click_deltay
bcs fail
ok: return #0
.endproc
counter:
.word 0
coords:
xcoord: .word 0
ycoord: .word 0
delta: .byte 0
.endproc
;;; ============================================================
.proc open_prompt_window
sta LD8E7
jsr open_dialog_window
bit LD8E7
bvc :+
jsr draw_yes_no_all_cancel_buttons
jmp no_ok
: MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::ok_button_rect
jsr draw_ok_label
no_ok: bit LD8E7
bmi done
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::cancel_button_rect
jsr draw_cancel_label
done: jmp reset_grafport3a
.endproc
;;; ============================================================
.proc open_dialog_window
MGTK_RELAY_CALL MGTK::OpenWindow, winfo_alert_dialog
lda winfo_alert_dialog
jsr set_port_from_window_id
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::confirm_dialog_outer_rect
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::confirm_dialog_inner_rect
rts
.endproc
;;; ============================================================
.proc open_alert_window
MGTK_RELAY_CALL MGTK::OpenWindow, winfo_alert_dialog
lda winfo_alert_dialog
jsr set_port_from_window_id
jsr set_fill_white
MGTK_RELAY_CALL MGTK::PaintBits, alert_bitmap2_params
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::confirm_dialog_outer_rect
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::confirm_dialog_inner_rect
rts
.endproc
;;; ============================================================
;;; Draw dialog label.
;;; A,X has pointer to DrawText params block
;;; Y has row number (1, 2, ... ) with high bit to center it
DDL_CENTER = $80
.proc draw_dialog_label
textwidth_params := $8
textptr := $8
textlen := $A
result := $B
ptr := $6
stx ptr+1
sta ptr
tya
bmi :+
jmp skip
;; Compute text width and center it
: and #$7F ; strip "center?" flag
pha
add16 ptr, #1, textptr
jsr load_aux_from_ptr
sta textlen
MGTK_RELAY_CALL MGTK::TextWidth, textwidth_params
lsr16 result
sub16 #200, result, dialog_label_pos
pla
;; y = base + desktop_aux::dialog_label_height * line
skip: ldx #0
ldy #desktop_aux::dialog_label_height
jsr Multiply_16_8_16
stax dialog_label_pos::ycoord
add16 dialog_label_pos::ycoord, dialog_label_base_pos::ycoord, dialog_label_pos::ycoord
MGTK_RELAY_CALL MGTK::MoveTo, dialog_label_pos
addr_call_indirect draw_text1, ptr
ldx dialog_label_pos
copy #dialog_label_default_x,dialog_label_pos::xcoord ; restore original x coord
rts
.endproc
;;; ============================================================
draw_ok_label:
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::ok_label_pos
addr_call draw_text1, desktop_aux::str_ok_label
rts
draw_cancel_label:
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::cancel_label_pos
addr_call draw_text1, desktop_aux::str_cancel_label
rts
draw_yes_label:
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::yes_label_pos
addr_call draw_text1, desktop_aux::str_yes_label
rts
draw_no_label:
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::no_label_pos
addr_call draw_text1, desktop_aux::str_no_label
rts
draw_all_label:
MGTK_RELAY_CALL MGTK::MoveTo, desktop_aux::all_label_pos
addr_call draw_text1, desktop_aux::str_all_label
rts
draw_yes_no_all_cancel_buttons:
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::yes_button_rect
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::no_button_rect
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::all_button_rect
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::cancel_button_rect
jsr draw_yes_label
jsr draw_no_label
jsr draw_all_label
jsr draw_cancel_label
copy #$40, LD8E7
rts
erase_yes_no_all_cancel_buttons:
jsr set_fill_white
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::yes_button_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::no_button_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::all_button_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::cancel_button_rect
rts
draw_ok_cancel_buttons:
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::ok_button_rect
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::cancel_button_rect
jsr draw_ok_label
jsr draw_cancel_label
copy #$00, LD8E7
rts
erase_ok_cancel_buttons:
jsr set_fill_white
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::ok_button_rect
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::cancel_button_rect
rts
draw_ok_button:
jsr set_penmode_xor2
MGTK_RELAY_CALL MGTK::FrameRect, desktop_aux::ok_button_rect
jsr draw_ok_label
copy #$80, LD8E7
rts
erase_ok_button:
jsr set_fill_white
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::ok_button_rect
rts
;;; ============================================================
.proc draw_text1
params := $6
textptr := $6
textlen := $8
stax textptr
jsr load_aux_from_ptr
beq done
sta textlen
inc16 textptr
MGTK_RELAY_CALL MGTK::DrawText, params
done: rts
.endproc
;;; ============================================================
.proc draw_dialog_title
str := $6
str_data := $6
str_len := $8
str_width := $9
stax str ; input is length-prefixed string
jsr load_aux_from_ptr
sta str_len
inc str_data ; point past length byte
bne :+
inc str_data+1
: MGTK_RELAY_CALL MGTK::TextWidth, str
lsr16 str_width ; divide by two
lda #>400 ; center within 400px
sta hi
lda #<400
lsr hi ; divide by two
ror a
sec
sbc str_width
sta pos_dialog_title::xcoord
lda hi
sbc str_width+1
sta pos_dialog_title::xcoord+1
MGTK_RELAY_CALL MGTK::MoveTo, pos_dialog_title
MGTK_RELAY_CALL MGTK::DrawText, str
rts
hi: .byte 0
.endproc
;;; ============================================================
;;; Adjust filename case, using GS/OS bits or heuristics
;;; http://www.1000bit.it/support/manuali/apple/technotes/gsos/tn.gsos.08.html
;;; adjust_fileeentry_case:
;;; Input: A,X points at FileEntry structure.
;;;
;;; adjust_volname_case:
;;; Input: A,X points at ON_LINE result (e.g. 'MY.DISK', length + 15 chars)
.proc adjust_case_impl
volpath := $810
volbuf := $820
DEFINE_OPEN_PARAMS volname_open_params, volpath, $1000
DEFINE_READ_PARAMS volname_read_params, volbuf, .sizeof(VolumeDirectoryHeader)
DEFINE_CLOSE_PARAMS volname_close_params
ptr := $A
;;; --------------------------------------------------
;;; Called with volume name. Convert to path, load
;;; VolumeDirectoryHeader, use bytes $1A/$1B
vol_name:
stax ptr
;; Convert volume name to a path
ldy #0
lda (ptr),y
sta volpath
tay
: lda (ptr),y
sta volpath+1,y
dey
bne :-
lda #'/'
sta volpath+1
inc volpath
MLI_RELAY_CALL OPEN, volname_open_params
bne fallback
lda volname_open_params::ref_num
sta volname_read_params::ref_num
sta volname_close_params::ref_num
MLI_RELAY_CALL READ, volname_read_params
bne fallback
MLI_RELAY_CALL CLOSE, volname_close_params
copy16 volbuf + $1A, version_bytes
jmp common
;;; --------------------------------------------------
;;; Called with FileEntry. Copy version bytes directly.
file_entry:
stax ptr
.assert FileEntry::file_name = 1, error, "bad assumptions in structure"
ldy #FileEntry::version
copy16in (ptr),y, version_bytes
;; fall through
common:
asl16 version_bytes
bcs apply_bits ; High bit set = GS/OS case bits present
;;; --------------------------------------------------
;;; GS/OS bits are not present; apply heuristics
fallback:
ldy #0
lda (ptr),y
and #NAME_LENGTH_MASK
beq done
;; Walk backwards through string. At char N, check char N-1
;; to see if it is a '.'. If it isn't, and char N is a letter,
;; lower-case it.
tay
loop: dey
beq done
bpl :+
done: rts
: lda (ptr),y
cmp #'.'
bne check_alpha
dey
bpl loop ; always
check_alpha:
iny
lda (ptr),y
cmp #'A'
bcc :+
ora #AS_BYTE(~CASE_MASK)
sta (ptr),y
: dey
bpl loop ; always
;;; --------------------------------------------------
;;; GS/OS bits are present - apply to recase string.
apply_bits:
ldy #1
bloop: asl16 version_bytes
bcc :+
lda (ptr),y
ora #AS_BYTE(~CASE_MASK)
sta (ptr),y
: iny
cpy #16
bcc bloop
rts
version_bytes:
.word 0
.endproc
adjust_fileentry_case := adjust_case_impl::file_entry
adjust_volname_case := adjust_case_impl::vol_name
;;; ============================================================
.proc set_port_from_window_id
sta getwinport_params2::window_id
MGTK_RELAY_CALL MGTK::GetWinPort, getwinport_params2
MGTK_RELAY_CALL MGTK::SetPort, grafport2
rts
.endproc
;;; ============================================================
;;; Event loop during button press - handle inverting
;;; the text as mouse is dragged in/out, report final
;;; click (A as passed) / cancel (A is negative)
button_loop_ok:
lda #PromptResult::ok
jmp button_event_loop
button_loop_cancel:
lda #PromptResult::cancel
jmp button_event_loop
button_loop_yes:
lda #PromptResult::yes
jmp button_event_loop
button_loop_no:
lda #PromptResult::no
jmp button_event_loop
button_loop_all:
lda #PromptResult::all
jmp button_event_loop
.proc button_event_loop
;; Configure test and fill procs
pha
asl a
asl a
tax
copy16 test_fill_button_proc_table,x, test_button_proc_addr
copy16 test_fill_button_proc_table+2,x, fill_button_proc_addr
pla
jmp event_loop
test_fill_button_proc_table:
.addr test_ok_button,fill_ok_button
.addr test_cancel_button,fill_cancel_button
.addr test_yes_button,fill_yes_button
.addr test_no_button,fill_no_button
.addr test_all_button,fill_all_button
test_ok_button:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::ok_button_rect
rts
test_cancel_button:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::cancel_button_rect
rts
test_yes_button:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::yes_button_rect
rts
test_no_button:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::no_button_rect
rts
test_all_button:
MGTK_RELAY_CALL MGTK::InRect, desktop_aux::all_button_rect
rts
fill_ok_button:
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::ok_button_rect
rts
fill_cancel_button:
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::cancel_button_rect
rts
fill_yes_button:
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::yes_button_rect
rts
fill_no_button:
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::no_button_rect
rts
fill_all_button:
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::all_button_rect
rts
test_proc: jmp (test_button_proc_addr)
fill_proc: jmp (fill_button_proc_addr)
test_button_proc_addr: .addr 0
fill_button_proc_addr: .addr 0
event_loop:
sta click_result
copy #0, down_flag
loop: MGTK_RELAY_CALL MGTK::GetEvent, event_params
lda event_kind
cmp #MGTK::EventKind::button_up
beq exit
lda winfo_alert_dialog
sta event_params
MGTK_RELAY_CALL MGTK::ScreenToWindow, screentowindow_params
MGTK_RELAY_CALL MGTK::MoveTo, screentowindow_windowx
jsr test_proc
cmp #MGTK::inrect_inside
beq inside
lda down_flag ; outside but was inside?
beq invert
jmp loop
inside: lda down_flag ; already depressed?
bne invert
jmp loop
invert: jsr set_penmode_xor2
jsr fill_proc
lda down_flag
clc
adc #$80
sta down_flag
jmp loop
exit: lda down_flag ; was depressed?
beq clicked
return #$FF ; hi bit = cancelled
clicked:
jsr fill_proc ; invert one last time
return click_result ; grab expected result
down_flag:
.byte 0
click_result:
.byte 0
.endproc
.proc noop
rts
.endproc
;;; ============================================================
.proc redraw_prompt_insertion_point
point := $6
xcoord := $6
ycoord := $8
jsr measure_path_buf1
stax xcoord
copy16 name_input_textpos::ycoord, ycoord
MGTK_RELAY_CALL MGTK::MoveTo, point
MGTK_RELAY_CALL MGTK::SetPortBits, name_input_mapinfo
bit prompt_ip_flag
bpl set_flag
clear_flag:
MGTK_RELAY_CALL MGTK::SetTextBG, desktop_aux::textbg_black
copy #0, prompt_ip_flag
beq draw ; always
set_flag:
MGTK_RELAY_CALL MGTK::SetTextBG, desktop_aux::textbg_white
copy #$FF, prompt_ip_flag
drawtext_params := $6
textptr := $6
textlen := $8
draw: copy16 #str_insertion_point+1, textptr
lda str_insertion_point
sta textlen
MGTK_RELAY_CALL MGTK::DrawText, drawtext_params
MGTK_RELAY_CALL MGTK::SetTextBG, desktop_aux::textbg_white
lda winfo_alert_dialog
jsr set_port_from_window_id
rts
.endproc
;;; ============================================================
.proc draw_filename_prompt
lda winfo_alert_dialog
jsr set_port_from_window_id
jsr set_fill_white
MGTK_RELAY_CALL MGTK::PaintRect, name_input_rect
MGTK_RELAY_CALL MGTK::SetPenMode, penXOR
MGTK_RELAY_CALL MGTK::FrameRect, name_input_rect
MGTK_RELAY_CALL MGTK::MoveTo, name_input_textpos
MGTK_RELAY_CALL MGTK::SetPortBits, name_input_mapinfo
addr_call draw_text1, path_buf1
addr_call draw_text1, path_buf2
addr_call draw_text1, str_2_spaces
lda winfo_alert_dialog
jsr set_port_from_window_id
done: rts
.endproc
;;; ============================================================
.proc LB9B8
ptr := $6
textwidth_params := $6
textptr := $6
textlen := $8
result := $9
click_coords := screentowindow_windowx
;; Mouse coords to window coords; is click inside name field?
MGTK_RELAY_CALL MGTK::ScreenToWindow, screentowindow_params
MGTK_RELAY_CALL MGTK::MoveTo, click_coords
MGTK_RELAY_CALL MGTK::InRect, name_input_rect
cmp #MGTK::inrect_inside
beq :+
rts
;; Is it to the right of the text?
: jsr measure_path_buf1
width := $6
stax width
cmp16 click_coords, width
bcs to_right
jmp within_text
;;; --------------------------------------------------
;; Click is to the right of the text
.proc to_right
jsr measure_path_buf1
stax buf1_width
ldx path_buf2
inx
copy #' ', path_buf2,x
inc path_buf2
copy16 #path_buf2, textptr
lda path_buf2
sta ptr+2
LBA10: MGTK_RELAY_CALL MGTK::TextWidth, textwidth_params
add16 result, buf1_width, result
cmp16 result, click_coords
bcc LBA42
dec textlen
lda textlen
cmp #1
bne LBA10
dec path_buf2
jmp draw_text
LBA42:
lda textlen
cmp path_buf2
bcc LBA4F
dec path_buf2
jmp input_field_ip_end
LBA4F: ldx #2
ldy path_buf1
iny
LBA55: lda path_buf2,x
sta path_buf1,y
cpx textlen
beq LBA64
iny
inx
jmp LBA55
LBA64: sty path_buf1
ldy #2
ldx textlen
inx
LBA6C: lda path_buf2,x
sta path_buf2,y
cpx path_buf2
beq LBA7C
iny
inx
jmp LBA6C
LBA7C: dey
sty path_buf2
jmp draw_text
.endproc
;;; --------------------------------------------------
;; Click within text - loop to find where in the
;; name to split the string.
.proc within_text
copy16 #path_buf1, textptr
lda path_buf1
sta textlen
: MGTK_RELAY_CALL MGTK::TextWidth, textwidth_params
add16 result, name_input_textpos::xcoord, result
cmp16 result, click_coords
bcc :+
dec textlen
lda textlen
cmp #1
bcs :-
jmp input_field_ip_start
;; Copy the text to the right of the click to split_buf
: inc textlen
ldy #0
ldx textlen
: cpx path_buf1
beq :+
inx
iny
lda path_buf1,x
sta split_buf+1,y
jmp :-
:
;; Copy it (again) into path_buf2
iny
sty split_buf
ldx #1
ldy split_buf
: cpx path_buf2
beq :+
inx
iny
lda path_buf2,x
sta split_buf,y
jmp :-
:
sty split_buf
lda str_insertion_point+1
sta split_buf+1
LBAF7: lda split_buf,y
sta path_buf2,y
dey
bpl LBAF7
lda textlen
sta path_buf1
;; fall through
.endproc
draw_text:
jsr draw_filename_prompt
rts
buf1_width:
.word 0
.endproc
;;; ============================================================
.proc LBB0B
sta param
lda path_buf1
clc
adc path_buf2
cmp #$10
bcc :+
rts
point := $6
xcoord := $6
ycoord := $8
: lda param
ldx path_buf1
inx
sta path_buf1,x
sta str_1_char+1
jsr measure_path_buf1
inc path_buf1
stax xcoord
copy16 name_input_textpos::ycoord, ycoord
MGTK_RELAY_CALL MGTK::MoveTo, point
MGTK_RELAY_CALL MGTK::SetPortBits, name_input_mapinfo
addr_call draw_text1, str_1_char
addr_call draw_text1, path_buf2
lda winfo_alert_dialog
jsr set_port_from_window_id
rts
param: .byte 0
.endproc
;;; ============================================================
.proc LBB63
lda path_buf1
bne :+
rts
point := $6
xcoord := $6
ycoord := $8
: dec path_buf1
jsr measure_path_buf1
stax xcoord
copy16 name_input_textpos::ycoord, ycoord
MGTK_RELAY_CALL MGTK::MoveTo, point
MGTK_RELAY_CALL MGTK::SetPortBits, name_input_mapinfo
addr_call draw_text1, path_buf2
addr_call draw_text1, str_2_spaces
lda winfo_alert_dialog
jsr set_port_from_window_id
rts
.endproc
;;; ============================================================
;;; Move IP one character left.
.proc input_field_ip_left
;; Any characters to left of IP?
lda path_buf1
bne :+
rts
point := $6
xcoord := $6
ycoord := $8
: ldx path_buf2
cpx #1
beq finish
;; Shift right up by a character.
loop: lda path_buf2,x
sta path_buf2+1,x
dex
cpx #1
bne loop
;; Copy character left to right and adjust lengths.
finish: ldx path_buf1
lda path_buf1,x
sta path_buf2+2
dec path_buf1
inc path_buf2
;; Redraw (just the right part)
jsr measure_path_buf1
stax xcoord
copy16 name_input_textpos::ycoord, ycoord
MGTK_RELAY_CALL MGTK::MoveTo, point
MGTK_RELAY_CALL MGTK::SetPortBits, name_input_mapinfo
addr_call draw_text1, path_buf2
addr_call draw_text1, str_2_spaces
lda winfo_alert_dialog
jsr set_port_from_window_id
rts
.endproc
;;; ============================================================
;;; Move IP one character right.
.proc input_field_ip_right
;; Any characters to right of IP?
lda path_buf2
cmp #2
bcs :+
rts
;; Copy char from right to left and adjust lengths.
: ldx path_buf1
inx
lda path_buf2+2
sta path_buf1,x
inc path_buf1
ldx path_buf2
cpx #3
bcc finish
;; Shift right string down.
ldx #2
loop: lda path_buf2+1,x
sta path_buf2,x
inx
cpx path_buf2
bne loop
;; Redraw (the whole thing)
finish: dec path_buf2
MGTK_RELAY_CALL MGTK::MoveTo, name_input_textpos
MGTK_RELAY_CALL MGTK::SetPortBits, name_input_mapinfo
addr_call draw_text1, path_buf1
addr_call draw_text1, path_buf2
addr_call draw_text1, str_2_spaces
lda winfo_alert_dialog
jsr set_port_from_window_id
rts
.endproc
;;; ============================================================
;;; Move IP to start of input field.
.proc input_field_ip_start
;; Any characters to left of IP?
lda path_buf1
bne :+
rts
;; Any characters to right of IP?
: ldx path_buf2
cpx #1
beq move
;; Preserve right characters up to make room.
;; TODO: Why not just shift them up???
loop1: lda path_buf2,x
sta split_buf-1,x
dex
cpx #1
bne loop1
ldx path_buf2
;; Move characters left to right
move: dex
stx split_buf
ldx path_buf1
loop2: lda path_buf1,x
sta path_buf2+1,x
dex
bne loop2
;; Adjust lengths.
lda str_insertion_point+1
sta path_buf2+1
inc path_buf1
lda path_buf1
sta path_buf2
lda path_buf1
clc
adc split_buf
tay
pha
;; Append right right characters again if needed.
ldx split_buf
beq finish
loop3: lda split_buf,x
sta path_buf2,y
dex
dey
cpy path_buf2
bne loop3
finish: pla
sta path_buf2
copy #0, path_buf1
MGTK_RELAY_CALL MGTK::MoveTo, name_input_textpos ; Seems unnecessary???
jsr draw_filename_prompt
rts
.endproc
;;; ============================================================
.proc merge_path_buf1_path_buf2
lda path_buf2
cmp #2
bcc done
;; Compute new path_buf1 length
ldx path_buf2
dex
txa
clc
adc path_buf1
pha
;; Copy chars from path_buf2 to path_buf1
tay
ldx path_buf2
loop: lda path_buf2,x
sta path_buf1,y
dex
dey
cpy path_buf1
bne loop
;; Finish up, shrinking path_buf2 to just an insertion point
pla
sta path_buf1
copy #1, path_buf2
done: rts
.endproc
;;; ============================================================
;;; Move IP to end of input field.
.proc input_field_ip_end
jsr merge_path_buf1_path_buf2
MGTK_RELAY_CALL MGTK::MoveTo, name_input_textpos ; Seems unnecessary???
jsr draw_filename_prompt
rts
.endproc
;;; ============================================================
;;; Compute width of path_buf1, offset name_input_textpos, return x coord in (A,X)
.proc measure_path_buf1
textwidth_params := $6
textptr := $6
textlen := $8
result := $9
copy16 #path_buf1+1, textptr
lda path_buf1
sta textlen
bne :+
ldax name_input_textpos::xcoord
rts
: MGTK_RELAY_CALL MGTK::TextWidth, textwidth_params
lda result
clc
adc name_input_textpos::xcoord
tay
lda result+1
adc name_input_textpos::xcoord+1
tax
tya
rts
.endproc
;;; ============================================================
.proc clear_path_buf2
copy #1, path_buf2 ; length
copy str_insertion_point+1, path_buf2+1 ; IP character
rts
.endproc
.proc clear_path_buf1
copy #0, path_buf1 ; length
rts
.endproc
;;; ============================================================
.proc load_aux_from_ptr
target := $20
;; Backup copy of $20
COPY_BYTES proc_len+1, target, saved_proc_buf
;; Overwrite with proc
ldx #proc_len
: lda proc,x
sta target,x
dex
bpl :-
;; Call proc
jsr target
pha
;; Restore copy
COPY_BYTES proc_len+1, saved_proc_buf, target
pla
rts
.proc proc
sta RAMRDON
sta RAMWRTON
ldy #0
lda ($06),y
sta RAMRDOFF
sta RAMWRTOFF
rts
.endproc
proc_len = .sizeof(proc)
saved_proc_buf:
.res 20, 0
.endproc
;;; ============================================================
;;; Make str_files singular or plural based on file_count
.proc adjust_str_files_suffix
ldx str_files
lda file_count+1 ; > 255?
bne :+
lda file_count
cmp #2 ; > 2?
bcs :+
copy #' ', str_files,x ; singular
rts
: copy #'s', str_files,x ; plural
rts
.endproc
;;; ============================================================
.proc compose_file_count_string
ldax file_count
jsr int_to_string
ldy #1
copy #' ', str_file_count,y
ldx #0
: cpx str_from_int
beq :+
inx
iny
copy str_from_int,x, str_file_count,y
bne :-
: iny
copy #' ', str_file_count,y
sty str_file_count
rts
.endproc
;;; ============================================================
.proc copy_name_to_buf0
ptr := $6
ldy #0
lda (ptr),y
tay
: lda (ptr),y
sta path_buf0,y
dey
bpl :-
rts
.endproc
.proc copy_name_to_buf1
ptr := $6
ldy #0
lda (ptr),y
tay
: lda (ptr),y
sta path_buf1,y
dey
bpl :-
rts
.endproc
;;; ============================================================
clear_target_file_rect:
jsr set_fill_white
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::current_target_file_rect
rts
clear_dest_file_rect:
jsr set_fill_white
MGTK_RELAY_CALL MGTK::PaintRect, desktop_aux::current_dest_file_rect
rts
set_fill_white:
MGTK_RELAY_CALL MGTK::SetPenMode, pencopy
rts
reset_grafport3a:
MGTK_RELAY_CALL MGTK::InitPort, grafport3
MGTK_RELAY_CALL MGTK::SetPort, grafport3
rts
;;; ============================================================
str_preview_fot:
PASCAL_STRING "Preview/show.image.file"
str_preview_fnt:
PASCAL_STRING "Preview/show.font.file"
str_preview_txt:
PASCAL_STRING "Preview/show.text.file"
;;; ============================================================
PAD_TO $BF00
.endproc ; desktop_main
desktop_main_pop_pointers := desktop_main::pop_pointers
desktop_main_push_pointers := desktop_main::push_pointers
;;; ============================================================
;;; Segment loaded into MAIN $800-$FFF
;;; ============================================================
;;; Init sequence - machine identification, etc
.proc desktop_800
.org $800
start:
;;; ============================================================
;;; Set the reset vector to cold start
.scope hook_reset_vector
;; Main hook
lda #<desktop_main::reset_handler
sta RESETVEC
lda #>desktop_main::reset_handler
sta RESETVEC+1
eor #$A5
sta RESETVEC+2
.endscope
;;; ============================================================
;;; Detect Machine Type
;;; NOTE: Starts with ROM paged in, exits with LCBANK1 paged in.
.scope machine_type
;; See Apple II Miscellaneous #7: Apple II Family Identification
;; First, detect IIgs
sec ; Follow detection protocol
jsr ID_BYTE_FE1F ; RTS on pre-IIgs
bcs :+ ; carry clear = IIgs
copy #$80, is_iigs_flag
:
;; Now stash the bytes we need
copy ID_BYTE_FBB3, id_FBB3 ; $06 = IIe or later
copy ID_BYTE_FBC0, id_FBC0 ; $00 = IIc or later
copy ID_BYTE_FBBF, id_FBBF ; IIc ROM version (IIc+ = $05)
copy ID_BYTE_FB1E, id_FB1E ; $AC = Laser 128
;; ... and page in LCBANK1
sta ALTZPON
lda LCBANK1
lda LCBANK1
sta SET80COL
;; Ensure we're on a IIe or later
lda id_FBB3
cmp #$06 ; Ensure a IIe or later
beq :+
brk ; Otherwise (][, ][+, ///), just crash
;; State needed by MGTK
: copy id_FBB3, startdesktop_params::machine
copy id_FBC0, startdesktop_params::subid
;; Identify machine type (double-click timer, other flags)
lda id_FBC0
beq is_iic ; $FBC0 = $00 -> is IIc or IIc+
bit is_iigs_flag
bmi is_iigs
;; IIe (or IIe Option Card, or Laser 128)
copy #$96, machine_type ; IIe
lda id_FB1E ; Is it a Laser 128?
cmp #$AC
bne :+
copy #$80, is_laser128_flag
copy #$FD, machine_type ; Assume accelerated?
: jmp end
;; IIgs
is_iigs:
copy #$FD, machine_type ; IIgs
jmp end
;; IIc or IIc+
is_iic: copy #$FA, machine_type ; IIc
lda id_FBBF ; ROM version
cmp #$05 ; IIc Plus = $05
bne :+
copy #$80, is_iic_plus_flag
: jmp end
id_FB1E: .byte 0
id_FBB3: .byte 0
id_FBC0: .byte 0
id_FBBF: .byte 0
end:
.endscope
;;; ============================================================
;;; Back up DEVLST
.scope
;; Make a copy of the original device list
ldx DEVCNT
inx
: lda DEVLST-1,x
sta devlst_backup,x
dex
bpl :-
;; fall through
.endscope
;;; ============================================================
;;; Detach aux-memory RAM Disk
.scope
;; Look for /RAM
ldx DEVCNT
: lda DEVLST,x
;; BUG: ProDOS Tech Note #21 says $B3,$B7,$BB or $BF could be /RAM
cmp #(1<<7 | 3<<4 | DT_RAM) ; unit_num for /RAM is Slot 3, Drive 2
beq found_ram
dex
bpl :-
bmi end
found_ram:
jsr remove_device
;; fall through
end:
.endscope
;;; ============================================================
;;; Initialize MGTK
.scope
MGTK_RELAY_CALL MGTK::StartDeskTop, startdesktop_params
jsr desktop_main::set_mono_mode
MGTK_RELAY_CALL MGTK::SetMenu, splash_menu
MGTK_RELAY_CALL MGTK::SetCursor, watch_cursor
MGTK_RELAY_CALL MGTK::ShowCursor
;; fall through
.endscope
;;; ============================================================
;;; Populate icon_entries table
.scope
ptr := $6
jsr desktop_main::push_pointers
copy16 #icon_entries, ptr
ldx #1
loop: cpx #max_icon_count
bne :+
jsr desktop_main::pop_pointers
jmp end
: txa
pha
asl a
tax
copy16 ptr, icon_entry_address_table,x
pla
pha
ldy #0
sta (ptr),y
iny
copy #0, (ptr),y
lda ptr
clc
adc #.sizeof(IconEntry)
sta ptr
bcc :+
inc ptr+1
: pla
tax
inx
jmp loop
end:
.endscope
;;; ============================================================
;;; Zero the window icon tables
.scope
sta RAMWRTON
lda #$00
tax
loop: sta WINDOW_ICON_TABLES + $400,x ; window 8, icon use map
sta WINDOW_ICON_TABLES + $300,x ; window 6, 7
sta WINDOW_ICON_TABLES + $200,x ; window 4, 5
sta WINDOW_ICON_TABLES + $100,x ; window 2, 3
sta WINDOW_ICON_TABLES + $000,x ; window 0, 1 (0=desktop)
inx
bne loop
sta RAMWRTOFF
jmp create_trash_icon
.endscope
;;; ============================================================
trash_name: PASCAL_STRING " Trash "
.proc create_trash_icon
ptr := $6
copy #0, cached_window_id
lda #1
sta cached_window_icon_count
sta icon_count
jsr AllocateIcon
sta trash_icon_num
sta cached_window_icon_list
jsr desktop_main::icon_entry_lookup
stax ptr
ldy #IconEntry::win_type
copy #icon_entry_type_trash, (ptr),y
ldy #IconEntry::iconx
copy16in #desktop_main::create_volume_icon::trash_iconx, (ptr),y
ldy #IconEntry::icony
copy16in #desktop_main::create_volume_icon::trash_icony, (ptr),y
ldy #IconEntry::iconbits
copy16in #trash_icon, (ptr),y
iny
ldx #0
: lda trash_name,x
sta (ptr),y
iny
inx
cpx trash_name
bne :-
lda trash_name,x
sta (ptr),y
;; fall through
.endproc
;;; ============================================================
;;; This removes particular devices from the device list.
;;; * SmartPort devices
;;; * Mapped to Drive 2
;;; * Removable
;;; * With only one actual device present (per STATUS call)
;;; ... but why???
.proc filter_devices
ptr := $06
lda DEVCNT
sta devcnt
inc devcnt
ldx #0
: lda DEVLST,x
and #%10001111 ; drive, not slot, $CnFE status
cmp #%10001011 ; drive 2 ... ??? $CnFE = $Bx ?
beq :+
inx
cpx devcnt
bne :-
jmp done
: lda DEVLST,x ; unit_num
stx index
sp_addr := $0A
jsr desktop_main::find_smartport_dispatch_address
bne done ; not SmartPort
;; Execute SmartPort call
jsr smartport_call
.byte 0 ; $00 = STATUS
.addr smartport_params
bcs done
lda $1F00 ; number of devices
cmp #2
bcs done
;; Single device - remove from DEVLST - Why ???
ldx index
: copy DEVLST+1,x, DEVLST,x
inx
cpx devcnt
bne :-
dec DEVCNT
done: jmp end
index: .byte 0
smartport_call:
jmp (sp_addr)
smartport_params:
.byte $03 ; parameter count
.byte 0 ; unit number (0 = overall status)
.addr $1F00 ; status list pointer
.byte 0 ; status code (0 = device status)
devcnt: .byte 0
end:
.endproc
;;; ============================================================
.proc load_selector_list
ptr1 := $6
ptr2 := $8
selector_list_io_buf := $1000
selector_list_data_buf := $1400
selector_list_data_len := $400
MGTK_RELAY_CALL MGTK::CheckEvents
copy #0, L0A92
jsr read_selector_list
bne done
lda selector_list_data_buf
clc
adc selector_list_data_buf+1
sta num_selector_list_items
lda #0
sta LD344
lda selector_list_data_buf
sta L0A93
L0A3B: lda L0A92
cmp L0A93
beq done
jsr calc_data_addr
stax ptr1
lda L0A92
jsr calc_entry_addr
stax ptr2
ldy #0
lda (ptr1),y
tay
L0A59: lda (ptr1),y
sta (ptr2),y
dey
bpl L0A59
ldy #15
lda (ptr1),y
sta (ptr2),y
lda L0A92
jsr calc_data_str
stax ptr1
lda L0A92
jsr calc_entry_str
stax ptr2
ldy #0
lda (ptr1),y
tay
L0A7F: lda (ptr1),y
sta (ptr2),y
dey
bpl L0A7F
inc L0A92
inc selector_menu
jmp L0A3B
done: jmp calc_header_item_widths
L0A92: .byte 0
L0A93: .byte 0
.byte 0
;;; --------------------------------------------------
calc_data_addr:
jsr desktop_main::a_times_16
clc
adc #<(selector_list_data_buf+2)
tay
txa
adc #>(selector_list_data_buf+2)
tax
tya
rts
calc_entry_addr:
jsr desktop_main::a_times_16
clc
adc #<run_list_entries
tay
txa
adc #>run_list_entries
tax
tya
rts
calc_entry_str:
jsr desktop_main::a_times_64
clc
adc #<run_list_paths
tay
txa
adc #>run_list_paths
tax
tya
rts
calc_data_str:
jsr desktop_main::a_times_64
clc
adc #<(selector_list_data_buf+2 + $180)
tay
txa
adc #>(selector_list_data_buf+2 + $180)
tax
tya
rts
;;; --------------------------------------------------
DEFINE_OPEN_PARAMS open_params, str_selector_list, selector_list_io_buf
str_selector_list:
PASCAL_STRING "Selector.List"
DEFINE_READ_PARAMS read_params, selector_list_data_buf, selector_list_data_len
DEFINE_CLOSE_PARAMS close_params
.proc read_selector_list
MLI_RELAY_CALL OPEN, open_params
;; bne done
bne write_selector_list
lda open_params::ref_num
sta read_params::ref_num
MLI_RELAY_CALL READ, read_params
MLI_RELAY_CALL CLOSE, close_params
done: rts
.endproc
DEFINE_CREATE_PARAMS create_params, str_selector_list, ACCESS_DEFAULT, $F1
DEFINE_WRITE_PARAMS write_params, selector_list_data_buf, selector_list_data_len
.proc write_selector_list
ptr := $06
;; Clear buffer
copy16 #selector_list_data_buf, ptr
ldx #>selector_list_data_len ; number of pages
lda #0
ploop: ldy #0
: sta (ptr),y
dey
bne :-
dex
bne ploop
;; Write out file
MLI_RELAY_CALL CREATE, create_params
bne done
MLI_RELAY_CALL OPEN, open_params
lda open_params::ref_num
sta write_params::ref_num
sta close_params::ref_num
MLI_RELAY_CALL WRITE, write_params ; two blocks of $400
MLI_RELAY_CALL WRITE, write_params
MLI_RELAY_CALL CLOSE, close_params
done: rts
.endproc
.endproc
;;; ============================================================
.proc calc_header_item_widths
;; Enough space for "123456"
addr_call desktop_main::measure_text1, str_from_int
stax dx
;; Width of "123456 Items"
addr_call desktop_main::measure_text1, str_items
addax dx, width_items_label
;; Width of "123456K in disk"
addr_call desktop_main::measure_text1, str_k_in_disk
addax dx, width_k_in_disk_label
;; Width of "123456K available"
addr_call desktop_main::measure_text1, str_k_available
addax dx, width_k_available_label
add16 width_k_in_disk_label, width_k_available_label, width_right_labels
add16 width_items_label, #5, width_items_label_padded
add16 width_items_label_padded, width_k_in_disk_label, width_left_labels
add16 width_left_labels, #3, width_left_labels
jmp end
dx: .word 0
end:
.endproc
;;; ============================================================
;;; Enumerate Desk Accessories
.scope
MGTK_RELAY_CALL MGTK::CheckEvents
read_dir_buffer := $1400
;; Does the directory exist?
MLI_RELAY_CALL GET_FILE_INFO, get_file_info_params
beq :+
jmp end
: lda get_file_info_type
cmp #FT_DIRECTORY
beq open_dir
jmp end
open_dir:
MLI_RELAY_CALL OPEN, open_params
lda open_ref_num
sta read_ref_num
sta close_ref_num
MLI_RELAY_CALL READ, read_params
lda #0
sta entry_num
sta desk_acc_num
lda #1 ; First block has header instead of entry
sta entry_in_block
lda read_dir_buffer + SubdirectoryHeader::file_count
and #$7F
sta file_count
lda #2
sta apple_menu ; "About..." and separator
lda read_dir_buffer + SubdirectoryHeader::entries_per_block
sta entries_per_block
lda read_dir_buffer + SubdirectoryHeader::entry_length
sta entry_length
dir_ptr := $06
da_ptr := $08
copy16 #read_dir_buffer + .sizeof(SubdirectoryHeader), dir_ptr
process_block:
;; TODO: Adjust case
addr_call_indirect desktop_main::adjust_fileentry_case, dir_ptr
ldy #FileEntry::storage_type_name_length
lda (dir_ptr),y
and #NAME_LENGTH_MASK
bne :+
jmp next_entry
: inc entry_num
ldy #FileEntry::file_type
lda (dir_ptr),y
cmp #DA_FILE_TYPE
bne next_entry
ldy #FileEntry::aux_type+1 ; high bit set = skip
lda (dir_ptr),y
bmi next_entry
;; Compute slot in DA name table
is_da: inc desk_acc_num
copy16 #desk_acc_names, da_ptr
lda #0
sta ptr_calc_hi
lda apple_menu ; num menu items
sec
sbc #2 ; ignore "About..." and separator
asl a
rol ptr_calc_hi
asl a
rol ptr_calc_hi
asl a
rol ptr_calc_hi
asl a
rol ptr_calc_hi
clc
adc da_ptr
sta da_ptr
lda ptr_calc_hi
adc da_ptr+1
sta da_ptr+1
;; Copy name
ldy #FileEntry::storage_type_name_length
lda (dir_ptr),y
and #NAME_LENGTH_MASK
sta (da_ptr),y
tay
: lda (dir_ptr),y
sta (da_ptr),y
dey
bne :-
;; Convert periods to spaces
lda (da_ptr),y
tay
loop: lda (da_ptr),y
cmp #'.'
bne :+
lda #' '
sta (da_ptr),y
: dey
bne loop
inc apple_menu ; number of menu items
next_entry:
;; Room for more DAs?
lda desk_acc_num
cmp #max_desk_acc_count
bcc :+
jmp close_dir
;; Any more entries in dir?
: lda entry_num
cmp file_count
bne :+
jmp close_dir
;; Any more entries in block?
: inc entry_in_block
lda entry_in_block
cmp entries_per_block
bne :+
MLI_RELAY_CALL READ, read_params
copy16 #read_dir_buffer + 4, dir_ptr
lda #0
sta entry_in_block
jmp process_block
: add16_8 dir_ptr, entry_length, dir_ptr
jmp process_block
close_dir:
MLI_RELAY_CALL CLOSE, close_params
jmp end
DEFINE_OPEN_PARAMS open_params, str_desk_acc, $1000
open_ref_num := open_params::ref_num
DEFINE_READ_PARAMS read_params, read_dir_buffer, BLOCK_SIZE
read_ref_num := read_params::ref_num
DEFINE_GET_FILE_INFO_PARAMS get_file_info_params, str_desk_acc
get_file_info_type := get_file_info_params::file_type
.byte 0
DEFINE_CLOSE_PARAMS close_params
close_ref_num := close_params::ref_num
str_desk_acc:
PASCAL_STRING "Desk.acc"
file_count: .byte 0
entry_num: .byte 0
desk_acc_num: .byte 0
entry_length: .byte 0
entries_per_block: .byte 0
entry_in_block: .byte 0
ptr_calc_hi: .byte 0
end:
.endscope
;;; ============================================================
;;; Populate volume icons and device names
;;; TODO: Dedupe with cmd_check_drives
.scope
devname_ptr := $08
ldy #0
sty desktop_main::pending_alert
;; Enumerate DEVLST in reverse order (most important volumes first)
lda DEVCNT
sta device_index
process_volume:
lda device_index
asl a
tay
copy16 device_name_table,y, devname_ptr
ldy device_index
lda DEVLST,y
pha ; save all registers
txa
pha
tya
pha
inc cached_window_icon_count
inc icon_count
lda DEVLST,y
ldx cached_window_icon_count
jsr desktop_main::create_volume_icon ; A = unit number, X = icon index, Y = device number
sta cvi_result
MGTK_RELAY_CALL MGTK::CheckEvents
pla ; restore all registers
tay
pla
tax
pla
pha
lda cvi_result
cmp #ERR_DEVICE_NOT_CONNECTED
bne :+
ldy device_index ; BUG? Is there a missing pla instruction in this path?
lda DEVLST,y
and #$0F
beq select_template
ldx device_index
jsr remove_device
jmp next
: cmp #ERR_DUPLICATE_VOLUME
bne select_template
lda #ERR_DUPLICATE_VOL_NAME
sta desktop_main::pending_alert
;; This section populates device_name_table -
;; it determines which device type string to use, and
;; fills in slot and drive as appropriate.
;;
;; This is for a "Check" menu present in MouseDesk 1.1
;; but which was removed in MouseDesk 2.0, which allowed
;; refreshing individual windows. It is also used in the
;; Format/Erase disk dialog.
.proc select_template
pla ; unit number into A
pha
jsr desktop_main::get_device_type
sta device_type
;; Copy template to device name
asl ; * 2
tax
src := $06
copy16 device_template_table,x, src
ldy #0
lda (src),y
tay
: lda (src),y
sta (devname_ptr),y
dey
bpl :-
;; Insert Slot #
pla ; unit number into A
pha
and #%01110000 ; slot (from DSSSxxxx)
lsr a
lsr a
lsr a
lsr a
ora #'0'
ldx device_type
ldy device_template_slot_offset_table,x
sta (devname_ptr),y
;; Insert Drive #
pla ; unit number into A
pha
rol a ; set carry to drive - 1
lda #0 ; 0 + 1 + carry...
adc #1 ; now 1 or 2
ora #'0' ; convert to '1' or '2'
ldx device_type
ldy device_template_drive_offset_table,x
beq :+ ; 0 = no drive # for this type
sta (devname_ptr),y
:
.endproc
done_drive_num:
pla
next: dec device_index
lda device_index
bpl :+
bmi populate_startup_menu
: jmp process_volume ; next!
device_type:
.byte 0
device_index:
.byte 0
cvi_result:
.byte 0
.endscope
;;; ============================================================
;; Remove device num in X from devices list
.proc remove_device
dex
: inx
copy DEVLST+1,x, DEVLST,x
lda device_to_icon_map+1,x
sta device_to_icon_map,x
cpx DEVCNT
bne :-
dec DEVCNT
rts
.endproc
;;; ============================================================
.proc populate_startup_menu
slot_ptr := $06 ; pointed at $Cn00
table_ptr := $08 ; points into slot_string_table
lda #7
sta slot
lda #0
sta slot_ptr
tax ; X = menu entry
;; Identify ProDOS device in slot by ID bytes
loop: lda slot
ora #$C0 ; hi byte of $Cn00
sta slot_ptr+1
ldy #$01 ; $Cn01 == $20 ?
lda (slot_ptr),y
cmp #$20
bne next
ldy #$03 ; $Cn03 == $00 ?
lda (slot_ptr),y
cmp #$00
bne next
ldy #$05 ; $Cn05 == $03 ?
lda (slot_ptr),y
cmp #$03
bne next
;; It is a ProDOS device - prepare menu item.
txa ; pointer to nth sNN string
pha
asl a
tax
copy16 slot_string_table,x, table_ptr
ldy startup_menu_item_1 ; replace second-from-last char
dey
lda slot
ora #'0'
sta (table_ptr),y
pla
tax
inx
next: dec slot
bne loop
;; Set number of menu items.
stx startup_menu
jmp initialize_disks_in_devices_tables
slot: .byte 0
slot_string_table:
.addr startup_menu_item_1
.addr startup_menu_item_2
.addr startup_menu_item_3
.addr startup_menu_item_4
.addr startup_menu_item_5
.addr startup_menu_item_6
.addr startup_menu_item_7
.endproc
;;; ============================================================
;;; Enumerate DEVLST and find removable devices; build a list of
;;; these, and check to see which have disks in them. The list
;;; will be polled periodically to detect changes and refresh.
;;;
;;; Some hardware (machine/slot) combinations are filtered out
;;; due to known-buggy firmware.
.proc initialize_disks_in_devices_tables
ldx #0
ldy DEVCNT
loop: lda DEVLST,y
and #$0F
cmp #DT_REMOVABLE
beq append ; yes
next: dey
bpl loop
stx desktop_main::removable_device_table
stx desktop_main::disk_in_device_table
jsr desktop_main::check_disks_in_devices
;; Make copy of table
ldx desktop_main::disk_in_device_table
beq done
: copy desktop_main::disk_in_device_table,x, desktop_main::last_disk_in_devices_table,x
dex
bpl :-
done: jmp final_setup
append: lda DEVLST,y ; add it to the list
;; Don't issue STATUS calls to IIc Plus Slot 5 firmware, as it causes
;; the motor to spin. https://github.com/inexorabletash/a2d/issues/25
bit is_iic_plus_flag
bpl :+
and #%01110000 ; mask off slot
cmp #$50 ; is it slot 5?
beq next ; if so, ignore
;; Don't issue STATUS calls to Laser 128 Slot 7 firmware, as it causes
;; hangs in some cases. https://github.com/inexorabletash/a2d/issues/138
: bit is_laser128_flag
bpl :+
and #%01110000 ; mask off slot
cmp #$70 ; is it slot 7?
beq next ; if so, ignore
: lda DEVLST,y
inx
sta desktop_main::removable_device_table,x
bne next ; always
.endproc
;;; ============================================================
.proc final_setup
;; Final MGTK configuration
MGTK_RELAY_CALL MGTK::CheckEvents
MGTK_RELAY_CALL MGTK::SetMenu, desktop_aux::desktop_menu
MGTK_RELAY_CALL MGTK::SetCursor, pointer_cursor
lda #0
sta active_window_id
jsr desktop_main::update_window_menu_items
jsr desktop_main::disable_eject_menu_item
jsr desktop_main::disable_file_menu_items
jmp desktop_main::enter_main_loop
.endproc
;;; ============================================================
;;; High bits set if specific machine type detected.
is_iigs_flag:
.byte 0
is_iic_plus_flag:
.byte 0
is_laser128_flag:
.byte 0
;;; ============================================================
PAD_TO $1000
.endproc ; desktop_800