rbcurse 0.1.3 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +126 -0
- data/Manifest.txt +53 -20
- data/README.markdown +423 -0
- data/Rakefile +3 -1
- data/examples/keytest.rb +177 -0
- data/examples/mpad2.rb +156 -0
- data/examples/newtesttabp.rb +121 -0
- data/examples/rfe.rb +48 -10
- data/examples/rfe_renderer.rb +4 -4
- data/examples/rvimsplit.rb +376 -0
- data/examples/sqlc.rb +97 -106
- data/examples/sqlm.rb +446 -0
- data/examples/test1.rb +4 -4
- data/examples/test2.rb +12 -12
- data/examples/testchars.rb +140 -0
- data/examples/testkeypress.rb +9 -4
- data/examples/testmulticomp.rb +72 -0
- data/examples/testscroller.rb +136 -0
- data/examples/testscrolllb.rb +86 -0
- data/examples/testscrollp.rb +87 -0
- data/examples/testscrollta.rb +80 -0
- data/examples/testscrolltable.rb +166 -0
- data/examples/testsplit.rb +87 -0
- data/examples/testsplit2.rb +123 -0
- data/examples/testsplit3.rb +215 -0
- data/examples/testsplit3_1.rb +244 -0
- data/examples/testsplit3a.rb +215 -0
- data/examples/testsplit3b.rb +237 -0
- data/examples/testsplitta.rb +148 -0
- data/examples/testsplittv.rb +142 -0
- data/examples/testsplittvv.rb +144 -0
- data/examples/testtable.rb +1 -1
- data/examples/testtabp.rb +3 -2
- data/examples/testtestw.rb +69 -0
- data/examples/testtodo.rb +5 -3
- data/examples/testtpane.rb +203 -0
- data/examples/testtpane2.rb +145 -0
- data/examples/testtpanetable.rb +199 -0
- data/examples/viewtodo.rb +5 -3
- data/lib/rbcurse.rb +1 -1
- data/lib/rbcurse/celleditor.rb +2 -2
- data/lib/rbcurse/colormap.rb +5 -5
- data/lib/rbcurse/defaultlistselectionmodel.rb +3 -3
- data/lib/rbcurse/io.rb +663 -0
- data/lib/rbcurse/listeditable.rb +306 -0
- data/lib/rbcurse/listkeys.rb +15 -15
- data/lib/rbcurse/listscrollable.rb +168 -27
- data/lib/rbcurse/mapper.rb +35 -13
- data/lib/rbcurse/rchangeevent.rb +28 -0
- data/lib/rbcurse/rform.rb +845 -0
- data/lib/rbcurse/rlistbox.rb +144 -34
- data/lib/rbcurse/rmessagebox.rb +10 -5
- data/lib/rbcurse/rmulticontainer.rb +325 -0
- data/lib/rbcurse/rmultitextview.rb +306 -0
- data/lib/rbcurse/rscrollform.rb +369 -0
- data/lib/rbcurse/rscrollpane.rb +511 -0
- data/lib/rbcurse/rsplitpane.rb +820 -0
- data/lib/rbcurse/rtabbedpane.rb +737 -109
- data/lib/rbcurse/rtabbedwindow.rb +326 -0
- data/lib/rbcurse/rtable.rb +220 -64
- data/lib/rbcurse/rtextarea.rb +340 -181
- data/lib/rbcurse/rtextview.rb +237 -101
- data/lib/rbcurse/rviewport.rb +203 -0
- data/lib/rbcurse/rwidget.rb +919 -95
- data/lib/rbcurse/scrollable.rb +7 -7
- data/lib/rbcurse/selectable.rb +4 -4
- data/lib/rbcurse/table/tablecellrenderer.rb +3 -0
- data/lib/rbcurse/undomanager.rb +181 -0
- data/lib/rbcurse/vieditable.rb +100 -0
- data/lib/ver/window.rb +471 -21
- metadata +66 -22
- data/README.txt +0 -312
- data/examples/testd.db +0 -0
- data/examples/todocsv.csv +0 -28
@@ -0,0 +1,306 @@
|
|
1
|
+
# Some methods for manipulating lists
|
2
|
+
# Different components may bind different keys to these
|
3
|
+
# Currently will be called by TextArea and the editable version
|
4
|
+
# of TextView (vieditable).
|
5
|
+
#
|
6
|
+
require 'rbcurse/rinputdataevent'
|
7
|
+
module ListEditable
|
8
|
+
|
9
|
+
def remove_all
|
10
|
+
@list = []
|
11
|
+
set_modified # added 2009-02-13 22:28 so repaints
|
12
|
+
end
|
13
|
+
# current behav is a mix of vim's D and C-k from alpine, i don;t know how i screwed it up like this
|
14
|
+
# Should be:
|
15
|
+
# 1. do not take cursor back by 1 (this is vims D behavior)
|
16
|
+
# 2. retain EOL, we need to evaluate at undo
|
17
|
+
# 3. if nothing coming in delete buffer then join next line here
|
18
|
+
# 4. if line is blank, it will go to delete line (i think).
|
19
|
+
# Earlier, a C-k at pos 0 would blank the line and not delete it (copied from alpine).
|
20
|
+
# The next C-k would delete. emacs deletes if C-k at pos 0.
|
21
|
+
def delete_eol
|
22
|
+
return -1 unless @editable
|
23
|
+
pos = @curpos -1 # retain from 0 till prev char
|
24
|
+
@delete_buffer = @buffer[@curpos..-1]
|
25
|
+
# currently eol is there in delete_buff often. Should i maintain it ? 2010-03-08 18:29 UNDO
|
26
|
+
#@delete_buffer.chomp! # new 2010-03-08 18:29 UNDO - this worked but hope does not have othe impact
|
27
|
+
|
28
|
+
# if pos is 0, pos-1 becomes -1, end of line!
|
29
|
+
@list[@current_index] = pos == -1 ? "" : @buffer[0..pos]
|
30
|
+
$log.debug "delete EOL :pos=#{pos}, #{@delete_buffer}: row: #{@list[@current_index]}:"
|
31
|
+
@buffer = @list[@current_index]
|
32
|
+
if @delete_buffer == ""
|
33
|
+
$log.debug " TA: DELETE going to join next "
|
34
|
+
join_next_line # pull next line in
|
35
|
+
end
|
36
|
+
oldcur = @curpos
|
37
|
+
#x cursor_backward if @curpos > 0 # this was vims behavior -- knoecked off
|
38
|
+
#fire_handler :CHANGE, self # 2008-12-09 14:56
|
39
|
+
fire_handler :CHANGE, InputDataEvent.new(oldcur,oldcur+@delete_buffer.length, self, :DELETE, @current_index, @delete_buffer) # 2008-12-24 18:34
|
40
|
+
set_modified
|
41
|
+
return @delete_buffer
|
42
|
+
end
|
43
|
+
def join_next_line
|
44
|
+
# return if last line TODO
|
45
|
+
buff = @list.delete_at(@current_index + 1)
|
46
|
+
if buff
|
47
|
+
$log.debug " TA: DELETE inside to join next #{buff} "
|
48
|
+
fire_handler :CHANGE, InputDataEvent.new(0,0+buff.length, self, :DELETE_LINE, @current_index+1, buff)
|
49
|
+
@buffer << buff
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# deletes given line or current
|
53
|
+
# now fires DELETE_LINE so no guessing by undo manager
|
54
|
+
def delete_line line=@current_index
|
55
|
+
return -1 unless @editable
|
56
|
+
if !$multiplier or $multiplier == 0
|
57
|
+
@delete_buffer = @list.delete_at line
|
58
|
+
else
|
59
|
+
@delete_buffer = @list.slice!(line, $multiplier)
|
60
|
+
end
|
61
|
+
$multiplier = 0
|
62
|
+
add_to_kill_ring @delete_buffer
|
63
|
+
@buffer = @list[@current_index]
|
64
|
+
if @buffer.nil?
|
65
|
+
up
|
66
|
+
setrowcol @row + 1, nil # @form.col
|
67
|
+
end
|
68
|
+
# warning: delete buffer can now be an array
|
69
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :DELETE_LINE, line, @delete_buffer) # 2008-12-24 18:34
|
70
|
+
set_modified
|
71
|
+
end
|
72
|
+
def delete_curr_char num=($multiplier == 0 ? 1 : $multiplier)
|
73
|
+
return -1 unless @editable
|
74
|
+
delete_at @curpos, num # changed so only one event, and one undo
|
75
|
+
set_modified
|
76
|
+
$multiplier = 0
|
77
|
+
end
|
78
|
+
#
|
79
|
+
# 2010-03-08 23:30 does not seem to be working well when backspacing at first char of line
|
80
|
+
# FIXME should work as a unit, so one undo and one fire_handler, at least if on one line.
|
81
|
+
def delete_prev_char num=($multiplier == 0 ? 1 : $multiplier)
|
82
|
+
return -1 if !@editable
|
83
|
+
num.times do
|
84
|
+
if @curpos <= 0
|
85
|
+
join_to_prev_line
|
86
|
+
return
|
87
|
+
end
|
88
|
+
@curpos -= 1 if @curpos > 0
|
89
|
+
delete_at
|
90
|
+
set_modified
|
91
|
+
addcol -1
|
92
|
+
end
|
93
|
+
$multiplier = 0
|
94
|
+
end
|
95
|
+
# open a new line and add chars to it.
|
96
|
+
# FIXME does not fire handler, thus won't undo
|
97
|
+
def append_row lineno=@current_index, chars=""
|
98
|
+
$log.debug "append row sapce:#{chars}."
|
99
|
+
@list.insert lineno+1, chars
|
100
|
+
end
|
101
|
+
##
|
102
|
+
# delete character/s on current line
|
103
|
+
def delete_at index=@curpos, howmany=1
|
104
|
+
return -1 if !@editable
|
105
|
+
$log.debug "delete_at (characters) : #{@current_index} #{@buffer} #{index}"
|
106
|
+
char = @buffer.slice!(@curpos,howmany) # changed added ,1 and take char for event
|
107
|
+
# if no newline at end of this then bring up prev character/s till maxlen
|
108
|
+
# NO WE DON'T DO THIS ANYLONGER 2008-12-26 21:09 lets see
|
109
|
+
=begin
|
110
|
+
if @buffer[-1,1]!="\r"
|
111
|
+
@buffer[-1]=" " if @buffer[-1,1]=="\n"
|
112
|
+
if !next_line.nil? and next_line.length > 0
|
113
|
+
move_chars_up
|
114
|
+
end
|
115
|
+
end
|
116
|
+
=end
|
117
|
+
set_modified true
|
118
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+howmany, self, :DELETE, @current_index, char) # 2008-12-24 18:34
|
119
|
+
end
|
120
|
+
def undo_handler(uh)
|
121
|
+
@undo_handler = uh
|
122
|
+
end
|
123
|
+
## THIS ONE SHOULD BE IN TEXTVIEW ALSO
|
124
|
+
# saves current or n lines into kill ring, appending to earlier contents
|
125
|
+
# Use yank (paste) or yank-pop to retrieve
|
126
|
+
def kill_ring_save
|
127
|
+
pointer = @current_index
|
128
|
+
list = []
|
129
|
+
repeatm {
|
130
|
+
line = @list[pointer]
|
131
|
+
list << line unless line.nil?
|
132
|
+
pointer += 1
|
133
|
+
}
|
134
|
+
add_to_kill_ring list
|
135
|
+
end
|
136
|
+
## THIS ONE SHOULD BE IN TEXTVIEW ALSO
|
137
|
+
# add given line or lines to kill_ring
|
138
|
+
def add_to_kill_ring list
|
139
|
+
# directly referenceing kill_ring. We need to OO it a bit, so we can change internals w'o breaking all.
|
140
|
+
# FIXME
|
141
|
+
if $append_next_kill
|
142
|
+
# user requested this kill to be appened to last kill, so it can be yanked as one
|
143
|
+
#$kill_ring.last << list
|
144
|
+
last = $kill_ring.pop
|
145
|
+
case list
|
146
|
+
when Array
|
147
|
+
list.insert 0, last
|
148
|
+
$kill_ring << list
|
149
|
+
when String
|
150
|
+
$kill_ring << [last, list]
|
151
|
+
end
|
152
|
+
else
|
153
|
+
$kill_ring << list
|
154
|
+
end
|
155
|
+
$kill_ring_pointer = $kill_ring.size
|
156
|
+
$append_next_kill = false
|
157
|
+
end
|
158
|
+
|
159
|
+
# pastes recent (last) entry of kill_ring.
|
160
|
+
# This can be one or more lines. Please note that for us vimmer's yank means copy
|
161
|
+
# but for emacsers it seems to mean paste. Aargh!!
|
162
|
+
def yank where=@current_index
|
163
|
+
return -1 if !@editable
|
164
|
+
return if $kill_ring.empty?
|
165
|
+
row = $kill_ring.last
|
166
|
+
index = where
|
167
|
+
case row
|
168
|
+
when Array
|
169
|
+
#index = @current_index
|
170
|
+
row.each{ |r|
|
171
|
+
@list.insert index, r.dup
|
172
|
+
index += 1
|
173
|
+
}
|
174
|
+
$kill_last_pop_size = row.size
|
175
|
+
when String
|
176
|
+
#@list[@current_index].insert row.dup
|
177
|
+
#@list.insert @current_index, row.dup
|
178
|
+
@list.insert index, row.dup
|
179
|
+
$kill_last_pop_size = 1
|
180
|
+
else
|
181
|
+
raise "textarea yank got uncertain datatype from kill_ring #{row.class} "
|
182
|
+
end
|
183
|
+
$kill_ring_pointer = $kill_ring.size - 1
|
184
|
+
$kill_ring_index = @current_index # pops will replace data in this row, never an insert
|
185
|
+
@repaint_required = true
|
186
|
+
# XXX not firing anything here, so i can't undo. yet, i don't know whether a yank will
|
187
|
+
# be followed by a yank-pop, in which case it will not be undone.
|
188
|
+
# object row can be string or array - time to use INSERT_LINE so we are clear
|
189
|
+
# row.length can be array's size or string length - beware
|
190
|
+
fire_handler :CHANGE, InputDataEvent.new(0,row.length, self, :INSERT_LINE, @current_index, row)
|
191
|
+
end
|
192
|
+
|
193
|
+
# paste previous entries from kill ring
|
194
|
+
# I am not totally clear on this, not being an emacs user. but seems you have to do C-y
|
195
|
+
# once (yank) before you can do a yank pop.
|
196
|
+
def yank_pop
|
197
|
+
return -1 if !@editable
|
198
|
+
return if $kill_ring.empty?
|
199
|
+
mapped_key = @current_key # we are mapped to this
|
200
|
+
# checking that user has done a yank on this row. We only replace on the given row, never
|
201
|
+
# insert. But what if user edited after yank, Sheesh ! XXX
|
202
|
+
if $kill_ring_index != @current_index
|
203
|
+
Ncurses.beep
|
204
|
+
return # error message required that user must yank first
|
205
|
+
end
|
206
|
+
# the real reason i put this into a loop is so that i can properly undo the
|
207
|
+
# action later if required. I only need to store the final selection.
|
208
|
+
# This also ensures the user doesn't wander off in between and come back.
|
209
|
+
row = nil
|
210
|
+
while true
|
211
|
+
# remove lines from last replace, then insert
|
212
|
+
index = @current_index
|
213
|
+
$kill_last_pop_size.times {
|
214
|
+
del = @list.delete_at index
|
215
|
+
}
|
216
|
+
row = $kill_ring[$kill_ring_pointer-$multiplier]
|
217
|
+
$multiplier = 0
|
218
|
+
index = @current_index
|
219
|
+
case row
|
220
|
+
when Array
|
221
|
+
row.each{ |r|
|
222
|
+
@list.insert index, r.dup
|
223
|
+
index += 1
|
224
|
+
}
|
225
|
+
$kill_last_pop_size = row.size
|
226
|
+
when String
|
227
|
+
@list.insert index, row.dup
|
228
|
+
$kill_last_pop_size = 1
|
229
|
+
else
|
230
|
+
raise "textarea yank_pop got uncertain datatype from kill_ring #{row.class} "
|
231
|
+
end
|
232
|
+
|
233
|
+
$kill_ring_pointer -= 1
|
234
|
+
if $kill_ring_pointer < 0
|
235
|
+
# should be size, but that'll give an error. need to find a way!
|
236
|
+
$kill_ring_pointer = $kill_ring.size - 1
|
237
|
+
end
|
238
|
+
@repaint_required = true
|
239
|
+
my_win = @form || @parent_component.form # 2010-02-12 12:51
|
240
|
+
my_win.repaint
|
241
|
+
ch = @graphic.getchar
|
242
|
+
if ch != mapped_key
|
243
|
+
@graphic.ungetch ch # seems to work fine
|
244
|
+
return ch # XXX to be picked up by handle_key loop and processed
|
245
|
+
end
|
246
|
+
end
|
247
|
+
# object row can be string or array - time to use INSERT_LINE so we are clear
|
248
|
+
# row.length can be array's size or string length - beware
|
249
|
+
fire_handler :CHANGE, InputDataEvent.new(0,row.length, self, :INSERT_LINE, @current_index, row)
|
250
|
+
return 0
|
251
|
+
end
|
252
|
+
def append_next_kill
|
253
|
+
$append_next_kill = true
|
254
|
+
end
|
255
|
+
# deletes count words on current line
|
256
|
+
# Does not at this point go beyond the line
|
257
|
+
def delete_word
|
258
|
+
return -1 unless @editable
|
259
|
+
$multiplier = 1 if !$multiplier or $multiplier == 0
|
260
|
+
line = @current_index
|
261
|
+
pos = @curpos
|
262
|
+
@delete_buffer = ""
|
263
|
+
# currently only look in current line
|
264
|
+
$multiplier.times {
|
265
|
+
found = @buffer.index(/[[:punct:][:space:]]/, pos)
|
266
|
+
break if !found
|
267
|
+
$log.debug " delete_word: pos #{pos} found #{found} buff: #{@buffer} "
|
268
|
+
@delete_buffer << @buffer.slice!(pos..found)
|
269
|
+
}
|
270
|
+
return if @delete_buffer == ""
|
271
|
+
$log.debug " delete_word: delbuff #{@delete_buffer} "
|
272
|
+
add_to_kill_ring @delete_buffer
|
273
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :DELETE, line, @delete_buffer) # 2008-12-24 18:34
|
274
|
+
set_modified
|
275
|
+
end
|
276
|
+
##
|
277
|
+
# deletes forward till the occurence of a character
|
278
|
+
# it gets the char from the user
|
279
|
+
# Should we pass in the character (and accept it as a separate func) ???
|
280
|
+
def delete_forward
|
281
|
+
return -1 unless @editable
|
282
|
+
ch = @graphic.getchar
|
283
|
+
return if ch < 0 || ch > 255
|
284
|
+
char = ch.chr
|
285
|
+
$multiplier = 1 if !$multiplier or $multiplier == 0
|
286
|
+
line = @current_index
|
287
|
+
pos = @curpos
|
288
|
+
tmpbuf = ""
|
289
|
+
# currently only look in current line
|
290
|
+
$multiplier.times {
|
291
|
+
found = @buffer.index(char, pos)
|
292
|
+
break if !found
|
293
|
+
#$log.debug " delete_forward: pos #{pos} found #{found} buff: #{@buffer} "
|
294
|
+
# ideally do this in one shot outside loop, but its okay here for now
|
295
|
+
tmpbuf << @buffer.slice!(pos..found)
|
296
|
+
}
|
297
|
+
return if tmpbuf == ""
|
298
|
+
@delete_buffer = tmpbuf
|
299
|
+
$log.debug " delete_forward: delbuff #{@delete_buffer} "
|
300
|
+
add_to_kill_ring @delete_buffer
|
301
|
+
fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :DELETE, line, @delete_buffer) # 2008-12-24 18:34
|
302
|
+
set_modified
|
303
|
+
$multiplier = 0
|
304
|
+
end
|
305
|
+
|
306
|
+
end # end module
|
data/lib/rbcurse/listkeys.rb
CHANGED
@@ -4,22 +4,22 @@ module RubyCurses
|
|
4
4
|
# That was possible earlier, but now that i am binding the key at construction time
|
5
5
|
# any changes to the vars after construction won't have an effect.
|
6
6
|
def install_list_keys
|
7
|
-
@KEY_ROW_SELECTOR ||= ?\C-x
|
8
|
-
@KEY_BLOCK_SELECTOR ||= ?\M-x
|
9
|
-
@KEY_GOTO_TOP ||= ?\M-0
|
10
|
-
@KEY_GOTO_BOTTOM ||= ?\M-9
|
11
|
-
#@KEY_ASK_FIND_FORWARD ||= ?\M-f
|
12
|
-
#@KEY_ASK_FIND_BACKWARD ||= ?\M-F
|
13
|
-
#@KEY_FIND_NEXT ||= ?\M-g
|
14
|
-
#@KEY_FIND_PREV ||= ?\M-G
|
15
|
-
@KEY_SCROLL_FORWARD ||= ?\C-n
|
16
|
-
@KEY_SCROLL_BACKWARD ||= ?\C-p
|
17
|
-
@KEY_SCROLL_RIGHT ||= ?\M-8
|
18
|
-
@KEY_SCROLL_LEFT ||= ?\M-7
|
7
|
+
@KEY_ROW_SELECTOR ||= ?\C-x.getbyte(0)
|
8
|
+
@KEY_BLOCK_SELECTOR ||= ?\M-x.getbyte(0)
|
9
|
+
@KEY_GOTO_TOP ||= ?\M-0.getbyte(0)
|
10
|
+
@KEY_GOTO_BOTTOM ||= ?\M-9.getbyte(0)
|
11
|
+
#@KEY_ASK_FIND_FORWARD ||= ?\M-f.getbyte(0)
|
12
|
+
#@KEY_ASK_FIND_BACKWARD ||= ?\M-F.getbyte(0)
|
13
|
+
#@KEY_FIND_NEXT ||= ?\M-g.getbyte(0)
|
14
|
+
#@KEY_FIND_PREV ||= ?\M-G.getbyte(0)
|
15
|
+
@KEY_SCROLL_FORWARD ||= ?\C-n.getbyte(0)
|
16
|
+
@KEY_SCROLL_BACKWARD ||= ?\C-p.getbyte(0)
|
17
|
+
@KEY_SCROLL_RIGHT ||= ?\M-8.getbyte(0)
|
18
|
+
@KEY_SCROLL_LEFT ||= ?\M-7.getbyte(0)
|
19
19
|
|
20
|
-
@KEY_CLEAR_SELECTION ||= ?\M-e
|
21
|
-
@KEY_PREV_SELECTION ||= ?\M-"
|
22
|
-
@KEY_NEXT_SELECTION ||= ?\M-'
|
20
|
+
@KEY_CLEAR_SELECTION ||= ?\M-e.getbyte(0)
|
21
|
+
@KEY_PREV_SELECTION ||= ?\M-".getbyte(0)
|
22
|
+
@KEY_NEXT_SELECTION ||= ?\M-'.getbyte(0)
|
23
23
|
|
24
24
|
=begin
|
25
25
|
bind_key(@KEY_ROW_SELECTOR) { toggle_row_selection }
|
@@ -9,17 +9,24 @@
|
|
9
9
|
#
|
10
10
|
module ListScrollable
|
11
11
|
attr_reader :search_found_ix, :find_offset, :find_offset1
|
12
|
-
|
12
|
+
attr_accessor :show_caret # 2010-01-23 23:06 our own fake insertion point
|
13
|
+
def previous_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
|
13
14
|
@oldrow = @current_index
|
14
|
-
|
15
|
+
# NOTE that putting a multiplier inside, prevents an event from being triggered for each row's
|
16
|
+
# on leave and on enter
|
17
|
+
num.times {
|
18
|
+
@current_index -= 1 if @current_index > 0
|
19
|
+
}
|
15
20
|
bounds_check
|
21
|
+
$multiplier = 0
|
16
22
|
end
|
17
23
|
alias :up :previous_row
|
18
|
-
def next_row
|
24
|
+
def next_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
|
19
25
|
@oldrow = @current_index
|
20
26
|
rc = row_count
|
21
|
-
@current_index += 1 if @current_index < rc
|
27
|
+
@current_index += 1*num if @current_index < rc
|
22
28
|
bounds_check
|
29
|
+
$multiplier = 0
|
23
30
|
end
|
24
31
|
alias :down :next_row
|
25
32
|
def goto_bottom
|
@@ -38,15 +45,18 @@ module ListScrollable
|
|
38
45
|
def scroll_backward
|
39
46
|
@oldrow = @current_index
|
40
47
|
h = scrollatrow()
|
41
|
-
|
48
|
+
m = $multiplier == 0? 1 : $multiplier
|
49
|
+
@current_index -= h * m
|
42
50
|
bounds_check
|
51
|
+
$multiplier = 0
|
43
52
|
end
|
44
53
|
def scroll_forward
|
45
54
|
@oldrow = @current_index
|
46
55
|
h = scrollatrow()
|
47
56
|
rc = row_count
|
57
|
+
m = $multiplier == 0? 1 : $multiplier
|
48
58
|
# more rows than box
|
49
|
-
if h < rc
|
59
|
+
if h * m < rc
|
50
60
|
@toprow += h+1 #if @current_index+h < rc
|
51
61
|
@current_index = @toprow
|
52
62
|
else
|
@@ -86,17 +96,81 @@ module ListScrollable
|
|
86
96
|
# the cursor should be appropriately positioned
|
87
97
|
def set_form_row
|
88
98
|
r,c = rowcol
|
89
|
-
@
|
99
|
+
@rows_panned ||= 0
|
100
|
+
|
101
|
+
#win_row=@form.window.top
|
102
|
+
win_row=@win_top # 2010-02-11 15:12 RFED16
|
103
|
+
win_row = 0 # 2010-02-07 21:44 now ext offset added by widget
|
104
|
+
#win_row = 0 # new approach, we have it
|
105
|
+
#win_col=@form.window.left
|
106
|
+
# added 1 ?? in copywin too 2010-02-11 18:51 RFED16 this results in extra in normal situations.
|
107
|
+
row = win_row + r + (@current_index-@toprow) + @rows_panned
|
108
|
+
$log.debug " #{@name} LIST set_form_row #{row} = ci #{@current_index} + r #{r} + winrow: #{win_row} - tr:#{@toprow} #{@toprow} + rowsp #{@rows_panned} "
|
109
|
+
$log.debug " - LIST set_form_row row_offset: #{@row_offset} + r #{r} + ci - topr + rowsp: #{@rows_panned}. c= #{c} "
|
110
|
+
|
111
|
+
## 2009-12-28 23:05 TRYING OUT but i really can't do this everywhere. BUFFERED
|
112
|
+
## this needs to percolate up a heirarchy.
|
113
|
+
## 2010-01-05 21:09 changed c to nil, since c is not cursor col pos but where printing starts, i think
|
114
|
+
#@form.setrowcol row, nil
|
115
|
+
#setformrowcol row, nil
|
116
|
+
setrowcol row, nil
|
117
|
+
show_caret_func
|
118
|
+
end
|
119
|
+
## In many situations like placing a textarea or textview inside a splitpane
|
120
|
+
##+ or scrollpane there have been issues getting the cursor at the right point,
|
121
|
+
##+ since there are multiple buffers. Finally in tabbedpanes, i am pretty
|
122
|
+
##+ lost getting the correct position, and i feel we should set the cursor
|
123
|
+
##+ internally once and for all. So here's an attempt
|
124
|
+
|
125
|
+
# paint the cursor ourselves on the widget, rather than rely on getting to the top window with
|
126
|
+
# the correct coordinates. I do need to erase cursor too. Can be dicey, but is worth the attempt.
|
127
|
+
# This works perfectly, except for when placed in a Tabbedpane since that prints the form with a row offset
|
128
|
+
#+ of 2 and the widget does not know of the offset. cursor gets it correct since the form has an add_row.
|
129
|
+
def show_caret_func
|
130
|
+
return unless @show_caret
|
131
|
+
# trying highlighting cursor 2010-01-23 19:07 TABBEDPANE TRYING
|
132
|
+
# TODO take into account rows_panned etc ? I don't think so.
|
133
|
+
@rows_panned ||= 0
|
134
|
+
r,c = rowcol
|
135
|
+
yy = r + @current_index - @toprow - @win_top
|
136
|
+
#xx = @form.col # how do we know what value has been set earlier ?
|
137
|
+
yy = r + @current_index - @toprow #- @win_top
|
138
|
+
yy = @row_offset + @current_index - @toprow #- @win_top
|
139
|
+
xx = @col_offset + @curpos || 0
|
140
|
+
#yy = @row_offset if yy < @row_offset # sometimes r is 0, we are missing something in tabbedpane+scroll
|
141
|
+
#xx = @col_offset if xx < @col_offset
|
142
|
+
#xx = 0 if xx < 0
|
143
|
+
|
144
|
+
$log.debug " #{@name} printing CARET at #{yy},#{xx}: fwt:- #{@win_top} r:#{@row} tr:-#{@toprow}+ci:#{@current_index},+r #{r} "
|
145
|
+
if !@oldcursorrow.nil?
|
146
|
+
@graphic.mvchgat(y=@oldcursorrow, x=@oldcursorcol, 1, Ncurses::A_NORMAL, $datacolor, NIL)
|
147
|
+
end
|
148
|
+
@oldcursorrow = yy
|
149
|
+
@oldcursorcol = xx
|
150
|
+
@graphic.mvchgat(y=yy, x=xx, 1, Ncurses::A_NORMAL, $reversecolor, nil)
|
151
|
+
@buffer_modified = true
|
90
152
|
end
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
#
|
153
|
+
def scroll_right
|
154
|
+
$log.debug " inside scroll_right "
|
155
|
+
hscrollcols = $multiplier > 0 ? $multiplier : @width/2
|
156
|
+
$log.debug " scroll_right mult:#{$multiplier} , hscrollcols #{hscrollcols}, w: #{@width} ll:#{@longest_line} "
|
157
|
+
#blen = @buffer.rstrip.length
|
158
|
+
blen = @longest_line
|
159
|
+
@pcol += hscrollcols if @pcol + @width < blen
|
160
|
+
@repaint_required = true
|
95
161
|
end
|
96
|
-
def
|
97
|
-
|
98
|
-
@pcol -=
|
162
|
+
def scroll_left
|
163
|
+
hscrollcols = $multiplier > 0 ? $multiplier : @width/2
|
164
|
+
@pcol -= hscrollcols if @pcol > 0
|
99
165
|
@pcol = 0 if @pcol < 0
|
166
|
+
@repaint_required = true
|
167
|
+
end
|
168
|
+
## returns cursor to last row (if moving columns in same row, won't work)
|
169
|
+
# Useful after a large move such as 12j, 20 C-n etc, Mapped to '' in textview
|
170
|
+
def goto_last_position
|
171
|
+
return unless @oldrow
|
172
|
+
@current_index = @oldrow
|
173
|
+
bounds_check
|
100
174
|
end
|
101
175
|
# not that saving content_rows is buggy since we add rows.
|
102
176
|
##
|
@@ -116,16 +190,16 @@ module ListScrollable
|
|
116
190
|
begin
|
117
191
|
###pre_key # 2009-01-07 13:23
|
118
192
|
case ch
|
119
|
-
when ?\C-n
|
193
|
+
when ?\C-n.getbyte(0)
|
120
194
|
scroll_forward
|
121
195
|
when 32
|
122
196
|
scroll_forward
|
123
|
-
when ?\C-p
|
197
|
+
when ?\C-p.getbyte(0)
|
124
198
|
scroll_backward
|
125
|
-
when ?0
|
199
|
+
when ?0.getbyte(0)
|
126
200
|
#goto_start
|
127
201
|
goto_top
|
128
|
-
when ?9
|
202
|
+
when ?9.getbyte(0)
|
129
203
|
#goto_end
|
130
204
|
goto_bottom
|
131
205
|
when KEY_UP
|
@@ -143,7 +217,7 @@ module ListScrollable
|
|
143
217
|
if respond_to? :fire
|
144
218
|
fire
|
145
219
|
end
|
146
|
-
when ?A..?Z, ?a..?z
|
220
|
+
when ?A.getbyte(0)..?Z.getbyte(0), ?a.getbyte(0)..?z.getbyte(0)
|
147
221
|
ret = set_selection_for_char ch.chr
|
148
222
|
else
|
149
223
|
return :UNHANDLED #if ret == -1
|
@@ -159,7 +233,7 @@ module ListScrollable
|
|
159
233
|
data = get_content
|
160
234
|
row = focussed_index + 1
|
161
235
|
row.upto(data.length-1) do |ix|
|
162
|
-
val = data[ix].chomp
|
236
|
+
val = data[ix].chomp rescue return # 2010-01-05 15:28 crashed on trueclass
|
163
237
|
#if val[0,1] == char #and val != currval
|
164
238
|
if val[0,1].casecmp(char) == 0 #AND VAL != CURRval
|
165
239
|
return ix
|
@@ -180,7 +254,7 @@ module ListScrollable
|
|
180
254
|
def set_selection_for_char char
|
181
255
|
@oldrow = @current_index
|
182
256
|
ix = next_match char
|
183
|
-
@current_index = ix if ix != -1
|
257
|
+
@current_index = ix if ix && ix != -1
|
184
258
|
bounds_check
|
185
259
|
return ix
|
186
260
|
end
|
@@ -216,13 +290,13 @@ module ListScrollable
|
|
216
290
|
end
|
217
291
|
def install_keys
|
218
292
|
=begin
|
219
|
-
@KEY_ASK_FIND_FORWARD ||= ?\M-f
|
220
|
-
@KEY_ASK_FIND_BACKWARD ||= ?\M-F
|
221
|
-
@KEY_FIND_NEXT ||= ?\M-g
|
222
|
-
@KEY_FIND_PREV ||= ?\M-G
|
293
|
+
@KEY_ASK_FIND_FORWARD ||= ?\M-f.getbyte(0)
|
294
|
+
@KEY_ASK_FIND_BACKWARD ||= ?\M-F.getbyte(0)
|
295
|
+
@KEY_FIND_NEXT ||= ?\M-g.getbyte(0)
|
296
|
+
@KEY_FIND_PREV ||= ?\M-G.getbyte(0)
|
223
297
|
=end
|
224
|
-
@KEY_ASK_FIND ||= ?\M-f
|
225
|
-
@KEY_FIND_MORE ||= ?\M-g
|
298
|
+
@KEY_ASK_FIND ||= ?\M-f.getbyte(0)
|
299
|
+
@KEY_FIND_MORE ||= ?\M-g.getbyte(0)
|
226
300
|
end
|
227
301
|
def ask_search
|
228
302
|
options = ["Search backwards", "case insensitive", "Wrap around"]
|
@@ -349,5 +423,72 @@ module ListScrollable
|
|
349
423
|
end
|
350
424
|
return nil
|
351
425
|
end
|
426
|
+
##
|
427
|
+
# goes to start of next word (or n words) - vi's w
|
428
|
+
#
|
429
|
+
def forward_word
|
430
|
+
$multiplier = 1 if !$multiplier or $multiplier == 0
|
431
|
+
line = @current_index
|
432
|
+
buff = @list[line]
|
433
|
+
pos = @curpos
|
434
|
+
$multiplier.times {
|
435
|
+
found = buff.index(/[[:punct:][:space:]]/, pos)
|
436
|
+
if !found
|
437
|
+
# if not found, we've lost a counter
|
438
|
+
line += 1 # unless eof
|
439
|
+
buff = @list[line]
|
440
|
+
pos = 0
|
441
|
+
else
|
442
|
+
pos = found + 1
|
443
|
+
end
|
444
|
+
$log.debug " forward_word: pos #{pos} line #{line} buff: #{buff}"
|
445
|
+
}
|
446
|
+
@current_index = line
|
447
|
+
@curpos = pos
|
448
|
+
@buffer = @list[@current_index]
|
449
|
+
set_form_row
|
450
|
+
set_form_col pos
|
451
|
+
@repaint_required = true
|
452
|
+
end
|
453
|
+
##
|
454
|
+
# goes to next occurence of <char> (or nth occurence)
|
455
|
+
# Actually, we can club this with forward_word so no duplication
|
456
|
+
# Or call one from the other
|
457
|
+
#
|
458
|
+
def forward_char char=nil
|
459
|
+
if char.nil?
|
460
|
+
$log.debug " XXX acceptng char"
|
461
|
+
ch = @graphic.getchar
|
462
|
+
return -1 if ch < 0 or ch > 255 # or 127 ???
|
463
|
+
char = ch.chr
|
464
|
+
end
|
465
|
+
$log.debug " forward_char char:#{char}:"
|
466
|
+
$multiplier = 1 if !$multiplier or $multiplier == 0
|
467
|
+
line = @current_index
|
468
|
+
buff = @list[line]
|
469
|
+
pos = @curpos
|
470
|
+
$multiplier.times {
|
471
|
+
found = false
|
472
|
+
while !found
|
473
|
+
found = buff.index(char, pos)
|
474
|
+
if !found
|
475
|
+
line += 1 # unless eof
|
476
|
+
buff = @list[line]
|
477
|
+
pos = 0
|
478
|
+
else
|
479
|
+
pos = found + 1
|
480
|
+
end
|
481
|
+
break if line >= @list.size
|
482
|
+
$log.debug " #{found} forward_word: pos #{pos} line #{line} buff: #{buff}"
|
483
|
+
end
|
484
|
+
}
|
485
|
+
@current_index = line
|
486
|
+
@curpos = pos
|
487
|
+
@buffer = @list[@current_index]
|
488
|
+
set_form_row
|
489
|
+
set_form_col pos
|
490
|
+
@repaint_required = true
|
491
|
+
end
|
492
|
+
|
352
493
|
|
353
494
|
end
|