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 >
Assembly Source File  |  1992-10-28  |  35KB  |  1,361 lines

  1.         *********************************
  2.         *                               *
  3.         *   Visual Shell v1.17  10/92   *
  4.         *                               *
  5.         *     by Torsten Jürgeleit      *
  6.         *                               *
  7.         *   assembly support routines   *
  8.         *            part I             *
  9.         *                               *
  10.         *********************************
  11.  
  12.     NOLIST
  13.     INCLUDE "exec/types.i"
  14.     INCLUDE "exec/ports.i"
  15.     INCLUDE "exec/nodes.i"
  16.     INCLUDE "exec/lists.i"
  17.     INCLUDE "exec/memory.i"
  18.     INCLUDE "devices/conunit.i"
  19.     INCLUDE "devices/inputevent.i"
  20.     INCLUDE "libraries/dos.i"
  21.     INCLUDE "libraries/dosextens.i"
  22.     INCLUDE "libraries/arpbase.i"
  23.     INCLUDE "intuition/intuition.i"
  24.     INCLUDE "equates.i"
  25.     LIST
  26.  
  27. ;---------------------------------------------------------------------------
  28. ; External definitions
  29. ;---------------------------------------------------------------------------
  30.  
  31.     XDEF    _input_event_handler
  32.     XDEF    _get_list_node
  33.     XDEF    _build_file_node
  34.     XDEF    _build_dev_node
  35.     XDEF    _insert_file_node
  36.     XDEF    _search_file_node
  37.     XDEF    _count_file_nodes
  38.     XDEF    _recount_file_nodes
  39.     XDEF    _sum_file_sizes
  40.     XDEF    _get_view_mode
  41.     XDEF    _build_view_line_list
  42.     XDEF    _get_first_visible_line
  43.     XDEF    _search_line_node
  44.     XDEF    _protection
  45.     XDEF    _build_limited_path_name
  46.  
  47. ;---------------------------------------------------------------------------
  48. ; External references
  49. ;---------------------------------------------------------------------------
  50.  
  51.     XREF    _IntuitionBase
  52.     XREF    _GfxBase
  53.     XREF    _gadget_buffer
  54.     XREF    _con_device
  55.     XREF    _con_unit
  56.     XREF    _con_window
  57.     XREF    _con_rport
  58.     XREF    _main_task
  59.     XREF    _vsh_port
  60.     XREF    _event_mode
  61.     XREF    _auto_repeat
  62.     XREF    _show_flag
  63.     XREF    _scroll_flag
  64.     XREF    _vsh_scroll_speed
  65.     XREF    _vsh_keyboard_type
  66.     XREF    _qualifier
  67.     XREF    _enable_abort
  68.     XREF    _num_lock
  69.     XREF    _key_table
  70.     XREF    _action_table
  71.     XREF    _scroll_flag_table
  72.     XREF    _action
  73.     XREF    _file_req
  74.     XREF    _view_req
  75.     XREF    _active_freq
  76.     XREF    _line1_buffer
  77.     XREF    _max_line_len
  78.     XREF    _print_dir_info
  79.     XREF    _print_info_line
  80.     XREF    _print_vreq_status
  81.     XREF    _print_quick_view
  82.     XREF    _SPrintf
  83.     XREF    _protection_bits
  84.     XREF    _protection_string
  85.     XREF    _font_data
  86.     XREF    _template_buffer
  87.     XREF    write_text
  88.  
  89. ;---------------------------------------------------------------------------
  90. ; struct InputEvent  *input_event_handler(event, data)
  91. ;                       a0      a1
  92. ;    struct InputEvent  *event
  93. ;    APTR data = data segment ptr for a4
  94. ; Tied into input chain and parses event list for VSh special keys
  95. ;---------------------------------------------------------------------------
  96. _input_event_handler:
  97.     PUSH    a0-a6/d0-d7
  98.  
  99.     move.l    a1,a4                ; a4 := data segment ptr
  100.     move.l    _IntuitionBase,a1
  101.     move.l    ib_ActiveWindow(a1),a1
  102.     cmp.l    _con_window,a1            ; input for VSh con window ?
  103.     bne    ieh_exit
  104.     move.l    a0,a2                ; a2 := event
  105.     move.l    _main_task,a3            ; a3 := task ptr
  106.     move.l    (4).w,a6            ; a6 := exec base ptr
  107.     move.l    _vsh_port,a0            ; a0 := msg port
  108.     moveq    #0,d0
  109.     move.b    MP_SIGBIT(a0),d0        ; d0 := signal bit
  110.     moveq    #0,d4
  111.     bset    d0,d4                ; d4 := signal mask
  112.     moveq    #0,d5                ; clear "don't clear event" flag
  113.     bra    ieh_check_next_event
  114.  
  115. ieh_event_loop:
  116.     move.b    ie_Class(a2),d1            ; check ie_Class
  117.  
  118. ieh_check_raw_mouse:
  119.     cmp.b    #IECLASS_RAWMOUSE,d1        ; raw mouse event ?
  120.     bne    ieh_check_raw_key
  121.     move.w    ie_Code(a2),d0            ; check ie_Code
  122.     cmp.w    #IECODE_LBUTTON,d0        ; left or right button pressed ?
  123.     beq    ieh_mouse_button_pressed
  124.     cmp.w    #IECODE_RBUTTON,d0
  125.     bne    ieh_next_event
  126.  
  127. ieh_mouse_button_pressed:
  128.     move.b    _event_mode,d0            ; input for input or config gadget ?
  129.     cmp.b    #EVENT_MODE_INPUT,d0        ; if yes, don't report any mouse button events
  130.     beq    ieh_clear_event
  131.     cmp.b    #EVENT_MODE_CONFIG,d0
  132.     beq    ieh_clear_event
  133.     bra    ieh_next_event
  134.  
  135. ieh_check_raw_key:
  136.     cmp.b    #IECLASS_RAWKEY,d1        ; raw key event ?
  137.     bne    ieh_next_event
  138.     cmp.b    #EVENT_MODE_IGNORE,_event_mode    ; ignore input for VSh ?
  139.     beq    ieh_clear_event
  140.     move.w    ie_Code(a2),d2            ; d2 := key code
  141.     move.w    ie_Qualifier(a2),d3        ; d3 := qualifier
  142.     and.w    #QUALIFIER_MASK,d3        ; mask unused qualifier bits
  143.  
  144. ieh_search_key:
  145.     lea    _key_table,a0            ; search raw key code in table
  146.     move.w    d2,d1                ; d1 := key code
  147.     bclr    #IECODEB_UP_PREFIX,d1        ; mask key up prefix
  148.     moveq    #MAX_ACTION_KEYS-1,d0
  149.  
  150. ieh_search_key_loop:
  151.     cmp.w    (a0)+,d1            ; key code in table ?
  152.     beq    ieh_get_qualifier_bit_or_action_code
  153.     dbra    d0,ieh_search_key_loop
  154.  
  155. ieh_unknown_key:
  156.     btst    #IECODEB_UP_PREFIX,d2        ; ignore key up events
  157.     bne    ieh_next_event
  158.     move.b    _event_mode,d0            ; d0 := event mode
  159.  
  160. ieh_unknown_key_for_config:
  161.     cmp.b    #EVENT_MODE_CONFIG,d0        ; input for config gadget ?
  162.     bne    ieh_unknown_key_for_input
  163.     btst    #IEQUALIFIERB_REPEAT,d3        ; ignore auto repeat
  164.     bne    ieh_next_event
  165.     cmp.w    #IECODE_UP_ARROW,d2
  166.     beq    ieh_config_up_arrow
  167.     cmp.w    #IECODE_DOWN_ARROW,d2
  168.     bne    ieh_next_event
  169.  
  170. ieh_config_down_arrow:
  171.     move.w    #IECODE_RETURN,ie_Code(a2)    ; convert arrow key code to return
  172.     moveq    #VSH_ACTION_GADGET_END_KEY,d1    ; d1 := action code
  173.     bra    ieh_set_config_or_input_key_action
  174.  
  175. ieh_config_up_arrow:
  176.     move.w    #IECODE_RETURN,ie_Code(a2)    ; convert arrow key code to return
  177.     moveq    #VSH_ACTION_SHIFT_GADGET_END_KEY,d1    ; d1 := action code
  178.     bra    ieh_set_config_or_input_key_action
  179.  
  180. ieh_unknown_key_for_input:
  181.     cmp.b    #EVENT_MODE_INPUT,d0        ; input for input gadget ?
  182.     bne    ieh_unknown_key_for_speed_search
  183.     moveq    #VSH_ACTION_SPEED_SEARCH,d1    ; d1 := action code
  184.  
  185. ieh_set_config_or_input_key_action:
  186.     moveq    #1,d5                ; set "don't clear event" flag
  187.     bra    ieh_set_action
  188.  
  189. ieh_unknown_key_for_speed_search:
  190.     tst.b    _num_lock            ; num lock set ?
  191.     beq    ieh_next_event            ; if no, normal alt keys
  192.     btst    #IEQUALIFIERB_REPEAT,d3        ; ignore auto repeat
  193.     bne    ieh_next_event
  194.     cmp.w    #IEQUALIFIER_LALT,d3        ; alt key + letter -> speed search
  195.     beq    ieh_set_speed_search_action
  196.     cmp.w    #IEQUALIFIER_RALT,d3
  197.     bne    ieh_next_event
  198.  
  199. ieh_set_speed_search_action:
  200.     bsr    raw_key_convert            ; convert raw key event to ASCII
  201.     cmp.l    #1,d0                ; one char converted ?
  202.     bne    ieh_next_event
  203.     moveq    #VSH_ACTION_SPEED_SEARCH,d1    ; d1 := action code
  204.     bra    ieh_set_action
  205.  
  206. ieh_get_qualifier_bit_or_action_code:
  207.     lea    _action_table,a0
  208.     moveq    #MAX_ACTION_KEYS-1,d1
  209.     sub.w    d0,d1
  210.     move.w    d1,d0                ; d0 := pos in key code table
  211.     move.b    (a0,d0.w),d1            ; d1 := qualifier bit or action code
  212.     cmp.w    #MAX_QUALIFIER_KEYS,d0        ; check pos in action table
  213.     bhs    ieh_action_code
  214.  
  215. ieh_qualifier_bit:
  216.     btst    #IECODEB_UP_PREFIX,d2        ; qualifier key up ?
  217.     bne    ieh_qualifier_up
  218.  
  219. ieh_qualifier_down:
  220.     bset    d1,_qualifier            ; set qualifier bit
  221.     bra    ieh_set_qualifier_action
  222.  
  223. ieh_qualifier_up:
  224.     bclr    d1,_qualifier            ; clear qualifier bit
  225.  
  226. ieh_set_qualifier_action:
  227.     cmp.b    #EVENT_MODE_NORMAL,_event_mode    ; normal event mode ?
  228.     bne    ieh_next_event
  229.     moveq    #VSH_ACTION_QUALIFIER,d1    ; d1 := action code
  230.     bra    ieh_set_action            ; set action only for none gadget input event
  231.  
  232. ieh_action_code:
  233.     bclr    #IECODEB_UP_PREFIX,d2        ; ignore key up events
  234.     bne    ieh_clear_flags
  235.     move.b    _event_mode,d0            ; d0 := event mode
  236.     cmp.b    #EVENT_MODE_INPUT,d0        ; input for input or config gadget ?
  237.     beq    ieh_check_end_gadget
  238.     cmp.b    #EVENT_MODE_CONFIG,d0
  239.     bne    ieh_check_return
  240.  
  241. ieh_check_config_fkeys:
  242.     cmp.b    #VSH_ACTION_F10,d1        ; f1 - f4 or f10 pressed ?
  243.     beq    ieh_convert_config_fkey
  244.     cmp.w    #VSH_ACTION_F4,d1
  245.     bhi    ieh_check_end_gadget        ; illegal fkey
  246.  
  247. ieh_convert_config_fkey:
  248.     tst.w    d3                ; no qualifier ?
  249.     bne    ieh_next_event
  250.     move.w    #IECODE_RETURN,ie_Code(a2)    ; convert fkey code to return
  251.     bra    ieh_set_end_gadget_action
  252.  
  253. ieh_check_end_gadget:
  254.     cmp.b    #VSH_ACTION_ESC,d1        ; esc key pressed ?
  255.     beq    ieh_convert_esc_to_return
  256.     cmp.b    #VSH_ACTION_RETURN,d1        ; return pressed ?
  257.     beq    ieh_check_shift_end_gadget
  258.     cmp.b    #VSH_ACTION_NUM_ENTER,d1    ; enter pressed ?
  259.     bne    ieh_next_event
  260.  
  261. ieh_check_shift_end_gadget:            ; shifted finish gadget input ?
  262.     bclr    #IEQUALIFIERB_NUMERICPAD,d3
  263.     cmp.w    #IEQUALIFIER_LSHIFT,d3        ; shift key pressed ?
  264.     beq    ieh_shift_end_gadget
  265.     cmp.w    #IEQUALIFIER_RSHIFT,d3
  266.     beq    ieh_shift_end_gadget
  267.  
  268. ieh_end_gadget:
  269.     move.b    #VSH_ACTION_GADGET_END_KEY,d1    ; d1 := action code
  270.     bra    ieh_set_end_gadget_action
  271.  
  272. ieh_shift_end_gadget:                ; shift return or enter for jump to next entry
  273.     move.b    #VSH_ACTION_SHIFT_GADGET_END_KEY,d1    ; d1 := action code
  274.     cmp.b    #EVENT_MODE_CONFIG,d0        ; input for config ?
  275.     bne    ieh_set_action
  276.     and.w    #~(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT),ie_Qualifier(a2)
  277.     bra    ieh_set_end_gadget_action
  278.  
  279. ieh_convert_esc_to_return
  280.     move.w    #IECODE_RETURN,ie_Code(a2)    ; convert esc key code to return
  281.  
  282. ieh_set_end_gadget_action:
  283.     bclr    #IEQUALIFIERB_REPEAT,d3        ; ignore auto repeat
  284.     bne    ieh_clear_event
  285.     moveq    #1,d5                ; set "don't clear event" flag
  286.     cmp.b    #EVENT_MODE_INPUT,_event_mode
  287.     bne    ieh_set_action
  288.     move.b    #EVENT_MODE_NORMAL,_event_mode    ; reset input event mode to normal
  289.     bra    ieh_set_action
  290.  
  291. ieh_check_return:
  292.     cmp.b    #VSH_ACTION_RETURN,d1        ; return key pressed ?
  293.     beq    ieh_next_event
  294.  
  295. ieh_check_repeat:
  296.     bclr    #IEQUALIFIERB_REPEAT,d3        ; auto repeat ?
  297.     beq    ieh_check_numlock_key
  298.     cmp.b    #VSH_ACTION_SCROLL_PAGE_UP,d1    ; check action for autorepeatable action
  299.     blo    ieh_clear_flags
  300.     cmp.b    #VSH_ACTION_MARK_FILE,d1
  301.     bhi    ieh_clear_flags
  302.     move.b    #1,_auto_repeat            ; set auto repeat flag
  303.     tst.b    _num_lock            ; num lock set ?
  304.     beq    ieh_next_event            ; if no, normal numeric pad keys
  305.     bra    ieh_check_shift
  306.  
  307. ieh_check_numlock_key:
  308.     cmp.b    #KEYBOARD_TYPE1,_vsh_keyboard_type
  309.     bne    ieh_numlock_keyboard_type2
  310.  
  311. ieh_numlock_keyboard_type1:
  312.     cmp.b    #VSH_ACTION_NUM_MINUS,d1    ; numlock key pressed ?
  313.     bne    ieh_check_numlock
  314.     cmp.w    #IEQUALIFIER_LALT|IEQUALIFIER_NUMERICPAD,d3
  315.     beq    ieh_set_numlock_action
  316.     cmp.w    #IEQUALIFIER_RALT|IEQUALIFIER_NUMERICPAD,d3
  317.     bne    ieh_check_numlock
  318.     bra    ieh_set_numlock_action
  319.  
  320. ieh_numlock_keyboard_type2:
  321.     cmp.b    #VSH_ACTION_NUM_LEFT_BRAKET,d1    ; numlock key pressed ?
  322.     bne    ieh_check_numlock
  323.  
  324. ieh_set_numlock_action:
  325.     moveq    #VSH_ACTION_NUMLOCK,d1        ; d1 := action code
  326.     bra    ieh_set_action
  327.  
  328. ieh_check_numlock:
  329.     tst.b    _num_lock            ; num lock set ?
  330.     beq    ieh_next_event            ; if no, normal numeric pad keys
  331.  
  332. ieh_check_control:
  333.     btst    #IEQUALIFIERB_CONTROL,d3    ; control key pressed ?
  334.     beq    ieh_check_shift
  335.     and.w    #~(IEQUALIFIER_CONTROL),ie_Qualifier(a2)    ; clear control qualifier bit
  336.     bra    ieh_next_event            ; normal events
  337.  
  338. ieh_check_shift:
  339.     bclr    #IEQUALIFIERB_NUMERICPAD,d3
  340.     cmp.w    #IEQUALIFIER_LSHIFT,d3        ; shift key pressed ?
  341.     beq    ieh_shift_action
  342.     cmp.w    #IEQUALIFIER_RSHIFT,d3
  343.     bne    ieh_check_alternate
  344.  
  345. ieh_shift_action:
  346.     add.b    #SHIFTED,d1            ; change to shifted action code
  347.     bra    ieh_set_action
  348.  
  349. ieh_check_alternate:
  350.     cmp.w    #IEQUALIFIER_LALT,d3        ; alternate key pressed ?
  351.     beq    ieh_alternate_action
  352.     cmp.w    #IEQUALIFIER_RALT,d3
  353.     bne    ieh_check_alternate_shift
  354.  
  355. ieh_alternate_action:
  356.     add.b    #ALTERNATED,d1            ; change to alternated action code
  357.     bra    ieh_set_action
  358.  
  359. ieh_check_alternate_shift:
  360.     cmp.w    #IEQUALIFIER_LSHIFT|IEQUALIFIER_LALT,d3        ; alternate + shift key pressed ?
  361.     beq    ieh_alternate_shift_action
  362.     cmp.w    #IEQUALIFIER_RSHIFT|IEQUALIFIER_RALT,d3
  363.     bne    ieh_check_qualifier
  364.  
  365. ieh_alternate_shift_action:
  366.     add.b    #ALTERNATED+SHIFTED,d1        ; change to alternated + shifted action code
  367.     bra    ieh_set_action
  368.  
  369. ieh_check_qualifier:
  370.     tst.w    d3                ; other qualifier ?
  371.     bne    ieh_next_event
  372.  
  373. ieh_set_action:
  374.     move.b    d1,_action
  375.  
  376. ieh_check_scrolling:
  377.     cmp.b    #VSH_ACTION_SCROLL_TOP,d1    ; check action for scrolling action
  378.     blo    ieh_check_esc
  379.     cmp.b    #VSH_ACTION_SCROLL_RIGHT,d1
  380.     bhi    ieh_check_esc
  381.     lea    _scroll_flag_table,a0        ; set scroll flag
  382.     sub.b    #VSH_ACTION_SCROLL_TOP+1,d1
  383.     ext.w    d1
  384.     move.b    (a0,d1.w),_scroll_flag
  385.     bra    ieh_signal_task
  386.  
  387. ieh_check_esc:
  388.     tst.b    _enable_abort            ; ESC abort enabled ?
  389.     beq    ieh_signal_task
  390.     cmp.b    #VSH_ACTION_ESC,d1        ; ESC key pressed ?
  391.     bne    ieh_signal_task
  392.  
  393. ieh_set_ctrl_c:
  394.     move.l    #SIGBREAKF_CTRL_C,d0        ; d0 := signal mask
  395.     move.l    a3,a1                ; a1 := task ptr
  396.     CALLSYS    Signal                ; set ctrl c signal
  397.  
  398. ieh_signal_task:
  399.     move.l    d4,d0                ; d0 := signal mask
  400.     move.l    a3,a1                ; a1 := task ptr
  401.     CALLSYS    Signal                ; signal main task
  402.  
  403. ieh_check_dont_clear_event_flag:
  404.     tst.b    d5                ; "don't clear event" flag set ?
  405.     bne    ieh_next_event            ; if yes, don't clear this event
  406.     bra    ieh_clear_event
  407.  
  408. ieh_clear_flags:
  409.     clr.b    _auto_repeat
  410.     clr.b    _scroll_flag
  411.  
  412. ieh_clear_event:
  413.     move.w    #IECLASS_NULL,ie_Class(a2)
  414.  
  415. ieh_next_event:
  416.     move.l    ie_NextEvent(a2),a2        ; get next event in list
  417.  
  418. ieh_check_next_event:
  419.     move.l    a2,d0                ; next event ptr == NULL ?
  420.     bne    ieh_event_loop
  421.  
  422. ieh_exit:
  423.     PULL    a0-a6/d0-d7
  424.     move.l    a0,d0                ; return old event list ptr
  425.     rts
  426.  
  427. ;---------------------------------------------------------------------------
  428. ; BOOL raw_key_convert(event)
  429. ;            a2
  430. ;    struct InputEvent  *event
  431. ; Convert a raw key input event into an ASCII char
  432. ;---------------------------------------------------------------------------
  433. raw_key_convert:
  434.     PUSH    a2/a6
  435.  
  436.     clr.w    ie_Qualifier(a2)        ; clear qualifier -> no alt
  437.     move.l    a2,a0                ; a0 := input event ptr
  438.     lea    _gadget_buffer,a1        ; a1 := buffer ptr
  439.     moveq    #1,d1                ; d1 := buffer length
  440.     move.l    _con_unit,a2            ; get ConUnit ptr
  441.     lea    cu_KeyMapStruct(a2),a2        ; a2 := keymap ptr
  442.     move.l    _con_device,a6            ; get ConsoleBase ptr
  443.     CALLSYS    RawKeyConvert
  444.     lea    _gadget_buffer,a1        ; a1 := buffer ptr
  445.     clr.b    1(a1)                ; set end of string
  446.  
  447.     PULL    a2/a6
  448.     rts
  449.  
  450. ;---------------------------------------------------------------------------
  451. ; struct MinNode  *get_list_node(list, num_entries, num)
  452. ;                  a0       d0       d1
  453. ;     struct MinList  *list
  454. ;    ULONG num_entries, num
  455. ; Get specified entry from list
  456. ;---------------------------------------------------------------------------
  457. _get_list_node:
  458.     tst.l    d0                ; no entries in list ?
  459.     beq    gln_return_null
  460.     sub.l    d1,d0                ; num > num_entries ?
  461.     bmi    gln_return_last_node
  462.     cmp.l    d1,d0                ; num >= (num_entries - num) ?
  463.     bhs    gln_from_end
  464.  
  465. gln_from_start:
  466.     move.l    MLH_HEAD(a0),a0            ; a0 := first node
  467.     bra    gln_start_check
  468.  
  469. gln_start_loop:
  470.     move.l    MLN_SUCC(a0),a0            ; get next node
  471.  
  472. gln_start_check:
  473.     subq.l    #1,d1                ; dec num
  474.     bne    gln_start_loop
  475.     bra    gln_return_current_node
  476.  
  477. gln_from_end:
  478.     move.l    MLH_TAILPRED(a0),a0        ; a0 := last node
  479.     bra    gln_end_check
  480.  
  481. gln_end_loop:
  482.     move.l    MLN_PRED(a0),a0            ; get previous node
  483.  
  484. gln_end_check:
  485.     subq.l    #1,d0                ; dec num
  486.     bpl    gln_end_loop
  487.  
  488. gln_return_current_node:
  489.     move.l    a0,d0                ; d0 := current node
  490.     rts
  491.  
  492. gln_return_last_node;
  493.     move.l    MLH_TAILPRED(a0),d0        ; d0 := last node
  494.     rts
  495.  
  496. gln_return_null:
  497.     moveq    #0,d0                ; d0 := NULL
  498.     rts
  499.  
  500. ;---------------------------------------------------------------------------
  501. ; struct FileNode  *build_file_node(fib)
  502. ;                    a0
  503. ;     struct FileInfoBlock  *fib
  504. ; Allocate memory for file node and fill it with data from fle info block
  505. ;---------------------------------------------------------------------------
  506. _build_file_node:
  507.     PUSH    a2-a3/a6
  508.  
  509.     move.l    a0,a3                ; a3 := fib
  510.  
  511.     ; --- alloc memory for new file node
  512.     moveq    #FileNode_Sizeof,d0
  513.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  514.     move.l    (4).w,a6            ; a6 := exec base
  515.     CALLSYS    AllocMem
  516.     tst.l    d0
  517.     beq    bfn_error
  518.     move.l    d0,a2                ; a2 := file node ptr
  519.  
  520.     ; --- init file node
  521.     lea    fib_FileName(a3),a0        ; source ptr
  522.     lea    fn_Text(a2),a1            ; dest ptr
  523.     moveq    #0,d0                ; reset name len counter
  524.  
  525. bfn_copy_loop:
  526.     move.b    (a0)+,d1            ; copy a char till null
  527.     beq    bfn_fill_spaces
  528.     move.b    d1,(a1)+
  529.     addq.w    #1,d0
  530.     cmp.w    #MAX_FILE_NAME_LEN,d0
  531.     blo    bfn_copy_loop
  532.  
  533. bfn_fill_spaces:
  534.     move.w    d0,fn_NameLen(a2)        ; save name len
  535.     moveq    #' ',d1
  536.     bra    bfn_check_len
  537.  
  538. bfn_fill_loop:
  539.     move.b    d1,(a1)+            ; fill string with spaces
  540.     addq.w    #1,d0
  541.  
  542. bfn_check_len:
  543.     cmp.w    #MAX_FILE_NAME_LEN+1,d0        ; one additional space as delimiter
  544.     blo    bfn_fill_loop
  545.  
  546. bfn_copy_date:
  547.     move.l    fib_DateStamp+ds_Days(a3),fn_Date+ds_Days(a2)
  548.     move.l    fib_DateStamp+ds_Minute(a3),fn_Date+ds_Minute(a2)
  549.     move.l    fib_DateStamp+ds_Tick(a3),fn_Date+ds_Tick(a2)
  550.  
  551. bfn_copy_protection:
  552.     move.l    fib_Protection(a3),d0
  553.     tst.b    fib_Comment(a3)            ; any comment ?
  554.     beq    bfn_no_comment
  555.     bset    #MAX_PROTECTION_BITS-1,d0    ; set comment bit
  556.  
  557. bfn_no_comment:
  558.     move.w    d0,fn_Protection(a2)
  559.  
  560. bfn_check_type:
  561.     moveq    #ENTRY_TYPE_FILE,d0        ; default type = file
  562.     lea    bfn_size_fmt_string,a0        ; default size text = number
  563.     tst.l    fib_DirEntryType(a3)        ; check file type
  564.     bmi    bfn_set_type            ; < 0 => it's a file
  565.     moveq    #ENTRY_TYPE_DIR,d0        ; type = dir
  566.     lea    bfn_dir_fmt_string,a0        ; size text = dir
  567.  
  568. bfn_set_type:
  569.     move.b    d0,fn_Type(a2)            ; set file type
  570.     move.l    fib_Size(a3),d0
  571.     move.l    d0,fn_Size(a2)            ; set file size
  572.     move.l    d0,-(sp)            ; size -> only valid for files
  573.     move.l    a0,-(sp)            ; format string
  574.     move.l    a1,-(sp)            ; dest string
  575.     CALL    _SPrintf            ; append size to string
  576.     lea    3*4(sp),sp
  577.     move.l    a2,d0                ; return value
  578.  
  579. bfn_exit:
  580.     PULL    a2-a3/a6
  581.     rts
  582.  
  583. bfn_error:
  584.     moveq    #0,d0
  585.     bra    bfn_exit
  586.  
  587. bfn_size_fmt_string:
  588.     dc.b    "%8ld",0
  589. bfn_dir_fmt_string:
  590.     dc.b    "   (Dir)",0
  591.  
  592. ;---------------------------------------------------------------------------
  593. ; struct FileNode  *build_dev_node(dlist)
  594. ;                    a0
  595. ;     struct DosList  *dlist
  596. ; Allocate memory for a device node and fill it with data from dos list
  597. ;---------------------------------------------------------------------------
  598. _build_dev_node:
  599.     PUSH    a2-a3/a6
  600.  
  601.     move.l    a0,a3                ; a3 := dos list
  602.  
  603.     ; --- alloc memory for file node
  604.     moveq    #FileNode_Sizeof,d0
  605.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  606.     move.l    (4).w,a6            ; a6 := exec base
  607.     CALLSYS    AllocMem
  608.     tst.l    d0
  609.     beq    bdn_error
  610.     move.l    d0,a2                ; a2 := file node ptr
  611.  
  612.     ; --- init file node
  613.     move.l    a3,d0                ; dlist == NULL ?
  614.     bne    bdn_no_ram_disk
  615.  
  616. bdn_ram_disk:
  617.     move.w    #4,fn_NameLen(a2)        ; build a device node for RAM:
  618.     lea    bdn_ram_string,a0        ; source ptr
  619.     lea    fn_Text(a2),a1            ; dest ptr
  620.     moveq    #1,d0                ; type := device
  621.     bra    bdn_set_type
  622.  
  623. bdn_no_ram_disk:
  624.     move.l    dvi_Name(a3),d0
  625.     lsl.l    #2,d0                ; make BPTR to PTR
  626.     move.l    d0,a0
  627.     move.b    (a0),d1                ; d1 := length of BSTR
  628.     add.l    #1,a0                ; source ptr
  629.     lea    fn_Text(a2),a1            ; dest ptr
  630.     moveq    #0,d0                ; rest name len counter
  631.  
  632. bdn_copy_loop:
  633.     move.b    (a0)+,(a1)+            ; copy a char
  634.     addq.w    #1,d0
  635.     cmp.w    #MAX_FILE_NAME_LEN,d0
  636.     bhs    bdn_append_colon
  637.     cmp.b    d1,d0                ; end of name ?
  638.     blo    bdn_copy_loop
  639.  
  640. bdn_append_colon:
  641.     move.b    #':',(a1)+            ; append colon to name
  642.     add.w    #1,d0
  643.  
  644. bdn_fill_line:
  645.     move.w    d0,fn_NameLen(a2)        ; save name len
  646.     moveq    #' ',d1
  647.     bra    bdn_check_len
  648.  
  649. bdn_fill_loop:
  650.     move.b    d1,(a1)+            ; fill string with spaces
  651.     addq.w    #1,d0
  652.  
  653. bdn_check_len:
  654.     cmp.w    #MAX_FILE_NAME_LEN+1,d0        ; one additional space as delimiter
  655.     blo    bdn_fill_loop
  656.  
  657.     moveq    #ENTRY_TYPE_ASSIGN,d0        ; default type = assign
  658.     lea    bdn_assign_string,a0        ; default text = assign
  659.     tst.l    dvi_Type(a3)            ; check dos list type
  660.     bne    bdn_set_type            ; != 0 => it's a assign
  661.     moveq    #ENTRY_TYPE_DEVICE,d0        ; type = device
  662.     lea    bdn_device_string,a0        ; text = device
  663.  
  664. bdn_set_type:
  665.     move.b    d0,fn_Type(a2)            ; set file type
  666.  
  667. bdn_append_type:
  668.     move.b    (a0)+,(a1)+            ; append type to text
  669.     bne    bdn_append_type
  670.  
  671.     move.l    a2,d0                ; return value
  672.  
  673. bdn_exit:
  674.     PULL    a2-a3/a6
  675.     rts
  676.  
  677. bdn_error:
  678.     moveq    #0,d0
  679.     bra    bdn_exit
  680.  
  681. bdn_assign_string:
  682.     dc.b    "   (Asn)",0
  683. bdn_device_string:
  684.     dc.b    "   (Dev)",0
  685. bdn_ram_string:
  686.     dc.b    "RAM:                              (Dev)",0
  687.  
  688. ;---------------------------------------------------------------------------
  689. ; VOID insert_file_node(node, list)
  690. ;             a0    a1
  691. ;    struct FileNode  *node
  692. ;    struct MinList   *list
  693. ; Insert file node into list according to type and name
  694. ;---------------------------------------------------------------------------
  695. _insert_file_node:
  696.     PUSH    a2-a3/a5-a6
  697.  
  698.     move.l    a0,a2                ; a2 := node
  699.     move.l    a1,a3                ; a3 := list
  700.     move.l    a3,a5                ; save list ptr
  701.     move.l    MLH_HEAD(a3),a3            ; a3 := list->mlh_Head
  702.  
  703. ifn_search_loop:
  704.     tst.l    MLN_SUCC(a3)            ; end of list ?
  705.     beq    ifn_insert
  706.  
  707.     move.l    a2,a0                ; a0 := new node
  708.     move.l    a3,a1                ; a1 := node from list
  709.     bsr    compare_file_nodes
  710.     tst.b    d0
  711.     beq    ifn_insert
  712.     move.l    MLN_SUCC(a3),a3            ; next node
  713.     bra    ifn_search_loop
  714.  
  715. ifn_insert:
  716.     move.l    a5,a0                ; a0 := list
  717.     move.l    a2,a1                ; a1 := new node
  718.     move.l    MLN_PRED(a3),a2            ; a2 := node from list
  719.     move.l    (4).w,a6            ; a6 := exec base
  720.     CALLSYS    Insert
  721.  
  722.     PULL    a2-a3/a5-a6
  723.     rts
  724.  
  725. compare_file_nodes:        ; (a0 := file node 1, a1 := file node 2)
  726.     move.b    fn_Type(a0),d1            ; compare type of entries
  727.     cmp.b    fn_Type(a1),d1
  728.     beq    cfn_alpha            ; same type -> sort alphabetical
  729.     bcs    cfn_match            ; a0->fn_Type > a1->fn_Type
  730.     bra    cfn_no_match            ; a0->fn_Type < a1->fn_Type
  731.  
  732. cfn_alpha:
  733.     lea    fn_Text(a0),a0            ; compare name of entries
  734.     lea    fn_Text(a1),a1
  735.  
  736. cfn_alpha_loop:
  737.     move.b    (a0)+,d0            ; convert char to lower case
  738.     cmp.b    #'A',d0
  739.     blo    1$
  740.     cmp.b    #'Z',d0
  741.     bhi    1$
  742.     add.b    #32,d0
  743.  
  744. 1$:
  745.     move.b    (a1)+,d1            ; convert char to lower case
  746.     cmp.b    #'A',d1
  747.     blo    2$
  748.     cmp.b    #'Z',d1
  749.     bhi    2$
  750.     add.b    #32,d1
  751.  
  752. 2$:
  753.     tst.b    d0                ; end of first name ?
  754.     beq    3$
  755.     cmp.b    d1,d0
  756.     beq    cfn_alpha_loop
  757.  
  758. 3$:
  759.     sub.b    d1,d0
  760.     bls    cfn_no_match
  761.  
  762. cfn_match:
  763.     moveq    #1,d0                ; file node 1 > file node 2
  764.     rts
  765.  
  766. cfn_no_match:
  767.     moveq    #0,d0                ; file node 1 <= file node 2
  768.     rts
  769.  
  770. ;---------------------------------------------------------------------------
  771. ; struct FileNode  *search_file_node(node, name, name_len)
  772. ;                      a0    a1      d0
  773. ;    struct FileNode  *node
  774. ;    UBYTE  *name
  775. ;    USHORT name_len
  776. ; Search file node in list which file name starts with name
  777. ;---------------------------------------------------------------------------
  778. _search_file_node:
  779.     PUSH    d2/a2-a3
  780.  
  781.     move.l    a1,d1                ; node == NULL ?
  782.     beq    sfn_not_found
  783.     move.l    a0,a2                ; a2 := node
  784.     move.l    a1,a3                ; a3 := name
  785.     move.w    d0,d2                ; d2 := name length
  786.  
  787. sfn_search_loop:
  788.     tst.l    MLN_SUCC(a2)            ; end of list ?
  789.     beq    sfn_not_found
  790.     tst.w    d2                ; length given ?
  791.     beq    sfn_compare_names
  792.     cmp.w    fn_NameLen(a2),d2        ; same name length ?
  793.     bne    sfn_next_entry
  794.  
  795. sfn_compare_names:
  796.     move.l    a3,a0                ; a0 := search name
  797.     lea    fn_Text(a2),a1            ; a1 := name from node
  798.     bsr    compare_names
  799.     tst.b    d0
  800.     beq    sfn_found
  801.  
  802. sfn_next_entry:
  803.     move.l    MLN_SUCC(a2),a2            ; next node
  804.     bra    sfn_search_loop
  805.  
  806. sfn_found:
  807.     move.l    a2,d0                ; d0 := file node -> return value
  808.  
  809. sfn_exit:
  810.     PULL    d2/a2-a3
  811.     rts
  812.  
  813. sfn_not_found:
  814.     moveq    #0,d0                ; d0 := NULL -> return value
  815.     bra    sfn_exit
  816.  
  817.  
  818. compare_names:        ; (a0 := search name, a1 := name from node)
  819.     move.b    (a0)+,d0            ; convert char to lower case
  820.     tst.w    d2                ; name length given ?
  821.     bne    1$
  822.     cmp.b    #'A',d0
  823.     blo    1$
  824.     cmp.b    #'Z',d0
  825.     bhi    1$
  826.     add.b    #32,d0
  827.  
  828. 1$:
  829.     move.b    (a1)+,d1            ; convert char to lower case
  830.     tst.w    d2                ; name length given ?
  831.     bne    2$
  832.     cmp.b    #'A',d1
  833.     blo    2$
  834.     cmp.b    #'Z',d1
  835.     bhi    2$
  836.     add.b    #32,d1
  837.  
  838. 2$:
  839.     tst.b    d0                ; end of first name ?
  840.     beq    cn_match
  841.     cmp.b    d1,d0
  842.     beq    compare_names
  843.     bne    cn_no_match
  844.  
  845. cn_match:
  846.     moveq    #0,d0                ; search name == name from node
  847.     rts
  848.  
  849. cn_no_match:
  850.     moveq    #1,d0                ; search name != name from node
  851.     rts
  852.  
  853. ;---------------------------------------------------------------------------
  854. ; ULONG count_file_nodes(list)
  855. ;              a0
  856. ;    struct MinList  *list
  857. ; Count file nodes in list and set position of all nodes
  858. ;---------------------------------------------------------------------------
  859. _count_file_nodes:
  860.     move.l    MLH_HEAD(a0),a0            ; a0 := first node in list
  861.     moveq    #0,d0                ; reset node counter
  862.  
  863. cfn_loop:
  864.     tst.l    MLN_SUCC(a0)            ; end of list ?
  865.     beq    cfn_exit
  866.     addq.l    #1,d0
  867.     move.l    d0,fn_Pos(a0)            ; set pos of node
  868.     move.l    MLN_SUCC(a0),a0            ; next node
  869.     bra    cfn_loop
  870.  
  871. cfn_exit:
  872.     rts
  873.  
  874. ;---------------------------------------------------------------------------
  875. ; ULONG recount_file_nodes(fnode)
  876. ;                a0
  877. ;    struct FileNode  *fnode
  878. ; Count file nodes in list from given node and dec position of all nodes
  879. ;---------------------------------------------------------------------------
  880. _recount_file_nodes:
  881.     move.l    fn_Pos(a0),d0            ; d0 := old fnode counter
  882.     subq.l    #1,d0                ; dec node counter, because this fnode will be removed
  883.     bra    rfn_next            ; start from next fnode
  884.  
  885. rfn_loop:
  886.     tst.l    MLN_SUCC(a0)            ; end of list ?
  887.     beq    rfn_exit
  888.     addq.l    #1,d0
  889.     move.l    d0,fn_Pos(a0)            ; set pos of node
  890.  
  891. rfn_next:
  892.     move.l    MLN_SUCC(a0),a0            ; next node
  893.     bra    rfn_loop
  894.  
  895. rfn_exit:
  896.     rts
  897.  
  898. ;---------------------------------------------------------------------------
  899. ; VOID sum_file_sizes(freq)
  900. ;               a0
  901. ;    struct FileRequest  *freq
  902. ; Count dirs and files in list and calc total size of all files
  903. ;---------------------------------------------------------------------------
  904. _sum_file_sizes:
  905.     PUSH    d2-d3
  906.  
  907.     move.l    a0,a1                ; a1 := freq ptr
  908.     moveq    #0,d1                ; reset dir counter
  909.     moveq    #0,d2                ; reset file counter
  910.     moveq    #0,d3                ; reset size counter
  911.     move.l    fr_Display+d_List(a1),a0    ; a0 := file list ptr
  912.     move.l    MLH_HEAD(a0),a0            ; a0 := first node in list
  913.     move.l    fr_Display+d_NumEntries(a1),d0    ; d0 := entry count
  914.     beq    sfs_exit
  915.  
  916. sfs_loop:
  917.     cmp.b    #ENTRY_TYPE_FILE,fn_Type(a0)    ; file ?
  918.     beq    sfs_file
  919.  
  920. sfs_dir:
  921.     addq.l    #1,d1                ; inc dir counter
  922.     bra    sfs_next
  923.  
  924. sfs_file:
  925.     addq.l    #1,d2                ; inc file counter
  926.     add.l    fn_Size(a0),d3            ; add size
  927.  
  928. sfs_next:
  929.     move.l    MLN_SUCC(a0),a0            ; next node
  930.     subq.l    #1,d0
  931.     bne    sfs_loop
  932.  
  933. sfs_exit:
  934.     lea    fr_Info(a1),a0            ; save data
  935.     move.l    d1,i_Dirs(a0)
  936.     move.l    d2,i_Files(a0)
  937.     move.l    d3,i_FileSizes(a0)
  938.  
  939.     PULL    d2-d3
  940.     rts
  941.  
  942. ;---------------------------------------------------------------------------
  943. ; USHORT get_view_mode(vreq)
  944. ;            a0
  945. ;    struc t ViewRequest  *vreq
  946. ; Check file buffer for binaries and return view mode (ASCII or hex dump)
  947. ;---------------------------------------------------------------------------
  948. _get_view_mode:
  949.     PUSH    d2
  950.  
  951.     move.l    a0,a1                ; a1 := vreq ptr
  952.     move.l    vr_Buffer(a1),a0        ; a0 := buffer ptr
  953.     move.l    vr_BufferSize(a1),d2        ; d1 := size
  954.     moveq    #VIEW_MODE_ASCII,d0        ; mode = ASCII dump
  955.  
  956. gvm_loop:
  957.     subq.l    #1,d2                ; end of buffer ?
  958.     bmi    gvm_exit
  959.     move.b    (a0)+,d1            ; get char from buffer
  960.  
  961. gvm_ascii:
  962.     cmp.b    #' ',d1                ; check for ASCII char
  963.     blo    gvm_alternate
  964.     cmp.b    #'~',d1
  965.     bls    gvm_loop            ; yes, its an ASCII char
  966.  
  967. gvm_alternate:
  968.     cmp.b    #160,d1                ; check for alternate char
  969.     blo    gvm_control_code
  970.     cmp.b    #255,d1
  971.     bls    gvm_loop            ; yes, its an alternate char
  972.  
  973. gvm_control_code:
  974.     cmp.b    #9,d1                ; tab ?
  975.     beq    gvm_loop
  976.     cmp.b    #10,d1                ; line feed ?
  977.     beq    gvm_loop
  978.     cmp.b    #12,d1                ; form feed ?
  979.     beq    gvm_loop
  980.     cmp.b    #13,d1                ; carriage return ?
  981.     beq    gvm_loop
  982.  
  983.     moveq    #VIEW_MODE_HEX,d0        ; mode = hex dump
  984.  
  985. gvm_exit:
  986.     PULL    d2
  987.     rts
  988.  
  989. ;---------------------------------------------------------------------------
  990. ; BOOL build_view_line_list(vreq, view_mode)
  991. ;                 a0       d0
  992. ;    struct ViewRequest  *vreq
  993. ;    USHORT view_mode
  994. ; Build view line list with nodes for every line of text
  995. ;---------------------------------------------------------------------------
  996. _build_view_line_list:
  997.     PUSH    d2-d7/a2-a3/a5-a6
  998.  
  999.     move.l    a0,a5                ; a0 := vreq ptr
  1000.     move.w    d0,d7                ; d7 := view mode
  1001.     move.w    d7,vr_Mode(a5)            ; set mode
  1002.     move.l    (4).w,a6            ; a6 := exec base
  1003.     moveq    #MLH_SIZE,d0            ; alloc mem for line list header
  1004.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  1005.     CALLSYS    AllocMem
  1006.     move.l    d0,vr_Display+d_List(a5)
  1007.     beq    bvl_error
  1008.     move.l    d0,a0                ; init new list
  1009.     NEWLIST    a0
  1010.     move.l    vr_Buffer(a5),a3        ; a3 := buffer ptr
  1011.     move.l    vr_BufferSize(a5),d6        ; d6 := size
  1012.     moveq    #0,d5                ; reset entry counter
  1013.     moveq    #0,d4                ; reset offset counter
  1014.     move.w    _max_line_len,d3        ; max num of chars per line
  1015.     subq.w    #1,d3                ; dec num -> only valid for ASCII dump
  1016.     tst.w    d7                ; check mode -> bytes per line
  1017.     beq    bvl_loop
  1018.     moveq    #MAX_HEX_LONG_WORDS*4-1,d3    ; bytes per line for hex dump
  1019.  
  1020. bvl_loop:
  1021.     move.l    a3,a2                ; save start of line ptr
  1022.     moveq    #0,d1                ; reset pos counter -> only valid for ASCII
  1023.     moveq    #0,d2                ; reset byte counter
  1024.     tst.w    d7                ; check mode -> bytes per line
  1025.     beq    bvl_line_loop
  1026.     move.w    d3,d1                ; reload char counter -> only valid for hex dump
  1027.  
  1028. bvl_line_loop:
  1029.     tst.l    d6                ; end of buffer ?
  1030.     beq    bvl_next_line
  1031.     move.b    (a3)+,d0            ; get char from buffer
  1032.     subq.l    #1,d6                ; dec size counter
  1033.     tst.w    d7                ; check mode
  1034.     beq    bvl_ascii
  1035.  
  1036. bvl_hex:
  1037.     addq.w    #1,d2                ; inc char counter
  1038.     dbra    d1,bvl_line_loop
  1039.     bra    bvl_next_line
  1040.  
  1041. bvl_ascii:
  1042.     cmp.b    #10,d0                ; line feed ?
  1043.     beq    bvl_next_line
  1044.     cmp.b    #12,d0                ; form feed ?
  1045.     beq    bvl_next_line
  1046.     cmp.b    #13,d0                ; carriage return ?
  1047.     beq    bvl_next_line
  1048.     addq.w    #1,d2                ; inc char counter
  1049.     cmp.b    #9,d0                ; tab ?
  1050.     bne    bvl_ascii_normal
  1051.  
  1052. bvl_ascii_tab:
  1053.     move.w    d1,d0                ; calc num of spaces to fill
  1054.     not.w    d0
  1055.     and.w    #7,d0
  1056.     addq.w    #1,d0
  1057.     add.w    d0,d1                ; add num of spaces to pos counter
  1058.     bra    bvl_ascii_check_pos
  1059.  
  1060. bvl_ascii_normal:
  1061.     addq.w    #1,d1                ; inc pos counter
  1062.  
  1063. bvl_ascii_check_pos:
  1064.     cmp.w    d3,d1                ; end of line ?
  1065.     bls    bvl_line_loop
  1066.  
  1067. bvl_next_line:
  1068.     moveq    #LineNode_Sizeof,d0        ; alloc mem for line node
  1069.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  1070.     CALLSYS    AllocMem
  1071.     tst.l    d0
  1072.     beq    bvl_error
  1073.     move.l    d0,a1                ; a1 := line node ptr
  1074.     move.l    a2,ln_Line(a1)
  1075.     move.w    d2,ln_LineLen(a1)
  1076.     move.l    d4,ln_Offset(a1)
  1077.     ext.l    d2
  1078.     add.l    d2,d4                ; update offset counter
  1079.     tst.w    d7                ; view mode == ASCII ?
  1080.     bne    bvl_no_offset_inc
  1081.     add.l    #1,d4                ; inc ASCII offset for LF, FF or CR
  1082.  
  1083. bvl_no_offset_inc:
  1084.     addq.l    #1,d5                ; inc entry counter
  1085.     move.l    d5,ln_Pos(a1)
  1086.     move.l    vr_Display+d_List(a5),a0    ; a0 := list ptr
  1087.     ADDTAIL                    ; append node to list
  1088.     tst.l    d6                ; end of buffer ?
  1089.     bne    bvl_loop
  1090.  
  1091. bvl_end_of_buffer:
  1092.     move.l    d5,vr_Display+d_NumEntries(a5)    ; save num of entries in vreq
  1093.     moveq    #1,d0                ; return value -> success
  1094.  
  1095. bvl_exit:
  1096.     PULL    d2-d7/a2-a3/a5-a6
  1097.     rts
  1098.  
  1099. bvl_error:
  1100.     moveq    #0,d0                ; return value -> error
  1101.     bra    bvl_exit
  1102.  
  1103. ;---------------------------------------------------------------------------
  1104. ; struct LineNode  *get_first_visible_line(vreq, old_offset)
  1105. ;                        a0       d0
  1106. ;    struct ViewRequest  *vreq
  1107. ;    ULONG old_offset
  1108. ; Get first visible line node from offset of old view mode
  1109. ;---------------------------------------------------------------------------
  1110. _get_first_visible_line:
  1111.     PUSH    d2/a2
  1112.  
  1113.     move.l    a0,a2                ; a2 := vreq ptr
  1114.     move.l    d0,d1                ; d1 := old offset
  1115.     move.w    vr_Mode(a2),d2            ; d2 := view mode
  1116.     move.l    vr_Display+d_List(a2),a0
  1117.     move.l    MLH_HEAD(a0),a0            ; a0 := first node in list
  1118.     move.l    a0,a1                ; a1 := default first visible node
  1119.  
  1120. gfvl_loop:
  1121.     tst.l    MLN_SUCC(a0)            ; end of list ?
  1122.     beq    gfvl_not_found
  1123.     moveq    #0,d0
  1124.     move.w    ln_LineLen(a0),d0
  1125.     add.l    ln_Offset(a0),d0
  1126.     cmp.l    d1,d0                ; offset + line_len > old_offset ?
  1127.     bhi    gfvl_found
  1128.     move.l    MLN_SUCC(a0),a0            ; next line node
  1129.     bra    gfvl_loop
  1130.  
  1131. gfvl_not_found:
  1132.     move.l    a1,d0                ; return first node as first visible node
  1133.     bra    gfvl_exit
  1134.  
  1135. gfvl_found:
  1136.     move.l    a0,d0                ; return current node as first visible node
  1137.  
  1138. gfvl_exit:
  1139.     PULL    d2/a2
  1140.     rts
  1141.  
  1142. ;---------------------------------------------------------------------------
  1143. ; struct LineNode  *search_line_node(start_node, string, len)
  1144. ;                     a0        a1    d0
  1145. ;    struct LineNode  *start_node
  1146. ;    UBYTE  *string
  1147. ;    USHORT len
  1148. ; Search line node in list which contains the search string
  1149. ;---------------------------------------------------------------------------
  1150. _search_line_node:
  1151.     PUSH    d2/a2-a3/a5
  1152.  
  1153.     move.l    a0,d1                ; start node == NULL ?
  1154.     beq    sln_not_found
  1155.     move.l    a0,a5                ; a5 := lnode
  1156.     move.l    a1,a3                ; a1 := search string
  1157.     move.w    d0,d2                ; d2 := len of search string
  1158.     subq.w    #1,d2                ; dec len for dbra
  1159.  
  1160. sln_search_loop:
  1161.     tst.l    MLN_SUCC(a5)            ; end of list ?
  1162.     beq    sln_not_found
  1163.  
  1164.     move.l    ln_Line(a5),a2            ; a2 := line ptr
  1165.     move.w    ln_LineLen(a5),d1        ; d1 := line len
  1166.     bsr    compare_lines
  1167.     tst.b    d0
  1168.     beq    sln_found
  1169.     move.l    MLN_SUCC(a5),a5            ; next node
  1170.     bra    sln_search_loop
  1171.  
  1172. sln_found:
  1173.     move.l    a5,d0                ; d0 := file node -> return value
  1174.     bra    sln_exit
  1175.  
  1176. sln_not_found:
  1177.     moveq    #0,d0                ; d0 := NULL -> return value
  1178.  
  1179. sln_exit:
  1180.     PULL    d2/a2-a3/a5
  1181.     rts
  1182.  
  1183. compare_lines:    ; (a2 := line ptr, a3 := search string ptr, d1.w := line len, d2.w := search string len - 1)
  1184.     move.b    (a3),d0                ; search first char of search string
  1185.  
  1186. cl_loop1:
  1187.     cmp.b    (a2)+,d0
  1188.     beq    cl_check_full
  1189.     subq.w    #1,d1                ; end of line ?
  1190.     bhi    cl_loop1
  1191.  
  1192. cl_no_match:
  1193.     moveq    #1,d0                ; search string not found
  1194.     rts
  1195.  
  1196. cl_check_full:
  1197.     move.l    a2,a0                ; check full search string
  1198.     lea    1(a3),a1
  1199.     move.w    d2,d0                ; only one char to search ?
  1200.     beq    cl_match
  1201.     subq.w    #1,d0
  1202.  
  1203. cl_loop2:
  1204.     cmp.b    (a0)+,(a1)+
  1205.     bne    compare_lines
  1206.     dbra    d0,cl_loop2
  1207.  
  1208. cl_match:
  1209.     moveq    #0,d0                ; search string found
  1210.     rts
  1211.  
  1212. ;---------------------------------------------------------------------------
  1213. ; UBYTE *protection(fnode)
  1214. ;             a0
  1215. ;    struct FileNode  *fnode
  1216. ; Build string with protection bits setting for given file node
  1217. ;---------------------------------------------------------------------------
  1218. _protection:
  1219.     PUSH    d2/a2
  1220.  
  1221.     move.l    a0,a2                ; a2 := fnode ptr
  1222.     move.w    fn_Protection(a2),d0
  1223.     move.l    _protection_bits,a0
  1224.     lea    _protection_string,a1
  1225.     moveq    #MAX_PROTECTION_BITS-1,d2    ; d2 := bit count - 1
  1226.     clr.b    1(a1,d2.w)            ; set end of string
  1227.  
  1228. prot_loop:
  1229.     moveq    #'-',d1                ; default value for not active
  1230.     cmp.w    #MAX_PROTECTION_BITS-4,d2    ; RWED ?
  1231.     blo    prot_chspa
  1232.  
  1233. prot_rwed:
  1234.     lsr.w    #1,d0                ; RWED : protection bit clear ?
  1235.     bcs    prot_write_byte
  1236.     bra    prot_get_byte
  1237.  
  1238. prot_chspa:
  1239.     lsr.w    #1,d0                ; CHSPA : protection bit set ?
  1240.     bcc    prot_write_byte
  1241.  
  1242. prot_get_byte:
  1243.     move.b    (a0,d2.w),d1
  1244.  
  1245. prot_write_byte:
  1246.     move.b    d1,(a1,d2.w)
  1247.     dbra    d2,prot_loop
  1248.     move.l    a1,d0                ; return ptr to protection string
  1249.  
  1250.     PULL    d2/a2
  1251.     rts
  1252.  
  1253. ;---------------------------------------------------------------------------
  1254. ; VOID build_limited_path_name(buffer,device_name,path_name,max_len,mode)
  1255. ;                     a0        a1         a2       d0    d1
  1256. ;    BYTE   *buffer, *device_name, *path_name
  1257. ;    USHORT max_len, mode
  1258. ; Build path name with specified maximal length - if path is too long then
  1259. ; use the form 'start of path...end of path'
  1260. ;---------------------------------------------------------------------------
  1261. _build_limited_path_name:
  1262.     PUSH    d2-d5/a2-a3
  1263.  
  1264.     ; --- init some regs
  1265.     move.l    a0,a3            ; a3 := buffer
  1266.     move.w    d0,d2            ; d2 := max len
  1267.     move.w    #0,d3            ; d3 := buffer char count
  1268.     move.w    d1,d4            ; d4 := mode
  1269.  
  1270.     ; --- copy device name (if any) to buffer
  1271.     move.l    a1,d0
  1272.     beq    blpn_count_path_name_len
  1273.  
  1274. bpln_copy_device_name:
  1275.     move.b    (a1)+,d0
  1276.     beq    bpln_skip_volume_name
  1277.     move.b    d0,(a3)+
  1278.     addq.w    #1,d3            ; inc char count
  1279.     bra    bpln_copy_device_name
  1280.  
  1281. bpln_skip_volume_name:
  1282.     ; --- skip volume name in path name
  1283.     sub.w    d3,d2            ; max len -= char count
  1284.  
  1285. bpln_skip_loop:
  1286.     cmp.b    #':',(a2)+
  1287.     bne    bpln_skip_loop
  1288.  
  1289. blpn_count_path_name_len:
  1290.     ; --- count length of path name
  1291.     move.l    a2,a0            ; a0 := path name
  1292.     moveq    #0,d5            ; d5 := len count
  1293.  
  1294. bpln_count_loop:
  1295.     tst.b    (a0)+
  1296.     beq    bpln_check_path_name_len
  1297.     addq.w    #1,d5            ; inc len count
  1298.     bra    bpln_count_loop
  1299.  
  1300. bpln_check_path_name_len:
  1301.     ; --- compare path name len with max name len
  1302.     cmp.w    d5,d2
  1303.     bgt    bpln_build_full_path_name
  1304.  
  1305.     ; --- build limited path name
  1306.     moveq    #START_OF_PATH_NAME_LEN,d0
  1307.     sub.w    d3,d0            ; d0 := len of 'start of path name'
  1308.     sub.w    d0,d2            ; max len -= len of 'start of path name'
  1309.     sub.w    d0,d5            ; path name len -= len of 'start of path name'
  1310.     subq.w    #1,d0            ; dec for dbra
  1311.  
  1312. bpln_copy_start_of_path_name:
  1313.     ; --- copy 'start of path name' to buffer
  1314.     move.b    (a2)+,(a3)+
  1315.     dbra    d0,bpln_copy_start_of_path_name
  1316.  
  1317.     ; --- insert delimiters
  1318.     moveq    #'.',d0
  1319.     move.b    d0,(a3)+
  1320.     move.b    d0,(a3)+
  1321.     move.b    d0,(a3)+
  1322.     subq.w    #3,d2            ; dec max len
  1323.  
  1324.     ; --- copy end of path name to buffer
  1325.     lea    0(a2,d5),a0        ; a0 := last char of path name
  1326.     sub.w    d2,a0            ; a0 := start of 'end of path name'
  1327.     subq.w    #1,d2            ; dec for dbra
  1328.     
  1329. bpln_copy_end_of_path_name:
  1330.     move.b    (a0)+,(a3)+
  1331.     dbra    d2,bpln_copy_end_of_path_name
  1332.     bra    bpln_exit
  1333.  
  1334. bpln_build_full_path_name:
  1335.     ; --- copy full path name to buffer
  1336.     sub.w    d5,d2            ; max_len -= path name len
  1337.     subq.w    #1,d5            ; dec for dbra
  1338.     bmi    bpln_fill_rest_of_buffer
  1339.  
  1340. bpln_copy_loop:
  1341.     move.b    (a2)+,(a3)+
  1342.     dbra    d5,bpln_copy_loop
  1343.  
  1344. bpln_fill_rest_of_buffer:
  1345.     ; -- fill rest of buffer with spaces
  1346.     tst.w    d4            ; no fill?
  1347.     beq    bpln_exit
  1348.     moveq    #' ',d0
  1349.     subq.w    #1,d2            ; dec for dbra
  1350.  
  1351. bpln_fill_loop:
  1352.     move.b    d0,(a3)+
  1353.     dbra    d2,bpln_fill_loop
  1354.  
  1355. bpln_exit:
  1356.     ; --- mark end of string
  1357.     clr.b    (a3)
  1358.  
  1359.     PULL    d2-d5/a2-a3
  1360.     rts
  1361.