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.
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