Class: RubyCurses::TextArea

Inherits:
Widget
  • Object
show all
Includes:
ListEditable, ListScrollable
Defined in:
lib/rbcurse/rtextarea.rb

Overview

a multiline text editing widget TODO - giving data to user - adding newlines, and withog adding.

- respect newlines for incoming data
we need a set_text method, passing nil or blank clears
current way is not really good. remove_all sucks.
 TODO don't set maxlen if nil. compute it as a local in methods. Else splitpane will not
 work correctly.

Constant Summary

Constants included from Io

Io::ERROR_COLOR_PAIR, Io::FOOTER_COLOR_PAIR, Io::LINEONE, Io::MAIN_WINDOW_COLOR_PAIR

Instance Attribute Summary collapse

Attributes included from ListScrollable

#find_offset, #find_offset1, #search_found_ix, #show_caret

Attributes inherited from Widget

#col_offset, #cols_panned, #config, #curpos, #ext_col_offset, #ext_row_offset, #form, #id, #parent_component, #row_offset, #rows_panned, #should_create_buffer, #state

Instance Method Summary collapse

Methods included from ListEditable

#add_to_kill_ring, #append_next_kill, #append_row, #delete_at, #delete_curr_char, #delete_eol, #delete_forward, #delete_line, #delete_prev_char, #delete_word, #join_next_line, #kill_ring_save, #remove_all, #undo_handler, #yank, #yank_pop

Methods included from ListScrollable

#OLDscrollable_handle_key, #OLDset_focus_on, #_find_next, #_find_prev, #ask_search, #bounds_check, #find_more, #find_next, #find_prev, #focussed_index, #forward_char, #forward_word, #goto_bottom, #goto_last_position, #goto_top, #install_keys, #next_match, #next_row, #previous_row, #scroll_backward, #scroll_forward, #scroll_left, #scroll_right, #selected_item, #set_focus_on, #set_form_row, #set_selection_for_char, #show_caret_func

Methods inherited from Widget

#OLDbind_key, #buffer_to_screen, #buffer_to_window, #create_buffer, #destroy, #destroy_buffer, #focus, #get_buffer, #get_color, #get_preferred_size, #getvalue_for_paint, #height, #height=, #hide, #is_double_buffered?, #modified?, #move, #on_enter, #on_leave, #override_graphic, #printstring, #process_key, #remove, #repaint_all, #repaint_required, #safe_create_buffer, #set_buffer_modified, #set_buffering, #set_form, #set_form_row, #setformrowcol, #setrowcol, #show, #text_variable, #unbind_key, #width, #width=

Methods included from Io

#askchoice, #askyesno, #askyesnocancel, #clear_error, #clear_this, #get_string, #newaskyesno, #old_print_header, #old_print_top_right, #print_action, #print_error, #print_footer_help, #print_header, #print_headers, #print_help, #print_help_page, #print_in_middle, #print_key_labels, #print_key_labels_row, #print_screen_labels, #print_status, #print_this, #print_top_right, #rbgetstr

Methods included from Utils

#_process_key, #bind_key, #clean_string!, #get_color, #keycode_tos, #repeatm

Methods included from ConfigSetup

#cget, #config_setup, #configure, #variable_set

Methods included from EventHandler

#bind, #fire_handler, #fire_property_change

Methods included from DSL

#OLD_method_missing

Constructor Details

#initialize(form = nil, config = {}, &block) ⇒ TextArea

Returns a new instance of TextArea.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rbcurse/rtextarea.rb', line 53

def initialize form = nil, config={}, &block
  @focusable = true
  @editable = true
  @row = 0
  @col = 0
  @curpos = 0
  @list = []
  super
  @row_offset = @col_offset = 1 # for cursor display on first entry, so not positioned on border
  @orig_col = @col
  # this does result in a blank line if we insert after creating. That's required at 
  # present if we wish to only insert
  if @list.empty?
  #  @list << "\r"   # removed this on 2009-02-15 17:25 lets see how it goes
  end
 # @scrollatrow = @height-2
  @content_rows = @list.length
  #@win = @form.window
  @win = @graphic # 2009-12-26 14:54 BUFFERED  replace form.window with graphic
#  init_scrollable
  #print_borders
  # 2010-01-10 19:35 compute locally if not set
  #@maxlen ||= @width-2
  install_keys
  init_vars
end

Instance Attribute Details

#overwrite_modeObject

boolean: insert or overwrite, default false.



51
52
53
# File 'lib/rbcurse/rtextarea.rb', line 51

def overwrite_mode
  @overwrite_mode
end

#toprowObject (readonly)

Returns the value of attribute toprow.



46
47
48
# File 'lib/rbcurse/rtextarea.rb', line 46

def toprow
  @toprow
end

Instance Method Details

#<<(data) ⇒ Object

wraps line sent in if longer than _maxlen Typically a line is sent in. We wrap and put a hard return at end.



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/rbcurse/rtextarea.rb', line 136

def << data
  # if width if nil, either set it, or add this to a container that sets it before calling this method
  _maxlen = @maxlen || @width - 2
  if data.length > _maxlen
    #$log.debug "wrapped append for #{data}"
    data = wrap_text data
    #$log.debug "after wrap text for :#{data}"
    data = data.split("\n")
    # 2009-01-01 22:24 the \n was needed so we would put a space at time of writing.
    # we need a soft return so a space can be added when pushing down.
    # commented off 2008-12-28 21:59 
    #data.each {|line| @list << line+"\n"}
    data.each {|line| @list << line}
     @list[-1] << "\r" #XXXX
  else
    #$log.debug "normal append for #{data}"
    data << "\r" if data[-1,1] != "\r" #XXXX
    @list << data
  end
  set_modified  # added 2009-03-07 18:29 
  goto_end if @auto_scroll 
  self
end

#addcol(num) ⇒ Object

FIXME : these 2 only require the footer to be repainted not everything We should be able to manage that. We need a repaint_footer_required. Setting repaint_required really slows performance when one presses the right arrow key since a repaint is happenign repeatedly for each key.



447
448
449
450
451
452
# File 'lib/rbcurse/rtextarea.rb', line 447

def addcol num
#     @repaint_required = true # added 2010-01-15 23:59, so that footer is updated, sucks!
  @repaint_footer_required = true # 2010-01-23 22:41 
  my_win = @form || @parent_component.form # 2010-02-12 12:51 
  my_win.addcol num
end

#addrowcol(row, col) ⇒ Object



453
454
455
456
457
458
# File 'lib/rbcurse/rtextarea.rb', line 453

def addrowcol row,col
  #@repaint_required = true # added 2010-01-15 23:59 
  @repaint_footer_required = true # 2010-01-23 22:41 
  my_win = @form || @parent_component.form # 2010-02-12 12:51 
  my_win.addrowcol row, col
end

#ask_search_forwardObject



853
854
855
856
857
858
859
860
861
862
# File 'lib/rbcurse/rtextarea.rb', line 853

def ask_search_forward
    regex =  get_string("Enter regex to search", 20, @last_regex||"")
    ix = _find_next regex, @current_index
    if ix.nil?
      alert("No matching data for: #{regex}")
    else
      set_focus_on(ix)
      set_form_col @find_offset
    end
end

#at_eol?Boolean

added 2009-10-04 22:13 returns whether cursor is at end of line

Returns:

  • (Boolean)


431
432
433
434
435
436
# File 'lib/rbcurse/rtextarea.rb', line 431

def at_eol?
  if @curpos+1== @list[@current_index].length  
    return  true
  end
  return false
end

#at_last_line?Boolean

added 2009-10-04 22:13 returns whether at last line (required so that forward does not go to start)

Returns:

  • (Boolean)


439
440
441
442
# File 'lib/rbcurse/rtextarea.rb', line 439

def at_last_line?
  return true if @list.length == @current_index + 1
  return false
end

#buffer_lenObject



403
404
405
# File 'lib/rbcurse/rtextarea.rb', line 403

def buffer_len
  @list[@current_index].nil? ? 0 : @list[@current_index].chomp().length  
end

#current_lineObject



750
751
752
# File 'lib/rbcurse/rtextarea.rb', line 750

def current_line
  @list[@current_index]
end

#cursor_backwardObject

2009-10-04 23:01 taken care that you can’t go back at start of textarea it was going onto border



461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'lib/rbcurse/rtextarea.rb', line 461

def cursor_backward
    #$log.debug "back char cp ll and ci #{@list.length}, #{@current_index}"
    #$log.debug "back char cb #{@curpos}, #{@buffer.length}. wi: #{@width}"
    return if @curpos == 0 and @current_index == 0 # added 2009-10-04 23:02 
    repeatm { 
      if @curpos > 0
        @curpos -= 1
        addcol -1
      else # trying this out 2008-12-26 20:18 
        ret = up
        cursor_eol if ret != -1
      end
    }
end

#cursor_bolObject



768
769
770
# File 'lib/rbcurse/rtextarea.rb', line 768

def cursor_bol
  set_form_col 0
end

#cursor_bounds_checkObject



399
400
401
402
# File 'lib/rbcurse/rtextarea.rb', line 399

def cursor_bounds_check
  max = buffer_len()
  @curpos = max if @curpos > max # check 2008-12-27 00:02 
end

#cursor_eolObject



763
764
765
766
767
# File 'lib/rbcurse/rtextarea.rb', line 763

def cursor_eol
   _maxlen = @maxlen || @width - 2
  $log.error "ERROR !!! bufferlen gt _maxlen #{@buffer.length}, #{_maxlen}" if @buffer.length > _maxlen
  set_form_col current_line().chomp().length()-1
end

#cursor_forward(num = 1) ⇒ Object

FIXME : if cursor at end of last line then forward takes cursor to start of last line (same line), should stop there.



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
# File 'lib/rbcurse/rtextarea.rb', line 413

def cursor_forward num=1
  #$log.debug "next char cp #{@curpos}, #{@buffer.length}. wi: #{@width}"
  #$log.debug "next char cp ll and ci #{@list.length}, #{@current_index}"
  #if @curpos < @width and @curpos < maxlen-1 # else it will do out of box
  return if at_eol? and at_last_line?
  repeatm { 
  if @curpos < buffer_len()
    @curpos += 1
    addcol 1
  else # trying this out 2008-12-26 20:18 
    @curpos = 0
    down 1 # if not then multipler will trigger there too
  end
  cursor_bounds_check
  }
end

#do_current_row {|| ... } ⇒ Object

:yields current row

Yields:

  • ()


406
407
408
409
# File 'lib/rbcurse/rtextarea.rb', line 406

def do_current_row # :yields current row
  yield @list[@current_index]
  @buffer = @list[@current_index]
end

#do_relative_row(num) {|| ... } ⇒ Object

Yields:

  • ()


753
754
755
# File 'lib/rbcurse/rtextarea.rb', line 753

def do_relative_row num
  yield @list[@current_index+num] 
end

#get_contentObject

FOR scrollable ###



215
216
217
# File 'lib/rbcurse/rtextarea.rb', line 215

def get_content
  @list
end

#get_textObject

def to_s this was just annoying in debugs



772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
# File 'lib/rbcurse/rtextarea.rb', line 772

def get_text
  l = getvalue
  str = ""
  old = " "
  l.each_with_index do |line, i|
    tmp = line.gsub("\n","")
    tmp.gsub!("\r", "\n")
    if old[-1,1] !~ /\s/ and tmp[0,1] !~ /\s/
      str << " "
    end
    str << tmp
    old = tmp
  end
  str
end

#get_windowObject



218
219
220
# File 'lib/rbcurse/rtextarea.rb', line 218

def get_window
  @graphic
end

#getvalueObject



234
235
236
# File 'lib/rbcurse/rtextarea.rb', line 234

def getvalue
  @list
end

#handle_key(ch) ⇒ Object

textarea



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/rbcurse/rtextarea.rb', line 239

def handle_key ch
  @current_key = ch # I need some funcs to know what key they were mapped to
  @buffer = @list[@current_index]
  if @buffer.nil? and @list.length == 0
    ## 2009-10-04 22:39 
    # what this newline does is , if we use << to append, data is appended
    # to second line
    @list << "\n" # changed space to newline so wrapping puts a line.
    @current_index = 0 ; ## added 2009-10-04 21:47 
    @buffer = @list[@current_index]
  end
  ## 2009-10-04 20:48  i think the next line was resulting in a hang if buffer nil
  # in sqlc on pressing Clear.
  # if buffer is nil and user wants to enter something -- added UNHANDLED
  return :UNHANDLED if @buffer.nil?
  $log.debug "TA: before: curpos #{@curpos} blen: #{@buffer.length}"
  # on any line if the cursor is ahead of buffer length, ensure its on last position
  # what if the buffer is somehow gt maxlen ??
  if @curpos > @buffer.length
    addcol(@buffer.length-@curpos)+1
    @curpos = @buffer.length
  end
  $log.debug "TA: after : curpos #{@curpos} blen: #{@buffer.length}, w: #{@width} max #{@maxlen}"
  #pre_key
  case ch
  when ?\C-n.getbyte(0)
    scroll_forward
  when ?\C-p.getbyte(0)
    scroll_backward
  when ?\C-[.getbyte(0)
    goto_start #cursor_start of buffer
  when ?\C-].getbyte(0)
    goto_end # cursor_end of buffer
  when KEY_UP
    #select_prev_row
    ret = up
  when KEY_DOWN
    ret = down
  when KEY_ENTER, 10, 13
    insert_break
  when KEY_LEFT
    cursor_backward
  when KEY_RIGHT
    cursor_forward
  when KEY_BACKSPACE, 127
    if @editable   # checking here means that i can programmatically bypass!!
      delete_prev_char 
    end
  when 330, ?\C-d.getbyte(0) # delete char
    if @editable
      delete_curr_char 
    end
  when ?\C-k.getbyte(0) # delete till eol
    # i'ved added curpos == 0 since emacs deletes a line if cursor is at 0
    # Earlier behavior was based on alpine which leaves a blank line
    if @editable
      #if @buffer == ""
      if @buffer.chomp == "" or @curpos == 0
        delete_line
      else
        delete_eol 
      end
    end
  #when ?\C-u.getbyte(0)
    ## since textareas are editable we use a control key to increase
    ## multiplier. Series is 4 16 64
    #@multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
    #return 0
  when ?\C-_.getbyte(0) # changed from C-u so i can use C-u for multipliers
    if @undo_handler
      @undo_handler.undo
    else
      undo_delete
    end
  when ?\C-r.getbyte(0) # redo if UndoHandler installed
    return unless @undo_handler
    @undo_handler.redo
  when ?\C-a.getbyte(0)
    cursor_bol
  when ?\C-e.getbyte(0)
    cursor_eol
    #set_form_col @buffer.length
  #when @KEY_ASK_FIND_FORWARD
  #  ask_search_forward
  #when @KEY_ASK_FIND_BACKWARD
  #  ask_search_backward
  when @KEY_ASK_FIND
    ask_search
  when @KEY_FIND_MORE
    find_more
  #when @KEY_FIND_NEXT
  #  find_next
  #when @KEY_FIND_PREV
  #  find_prev
  else
    #$log.debug(" textarea ch #{ch}")
    ret = putc ch
    if ret == :UNHANDLED
      # check for bindings, these cannot override above keys since placed at end
      ret = process_key ch, self
      $log.debug "TA process_key #{ch} got ret #{ret} in #{@name} "
      return :UNHANDLED if ret == :UNHANDLED
    end
  end
  set_form_row
  set_form_col  # testing 2008-12-26 19:37 
  $multiplier = 0 # reset only if key handled
  return 0
end

#init_varsObject



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/rbcurse/rtextarea.rb', line 79

def init_vars
  @repaint_required = true
  @repaint_footer_required = true # 2010-01-23 22:41 
  @toprow = @current_index = @pcol = 0
  @repaint_all=true 
  ## 2010-02-12 12:20 RFED16 taking care if no border requested
  @suppress_borders ||= false
  @row_offset = @col_offset = 0 if @suppress_borders == true
  # added 2010-02-11 15:11 RFED16 so we don't need a form.
  @win_left = 0
  @win_top = 0
  @longest_line = 0
  bind_key(?\M-w, :kill_ring_save)
  bind_key(?\C-y, :yank)
  bind_key(?\M-y, :yank_pop)
  bind_key(?\M-\C-w, :append_next_kill)
  bind_key(?\M-d, :delete_word)
  bind_key(?\M-f, :forward_word)
end

#insert(off0, data) ⇒ Object

trying to wrap and insert



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/rbcurse/rtextarea.rb', line 117

def insert off0, data
   _maxlen = @maxlen || @width - 2
  if data.length > _maxlen
    data = wrap_text data
  #  $log.debug "after wrap text done :#{data}"
    data = data.split("\n")
     data[-1] << "\r" #XXXX
  else
    data << "\r" if data[-1,1] != "\r" #XXXX
  end
  data.each do |row|
    @list.insert off0, row
    off0 += 1
  end
  #$log.debug " AFTER INSERT: #{@list}"
end

#insert_breakObject

FIXME - fire event not correct, not undo’ing correctly, check row and also slash r append



366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/rbcurse/rtextarea.rb', line 366

def insert_break
  return -1 unless @editable
  # insert a blank row and append rest of this line to cursor
  $log.debug "ENTER PRESSED at  #{@curpos}, on row #{@current_index}"
  @delete_buffer = (delete_eol || "")
  @list[@current_index] << "\r"
  $log.debug "DELETE BUFFER #{@delete_buffer}" 
  @list.insert @current_index+1, @delete_buffer 
  @curpos = 0
  down
  col = @orig_col + @col_offset
  setrowcol @row+1, col
  # FIXME maybe this should be insert line since line inserted, not just data, undo will delete it
  fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT_LINE, @current_index, @delete_buffer)     #  2008-12-24 18:34 
end

#insert_wrap(lineno, pos, lastchars) ⇒ Object

this attempts to recursively insert into a row, seeing that any stuff exceeding is pushed down further. Yes, it should check for a para end and insert. Currently it could add to next para.



655
656
657
658
659
660
661
662
# File 'lib/rbcurse/rtextarea.rb', line 655

def insert_wrap lineno, pos, lastchars
   _maxlen = @maxlen || @width - 2
  @list[lineno].insert pos, lastchars 
  len = @list[lineno].length 
  if len > _maxlen
      push_last_word lineno #- sometime i may push down 10 chars but the last word is less
    end
end

#join_to_prev_lineObject

private when backspace pressed in position zero if the previous line is filled we may have to bring down the last word and join, rather than go up FIXME : make logic simple. Append entire line to above line. Then go to maxlen if not a space, reverse to find last space. Lop off all after space and replace this line with that balance. UNDO and REDO has to work in this case too. FIXME bare in mind handlers when doing this



481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
# File 'lib/rbcurse/rtextarea.rb', line 481

def join_to_prev_line
  return -1 unless @editable
  return if @current_index == 0
  oldcurpos = @curpos
  oldprow = @current_index
  prev = @list[@current_index-1].chomp
  prevlen = prev.length
  # 2008-12-26 21:37 delete previous line if nothing there. This moves entire buffer up.
  if prevlen == 0
    delete_line @current_index-1
    up
    return
  end
  _maxlen = @maxlen || @width - 2
  space_left = _maxlen - prevlen
  # prev line is full exit
  return if space_left == 0

  # get last space, if none, return
  blank_found = @buffer.rindex(' ', space_left)
  return unless blank_found # no word in the space i can carry up.
  # get string for carrying up
  carry_up = @buffer[0..blank_found]
  result = @list[@current_index-1].chomp! # this has to be undone too.
  @list[@current_index-1] << carry_up
  #$log.debug "carry up: #{carry_up} prevrow:#{@list[@current_index -1]}"
  # remove from curr line
  @list[@current_index].slice!(0..carry_up.length-1)
  $log.debug "carry up: #{carry_up} currrow:#{@list[@current_index]}"
  #@list[@current_index] ||= ""
  up
  addrowcol -1,0
  @curpos = prevlen
  # if result not nil, then we need that to be recorded FIXME
  fire_handler :CHANGE, InputDataEvent.new(oldcurpos,oldcurpos+carry_up.length, self, :DELETE, oldprow, carry_up)
  fire_handler :CHANGE, InputDataEvent.new(prevlen,prevlen+carry_up.length, self, :INSERT, oldprow-1, carry_up)

  ## BUG. carry full words up, or if no space then bring down last word of prev lien and join with first
  #carry_up = words_in_length @buffer, space_left #@buffer[0..space_left] # XXX
  #if carry_up.nil?
    ## carry down last word
    #prev_wd = remove_last_word @current_index-1
    ## 2010-01-14 18:26 check added else crashing if C-h pressed with no data in line
    #if !prev_wd.nil?
       #@buffer.insert 0, prev_wd
       #@curpos = prev_wd.length
       #$log.debug " carry up nil! prev_wd (#{prev_wd}) len:#{prev_wd.length}"
       #fire_handler :CHANGE, InputDataEvent.new(0,prev_wd.length, self, :INSERT, oldprow, prev_wd)     #  2008-12-26 23:07 
    #end
  #else
    #$log.debug " carrying up #{carry_up.length} #{carry_up}, space: #{space_left}"
    #@list[@current_index-1]=prev + carry_up
    #space_left2 = @buffer[(carry_up.length+1)..-1]
    #@list[@current_index]=space_left2 #if !space_left2.nil?
    #@list[@current_index] ||= ""
    #up
    #addrowcol -1,0
    #@curpos = prevlen
    #fire_handler :CHANGE, InputDataEvent.new(oldcurpos,carry_up.length, self, :DELETE, oldprow, carry_up)     #  2008-12-24 18:34 
    #fire_handler :CHANGE, InputDataEvent.new(prevlen,carry_up.length, self, :INSERT, oldprow-1, carry_up)     #  2008-12-24 18:34 
  #end
  ## FIXME -- can;t have a naked for reference here.
  ##@form.col = @orig_col + @col_offset + @curpos
  col1 = @orig_col + @col_offset + @curpos
  setrowcol nil, col1 # 2010-02-12 13:09  RFED16

#     $log.debug "carry up: nil" if carry_up.nil?
#     $log.debug "listrow nil " if @list[@current_index].nil?
#     $log.debug "carry up: #{carry_up} prow:#{@list[@current_index]}"
end

#move_char_upObject

move up one char from next row to current, used when deleting in a line should not be called if line ends in “r”



729
730
731
732
# File 'lib/rbcurse/rtextarea.rb', line 729

def move_char_up
  @list[@current_index] << @list[@current_index+1].slice!(0)
  delete_line(@current_index+1) if next_line().length==0
end

#move_chars_upObject

tries to move up as many as possible should not be called if line ends in “r”



735
736
737
738
739
740
741
742
743
744
745
# File 'lib/rbcurse/rtextarea.rb', line 735

def move_chars_up
  oldprow = @current_index
  oldcurpos = @curpos
   _maxlen = @maxlen || @width - 2
  space_left = _maxlen - @buffer.length
  can_move = [space_left, next_line.length].min
  carry_up =  @list[@current_index+1].slice!(0, can_move)
  @list[@current_index] << carry_up
  delete_line(@current_index+1) if next_line().length==0
  fire_handler :CHANGE, InputDataEvent.new(oldcurpos,oldcurpos+can_move, self, :INSERT, oldprow, carry_up)     #  2008-12-24 18:34 
end

#next_lineObject

returns next line, does not move to it,



747
748
749
# File 'lib/rbcurse/rtextarea.rb', line 747

def next_line
  @list[@current_index+1]
end

#Oinsert(off0, *data) ⇒ Object

this avoids wrapping. Better to use the <<.



104
105
106
107
# File 'lib/rbcurse/rtextarea.rb', line 104

def Oinsert off0, *data
  @list.insert off0, *data
  # fire_handler :CHANGE, self  # 2008-12-09 14:56  NOT SURE
end

#old_join_to_prev_lineObject

private when backspace pressed in position zero if the previous line is filled we may have to bring down the last word and join, rather than go up FIXME : make logic simple. Append entire line to above line. Then go to maxlen if not a space, reverse to find last space. Lop off all after space and replace this line with that balance. UNDO and REDO has to work in this case too. FIXME bare in mind handlers when doing this



557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
# File 'lib/rbcurse/rtextarea.rb', line 557

def old_join_to_prev_line
  return -1 unless @editable
  return if @current_index == 0
  oldcurpos = @curpos
  oldprow = @current_index
  prev = @list[@current_index-1].chomp
  prevlen = prev.length
  # 2008-12-26 21:37 delete previous line if nothing there. This moves entire buffer up.
  if prevlen == 0
    delete_line @current_index-1
    up
    return
  end
  _maxlen = @maxlen || @width - 2
  space_left = _maxlen - prev.length
  # BUG. carry full words up, or if no space then bring down last word of prev lien and join with first
  carry_up = words_in_length @buffer, space_left #@buffer[0..space_left] # XXX
  if carry_up.nil?
    # carry down last word
    prev_wd = remove_last_word @current_index-1
    # 2010-01-14 18:26 check added else crashing if C-h pressed with no data in line
    if !prev_wd.nil?
       @buffer.insert 0, prev_wd
       @curpos = prev_wd.length
       $log.debug " carry up nil! prev_wd (#{prev_wd}) len:#{prev_wd.length}"
       fire_handler :CHANGE, InputDataEvent.new(0,prev_wd.length, self, :INSERT, oldprow, prev_wd)     #  2008-12-26 23:07 
    end
  else
    $log.debug " carrying up #{carry_up.length} #{carry_up}, space: #{space_left}"
    @list[@current_index-1]=prev + carry_up
    space_left2 = @buffer[(carry_up.length+1)..-1]
    @list[@current_index]=space_left2 #if !space_left2.nil?
    @list[@current_index] ||= ""
    up
    addrowcol -1,0
    @curpos = prevlen
    fire_handler :CHANGE, InputDataEvent.new(oldcurpos,carry_up.length, self, :DELETE, oldprow, carry_up)     #  2008-12-24 18:34 
    fire_handler :CHANGE, InputDataEvent.new(prevlen,carry_up.length, self, :INSERT, oldprow-1, carry_up)     #  2008-12-24 18:34 
  end
  # FIXME -- can;t have a naked for reference here.
  #@form.col = @orig_col + @col_offset + @curpos
  col1 = @orig_col + @col_offset + @curpos
  setrowcol nil, col1 # 2010-02-12 13:09  RFED16

#     $log.debug "carry up: nil" if carry_up.nil?
#     $log.debug "listrow nil " if @list[@current_index].nil?
#     $log.debug "carry up: #{carry_up} prow:#{@list[@current_index]}"
end

#paintObject



795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
# File 'lib/rbcurse/rtextarea.rb', line 795

def paint
  # not sure where to put this, once for all or repeat 2010-02-12 RFED16
  my_win = @form? @form.window : @target_window
  $log.warn "neither form not target window given!!! TA paint 751" unless my_win
  @win_left = my_win.left # unused remove TODO
  @win_top = my_win.top
  print_borders if (@suppress_borders == false && @repaint_all) # do this once only, unless everything changes
  rc = row_count
  _maxlen = @maxlen || @width-2 # TODO fix in other branches remove ||= 
  $log.debug " #{@name} textarea repaint width is #{@width}, height is #{@height} , maxlen #{_maxlen}/ #{@maxlen}, #{@graphic.name} "
  tm = get_content
  tr = @toprow
  acolor = get_color $datacolor
  h = scrollatrow()
  r,c = rowcol
  @longest_line = @width # _maxlen scroll uses width not maxlen
  $log.debug " TA:::: #{tr} , #{h}, r #{r} c #{c} "
  0.upto(h) do |hh|
    crow = tr+hh
    if crow < rc
        #focussed = @current_index == crow ? true : false 
        #selected = is_row_selected crow
      content = tm[crow].chomp rescue ""
        content.gsub!(/\t/, '  ') # don't display tab
        content.gsub!(/[^[:print:]]/, '')  # don't display non print characters
        if !content.nil? 
          if content.length > _maxlen # only show _maxlen
            @longest_line = content.length if content.length > @longest_line
            content = content[@pcol..@pcol+_maxlen-1] 
          else
            content = content[@pcol..-1]
          end
        end
        #renderer = get_default_cell_renderer_for_class content.class.to_s
        #renderer = cell_renderer()
        #renderer.repaint @form.window, r+hh, c+(colix*11), content, focussed, selected
        #renderer.repaint @form.window, r+hh, c, content, focussed, selected
        @graphic.printstring  r+hh, c, "%-*s" % [@width-2,content], acolor, @attr
        if @search_found_ix == tr+hh
          if !@find_offset.nil?
            @graphic.mvchgat(y=r+hh, x=c+@find_offset, @find_offset1-@find_offset, Ncurses::A_NORMAL, $reversecolor, nil)
          end
        end

    else
      # clear rows
        # TODO the spaces string can be stored once outside loop
      @graphic.printstring r+hh, c, " " * (@width-2), acolor,@attr
    end
  end
  show_caret_func

  @table_changed = false
  @repaint_required = false
  @repaint_footer_required = true # 2010-01-23 22:41 
  @buffer_modified = true # required by form to call buffer_to_screen
  @repaint_all = false # added 2010-01-14 for redrawing everything
end

private



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/rbcurse/rtextarea.rb', line 179

def print_borders
  window = @graphic # 2009-12-26 14:54 BUFFERED
  color = $datacolor
  #window.print_border @row, @col, @height, @width, color
  ## NOTE: If it bombs in next line, either no form passed
  ##+ or you using this embedded and need to set should_create_buffer true when
  ##+ creating. See examples/testscrollta.rb.
  window.print_border @row, @col, @height-1, @width, color
  print_title
=begin
  hline = "+%s+" % [ "-"*(width-((1)*2)) ]
  hline2 = "|%s|" % [ " "*(width-((1)*2)) ]
  window.printstring( row=startrow, col=startcol, hline, color)
  print_title
  (startrow+1).upto(startrow+height-1) do |row|
    window.printstring(row, col=startcol, hline2, color)
  end
  window.printstring(startrow+height, col=startcol, hline, color)
=end
  
end

text_area print footer



205
206
207
208
209
210
211
212
213
# File 'lib/rbcurse/rtextarea.rb', line 205

def print_foot
  @footer_attrib ||= Ncurses::A_REVERSE
  footer = "R: #{@current_index+1}, C: #{@curpos}, #{@list.length} lines  "
  #$log.debug " print_foot calling printstring with #{@row} + #{@height} -1, #{@col}+2"
  # changed 2010-01-02 19:31 BUFFERED we were exceeding 1
  #@graphic.printstring( @row + @height, @col+2, footer, $datacolor, @footer_attrib) 
  @graphic.printstring( @row + @height-1, @col+2, footer, $datacolor, @footer_attrib) 
  @repaint_footer_required = false
end

private



201
202
203
# File 'lib/rbcurse/rtextarea.rb', line 201

def print_title
  @graphic.printstring( @row, @col+(@width-@title.length)/2, @title, $datacolor, @title_attrib) unless @title.nil?
end

#push_last_word(lineno = @current_index) ⇒ Object

push the last word from given line to next I have modified it to push all words that are exceeding maxlen. This was needed for if i push 10 chars to next line, and the last word is less then the line will exceed. So i must push as many words as exceed length.



622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
# File 'lib/rbcurse/rtextarea.rb', line 622

def push_last_word lineno=@current_index
   _maxlen = @maxlen || @width - 2
  #lastspace = @buffer.rindex(" ")
  #lastspace = @list[lineno].rindex(/ \w/)
  line = @list[lineno]
  line = @list[lineno][0.._maxlen+1] if line.length > _maxlen
  lastspace = line.rindex(/ \w/)
  $log.debug " PUSH:2 #{lastspace},#{line},"
  if !lastspace.nil?
    lastchars = @list[lineno][lastspace+1..-1]
    @list[lineno] = @list[lineno][0..lastspace]
    $log.debug "PUSH_LAST:ls:#{lastspace},lw:#{lastchars},lc:#{lastchars[-1]},:#{@list[lineno]}$"
    if lastchars[-1,1] == "\r" or @list[lineno+1].nil?
      # open a new line and keep the 10 at the end.
      append_row lineno, lastchars
    else
      # check for soft tab \n - NO EVEN THIS LOGIC IS WRONG.
      #if lastchars[-1,1] == "\n"
      if lastchars[-1,1] != ' ' and @list[lineno+1][0,1] !=' '
        #@list[lineno+1].insert 0, lastchars + ' '
        insert_wrap lineno+1, 0, lastchars + ' '
      else
        #@list[lineno+1].insert 0, lastchars 
        insert_wrap lineno+1, 0, lastchars 
      end
    end
    return lastchars, lastspace
  end
  return nil
end

#putc(c) ⇒ Object



716
717
718
719
720
721
722
723
724
725
726
# File 'lib/rbcurse/rtextarea.rb', line 716

def putc c
  if c >= 32 and c <= 126
    ret = putch c.chr
    if ret == 0
    # addcol 1
      set_modified 
      return 0
    end
  end
  return :UNHANDLED
end

#putch(char) ⇒ Object

add one char. careful, i shoved a string in yesterday.



665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
# File 'lib/rbcurse/rtextarea.rb', line 665

def putch char
   _maxlen = @maxlen || @width - 2
  @buffer ||= @list[@current_index]
  return -1 if !@editable #or @buffer.length >= _maxlen
  #if @chars_allowed != nil # remove useless functionality
    #return if char.match(@chars_allowed).nil?
  #end
  raise "putch expects only one char" if char.length != 1
  oldcurpos = @curpos
  #$log.debug "putch : pr:#{@current_index}, cp:#{@curpos}, char:#{char}, lc:#{@buffer[-1]}, buf:(#{@buffer})"
  if @overwrite_mode
    @buffer[@curpos] = char
  else
    @buffer.insert(@curpos, char)
  end
  @curpos += 1 
  #$log.debug "putch INS: cp:#{@curpos}, max:#{_maxlen}, buf:(#{@buffer.length})"
  if @curpos-1 > _maxlen or @buffer.length()-1 > _maxlen
    lastchars, lastspace = push_last_word @current_index
    #$log.debug "last sapce #{lastspace}, lastchars:#{lastchars},lc:#{lastchars[-1]}, #{@list[@current_index]} "
    ## wrap on word XX If last char is 10 then insert line
    @buffer = @list[@current_index]
    if @curpos-1 > _maxlen  or @curpos-1 > @buffer.length()-1
      ret = down 
      # keep the cursor in the same position in the string that was pushed down.
      @curpos = oldcurpos - lastspace  #lastchars.length # 0
    end
  end
  set_form_row
  @buffer = @list[@current_index]
  set_form_col
  @modified = true
  fire_handler :CHANGE, InputDataEvent.new(oldcurpos,@curpos, self, :INSERT, @current_index, char)     #  2008-12-24 18:34 
  @repaint_required = true
  0
end

#remove_last_word(lineno) ⇒ Object

removes and returns last word in given line number, or nil if no whitespace



702
703
704
705
706
707
708
709
710
711
712
713
714
# File 'lib/rbcurse/rtextarea.rb', line 702

def remove_last_word lineno
  @list[lineno].chomp!
  line=@list[lineno]
  lastspace = line.rindex(" ")
  if !lastspace.nil?
    lastchars = line[lastspace+1..-1]
    @list[lineno].slice!(lastspace..-1)
    $log.debug " remove_last: lastspace #{lastspace},#{lastchars},#{@list[lineno]}"
    fire_handler :CHANGE, InputDataEvent.new(lastspace,lastchars.length, self, :DELETE, lineno, lastchars)     #  2008-12-26 23:06 
    return lastchars
  end
  return nil
end

#repaintObject

FOR scrollable ###



222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/rbcurse/rtextarea.rb', line 222

def repaint # textarea
  if @screen_buffer.nil? and @should_create_buffer
    safe_create_buffer
    @screen_buffer.name = "Pad::TXTA_PAD_#{@name}"
    $log.debug " textarea creates pad #{@screen_buffer} #{@name}"
  end
  
  #return unless @repaint_required # 2010-02-12 19:08  TRYING - won't let footer print if only col move
  paint if @repaint_required
  print_foot if @print_footer && (@repaint_footer_required || @repaint_required)
  buffer_to_window # 2010-02-12 14:54 RFED16
end

#row_countObject



792
793
794
# File 'lib/rbcurse/rtextarea.rb', line 792

def row_count
  @list.size
end

#rowcolObject



98
99
100
101
# File 'lib/rbcurse/rtextarea.rb', line 98

def rowcol
#  $log.debug "textarea rowcol : #{@row+@row_offset+@winrow}, #{@col+@col_offset}"
  return @row+@row_offset, @col+@col_offset
end

#scrollatrowObject

alias :get_text :to_s —- for listscrollable —- ##



789
790
791
# File 'lib/rbcurse/rtextarea.rb', line 789

def scrollatrow
  @height-3 # 2010-01-02 19:28 BUFFERED 
end

#set_form_col(col1 = @curpos) ⇒ Object

set cursor on correct column



382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/rbcurse/rtextarea.rb', line 382

def set_form_col col1=@curpos
  @curpos = col1
  @cols_panned ||= 0
  cursor_bounds_check
  
  ## added win_col on 2009-12-28 20:21 for embedded forms BUFFERED TRYING OUT
  win_col = 0 # 2010-02-07 23:19 new cursor stuff
  #col = win_col + @orig_col + @col_offset + @curpos
  #col = win_col + @orig_col + @col_offset + @curpos + @cols_panned
  # 2010-01-14 13:31 changed orig_col to col for embedded forms, splitpanes.
  col = win_col + @col + @col_offset + @curpos + @cols_panned
  $log.debug "sfc: wc:#{win_col}  col:#{@col}, coff:#{@col_offset}. cp:#{@curpos} colsp:#{@cols_panned} . "
  #@form.setrowcol @form.row, col   # added 2009-12-29 18:50 BUFFERED
  $log.debug " TA calling setformrow col nil, #{col} "
  setrowcol nil, col   # added 2009-12-29 18:50 BUFFERED
  @repaint_footer_required = true
end

#set_modified(tf = true) ⇒ Object



756
757
758
759
760
761
762
# File 'lib/rbcurse/rtextarea.rb', line 756

def set_modified tf=true
  @modified = tf
  @repaint_required = tf
  @repaint_footer_required = tf
  # 2010-01-14 22:45 putting a check for form, so not necessary to have form set when appending data
  @form.modified = true if tf and !@form.nil?
end

#undo_deleteObject

this is broken, delete_buffer could be a line or a string or array of lines



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/rbcurse/rtextarea.rb', line 349

def undo_delete
    # added 2008-11-27 12:43  paste delete buffer into insertion point
    return if @delete_buffer.nil?
    $log.warn "undo_delete is broken! perhaps cannot be used . textarea 347 "
    # FIXME - can be an array
    case @delete_buffer
    when Array
      # we need to unroll array, and it could be lines not just a string
      str = @delete_buffer.first
    else
      str = @delete_buffer
    end
    @buffer.insert @curpos, str 
    set_modified 
    fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT, @current_index, @delete_buffer)     #  2008-12-24 18:34 
end

#words_in_length(buff, len) ⇒ Object

return as many words as fit into len for carrying up.. actually there is a case of when the next char (len+1) is a white space or word boundary. XXX



608
609
610
611
612
613
614
615
616
617
# File 'lib/rbcurse/rtextarea.rb', line 608

def words_in_length buff, len
  return nil if len == 0
  str = buff[0..len]
  ix = str.rindex(/\s/)
  $log.debug " str #{str} len #{len} ix #{ix} , buff #{buff}~"
  return nil if ix.nil?
  ix = ix > 0 ? ix - 1 : ix
  $log.debug " str[]:#{str[0..ix]}~ len #{len} ix #{ix} , buff #{buff}~"
  return str[0..ix]
end

#wrap_para(line = @current_index) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/rbcurse/rtextarea.rb', line 159

def wrap_para line=@current_index
  line ||= 0
  l=[]
  while true
    if @list[line].nil? or @list[line]=="" or @list[line]==13 #"\r"
      break
    end
    #$log.debug "lastchar #{@list[line][-1]}, appending: #{@list[line]}]"
    t =  @list[line]
    l << t.strip
    @list.delete_at line
    break if t[-1]==13 # "\r"
#    line += 1
  end
  str=l.join(" ")
  #$log.debug " sending insert : #{str}."
  insert line, str
end

#wrap_text(txt, col = @maxlen) ⇒ Object

private



109
110
111
112
113
114
# File 'lib/rbcurse/rtextarea.rb', line 109

def wrap_text(txt, col = @maxlen)
   col ||= @width - 2
  #$log.debug "inside wrap text for :#{txt}"
  txt.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/,
           "\\1\\3\n") 
end