<pre><span id="VALempty"><span class="keyword">val</span> empty</span> : <code class="type"><a href="Buf.html#TYPEbuf">buf</a></code></pre>
<pre><span id="VALload"><span class="keyword">val</span> load</span> : <code class="type">string -> <a href="Buf.html#TYPEbuf">buf</a></code></pre>
+<pre><span id="VALlength"><span class="keyword">val</span> length</span> : <code class="type"><a href="Buf.html#TYPEbuf">buf</a> -> int</code></pre>
<pre><span id="VALiteri"><span class="keyword">val</span> iteri</span> : <code class="type">(int -> <a href="Rope.html#TYPErune">Rope.rune</a> -> bool) -> <a href="Buf.html#TYPEbuf">buf</a> -> int -> unit</code></pre>
<pre><span id="VALiter"><span class="keyword">val</span> iter</span> : <code class="type">(<a href="Rope.html#TYPErune">Rope.rune</a> -> bool) -> <a href="Buf.html#TYPEbuf">buf</a> -> int -> unit</code></pre>
<pre><span class="keyword">module</span> <a href="Buf.Cursor.html">Cursor</a>: <code class="code">sig</code> <a href="Buf.Cursor.html">..</a> <code class="code">end</code></pre>
<pre><span id="VALmake"><span class="keyword">val</span> make</span> : <code class="type">int * int -> int -> int -> <a href="Draw.Cursor.html#TYPEt">t</a></code></pre>
+<pre><span id="VALclone"><span class="keyword">val</span> clone</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">t</a> -> <a href="Draw.Cursor.html#TYPEt">t</a></code></pre>
+<pre><span id="VALmove_x"><span class="keyword">val</span> move_x</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">t</a> -> int -> unit</code></pre>
<pre><span id="VALmax_width"><span class="keyword">val</span> max_width</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">t</a> -> int</code></pre>
<pre><span id="VALrestart"><span class="keyword">val</span> restart</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">t</a> -> int -> int -> <a href="Draw.Cursor.html#TYPEt">t</a></code></pre>
<pre><span id="VALnext_line"><span class="keyword">val</span> next_line</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">t</a> -> unit</code></pre>
<pre><span id="VALstring"><span class="keyword">val</span> string</span> : <code class="type">string -> <a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> unit</code></pre>
<pre><span id="VALhrule"><span class="keyword">val</span> hrule</span> : <code class="type">int -> <a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> unit</code></pre>
<pre><span id="VALvrule"><span class="keyword">val</span> vrule</span> : <code class="type">int -> <a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> unit</code></pre>
-<pre><span id="VALbuffer"><span class="keyword">val</span> buffer</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> <a href="Buf.html#TYPEt">Buf.t</a> -> int -> unit</code></pre>
+<pre><span id="VALbuffer"><span class="keyword">val</span> buffer</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> <a href="Buf.html#TYPEt">Buf.t</a> -> int -> int</code></pre>
<pre><span id="VALstatus"><span class="keyword">val</span> status</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> string -> unit</code></pre>
<pre><span id="VALtags"><span class="keyword">val</span> tags</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> 'a -> unit</code></pre>
-<pre><span id="VALscroll"><span class="keyword">val</span> scroll</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> unit</code></pre>
-<pre><span id="VALedit"><span class="keyword">val</span> edit</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> <a href="Buf.html#TYPEt">Buf.t</a> -> int -> unit</code></pre></body></html>
\ No newline at end of file
+<pre><span id="VALscroll"><span class="keyword">val</span> scroll</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> float -> unit</code></pre>
+<pre><span id="VALedit"><span class="keyword">val</span> edit</span> : <code class="type"><a href="Draw.Cursor.html#TYPEt">Cursor.t</a> -> <a href="Buf.html#TYPEt">Buf.t</a> -> int -> int</code></pre></body></html>
\ No newline at end of file
<pre><span id="VALlength"><span class="keyword">val</span> length</span> : <code class="type"><a href="Rope.html#TYPEt">t</a> -> int</code></pre>
<pre><span id="VALheight"><span class="keyword">val</span> height</span> : <code class="type"><a href="Rope.html#TYPEt">t</a> -> int</code></pre>
<pre><span id="VALis_leaf"><span class="keyword">val</span> is_leaf</span> : <code class="type"><a href="Rope.html#TYPEt">t</a> -> bool</code></pre>
-<pre><span id="VALis_leaf"><span class="keyword">val</span> is_leaf</span> : <code class="type"><a href="Rope.html#TYPEt">t</a> -> bool</code></pre>
<pre><span id="VALlimit_index"><span class="keyword">val</span> limit_index</span> : <code class="type"><a href="Rope.html#TYPEt">t</a> -> int -> int</code></pre>
<pre><span id="VALlast"><span class="keyword">val</span> last</span> : <code class="type"><a href="Rope.html#TYPEt">t</a> -> int</code></pre>
<pre><span id="VALcheck_index"><span class="keyword">val</span> check_index</span> : <code class="type"><a href="Rope.html#TYPEt">t</a> -> int -> unit</code></pre>
<td></td></tr>
<tr><td><a href="Rope.html#VALcheck_index">check_index</a> [<a href="Rope.html">Rope</a>]</td>
<td></td></tr>
+<tr><td><a href="Draw.Cursor.html#VALclone">clone</a> [<a href="Draw.Cursor.html">Draw.Cursor</a>]</td>
+<td></td></tr>
<tr><td><a href="Buf.Cursor.html#VALclone">clone</a> [<a href="Buf.Cursor.html">Buf.Cursor</a>]</td>
<td></td></tr>
<tr><td><a href="Cfg.html#VALclrvar">clrvar</a> [<a href="Cfg.html">Cfg</a>]</td>
<tr><td align="left"><br>L</td></tr>
<tr><td><a href="Rope.html#VALlast">last</a> [<a href="Rope.html">Rope</a>]</td>
<td></td></tr>
+<tr><td><a href="Buf.html#VALlength">length</a> [<a href="Buf.html">Buf</a>]</td>
+<td></td></tr>
<tr><td><a href="Rope.html#VALlength">length</a> [<a href="Rope.html">Rope</a>]</td>
<td></td></tr>
<tr><td><a href="Draw.html#VALlight_bkg">light_bkg</a> [<a href="Draw.html">Draw</a>]</td>
<td></td></tr>
<tr><td><a href="Buf.html#VALmove_to">move_to</a> [<a href="Buf.html">Buf</a>]</td>
<td></td></tr>
+<tr><td><a href="Draw.Cursor.html#VALmove_x">move_x</a> [<a href="Draw.Cursor.html">Draw.Cursor</a>]</td>
+<td></td></tr>
<tr><td align="left"><br>N</td></tr>
<tr><td><a href="Draw.Cursor.html#VALnext_glyph">next_glyph</a> [<a href="Draw.Cursor.html">Draw.Cursor</a>]</td>
<td></td></tr>
<span class="keyword">mutable</span> y : int;<br>
}<br>
<span class="keyword">val</span> make : int * int <span class="keywordsign">-></span> int <span class="keywordsign">-></span> int <span class="keywordsign">-></span> <span class="constructor">Draw</span>.<span class="constructor">Cursor</span>.t<br>
+ <span class="keyword">val</span> clone : <span class="constructor">Draw</span>.<span class="constructor">Cursor</span>.t <span class="keywordsign">-></span> <span class="constructor">Draw</span>.<span class="constructor">Cursor</span>.t<br>
+ <span class="keyword">val</span> move_x : <span class="constructor">Draw</span>.<span class="constructor">Cursor</span>.t <span class="keywordsign">-></span> int <span class="keywordsign">-></span> unit<br>
<span class="keyword">val</span> max_width : <span class="constructor">Draw</span>.<span class="constructor">Cursor</span>.t <span class="keywordsign">-></span> int<br>
<span class="keyword">val</span> restart : <span class="constructor">Draw</span>.<span class="constructor">Cursor</span>.t <span class="keywordsign">-></span> int <span class="keywordsign">-></span> int <span class="keywordsign">-></span> <span class="constructor">Draw</span>.<span class="constructor">Cursor</span>.t<br>
<span class="keyword">val</span> next_line : <span class="constructor">Draw</span>.<span class="constructor">Cursor</span>.t <span class="keywordsign">-></span> unit<br>
open X11
module View = struct
- type t = { buf : Buf.t; map : Scrollmap.t }
+ type t = {
+ num : int;
+ buf : Buf.t;
+ map : Scrollmap.t
+ }
let from_buffer buf width height =
- { buf = buf; map = Scrollmap.make buf width 0 }
+ { num = 0; buf = buf; map = Scrollmap.make buf width 0 }
let empty width height =
from_buffer (Buf.empty) width height
let draw view csr =
let view = (resize view (Draw.Cursor.max_width csr)) in
- Draw.buffer csr view.buf (Scrollmap.first view.map);
- view
+ let num = Draw.buffer csr view.buf (Scrollmap.first view.map) in
+ { view with num = num }
let scroll_up view =
{ view with map = Scrollmap.scroll_up view.map view.buf }
let scroll_dn view =
{ view with map = Scrollmap.scroll_dn view.map view.buf }
+
+ let visible view =
+ (float_of_int view.num) /. (float_of_int (Buf.length view.buf))
+
end
let tags_buf = ref Buf.empty
let csr = Draw.Cursor.make (width, height) 0 0 in
Draw.status csr "UNSI> *scratch*";
Draw.tags csr !tags_buf;
- Draw.scroll csr;
- edit_view := View.draw !edit_view csr
+ let scrollcsr = (Draw.Cursor.clone csr) in
+ Draw.Cursor.move_x csr 15;
+ edit_view := View.draw !edit_view csr;
+ Draw.scroll scrollcsr (View.visible !edit_view)
let onshutdown () = ()
let load path =
{ path = path; rope = Rope.from_string (Misc.load_file path) }
+let length buf =
+ Rope.length buf.rope
+
let iteri fn buf i =
Rope.iteri fn buf.rope i
val empty : t
val load : string -> t
+val length : t -> int
val iter : (int -> bool) -> t -> int -> unit
val iteri : (int -> int -> bool) -> t -> int -> unit
{ height = height; width = width;
startx = x; starty = y; x = x; y = y }
+ let clone csr =
+ { height = csr.height; width = csr.width;
+ startx = csr.startx; starty = csr.starty;
+ x = csr.x; y = csr.y }
+
+ let move_x csr n =
+ csr.x <- csr.x + n
+
let max_width csr =
(csr.width - csr.x)
let buffer csr buf off =
dark_bkg (csr.width - csr.x) (csr.height - csr.y) csr;
- let csr = (restart csr 2 0) in
+ let num = ref 0 and csr = (restart csr 2 0) in
let draw_rune c =
draw_glyph csr c;
+ num := !num + 1;
has_next_line csr
in
- Buf.iter draw_rune buf off
+ Buf.iter draw_rune buf off;
+ !num
let status csr str =
dark_bkg csr.width (4 + font_height) csr;
string "Quit Save Undo Redo Cut Copy Paste | Find " csr;
hrule csr.width csr
-let scroll csr =
+let scroll csr pct =
+ let thumbsz = int_of_float ((float_of_int csr.height) *. pct) in
rule_bkg 14 csr.height csr;
- dark_bkg 14 (csr.height / 2) csr;
+ dark_bkg 14 thumbsz csr;
csr.x <- csr.x + 14;
vrule csr.height csr
module Cursor : sig
type t
val make : (int * int) -> int -> int -> t
+ val clone : t -> t
+ val move_x : t -> int -> unit
val max_width : t -> int
val restart : t -> int -> int -> t
val next_line : t -> unit
val light_bkg : int -> int -> Cursor.t -> unit
val rule_bkg : int -> int -> Cursor.t -> unit
-val buffer : Cursor.t -> Buf.t -> int -> unit
+val buffer : Cursor.t -> Buf.t -> int -> int
val string : string -> Cursor.t -> unit
val hrule : int -> Cursor.t -> unit
val status : Cursor.t -> string -> unit
val tags : Cursor.t -> Buf.t -> unit
-val scroll : Cursor.t -> unit
-val edit : Cursor.t -> Buf.t -> int -> unit
+val scroll : Cursor.t -> float -> unit
+val edit : Cursor.t -> Buf.t -> int -> int
| Leaf _ -> true
| _ -> false
-let is_leaf = function
- | Leaf _ -> true
- | _ -> false
-
let limit_index rope i =
if i < 0 then 0
else if i > 0 && i >= (length rope) then
(* inefficient form of iteri *)
let rec iteri fn rope pos =
- if pos < (length rope) && (fn pos (getc rope pos)) then
+ if pos < (length rope) && (fn pos (Char.code (getb rope pos))) then
iteri fn rope (pos + 1)
(* More efficient form of iteri?
(******************************************************************************)
+(* Rebalancing:
+
+* Height of leaf is 0
+* Height of a node is (1 + max(left,right))
+* Rope balanced if (length >= Fib(n) + 2)
+
+
+The rebalancing operation maintains an ordered sequence of (empty or) balanced
+ropes, one for each length interval [Fn, Fn+1), for n $2.
+
+We traverse the rope from left to right, inserting each leaf into the
+appropriate sequence position, depending on its length.
+
+The concatenation of the sequence of ropes in order of decreasing length is
+equivalent to the prefix of the rope we have traversed so far.
+
+Each new leaf x is inserted into the appropriate entry of the sequence.
+
+Assume that x's length is in the interval [Fib(n), Fib(n+1)], and thus it should be put
+in slot n (which also corresponds to maximum depth n - 2).
+
+If all lower and equal numbered levels are empty, then this can be done directly.
+
+If not, then we concatenate ropes in slots 2,. . .,(n - 1) (concatenating onto
+the left), and concatenate x to the right of the result.
+
+We then continue to concatenate ropes from the sequence in increasing order to
+the left of this result, until the result fits into an empty slot in the sequence.
+
+The concatenation we form in this manner is guaranteed to be balanced.
+
+The concatenations formed before the addition of x each have depth at most one more
+than is warranted by their length.
+
+If slot n - 1 is empty then the concatenation of shorter ropes has depth at most
+n - 3, so the concatenation with x has depth n - 2, and is thus balanced.
+
+If slot n - 1 is full, then the final depth after adding x may be n - 1, but the
+resulting length is guaranteed to be at least Fn+1, again guaranteeing
+balance.
+
+Subsequent concatenations (if any) involve concatenating two balanced ropes with
+lengths at least Fm and Fm-1 and producing a rope of depth m - 1, which must
+again be balanced.
+
+*)
+
let flatten rope =
let s = (gets rope 0 (length rope)) in
Leaf (s,0,(String.length s))
uint64_t t = getmillis();
while (XPending(X.display)) {
XNextEvent(X.display, &e);
- printf("%d ", e.type);
if (!XFilterEvent(&e, None) && EventHandlers[e.type]) {
event = EventHandlers[e.type](&e);
if (event != Val_int(TNone))
caml_callback(cbfn, event);
}
}
- puts("");
printf("time 1 %lu ", getmillis()-t);
t = getmillis();
if (X.running) {