1    local set_cursor_index (text_box : TextBox
2                            prev_i : u32
3                            i : u32
4                            is_mouse_move : bool
5                            is_move : bool) =
6        if text_box.os_window.is_shift_pressed && is_move || is_mouse_move then
7            if prev_i <> i then
8                let length = text_box.display_text.length
9                let prev_selection = text_box.selection
10               let left = i.min length |> min prev_i
11               let right = i.min length |> max prev_i
12               let (min, max) = case prev_selection of
13                   None -> (left, right)
14                   Some (prev_min, prev_max) ->
15                       if i > prev_i then
16                           if prev_i == prev_max
17                           then (prev_min, right)
18                           else (prev_max.min right, prev_max.max right)
19                       else
20                           if prev_i == prev_min
21                           then (left, prev_max)
22                           else (left.min prev_min, left.max prev_min)
23   
24               let selection = if min == max then None else Some (min, max)
25               text_box.selection = selection
26       else
27           text_box.selection = None
28   
29       text_box.cursor_index = i
30       text_box.update_offset
31   
32   let char_offset (text_block : TextBlock) (index : u32) =
33       let value = text_block.offsets[index]
34       (left = value.left, up = value.up)
35   
36   let create_cursor (text_box : TextBox) =
37       let text_block = text_box.text_block
38       let canvas = text_box.canvas
39   
40       let cursor = QuadControl
41           is_visible = text_box.is_focused
42           size@obs =
43               let rectangles = text_block.font@obs.rectangles
44               let width = rectangles['a'].right - rectangles['a'].left
45               let height = width / 4 |> max 2
46               Size width height
47   
48       let height = Atom<u32> text_box.height
49       text_box.subscribe { _, event -> if event ? SizeEvent/Height h then
50           height.set h }
51   
52       (text_box.cursor_index@atom, height)
53       |> to_atom
54       |> bind { i, h ->
55           let offset = char_offset text_block i
56           let v = Vector3
57               x = offset.left as f32 + text_box.offset as f32
58               y = h as f32 - (h as f32 * 0.2).round
59               z = Control.offset_z * 2
60   
61           cursor.position = v } |> text_box.push_token
62   
63       text_box.offset_controls.add cursor
64       canvas.items.add cursor
65       cursor
66   
67   type TextBox
68       local move_cursor (x : u32) (is_mouse_move : bool) =
69           let maybe_index = text_block.offsets.try_find_index
70               { _.left as i32 >= x as i32 - offset }
71   
72           let index = case maybe_index of
73               None -> display_text.length
74               Some index -> if index == 0 then 0 else index - 1
75   
76           set_cursor_index self cursor_index
77                            index.as<u32> is_mouse_move true
78   
79       val cursor = create_cursor self
80