rbcurse 0.1.3 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGELOG +126 -0
  2. data/Manifest.txt +53 -20
  3. data/README.markdown +423 -0
  4. data/Rakefile +3 -1
  5. data/examples/keytest.rb +177 -0
  6. data/examples/mpad2.rb +156 -0
  7. data/examples/newtesttabp.rb +121 -0
  8. data/examples/rfe.rb +48 -10
  9. data/examples/rfe_renderer.rb +4 -4
  10. data/examples/rvimsplit.rb +376 -0
  11. data/examples/sqlc.rb +97 -106
  12. data/examples/sqlm.rb +446 -0
  13. data/examples/test1.rb +4 -4
  14. data/examples/test2.rb +12 -12
  15. data/examples/testchars.rb +140 -0
  16. data/examples/testkeypress.rb +9 -4
  17. data/examples/testmulticomp.rb +72 -0
  18. data/examples/testscroller.rb +136 -0
  19. data/examples/testscrolllb.rb +86 -0
  20. data/examples/testscrollp.rb +87 -0
  21. data/examples/testscrollta.rb +80 -0
  22. data/examples/testscrolltable.rb +166 -0
  23. data/examples/testsplit.rb +87 -0
  24. data/examples/testsplit2.rb +123 -0
  25. data/examples/testsplit3.rb +215 -0
  26. data/examples/testsplit3_1.rb +244 -0
  27. data/examples/testsplit3a.rb +215 -0
  28. data/examples/testsplit3b.rb +237 -0
  29. data/examples/testsplitta.rb +148 -0
  30. data/examples/testsplittv.rb +142 -0
  31. data/examples/testsplittvv.rb +144 -0
  32. data/examples/testtable.rb +1 -1
  33. data/examples/testtabp.rb +3 -2
  34. data/examples/testtestw.rb +69 -0
  35. data/examples/testtodo.rb +5 -3
  36. data/examples/testtpane.rb +203 -0
  37. data/examples/testtpane2.rb +145 -0
  38. data/examples/testtpanetable.rb +199 -0
  39. data/examples/viewtodo.rb +5 -3
  40. data/lib/rbcurse.rb +1 -1
  41. data/lib/rbcurse/celleditor.rb +2 -2
  42. data/lib/rbcurse/colormap.rb +5 -5
  43. data/lib/rbcurse/defaultlistselectionmodel.rb +3 -3
  44. data/lib/rbcurse/io.rb +663 -0
  45. data/lib/rbcurse/listeditable.rb +306 -0
  46. data/lib/rbcurse/listkeys.rb +15 -15
  47. data/lib/rbcurse/listscrollable.rb +168 -27
  48. data/lib/rbcurse/mapper.rb +35 -13
  49. data/lib/rbcurse/rchangeevent.rb +28 -0
  50. data/lib/rbcurse/rform.rb +845 -0
  51. data/lib/rbcurse/rlistbox.rb +144 -34
  52. data/lib/rbcurse/rmessagebox.rb +10 -5
  53. data/lib/rbcurse/rmulticontainer.rb +325 -0
  54. data/lib/rbcurse/rmultitextview.rb +306 -0
  55. data/lib/rbcurse/rscrollform.rb +369 -0
  56. data/lib/rbcurse/rscrollpane.rb +511 -0
  57. data/lib/rbcurse/rsplitpane.rb +820 -0
  58. data/lib/rbcurse/rtabbedpane.rb +737 -109
  59. data/lib/rbcurse/rtabbedwindow.rb +326 -0
  60. data/lib/rbcurse/rtable.rb +220 -64
  61. data/lib/rbcurse/rtextarea.rb +340 -181
  62. data/lib/rbcurse/rtextview.rb +237 -101
  63. data/lib/rbcurse/rviewport.rb +203 -0
  64. data/lib/rbcurse/rwidget.rb +919 -95
  65. data/lib/rbcurse/scrollable.rb +7 -7
  66. data/lib/rbcurse/selectable.rb +4 -4
  67. data/lib/rbcurse/table/tablecellrenderer.rb +3 -0
  68. data/lib/rbcurse/undomanager.rb +181 -0
  69. data/lib/rbcurse/vieditable.rb +100 -0
  70. data/lib/ver/window.rb +471 -21
  71. metadata +66 -22
  72. data/README.txt +0 -312
  73. data/examples/testd.db +0 -0
  74. 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
@@ -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
- def previous_row
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
- @current_index -= 1 if @current_index > 0
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
- @current_index -= h
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
- @form.row = r + (@current_index-@toprow)
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 right
92
- @hscrollcols ||= @cols/2
93
- @pcol += @hscrollcols if @pcol + @hscrollcols < @padcols
94
- # window_erase @win XXX
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 left
97
- @hscrollcols ||= @cols/2
98
- @pcol -= @hscrollcols if @pcol > 0
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