1 ! Copyright (C) 2007 Alex Chapman All Rights Reserved.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: assocs kernel gap-buffer generic trees trees.avl math
5 IN: gap-buffer.cursortree
7 TUPLE: cursortree cursors ;
9 : <cursortree> ( seq -- cursortree )
10 <gb> cursortree new tuck set-delegate <avl>
11 over set-cursortree-cursors ;
13 GENERIC: cursortree-gb ( cursortree -- gb )
14 M: cursortree cursortree-gb ( cursortree -- gb ) delegate ;
15 GENERIC: set-cursortree-gb ( gb cursortree -- )
16 M: cursortree set-cursortree-gb ( gb cursortree -- ) set-delegate ;
18 TUPLE: cursor i tree ;
22 : cursor-index ( cursor -- i ) cursor-i ;
24 : add-cursor ( cursortree cursor -- ) dup cursor-index rot push-at ;
26 : remove-cursor ( cursortree cursor -- )
27 tuck cursor-index swap cursortree-cursors at* [ delete ] [ 2drop ] if ;
29 : set-cursor-index ( index cursor -- )
30 dup cursor-tree over remove-cursor tuck set-cursor-i
31 dup cursor-tree cursortree-cursors swap add-cursor ;
33 GENERIC: cursor-pos ( cursor -- n )
34 GENERIC: set-cursor-pos ( n cursor -- )
35 M: left-cursor cursor-pos ( cursor -- n ) [ cursor-i 1+ ] keep cursor-tree index>position ;
36 M: right-cursor cursor-pos ( cursor -- n ) [ cursor-i ] keep cursor-tree index>position ;
37 M: left-cursor set-cursor-pos ( n cursor -- ) >r 1- r> [ cursor-tree position>index ] keep set-cursor-index ;
38 M: right-cursor set-cursor-pos ( n cursor -- ) [ cursor-tree position>index ] keep set-cursor-index ;
40 : <cursor> ( cursortree -- cursor )
41 cursor new tuck set-cursor-tree ;
43 : make-cursor ( cursortree pos cursor -- cursor )
44 >r swap <cursor> r> tuck set-delegate tuck set-cursor-pos ;
46 : <left-cursor> ( cursortree pos -- left-cursor )
47 left-cursor new make-cursor ;
49 : <right-cursor> ( cursortree pos -- right-cursor )
50 right-cursor new make-cursor ;
52 : cursors ( cursortree -- seq )
53 cursortree-cursors values concat ;
55 : cursor-positions ( cursortree -- seq )
56 cursors [ cursor-pos ] map ;
58 M: cursortree move-gap ( n cursortree -- )
59 #! Get the position of each cursor before the move, then re-set the
60 #! position afterwards. This will update any changed cursor indices.
61 dup cursor-positions >r tuck cursortree-gb move-gap
62 cursors r> swap [ set-cursor-pos ] 2each ;
64 : element@< ( cursor -- pos cursortree ) [ cursor-pos 1- ] keep cursor-tree ;
65 : element@> ( cursor -- pos cursortree ) [ cursor-pos ] keep cursor-tree ;
67 : at-beginning? ( cursor -- ? ) cursor-pos 0 = ;
68 : at-end? ( cursor -- ? ) element@> length = ;
70 : insert ( obj cursor -- ) element@> insert* ;
72 : element< ( cursor -- elem ) element@< nth ;
73 : element> ( cursor -- elem ) element@> nth ;
75 : set-element< ( elem cursor -- ) element@< set-nth ;
76 : set-element> ( elem cursor -- ) element@> set-nth ;
78 GENERIC: fix-cursor ( cursortree cursor -- )
80 M: left-cursor fix-cursor ( cursortree cursor -- )
81 >r gb-gap-start 1- r> set-cursor-index ;
83 M: right-cursor fix-cursor ( cursortree cursor -- )
84 >r gb-gap-end r> set-cursor-index ;
86 : fix-cursors ( old-gap-end cursortree -- )
87 tuck cursortree-cursors at [ fix-cursor ] with each ;
89 M: cursortree delete* ( pos cursortree -- )
90 tuck move-gap dup gb-gap-end swap dup (delete*) fix-cursors ;
92 : delete< ( cursor -- ) element@< delete* ;
93 : delete> ( cursor -- ) element@> delete* ;