home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 3 / CDPDIII.bin / pd / utilities / dirutils / visualshell / src / asmsupp3.asm < prev    next >
Assembly Source File  |  1992-10-28  |  27KB  |  1,112 lines

  1.         *********************************
  2.         *                               *
  3.         *   Visual Shell v1.17  10/92   *
  4.         *                               *
  5.         *     by Torsten Jürgeleit      *
  6.         *                               *
  7.         *   assembly support routines   *
  8.         *           part III            *
  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 "libraries/arpbase.i"
  19.     INCLUDE "intuition/intuition.i"
  20.     INCLUDE "equates.i"
  21.     LIST
  22.  
  23. ;---------------------------------------------------------------------------
  24. ; External definitions
  25. ;---------------------------------------------------------------------------
  26.  
  27.     XDEF    _hcomp_treq_cursor
  28.     XDEF    _print_dir_tree
  29.     XDEF    _get_tree_node_by_pos
  30.     XDEF    _get_next_column_tree_node
  31.     XDEF    _get_prev_column_tree_node
  32.     XDEF    _build_history_line_list
  33.     XDEF    _print_hreq_lines
  34.     XDEF    _build_hreq_line
  35.     XDEF    _hcomp_hreq_cursor
  36.     XDEF    _scroll_history_req
  37.  
  38. ;---------------------------------------------------------------------------
  39. ; External references
  40. ;---------------------------------------------------------------------------
  41.  
  42.     XREF    _IntuitionBase
  43.     XREF    _GfxBase
  44.     XREF    _gadget_buffer
  45.     XREF    _con_device
  46.     XREF    _con_unit
  47.     XREF    _con_window
  48.     XREF    _con_rport
  49.     XREF    _main_task
  50.     XREF    _vsh_port
  51.     XREF    _auto_repeat
  52.     XREF    _show_flag
  53.     XREF    _scroll_flag
  54.     XREF    _vsh_scroll_speed
  55.     XREF    _qualifier
  56.     XREF    _enable_abort
  57.     XREF    _num_lock
  58.     XREF    _key_table
  59.     XREF    _action_table
  60.     XREF    _scroll_flag_table
  61.     XREF    _action
  62.     XREF    _file_req
  63.     XREF    _view_req
  64.     XREF    _history_req
  65.     XREF    _active_freq
  66.     XREF    _line1_buffer
  67.     XREF    _max_line_len
  68.     XREF    _print_dir_info
  69.     XREF    _print_info_line
  70.     XREF    _print_vreq_status
  71.     XREF    _print_quick_view
  72.     XREF    _SPrintf
  73.     XREF    _protection_bits
  74.     XREF    _protection_string
  75.     XREF    _font_data
  76.     XREF    _template_buffer
  77.     XREF    build_text_line
  78.     XREF    write_text
  79.  
  80. ;---------------------------------------------------------------------------
  81. ; VOID hcomp_treq_cursor(treq)
  82. ;              a0
  83. ;    struct TreeRequest  *treq
  84. ; Highlight or de-highlight the cursor line in tree requester
  85. ;---------------------------------------------------------------------------
  86. _hcomp_treq_cursor:
  87.     PUSH    d2-d3/a2-a3/a6
  88.  
  89.     move.l    a0,a2                ; a2 := treq
  90.     move.l    _con_rport,a3            ; a3 := rastport
  91.     move.l    _GfxBase,a6
  92.  
  93.     moveq    #RP_COMPLEMENT,d0        ; draw mode
  94.     move.l    a3,a1
  95.     CALLSYS    SetDrMd
  96.  
  97.     move.l    tr_CursorNode(a2),a0        ; a0 := cursor tnode
  98.     move.l    tn_XPos(a0),d0
  99.     sub.l    tr_XPos(a2),d0
  100.     mulu    #MAX_TREE_NODE_NAME_LEN+3,d0
  101.     addq.w    #2,d0
  102.     lsl.w    #3,d0                ; d0 * 8
  103.     move.w    tr_Display+d_LeftEdge(a2),d1
  104.     add.w    d1,d0                ; x1
  105.     move.l    tn_YPos(a0),d1
  106.     sub.l    tr_YPos(a2),d1
  107.     lsl.w    #3,d1                ; d1 * 8
  108.     move.w    tr_Display+d_TopEdge(a2),d2
  109.     add.w    d2,d1                ; y1
  110.     move.w    d0,d2
  111.     add.w    #MAX_TREE_NODE_NAME_LEN*8-1,d2    ; x2
  112.     move.w    d1,d3
  113.     addq.w    #7,d3                ; y2
  114.     move.l    a3,a1
  115.     CALLSYS    RectFill
  116.  
  117.     moveq    #RP_JAM2,d0            ; draw mode
  118.     move.l    a3,a1
  119.     CALLSYS    SetDrMd
  120.  
  121.     PULL    d2-d3/a2-a3/a6
  122.     rts
  123.  
  124. ;---------------------------------------------------------------------------
  125. ; VOID print_dir_tree(treq)
  126. ;               a0
  127. ;    struct TreeRequest  *treq
  128. ; Print directory tree
  129. ;---------------------------------------------------------------------------
  130. _print_dir_tree
  131.     PUSH    d2-d7/a2-a3/a5-a6
  132.  
  133.     move.l    a0,a2                ; a2 := treq
  134.     move.l    _con_rport,a5            ; za5 := rast port
  135.     move.l    _GfxBase,a6
  136.  
  137.     moveq    #RP_JAM2,d0            ; draw mode
  138.     move.l    a5,a1
  139.     CALLSYS    SetDrMd
  140.  
  141.     moveq    #COLOR1,d0            ; front color
  142.     move.l    a5,a1
  143.     CALLSYS    SetAPen
  144.  
  145.     moveq    #COLOR0,d0            ; back color
  146.     move.l    a5,a1
  147.     CALLSYS    SetBPen
  148.  
  149.     move.w    tr_Display+d_LeftEdge(a2),d6    ; d6 := horizontal position
  150.     move.w    tr_Display+d_TopEdge(a2),d7    ; d7 := verical position
  151.     moveq    #MAX_TREE_NODE_NAME_LEN+3,d0
  152.     mulu    tr_Columns(a2),d0
  153.     move.l    d0,a5                ; a5 := line len
  154.  
  155.     move.l    tr_YPos(a2),d3            ; d3 := ypos
  156.     move.w    tr_Rows(a2),d5
  157.     subq.w    #1,d5                ; d5 := rows - 1
  158.  
  159. pdt_row_loop:
  160.     lea    _line1_buffer,a3        ; a3 := text buffer ptr
  161.     move.l    tr_XPos(a2),d2            ; d2 := xpos
  162.     move.w    tr_Columns(a2),d4
  163.     subq.w    #1,d4                ; d4 := columns - 1
  164.  
  165. pdt_column_loop:
  166.     bsr    get_tree_node_by_pos
  167.  
  168. pdt_outside:
  169.     tst.l    d0                ; tnode == NULL ?
  170.     bne    pdt_between
  171.     moveq    #MAX_TREE_NODE_NAME_LEN+3-1,d1
  172.     bra    pdt_fill_column1
  173.  
  174. pdt_between:
  175.     cmp.l    #-1,d0                ; tnode == -1 ?
  176.     bne    pdt_node
  177.     move.b    #129,(a3)+            ; '|'
  178.     moveq    #MAX_TREE_NODE_NAME_LEN+2-1,d1
  179.  
  180. pdt_fill_column1:
  181.     moveq    #' ',d0
  182.  
  183. 1$:
  184.     move.b    d0,(a3)+
  185.     dbra    d1,1$
  186.     bra    pdt_next_column
  187.  
  188. pdt_node:
  189.     move.l    d0,a1                ; a1 := tnode
  190.     lea    tr_RootNode(a2),a0        ; tnode == root node ?
  191.     cmp.l    a0,a1
  192.     bne    pdt_node_loop
  193.  
  194. pdt_root_node:
  195.     move.b    #' ',(a3)+
  196.     move.b    #' ',(a3)+
  197.     bra    pdt_insert_name
  198.  
  199. pdt_node_loop:
  200.     move.l    tn_Node+MLN_SUCC(a1),a0
  201.     tst.l    MLN_SUCC(a0)
  202.     bne    pdt_more_entries
  203.  
  204. pdt_no_next_entry:
  205.     move.l    tn_Node+MLN_PRED(a1),a0
  206.     tst.l    MLN_PRED(a0)
  207.     bne    pdt_last_entry
  208.  
  209. pdt_only_one_entry:
  210.     move.b    #128,d0                ; only one entry in list '-'
  211.     bra    pdt_insert_delimiter
  212.  
  213. pdt_last_entry:
  214.     move.b    #132,d0                ; last entry in list '`'
  215.     bra    pdt_insert_delimiter
  216.  
  217. pdt_more_entries:
  218.     move.l    tn_Node+MLN_PRED(a1),a0
  219.     tst.l    MLN_PRED(a0)
  220.     bne    pdt_next_entry
  221.  
  222. pdt_first_entry:
  223.     move.b    #130,d0                ; first entry in list '+'
  224.     bra    pdt_insert_delimiter
  225.  
  226. pdt_next_entry:
  227.     move.b    #131,d0                ; more entries in list '+'
  228.  
  229. pdt_insert_delimiter:
  230.     move.b    d0,(a3)+
  231.     move.b    #128,(a3)+            ; '-'
  232.  
  233. pdt_insert_name:
  234.     lea    tn_Name(a1),a0
  235.     moveq    #MAX_TREE_NODE_NAME_LEN-1,d1
  236.  
  237. pdt_insert_name_loop:
  238.     move.b    (a0)+,d0
  239.     beq    pdt_check_list
  240.     move.b    d0,(a3)+
  241.     dbra    d1,pdt_insert_name_loop
  242.  
  243. pdt_check_list:
  244.     addq.w    #1,d1                ; fill one char more
  245.     moveq    #' ',d0
  246.     lea    tn_List(a1),a0
  247.     cmp.l    tn_List+MLH_TAILPRED(a1),a0    ; list empty ?
  248.     beq    pdt_fill_column2
  249.     move.b    #128,d0                ; '-'
  250.  
  251. pdt_fill_column2:                ; fill rest of column with spaces
  252.     move.b    d0,(a3)+
  253.     dbra    d1,pdt_fill_column2
  254.     cmp.b    #' ',d0                ; list empty ?
  255.     beq    pdt_fill_line
  256.  
  257. pdt_next_node:
  258.     move.l    tn_List+MLH_HEAD(a1),a1        ; a1 := first tnode in list
  259.     addq.l    #1,d2                ; inc xpos
  260.     dbra    d4,pdt_node_loop        ; next column
  261.     bra    pdt_print
  262.  
  263. pdt_next_column:
  264.     addq.l    #1,d2                ; inc xpos
  265.     dbra    d4,pdt_column_loop        ; next column
  266.     bra    pdt_print
  267.  
  268. pdt_fill_line_loop:                ; fill rest of line with spaces
  269.     moveq    #MAX_TREE_NODE_NAME_LEN+3-1,d1
  270.  
  271. pdt_fill_line_column_loop:
  272.     move.b    d0,(a3)+            ; fill one column
  273.     dbra    d1,pdt_fill_line_column_loop
  274.  
  275. pdt_fill_line:
  276.     addq.l    #1,d2                ; inc xpos
  277.     dbra    d4,pdt_fill_line_loop        ; next column
  278.  
  279. pdt_print:
  280.     clr.b    (a3)                ; mark end of string
  281.  
  282.     lea    _line1_buffer,a0        ; text
  283.     move.w    d6,d0                ; x
  284.     move.w    d7,d1                ; y
  285.     jsr    write_text
  286.  
  287. pdt_check_dir_node:
  288.     move.l    tr_DirNode(a2),a3        ; a3 := current dir tnode
  289.     cmp.l    tn_YPos(a3),d3            ; tn_YPos == ypos ?
  290.     bne    pdt_next_row
  291.     move.l    tn_XPos(a3),d0
  292.     cmp.l    d2,d0                ; tn_XPos >= (xpos + max_columns) ?
  293.     bhs    pdt_next_row
  294.     cmp.l    tr_XPos(a2),d0            ; tn_XPos < tr_XPos ?
  295.     blo    pdt_next_row
  296.  
  297. pdt_find_dir_name_end:
  298.     lea    tn_Name(a3),a0            ; find end of dir name in line1 buffer
  299.     lea    _line1_buffer,a1
  300.     moveq    #MAX_TREE_NODE_NAME_LEN-1,d1
  301.  
  302. pdt_find_dir_name_end_loop:
  303.     move.b    (a0)+,d0
  304.     beq    pdt_print_dir_node
  305.     move.b    d0,(a1)+
  306.     dbra    d1,pdt_find_dir_name_end_loop
  307.  
  308. pdt_print_dir_node:
  309.     clr.b    (a1)                ; mark end of current dir name
  310.  
  311.     moveq    #COLOR2,d0            ; new back color
  312.     move.l    _con_rport,a1
  313.     CALLSYS    SetBPen
  314.  
  315.     lea    _line1_buffer,a0        ; text
  316.     move.l    tn_XPos(a3),d0
  317.     sub.l    tr_XPos(a2),d0
  318.     mulu    #MAX_TREE_NODE_NAME_LEN+3,d0
  319.     addq.w    #2,d0
  320.     lsl.w    #3,d0                ; d0 * 8
  321.     add.w    d6,d0                ; x
  322.     move.w    d7,d1                ; y
  323.     jsr    write_text
  324.  
  325.     moveq    #COLOR0,d0            ; old back color
  326.     move.l    _con_rport,a1
  327.     CALLSYS    SetBPen
  328.  
  329. pdt_next_row:
  330.     addq.l    #1,d3                ; inc ypos
  331.     addq.l    #8,d7                ; inc vertical position
  332.     dbra    d5,pdt_row_loop
  333.  
  334.     PULL    d2-d7/a2-a3/a5-a6
  335.     rts
  336.  
  337. ;---------------------------------------------------------------------------
  338. ; struct TreeNode  *get_tree_node_by_pos(treq, xpos, ypos)
  339. ;                      a0    d0    d1
  340. ;    struct TreeRequest  *treq
  341. ;    ULONG xpos, ypos
  342. ; Get node from directory tree by given position
  343. ;---------------------------------------------------------------------------
  344. _get_tree_node_by_pos:
  345.     PUSH    d2-d3/a2
  346.  
  347.     move.l    a0,a2                ; a0 := treq
  348.     move.l    d0,d2                ; d2 := xpos
  349.     move.l    d1,d3                ; d3 := ypos
  350.     bsr    get_tree_node_by_pos
  351.  
  352.     PULL    d2-d3/a2
  353.     rts
  354.  
  355. get_tree_node_by_pos:   ; a2 := treq ptr, d2 := xpos, d3 := ypos
  356.     lea    tr_RootNode(a2),a1        ; a1 := parent tnode
  357.     moveq    #0,d1                ; save next tnode
  358.     bra    gtp_go_deeper
  359.  
  360. gtp_loop:
  361.     move.l    tn_Node+MLN_SUCC(a1),a0        ; a0 := next tnode in list
  362.     move.l    a0,d1                ; save next tnode
  363.     tst.l    tn_Node+MLN_SUCC(a0)        ; end of list ?
  364.     beq    gtp_go_deeper
  365.     cmp.l    tn_YPos(a0),d3            ; ypos < tn_YPos ?
  366.     blo    gtp_go_deeper
  367.     move.l    a0,a1                ; new parent tnode
  368.     bra    gtp_loop
  369.  
  370. gtp_go_deeper:
  371.     move.l    tn_List+MLH_HEAD(a1),a0        ; a0 := first tnode in list
  372.     tst.l    tn_Node+MLN_SUCC(a0)        ; empty list ?
  373.     beq    gtp_pos_reached
  374.     cmp.l    tn_XPos(a0),d2            ; xpos < tn_XPos ?
  375.     blo    gtp_pos_reached
  376.     move.l    a0,a1                ; new parent node
  377.     bra    gtp_loop
  378.  
  379. gtp_pos_reached:
  380.     cmp.l    tn_XPos(a1),d2            ; tn_XPos != xpos ?
  381.     bne     gtp_pos_outside
  382.     cmp.l    tn_YPos(a1),d3            ; tn_YPos == ypos ?
  383.     beq     gtp_pos_node
  384.  
  385. gtp_pos_empty:
  386.     tst.l    d1
  387.     beq    gtp_pos_outside            ; only valid for root node
  388.     move.l    d1,a0                ; a0 := save next tnode
  389.     tst.l    tn_Node+MLN_SUCC(a0)        ; last tnode in list ?
  390.     beq    gtp_pos_outside
  391.  
  392. gtp_pos_between:
  393.     move.l    #-1,d0                ; indicates pos between two tree branches
  394.     rts
  395.  
  396. gtp_pos_outside:
  397.     moveq    #0,d0                ; indicates pos outside of tree
  398.     rts
  399.  
  400. gtp_pos_node:
  401.     move.l    a1,d0                ; return tnode
  402.     rts
  403.  
  404. ;---------------------------------------------------------------------------
  405. ; struct TreeNode  *get_next_column_tree_node(tnode)
  406. ;                           a0
  407. ;    struct TreeNode  *tnode
  408. ; Get next tree node from given tree node in same column
  409. ;---------------------------------------------------------------------------
  410. _get_next_column_tree_node:
  411.     PUSH    d2/a2-a3
  412.  
  413.     move.l    a0,a3                ; a3 := start tnode
  414.     move.l    tn_XPos(a3),d1            ; d1 := column
  415.     moveq    #0,d2                ; d2 := nearest column
  416.     move.l    a3,a1                ; a1 := parent tnode
  417.     sub.l    a2,a2                ; a2 := nearest tnode
  418.  
  419. gnc_get_next:
  420.     move.l    tn_Node+MLN_SUCC(a1),d0
  421.     beq    gnc_get_old            ; only valid for root node
  422.     move.l    d0,a0
  423.     tst.l    tn_Node+MLN_SUCC(a0)        ; end of list ?
  424.     beq    gnc_go_back
  425.     move.l    a0,a1                ; new parent tnode
  426.     bra    gnc_found
  427.  
  428. gnc_go_back:
  429.     move.l    tn_ParentNode(a1),d0        ; root reached ?
  430.     beq    gnc_get_first
  431.     move.l    d0,a1                ; new parent tnode
  432.  
  433. gnc_go_next:
  434.     move.l    tn_Node+MLN_SUCC(a1),d0
  435.     beq    gnc_get_old            ; only valid for root node
  436.     move.l    d0,a0
  437.     tst.l    tn_Node+MLN_SUCC(a0)        ; end of list ?
  438.     beq    gnc_go_back
  439.  
  440. gnc_go_deeper:
  441.     move.l    a0,a1                ; new parent tnode
  442.     move.l    tn_XPos(a1),d0
  443.     cmp.l    d1,d0                ; tn_XPos == column ?
  444.     beq    gnc_found
  445.     cmp.l    d2,d0                ; tn_XPos <= nearest_column ?
  446.     bls    gnc_no_nearest
  447.     move.l    a1,a2                ; new nearest tnode
  448.     move.l    d0,d2                ; new nearest column
  449.  
  450. gnc_no_nearest:
  451.     move.l    tn_List+MLH_HEAD(a1),a0
  452.     tst.l    tn_Node+MLN_SUCC(a0)        ; empty list ?
  453.     bne    gnc_go_deeper
  454.     bra    gnc_go_next
  455.  
  456. gnc_get_first:
  457.     move.l    tn_List+MLH_HEAD(a3),a0
  458.     tst.l    tn_Node+MLN_SUCC(a0)        ; empty list ?
  459.     beq    gnc_get_nearest
  460.     move.l    a0,a1                ; go to first tnode in list
  461.     bra    gnc_found
  462.  
  463. gnc_get_nearest:
  464.     move.l    a2,d0                ; nearest tnode found ?
  465.     beq    gnc_get_old
  466.     move.l    a2,a1                ; go to nearest pos
  467.     bra    gnc_found
  468.  
  469. gnc_get_old:
  470.     move.l    a3,a1                ; stay at old pos
  471.  
  472. gnc_found:
  473.     move.l    a1,d0                ; return tnode
  474.  
  475. gnc_exit:
  476.     PULL    d2/a2-a3
  477.     rts
  478.  
  479. ;---------------------------------------------------------------------------
  480. ; struct TreeNode  *get_prev_column_tree_node(tnode)
  481. ;                           a0
  482. ;    struct TreeNode  *tnode
  483. ; Get previous tree node from given tree node in same column
  484. ;---------------------------------------------------------------------------
  485. _get_prev_column_tree_node:
  486.     PUSH    d2/a2-a3
  487.  
  488.     move.l    a0,a3                ; a3 := start tnode
  489.     move.l    tn_XPos(a3),d1            ; d1 := column
  490.     moveq    #0,d2                ; d2 := nearest column
  491.     move.l    a3,a1                ; a1 := parent tnode
  492.     sub.l    a2,a2                ; a2 := nearest tnode
  493.  
  494. gpc_get_next:
  495.     move.l    tn_Node+MLN_PRED(a1),d0        ; empty list ?
  496.     beq    gpc_go_back
  497.     move.l    d0,a0
  498.     tst.l    tn_Node+MLN_PRED(a0)        ; start of list ?
  499.     beq    gpc_go_back
  500.     move.l    a0,a1                ; new parent tnode
  501.     bra    gpc_found
  502.  
  503. gpc_go_back:
  504.     move.l    tn_ParentNode(a1),d0        ; root reached ?
  505.     beq    gpc_get_nearest
  506.     move.l    d0,a1                ; new parent tnode
  507.  
  508. gpc_go_next:
  509.     move.l    tn_Node+MLN_PRED(a1),d0        ; empty list ?
  510.     beq    gpc_go_back
  511.     move.l    d0,a0
  512.     tst.l    tn_Node+MLN_PRED(a0)        ; start of list ?
  513.     beq    gpc_go_back
  514.  
  515. gpc_go_deeper:
  516.     move.l    a0,a1                ; new parent tnode
  517.     move.l    tn_XPos(a1),d0
  518.     cmp.l    d1,d0                ; tn_XPos == column ?
  519.     beq    gpc_found
  520.     cmp.l    d2,d0                ; tn_XPos <= nearest_column ?
  521.     bls    gpc_no_nearest
  522.     move.l    a1,a2                ; new nearest tnode
  523.     move.l    d0,d2                ; new nearest column
  524.  
  525. gpc_no_nearest:
  526.     move.l    tn_List+MLH_TAILPRED(a1),a0
  527.     tst.l    tn_Node+MLN_PRED(a0)        ; empty list ?
  528.     bne    gpc_go_deeper
  529.     bra    gpc_go_next
  530.  
  531. gpc_get_nearest:
  532.     move.l    a2,d0                ; nearest tnode found ?
  533.     beq    gpc_get_parent
  534.     move.l    a2,a1                ; go to nearest pos
  535.     bra    gpc_found
  536.  
  537. gpc_get_parent:
  538.     move.l    tn_ParentNode(a3),d0
  539.     beq    gpc_get_old
  540.     move.l    d0,a1                ; go to first tnode in list
  541.     bra    gpc_found
  542.  
  543. gpc_get_old:
  544.     move.l    a3,a1                ; stay at old pos
  545.  
  546. gpc_found:
  547.     move.l    a1,d0                ; return tnode
  548.  
  549. gpc_exit:
  550.     PULL    d2/a2-a3
  551.     rts
  552.  
  553. ;---------------------------------------------------------------------------
  554. ; BOOL build_history_line_list(hreq)
  555. ;                a0
  556. ;    struct HistoryRequest  *hreq
  557. ; Build history line list with nodes for every line of text
  558. ;---------------------------------------------------------------------------
  559. _build_history_line_list:
  560.     PUSH    d2-d4/a2-a3/a5-a6
  561.  
  562.     move.l    a0,a3                ; a3 := hreq ptr
  563.     move.l    4,a6                ; a6 := exec base ptr
  564.     moveq    #MLH_SIZE,d0            ; alloc mem for line list header
  565.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  566.     CALLSYS    AllocMem
  567.     move.l    d0,hr_Display+d_List(a3)
  568.     beq    bhll_error
  569.     move.l    d0,a5                ; a5 := list ptr
  570.     move.l    a5,a0                ; init new list
  571.     NEWLIST    a0
  572.     move.l    hr_Buffer(a3),a2        ; a2 := buffer ptr
  573.     moveq    #0,d3                ; d3 := entry counter
  574.     move.w    _max_line_len,d4        ; max num of chars per line
  575.  
  576. bhll_loop:
  577.     moveq    #0,d2
  578.     move.b    (a2)+,d2            ; d2 := BSTR len
  579.     beq    bhll_end_of_buffer        ; end of buffer ?
  580.  
  581. bhll_build_line_node:
  582.     moveq    #LineNode_Sizeof,d0        ; alloc mem for line node
  583.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  584.     CALLSYS    AllocMem
  585.     tst.l    d0
  586.     beq    bhll_error
  587.     move.l    d0,a1                ; a1 := line node ptr
  588.     move.l    a2,ln_Line(a1)
  589.     add.w    d2,a2                ; inc buffer ptr
  590.     cmp.w    d4,d2                ; line too long ?
  591.     bls    bhll_insert_line_len
  592.     move.w    d4,d2                ; truncate line
  593.  
  594. bhll_insert_line_len:
  595.     move.w    d2,ln_LineLen(a1)
  596.     addq.l    #1,d3                ; inc entry counter
  597.     move.l    a5,a0                ; append node to list
  598.     ADDHEAD a0
  599.     bra    bhll_loop
  600.  
  601. bhll_end_of_buffer:
  602.     move.l    d3,hr_Display+d_NumEntries(a3)    ; save num of entries in hreq
  603.     bne    bhll_set_cursor
  604.  
  605. bhll_clear_cursor:
  606.     move.w    #-1,hr_CursorLine(a3)        ; cursor_line := -1
  607.     bra    bhll_success
  608.  
  609. bhll_set_cursor:
  610.     clr.w    hr_CursorLine(a3)        ; cursor_line := 0
  611.  
  612. bhll_set_pos:
  613.     move.l    MLH_HEAD(a5),a0            ; a0 := first line node
  614.     moveq    #1,d0                ; d0 := pos
  615.  
  616. bhll_set_pos_loop:
  617.     tst.l    MLN_SUCC(a0)            ; end of list ?
  618.     beq    bhll_success
  619.     move.l    d0,ln_Pos(a0)            ; set pos
  620.     addq.l    #1,d0                ; inc pos
  621.     move.l    MLN_SUCC(a0),a0            ; a0 := next line node
  622.     bra    bhll_set_pos_loop
  623.  
  624. bhll_success:
  625.     moveq    #1,d0                ; return value -> success
  626.  
  627. bhll_exit:
  628.     PULL    d2-d4/a2-a3/a5-a6
  629.     rts
  630.  
  631. bhll_error:
  632.     moveq    #0,d0                ; return value -> error
  633.     bra    bhll_exit
  634.  
  635. ;---------------------------------------------------------------------------
  636. ; VOID print_hreq_lines(hreq, node, line, count)
  637. ;             a0    a1    d0    d1
  638. ;    struct HistoryRequest  *hreq
  639. ;    struct LineNode        *node
  640. ;    USHORT line, count
  641. ; Print specified lines of history
  642. ;---------------------------------------------------------------------------
  643. _print_hreq_lines:
  644.     PUSH    d2-d7/a2-a3/a5-a6
  645.  
  646.     move.l    a1,d2                ; node == NULL ?
  647.     beq    pvl_exit
  648.     move.l    a0,a2                ; a2 := hreq
  649.     move.l    a1,a3                ; a3 := node ptr
  650.     move.l    _con_rport,a5            ; a5 := rast port
  651.     move.l    _GfxBase,a6            ; a6 := gfx base
  652.     move.w    _max_line_len,d4        ; d4 := max num of chars per line
  653.     subq.w    #1,d4                ; dec num for dbra
  654.     move.w    d0,d5                ; d5 := line
  655.     move.w    d1,d6                ; d6 := count
  656.     subq.w    #1,d6                ; dec count for dbra
  657.     moveq    #VIEW_MODE_ASCII,d7        ; d7 := view mode
  658.  
  659.     moveq    #RP_JAM2,d0            ; draw mode
  660.     move.l    a5,a1
  661.     CALLSYS    SetDrMd
  662.  
  663.     moveq    #COLOR1,d0            ; front color
  664.     move.l    a5,a1
  665.     CALLSYS    SetAPen
  666.  
  667.     moveq    #COLOR0,d0            ; back color
  668.     move.l    a5,a1
  669.     CALLSYS    SetBPen
  670.  
  671.     lea    _line1_buffer,a5
  672.  
  673. pvl_loop:
  674.     tst.l    MLN_SUCC(a3)            ; end of list ?
  675.     beq    pvl_exit
  676.  
  677.     jsr    build_text_line            ; build history line
  678.  
  679.     move.l    a5,a0                ; text
  680.     move.w    hr_Display+d_LeftEdge(a2),d0    ; x
  681.     move.w    d5,d1
  682.     lsl.w    #3,d1                ; d1 * 8
  683.     add.w    hr_Display+d_TopEdge(a2),d1    ; y
  684.     jsr    write_text
  685.  
  686.     move.l    MLN_SUCC(a3),a3            ; next node
  687.     addq.w    #1,d5                ; inc line counter
  688.     dbra    d6,pvl_loop
  689.  
  690. pvl_exit:
  691.     PULL    d2-d7/a2-a3/a5-a6
  692.     rts
  693.  
  694. ;---------------------------------------------------------------------------
  695. ; UBYTE *build_hreq_lines(hreq, node, max_line_len)
  696. ;               a0    a1        d0
  697. ;    struct HistoryRequest  *hreq
  698. ;    struct LineNode        *node
  699. ;    USHORT max_line_len
  700. ; Build specified line of text as ASCII or hex dump and returns pointer
  701. ;---------------------------------------------------------------------------
  702. _build_hreq_line:
  703.     PUSH    d2-d7/a2-a3/a5-a6
  704.  
  705.     move.l    a0,a2                ; a2 := hreq
  706.     move.l    a1,a3                ; a3 := node ptr
  707.     lea    _line1_buffer,a5        ; a5 := line buffer ptr
  708.     move.w    d0,d4                ; d4 := max num of chars per line
  709.     beq    bhl_no_max_line_len
  710.     subq.w    #1,d4                ; dec num for dbra
  711.  
  712. bhl_no_max_line_len:
  713.     moveq    #VIEW_MODE_ASCII,d7        ; d7 := mode
  714.     jsr    build_text_line
  715.     move.l    a5,d0                ; return pointer to line
  716.  
  717.     PULL    d2-d7/a2-a3/a5-a6
  718.     rts
  719.  
  720. ;---------------------------------------------------------------------------
  721. ; VOID hcomp_hreq_cursor(hreq)
  722. ;              a0
  723. ;    struct HistoryRequest  *hreq
  724. ; Highlight or de-highlight the cursor line in history requester
  725. ;---------------------------------------------------------------------------
  726. _hcomp_hreq_cursor:
  727.     PUSH    a2/a6
  728.  
  729.     move.l    a0,a2                ; a2 := hreq
  730.     move.l    _GfxBase,a6
  731.  
  732.     bsr    hcomp_hreq_cursor
  733.  
  734. hfc_exit:
  735.     PULL    a2/a6
  736.     rts
  737.  
  738. ;---------------------------------------------------------------------------
  739. ; Input : a2 = hreq ptr
  740. ;      a6 = GfxBase
  741. ; Highlight or de-highlight the cursor line in history requester
  742. ;---------------------------------------------------------------------------
  743. hcomp_hreq_cursor:
  744.     PUSH    d2-d3/a3
  745.  
  746.     move.w    hr_CursorLine(a2),d2        ; d2 := cursor line
  747.     cmp.w    #-1,d2                ; no cursor line ?
  748.     beq    hhc_return
  749.     cmp.w    hr_Display+d_VisibleLines(a2),d2
  750.     bhs    hhc_return
  751.  
  752.     move.l    _con_rport,a3            ; a3 := rast port
  753.     moveq    #RP_COMPLEMENT,d0        ; draw mode
  754.     move.l    a3,a1
  755.     CALLSYS    SetDrMd
  756.  
  757.     move.w    vr_Display+d_LeftEdge(a2),d0    ; x1
  758.     move.w    vr_Display+d_TopEdge(a2),d1
  759.     lsl.w    #3,d2                ; d2 * 8
  760.     add.w    d2,d1                ; y1
  761.     move.w    vr_Display+d_Width(a2),d2
  762.     add.w    d0,d2                ; x2
  763.     move.w    d1,d3
  764.     addq.w    #7,d3                ; y2
  765.     move.l    a3,a1
  766.     CALLSYS    RectFill
  767.  
  768.     moveq    #RP_JAM2,d0            ; draw mode
  769.     move.l    a3,a1
  770.     CALLSYS    SetDrMd
  771.  
  772. hhc_return:
  773.     PULL    d2-d3/a3
  774.     rts
  775.  
  776. ;---------------------------------------------------------------------------
  777. ; VOID scroll_history_req()
  778. ; Scroll history list in active historyrequester
  779. ;---------------------------------------------------------------------------
  780. _scroll_history_req:
  781.     PUSH    d2-d7/a2-a3/a6            ; save regs for scroll routines
  782.  
  783.     tst.b    _scroll_flag            ; check scroll flag
  784.     beq    shr_exit
  785.     lea    _history_req,a2            ; a2 := &history_req
  786.     cmp.l    #1,hr_Display+d_NumEntries(a2)    ; more than one entries in history list ?
  787.     bls    shr_exit
  788.  
  789. shr_auto_repeat_loop:
  790.     move.l    _GfxBase,a6
  791.     move.b    _scroll_flag,d1            ; d1 := scroll flag
  792.     bclr    #7,d1                ; top or bottom ?
  793.     bne    shr_scroll_all
  794.     moveq    #1,d7                ; d7 := count
  795.     bclr    #6,d1                ; page up or down ?
  796.     beq    shr_scroll_part
  797.     moveq    #0,d7
  798.     move.w    hr_Display+d_VisibleLines(a2),d7    ; d7 := count
  799.  
  800. shr_scroll_part:
  801.     bclr    #0,d1                ; scroll up ?
  802.     bne    shr_scroll_part_up
  803.     bclr    #1,d1                ; scroll down ?
  804.     beq    shr_exit
  805.  
  806. shr_scroll_part_down:
  807.     bsr    scroll_hreq_down
  808.     bra    shr_check_auto_repeat
  809.  
  810. shr_scroll_part_up:
  811.     bsr    scroll_hreq_up
  812.     bra    shr_check_auto_repeat
  813.  
  814. shr_scroll_all:
  815.     bsr    hcomp_hreq_cursor        ; clear old cursor line
  816.     move.l    hr_Display+d_List(a2),a0    ; a0 := history list ptr
  817.     move.b    _scroll_flag,d0            ; d0 := scroll flag
  818.     btst    #0,d0                ; scroll up ?
  819.     beq    shr_scroll_all_down
  820.  
  821. shr_scroll_all_up:
  822.     move.l    MLH_HEAD(a0),a0
  823.     clr.w    hr_CursorLine(a2)        ; cursor at top
  824.     bra    shr_scroll_all_print
  825.  
  826. shr_scroll_all_down:
  827.     moveq    #0,d0
  828.     move.w    hr_Display+d_VisibleLines(a2),d0
  829.     cmp.l    hr_Display+d_NumEntries(a2),d0    ; lesser entries than lines ?
  830.     blo    shr_search_last_entry
  831.     move.l    hr_Display+d_NumEntries(a2),d0    ; cursor to last entry
  832.     subq.w    #1,d0
  833.     move.w    d0,hr_CursorLine(a2)
  834.     bra    shr_draw_cursor
  835.  
  836. shr_search_last_entry:
  837.     move.l    MLH_TAILPRED(a0),a0
  838.     move.w    hr_Display+d_VisibleLines(a2),d0
  839.     subq.w    #2,d0                ; dec for dbra
  840.  
  841. shr_last_entry_loop:
  842.     move.l    MLN_PRED(a0),a0
  843.     dbra    d0,shr_last_entry_loop
  844.     move.w    hr_Display+d_VisibleLines(a2),d0    ; cursor at bottom
  845.     subq.w    #1,d0
  846.     move.w    d0,hr_CursorLine(a2)
  847.  
  848. shr_scroll_all_print:
  849.     move.l    a0,hr_Display+d_FirstVisibleNode(a2)
  850.     move.l    a0,a1                    ; a1 := node
  851.     move.l    a2,a0                    ; a0 := hreq
  852.     moveq    #0,d0                    ; d0 := line
  853.     move.w    hr_Display+d_VisibleLines(a2),d1    ; d1 := count
  854.     jsr    _print_hreq_lines            ; print whole page
  855.  
  856. shr_draw_cursor:
  857.     bsr    hcomp_hreq_cursor        ; draw new cursor line
  858.  
  859. shr_check_auto_repeat:
  860.     cmp.b    #SCROLL_SPEED_FAST,_vsh_scroll_speed    ; fast scrolling ?
  861.     bne    shr_exit
  862.     tst.b    _auto_repeat            ; auto_repeat ?
  863.     beq    shr_exit
  864.     tst.b    _scroll_flag            ; check scroll flag
  865.     bne    shr_auto_repeat_loop
  866.  
  867. shr_exit:
  868.     PULL    d2-d7/a2-a3/a6
  869.     rts
  870.  
  871. ;---------------------------------------------------------------------------
  872. ; Input : a2   = history request ptr
  873. ;      a6   = GfxBase
  874. ;      d7.l = scroll count
  875. ; Scroll history list of active history requester count times up
  876. ;---------------------------------------------------------------------------
  877. scroll_hreq_up:
  878.     moveq    #0,d2
  879.     move.w    hr_Display+d_VisibleLines(a2),d2    ; d2 := visible lines
  880.     move.l    hr_Display+d_NumEntries(a2),d3        ; d3 := number of entries
  881.     move.l    hr_Display+d_FirstVisibleNode(a2),a3    ; check cursor line - count
  882.     moveq    #0,d4
  883.     move.w    hr_CursorLine(a2),d4
  884.     add.l    ln_Pos(a3),d4
  885.     subq.l    #1,d4
  886.     beq    shu_exit            ; already at top ?
  887.     bsr    hcomp_hreq_cursor        ; clear old cursor line
  888.     cmp.l    d7,d4
  889.     bhi    shu_move_cursor
  890.     cmp.l    #1,ln_Pos(a3)            ; already at top ?
  891.     bhi    shu_start_scroll
  892.     clr.w    hr_CursorLine(a2)        ; now cursor at top
  893.     bra    shu_draw_cursor
  894.  
  895. shu_move_cursor:
  896.     move.w    hr_CursorLine(a2),d0        ; dec cursor line
  897.     sub.w    d7,d0
  898.     bmi    shu_scroll
  899.     bne    shu_set_cursor            ; cursor at top ?
  900.     cmp.l    #1,ln_Pos(a3)            ; already at top ?
  901.     bhi    shu_start_scroll
  902.  
  903. shu_set_cursor:
  904.     move.w    d0,hr_CursorLine(a2)
  905.     bra    shu_draw_cursor
  906.  
  907. shu_scroll:
  908.     cmp.l    #1,ln_Pos(a3)            ; already at top ?
  909.     bls    shu_draw_cursor
  910.  
  911. shu_start_scroll:
  912.     move.w    d7,d0                ; d0 := scroll count
  913.     subq.w    #1,d0                ; dec count for dbra
  914.  
  915. shu_loop:
  916.     cmp.l    #1,ln_Pos(a3)            ; top reached ?
  917.     beq    shu_check_count
  918.     move.l    MLN_PRED(a3),a3            ; get previous node
  919.     dbra    d0,shu_loop
  920.  
  921. shu_check_count:
  922.     cmp.w    #1,d7                ; paging ?
  923.     bhi    shu_paging
  924.  
  925. shu_init_scroll:
  926.     move.l    _con_rport,a0            ; source rport
  927.     move.l    a0,a1                ; dest rport
  928.     move.w    fr_Display+d_LeftEdge(a2),d0    ; x1
  929.     move.w    fr_Display+d_TopEdge(a2),d1    ; y1
  930.     move.w    d1,d3                ; y2
  931.     move.w    d0,d2                ; x2
  932.     move.w    fr_Display+d_Width(a2),d4    ; width
  933.     move.w    fr_Display+d_VisibleLines(a2),d5
  934.     lsl.w    #3,d5                ; height
  935.     move.w    #$0c0,d6            ; minterm
  936.     cmp.b    #SCROLL_SPEED_SLOW,_vsh_scroll_speed
  937.     beq    shu_scroll_slow
  938.  
  939. shu_scroll_normal:
  940.     addq.w    #8,d3                ; y2
  941.     subq.w    #8,d5                ; height
  942.     CALLSYS    ClipBlit            ; scroll one entry up
  943.     bra    shu_paging
  944.  
  945. shu_scroll_slow:
  946.     PUSH    d7
  947.     subq.w    #1,d1                ; y1
  948.     moveq    #8-1,d7                ; d7 := count
  949.  
  950. 1$:
  951.     movem.w    d0-d6,-(sp)
  952.     PUSH    a0-a1
  953.     CALLSYS    ClipBlit            ; scroll one scanline up
  954.     PULL    a0-a1
  955.     movem.w    (sp)+,d0-d6
  956.     dbra    d7,1$
  957.     PULL    d7
  958.  
  959. shu_paging:
  960.     move.l    a2,a0                ; a0 := hreq
  961.     move.l    a3,a1                ; a1 := node
  962.     moveq    #0,d0                ; d0 := line
  963.     move.w    d7,d1                ; d1 := count
  964.     jsr    _print_hreq_lines        ; print new entry
  965.     move.l    a3,hr_Display+d_FirstVisibleNode(a2)
  966.  
  967. shu_draw_cursor:
  968.     bsr    hcomp_hreq_cursor        ; draw new cursor line
  969.  
  970. shu_exit:
  971.     rts
  972.  
  973. ;---------------------------------------------------------------------------
  974. ; Input : a2   = history request ptr
  975. ;      a6   = GfxBase
  976. ;      d7.l = scroll count
  977. ; Scroll history list of active history requester count times down
  978. ;---------------------------------------------------------------------------
  979. scroll_hreq_down:
  980.     moveq    #0,d2
  981.     move.w    hr_Display+d_VisibleLines(a2),d2    ; d2 := visible lines
  982.     move.l    hr_Display+d_NumEntries(a2),d3        ; d3 := number of entries
  983.     move.l    hr_Display+d_FirstVisibleNode(a2),a3    ; check cursor line + count
  984.     moveq    #0,d4
  985.     move.w    hr_CursorLine(a2),d4
  986.     add.l    ln_Pos(a3),d4
  987.     cmp.l    d3,d4                ; already at bottom ?
  988.     beq    shd_exit
  989.     bsr    hcomp_hreq_cursor        ; clear old cursor line
  990.     subq.l    #1,d4
  991.     add.l    d7,d4
  992.     cmp.l    d3,d4
  993.     blo    shd_move_cursor
  994.     move.l    ln_Pos(a3),d1            ; already at bottom ?
  995.     add.l    d2,d1
  996.     cmp.l    d3,d1
  997.     bls    shd_start_scroll
  998.     cmp.l    d2,d3                ; more than one page ?
  999.     bhi    shd_more_pages
  1000.     move.w    d3,d0                ; now cursor at bottom
  1001.     subq.w    #1,d0
  1002.     move.w    d0,hr_CursorLine(a2)
  1003.     bra    shd_draw_cursor
  1004.  
  1005. shd_more_pages:
  1006.     move.w    d2,d0                ; now cursor at bottom
  1007.     subq.w    #1,d0
  1008.     move.w    d0,hr_CursorLine(a2)
  1009.     bra    shd_scroll
  1010.  
  1011. shd_move_cursor:
  1012.     move.w    hr_CursorLine(a2),d0        ; dec cursor line
  1013.     add.w    d7,d0
  1014.     move.w    d2,d1
  1015.     subq.w    #1,d1                ; d1 := visible lines - 1
  1016.     cmp.w    d1,d0
  1017.     bhi    shd_scroll
  1018.     bne    shd_set_cursor            ; cursor at bottom ?
  1019.     move.l    ln_Pos(a3),d1            ; already at bottom ?
  1020.     add.l    d2,d1
  1021.     cmp.l    d3,d1
  1022.     bls    shd_start_scroll
  1023.  
  1024. shd_set_cursor:
  1025.     move.w    d0,hr_CursorLine(a2)
  1026.     bra    shd_draw_cursor
  1027.  
  1028. shd_scroll:
  1029.     move.l    ln_Pos(a3),d1            ; already at bottom ?
  1030.     add.l    d2,d1
  1031.     cmp.l    d3,d1
  1032.     bhi    shd_draw_cursor
  1033.  
  1034. shd_start_scroll:
  1035.     move.w    d7,d0                ; d0 := scroll count
  1036.     subq.w    #1,d0                ; dec count for dbra
  1037.  
  1038. shd_loop:
  1039.     move.l    ln_Pos(a3),d1            ; bottom reached ?
  1040.     add.l    d2,d1
  1041.     cmp.l    d3,d1
  1042.     bhi    shd_check_count
  1043.     move.l    MLN_SUCC(a3),a3            ; get next node
  1044.     dbra    d0,shd_loop
  1045.  
  1046. shd_check_count:
  1047.     cmp.w    #1,d7                ; paging ?
  1048.     bhi    shd_paging
  1049.  
  1050. shd_init_scroll:
  1051.     move.l    _con_rport,a0            ; source rport
  1052.     move.l    a0,a1                ; dest rport
  1053.     move.w    fr_Display+d_LeftEdge(a2),d0    ; x1
  1054.     move.w    fr_Display+d_TopEdge(a2),d1    ; y1
  1055.     move.w    d1,d3                ; y2
  1056.     move.w    d0,d2                ; x2
  1057.     move.w    fr_Display+d_Width(a2),d4    ; width
  1058.     move.w    fr_Display+d_VisibleLines(a2),d5
  1059.     lsl.w    #3,d5                ; height
  1060.     move.w    #$0c0,d6            ; minterm
  1061.     cmp.b    #SCROLL_SPEED_SLOW,_vsh_scroll_speed
  1062.     beq    shd_scroll_slow
  1063.  
  1064. shd_scroll_normal:
  1065.     addq.w    #8,d1                ; y1
  1066.     subq.w    #8,d5                ; height
  1067.     CALLSYS    ClipBlit            ; scroll one entry up
  1068.     bra    shd_scroll_end
  1069.  
  1070. shd_scroll_slow:
  1071.     PUSH    d7
  1072.     addq.w    #1,d1                ; y1
  1073.     moveq    #8-1,d7                ; d7 := count
  1074.  
  1075. 1$:
  1076.     movem.w    d0-d6,-(sp)
  1077.     PUSH    a0-a1
  1078.     CALLSYS    ClipBlit            ; scroll one scanline up
  1079.     PULL    a0-a1
  1080.     movem.w    (sp)+,d0-d6
  1081.     dbra    d7,1$
  1082.     PULL    d7
  1083.  
  1084. shd_scroll_end:
  1085.     move.l    a3,a1                ; a1 := node
  1086.     move.w    hr_Display+d_VisibleLines(a2),d0
  1087.     subq.w    #1,d0                ; d0 := line
  1088.     move.w    d0,d1
  1089.     subq.w    #1,d1                ; dec for dbra
  1090.  
  1091. shd_get_last_line:
  1092.     move.l    MLN_SUCC(a1),a1            ; get next node
  1093.     dbra    d1,shd_get_last_line
  1094.     move.w    d7,d1                ; d1 := count
  1095.     bra    shd_print
  1096.  
  1097. shd_paging:
  1098.     moveq    #0,d0                ; d0 := line
  1099.     move.w    d7,d1                ; d1 := count
  1100.     move.l    a3,a1                ; a1 := node
  1101.  
  1102. shd_print:
  1103.     move.l    a2,a0                ; a0 := hreq
  1104.     jsr    _print_hreq_lines        ; print new entry
  1105.     move.l    a3,hr_Display+d_FirstVisibleNode(a2)
  1106.  
  1107. shd_draw_cursor:
  1108.     bsr    hcomp_hreq_cursor        ; draw new cursor line
  1109.  
  1110. shd_exit:
  1111.     rts
  1112.