Class: Canis::TextPad

Inherits:
Widget show all
Extended by:
Forwardable
Includes:
BorderTitle
Defined in:
lib/canis/core/widgets/textpad.rb

Direct Known Subclasses

Listbox, Table

Instance Attribute Summary collapse

Attributes inherited from Widget

#_object_created, #col_offset, #config, #curpos, #focussed, #form, #handler, #id, #key_label, #parent_component, #row_offset, #state

Instance Method Summary collapse

Methods included from BorderTitle

#bordertitle_init, #print_borders, #print_title

Methods inherited from Widget

#action_manager, #bgcolor, #color, #color_pair, #command, #focus, #focusable, #focusable?, #getvalue, #getvalue_for_paint, #hide, #modified?, #move, #on_leave, #override_graphic, #process_key, #property_set, #remove, #repaint_all, #repaint_required, #set_form, #set_modified, #setformrowcol, #setrowcol, #show, #unbind_key

Methods included from Io

#__create_footer_window, #clear_this, #get_file, #print_this, #rb_getchar, #rb_gets, #rb_getstr, #warn

Methods included from Utils

#ORIG_process_key, #ORIGbind_key, #ORIGkeycode_tos, #_process_key, #bind_composite_mapping, #bind_key, #bind_keys, #check_composite_mapping, #create_logger, #define_key, #define_prefix_command, #execute_mapping, #get_attrib, #get_color, #key_tos, #print_key_bindings, #repeatm, #run_command, #shell_out, #shell_output, #suspend, #view, #xxxbind_composite_mapping

Methods included from ConfigSetup

#config_setup, #variable_set

Methods included from EventHandler

#bind, #event?, #event_list, #fire_handler, #fire_property_change, #register_events

Constructor Details

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

Returns a new instance of TextPad.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/canis/core/widgets/textpad.rb', line 81

def initialize form=nil, config={}, &block

  @editable = false
  @focusable = true
  @config = config
  @row = @col = 0
  @prow = @pcol = 0
  @startrow = 0
  @startcol = 0
  register_events( [:ENTER_ROW, :PRESS, :DIMENSION_CHANGED, :ROW_CHANGED])
  @text_patterns = {}
  # FIXME we need to be compatible with vim's word
  @text_patterns[:word] =  /[[:punct:][:space:]]\S/
  # we need to be compatible with vim's WORD
  @text_patterns[:WORD] =  /[[:space:]]\S/
  super

  init_vars
end

Instance Attribute Details

#colsObject (readonly)

rows is the actual number of rows the pad has which is slightly less than height (taking

into account borders. Same for cols and width.


50
51
52
# File 'lib/canis/core/widgets/textpad.rb', line 50

def cols
  @cols
end

#current_indexObject (readonly)

dsl_accessor :list_footer # attempt at making a footer object index of focussed row, starting 0, index into the data supplied



47
48
49
# File 'lib/canis/core/widgets/textpad.rb', line 47

def current_index
  @current_index
end

#documentObject (readonly)

Returns the value of attribute document.



79
80
81
# File 'lib/canis/core/widgets/textpad.rb', line 79

def document
  @document
end

#key_handlerObject

for external methods or classes to advance cursor attr_accessor :curpos the object that handles keys that are sent to this object by the form. This widget creates its own default handler if not overridden by user.



58
59
60
# File 'lib/canis/core/widgets/textpad.rb', line 58

def key_handler
  @key_handler
end

#lastcolObject (readonly)

adding these only for debugging table, to see where cursor is.



53
54
55
# File 'lib/canis/core/widgets/textpad.rb', line 53

def lastcol
  @lastcol
end

#lastrowObject (readonly)

adding these only for debugging table, to see where cursor is.



53
54
55
# File 'lib/canis/core/widgets/textpad.rb', line 53

def lastrow
  @lastrow
end

#padObject

type of content in case parsing is required. Values :tmux, :ansi, :none trying to put content+type into document attr_accessor :content_type path of yaml file which contains conversion of style names to color, bgcolor and attrib attr_accessor :stylesheet



78
79
80
# File 'lib/canis/core/widgets/textpad.rb', line 78

def pad
  @pad
end

#text_patternsObject (readonly)

a map of symbols and patterns, used currently in jumping to next or prev occurence of that

pattern. Default contains :word. Callers may add patterns, or modify existing ones and
create key bindings for the same.


72
73
74
# File 'lib/canis/core/widgets/textpad.rb', line 72

def text_patterns
  @text_patterns
end

Instance Method Details

#[]=(index, val) ⇒ Object

update the value at index with given value, returning self



766
767
768
769
770
# File 'lib/canis/core/widgets/textpad.rb', line 766

def []=(index, val)
  @list[index]=val
  fire_row_changed index
  self
end

#__calc_dimensionsObject

calculates the dimensions of the pad which will be used when the pad refreshes, taking into account whether borders are printed or not. This must be called whenever there is a change in height or width otherwise @rows will not be recalculated. Internal.



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/canis/core/widgets/textpad.rb', line 122

def __calc_dimensions
  ## NOTE
  #  ---------------------------------------------------
  #  Since we are using pads, you need to get your height, width and rows correct
  #  Make sure the height factors in the row, else nothing may show
  #  ---------------------------------------------------


  raise " CALC inside #{@name} h or w is nil #{@height} , #{@width} " if @height.nil? or @width.nil?
  @rows = @height
  @cols = @width
  # NOTE XXX if cols is > COLS then padrefresh can fail
  @startrow = @row
  @startcol = @col
  unless @suppress_borders
    @row_offset = @col_offset = 1
    @startrow += 1
    @startcol += 1
    @rows -=3  # 3 is since print_border_only reduces one from width, to check whether this is correct
    @cols -=3
    @scrollatrows = @height - 3
  else
    # no borders printed
    @rows -= 1  # 3 is since print_border_only reduces one from width, to check whether this is correct
    ## if next is 0 then padrefresh doesn't print, gives -1 sometimes.
    ## otoh, if we reduce 1, then there is a blank or white left at 128 since clear_pad clears 128
    # but this only writes 127 2014-05-01 - 12:31 CLEAR_PAD
    #@cols -=0
    @cols -=1
    @scrollatrows = @height - 1 # check this out 0 or 1
    @row_offset = @col_offset = 0
  end
  @top = @row
  @left = @col
  @lastrow = @row + @row_offset
  @lastcol = @col + @col_offset
  $log.debug "  CALC_DIMENSION r:#{@rows} , c:#{@cols}, h:#{@height} , w:#{@width} , top:#{@top} , left:#{@left} "
end

#_do_bordersObject



1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
# File 'lib/canis/core/widgets/textpad.rb', line 1283

def _do_borders
  unless @suppress_borders
    if @repaint_all
      ## XXX im not getting the background color.
      #@window.print_border_only @top, @left, @height-1, @width, $datacolor
      clr = get_color $datacolor, color(), bgcolor()
      #@window.print_border @top, @left, @height-1, @width, clr
      @window.print_border_only @top, @left, @height-1, @width, clr
      print_title

      # oldrow changed to oldindex 2014-04-13 - 16:55
      @repaint_footer_required = true if @oldindex != @current_index
      print_foot if @print_footer && !@suppress_borders && @repaint_footer_required

      @window.wrefresh
    end
  end
end

#_getarrayObject

internal method to return the correct list. Rather than trying to synch list and native text for those who do not use the latter

let us just use the correct array

NOTE there are some cases where document can return a nil since native_text has not been

calculated yet. Happens in back button of help. Earlier preprocess was done from +text+
not it is only done from +repaint+

NOTE: native_text is currently Chunklines - chunks of text with information of color, whereas

list contains whatever the user set, which can include markup for coloring (ansi/tmux).


693
694
695
696
697
698
699
# File 'lib/canis/core/widgets/textpad.rb', line 693

def _getarray
  if @document.nil?
    return @list
  else
    return @document.native_text
  end
end

#_handle_key(ch) ⇒ Object

this is a barebones handler to be used only if an overriding key handler wishes to fall back to default processing after it has handled some keys. The complete version is in Defaultkeyhandler. BUT the key will be executed again.



1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
# File 'lib/canis/core/widgets/textpad.rb', line 1101

def _handle_key ch
  begin
    ret = process_key ch, self
    $multiplier = 0
    bounds_check
  rescue => err
    $log.error " TEXTPAD ERROR _handle_key #{err} "
    $log.debug(err.backtrace.join("\n"))
    alert "#{err}"
    #textdialog ["Error in TextPad: #{err} ", *err.backtrace], :title => "Exception"
  ensure
    padrefresh
    Ncurses::Panel.update_panels
  end
  return 0
end

#append(text) ⇒ Object

Deprecated.

pls use << or push as per Array semantics

NOTE : 2014-04-09 - 14:05 i think this does not have line wise operations since we deal with

formatting of data
But what if data is not formatted. This imposes a severe limitation. listbox does have linewise
operations, so lets try them

append a row to the list



721
722
723
724
725
726
727
# File 'lib/canis/core/widgets/textpad.rb', line 721

def append text
  raise "append: deprecated pls use << or push as per Array semantics"
  @list ||= []
  @list.push text
  fire_dimension_changed :append
  self
end

#ask_search(str = nil) ⇒ Object

Ask user for string to search for This uses the dialog, but what if user wants the old style. Isn’t there a cleaner way to let user override style, or allow user to use own UI for getting pattern and then passing here.

Parameters:

  • str (defaults to: nil)

    default nil. If not passed, then user is prompted using get_string dialog This allows caller to use own method to prompt for string such as ‘get_line’ or ‘rbgetstr’ / ‘ask()’



1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
# File 'lib/canis/core/widgets/textpad.rb', line 1357

def ask_search str=nil
  # the following is a change that enables callers to prompt for the string
  # using some other style, basically the classical style and send the string in
  str = get_string("Enter pattern: ", :title => "Find pattern") unless str
  return if str.nil?
  str = @last_regex if str == ""
  return if !str or str == ""
  str = Regexp.new str if str.is_a? String
  ix = next_match str
  return unless ix
  @last_regex = str

  #@oldindex = @current_index
  @current_index = ix[0]
  @curpos = ix[1]
  ensure_visible
end

#backward_regex(regex) ⇒ Object

jump to previous occurence of given regexp within a line, and then to previous line

This is more line 'w' or 'b' in vim, not like '/'

Parameters:

  • pattern (Regexp)

    to go back to.



977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
# File 'lib/canis/core/widgets/textpad.rb', line 977

def backward_regex regex
  if regex.is_a? Symbol
    regex = @text_patterns[regex]
    raise "Pattern specified #{regex} does not exist in text_patterns " unless regex
  end
  $multiplier = 1 if !$multiplier || $multiplier == 0
  _arr = _getarray
  pos = @curpos || 0 # list does not have curpos
  line = @current_index
  #buff = _arr[line].to_s
  #return unless buff
  # if curpos is at zero , we should be checking previous line !
  $multiplier.times {
    # if at start of line, go to previous line
    if pos == 0
      if @current_index > 0
        line -= 1
        pos = _arr[line].to_s.size
      else
        # we are on first line of file at start
        break
      end
    end
    buff = _arr[line].to_s
    return unless buff
    pos2 = pos - 2
    pos2 = 0 if pos2 < 0
    found = buff.rindex(regex, pos2)
    $log.debug "  backward: pos #{pos} , found #{found}, pos2 = #{pos2} "
    if !found || found == 0
      # if not found, we've lost a counter
      if pos > 0
        pos = 0
      elsif line > 0
        #line -= 1
        #pos = _arr[line].to_s.size
      else
        break
      end
    else
      pos = found + 1
    end
    $log.debug " backward_word: pos #{pos} line #{line} buff: #{buff}"
  }
  $multiplier = 0
  @current_index = line
  @curpos = pos
  ensure_visible
  @repaint_required = true
end

#backward_wordObject

jump to previous word, like vim’s “b”



970
971
972
973
# File 'lib/canis/core/widgets/textpad.rb', line 970

def backward_word
    #backward_regex(/[[:punct:][:space:]]\w/)
    backward_regex(:word)
end

#bottom_of_windowObject



818
819
820
821
822
823
824
825
# File 'lib/canis/core/widgets/textpad.rb', line 818

def bottom_of_window
  @current_index = @prow + @scrollatrows
  $multiplier ||= 0
  if $multiplier > 0
    @current_index -= $multiplier
    $multiplier = 0
  end
end

#bounds_checkObject



1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
# File 'lib/canis/core/widgets/textpad.rb', line 1166

def bounds_check
  raise "@list is empty in textpad. Bounds_check." unless @list
  r,c = rowcol
  @current_index = 0 if @current_index < 0
  @current_index = @list.count()-1 if @current_index > @list.count()-1
  ensure_visible

  check_prow
  @crow = @current_index + r - @prow
  @crow = r if @crow < r
  #$log.debug "XXX: PAD BOUNDS ci:#{@current_index} , old #{@oldrow},pr #{@prow}, crow #{@crow}, max #{@maxrow} pcol #{@pcol} maxcol #{@maxcol}"
  # 2 depends on whetehr suppress_borders
  if @suppress_borders
    @crow = @row + @height -1 if @crow >= r + @height -1
  else
    @crow = @row + @height -2 if @crow >= r + @height -2
  end
  #$log.debug "  PAD BOUNDS CROW #{@crow} calling setrowcol"
  setrowcol @crow, @curpos+c
  lastcurpos @crow, @curpos+c
  if @oldindex != @current_index
    on_leave_row @oldindex if respond_to? :on_leave_row
    on_enter_row @current_index
    @oldindex = @current_index
  end
  if @oldrow != @prow || @oldcol != @pcol
    # only if scrolling has happened.
    @repaint_required = true
  end
end

#check_prowObject

check that prow and pcol are within bounds



1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
# File 'lib/canis/core/widgets/textpad.rb', line 1206

def check_prow
  @prow = 0 if @prow < 0
  @pcol = 0 if @pcol < 0

  cc = @list.count
  @rows = rows()

  #$log.debug "  check_prow prow #{@prow} , list count #{cc}, rows #{@rows} "
  # 2014-05-28 - 22:41 changed < to <= otherwise prow became -1 when equal
  if cc <= @rows
    @prow = 0
  else
    maxrow = cc - @rows - 1
    if @prow > maxrow
      @prow = maxrow
    end
  end
  #$log.debug "  check_prow after prow #{@prow} , list count #{cc} "
  # we still need to check the max that prow can go otherwise
  # the pad shows earlier stuff.
  #
  return
end

#clearObject

clear all items in the object. NOTE: requires to be separate since init_vars is called to reset index of focus etc. Also, listbox will extend this to clear selected_indices



758
759
760
761
762
763
764
# File 'lib/canis/core/widgets/textpad.rb', line 758

def clear
  return unless @list
  @list.clear
  @native_text.clear if @native_text # check this line, should it be removed 2014-08-27 - 20:54
  fire_dimension_changed :clear
  init_vars
end

#clear_padObject



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
# File 'lib/canis/core/widgets/textpad.rb', line 253

def clear_pad
  # this still doesn't work since somehow content_rows is less than height.
  # this is ineffectual if the rest of the code is functioning.
  # But REQUIRED for listbox which has its own clear_row needed in cases of white background.
  # as in testmessagebox.rb 5

  # if called directly then cp does not reflect changes to bgcolor
  _color = color()
  _bgcolor = bgcolor()
  cp = get_color($datacolor, _color, _bgcolor)
  @cp = FFI::NCurses.COLOR_PAIR(cp)

  raise "pad not created" unless @pad
  $log.debug "  clear pad content Rows is #{@content_rows} "
  raise "content_rows is nil" unless @content_rows
  (0..@content_rows).each do |n|
    clear_row @pad, n
  end
  # REST IS REQUIRED otherwise sometimes last line of window is not cleared
  # Happens in bline.rb. i think the above clears the new pad size in the window
  #  which if it is smaller then does not clear complete window.
  ## TRYING OUT COMMENTING OFF THE REMAINDER 2014-05-31 - 14:35
  # next part is messing up messageboxes which have a white background
  # so i use this copied from print_border
  # In messageboxes the border is more inside. but pad cannot clear the entire
  # window. The component may be just a part of the window.
  r,c = rowcol
  # width - 2 was okay if we started from @col + 1 as print_border does in window
  # but here we start from @col so reduce only 1 2014-06-20 - 01:13 TEST THIS XXX
  ww=width-2
  ww=width-1
  _col = @col + 0
  startcol = 1
  startcol = 0 if @suppress_borders
  # need to account for borders. in col+1 and ww
  ww=@width-0 if @suppress_borders
  color = @cp || $datacolor # check this out XXX @cp is already converted to COLOR_PAIR !!
  color = get_color($datacolor, _color, _bgcolor)
  att = attr() || NORMAL
  sp = " " * ww
  #if color == $datacolor
  $log.debug "  clear_pad: colors #{@cp}, ( #{_bgcolor} #{_color} ) #{$datacolor} , attrib #{att} . r #{r} w #{ww}, h #{@height} top #{@window.top}  "
  # 2014-05-15 - 11:01 seems we were clearing an extra row at bottom.
  # earlier it was r+1 but that was missing the first row, so now made it r+0 2014-06-20 - 01:15 XXX
    (r+0).upto(r+@height-startcol-1) do |rr|
      @window.printstring( rr, _col ,sp , color, att)
    end
  #end
end

#clear_row(pad, lineno) ⇒ Object

before updating a single row in a table we need to clear the row otherwise previous contents can show through



455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# File 'lib/canis/core/widgets/textpad.rb', line 455

def clear_row pad, lineno
  if @renderer and @renderer.respond_to? :clear_row
      @renderer.clear_row pad, lineno
  else
    # need pad width not window width, the other clearstring uses width of
    #  widget to paint on window.
    @_clearstring ||= " " * @content_cols
    # what about bg color ??? XXX, left_margin and internal width
    #cp = get_color($datacolor, @color, @bgcolor)
    cp = @cp || FFI::NCurses.COLOR_PAIR($datacolor)
    att = attr() || NORMAL
    FFI::NCurses.wattron(pad,cp | att)
    FFI::NCurses.mvwaddstr(pad,lineno, 0, @_clearstring)
    FFI::NCurses.wattroff(pad,cp | att)
  end
end

#contentObject Also known as: get_content

this is returning the original content Who is using this, should it return native ?



679
680
681
682
# File 'lib/canis/core/widgets/textpad.rb', line 679

def content
  raise "content is nil " unless @list
  return @list
end

#content_colsObject

length of longest string in array This will give a ‘wrong’ max length if the array has ansi color escape sequences in it which inc the length but won’t be printed. Such lines actually have less length when printed So in such cases, give more space to the pad.



388
389
390
391
392
393
# File 'lib/canis/core/widgets/textpad.rb', line 388

def content_cols
  longest = @list.max_by(&:length)
  ## 2013-03-06 - 20:41 crashes here for some reason when man gives error message no man entry
  return 0 unless longest
  longest.length
end

#create_default_keyhandlerObject



1082
1083
1084
# File 'lib/canis/core/widgets/textpad.rb', line 1082

def create_default_keyhandler
  @key_handler = DefaultKeyHandler.new self
end

#create_default_rendererObject



1079
1080
1081
# File 'lib/canis/core/widgets/textpad.rb', line 1079

def create_default_renderer
  @renderer = DefaultRenderer.new self
end

#current_valueObject

returns focussed value (what cursor is on) This may not be a string. A tree may return a node, a table an array or row



709
710
711
712
713
# File 'lib/canis/core/widgets/textpad.rb', line 709

def current_value
  # many descendants do not set native_text - note that list and tree and table use just @list.
  #@native_text[@current_index]
  _getarray[@current_index]
end

#cursor_backwardObject

move cursor backward by one char (currently will not pan)



1042
1043
1044
1045
1046
1047
1048
1049
1050
# File 'lib/canis/core/widgets/textpad.rb', line 1042

def cursor_backward
  $multiplier = 1 if $multiplier == 0
  if @curpos > 0
    @curpos -= $multiplier
    @curpos = 0 if @curpos < 0
    @repaint_required = true
  end
  $multiplier = 0
end

#cursor_bolObject

moves cursor to start of line, panning if required



1064
1065
1066
1067
1068
1069
# File 'lib/canis/core/widgets/textpad.rb', line 1064

def cursor_bol
  # copy of C-a - start of line
  @repaint_required = true if @pcol > 0
  @pcol = 0
  @curpos = 0
end

#cursor_eolObject

moves cursor to end of line also panning window if necessary NOTE: if one line on another page (not displayed) is way longer than any displayed line, then this will pan way ahead, so may not be very intelligent in such situations.



1055
1056
1057
1058
1059
1060
1061
# File 'lib/canis/core/widgets/textpad.rb', line 1055

def cursor_eol
  # pcol is based on max length not current line's length
  @pcol = @content_cols - @cols - 1
  _arr = _getarray
  @curpos = _arr[@current_index].size
  @repaint_required = true
end

#cursor_forwardObject

move cursor forward by one char (currently will not pan)



1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
# File 'lib/canis/core/widgets/textpad.rb', line 1029

def cursor_forward
  $multiplier = 1 if $multiplier == 0
  if @curpos < @cols
    @curpos += $multiplier
    if @curpos > @cols
      @curpos = @cols
    end
    @repaint_required = true
  end
  $multiplier = 0
end

#DEADhighlight_row(index = @current_index, cfg = {}) ⇒ Object

some general methods for highlighting a row or changing attribute. However, these will change the moment panning is done, or a repaint happens. If these should be maintained then they should be called from the repaint method

This was just indicative, and is not used anywhere



1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
# File 'lib/canis/core/widgets/textpad.rb', line 1514

def DEADhighlight_row index = @current_index, cfg={}
  return unless index
  c = 0 # we are using pads so no col except for left_margin if present
  # in a pad we don't need to convert index to printable
  r = index
  defcolor = cfg[:defaultcolor] || $promptcolor
  acolor ||= get_color defcolor, cfg[:color], cfg[:bgcolor]
  att = FFI::NCurses::A_REVERSE
  att = get_attrib(cfg[:attrib]) if cfg[:attrib]
  #@graphic.mvchgat(y=r, x=c, @width-2, att , acolor , nil)
  FFI::NCurses.mvwchgat(@pad, y=r, x=c, @width-2, att, acolor, nil)
end

#destroyObject

Now since we use get_pad from window, upon the window being destroyed, it will call this. Else it will destroy pad



308
309
310
311
# File 'lib/canis/core/widgets/textpad.rb', line 308

def destroy
  FFI::NCurses.delwin(@pad) if @pad # when do i do this ? FIXME
  @pad = nil
end

#down(num = (($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) ⇒ Object

move down a line mimicking vim’s j key

Parameters:

  • multiplier (int)

    entered prior to invoking key



834
835
836
837
838
839
840
841
842
843
844
# File 'lib/canis/core/widgets/textpad.rb', line 834

def down num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  #@oldindex = @current_index if num > 10
  @current_index += num
  # no , i don't like this here. it scrolls up too much making prow = current_index
  unless is_visible? @current_index
    #alert "#{@current_index} not visible prow #{@prow} #{@scrollatrows} "
      @prow += num
  end
  #ensure_visible
  $multiplier = 0
end

#ensure_visible(row = @current_index) ⇒ Object

Ensure current row is visible, if not make it first row NOTE - need to check if its at end and then reduce scroll at rows, check_prow does that

Parameters:

  • current_index (default if not given)


1489
1490
1491
1492
1493
# File 'lib/canis/core/widgets/textpad.rb', line 1489

def ensure_visible row = @current_index
  unless is_visible? row
      @prow = row
  end
end

#filename(filename, reader = nil) ⇒ Object

supply a filename as source for textpad Reads up file into @list One can optionally send in a method which takes a filename and returns an array of data This is required if you are processing files which are binary such as zip/archives and wish to print the contents. (e.g. cygnus gem sends in :get_file_contents).

filename("a.c", method(:get_file_contents))

TODO: i think this should be sent to text in case content_type has been set. FIXME



507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
# File 'lib/canis/core/widgets/textpad.rb', line 507

def filename(filename, reader=nil)
  @file = filename
  unless File.exists? filename
    alert "#{filename} does not exist"
    return
  end
  @filetype = File.extname filename
  if reader
    @list = reader.call(filename)
  else
    @list = File.open(filename,"r").read.split("\n")
  end
  if @filetype == ""
    if @list.first.index("ruby")
      @filetype = ".rb"
    end
  end
  init_vars
  @repaint_all = true
  @_populate_needed = true
end

#find_moreObject

Find next matching row for string accepted in ask_search



1377
1378
1379
1380
1381
1382
1383
1384
1385
# File 'lib/canis/core/widgets/textpad.rb', line 1377

def find_more
  return unless @last_regex
  ix = next_match @last_regex
  return unless ix
  #@oldindex = @current_index
  @current_index = ix[0]
  @curpos = ix[1]
  ensure_visible
end

#fire_action_eventObject

event when user hits ENTER on a row, user would bind :PRESS callers may use text() to get the value of the row, source to get parent object.

obj.bind :PRESS { |eve| eve.text }


1125
1126
1127
1128
1129
1130
# File 'lib/canis/core/widgets/textpad.rb', line 1125

def fire_action_event
  return if @list.nil? || @list.size == 0
  require 'canis/core/include/ractionevent'
  aev = text_action_event
  fire_handler :PRESS, aev
end

#fire_dimension_changed(_method = nil) ⇒ Object

to be called with program / user has added a row or changed column widths so that the pad needs to be recreated. However, cursor positioning is maintained since this is considered to be a minor change. We do not call ‘init_vars` since user is continuing to do some work on a row/col. NOTE : if height and width are changed then only render_all is required

not a reparse since content has not changed.


403
404
405
406
407
408
409
410
# File 'lib/canis/core/widgets/textpad.rb', line 403

def fire_dimension_changed _method=nil
  # recreate pad since width or ht has changed (row count or col width changed)
  @_populate_needed = true
  @repaint_required = true
  @repaint_all = true
  fire_handler :DIMENSION_CHANGED, _method
  @__first_time = nil
end

#fire_row_changed(ix) ⇒ Object

repaint only one row since content of that row has changed. No recreate of pad is done.



413
414
415
416
417
418
419
420
421
# File 'lib/canis/core/widgets/textpad.rb', line 413

def fire_row_changed ix
  return if ix >= @list.length
  clear_row @pad, ix
  # allow documents to reparse that line
  fire_handler :ROW_CHANGED, ix
  _arr = _getarray
  render @pad, ix, _arr[ix]

end

#forward_regex(regex) ⇒ Object

jump to the next occurence of given regex in the current line. It only jumps to next line after exhausting current.

Parameters:

  • passed (Regexp)

    to String.index



937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
# File 'lib/canis/core/widgets/textpad.rb', line 937

def forward_regex regex
  if regex.is_a? Symbol
    regex = @text_patterns[regex]
    raise "Pattern specified #{regex} does not exist in text_patterns " unless regex
  end
  $multiplier = 1 if !$multiplier || $multiplier == 0
  line = @current_index
  _arr = _getarray
  buff = _arr[line].to_s
  return unless buff
  pos = @curpos || 0 # list does not have curpos
  $multiplier.times {
    found = buff.index(regex, pos)
    if !found
      # if not found, we've lost a counter
      if line+1 < _arr.length
        line += 1
      else
        return
      end
      pos = 0
    else
      pos = found + 1
    end
    $log.debug " forward_word: pos #{pos} line #{line} buff: #{buff}"
  }
  $multiplier = 0
  @current_index = line
  @curpos = pos
  ensure_visible
  @repaint_required = true
end

#forward_wordObject

jumps cursor to next word, like vim’s w key



930
931
932
933
# File 'lib/canis/core/widgets/textpad.rb', line 930

def forward_word
    #forward_regex(/[[:punct:][:space:]]\w/)
    forward_regex(:word)
end

#goto_endObject

goto last line of file



792
793
794
795
796
797
798
799
800
801
# File 'lib/canis/core/widgets/textpad.rb', line 792

def goto_end
  $multiplier ||= 0
  if $multiplier > 0
    goto_line $multiplier - 1
    return
  end
  @current_index = @list.count() - 1
  @prow = @current_index - @scrollatrows
  $multiplier = 0
end

#goto_last_positionObject



897
898
899
900
901
902
903
# File 'lib/canis/core/widgets/textpad.rb', line 897

def goto_last_position
  return unless @oldindex
  tmp = @current_index
  @current_index = @oldindex
  @oldindex = tmp
  bounds_check
end

#goto_line(line) ⇒ Object



802
803
804
805
806
807
808
809
# File 'lib/canis/core/widgets/textpad.rb', line 802

def goto_line line
  ## we may need to calculate page, zfm style and place at right position for ensure visible
  #line -= 1
  @current_index = line
  ensure_visible line
  bounds_check
  $multiplier = 0
end

#goto_startObject



779
780
781
782
783
784
785
786
787
788
789
# File 'lib/canis/core/widgets/textpad.rb', line 779

def goto_start
  $multiplier ||= 0
  if $multiplier > 0
    goto_line $multiplier - 1
    return
  end
  @current_index = 0
  @curpos = @pcol = @prow = 0
  @prow = 0
  $multiplier = 0
end

#handle_key(ch) ⇒ Object



1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
# File 'lib/canis/core/widgets/textpad.rb', line 1086

def handle_key ch
  return :UNHANDLED unless @list

  unless @key_handler
    create_default_keyhandler
  end
  @oldrow = @prow
  @oldcol = @pcol
  $log.debug "XXX: TEXTPAD got #{ch} prow = #{@prow}"
  ret = @key_handler.handle_key(ch)
end

#height=(val) ⇒ Object

update the height This also calls fire_dimension_changed so that the dimensions can be recalculated



175
176
177
178
# File 'lib/canis/core/widgets/textpad.rb', line 175

def height=(val)
  super
  fire_dimension_changed :height
end

#init_varsObject



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/canis/core/widgets/textpad.rb', line 100

def init_vars
  $multiplier = 0
  @oldindex = @current_index = 0
  # column cursor
  @prow = @pcol = @curpos = 0
  if @row && @col
    @lastrow = @row + @row_offset
    @lastcol = @col + @col_offset
  end
  # next 4 are required because in some cases a descendant may not use methods such as list or text
  #  to populate. +tree+ has an option of using +root()+.
  @repaint_required = true
  @repaint_all = true
  @_populate_needed = true
  map_keys unless @mapped_keys

end

#is_visible?(index) ⇒ Boolean

return true if the given row is visible

Returns:

  • (Boolean)


1072
1073
1074
1075
# File 'lib/canis/core/widgets/textpad.rb', line 1072

def is_visible? index
  j = index - @prow #@toprow
  j >= 0 && j <= scrollatrows()
end

#lastcurpos(r, c) ⇒ Object

save last cursor position so when reentering, cursor can be repositioned



1198
1199
1200
1201
# File 'lib/canis/core/widgets/textpad.rb', line 1198

def lastcurpos r,c
  @lastrow = r
  @lastcol = c
end

#map_keysObject

key mappings

TODO take from listbindings so that emacs and vim can be selected. also user can change in one place.



1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
# File 'lib/canis/core/widgets/textpad.rb', line 1306

def map_keys
  @mapped_keys = true
  require 'canis/core/include/listbindings'
  bindings
=begin
  bind_key([?g,?g], 'goto_start'){ goto_start } # mapping double keys like vim
  bind_key(279, 'goto_start'){ goto_start }
  bind_keys([?G,277], 'goto end'){ goto_end }
  bind_keys([?k,KEY_UP], "Up"){ up }
  bind_keys([?j,KEY_DOWN], "Down"){ down }
  bind_key(?\C-e, "Scroll Window Down"){ scroll_window_down }
  bind_key(?\C-y, "Scroll Window Up"){ scroll_window_up }
  bind_keys([32,338, ?\C-d], "Scroll Forward"){ scroll_forward }
  # adding CTRL_SPACE as back scroll 2014-04-14
  bind_keys([0,?\C-b,339], "Scroll Backward"){ scroll_backward }
  # the next one invalidates the single-quote binding for bookmarks
  #bind_key([?',?']){ goto_last_position } # vim , goto last row position (not column)
  bind_key(?/, :ask_search)
  bind_key(?n, :find_more)
  bind_key([?\C-x, ?>], :scroll_right)
  bind_key([?\C-x, ?<], :scroll_left)
  bind_key(?\M-l, :scroll_right)
  bind_key(?\M-h, :scroll_left)
  bind_key(?L, :bottom_of_window)
  bind_key(?M, :middle_of_window)
  bind_key(?H, :top_of_window)
  bind_key(?w, :forward_word)
  bind_key(?b, :backward_word)
  bind_key(?l, :cursor_forward)
  bind_key(?h, :cursor_backward)
  bind_key(?$, :cursor_eol)
  bind_key(KEY_ENTER, :fire_action_event)
=end
end

#middle_of_windowObject



827
828
829
830
# File 'lib/canis/core/widgets/textpad.rb', line 827

def middle_of_window
  @current_index = @prow + (@scrollatrows/2)
  $multiplier = 0
end

#next_match(str, startline = nil, endline = nil) ⇒ Array<Integer, Integer>

since 2014-05-26 - 12:13 new logic to take into account multiple matches in one line

First time, starts searching current line from cursor position onwards to end of file

If no match, then checks from start of file to current line.

NOTE:

startline and endline are more for internal purposes, externally we would call this only with
the pattern.

2014-05-28 - Added to_s before index() so that other descendants can use, such as treemodel or tablemodel

Examples:

pos = next_match /abc/
# pos is nil or [line, col]

Parameters:

  • pattern (String, Regex)

    to search (uses :index)

  • line (Integer)

    number to start with. Optional. nil means start search from current position.

  • line (Integer)

    number to end with. Optional. nil means end search at end of array

Returns:

  • (Array<Integer, Integer>)

    index of line where pattern found, index of offset in line. nil returned if no match.



1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
# File 'lib/canis/core/widgets/textpad.rb', line 1432

def next_match str, startline=nil, endline=nil
  # 1. look in current row after the curpos
  # 2. if no match look in rest of array
  # 3. if no match and you started from current_index, then search
  #   from start of file to current_index. call _next_match with 0.
  _arr = _getarray
  if !startline
    startline = @current_index
    pos = @curpos + 1
    # FIXME you could be at end of line
    #_line = _arr[startline]
    _line = to_searchable(startline)
    _col = _line.index(str, pos) if _line
    if _col
      return [startline, _col]
    end
    startline += 1 # FIXME check this end of file
  end
   # FIXME iterate only through the ones we need, not all
  _arr.each_with_index do |line, ix|
    next if ix < startline
    break if endline && ix > endline
    # next line just a hack and not correct if only one match in file FIXME
    line = to_searchable(ix)
    _col = line.index str
    if _col
      return [ix, _col]
    end
  end
  if startline > 0
    return next_match str, 0, @current_index
  end
  return nil

end

#next_regex(regex) ⇒ nil

search for the next occurence of given regexp. Returns line and col if found, else nil.

Parameters:

  • pattern (String, Regexp)

    to search for (uses :index)

Returns:

  • (nil)

    return value of no consequence



1470
1471
1472
1473
1474
1475
1476
1477
# File 'lib/canis/core/widgets/textpad.rb', line 1470

def next_regex regex
  if regex.is_a? Symbol
    regex = @text_patterns[regex]
    raise "Pattern specified #{regex} does not exist in text_patterns " unless regex
  end
  @last_regex = regex
  find_more
end

#on_enterObject

called when this widget is entered, by form



1152
1153
1154
1155
# File 'lib/canis/core/widgets/textpad.rb', line 1152

def on_enter
  super
  set_form_row
end

#on_enter_row(arow) ⇒ Object

execute binding when a row is entered, used more in lists to display some text in a header or footer as one traverses



1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
# File 'lib/canis/core/widgets/textpad.rb', line 1139

def on_enter_row arow
  return nil if @list.nil? || @list.size == 0

  @repaint_footer_required = true

  ## can this be done once and stored, and one instance used since a lot of traversal will be done
  require 'canis/core/include/ractionevent'
  aev = TextActionEvent.new self, :ENTER_ROW, current_value().to_s, @current_index, @curpos
  fire_handler :ENTER_ROW, aev
end

#ORIG_text(*val) ⇒ Object

old text {{{



615
616
617
618
619
620
621
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
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
# File 'lib/canis/core/widgets/textpad.rb', line 615

def ORIG_text(*val)
  if val.empty?
    return @list
  end
  lines = val[0]
  raise "Textpad: text() received nil" unless lines
  fmt = val.size == 2 ? val[1] : nil
  case fmt
  when Hash
    #raise "textpad.text expected content_type in Hash : #{fmt}"
    c = fmt[:content_type]
    t = fmt[:title]
    @title = t if t
    @content_type = c if c
    @stylesheet = fmt[:stylesheet] if fmt.key? :stylesheet
    $log.debug "  TEXTPAD text() got  #{@content_type} and #{@stylesheet} "
    fmt = c
    #raise "textpad.text expected content_type in Hash : #{fmt}" unless fmt
  when Symbol
    @content_type = fmt
  when NilClass
  else
    raise "textpad.text expected symbol or content_type in Hash, got #{fmt.class} "
  end

  ## some programs like testlistbox which uses multibuffers calls this with a config
  # in arg2 containing :content_type and :title


  # added so callers can have one interface and avoid an if condition
  #return formatted_text(lines, fmt) unless @content_type == :none
  # 2014-05-20 - 13:21 change and simplication of conversion process
  # We maintain original text in @list
  # but use another variable for native format (chunks).
  @parse_required = true
  @list = lines

  # 2014-06-15 - 13:39 i am commenting this off, since a user can change or set content_type
  # at any time, and also content handler.
  if @content_type
    # this will create a default content handler if not yet specified
    #  which is wrong since user may specify it after setting text. he may not have
    #  set the content type yet too. Too much dependent on order !
    #preprocess_text
    #parse_formatted_text lines, :content_type => @content_type, :stylesheet => @stylesheet
  end

  return @list if lines.empty?
  #@list = lines
  #@native_text ||= @list
  @_populate_needed = true
  @repaint_all = true
  @repaint_required = true
  init_vars
  # i don't want the whole thing going into the event 2014-06-04
  fire_property_change :text, "dummmy", "text has changed"
  self
end

#ORIGnext_match(str) ⇒ Object

Find the next row that contains given string FIXME: 2014-05-26 - 01:26 currently if there are two matches in a row skips the second

one, which is a pain if two matches only on same row.
Ok, now it goes to second but won't come back to first, if only two matches, and both in one row.

Parameters:

  • String

    to find

Returns:

  • row and col offset of match, or nil



1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
# File 'lib/canis/core/widgets/textpad.rb', line 1394

def ORIGnext_match str
  return unless str
  first = nil
  ## content can be string or Chunkline, so we had to write <tt>index</tt> for this.
  ## =~ does not give an error, but it does not work.
  @native_text.each_with_index do |line, ix|
    offset = 0
    # next line just a hack and not correct if only one match in file FIXME
    offset = @curpos + 1 if ix == @current_index
    _col = line.index str, offset
    if _col
      first ||= [ ix, _col ]
      if ix > @current_index || ( ix == @current_index && _col > @curpos)
        return [ix, _col]
      end
    end
  end
  # if first is nil, then none found in current line also, so don't increment offset in current line
  #  next time. FIXME TODO
  return first
end

#pad_colsObject



217
218
219
220
221
222
# File 'lib/canis/core/widgets/textpad.rb', line 217

def pad_cols
  return @content_cols if @content_cols
  _content_cols = content_cols()
  _content_cols = @cols if _content_cols < @cols
  return _content_cols
end

#pad_rowsObject



207
208
209
210
211
212
213
# File 'lib/canis/core/widgets/textpad.rb', line 207

def pad_rows
  # content_rows can be more than size of pad, but never less. Same for cols.
  return @content_rows if @content_rows
  content_rows = @list.count
  content_rows = @rows if content_rows < @rows
  return content_rows
end

#padrefreshObject



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
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/canis/core/widgets/textpad.rb', line 318

def padrefresh
  # sometimes padref is called directly from somewhere but dimensions have changed.
  # 2014-05-27 - 11:42
  unless @__first_time
    __calc_dimensions
    @__first_time = true
  end
  # startrow is the row of TP plus 1 for border
  top = @window.top
  left = @window.left
  sr = @startrow + top
  sc = @startcol + left
  ser = @rows + sr
  sec = @cols + sc

  if @fixed_bounds
    #retval = FFI::NCurses.prefresh(@pad,@prow,@pcol, sr , sc , ser , sec );
    $log.debug "PAD going into fixed_bounds with #{@fixed_bounds}"
    sr = @fixed_bounds[0] if @fixed_bounds[0]
    sc = @fixed_bounds[1] if @fixed_bounds[1]
    ser = @fixed_bounds[2] if @fixed_bounds[2]
    sec = @fixed_bounds[3] if @fixed_bounds[3]
  end

  # this is a fix, but the entire popup is not moved up. title and borders are still
  # drawn in wrong positions, and left there after popup is off.
  maxr = FFI::NCurses.LINES - 1
  maxc = FFI::NCurses.COLS
  if ser > maxr
    $log.warn "XXX PADRE ser > max. sr= #{sr} and ser #{ser}. sr:#{@startrow}+ #{top} , sc:#{@startcol}+ #{left},  rows:#{@rows}+ #{sr} cols:#{@cols}+ #{sc}  top #{top} left #{left} "
    #_t = ser - maxr
    #ser = maxr
    #sr -= _t
    #$log.warn "XXX PADRE after correcting ser #{sr} and #{ser} "
  end
  # there are some freak cases where prow or pcol comes as -1, but prefresh does not return a -1. However, this
  # could affect some other calculation somewhere.

  retval = FFI::NCurses.prefresh(@pad,@prow,@pcol, sr , sc , ser , sec );
  $log.warn "XXXPADREFRESH #{retval} #{self.class}:#{self.name}, #{@prow}, #{@pcol}, #{sr}, #{sc}, #{ser}, #{sec}." if retval == -1
  # remove next debug statement after some testing DELETE
  $log.debug "0PADREFRESH #{retval} #{self.class}, #{@prow}, #{@pcol}, #{sr}, #{sc}, #{ser}, #{sec}." if retval == 0
  if retval < 0
    Ncurses.beep
    if sr > maxr
      $log.warn "XXXPADREF #{sr} should be <= #{maxr} "
    end
    if sc < 0 || sc >= maxc
      $log.warn "XXXPADREF #{sc} should be less than #{maxc} "
    end
    if ser > maxr || ser < sr
      $log.warn "XXXPADREF #{ser} should be less than #{maxr} and gt #{sr}  "
    end
    if sec > maxc || sec < sc
      $log.warn "XXXPADREF #{sec} should be less than #{maxc} and gt #{sc}  "
    end
    $log.warn "XXXPADRE sr= #{sr} and ser #{ser}. sr:#{@startrow}+ #{top} , sc:#{@startcol}+ #{left},  rows:#{@rows}+ #{sr} cols:#{@cols}+ #{sc}  top #{top} left #{left} "
  end
  #$log.debug "XXX:  PADREFRESH #{retval} #{self.class}, #{@prow}, #{@pcol}, #{sr}, #{sc}, #{ser}, #{sec}." if retval == 0
  # padrefresh can fail if width is greater than NCurses.COLS
  # or if height exceeds tput lines. As long as content is less, it will work
  # the moment content_rows exceeds then this issue happens.
  # @rows + sr < tput lines
  #FFI::NCurses.prefresh(@pad,@prow,@pcol, @startrow + top, @startcol + left, @rows + @startrow + top, @cols+@startcol + left);
end

#preprocess_textObject

textpad’s preprocess



701
702
703
704
705
# File 'lib/canis/core/widgets/textpad.rb', line 701

def preprocess_text
  if @document
    @document.preprocess_text @list
  end
end

print footer containing line and position



473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
# File 'lib/canis/core/widgets/textpad.rb', line 473

def print_foot #:nodoc:
  return unless @print_footer
  return unless @suppress_borders
  footer = "R: #{@current_index+1}, C: #{@curpos+@pcol}, #{@list.length} lines  "
  @graphic.printstring( @row + @height -1 , @col+2, footer, @color_pair || $datacolor, @footer_attrib)
=begin
  if @list_footer
    if false
      # if we want to print ourselves
      footer = @list_footer.text(self)
      footer_attrib = @list_footer.config[:attrib] ||  Ncurses::A_REVERSE
      #footer = "R: #{@current_index+1}, C: #{@curpos+@pcol}, #{@list.length} lines  "
      $log.debug " print_foot calling printstring with #{@row} + #{@height} -1, #{@col}+2"
      @graphic.printstring( @row + @height -1 , @col+2, footer, @color_pair || $datacolor, footer_attrib)
    end
    # use default print method which only prints on left
    @list_footer.print self
  end
=end
  @repaint_footer_required = false # 2010-01-23 22:55
end

#render(pad, lineno, text) ⇒ Object

This is to render a row, for those overriding classes who have overridden

render_all, but not +render+. e.g. +Table+. THis is also required
for row modifications.


444
445
446
# File 'lib/canis/core/widgets/textpad.rb', line 444

def render pad, lineno, text
  @renderer.render pad, lineno, text
end

#render_allObject

iterate through content rendering each row 2013-03-27 - 01:51 separated so that widgets with headers such as tables can override this for better control



428
429
430
431
432
433
# File 'lib/canis/core/widgets/textpad.rb', line 428

def render_all
  _arr = _getarray
  raise "textpad:render_all: array is nil " unless _arr
  @renderer.source ||= self
  @renderer.render_all @pad, _arr
end

#renderer(r) ⇒ Object

supply a custom renderer that implements render()

See Also:



438
439
440
# File 'lib/canis/core/widgets/textpad.rb', line 438

def renderer r
  @renderer = r
end

#repaintObject



1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
# File 'lib/canis/core/widgets/textpad.rb', line 1230

def repaint
  unless @__first_time
    __calc_dimensions
    @__first_time = true
  end
  return unless @list # trying out since it goes into padrefresh even when no data 2014-04-10 - 00:32
  @graphic = @form.window unless @graphic
  @window ||= @graphic
  raise "Window not set in textpad" unless @window
  unless @renderer
    create_default_renderer
  end

  ## 2013-03-08 - 21:01 This is the fix to the issue of form callign an event like ? or F1
  # which throws up a messagebox which leaves a black rect. We have no place to put a refresh
  # However, form does call repaint for all objects, so we can do a padref here. Otherwise,
  # it would get rejected. UNfortunately this may happen more often we want, but we never know
  # when something pops up on the screen.
  #$log.debug "  repaint textpad RR #{@repaint_required} #{@window.top} "
  unless @repaint_required
    print_foot if @repaint_footer_required  # set in on_enter_row
    # trying out removing this, since too many refreshes 2014-05-01 - 12:45
    #padrefresh
    return
  end
  # if repaint is required, print_foot not called. unless repaint_all is set, and that
  # is rarely set.

  preprocess_text

  # in textdialog, @window was nil going into create_pad 2014-04-15 - 01:28

  # creates pad and calls render_all
  populate_pad if !@pad or @_populate_needed
  if @repaint_all
    clear_pad
    Ncurses::Panel.update_panels
    render_all
  end

  raise "PAD IS NIL -- populate_pad was not called ??" unless @pad

  _do_borders
  print_foot if @repaint_footer_required  # if still not done

  padrefresh
  # in some cases next line prevents overlapped window from refreshing again, leaving black rows.
  # removing it causes problems in other cases. (tasks.rb, confirm window. dbdemo, F2 closing)
  Ncurses::Panel.update_panels
  @repaint_required = false
  @repaint_all = false
end

#row_countObject

Deprecated.

: row_count used just for compat, use length or size



729
# File 'lib/canis/core/widgets/textpad.rb', line 729

def row_count ; @list.length ; end

#rowcolObject

returns the row and col where the cursor is initially placed, and where printing starts from.



169
170
171
# File 'lib/canis/core/widgets/textpad.rb', line 169

def rowcol #:nodoc:
  return @row+@row_offset, @col+@col_offset
end

#scroll_backwardObject

scrolls lines backward a window full at a time, on pressing pageup C-u may not work since it is trapped by form earlier. Need to fix



892
893
894
895
896
# File 'lib/canis/core/widgets/textpad.rb', line 892

def scroll_backward
  #@oldindex = @current_index
  @current_index -= @scrollatrows
  @prow = @current_index - @scrollatrows
end

#scroll_forwardObject

scrolls lines a window full at a time, on pressing SPACE or C-d or pagedown



884
885
886
887
888
# File 'lib/canis/core/widgets/textpad.rb', line 884

def scroll_forward
  #@oldindex = @current_index
  @current_index += @scrollatrows
  @prow = @current_index - @scrollatrows
end

#scroll_leftObject

to prevent right from retaining earlier painted values padreader does not do a clear, yet works fine. OK it has an update_panel after padrefresh, that clears it seems. this clears entire window not just the pad FFI::NCurses.wclear(@window.get_window) so border and title is repainted after window clearing

Next line was causing all sorts of problems when scrolling with ansi formatted text



924
925
926
# File 'lib/canis/core/widgets/textpad.rb', line 924

def scroll_left
  @pcol -= 1
end

#scroll_rightObject



904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
# File 'lib/canis/core/widgets/textpad.rb', line 904

def scroll_right
  # I don't think it will ever be less since we've increased it to cols
  if @content_cols <= @cols
    maxpcol = 0
    @pcol = 0
  else
    maxpcol = @content_cols - @cols - 1
    @pcol += 1
    @pcol = maxpcol if @pcol > maxpcol
  end
  # to prevent right from retaining earlier painted values
  # padreader does not do a clear, yet works fine.
  # OK it has an update_panel after padrefresh, that clears it seems.
  #this clears entire window not just the pad
  #FFI::NCurses.wclear(@window.get_window)
  # so border and title is repainted after window clearing
  #
  # Next line was causing all sorts of problems when scrolling  with ansi formatted text
  #@repaint_all = true
end

#scroll_window_down(num = (($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) ⇒ Object

scrolls window down mimicking vim C-e

Parameters:

  • multiplier (int)

    entered prior to invoking key



863
864
865
866
867
868
869
870
# File 'lib/canis/core/widgets/textpad.rb', line 863

def scroll_window_down num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  @prow += num
    if @prow > @current_index
      @current_index += 1
    end
  #check_prow
  $multiplier = 0
end

#scroll_window_up(num = (($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) ⇒ Object

scrolls window up mimicking vim C-y

Parameters:

  • multiplier (int)

    entered prior to invoking key



874
875
876
877
878
879
880
881
# File 'lib/canis/core/widgets/textpad.rb', line 874

def scroll_window_up num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  @prow -= num
  unless is_visible? @current_index
    # one more check may be needed here TODO
    @current_index -= num
  end
  $multiplier = 0
end

#scrollatrowsObject Also known as: rows



160
161
162
163
164
165
166
# File 'lib/canis/core/widgets/textpad.rb', line 160

def scrollatrows
  unless @suppress_borders
    @height - 3
  else
    @height - 1
  end
end

#set_form_colObject

called by form



1161
1162
# File 'lib/canis/core/widgets/textpad.rb', line 1161

def set_form_col
end

#set_form_rowObject

called by form



1157
1158
1159
# File 'lib/canis/core/widgets/textpad.rb', line 1157

def set_form_row
  setrowcol @lastrow, @lastcol
end

#text(*val) ⇒ Object Also known as: list, set_content

display text given in an array format. This is the principal way of giving content to a textpad, other than filename(). If a format other than :none is given, then formatted_text is called.

Parameters:

  • Array

    of lines

  • format (optional)

    can be :tmux :ansi or :none



539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
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
605
606
607
608
609
610
611
612
613
# File 'lib/canis/core/widgets/textpad.rb', line 539

def text(*val)
  if val.empty?
    return @list
  end
  $log.debug "  TEXTPAD inside text() with #{val.class} "
  case val
  when Array
    # either its an array of strings
    # or its an array, and val[0] is an array of strings, and val[1] is a hash / symbol TODO
    case val[0]
    when String
      # This is the usual simple case of an array of strings
      @list = val
      $log.debug "  creating TEXTDOC 0 with String"
    when TextDocument
      # this is repeating it seems FIXME
      $log.debug "  creating TEXTDOC 04 with TextDocu #{val[0].content_type} "

      @document = val[0]
      @document.source ||= self
      @document.parse_required # added 2014-09-03 - 17:54
      @list = @document.text
    when Array
      # This is the complex case which i would like to phase out.
      # Earlier this was what was used where the second arg was an optional hash
      @list = val[0]
      if val[1].is_a? Symbol
        content_type = val[1]
        hsh = { :text => @list, :content_type => content_type }
        $log.debug "  creating TEXTDOC 1 with #{content_type} "
        @document = TextDocument.new hsh
        @document.source = self
      elsif val[1].is_a? Hash
        # this is hack for those cases where ct is there, but the caller may not
        # pass it in config
        if val[1].key? :content_type and val[1][:content_type].nil?
          ;
        else
          # content type comes nil from viewer/help which sets it later using block yield
          content_type = val[1][:content_type]
          stylesheet = val[1][:stylesheet]
          @title = val[1][:title] if val[1].key? :title
          $log.debug "  creating TEXTDOC 2 with ct=#{content_type}, #{val[1]} "
          @document = TextDocument.new val[1]
          @document.text = @list
          @document.source = self
        end
      else
      #raise "val_1 Unable to do anything with #{val[1].class} "
        $log.debug " val_1 Unable to do anything with #{val[1].class} in textpad text()"
      end
    else
      raise "val_0 Unable to do anything with #{val[0].class} "
    end
  when Hash
    $log.debug "  creating TEXTDOC 3 with #{val[:content_type]} "
    @document = TextDocument.new val
    @document.source ||= self
    @list = @document.text
  when TextDocument
    $log.debug "  creating TEXTDOC 4 with TextDocu #{val.content_type} "

    @document = val
    @document.source ||= self
    @document.parse_required # added 2014-09-03 - 17:54
    @list = @document.text
  end
  @_populate_needed = true
  @repaint_all = true
  @repaint_required = true
  init_vars
  # i don't want the whole thing going into the event 2014-06-04
  fire_property_change :text, "dummmy", "text has changed"
  self
end

#text_action_eventObject

creates and returns a textactionevent object with current_value , line number and cursor position



1132
1133
1134
# File 'lib/canis/core/widgets/textpad.rb', line 1132

def text_action_event
  aev = TextActionEvent.new self, :PRESS, current_value().to_s, @current_index, @curpos
end

#to_searchable(index) ⇒ Object

convert the row to something we can run index on. it should be exactly as the display will be, so find offsets are correct. Required for descendants such as Table.



1480
1481
1482
# File 'lib/canis/core/widgets/textpad.rb', line 1480

def to_searchable index
  _getarray[index].to_s
end

#top_of_windowObject



810
811
812
813
814
815
816
817
# File 'lib/canis/core/widgets/textpad.rb', line 810

def top_of_window
  @current_index = @prow
  $multiplier ||= 0
  if $multiplier > 0
    @current_index += $multiplier
    $multiplier = 0
  end
end

#up(num = (($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)) ⇒ Object

move up a line mimicking vim’s k key

Parameters:

  • multiplier (int)

    entered prior to invoking key



848
849
850
851
852
853
854
855
856
857
858
859
# File 'lib/canis/core/widgets/textpad.rb', line 848

def up num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
  #@oldindex = @current_index if num > 10
  @current_index -= num
  #unless is_visible? @current_index
    #if @prow > @current_index
      ##$status_message.value = "1 #{@prow} > #{@current_index} "
      #@prow -= 1
    #else
    #end
  #end
  $multiplier = 0
end

#visual_indexObject

returns the row offset of the focussed row, based on what is visible this takes into account scrolling, and is useful if some caller needs to know where the current index is actually being displayed (example if it wishes to display a popup at that row) An argument is not being taken since the index should be visible.



1500
1501
1502
1503
# File 'lib/canis/core/widgets/textpad.rb', line 1500

def visual_index
  row = @current_index
  row - @prow
end

#width=(val) ⇒ Object

set the width This also calls fire_dimension_changed so that the dimensions can be recalculated



181
182
183
184
# File 'lib/canis/core/widgets/textpad.rb', line 181

def width=(val)
  super
  fire_dimension_changed :width
end