home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CDPD Public Domain Collection for CDTV 3
/
CDPDIII.bin
/
pd
/
utilities
/
dirutils
/
visualshell
/
src
/
asmsupp1.asm
< prev
next >
Wrap
Assembly Source File
|
1992-10-28
|
35KB
|
1,361 lines
*********************************
* *
* Visual Shell v1.17 10/92 *
* *
* by Torsten Jürgeleit *
* *
* assembly support routines *
* part I *
* *
*********************************
NOLIST
INCLUDE "exec/types.i"
INCLUDE "exec/ports.i"
INCLUDE "exec/nodes.i"
INCLUDE "exec/lists.i"
INCLUDE "exec/memory.i"
INCLUDE "devices/conunit.i"
INCLUDE "devices/inputevent.i"
INCLUDE "libraries/dos.i"
INCLUDE "libraries/dosextens.i"
INCLUDE "libraries/arpbase.i"
INCLUDE "intuition/intuition.i"
INCLUDE "equates.i"
LIST
;---------------------------------------------------------------------------
; External definitions
;---------------------------------------------------------------------------
XDEF _input_event_handler
XDEF _get_list_node
XDEF _build_file_node
XDEF _build_dev_node
XDEF _insert_file_node
XDEF _search_file_node
XDEF _count_file_nodes
XDEF _recount_file_nodes
XDEF _sum_file_sizes
XDEF _get_view_mode
XDEF _build_view_line_list
XDEF _get_first_visible_line
XDEF _search_line_node
XDEF _protection
XDEF _build_limited_path_name
;---------------------------------------------------------------------------
; External references
;---------------------------------------------------------------------------
XREF _IntuitionBase
XREF _GfxBase
XREF _gadget_buffer
XREF _con_device
XREF _con_unit
XREF _con_window
XREF _con_rport
XREF _main_task
XREF _vsh_port
XREF _event_mode
XREF _auto_repeat
XREF _show_flag
XREF _scroll_flag
XREF _vsh_scroll_speed
XREF _vsh_keyboard_type
XREF _qualifier
XREF _enable_abort
XREF _num_lock
XREF _key_table
XREF _action_table
XREF _scroll_flag_table
XREF _action
XREF _file_req
XREF _view_req
XREF _active_freq
XREF _line1_buffer
XREF _max_line_len
XREF _print_dir_info
XREF _print_info_line
XREF _print_vreq_status
XREF _print_quick_view
XREF _SPrintf
XREF _protection_bits
XREF _protection_string
XREF _font_data
XREF _template_buffer
XREF write_text
;---------------------------------------------------------------------------
; struct InputEvent *input_event_handler(event, data)
; a0 a1
; struct InputEvent *event
; APTR data = data segment ptr for a4
; Tied into input chain and parses event list for VSh special keys
;---------------------------------------------------------------------------
_input_event_handler:
PUSH a0-a6/d0-d7
move.l a1,a4 ; a4 := data segment ptr
move.l _IntuitionBase,a1
move.l ib_ActiveWindow(a1),a1
cmp.l _con_window,a1 ; input for VSh con window ?
bne ieh_exit
move.l a0,a2 ; a2 := event
move.l _main_task,a3 ; a3 := task ptr
move.l (4).w,a6 ; a6 := exec base ptr
move.l _vsh_port,a0 ; a0 := msg port
moveq #0,d0
move.b MP_SIGBIT(a0),d0 ; d0 := signal bit
moveq #0,d4
bset d0,d4 ; d4 := signal mask
moveq #0,d5 ; clear "don't clear event" flag
bra ieh_check_next_event
ieh_event_loop:
move.b ie_Class(a2),d1 ; check ie_Class
ieh_check_raw_mouse:
cmp.b #IECLASS_RAWMOUSE,d1 ; raw mouse event ?
bne ieh_check_raw_key
move.w ie_Code(a2),d0 ; check ie_Code
cmp.w #IECODE_LBUTTON,d0 ; left or right button pressed ?
beq ieh_mouse_button_pressed
cmp.w #IECODE_RBUTTON,d0
bne ieh_next_event
ieh_mouse_button_pressed:
move.b _event_mode,d0 ; input for input or config gadget ?
cmp.b #EVENT_MODE_INPUT,d0 ; if yes, don't report any mouse button events
beq ieh_clear_event
cmp.b #EVENT_MODE_CONFIG,d0
beq ieh_clear_event
bra ieh_next_event
ieh_check_raw_key:
cmp.b #IECLASS_RAWKEY,d1 ; raw key event ?
bne ieh_next_event
cmp.b #EVENT_MODE_IGNORE,_event_mode ; ignore input for VSh ?
beq ieh_clear_event
move.w ie_Code(a2),d2 ; d2 := key code
move.w ie_Qualifier(a2),d3 ; d3 := qualifier
and.w #QUALIFIER_MASK,d3 ; mask unused qualifier bits
ieh_search_key:
lea _key_table,a0 ; search raw key code in table
move.w d2,d1 ; d1 := key code
bclr #IECODEB_UP_PREFIX,d1 ; mask key up prefix
moveq #MAX_ACTION_KEYS-1,d0
ieh_search_key_loop:
cmp.w (a0)+,d1 ; key code in table ?
beq ieh_get_qualifier_bit_or_action_code
dbra d0,ieh_search_key_loop
ieh_unknown_key:
btst #IECODEB_UP_PREFIX,d2 ; ignore key up events
bne ieh_next_event
move.b _event_mode,d0 ; d0 := event mode
ieh_unknown_key_for_config:
cmp.b #EVENT_MODE_CONFIG,d0 ; input for config gadget ?
bne ieh_unknown_key_for_input
btst #IEQUALIFIERB_REPEAT,d3 ; ignore auto repeat
bne ieh_next_event
cmp.w #IECODE_UP_ARROW,d2
beq ieh_config_up_arrow
cmp.w #IECODE_DOWN_ARROW,d2
bne ieh_next_event
ieh_config_down_arrow:
move.w #IECODE_RETURN,ie_Code(a2) ; convert arrow key code to return
moveq #VSH_ACTION_GADGET_END_KEY,d1 ; d1 := action code
bra ieh_set_config_or_input_key_action
ieh_config_up_arrow:
move.w #IECODE_RETURN,ie_Code(a2) ; convert arrow key code to return
moveq #VSH_ACTION_SHIFT_GADGET_END_KEY,d1 ; d1 := action code
bra ieh_set_config_or_input_key_action
ieh_unknown_key_for_input:
cmp.b #EVENT_MODE_INPUT,d0 ; input for input gadget ?
bne ieh_unknown_key_for_speed_search
moveq #VSH_ACTION_SPEED_SEARCH,d1 ; d1 := action code
ieh_set_config_or_input_key_action:
moveq #1,d5 ; set "don't clear event" flag
bra ieh_set_action
ieh_unknown_key_for_speed_search:
tst.b _num_lock ; num lock set ?
beq ieh_next_event ; if no, normal alt keys
btst #IEQUALIFIERB_REPEAT,d3 ; ignore auto repeat
bne ieh_next_event
cmp.w #IEQUALIFIER_LALT,d3 ; alt key + letter -> speed search
beq ieh_set_speed_search_action
cmp.w #IEQUALIFIER_RALT,d3
bne ieh_next_event
ieh_set_speed_search_action:
bsr raw_key_convert ; convert raw key event to ASCII
cmp.l #1,d0 ; one char converted ?
bne ieh_next_event
moveq #VSH_ACTION_SPEED_SEARCH,d1 ; d1 := action code
bra ieh_set_action
ieh_get_qualifier_bit_or_action_code:
lea _action_table,a0
moveq #MAX_ACTION_KEYS-1,d1
sub.w d0,d1
move.w d1,d0 ; d0 := pos in key code table
move.b (a0,d0.w),d1 ; d1 := qualifier bit or action code
cmp.w #MAX_QUALIFIER_KEYS,d0 ; check pos in action table
bhs ieh_action_code
ieh_qualifier_bit:
btst #IECODEB_UP_PREFIX,d2 ; qualifier key up ?
bne ieh_qualifier_up
ieh_qualifier_down:
bset d1,_qualifier ; set qualifier bit
bra ieh_set_qualifier_action
ieh_qualifier_up:
bclr d1,_qualifier ; clear qualifier bit
ieh_set_qualifier_action:
cmp.b #EVENT_MODE_NORMAL,_event_mode ; normal event mode ?
bne ieh_next_event
moveq #VSH_ACTION_QUALIFIER,d1 ; d1 := action code
bra ieh_set_action ; set action only for none gadget input event
ieh_action_code:
bclr #IECODEB_UP_PREFIX,d2 ; ignore key up events
bne ieh_clear_flags
move.b _event_mode,d0 ; d0 := event mode
cmp.b #EVENT_MODE_INPUT,d0 ; input for input or config gadget ?
beq ieh_check_end_gadget
cmp.b #EVENT_MODE_CONFIG,d0
bne ieh_check_return
ieh_check_config_fkeys:
cmp.b #VSH_ACTION_F10,d1 ; f1 - f4 or f10 pressed ?
beq ieh_convert_config_fkey
cmp.w #VSH_ACTION_F4,d1
bhi ieh_check_end_gadget ; illegal fkey
ieh_convert_config_fkey:
tst.w d3 ; no qualifier ?
bne ieh_next_event
move.w #IECODE_RETURN,ie_Code(a2) ; convert fkey code to return
bra ieh_set_end_gadget_action
ieh_check_end_gadget:
cmp.b #VSH_ACTION_ESC,d1 ; esc key pressed ?
beq ieh_convert_esc_to_return
cmp.b #VSH_ACTION_RETURN,d1 ; return pressed ?
beq ieh_check_shift_end_gadget
cmp.b #VSH_ACTION_NUM_ENTER,d1 ; enter pressed ?
bne ieh_next_event
ieh_check_shift_end_gadget: ; shifted finish gadget input ?
bclr #IEQUALIFIERB_NUMERICPAD,d3
cmp.w #IEQUALIFIER_LSHIFT,d3 ; shift key pressed ?
beq ieh_shift_end_gadget
cmp.w #IEQUALIFIER_RSHIFT,d3
beq ieh_shift_end_gadget
ieh_end_gadget:
move.b #VSH_ACTION_GADGET_END_KEY,d1 ; d1 := action code
bra ieh_set_end_gadget_action
ieh_shift_end_gadget: ; shift return or enter for jump to next entry
move.b #VSH_ACTION_SHIFT_GADGET_END_KEY,d1 ; d1 := action code
cmp.b #EVENT_MODE_CONFIG,d0 ; input for config ?
bne ieh_set_action
and.w #~(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT),ie_Qualifier(a2)
bra ieh_set_end_gadget_action
ieh_convert_esc_to_return
move.w #IECODE_RETURN,ie_Code(a2) ; convert esc key code to return
ieh_set_end_gadget_action:
bclr #IEQUALIFIERB_REPEAT,d3 ; ignore auto repeat
bne ieh_clear_event
moveq #1,d5 ; set "don't clear event" flag
cmp.b #EVENT_MODE_INPUT,_event_mode
bne ieh_set_action
move.b #EVENT_MODE_NORMAL,_event_mode ; reset input event mode to normal
bra ieh_set_action
ieh_check_return:
cmp.b #VSH_ACTION_RETURN,d1 ; return key pressed ?
beq ieh_next_event
ieh_check_repeat:
bclr #IEQUALIFIERB_REPEAT,d3 ; auto repeat ?
beq ieh_check_numlock_key
cmp.b #VSH_ACTION_SCROLL_PAGE_UP,d1 ; check action for autorepeatable action
blo ieh_clear_flags
cmp.b #VSH_ACTION_MARK_FILE,d1
bhi ieh_clear_flags
move.b #1,_auto_repeat ; set auto repeat flag
tst.b _num_lock ; num lock set ?
beq ieh_next_event ; if no, normal numeric pad keys
bra ieh_check_shift
ieh_check_numlock_key:
cmp.b #KEYBOARD_TYPE1,_vsh_keyboard_type
bne ieh_numlock_keyboard_type2
ieh_numlock_keyboard_type1:
cmp.b #VSH_ACTION_NUM_MINUS,d1 ; numlock key pressed ?
bne ieh_check_numlock
cmp.w #IEQUALIFIER_LALT|IEQUALIFIER_NUMERICPAD,d3
beq ieh_set_numlock_action
cmp.w #IEQUALIFIER_RALT|IEQUALIFIER_NUMERICPAD,d3
bne ieh_check_numlock
bra ieh_set_numlock_action
ieh_numlock_keyboard_type2:
cmp.b #VSH_ACTION_NUM_LEFT_BRAKET,d1 ; numlock key pressed ?
bne ieh_check_numlock
ieh_set_numlock_action:
moveq #VSH_ACTION_NUMLOCK,d1 ; d1 := action code
bra ieh_set_action
ieh_check_numlock:
tst.b _num_lock ; num lock set ?
beq ieh_next_event ; if no, normal numeric pad keys
ieh_check_control:
btst #IEQUALIFIERB_CONTROL,d3 ; control key pressed ?
beq ieh_check_shift
and.w #~(IEQUALIFIER_CONTROL),ie_Qualifier(a2) ; clear control qualifier bit
bra ieh_next_event ; normal events
ieh_check_shift:
bclr #IEQUALIFIERB_NUMERICPAD,d3
cmp.w #IEQUALIFIER_LSHIFT,d3 ; shift key pressed ?
beq ieh_shift_action
cmp.w #IEQUALIFIER_RSHIFT,d3
bne ieh_check_alternate
ieh_shift_action:
add.b #SHIFTED,d1 ; change to shifted action code
bra ieh_set_action
ieh_check_alternate:
cmp.w #IEQUALIFIER_LALT,d3 ; alternate key pressed ?
beq ieh_alternate_action
cmp.w #IEQUALIFIER_RALT,d3
bne ieh_check_alternate_shift
ieh_alternate_action:
add.b #ALTERNATED,d1 ; change to alternated action code
bra ieh_set_action
ieh_check_alternate_shift:
cmp.w #IEQUALIFIER_LSHIFT|IEQUALIFIER_LALT,d3 ; alternate + shift key pressed ?
beq ieh_alternate_shift_action
cmp.w #IEQUALIFIER_RSHIFT|IEQUALIFIER_RALT,d3
bne ieh_check_qualifier
ieh_alternate_shift_action:
add.b #ALTERNATED+SHIFTED,d1 ; change to alternated + shifted action code
bra ieh_set_action
ieh_check_qualifier:
tst.w d3 ; other qualifier ?
bne ieh_next_event
ieh_set_action:
move.b d1,_action
ieh_check_scrolling:
cmp.b #VSH_ACTION_SCROLL_TOP,d1 ; check action for scrolling action
blo ieh_check_esc
cmp.b #VSH_ACTION_SCROLL_RIGHT,d1
bhi ieh_check_esc
lea _scroll_flag_table,a0 ; set scroll flag
sub.b #VSH_ACTION_SCROLL_TOP+1,d1
ext.w d1
move.b (a0,d1.w),_scroll_flag
bra ieh_signal_task
ieh_check_esc:
tst.b _enable_abort ; ESC abort enabled ?
beq ieh_signal_task
cmp.b #VSH_ACTION_ESC,d1 ; ESC key pressed ?
bne ieh_signal_task
ieh_set_ctrl_c:
move.l #SIGBREAKF_CTRL_C,d0 ; d0 := signal mask
move.l a3,a1 ; a1 := task ptr
CALLSYS Signal ; set ctrl c signal
ieh_signal_task:
move.l d4,d0 ; d0 := signal mask
move.l a3,a1 ; a1 := task ptr
CALLSYS Signal ; signal main task
ieh_check_dont_clear_event_flag:
tst.b d5 ; "don't clear event" flag set ?
bne ieh_next_event ; if yes, don't clear this event
bra ieh_clear_event
ieh_clear_flags:
clr.b _auto_repeat
clr.b _scroll_flag
ieh_clear_event:
move.w #IECLASS_NULL,ie_Class(a2)
ieh_next_event:
move.l ie_NextEvent(a2),a2 ; get next event in list
ieh_check_next_event:
move.l a2,d0 ; next event ptr == NULL ?
bne ieh_event_loop
ieh_exit:
PULL a0-a6/d0-d7
move.l a0,d0 ; return old event list ptr
rts
;---------------------------------------------------------------------------
; BOOL raw_key_convert(event)
; a2
; struct InputEvent *event
; Convert a raw key input event into an ASCII char
;---------------------------------------------------------------------------
raw_key_convert:
PUSH a2/a6
clr.w ie_Qualifier(a2) ; clear qualifier -> no alt
move.l a2,a0 ; a0 := input event ptr
lea _gadget_buffer,a1 ; a1 := buffer ptr
moveq #1,d1 ; d1 := buffer length
move.l _con_unit,a2 ; get ConUnit ptr
lea cu_KeyMapStruct(a2),a2 ; a2 := keymap ptr
move.l _con_device,a6 ; get ConsoleBase ptr
CALLSYS RawKeyConvert
lea _gadget_buffer,a1 ; a1 := buffer ptr
clr.b 1(a1) ; set end of string
PULL a2/a6
rts
;---------------------------------------------------------------------------
; struct MinNode *get_list_node(list, num_entries, num)
; a0 d0 d1
; struct MinList *list
; ULONG num_entries, num
; Get specified entry from list
;---------------------------------------------------------------------------
_get_list_node:
tst.l d0 ; no entries in list ?
beq gln_return_null
sub.l d1,d0 ; num > num_entries ?
bmi gln_return_last_node
cmp.l d1,d0 ; num >= (num_entries - num) ?
bhs gln_from_end
gln_from_start:
move.l MLH_HEAD(a0),a0 ; a0 := first node
bra gln_start_check
gln_start_loop:
move.l MLN_SUCC(a0),a0 ; get next node
gln_start_check:
subq.l #1,d1 ; dec num
bne gln_start_loop
bra gln_return_current_node
gln_from_end:
move.l MLH_TAILPRED(a0),a0 ; a0 := last node
bra gln_end_check
gln_end_loop:
move.l MLN_PRED(a0),a0 ; get previous node
gln_end_check:
subq.l #1,d0 ; dec num
bpl gln_end_loop
gln_return_current_node:
move.l a0,d0 ; d0 := current node
rts
gln_return_last_node;
move.l MLH_TAILPRED(a0),d0 ; d0 := last node
rts
gln_return_null:
moveq #0,d0 ; d0 := NULL
rts
;---------------------------------------------------------------------------
; struct FileNode *build_file_node(fib)
; a0
; struct FileInfoBlock *fib
; Allocate memory for file node and fill it with data from fle info block
;---------------------------------------------------------------------------
_build_file_node:
PUSH a2-a3/a6
move.l a0,a3 ; a3 := fib
; --- alloc memory for new file node
moveq #FileNode_Sizeof,d0
move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
move.l (4).w,a6 ; a6 := exec base
CALLSYS AllocMem
tst.l d0
beq bfn_error
move.l d0,a2 ; a2 := file node ptr
; --- init file node
lea fib_FileName(a3),a0 ; source ptr
lea fn_Text(a2),a1 ; dest ptr
moveq #0,d0 ; reset name len counter
bfn_copy_loop:
move.b (a0)+,d1 ; copy a char till null
beq bfn_fill_spaces
move.b d1,(a1)+
addq.w #1,d0
cmp.w #MAX_FILE_NAME_LEN,d0
blo bfn_copy_loop
bfn_fill_spaces:
move.w d0,fn_NameLen(a2) ; save name len
moveq #' ',d1
bra bfn_check_len
bfn_fill_loop:
move.b d1,(a1)+ ; fill string with spaces
addq.w #1,d0
bfn_check_len:
cmp.w #MAX_FILE_NAME_LEN+1,d0 ; one additional space as delimiter
blo bfn_fill_loop
bfn_copy_date:
move.l fib_DateStamp+ds_Days(a3),fn_Date+ds_Days(a2)
move.l fib_DateStamp+ds_Minute(a3),fn_Date+ds_Minute(a2)
move.l fib_DateStamp+ds_Tick(a3),fn_Date+ds_Tick(a2)
bfn_copy_protection:
move.l fib_Protection(a3),d0
tst.b fib_Comment(a3) ; any comment ?
beq bfn_no_comment
bset #MAX_PROTECTION_BITS-1,d0 ; set comment bit
bfn_no_comment:
move.w d0,fn_Protection(a2)
bfn_check_type:
moveq #ENTRY_TYPE_FILE,d0 ; default type = file
lea bfn_size_fmt_string,a0 ; default size text = number
tst.l fib_DirEntryType(a3) ; check file type
bmi bfn_set_type ; < 0 => it's a file
moveq #ENTRY_TYPE_DIR,d0 ; type = dir
lea bfn_dir_fmt_string,a0 ; size text = dir
bfn_set_type:
move.b d0,fn_Type(a2) ; set file type
move.l fib_Size(a3),d0
move.l d0,fn_Size(a2) ; set file size
move.l d0,-(sp) ; size -> only valid for files
move.l a0,-(sp) ; format string
move.l a1,-(sp) ; dest string
CALL _SPrintf ; append size to string
lea 3*4(sp),sp
move.l a2,d0 ; return value
bfn_exit:
PULL a2-a3/a6
rts
bfn_error:
moveq #0,d0
bra bfn_exit
bfn_size_fmt_string:
dc.b "%8ld",0
bfn_dir_fmt_string:
dc.b " (Dir)",0
;---------------------------------------------------------------------------
; struct FileNode *build_dev_node(dlist)
; a0
; struct DosList *dlist
; Allocate memory for a device node and fill it with data from dos list
;---------------------------------------------------------------------------
_build_dev_node:
PUSH a2-a3/a6
move.l a0,a3 ; a3 := dos list
; --- alloc memory for file node
moveq #FileNode_Sizeof,d0
move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
move.l (4).w,a6 ; a6 := exec base
CALLSYS AllocMem
tst.l d0
beq bdn_error
move.l d0,a2 ; a2 := file node ptr
; --- init file node
move.l a3,d0 ; dlist == NULL ?
bne bdn_no_ram_disk
bdn_ram_disk:
move.w #4,fn_NameLen(a2) ; build a device node for RAM:
lea bdn_ram_string,a0 ; source ptr
lea fn_Text(a2),a1 ; dest ptr
moveq #1,d0 ; type := device
bra bdn_set_type
bdn_no_ram_disk:
move.l dvi_Name(a3),d0
lsl.l #2,d0 ; make BPTR to PTR
move.l d0,a0
move.b (a0),d1 ; d1 := length of BSTR
add.l #1,a0 ; source ptr
lea fn_Text(a2),a1 ; dest ptr
moveq #0,d0 ; rest name len counter
bdn_copy_loop:
move.b (a0)+,(a1)+ ; copy a char
addq.w #1,d0
cmp.w #MAX_FILE_NAME_LEN,d0
bhs bdn_append_colon
cmp.b d1,d0 ; end of name ?
blo bdn_copy_loop
bdn_append_colon:
move.b #':',(a1)+ ; append colon to name
add.w #1,d0
bdn_fill_line:
move.w d0,fn_NameLen(a2) ; save name len
moveq #' ',d1
bra bdn_check_len
bdn_fill_loop:
move.b d1,(a1)+ ; fill string with spaces
addq.w #1,d0
bdn_check_len:
cmp.w #MAX_FILE_NAME_LEN+1,d0 ; one additional space as delimiter
blo bdn_fill_loop
moveq #ENTRY_TYPE_ASSIGN,d0 ; default type = assign
lea bdn_assign_string,a0 ; default text = assign
tst.l dvi_Type(a3) ; check dos list type
bne bdn_set_type ; != 0 => it's a assign
moveq #ENTRY_TYPE_DEVICE,d0 ; type = device
lea bdn_device_string,a0 ; text = device
bdn_set_type:
move.b d0,fn_Type(a2) ; set file type
bdn_append_type:
move.b (a0)+,(a1)+ ; append type to text
bne bdn_append_type
move.l a2,d0 ; return value
bdn_exit:
PULL a2-a3/a6
rts
bdn_error:
moveq #0,d0
bra bdn_exit
bdn_assign_string:
dc.b " (Asn)",0
bdn_device_string:
dc.b " (Dev)",0
bdn_ram_string:
dc.b "RAM: (Dev)",0
;---------------------------------------------------------------------------
; VOID insert_file_node(node, list)
; a0 a1
; struct FileNode *node
; struct MinList *list
; Insert file node into list according to type and name
;---------------------------------------------------------------------------
_insert_file_node:
PUSH a2-a3/a5-a6
move.l a0,a2 ; a2 := node
move.l a1,a3 ; a3 := list
move.l a3,a5 ; save list ptr
move.l MLH_HEAD(a3),a3 ; a3 := list->mlh_Head
ifn_search_loop:
tst.l MLN_SUCC(a3) ; end of list ?
beq ifn_insert
move.l a2,a0 ; a0 := new node
move.l a3,a1 ; a1 := node from list
bsr compare_file_nodes
tst.b d0
beq ifn_insert
move.l MLN_SUCC(a3),a3 ; next node
bra ifn_search_loop
ifn_insert:
move.l a5,a0 ; a0 := list
move.l a2,a1 ; a1 := new node
move.l MLN_PRED(a3),a2 ; a2 := node from list
move.l (4).w,a6 ; a6 := exec base
CALLSYS Insert
PULL a2-a3/a5-a6
rts
compare_file_nodes: ; (a0 := file node 1, a1 := file node 2)
move.b fn_Type(a0),d1 ; compare type of entries
cmp.b fn_Type(a1),d1
beq cfn_alpha ; same type -> sort alphabetical
bcs cfn_match ; a0->fn_Type > a1->fn_Type
bra cfn_no_match ; a0->fn_Type < a1->fn_Type
cfn_alpha:
lea fn_Text(a0),a0 ; compare name of entries
lea fn_Text(a1),a1
cfn_alpha_loop:
move.b (a0)+,d0 ; convert char to lower case
cmp.b #'A',d0
blo 1$
cmp.b #'Z',d0
bhi 1$
add.b #32,d0
1$:
move.b (a1)+,d1 ; convert char to lower case
cmp.b #'A',d1
blo 2$
cmp.b #'Z',d1
bhi 2$
add.b #32,d1
2$:
tst.b d0 ; end of first name ?
beq 3$
cmp.b d1,d0
beq cfn_alpha_loop
3$:
sub.b d1,d0
bls cfn_no_match
cfn_match:
moveq #1,d0 ; file node 1 > file node 2
rts
cfn_no_match:
moveq #0,d0 ; file node 1 <= file node 2
rts
;---------------------------------------------------------------------------
; struct FileNode *search_file_node(node, name, name_len)
; a0 a1 d0
; struct FileNode *node
; UBYTE *name
; USHORT name_len
; Search file node in list which file name starts with name
;---------------------------------------------------------------------------
_search_file_node:
PUSH d2/a2-a3
move.l a1,d1 ; node == NULL ?
beq sfn_not_found
move.l a0,a2 ; a2 := node
move.l a1,a3 ; a3 := name
move.w d0,d2 ; d2 := name length
sfn_search_loop:
tst.l MLN_SUCC(a2) ; end of list ?
beq sfn_not_found
tst.w d2 ; length given ?
beq sfn_compare_names
cmp.w fn_NameLen(a2),d2 ; same name length ?
bne sfn_next_entry
sfn_compare_names:
move.l a3,a0 ; a0 := search name
lea fn_Text(a2),a1 ; a1 := name from node
bsr compare_names
tst.b d0
beq sfn_found
sfn_next_entry:
move.l MLN_SUCC(a2),a2 ; next node
bra sfn_search_loop
sfn_found:
move.l a2,d0 ; d0 := file node -> return value
sfn_exit:
PULL d2/a2-a3
rts
sfn_not_found:
moveq #0,d0 ; d0 := NULL -> return value
bra sfn_exit
compare_names: ; (a0 := search name, a1 := name from node)
move.b (a0)+,d0 ; convert char to lower case
tst.w d2 ; name length given ?
bne 1$
cmp.b #'A',d0
blo 1$
cmp.b #'Z',d0
bhi 1$
add.b #32,d0
1$:
move.b (a1)+,d1 ; convert char to lower case
tst.w d2 ; name length given ?
bne 2$
cmp.b #'A',d1
blo 2$
cmp.b #'Z',d1
bhi 2$
add.b #32,d1
2$:
tst.b d0 ; end of first name ?
beq cn_match
cmp.b d1,d0
beq compare_names
bne cn_no_match
cn_match:
moveq #0,d0 ; search name == name from node
rts
cn_no_match:
moveq #1,d0 ; search name != name from node
rts
;---------------------------------------------------------------------------
; ULONG count_file_nodes(list)
; a0
; struct MinList *list
; Count file nodes in list and set position of all nodes
;---------------------------------------------------------------------------
_count_file_nodes:
move.l MLH_HEAD(a0),a0 ; a0 := first node in list
moveq #0,d0 ; reset node counter
cfn_loop:
tst.l MLN_SUCC(a0) ; end of list ?
beq cfn_exit
addq.l #1,d0
move.l d0,fn_Pos(a0) ; set pos of node
move.l MLN_SUCC(a0),a0 ; next node
bra cfn_loop
cfn_exit:
rts
;---------------------------------------------------------------------------
; ULONG recount_file_nodes(fnode)
; a0
; struct FileNode *fnode
; Count file nodes in list from given node and dec position of all nodes
;---------------------------------------------------------------------------
_recount_file_nodes:
move.l fn_Pos(a0),d0 ; d0 := old fnode counter
subq.l #1,d0 ; dec node counter, because this fnode will be removed
bra rfn_next ; start from next fnode
rfn_loop:
tst.l MLN_SUCC(a0) ; end of list ?
beq rfn_exit
addq.l #1,d0
move.l d0,fn_Pos(a0) ; set pos of node
rfn_next:
move.l MLN_SUCC(a0),a0 ; next node
bra rfn_loop
rfn_exit:
rts
;---------------------------------------------------------------------------
; VOID sum_file_sizes(freq)
; a0
; struct FileRequest *freq
; Count dirs and files in list and calc total size of all files
;---------------------------------------------------------------------------
_sum_file_sizes:
PUSH d2-d3
move.l a0,a1 ; a1 := freq ptr
moveq #0,d1 ; reset dir counter
moveq #0,d2 ; reset file counter
moveq #0,d3 ; reset size counter
move.l fr_Display+d_List(a1),a0 ; a0 := file list ptr
move.l MLH_HEAD(a0),a0 ; a0 := first node in list
move.l fr_Display+d_NumEntries(a1),d0 ; d0 := entry count
beq sfs_exit
sfs_loop:
cmp.b #ENTRY_TYPE_FILE,fn_Type(a0) ; file ?
beq sfs_file
sfs_dir:
addq.l #1,d1 ; inc dir counter
bra sfs_next
sfs_file:
addq.l #1,d2 ; inc file counter
add.l fn_Size(a0),d3 ; add size
sfs_next:
move.l MLN_SUCC(a0),a0 ; next node
subq.l #1,d0
bne sfs_loop
sfs_exit:
lea fr_Info(a1),a0 ; save data
move.l d1,i_Dirs(a0)
move.l d2,i_Files(a0)
move.l d3,i_FileSizes(a0)
PULL d2-d3
rts
;---------------------------------------------------------------------------
; USHORT get_view_mode(vreq)
; a0
; struc t ViewRequest *vreq
; Check file buffer for binaries and return view mode (ASCII or hex dump)
;---------------------------------------------------------------------------
_get_view_mode:
PUSH d2
move.l a0,a1 ; a1 := vreq ptr
move.l vr_Buffer(a1),a0 ; a0 := buffer ptr
move.l vr_BufferSize(a1),d2 ; d1 := size
moveq #VIEW_MODE_ASCII,d0 ; mode = ASCII dump
gvm_loop:
subq.l #1,d2 ; end of buffer ?
bmi gvm_exit
move.b (a0)+,d1 ; get char from buffer
gvm_ascii:
cmp.b #' ',d1 ; check for ASCII char
blo gvm_alternate
cmp.b #'~',d1
bls gvm_loop ; yes, its an ASCII char
gvm_alternate:
cmp.b #160,d1 ; check for alternate char
blo gvm_control_code
cmp.b #255,d1
bls gvm_loop ; yes, its an alternate char
gvm_control_code:
cmp.b #9,d1 ; tab ?
beq gvm_loop
cmp.b #10,d1 ; line feed ?
beq gvm_loop
cmp.b #12,d1 ; form feed ?
beq gvm_loop
cmp.b #13,d1 ; carriage return ?
beq gvm_loop
moveq #VIEW_MODE_HEX,d0 ; mode = hex dump
gvm_exit:
PULL d2
rts
;---------------------------------------------------------------------------
; BOOL build_view_line_list(vreq, view_mode)
; a0 d0
; struct ViewRequest *vreq
; USHORT view_mode
; Build view line list with nodes for every line of text
;---------------------------------------------------------------------------
_build_view_line_list:
PUSH d2-d7/a2-a3/a5-a6
move.l a0,a5 ; a0 := vreq ptr
move.w d0,d7 ; d7 := view mode
move.w d7,vr_Mode(a5) ; set mode
move.l (4).w,a6 ; a6 := exec base
moveq #MLH_SIZE,d0 ; alloc mem for line list header
move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
CALLSYS AllocMem
move.l d0,vr_Display+d_List(a5)
beq bvl_error
move.l d0,a0 ; init new list
NEWLIST a0
move.l vr_Buffer(a5),a3 ; a3 := buffer ptr
move.l vr_BufferSize(a5),d6 ; d6 := size
moveq #0,d5 ; reset entry counter
moveq #0,d4 ; reset offset counter
move.w _max_line_len,d3 ; max num of chars per line
subq.w #1,d3 ; dec num -> only valid for ASCII dump
tst.w d7 ; check mode -> bytes per line
beq bvl_loop
moveq #MAX_HEX_LONG_WORDS*4-1,d3 ; bytes per line for hex dump
bvl_loop:
move.l a3,a2 ; save start of line ptr
moveq #0,d1 ; reset pos counter -> only valid for ASCII
moveq #0,d2 ; reset byte counter
tst.w d7 ; check mode -> bytes per line
beq bvl_line_loop
move.w d3,d1 ; reload char counter -> only valid for hex dump
bvl_line_loop:
tst.l d6 ; end of buffer ?
beq bvl_next_line
move.b (a3)+,d0 ; get char from buffer
subq.l #1,d6 ; dec size counter
tst.w d7 ; check mode
beq bvl_ascii
bvl_hex:
addq.w #1,d2 ; inc char counter
dbra d1,bvl_line_loop
bra bvl_next_line
bvl_ascii:
cmp.b #10,d0 ; line feed ?
beq bvl_next_line
cmp.b #12,d0 ; form feed ?
beq bvl_next_line
cmp.b #13,d0 ; carriage return ?
beq bvl_next_line
addq.w #1,d2 ; inc char counter
cmp.b #9,d0 ; tab ?
bne bvl_ascii_normal
bvl_ascii_tab:
move.w d1,d0 ; calc num of spaces to fill
not.w d0
and.w #7,d0
addq.w #1,d0
add.w d0,d1 ; add num of spaces to pos counter
bra bvl_ascii_check_pos
bvl_ascii_normal:
addq.w #1,d1 ; inc pos counter
bvl_ascii_check_pos:
cmp.w d3,d1 ; end of line ?
bls bvl_line_loop
bvl_next_line:
moveq #LineNode_Sizeof,d0 ; alloc mem for line node
move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
CALLSYS AllocMem
tst.l d0
beq bvl_error
move.l d0,a1 ; a1 := line node ptr
move.l a2,ln_Line(a1)
move.w d2,ln_LineLen(a1)
move.l d4,ln_Offset(a1)
ext.l d2
add.l d2,d4 ; update offset counter
tst.w d7 ; view mode == ASCII ?
bne bvl_no_offset_inc
add.l #1,d4 ; inc ASCII offset for LF, FF or CR
bvl_no_offset_inc:
addq.l #1,d5 ; inc entry counter
move.l d5,ln_Pos(a1)
move.l vr_Display+d_List(a5),a0 ; a0 := list ptr
ADDTAIL ; append node to list
tst.l d6 ; end of buffer ?
bne bvl_loop
bvl_end_of_buffer:
move.l d5,vr_Display+d_NumEntries(a5) ; save num of entries in vreq
moveq #1,d0 ; return value -> success
bvl_exit:
PULL d2-d7/a2-a3/a5-a6
rts
bvl_error:
moveq #0,d0 ; return value -> error
bra bvl_exit
;---------------------------------------------------------------------------
; struct LineNode *get_first_visible_line(vreq, old_offset)
; a0 d0
; struct ViewRequest *vreq
; ULONG old_offset
; Get first visible line node from offset of old view mode
;---------------------------------------------------------------------------
_get_first_visible_line:
PUSH d2/a2
move.l a0,a2 ; a2 := vreq ptr
move.l d0,d1 ; d1 := old offset
move.w vr_Mode(a2),d2 ; d2 := view mode
move.l vr_Display+d_List(a2),a0
move.l MLH_HEAD(a0),a0 ; a0 := first node in list
move.l a0,a1 ; a1 := default first visible node
gfvl_loop:
tst.l MLN_SUCC(a0) ; end of list ?
beq gfvl_not_found
moveq #0,d0
move.w ln_LineLen(a0),d0
add.l ln_Offset(a0),d0
cmp.l d1,d0 ; offset + line_len > old_offset ?
bhi gfvl_found
move.l MLN_SUCC(a0),a0 ; next line node
bra gfvl_loop
gfvl_not_found:
move.l a1,d0 ; return first node as first visible node
bra gfvl_exit
gfvl_found:
move.l a0,d0 ; return current node as first visible node
gfvl_exit:
PULL d2/a2
rts
;---------------------------------------------------------------------------
; struct LineNode *search_line_node(start_node, string, len)
; a0 a1 d0
; struct LineNode *start_node
; UBYTE *string
; USHORT len
; Search line node in list which contains the search string
;---------------------------------------------------------------------------
_search_line_node:
PUSH d2/a2-a3/a5
move.l a0,d1 ; start node == NULL ?
beq sln_not_found
move.l a0,a5 ; a5 := lnode
move.l a1,a3 ; a1 := search string
move.w d0,d2 ; d2 := len of search string
subq.w #1,d2 ; dec len for dbra
sln_search_loop:
tst.l MLN_SUCC(a5) ; end of list ?
beq sln_not_found
move.l ln_Line(a5),a2 ; a2 := line ptr
move.w ln_LineLen(a5),d1 ; d1 := line len
bsr compare_lines
tst.b d0
beq sln_found
move.l MLN_SUCC(a5),a5 ; next node
bra sln_search_loop
sln_found:
move.l a5,d0 ; d0 := file node -> return value
bra sln_exit
sln_not_found:
moveq #0,d0 ; d0 := NULL -> return value
sln_exit:
PULL d2/a2-a3/a5
rts
compare_lines: ; (a2 := line ptr, a3 := search string ptr, d1.w := line len, d2.w := search string len - 1)
move.b (a3),d0 ; search first char of search string
cl_loop1:
cmp.b (a2)+,d0
beq cl_check_full
subq.w #1,d1 ; end of line ?
bhi cl_loop1
cl_no_match:
moveq #1,d0 ; search string not found
rts
cl_check_full:
move.l a2,a0 ; check full search string
lea 1(a3),a1
move.w d2,d0 ; only one char to search ?
beq cl_match
subq.w #1,d0
cl_loop2:
cmp.b (a0)+,(a1)+
bne compare_lines
dbra d0,cl_loop2
cl_match:
moveq #0,d0 ; search string found
rts
;---------------------------------------------------------------------------
; UBYTE *protection(fnode)
; a0
; struct FileNode *fnode
; Build string with protection bits setting for given file node
;---------------------------------------------------------------------------
_protection:
PUSH d2/a2
move.l a0,a2 ; a2 := fnode ptr
move.w fn_Protection(a2),d0
move.l _protection_bits,a0
lea _protection_string,a1
moveq #MAX_PROTECTION_BITS-1,d2 ; d2 := bit count - 1
clr.b 1(a1,d2.w) ; set end of string
prot_loop:
moveq #'-',d1 ; default value for not active
cmp.w #MAX_PROTECTION_BITS-4,d2 ; RWED ?
blo prot_chspa
prot_rwed:
lsr.w #1,d0 ; RWED : protection bit clear ?
bcs prot_write_byte
bra prot_get_byte
prot_chspa:
lsr.w #1,d0 ; CHSPA : protection bit set ?
bcc prot_write_byte
prot_get_byte:
move.b (a0,d2.w),d1
prot_write_byte:
move.b d1,(a1,d2.w)
dbra d2,prot_loop
move.l a1,d0 ; return ptr to protection string
PULL d2/a2
rts
;---------------------------------------------------------------------------
; VOID build_limited_path_name(buffer,device_name,path_name,max_len,mode)
; a0 a1 a2 d0 d1
; BYTE *buffer, *device_name, *path_name
; USHORT max_len, mode
; Build path name with specified maximal length - if path is too long then
; use the form 'start of path...end of path'
;---------------------------------------------------------------------------
_build_limited_path_name:
PUSH d2-d5/a2-a3
; --- init some regs
move.l a0,a3 ; a3 := buffer
move.w d0,d2 ; d2 := max len
move.w #0,d3 ; d3 := buffer char count
move.w d1,d4 ; d4 := mode
; --- copy device name (if any) to buffer
move.l a1,d0
beq blpn_count_path_name_len
bpln_copy_device_name:
move.b (a1)+,d0
beq bpln_skip_volume_name
move.b d0,(a3)+
addq.w #1,d3 ; inc char count
bra bpln_copy_device_name
bpln_skip_volume_name:
; --- skip volume name in path name
sub.w d3,d2 ; max len -= char count
bpln_skip_loop:
cmp.b #':',(a2)+
bne bpln_skip_loop
blpn_count_path_name_len:
; --- count length of path name
move.l a2,a0 ; a0 := path name
moveq #0,d5 ; d5 := len count
bpln_count_loop:
tst.b (a0)+
beq bpln_check_path_name_len
addq.w #1,d5 ; inc len count
bra bpln_count_loop
bpln_check_path_name_len:
; --- compare path name len with max name len
cmp.w d5,d2
bgt bpln_build_full_path_name
; --- build limited path name
moveq #START_OF_PATH_NAME_LEN,d0
sub.w d3,d0 ; d0 := len of 'start of path name'
sub.w d0,d2 ; max len -= len of 'start of path name'
sub.w d0,d5 ; path name len -= len of 'start of path name'
subq.w #1,d0 ; dec for dbra
bpln_copy_start_of_path_name:
; --- copy 'start of path name' to buffer
move.b (a2)+,(a3)+
dbra d0,bpln_copy_start_of_path_name
; --- insert delimiters
moveq #'.',d0
move.b d0,(a3)+
move.b d0,(a3)+
move.b d0,(a3)+
subq.w #3,d2 ; dec max len
; --- copy end of path name to buffer
lea 0(a2,d5),a0 ; a0 := last char of path name
sub.w d2,a0 ; a0 := start of 'end of path name'
subq.w #1,d2 ; dec for dbra
bpln_copy_end_of_path_name:
move.b (a0)+,(a3)+
dbra d2,bpln_copy_end_of_path_name
bra bpln_exit
bpln_build_full_path_name:
; --- copy full path name to buffer
sub.w d5,d2 ; max_len -= path name len
subq.w #1,d5 ; dec for dbra
bmi bpln_fill_rest_of_buffer
bpln_copy_loop:
move.b (a2)+,(a3)+
dbra d5,bpln_copy_loop
bpln_fill_rest_of_buffer:
; -- fill rest of buffer with spaces
tst.w d4 ; no fill?
beq bpln_exit
moveq #' ',d0
subq.w #1,d2 ; dec for dbra
bpln_fill_loop:
move.b d0,(a3)+
dbra d2,bpln_fill_loop
bpln_exit:
; --- mark end of string
clr.b (a3)
PULL d2-d5/a2-a3
rts