rbcurse 0.1.3 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|