rbcurse 1.1.5 → 1.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/CHANGELOG +45 -0
  2. data/Makefile +1 -1
  3. data/Manifest.txt +91 -0
  4. data/NOTES +349 -2
  5. data/README.markdown +12 -0
  6. data/VERSION +1 -1
  7. data/examples/abasiclist.rb +25 -0
  8. data/examples/alpmenu.rb +42 -0
  9. data/examples/app.rb +883 -0
  10. data/examples/appcombo.rb +17 -0
  11. data/examples/appdirtree.rb +73 -0
  12. data/examples/appemail.rb +164 -0
  13. data/examples/appemaillb.rb +308 -0
  14. data/examples/appgcompose.rb +303 -0
  15. data/examples/appgmail.rb +951 -0
  16. data/examples/atree.rb +56 -0
  17. data/examples/dirtree.rb +78 -0
  18. data/examples/focusmanager.rb +31 -0
  19. data/examples/imap.rb +48 -0
  20. data/examples/menu1.rb +79 -0
  21. data/examples/multispl.rb +86 -0
  22. data/examples/rfe.rb +3 -4
  23. data/examples/rmail.rb +188 -0
  24. data/examples/s.rb +10 -0
  25. data/examples/scrollbar.rb +104 -0
  26. data/examples/splitp.rb +56 -0
  27. data/examples/table1.rb +30 -0
  28. data/examples/term.rb +48 -0
  29. data/examples/term2.rb +54 -0
  30. data/examples/test1.rb +4 -2
  31. data/examples/test2.rb +9 -9
  32. data/examples/testapp.rb +44 -0
  33. data/examples/testapp2.rb +51 -0
  34. data/examples/testcombo.rb +2 -2
  35. data/examples/testgmail.rb +46 -0
  36. data/examples/testlistbox.rb +0 -1
  37. data/examples/testmultispl.rb +199 -0
  38. data/examples/testree.rb +127 -0
  39. data/examples/testscroller.rb +0 -1
  40. data/examples/testscrolllb.rb +1 -1
  41. data/examples/testscrollp.rb +2 -1
  42. data/examples/testscrollta.rb +1 -1
  43. data/examples/testscrolltable.rb +1 -2
  44. data/examples/testsplit.rb +1 -1
  45. data/examples/testsplit2.rb +1 -1
  46. data/examples/testsplit3.rb +1 -1
  47. data/examples/testsplit3_1.rb +1 -1
  48. data/examples/testsplit3a.rb +1 -1
  49. data/examples/testsplit3b.rb +1 -1
  50. data/examples/testsplitta.rb +1 -1
  51. data/examples/testsplittv.rb +1 -1
  52. data/examples/testsplittvv.rb +1 -1
  53. data/examples/testtodo.rb +491 -488
  54. data/examples/testvimsplit.rb +111 -0
  55. data/examples/todo.db +0 -0
  56. data/examples/todocsv.csv +28 -0
  57. data/examples/viewtodo.rb +408 -403
  58. data/lib/rbcurse/action.rb +1 -0
  59. data/lib/rbcurse/app.rb +1294 -0
  60. data/lib/rbcurse/applicationheader.rb +7 -2
  61. data/lib/rbcurse/checkboxcellrenderer.rb +0 -12
  62. data/lib/rbcurse/colormap.rb +34 -8
  63. data/lib/rbcurse/comboboxcellrenderer.rb +0 -11
  64. data/lib/rbcurse/defaultlistselectionmodel.rb +23 -7
  65. data/lib/rbcurse/extras/bottomline.rb +1681 -0
  66. data/lib/rbcurse/extras/directorylist.rb +445 -0
  67. data/lib/rbcurse/extras/directorytree.rb +69 -0
  68. data/lib/rbcurse/extras/divider.rb +310 -0
  69. data/lib/rbcurse/extras/focusmanager.rb +31 -0
  70. data/lib/rbcurse/extras/listselectable.rb +222 -0
  71. data/lib/rbcurse/extras/masterdetail.rb +164 -0
  72. data/lib/rbcurse/extras/menutree.rb +63 -0
  73. data/lib/rbcurse/extras/rlink.rb +27 -0
  74. data/lib/rbcurse/extras/rmenulink.rb +21 -0
  75. data/lib/rbcurse/extras/scrollbar.rb +134 -0
  76. data/lib/rbcurse/extras/stdscrwindow.rb +247 -0
  77. data/lib/rbcurse/extras/tabular.rb +258 -0
  78. data/lib/rbcurse/extras/tabularwidget.rb +1070 -0
  79. data/lib/rbcurse/extras/viewer.rb +106 -0
  80. data/lib/rbcurse/io.rb +137 -80
  81. data/lib/rbcurse/keylabelprinter.rb +4 -0
  82. data/lib/rbcurse/listcellrenderer.rb +91 -59
  83. data/lib/rbcurse/listscrollable.rb +93 -95
  84. data/lib/rbcurse/listselectable.rb +60 -7
  85. data/lib/rbcurse/ractionevent.rb +67 -0
  86. data/lib/rbcurse/rbasiclistbox.rb +688 -0
  87. data/lib/rbcurse/rcombo.rb +5 -5
  88. data/lib/rbcurse/rcommandwindow.rb +555 -0
  89. data/lib/rbcurse/rinputdataevent.rb +12 -0
  90. data/lib/rbcurse/rlistbox.rb +305 -124
  91. data/lib/rbcurse/rmenu.rb +99 -46
  92. data/lib/rbcurse/rmessagebox.rb +13 -6
  93. data/lib/rbcurse/rmulticontainer.rb +54 -93
  94. data/lib/rbcurse/rmultisplit.rb +731 -0
  95. data/lib/rbcurse/rmultitextview.rb +3 -2
  96. data/lib/rbcurse/rpopupmenu.rb +0 -1
  97. data/lib/rbcurse/rprogress.rb +117 -0
  98. data/lib/rbcurse/rscrollpane.rb +2 -1
  99. data/lib/rbcurse/rsplitpane.rb +94 -20
  100. data/lib/rbcurse/rsplitpane2.rb +1009 -0
  101. data/lib/rbcurse/rtabbedpane.rb +3 -2
  102. data/lib/rbcurse/rtabbedwindow.rb +0 -1
  103. data/lib/rbcurse/rtable.rb +92 -64
  104. data/lib/rbcurse/rtextarea.rb +91 -57
  105. data/lib/rbcurse/rtextview.rb +223 -70
  106. data/lib/rbcurse/rtree.rb +723 -0
  107. data/lib/rbcurse/rviewport.rb +2 -1
  108. data/lib/rbcurse/rvimsplit.rb +768 -0
  109. data/lib/rbcurse/rwidget.rb +524 -325
  110. data/lib/rbcurse/table/tablecellrenderer.rb +1 -1
  111. data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -1
  112. data/lib/rbcurse/tree/treecellrenderer.rb +137 -0
  113. data/lib/rbcurse/tree/treemodel.rb +428 -0
  114. data/lib/rbcurse/vieditable.rb +14 -13
  115. data/lib/ver/ncurses.rb +6 -0
  116. data/lib/ver/window.rb +67 -32
  117. metadata +99 -23
  118. data/bin/rbcurse +0 -0
  119. data/examples/rvimsplit.rb +0 -376
  120. data/examples/todo.rb +0 -1
  121. data/lib/rbcurse/rform.rb +0 -845
  122. data/lib/rbcurse/selectable.rb +0 -94
  123. data/rbcurse.gemspec +0 -188
@@ -9,9 +9,6 @@
9
9
  Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
10
 
11
11
  =end
12
- require 'rubygems'
13
- require 'ncurses'
14
- require 'logger'
15
12
  require 'rbcurse'
16
13
  require 'rbcurse/rlistbox'
17
14
 
@@ -24,6 +21,7 @@ module RubyCurses
24
21
  # TODO :
25
22
  # i no longer use values, i now use "list" or better "list_data_model"
26
23
  # try to make it so values gets converted to list.
24
+ # NOTE: 2010-10-01 13:25 spacebar and enter will popup in addition to Alt-Down
27
25
  class ComboBox < Field
28
26
  include RubyCurses::EventHandler
29
27
  dsl_accessor :list_config
@@ -41,11 +39,12 @@ module RubyCurses
41
39
  # added if check since it was overriding set_buffer in creation. 2009-01-18 00:03
42
40
  set_buffer @list[@current_index].dup if @buffer.nil? or @buffer.empty?
43
41
  init_vars
42
+ @_events.push(*[:CHANGE, :ENTER_ROW, :LEAVE_ROW])
44
43
  end
45
44
  def init_vars
46
45
  super
47
46
  @show_symbol ||= true
48
- @COMBO_SYMBOL ||= Ncurses::ACS_GEQUAL
47
+ @COMBO_SYMBOL ||= Ncurses::ACS_DARROW #GEQUAL
49
48
  bind_key(KEY_UP) { previous_row }
50
49
  bind_key(KEY_DOWN) { next_row }
51
50
  end
@@ -84,7 +83,8 @@ module RubyCurses
84
83
  # previous_row
85
84
  #when KEY_DOWN # show previous value
86
85
  # next_row
87
- when KEY_DOWN+ RubyCurses::META_KEY # alt down
86
+ # adding spacebar to popup combo, as in microemacs 2010-10-01 13:21
87
+ when 32, KEY_DOWN+ RubyCurses::META_KEY # alt down
88
88
  popup # pop up the popup
89
89
  else
90
90
  super
@@ -0,0 +1,555 @@
1
+ =begin
2
+ * Name: rcommandwindow: pops up a status message at bottom of screen
3
+ creating a new window, so we don't have to worry about having window
4
+ handle.
5
+ Can use with say, ask etc. wsay wask wagree etc !
6
+ * Description
7
+ * Author: rkumar (arunachalesha)
8
+ * Date: 2008-11-19 12:49
9
+ * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
+ * file separated on 2009-01-13 22:39
11
+
12
+ =end
13
+ require 'rbcurse'
14
+
15
+ module RubyCurses
16
+ ##
17
+ #
18
+ #
19
+ class CommandWindow
20
+ include RubyCurses::Utils
21
+ dsl_accessor :box
22
+ dsl_accessor :title
23
+ attr_reader :config
24
+ attr_reader :layout
25
+ attr_reader :window # required for keyboard or printing
26
+ dsl_accessor :height, :width, :top, :left # 2009-01-06 00:05 after removing meth missing
27
+
28
+ def initialize form=nil, aconfig={}, &block
29
+ #@form = form
30
+ @config = aconfig
31
+ @config.each_pair { |k,v| instance_variable_set("@#{k}",v) }
32
+ instance_eval &block if block_given?
33
+ if @layout.nil?
34
+ set_layout(1,80, 27, 0)
35
+ end
36
+ @height = @layout[:height]
37
+ @width = @layout[:width]
38
+ @window = VER::Window.new(@layout)
39
+ @start = 0 # row for display of text with paging
40
+ @list = []
41
+ require 'forwardable'
42
+ require 'rbcurse/extras/bottomline'
43
+ @bottomline = Bottomline.new @window, 0
44
+ @bottomline.name = "rcommandwindow's bl"
45
+ extend Forwardable
46
+ def_delegators :@bottomline, :ask, :say, :agree, :choose #, :display_text_interactive
47
+ #if @form.nil?
48
+ #@form = RubyCurses::Form.new @window
49
+ #else
50
+ #@form.window = @window
51
+ #end
52
+ #acolor = get_color $reversecolor
53
+ #color = get_color $datacolor
54
+ #@window.printstring 0,0,"hello there", $normalcolor, 'normal'
55
+ #@window.bkgd(Ncurses.COLOR_PAIR(acolor));
56
+ if @box == :border
57
+ @window.box 0,0
58
+ elsif @box
59
+ @window.attron(Ncurses.COLOR_PAIR($normalcolor) | Ncurses::A_REVERSE)
60
+ @window.mvhline 0,0,1,@width
61
+ @window.printstring 0,0,@title, $normalcolor #, 'normal' if @title
62
+ @window.attroff(Ncurses.COLOR_PAIR($normalcolor) | Ncurses::A_REVERSE)
63
+ else
64
+ @window.printstring 0,0,@title, $normalcolor, 'reverse' if @title
65
+ end
66
+ @window.wrefresh
67
+ @panel = @window.panel
68
+ Ncurses::Panel.update_panels
69
+ #@form.repaint
70
+ @window.wrefresh
71
+ #handle_keys
72
+ @row_offset = 0
73
+ if @box
74
+ @row_offset = 1
75
+ end
76
+ end
77
+ ##
78
+ ## message box
79
+ def stopping?
80
+ @stop
81
+ end
82
+ # todo handle mappings, so user can map keys TODO
83
+ def handle_keys
84
+ begin
85
+ while((ch = @window.getchar()) != 999 )
86
+ case ch
87
+ when -1
88
+ next
89
+ else
90
+ press ch
91
+ break if @stop
92
+ yield ch if block_given?
93
+ end
94
+ end
95
+ ensure
96
+ destroy
97
+ end
98
+ return #@selected_index
99
+ end
100
+ # handles a key, commandline
101
+ def press ch
102
+ ch = ch.getbyte(0) if ch.class==String ## 1.9
103
+ $log.debug " XXX press #{ch} " if $log.debug?
104
+ case ch
105
+ when -1
106
+ return
107
+ when KEY_F1, 27, ?\C-q.getbyte(0)
108
+ @stop = true
109
+ return
110
+ when KEY_ENTER, 10, 13
111
+ #$log.debug "popup ENTER : #{@selected_index} "
112
+ #$log.debug "popup ENTER : #{field.name}" if !field.nil?
113
+ @stop = true
114
+ return
115
+ when ?\C-d.getbyte(0)
116
+ @start += @height-1
117
+ bounds_check
118
+ when KEY_UP
119
+ @start -= 1
120
+ @start = 0 if @start < 0
121
+ when KEY_DOWN
122
+ @start += 1
123
+ bounds_check
124
+ when ?\C-b.getbyte(0)
125
+ @start -= @height-1
126
+ @start = 0 if @start < 0
127
+ when 0
128
+ @start = 0
129
+ end
130
+ #@form.repaint
131
+ Ncurses::Panel.update_panels();
132
+ Ncurses.doupdate();
133
+ @window.wrefresh
134
+ end
135
+ # might as well add more keys for paging.
136
+ def configure(*val , &block)
137
+ case val.size
138
+ when 1
139
+ return @config[val[0]]
140
+ when 2
141
+ @config[val[0]] = val[1]
142
+ instance_variable_set("@#{val[0]}", val[1])
143
+ end
144
+ instance_eval &block if block_given?
145
+ end
146
+ def cget param
147
+ @config[param]
148
+ end
149
+
150
+ def set_layout(height=0, width=0, top=0, left=0)
151
+ @layout = { :height => height, :width => width, :top => top, :left => left }
152
+ @height = height
153
+ @width = width
154
+ end
155
+ def destroy
156
+ $log.debug "DESTROY : rcommandwindow"
157
+ if @window
158
+ begin
159
+ panel = @window.panel
160
+ Ncurses::Panel.del_panel(panel) if panel
161
+ @window.delwin
162
+ rescue => exc
163
+ end
164
+ end
165
+ end
166
+ # do not go more than 3 columns and do not print more than window TODO FIXME
167
+ def display_menu list, options={}
168
+ indexing = options[:indexing]
169
+ max_cols = 3
170
+ l_succ = "`"
171
+ act_height = @height
172
+ if @box
173
+ act_height = @height - 2
174
+ end
175
+ lh = list.size
176
+ if lh < act_height
177
+ $log.debug "DDD inside one window" if $log.debug?
178
+ list.each_with_index { |e, i|
179
+ text = e
180
+ case e
181
+ when Array
182
+ text = e.first + " ..."
183
+ end
184
+ if indexing == :number
185
+ text = "%d. %s" % [i+1, text]
186
+ elsif indexing == :letter
187
+ text = "%s. %s" % [l_succ.succ!, text]
188
+ end
189
+ @window.printstring i+@row_offset, 1, text, $normalcolor
190
+ }
191
+ else
192
+ $log.debug "DDD inside two window" if $log.debug?
193
+ row = 0
194
+ h = act_height
195
+ cols = (lh*1.0 / h).ceil
196
+ cols = max_cols if cols > max_cols
197
+ adv = (@width/cols).to_i
198
+ colct = 0
199
+ col = 1
200
+ $log.debug "DDDcols #{cols}, adv #{adv} size: #{lh} h: #{act_height} w #{@width} " if $log.debug?
201
+ list.each_with_index { |e, i|
202
+ # check that row + @row_offset < @top + @height or whatever TODO
203
+ text = e
204
+ # signify that there's a deeper level
205
+ case e
206
+ when Array
207
+ text = e.first + "..."
208
+ end
209
+ if indexing == :number
210
+ text = "%d. %s" % [i+1, text]
211
+ elsif indexing == :letter
212
+ text = "%s. %s" % [l_succ.succ!, text]
213
+ end
214
+ @window.printstring row+@row_offset, col, text, $normalcolor
215
+ colct += 1
216
+ if colct == cols
217
+ col = 1
218
+ row += 1
219
+ colct = 0
220
+ else
221
+ col += adv
222
+ end
223
+ }
224
+ end
225
+ Ncurses::Panel.update_panels();
226
+ Ncurses.doupdate();
227
+ @window.wrefresh
228
+ end
229
+ # refresh whatevers painted onto the window
230
+ def refresh
231
+ Ncurses::Panel.update_panels();
232
+ Ncurses.doupdate();
233
+ @window.wrefresh
234
+ end
235
+ # clears the window, leaving the title line as is, from row 1 onwards
236
+ def clear
237
+ @window.wmove 1,1
238
+ @window.wclrtobot
239
+ @window.box 0,0 if @box == :border
240
+ # lower line of border will get erased currently since we are writing to
241
+ # last line FIXME
242
+ end
243
+ def display_interactive text, config={}
244
+ if @to
245
+ @to.content text
246
+ else
247
+ config[:box] = @box
248
+ @to = ListObject.new self, text, config
249
+ end
250
+ yield @to if block_given?
251
+ @to.display_interactive
252
+ @to
253
+ end
254
+ # non interactive list display - EACH CALL IS CREATING A LIST OBJECT
255
+ def udisplay_list text, config={}
256
+ if @to
257
+ @to.content text
258
+ else
259
+ config[:box] = @box
260
+ @to = ListObject.new self, text, config
261
+ end
262
+ #@to ||= ListObject.new self, text, config
263
+ yield @to if block_given?
264
+ @to.display_content
265
+ @to
266
+ end
267
+ # displays a list
268
+ class ListObject
269
+ attr_reader :cw
270
+ attr_reader :list
271
+ attr_reader :current_index
272
+ attr_accessor :focussed_attrib
273
+ attr_accessor :focussed_symbol
274
+ def initialize cw, _list, config={}
275
+ @cw = cw
276
+ layout = @cw.layout
277
+ @window = @cw.window
278
+ @height = layout[:height]
279
+ @width = layout[:width]
280
+ content(_list)
281
+ @height_adjust = config.fetch(:box, true) == :border ? 3 : 2
282
+ @selected_index = nil
283
+ @current_index = 0
284
+ @row_offset = 1
285
+ @toprow = 0
286
+ $multiplier = 0 # till we can do something
287
+
288
+ @focussed_symbol = ''
289
+ @row_selected_symbol = ''
290
+ #@show_selector = true
291
+ if @show_selector
292
+ @row_selected_symbol ||= '*'
293
+ @row_unselected_symbol ||= ' '
294
+ @left_margin ||= @row_selected_symbol.length
295
+ end
296
+ #@show_selector = true
297
+ #@row_selected_symbol = '*'
298
+ #@row_unselected_symbol = ' '
299
+ end
300
+ def content txt, config={}
301
+ @current_index = 0 # sometimes it gets left at a higher value than there are rows to show
302
+ case txt
303
+ when String
304
+ txt = wrap_text(txt, @width-2).split("\n")
305
+ when Array
306
+ # okay
307
+ end
308
+ @list = txt
309
+ end
310
+ # maybe we should just use a textview or label rather than try to
311
+ # do it all voer again !
312
+ def display_interactive
313
+ display_content
314
+ while !@stop
315
+ # FIXME only clear and redisplay if change has happened (repaint_require)
316
+ handle_keys { |ch| @cw.clear; display_content }
317
+ end
318
+ return @list[@current_index]
319
+ end
320
+ def is_row_selected row
321
+ @selected_index == row
322
+ end
323
+
324
+ def scrollatrow
325
+ @height - 3
326
+ end
327
+ def row_count
328
+ @list.size
329
+ end
330
+ def rowcol
331
+ return @row_offset, @col_offset
332
+ end
333
+ def display_content #:nodoc:
334
+
335
+ @graphic = @window
336
+ @start ||= 0
337
+ @toprow ||= 0
338
+ @left_margin ||= @row_selected_symbol.length + @focussed_symbol.length
339
+
340
+ #print_borders unless @suppress_borders # do this once only, unless everything changes
341
+ #maxlen = @maxlen ||= @width-2
342
+ tm = @list
343
+ rc = tm.size
344
+ @col_offset = 1
345
+ #@longest_line = @width
346
+ if rc > 0 # just added in case no data passed
347
+ #tr = @start #@toprow
348
+ tr = @toprow
349
+ acolor = get_color $datacolor
350
+ #h = @height - 3 #2
351
+ h = @height - @height_adjust
352
+ r,c = @row_offset, @col_offset
353
+ 0.upto(h) do |hh|
354
+ crow = tr+hh
355
+ if crow < rc
356
+ focussed = @current_index == crow # row focussed ?
357
+ selected = is_row_selected crow
358
+ content = tm[crow] # 2009-01-17 18:37 chomp giving error in some cases says frozen
359
+ # by now it has to be a String
360
+ ## set the selector symbol if requested
361
+ selection_symbol = ''
362
+ if @show_selector
363
+ if selected
364
+ selection_symbol = @row_selected_symbol
365
+ else
366
+ selection_symbol = @row_unselected_symbol
367
+ end
368
+ @graphic.printstring r+hh, c, selection_symbol, acolor,@attr
369
+ end
370
+ #renderer = get_default_cell_renderer_for_class content.class.to_s
371
+ if focussed
372
+ if @focussed_symbol
373
+ @graphic.printstring r+hh, c, @focussed_symbol, acolor,@attr
374
+ end
375
+ @graphic.printstring r+hh, c+@left_margin, content, acolor, @focussed_attrib || 'reverse'
376
+ else
377
+ @graphic.printstring r+hh, c+@left_margin, content, acolor,@attr
378
+ end
379
+ #renderer.repaint @graphic, r+hh, c+@left_margin, crow, content, focussed, selected
380
+ else
381
+ # clear rows
382
+ @graphic.printstring r+hh, c, " " * (@width-2), acolor,@attr
383
+ end
384
+ end
385
+ end # rc == 0
386
+ set_form_row
387
+ end
388
+ # listobject
389
+ def press ch # list TODO copy from rbasiclist
390
+ ch = ch.getbyte(0) if ch.class==String ## 1.9
391
+ $log.debug " XXX press #{ch} " if $log.debug?
392
+ case ch
393
+ when -1
394
+ return
395
+ when KEY_F1, 27, ?\C-q.getbyte(0)
396
+ @stop = true
397
+ return
398
+ when KEY_ENTER, 10, 13
399
+ #$log.debug "popup ENTER : #{@selected_index} "
400
+ #$log.debug "popup ENTER : #{field.name}" if !field.nil?
401
+ @stop = true
402
+ return
403
+ when 32, ?\C-d.getbyte(0)
404
+ scroll_forward
405
+ #@start += @height-1
406
+ #bounds_check
407
+ when KEY_UP, ?k.getbyte(0)
408
+ previous_row
409
+ #@start -= 1
410
+ #@current_index -= 1
411
+ #@current_index = 0 if @current_index < 0
412
+ #@start = 0 if @start < 0
413
+ when KEY_DOWN, ?j.getbyte(0)
414
+ next_row
415
+ #@start += 1
416
+ #@current_index += 1
417
+ #bounds_check
418
+ when ?\C-b.getbyte(0)
419
+ scroll_backward
420
+ #@start -= @height-1
421
+ #@start = 0 if @start < 0
422
+ when 0, ?g.getbyte(0)
423
+ goto_top
424
+ when ?G.getbyte(0)
425
+ goto_bottom
426
+ end
427
+ #@form.repaint
428
+ Ncurses::Panel.update_panels();
429
+ Ncurses.doupdate();
430
+ @window.wrefresh
431
+ end
432
+
433
+ def previous_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
434
+ #return :UNHANDLED if @current_index == 0 # EVIL
435
+ return false if @current_index == 0
436
+ @oldrow = @current_index
437
+ num.times {
438
+ @current_index -= 1 if @current_index > 0
439
+ }
440
+ bounds_check
441
+ $multiplier = 0
442
+ end
443
+ alias :up :previous_row
444
+ def next_row num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
445
+ rc = row_count
446
+ return false if @current_index == rc-1
447
+ @oldrow = @current_index
448
+ @current_index += 1*num if @current_index < rc
449
+ bounds_check
450
+ $multiplier = 0
451
+ end
452
+ alias :down :next_row
453
+ def goto_bottom
454
+ @oldrow = @current_index
455
+ rc = row_count
456
+ @current_index = rc -1
457
+ bounds_check
458
+ end
459
+ alias :goto_end :goto_bottom
460
+ def goto_top
461
+ @oldrow = @current_index
462
+ @current_index = 0
463
+ bounds_check
464
+ end
465
+ alias :goto_start :goto_top
466
+ def scroll_backward
467
+ @oldrow = @current_index
468
+ h = scrollatrow()
469
+ m = $multiplier == 0? 1 : $multiplier
470
+ @current_index -= h * m
471
+ bounds_check
472
+ $multiplier = 0
473
+ end
474
+ def scroll_forward
475
+ @oldrow = @current_index
476
+ h = scrollatrow()
477
+ rc = row_count
478
+ m = $multiplier == 0? 1 : $multiplier
479
+ # more rows than box
480
+ if h * m < rc
481
+ @toprow += h+1 #if @current_index+h < rc
482
+ @current_index = @toprow
483
+ else
484
+ # fewer rows than box
485
+ @current_index = rc -1
486
+ end
487
+ #@current_index += h+1 #if @current_index+h < rc
488
+ bounds_check
489
+ end
490
+
491
+ ##
492
+ # please set oldrow before calling this. Store current_index as oldrow before changing. NOTE
493
+ def bounds_check
494
+ h = scrollatrow()
495
+ rc = row_count
496
+
497
+ @current_index = 0 if @current_index < 0 # not lt 0
498
+ @current_index = rc-1 if @current_index >= rc && rc>0 # not gt rowcount
499
+ @toprow = rc-h-1 if rc > h && @toprow > rc - h - 1 # toprow shows full page if possible
500
+ # curr has gone below table, move toprow forward
501
+ if @current_index - @toprow > h
502
+ @toprow = @current_index - h
503
+ elsif @current_index < @toprow
504
+ # curr has gone above table, move toprow up
505
+ @toprow = @current_index
506
+ end
507
+ set_form_row
508
+
509
+ end
510
+
511
+ def set_form_row
512
+ r,c = rowcol
513
+
514
+
515
+ # when the toprow is set externally then cursor can be mispositioned since
516
+ # bounds_check has not been called
517
+ if @current_index < @toprow
518
+ # cursor is outside table
519
+ @current_index = @toprow # ??? only if toprow 2010-10-19 12:56
520
+ end
521
+
522
+ row = r + (@current_index-@toprow)
523
+ # row should not be < r or greater than r+height TODO FIXME
524
+
525
+ #setrowcol row, nil
526
+ @window.wmove row, c
527
+ end
528
+ def OLDbounds_check
529
+ @start = 0 if @start < 0
530
+ row_offset = 1
531
+ last = (@list.length)-(@height-row_offset-1)
532
+ if @start > last
533
+ @start = last
534
+ end
535
+ end # bounds_check
536
+ def handle_keys
537
+ begin
538
+ while((ch = @window.getchar()) != 999 )
539
+ case ch
540
+ when -1
541
+ next
542
+ else
543
+ press ch
544
+ break if @stop
545
+ yield ch if block_given?
546
+ end
547
+ end
548
+ ensure
549
+ @cw.destroy
550
+ end
551
+ return @current_index
552
+ end
553
+ end # class ListObject
554
+ end # class CommandWindow
555
+ end # module