rbcurse-core 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ **2011-12-13**
2
+ ## 0.0.2 rbcurse-core
3
+ Mostly refactoring of multi-row components
4
+
5
+ ## 0.0.1 rbcurse-core
6
+ Added help system, and printing of key bindings
7
+
1
8
  **2011-12-05**
2
9
  ## 0.0.0 rbcurse-core
3
10
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -86,7 +86,7 @@ def view_sql stmt
86
86
  end
87
87
 
88
88
  App.new do
89
- header = app_header "rbcurse #{Rbcurse::VERSION}", :text_center => "Database Demo", :text_right =>"enabled"
89
+ #header = app_header "rbcurse #{Rbcurse::VERSION}", :text_center => "Database Demo", :text_right =>"enabled"
90
90
  form = @form
91
91
  mylabel = "a field"
92
92
  $catch_alt_digits = true # use M-1..9 in textarea
@@ -126,8 +126,14 @@ App.new do
126
126
  : - Command mode
127
127
  Alt-z - Commands in TextArea
128
128
 
129
- DB BROWSER KEYS
129
+ Sql Entry Area
130
+ C-x e Edit in $EDITOR or vi
131
+ M-? To see other key-bindings
132
+ F4 Execute SQL (there should be only one sql).
130
133
 
134
+
135
+ Result Set (this is not present in this demo any longer - moved
136
+ to rbcurse-extras)
131
137
  , Prev row (mnemonic <)
132
138
  . Next row (mnemonic >)
133
139
  < First row
@@ -1,3 +1,6 @@
1
+ # WARNING : IF THIS PROGRAM HANGS check the ri command
2
+ # Maybe your version of ri has different options and is going interactive.
3
+ # ruby 1.9.3's ri requires a -l option or else if becomes interactive.
1
4
  # this program tests out a listbox
2
5
  # This is written in the old style where we start and end ncurses and initiate a
3
6
  # getch loop. It gives more control.
@@ -90,7 +93,7 @@ if $0 == __FILE__
90
93
  h = FFI::NCurses.LINES-3
91
94
  file = "./data/ports.txt"
92
95
  #mylist = File.open(file,'r').readlines
93
- mylist = `ri -f bs`.split("\n")
96
+ mylist = `ri -l `.split("\n")
94
97
  w = 25
95
98
  #0.upto(100) { |v| mylist << "#{v} scrollable data" }
96
99
  #
@@ -5,15 +5,18 @@ module BorderTitle
5
5
  dsl_accessor :border_attrib, :border_color
6
6
  dsl_accessor :title #set this on top
7
7
  dsl_accessor :title_attrib #bold, reverse, normal
8
- dsl_accessor :border_attrib, :border_color #
9
8
 
10
9
  def bordertitle_init
10
+ @_bordertitle_init_called = true
11
11
  @row_offset = @col_offset = 0 if @suppress_borders
12
- @internal_width = 1 if @suppress_borders
12
+ @internal_width = 1 if @suppress_borders # the other programs have zero not 1 NOTE
13
13
  end
14
14
  # why the dash does it reduce height by one.
15
15
  def print_borders
16
+ bordertitle_init unless @_bordertitle_init_called
16
17
  raise ArgumentError, "Graphic not set" unless @graphic
18
+ raise "#{self} needs width" unless @width
19
+ raise "#{self} needs height" unless @height
17
20
  width = @width
18
21
  height = @height-1
19
22
  window = @graphic
@@ -26,6 +29,7 @@ module BorderTitle
26
29
  print_title
27
30
  end
28
31
  def print_title
32
+ bordertitle_init unless @_bordertitle_init_called
29
33
  return unless @title
30
34
  raise "#{self} needs width" unless @width
31
35
  @color_pair ||= get_color($datacolor) # should we not use this ??? XXX
@@ -39,3 +43,4 @@ module BorderTitle
39
43
  end
40
44
 
41
45
  end
46
+ include BorderTitle
@@ -148,7 +148,7 @@ module Chunks
148
148
  when String
149
149
 
150
150
  ## create the chunk
151
- $log.debug "XXX: CHUNK using on #{p} : #{@color_pair} , #{@attrib} "
151
+ #$log.debug "XXX: CHUNK using on #{p} : #{@color_pair} , #{@attrib} " # 2011-12-10 12:38:51
152
152
 
153
153
  #chunk = [color_pair, p, attrib]
154
154
  chunk = Chunk.new @color_pair, p, @attrib
@@ -0,0 +1,70 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: listbindings.rb
3
+ # Description: bindings for multi-row widgets such as listbox, table, textview
4
+ # Author: rkumar http://github.com/rkumar/rbcurse/
5
+ # Date: 2011-12-11 - 12:58
6
+ # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
7
+ # Last update: 2011-12-11 - 12:59
8
+ # ----------------------------------------------------------------------------- #
9
+ #
10
+ module RubyCurses
11
+ #
12
+ # bindings for multi-row widgets such as listbox, table, textview
13
+ #
14
+ module ListBindings
15
+ extend self
16
+ def bindings
17
+ $log.debug "XXX: INSIDE LISTBINDING FOR #{self.class} "
18
+ bind_key(Ncurses::KEY_LEFT, 'cursor backward'){ cursor_backward } if respond_to? :cursor_backward
19
+ bind_key(Ncurses::KEY_RIGHT, 'cursor_forward'){ cursor_forward } if respond_to? :cursor_forward
20
+ bind_key(Ncurses::KEY_UP, 'previous row'){ ret = up; get_window.ungetch(KEY_BTAB) if ret == :NO_PREVIOUS_ROW }
21
+ # the next was irritating if user wanted to add a row ! 2011-10-10
22
+ #bind_key(Ncurses::KEY_DOWN){ ret = down ; get_window.ungetch(KEY_TAB) if ret == :NO_NEXT_ROW }
23
+ bind_key(Ncurses::KEY_DOWN, 'next row'){ ret = down ; }
24
+
25
+ # this allows us to set on a component basis, or global basis
26
+ # Motivation was mainly for textarea which needs emacs keys
27
+ kmap = @key_map || $key_map || :both
28
+ if kmap == :emacs || kmap == :both
29
+ bind_key(?\C-v, 'scroll forward'){ scroll_forward }
30
+ # clashes with M-v for toggle one key selection, i guess you can set it as you like
31
+ bind_key(?\M-v, 'scroll backward'){ scroll_backward }
32
+ bind_key(?\C-s, 'ask search'){ ask_search() }
33
+ bind_key(?\C-n, 'next row'){ next_row() }
34
+ bind_key(?\C-p, 'previous row'){ previous_row() }
35
+ bind_key(?\M->, 'goto bottom'){ goto_bottom() }
36
+ bind_key(?\M-<, 'goto top'){ goto_top() }
37
+ bind_key([?\C-x, ?>], :scroll_right)
38
+ bind_key([?\C-x, ?<], :scroll_left)
39
+ end
40
+ if kmap == :vim || kmap == :both
41
+ # some of these will not have effect in textarea such as j k, gg and G, search
42
+ bind_key(?j, 'next row'){ next_row() }
43
+ bind_key(?k, 'previous row'){ previous_row() }
44
+ bind_key(?\C-d, 'scroll forward'){ scroll_forward() }
45
+ bind_key(?\C-b, 'scroll backward'){ scroll_backward() }
46
+ bind_key([?g,?g], 'goto start'){ goto_start } # mapping double keys like vim
47
+ bind_key(?G, 'goto end'){ goto_bottom() }
48
+ bind_key([?',?'], 'goto last position'){ goto_last_position } # vim , goto last row position (not column)
49
+
50
+ bind_key(?/, :ask_search)
51
+ bind_key(?n, :find_more)
52
+ bind_key(?h, 'cursor backward'){ cursor_backward } if respond_to? :cursor_backward
53
+ bind_key(?l, 'cursor forward'){ cursor_forward } if respond_to? :cursor_forward
54
+ end
55
+ bind_key(?\C-a, 'start of line'){ cursor_bol } if respond_to? :cursor_bol
56
+ bind_key(?\C-e, 'end of line'){ cursor_eol } if respond_to? :cursor_eol
57
+ bind_key(?\M-l, :scroll_right)
58
+ bind_key(?\M-h, :scroll_left)
59
+
60
+ # save as and edit_external are only in textview and textarea
61
+ # save_as can be given to list's also and tables
62
+ # put them someplace so the code can be shared.
63
+ bind_key([?\C-x, ?\C-s], :saveas)
64
+ bind_key([?\C-x, ?e], :edit_external)
65
+
66
+ # textview also uses space for scroll_forward
67
+ end # def
68
+ end
69
+ end
70
+ include RubyCurses::ListBindings
@@ -84,6 +84,7 @@ module ListScrollable
84
84
  rc = row_count
85
85
  @old_toprow = @toprow
86
86
 
87
+ @_header_adjustment ||= 0
87
88
  @current_index = 0 if @current_index < 0 # not lt 0
88
89
  @current_index = rc-1 if @current_index >= rc && rc>0 # not gt rowcount
89
90
  @toprow = rc-h-1 if rc > h && @toprow > rc - h - 1 # toprow shows full page if possible
@@ -92,7 +93,11 @@ module ListScrollable
92
93
  @toprow = @current_index - h
93
94
  elsif @current_index < @toprow
94
95
  # curr has gone above table, move toprow up
95
- @toprow = @current_index
96
+ # sometimes current row gets hidden below header line
97
+ @toprow = @current_index - (@_header_adjustment ||0)
98
+ # prev line can make top row -1, however, if we are going back, lets
99
+ # put it at start of page, so first or second row is not hidden
100
+ @toprow = 0 if @toprow < h
96
101
  end
97
102
 
98
103
  @row_changed = false
@@ -248,7 +253,8 @@ module ListScrollable
248
253
  # 2009-01-17 13:25
249
254
  def set_focus_on arow
250
255
  @oldrow = @current_index
251
- arow += @_header_adjustment if @_header_adjustment # for tables 2011-11-30
256
+ # the next line fixed cursor positioning, but when wraparound then it messed up
257
+ # matching line would get hidden
252
258
  @current_index = arow
253
259
  bounds_check if @oldrow != @current_index
254
260
  end
@@ -283,18 +289,10 @@ module ListScrollable
283
289
  @search_direction_prev = mb.widget("0").value
284
290
  @search_case = mb.widget("1").value
285
291
  @search_wrap = mb.widget("2").value
286
- #
287
- #-----
288
- #options = ["Search backwards", "case insensitive", "Wrap around"]
289
- #sel,regex,hash = get_string_with_options("Enter regex to search", 20, @last_regex||"", "checkboxes"=>options, "checkbox_defaults"=>[@search_direction_prev,@search_case,@search_wrap])
290
- #return if sel != 0
291
- #@search_direction_prev = hash[options[0]]
292
- #@search_case = hash[options[1]]
293
- #@search_wrap = hash[options[2]]
294
292
  if @search_direction_prev == true
295
- ix = _find_prev regex, @current_index
293
+ ix = _find_prev regex, @current_index - (@_header_adjustment || 0), true
296
294
  else
297
- ix = _find_next regex, @current_index
295
+ ix = _find_next regex, @current_index - (@_header_adjustment || 0), true
298
296
  end
299
297
  if ix.nil?
300
298
  alert("No matching data for: #{regex}")
@@ -314,13 +312,16 @@ module ListScrollable
314
312
  end
315
313
  # find forwards
316
314
  # Using this to start a search or continue search
317
- def _find_next regex=@last_regex, start = @search_found_ix
315
+ def _find_next regex=@last_regex, start = @search_found_ix, first_time = false
318
316
  #raise "No previous search" if regex.nil?
319
317
  warn "No previous search" and return if regex.nil?
320
318
  #$log.debug " _find_next #{@search_found_ix} : #{@current_index}"
319
+ extra = 1 # first time search on current line, next time skip current line or else we get stuck.
320
+ extra = 0 if first_time
321
+ start ||= 0
321
322
  fend = @list.size-1
322
323
  if start != fend
323
- start += 1 unless start == fend
324
+ start += extra unless start == fend # used to be +=1 so we don't get stuck in same row
324
325
  @last_regex = regex
325
326
  @search_start_ix = start
326
327
  regex = Regexp.new(regex, Regexp::IGNORECASE) if @search_case
@@ -334,6 +335,7 @@ module ListScrollable
334
335
  if !m.nil?
335
336
  @find_offset = m.offset(0)[0]
336
337
  @find_offset1 = m.offset(0)[1]
338
+ ix += (@_header_adjustment || 0)
337
339
  @search_found_ix = ix
338
340
  return ix
339
341
  end
@@ -348,6 +350,7 @@ module ListScrollable
348
350
  if !m.nil?
349
351
  @find_offset = m.offset(0)[0]
350
352
  @find_offset1 = m.offset(0)[1]
353
+ ix += (@_header_adjustment || 0)
351
354
  @search_found_ix = ix
352
355
  return ix
353
356
  end
@@ -403,6 +406,7 @@ module ListScrollable
403
406
  if !m.nil?
404
407
  @find_offset = m.offset(0)[0]
405
408
  @find_offset1 = m.offset(0)[1]
409
+ ix += (@_header_adjustment || 0)
406
410
  @search_found_ix = ix
407
411
  return ix
408
412
  end
@@ -416,7 +420,8 @@ module ListScrollable
416
420
  m=row.match(regex)
417
421
  if !m.nil?
418
422
  @find_offset = m.offset(0)[0]
419
- @find_offset1 = m.offset(0)[1]
423
+ @find_offset1 = m.offset(0)[1]
424
+ ix += (@_header_adjustment || 0)
420
425
  @search_found_ix = ix
421
426
  return ix
422
427
  end
@@ -206,7 +206,7 @@ module RubyCurses
206
206
  def list_bindings
207
207
  # what about users wanting 32 and ENTER to also go to next row automatically
208
208
  # should make that optional, TODO
209
- bind_key(32, 'toggle selection') { toggle_row_selection }
209
+ bind_key($row_selector || 32, 'toggle selection') { toggle_row_selection }
210
210
  bind_key(0, 'range select') { add_to_selection }
211
211
  bind_key(?+, :ask_select) # --> calls select_values
212
212
  bind_key(?-, :ask_unselect) # please implement FIXME TODO
@@ -69,6 +69,8 @@ module VER
69
69
  $error_message_row ||= Ncurses.LINES-1
70
70
  $error_message_col ||= 1 # ask (bottomline) uses 0 as default so you can have mismatch. XXX
71
71
  $status_message ||= RubyCurses::Variable.new # in case not an App
72
+
73
+ $key_map ||= :vim
72
74
  init_vars
73
75
 
74
76
 
@@ -288,7 +290,7 @@ module VER
288
290
  attrib ||= defattr
289
291
 
290
292
  cc, bg = ColorMap.get_colors_for_pair color
291
- $log.debug "XXX: CHUNK window #{text}, cp #{color} , attrib #{attrib}. #{cc}, #{bg} "
293
+ #$log.debug "XXX: CHUNK window #{text}, cp #{color} , attrib #{attrib}. #{cc}, #{bg} "
292
294
  color_set(color,nil) if color
293
295
  wattron(attrib) if attrib
294
296
  print(text)
@@ -607,7 +609,7 @@ module VER
607
609
  if content.is_a? String
608
610
  printstring(r,c,content, color, att)
609
611
  elsif content.is_a? Chunks::ChunkLine
610
- $log.debug "XXX: using chunkline"
612
+ #$log.debug "XXX: using chunkline" # 2011-12-10 12:40:13
611
613
  wmove r, c
612
614
  a = get_attrib att
613
615
  show_colored_chunks content, color, a
@@ -4,7 +4,8 @@
4
4
  # NOTE: on some terminal such as xterm-256color spaces do not print
5
5
  # so you will see black or empty spaces between text.
6
6
  # This does not happen on screen and xterm-color.
7
- # Author: rkumar http://github.com/rkumar/rbcurse/
7
+ # I've done some roundabout stuff to circumvent that.
8
+ # Author: rkumar http://github.com/rkumar/rbcurse-core/
8
9
  # Date:
9
10
  # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
11
  # Last update: 2011-11-16 - 00:07
@@ -16,6 +16,7 @@ CHANGES
16
16
  =end
17
17
  require 'rbcurse'
18
18
  require 'rbcurse/core/include/listcellrenderer'
19
+ require 'rbcurse/core/include/bordertitle'
19
20
  #require 'rbcurse/extras/include/listkeys'
20
21
  require 'forwardable'
21
22
 
@@ -42,12 +43,12 @@ module RubyCurses
42
43
  include NewListSelectable # added 2011-10-8
43
44
  extend Forwardable
44
45
  #dsl_accessor :height # << widget already has this
45
- dsl_accessor :title
46
- dsl_property :title_attrib # bold, reverse, normal
46
+ #dsl_accessor :title
47
+ #dsl_property :title_attrib # bold, reverse, normal
47
48
  # dsl_accessor :list # the array of data to be sent by user
48
49
  attr_reader :toprow
49
50
  #dsl_accessor :default_values # array of default values
50
- dsl_accessor :is_popup # if it is in a popup and single select, selection closes
51
+ #dsl_accessor :is_popup # if it is in a popup and single select, selection closes
51
52
  attr_accessor :current_index
52
53
  dsl_accessor :selection_mode
53
54
  dsl_accessor :selected_color, :selected_bgcolor, :selected_attr
@@ -60,13 +61,12 @@ module RubyCurses
60
61
  # please set these in he constructor block. Settin them later will have no effect
61
62
  # since i would have bound them to actions
62
63
  attr_accessor :one_key_selection # will pressing a single key select or not
63
- dsl_accessor :border_attrib, :border_color #
64
64
  # set to true if data could have newlines, tabs, and other stuff, def true
65
65
  dsl_accessor :sanitization_required
66
66
  # set to true if cell-renderer data can exceed width of listbox, default true
67
67
  # if you are absolutely sure that data is constant width, set to false.
68
68
  dsl_accessor :truncation_required
69
- dsl_accessor :suppress_borders #to_print_borders
69
+ #dsl_accessor :suppress_borders #to_print_borders
70
70
  dsl_accessor :justify # will be picked up by renderer
71
71
  # index of selected row
72
72
  attr_accessor :selected_index
@@ -107,7 +107,8 @@ module RubyCurses
107
107
 
108
108
  init_vars
109
109
  @internal_width = 2
110
- @internal_width = 0 if @suppress_borders
110
+ #@internal_width = 0 if @suppress_borders # NOTE it is 1 in bordertitle
111
+ bordertitle_init
111
112
 
112
113
  if @list && !@selected_index.nil? # XXX
113
114
  set_focus_on @selected_index # the new version
@@ -132,21 +133,12 @@ module RubyCurses
132
133
  end
133
134
  def map_keys
134
135
  return if @keys_mapped
136
+ require 'rbcurse/core/include/listbindings'
137
+ bindings()
135
138
  bind_key(?f, 'next row starting with char'){ ask_selection_for_char() }
136
- bind_key(?\M-v, 'toggle one_key_selection'){ @one_key_selection = false }
137
- bind_key(?j, 'next row'){ next_row() }
138
- bind_key(?k, 'previous row'){ previous_row() }
139
- bind_key(?\C-d, 'scroll forward'){ scroll_forward() }
140
- bind_key(?\C-b, 'scroll backward'){ scroll_backward() }
141
- bind_key(?G, 'goto end'){ goto_bottom() }
142
- bind_key([?g,?g], 'goto top'){ goto_top() }
143
- bind_key([?',?'], 'goto last position'){ goto_last_position() }
144
- bind_key(?/, 'ask search'){ ask_search() }
145
- bind_key(?n, 'find next'){ find_more() }
146
- bind_key(32){ toggle_row_selection() }
147
- bind_key(10, 'fire action event'){ fire_action_event }
139
+ bind_key(?\M-v, 'toggle one_key_selection'){ @one_key_selection = !@one_key_selection }
148
140
  bind_key(13, 'fire action event'){ fire_action_event }
149
- list_bindings
141
+ list_bindings # listselectable
150
142
  @keys_mapped = true
151
143
 
152
144
  end
@@ -242,24 +234,6 @@ module RubyCurses
242
234
  alias :current_row :current_value
243
235
  alias :text :current_value # thanks to shoes, not sure how this will impact since widget has text.
244
236
 
245
- def print_borders #:nodoc:
246
- width = @width
247
- height = @height-1 # 2010-01-04 15:30 BUFFERED HEIGHT
248
- window = @graphic # 2010-01-04 12:37 BUFFERED
249
- startcol = @col
250
- startrow = @row
251
- #@color_pair = get_color($datacolor)
252
- bordercolor = @border_color || $datacolor
253
- borderatt = @border_attrib || Ncurses::A_NORMAL
254
-
255
- window.print_border startrow, startcol, height, width, bordercolor, borderatt
256
- print_title
257
- end
258
- def print_title #:nodoc:
259
- @color_pair ||= get_color($datacolor)
260
- # TODO check title.length and truncate if exceeds width
261
- @graphic.printstring( @row, @col+(@width-@title.length)/2, @title, @color_pair, @title_attrib) unless @title.nil?
262
- end
263
237
  ### START FOR scrollable ###
264
238
  def get_content
265
239
  @list
@@ -278,59 +252,41 @@ module RubyCurses
278
252
  #map_keys unless @keys_mapped
279
253
  @current_index ||= 0
280
254
  @toprow ||= 0
281
- h = scrollatrow()
282
- rc = row_count
283
- $log.debug " basiclistbox got ch #{ch}"
255
+ #h = scrollatrow()
256
+ #rc = row_count
257
+ #$log.debug " basiclistbox got ch #{ch}"
284
258
  #$log.debug " when kps #{@KEY_PREV_SELECTION} "
285
259
  case ch
286
- when KEY_UP # show previous value
287
- return previous_row
288
- when KEY_DOWN # show previous value
289
- return next_row
290
- when 32
291
- return if is_popup and @selection_mode == 'single' # not allowing select this way since there will be a difference
292
- toggle_row_selection @current_index #, @current_index
293
- @repaint_required = true
294
- when 0 # c-space
295
- add_to_selection
296
- when @KEY_NEXT_SELECTION # ?'
297
- $log.debug "insdie next selection"
298
- @oldrow = @current_index
299
- do_next_selection
300
- bounds_check
301
- when @KEY_PREV_SELECTION # ?"
302
- @oldrow = @current_index
303
- $log.debug "insdie prev selection"
304
- do_prev_selection
305
- bounds_check
306
- when @KEY_CLEAR_SELECTION
307
- clear_selection
308
- @repaint_required = true
260
+ #when 32
261
+ #return if is_popup and @selection_mode == 'single' # not allowing select this way since there will be a difference
262
+ #toggle_row_selection @current_index #, @current_index
263
+ #@repaint_required = true
264
+ #when 0 # c-space
265
+ #add_to_selection
266
+ #when @KEY_NEXT_SELECTION # ?'
267
+ #$log.debug "insdie next selection"
268
+ #@oldrow = @current_index
269
+ #do_next_selection
270
+ #bounds_check
271
+ #when @KEY_PREV_SELECTION # ?"
272
+ #@oldrow = @current_index
273
+ #$log.debug "insdie prev selection"
274
+ #do_prev_selection
275
+ #bounds_check
276
+ #when @KEY_CLEAR_SELECTION
277
+ #clear_selection
278
+ #@repaint_required = true
309
279
  when 27, ?\C-c.getbyte(0)
310
- #editing_canceled @current_index if @cell_editing_allowed
311
- #cancel_block # block NW XXX don't think its required. 2011-09-9 FFI
312
280
  $multiplier = 0
313
- when @KEY_ASK_FIND_FORWARD
314
- # ask_search_forward
315
- when @KEY_ASK_FIND_BACKWARD
316
- # ask_search_backward
317
- when @KEY_FIND_NEXT
318
- # find_next
319
- when @KEY_FIND_PREV
320
- # find_prev
321
- when @KEY_ASK_FIND
322
- ask_search
323
- when @KEY_FIND_MORE
324
- find_more
325
281
  when @KEY_BLOCK_SELECTOR
326
282
  mark_block #selection
327
283
  #when ?\C-u.getbyte(0)
328
284
  # multiplier. Series is 4 16 64
329
285
  # TESTING @multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
330
286
  # return 0
331
- when ?\C-c.getbyte(0)
332
- @multiplier = 0
333
- return 0
287
+ #when ?\C-c.getbyte(0)
288
+ #@multiplier = 0
289
+ #return 0
334
290
  else
335
291
  # this has to be fixed, if compo does not handle key it has to continue into next part FIXME
336
292
  ret = :UNHANDLED # changed on 2009-01-27 13:14 not going into unhandled, tab not released