fortrangoingonforty/fortty / 8e6d2a3

Browse files

Add text selection module

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
8e6d2a3ae90297559937a6e4493a0a9cf3128a3e
Parents
5732b28
Tree
0778411

1 changed file

StatusFile+-
A src/terminal/selection.f90 131 0
src/terminal/selection.f90added
@@ -0,0 +1,131 @@
1
+module selection_mod
2
+  use cell_mod
3
+  use screen_mod
4
+  implicit none
5
+  private
6
+
7
+  public :: selection_t
8
+  public :: selection_start, selection_update, selection_end
9
+  public :: selection_clear, selection_contains
10
+  public :: selection_is_active, selection_get_bounds
11
+  public :: selection_normalize
12
+
13
+  type :: selection_t
14
+    logical :: active = .false.
15
+    logical :: selecting = .false.  ! Mouse button held
16
+    integer :: start_row = 0
17
+    integer :: start_col = 0
18
+    integer :: end_row = 0
19
+    integer :: end_col = 0
20
+  end type selection_t
21
+
22
+contains
23
+
24
+  subroutine selection_start(sel, row, col)
25
+    type(selection_t), intent(inout) :: sel
26
+    integer, intent(in) :: row, col
27
+
28
+    sel%start_row = row
29
+    sel%start_col = col
30
+    sel%end_row = row
31
+    sel%end_col = col
32
+    sel%selecting = .true.
33
+    sel%active = .false.  ! Not active until mouse moves
34
+  end subroutine selection_start
35
+
36
+  subroutine selection_update(sel, row, col)
37
+    type(selection_t), intent(inout) :: sel
38
+    integer, intent(in) :: row, col
39
+
40
+    if (.not. sel%selecting) return
41
+
42
+    sel%end_row = row
43
+    sel%end_col = col
44
+
45
+    ! Mark as active if selection spans at least one cell
46
+    if (sel%start_row /= sel%end_row .or. sel%start_col /= sel%end_col) then
47
+      sel%active = .true.
48
+    end if
49
+  end subroutine selection_update
50
+
51
+  subroutine selection_end(sel)
52
+    type(selection_t), intent(inout) :: sel
53
+
54
+    sel%selecting = .false.
55
+    ! Keep active if we have a valid selection
56
+  end subroutine selection_end
57
+
58
+  subroutine selection_clear(sel)
59
+    type(selection_t), intent(inout) :: sel
60
+
61
+    sel%active = .false.
62
+    sel%selecting = .false.
63
+    sel%start_row = 0
64
+    sel%start_col = 0
65
+    sel%end_row = 0
66
+    sel%end_col = 0
67
+  end subroutine selection_clear
68
+
69
+  function selection_is_active(sel) result(active)
70
+    type(selection_t), intent(in) :: sel
71
+    logical :: active
72
+
73
+    active = sel%active
74
+  end function selection_is_active
75
+
76
+  subroutine selection_normalize(sel, r1, c1, r2, c2)
77
+    type(selection_t), intent(in) :: sel
78
+    integer, intent(out) :: r1, c1, r2, c2
79
+
80
+    ! Return normalized bounds (r1,c1) <= (r2,c2) in reading order
81
+    if (sel%start_row < sel%end_row .or. &
82
+        (sel%start_row == sel%end_row .and. sel%start_col <= sel%end_col)) then
83
+      r1 = sel%start_row
84
+      c1 = sel%start_col
85
+      r2 = sel%end_row
86
+      c2 = sel%end_col
87
+    else
88
+      r1 = sel%end_row
89
+      c1 = sel%end_col
90
+      r2 = sel%start_row
91
+      c2 = sel%start_col
92
+    end if
93
+  end subroutine selection_normalize
94
+
95
+  subroutine selection_get_bounds(sel, r1, c1, r2, c2)
96
+    type(selection_t), intent(in) :: sel
97
+    integer, intent(out) :: r1, c1, r2, c2
98
+
99
+    call selection_normalize(sel, r1, c1, r2, c2)
100
+  end subroutine selection_get_bounds
101
+
102
+  function selection_contains(sel, row, col) result(contains)
103
+    type(selection_t), intent(in) :: sel
104
+    integer, intent(in) :: row, col
105
+    logical :: contains
106
+    integer :: r1, c1, r2, c2
107
+
108
+    contains = .false.
109
+    if (.not. sel%active) return
110
+
111
+    call selection_normalize(sel, r1, c1, r2, c2)
112
+
113
+    ! Check if (row, col) is within selection
114
+    if (row < r1 .or. row > r2) return
115
+
116
+    if (r1 == r2) then
117
+      ! Single line selection
118
+      contains = (col >= c1 .and. col <= c2)
119
+    else if (row == r1) then
120
+      ! First line of multi-line selection
121
+      contains = (col >= c1)
122
+    else if (row == r2) then
123
+      ! Last line of multi-line selection
124
+      contains = (col <= c2)
125
+    else
126
+      ! Middle lines are fully selected
127
+      contains = .true.
128
+    end if
129
+  end function selection_contains
130
+
131
+end module selection_mod