rbcurse-core 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/README.md +69 -0
  2. data/VERSION +1 -0
  3. data/examples/abasiclist.rb +151 -0
  4. data/examples/alpmenu.rb +46 -0
  5. data/examples/app.sample +17 -0
  6. data/examples/atree.rb +100 -0
  7. data/examples/common/file.rb +45 -0
  8. data/examples/data/README.markdown +9 -0
  9. data/examples/data/brew.txt +38 -0
  10. data/examples/data/color.2 +37 -0
  11. data/examples/data/gemlist.txt +60 -0
  12. data/examples/data/lotr.txt +12 -0
  13. data/examples/data/ports.txt +136 -0
  14. data/examples/data/table.txt +37 -0
  15. data/examples/data/tasks.csv +88 -0
  16. data/examples/data/tasks.txt +27 -0
  17. data/examples/data/todo.txt +10 -0
  18. data/examples/data/todocsv.csv +28 -0
  19. data/examples/data/unix1.txt +21 -0
  20. data/examples/data/unix2.txt +11 -0
  21. data/examples/dbdemo.rb +487 -0
  22. data/examples/dirtree.rb +90 -0
  23. data/examples/newtabbedwindow.rb +100 -0
  24. data/examples/newtesttabp.rb +92 -0
  25. data/examples/tabular.rb +132 -0
  26. data/examples/tasks.rb +167 -0
  27. data/examples/term2.rb +83 -0
  28. data/examples/testkeypress.rb +72 -0
  29. data/examples/testlistbox.rb +158 -0
  30. data/examples/testmessagebox.rb +140 -0
  31. data/examples/testree.rb +106 -0
  32. data/examples/testwsshortcuts.rb +66 -0
  33. data/examples/testwsshortcuts2.rb +127 -0
  34. data/lib/rbcurse.rb +8 -0
  35. data/lib/rbcurse/core/docs/index.txt +73 -0
  36. data/lib/rbcurse/core/include/action.rb +40 -0
  37. data/lib/rbcurse/core/include/appmethods.rb +112 -0
  38. data/lib/rbcurse/core/include/bordertitle.rb +41 -0
  39. data/lib/rbcurse/core/include/chunk.rb +182 -0
  40. data/lib/rbcurse/core/include/io.rb +953 -0
  41. data/lib/rbcurse/core/include/listcellrenderer.rb +140 -0
  42. data/lib/rbcurse/core/include/listeditable.rb +317 -0
  43. data/lib/rbcurse/core/include/listscrollable.rb +590 -0
  44. data/lib/rbcurse/core/include/listselectable.rb +264 -0
  45. data/lib/rbcurse/core/include/multibuffer.rb +83 -0
  46. data/lib/rbcurse/core/include/orderedhash.rb +77 -0
  47. data/lib/rbcurse/core/include/ractionevent.rb +67 -0
  48. data/lib/rbcurse/core/include/rchangeevent.rb +27 -0
  49. data/lib/rbcurse/core/include/rhistory.rb +62 -0
  50. data/lib/rbcurse/core/include/rinputdataevent.rb +47 -0
  51. data/lib/rbcurse/core/include/vieditable.rb +170 -0
  52. data/lib/rbcurse/core/system/colormap.rb +163 -0
  53. data/lib/rbcurse/core/system/keyboard.rb +150 -0
  54. data/lib/rbcurse/core/system/keydefs.rb +30 -0
  55. data/lib/rbcurse/core/system/ncurses.rb +218 -0
  56. data/lib/rbcurse/core/system/panel.rb +162 -0
  57. data/lib/rbcurse/core/system/window.rb +901 -0
  58. data/lib/rbcurse/core/util/ansiparser.rb +117 -0
  59. data/lib/rbcurse/core/util/app.rb +1235 -0
  60. data/lib/rbcurse/core/util/basestack.rb +407 -0
  61. data/lib/rbcurse/core/util/bottomline.rb +1850 -0
  62. data/lib/rbcurse/core/util/colorparser.rb +71 -0
  63. data/lib/rbcurse/core/util/focusmanager.rb +31 -0
  64. data/lib/rbcurse/core/util/padreader.rb +189 -0
  65. data/lib/rbcurse/core/util/rcommandwindow.rb +587 -0
  66. data/lib/rbcurse/core/util/rdialogs.rb +619 -0
  67. data/lib/rbcurse/core/util/viewer.rb +149 -0
  68. data/lib/rbcurse/core/util/widgetshortcuts.rb +505 -0
  69. data/lib/rbcurse/core/widgets/applicationheader.rb +102 -0
  70. data/lib/rbcurse/core/widgets/box.rb +58 -0
  71. data/lib/rbcurse/core/widgets/divider.rb +310 -0
  72. data/lib/rbcurse/core/widgets/keylabelprinter.rb +178 -0
  73. data/lib/rbcurse/core/widgets/rcombo.rb +238 -0
  74. data/lib/rbcurse/core/widgets/rcontainer.rb +415 -0
  75. data/lib/rbcurse/core/widgets/rlink.rb +30 -0
  76. data/lib/rbcurse/core/widgets/rlist.rb +723 -0
  77. data/lib/rbcurse/core/widgets/rmenu.rb +939 -0
  78. data/lib/rbcurse/core/widgets/rmenulink.rb +22 -0
  79. data/lib/rbcurse/core/widgets/rmessagebox.rb +373 -0
  80. data/lib/rbcurse/core/widgets/rprogress.rb +118 -0
  81. data/lib/rbcurse/core/widgets/rtabbedpane.rb +615 -0
  82. data/lib/rbcurse/core/widgets/rtabbedwindow.rb +68 -0
  83. data/lib/rbcurse/core/widgets/rtextarea.rb +920 -0
  84. data/lib/rbcurse/core/widgets/rtextview.rb +780 -0
  85. data/lib/rbcurse/core/widgets/rtree.rb +787 -0
  86. data/lib/rbcurse/core/widgets/rwidget.rb +3040 -0
  87. data/lib/rbcurse/core/widgets/scrollbar.rb +143 -0
  88. data/lib/rbcurse/core/widgets/statusline.rb +94 -0
  89. data/lib/rbcurse/core/widgets/tabular.rb +264 -0
  90. data/lib/rbcurse/core/widgets/tabularwidget.rb +1211 -0
  91. data/lib/rbcurse/core/widgets/textpad.rb +516 -0
  92. data/lib/rbcurse/core/widgets/tree/treecellrenderer.rb +150 -0
  93. data/lib/rbcurse/core/widgets/tree/treemodel.rb +428 -0
  94. metadata +156 -0
@@ -0,0 +1,68 @@
1
+ =begin
2
+ * Name: newtabbedwindow.rb
3
+ * Description : This is a window that contains a tabbedpane (NewTabbedPane). This for situation
4
+ when you want to pop up a setup/configuration type of tabbed pane.
5
+ See examples/newtabbedwindow.rb for an example of usage, and test2.rb
6
+ which calls it from the menu (Options2 item).
7
+ In a short while, I will deprecate the existing complex TabbedPane and use this
8
+ in the lib/rbcurse dir.
9
+ * Author: rkumar (http://github.com/rkumar/rbcurse/)
10
+ * Date: 22.10.11 - 20:35
11
+ * License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
12
+ * Last update: Sat Oct 22 20:35:46 IST 2011
13
+
14
+ == CHANGES
15
+ == TODO
16
+ =end
17
+ require 'rbcurse'
18
+ require 'rbcurse/core/widgets/rtabbedpane'
19
+ require 'rbcurse/core/widgets/rcontainer'
20
+
21
+ include RubyCurses
22
+ class TabbedWindow
23
+ attr_reader :tabbed_pane
24
+ # The given block is passed to the TabbedPane
25
+ # The given dimensions are used to create the window.
26
+ # The TabbedPane is placed at 0,0 and fills the window.
27
+ def initialize config={}, &block
28
+
29
+ h = config.fetch(:height, 0)
30
+ w = config.fetch(:width, 0)
31
+ t = config.fetch(:row, 0)
32
+ l = config.fetch(:col, 0)
33
+ @window = VER::Window.new :height => h, :width => w, :top => t, :left => l
34
+ @form = Form.new @window
35
+ config[:row] = config[:col] = 0
36
+ @tabbed_pane = TabbedPane.new @form, config , &block
37
+ end
38
+ # returns button index
39
+ # Call this after instantiating the window
40
+ def run
41
+ @form.repaint
42
+ @window.wrefresh
43
+ return handle_keys
44
+ end
45
+ # returns button index
46
+ private
47
+ def handle_keys
48
+ buttonindex = catch(:close) do
49
+ while((ch = @window.getchar()) != FFI::NCurses::KEY_F10 )
50
+ break if ch == ?\C-q.getbyte(0)
51
+ begin
52
+ @form.handle_key(ch)
53
+ @window.wrefresh
54
+ rescue => err
55
+ $log.debug( err) if err
56
+ $log.debug(err.backtrace.join("\n")) if err
57
+ alert "Got an exception in NewTabbedWindow: #{err}. Check log"
58
+ $error_message.value = ""
59
+ ensure
60
+ end
61
+
62
+ end # while loop
63
+ end # close
64
+ $log.debug "XXX: CALLER GOT #{buttonindex} "
65
+ @window.destroy
66
+ return buttonindex
67
+ end
68
+ end
@@ -0,0 +1,920 @@
1
+ =begin
2
+ * Name: TextArea
3
+ * Description Editable text area
4
+ * Author: rkumar (arunachalesha)
5
+ 2009-12-26 14:43 buffered version of rtextarea.rb. See BUFFERED
6
+ * major change: 2010-02-12 13:34 simplifying the buffer stuff.
7
+ * see FIXME of textview for some common issues to look at.
8
+ * removed many edit functions to listeditable - 2010-03-12 10:16
9
+
10
+ Todo:
11
+ * shoud we store path, so a save can be done
12
+ --------
13
+ * Date: 2008-11-14 23:43
14
+ * License:
15
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
16
+
17
+ =end
18
+ require 'logger'
19
+ require 'rbcurse'
20
+ require 'rbcurse/core/include/listscrollable'
21
+ require 'rbcurse/core/include/rinputdataevent'
22
+ require 'rbcurse/core/include/listeditable'
23
+
24
+ #include Ncurses # FFI 2011-09-8
25
+ include RubyCurses
26
+ module RubyCurses
27
+ extend self
28
+
29
+ ## a multiline text editing widget
30
+ # TODO - giving data to user - adding newlines, and withog adding.
31
+ # - respect newlines for incoming data
32
+ # we need a set_text method, passing nil or blank clears
33
+ # current way is not really good. remove_all sucks.
34
+ # TODO don't set maxlen if nil. compute it as a local in methods. Else splitpane will not
35
+ # work correctly.
36
+ class TextArea < Widget
37
+ include ListScrollable
38
+ # NOTE: common editing functions moved to listeditable
39
+ include ListEditable
40
+ dsl_accessor :title
41
+ dsl_accessor :title_attrib # bold, reverse, normal
42
+ dsl_accessor :footer_attrib # bold, reverse, normal added 2009-12-26 18:25 was this missing or delib
43
+ dsl_accessor :list # the array of data to be sent by user
44
+ dsl_accessor :maxlen # max display length of a row/line
45
+ attr_reader :toprow
46
+ dsl_accessor :auto_scroll # boolean, keeps view at end as data is inserted.
47
+ dsl_accessor :print_footer
48
+ dsl_accessor :editable # allow editing
49
+ dsl_accessor :suppress_borders # added 2010-02-12 12:21 values true or false
50
+ attr_accessor :overwrite_mode # boolean: insert or overwrite, default false.
51
+
52
+ def initialize form = nil, config={}, &block
53
+ @focusable = true
54
+ @editable = true
55
+ @row = 0
56
+ @col = 0
57
+ @curpos = 0
58
+ @list = []
59
+ @suppress_borders = false
60
+ @row_offset = @col_offset = 1 # for cursor display on first entry, so not positioned on border
61
+ @_events ||= []
62
+ @_events.push :CHANGE
63
+ super
64
+ @orig_col = @col
65
+ # this does result in a blank line if we insert after creating. That's required at
66
+ # present if we wish to only insert
67
+ if @list.empty?
68
+ # @list << "\r" # removed this on 2009-02-15 17:25 lets see how it goes
69
+ end
70
+ @content_rows = @list.length
71
+ @win = @graphic # 2009-12-26 14:54 BUFFERED replace form.window with graphic
72
+ # 2010-01-10 19:35 compute locally if not set
73
+ install_keys
74
+ init_vars
75
+ end
76
+ def init_vars
77
+ @repaint_required = true
78
+ @repaint_footer_required = true # 2010-01-23 22:41
79
+ @toprow = @current_index = @pcol = 0
80
+ @repaint_all=true
81
+ ## 2010-02-12 12:20 RFED16 taking care if no border requested
82
+ @row_offset = @col_offset = 0 if @suppress_borders == true
83
+ # added 2010-02-11 15:11 RFED16 so we don't need a form.
84
+ @win_left = 0
85
+ @win_top = 0
86
+ @longest_line = 0
87
+ # if borders used, reduce 2 from width else 0
88
+ @internal_width = 2
89
+ @internal_width = 2 if @suppress_borders
90
+ bind_key(?\M-w, :kill_ring_save)
91
+ bind_key(?\C-y, :yank)
92
+ bind_key(?\M-y, :yank_pop)
93
+ bind_key(?\M-\C-w, :append_next_kill)
94
+ map_keys
95
+ end
96
+ def rowcol
97
+ # $log.debug "textarea rowcol : #{@row+@row_offset+@winrow}, #{@col+@col_offset}"
98
+ return @row+@row_offset, @col+@col_offset
99
+ end
100
+ ##
101
+ # this avoids wrapping. Better to use the <<.
102
+ def Oinsert off0, *data
103
+ @list.insert off0, *data
104
+ # fire_handler :CHANGE, self # 2008-12-09 14:56 NOT SURE
105
+ end
106
+ # private
107
+ def wrap_text(txt, col = @maxlen)
108
+ col ||= @width - @internal_width
109
+ #$log.debug "inside wrap text for :#{txt}"
110
+ txt.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/,
111
+ "\\1\\3\n")
112
+ end
113
+ ##
114
+ # trying to wrap and insert
115
+ def insert off0, data
116
+ _maxlen = @maxlen || @width - @internal_width
117
+ if data.length > _maxlen
118
+ data = wrap_text data
119
+ # $log.debug "after wrap text done :#{data}"
120
+ data = data.split("\n")
121
+ data[-1] << "\r" #XXXX
122
+ data.each do |row|
123
+ @list.insert off0, row
124
+ off0 += 1
125
+ end
126
+ else
127
+ data << "\r" if data[-1,1] != "\r" #XXXX
128
+ @list.insert off0, data
129
+ end
130
+ # expecting array !!
131
+ #data.each do |row|
132
+ #@list.insert off0, row
133
+ #off0 += 1
134
+ #end
135
+ #$log.debug " AFTER INSERT: #{@list}"
136
+ end
137
+ ##
138
+ # wraps line sent in if longer than _maxlen
139
+ # Typically a line is sent in. We wrap and put a hard return at end.
140
+ def << data
141
+ # if width if nil, either set it, or add this to a container that sets it before calling this method
142
+ _maxlen = @maxlen || @width - @internal_width
143
+ if data.length > _maxlen
144
+ #$log.debug "wrapped append for #{data}"
145
+ data = wrap_text data
146
+ #$log.debug "after wrap text for :#{data}"
147
+ data = data.split("\n")
148
+ # 2009-01-01 22:24 the \n was needed so we would put a space at time of writing.
149
+ # we need a soft return so a space can be added when pushing down.
150
+ # commented off 2008-12-28 21:59
151
+ #data.each {|line| @list << line+"\n"}
152
+ data.each {|line| @list << line}
153
+ @list[-1] << "\r" #XXXX
154
+ else
155
+ #$log.debug "normal append for #{data}"
156
+ data << "\r" if data[-1,1] != "\r" #XXXX
157
+ @list << data
158
+ end
159
+ set_modified # added 2009-03-07 18:29
160
+ goto_end if @auto_scroll
161
+ self
162
+ end
163
+ def wrap_para line=@current_index
164
+ line ||= 0
165
+ l=[]
166
+ while true
167
+ if @list[line].nil? or @list[line]=="" or @list[line]==13 #"\r"
168
+ break
169
+ end
170
+ #$log.debug "lastchar #{@list[line][-1]}, appending: #{@list[line]}]"
171
+ t = @list[line]
172
+ l << t.strip
173
+ @list.delete_at line
174
+ break if t[-1]==13 # "\r"
175
+ # line += 1
176
+ end
177
+ str=l.join(" ")
178
+ #$log.debug " sending insert : #{str}."
179
+ insert line, str
180
+ end
181
+ ##
182
+ # private
183
+ def print_borders
184
+ window = @graphic # 2009-12-26 14:54 BUFFERED
185
+ @color_pair = get_color($datacolor) # 2011-09-28 V1.3.1
186
+ bordercolor = @border_color || @color_pair
187
+ borderatt = @border_attrib || Ncurses::A_NORMAL
188
+ #color = $datacolor
189
+ #window.print_border @row, @col, @height, @width, color
190
+ window.print_border @row, @col, @height-1, @width, bordercolor, borderatt
191
+ print_title
192
+ =begin
193
+ hline = "+%s+" % [ "-"*(width-((1)*2)) ]
194
+ hline2 = "|%s|" % [ " "*(width-((1)*2)) ]
195
+ window.printstring( row=startrow, col=startcol, hline, color)
196
+ print_title
197
+ (startrow+1).upto(startrow+height-1) do |row|
198
+ window.printstring(row, col=startcol, hline2, color)
199
+ end
200
+ window.printstring(startrow+height, col=startcol, hline, color)
201
+ =end
202
+
203
+ end
204
+ # private
205
+ def print_title
206
+ # truncate title if longer than width
207
+ return unless @title
208
+ @color_pair ||= get_color($datacolor)
209
+ _title = @title
210
+ if @title.length > @width - 2
211
+ _title = @title[0..@width-2]
212
+ end
213
+ @graphic.printstring( @row, @col+(@width-_title.length)/2, _title, @color_pair, @title_attrib) unless @title.nil?
214
+ end
215
+ # text_area print footer
216
+ def print_foot
217
+ @footer_attrib ||= Ncurses::A_REVERSE
218
+ footer = "R: #{@current_index+1}, C: #{@curpos}, #{@list.length} lines "
219
+ #$log.debug " print_foot calling printstring with #{@row} + #{@height} -1, #{@col}+2"
220
+ # changed 2010-01-02 19:31 BUFFERED we were exceeding 1
221
+ #@graphic.printstring( @row + @height, @col+2, footer, $datacolor, @footer_attrib)
222
+ @graphic.printstring( @row + @height-1, @col+2, footer, @color_pair || $datacolor, @footer_attrib)
223
+ @repaint_footer_required = false
224
+ end
225
+ ### FOR scrollable ###
226
+ def get_content
227
+ @list
228
+ end
229
+ #
230
+ # sets content of textarea. I don't know why this was not existing all this while
231
+ # Name to be consistent with textview. Okay, this does not wrap the words, we assume
232
+ # its short enough. FIXME. Avoid using currently till i firm this.
233
+ # NOTE: does not wrap, and does not trigger events
234
+ # Added on 2011-10-10
235
+ # @since 1.4.0
236
+ # @param [String, Array] String is an existing filename, Array is content to be replaced
237
+ def set_content lines
238
+ case lines
239
+ when String
240
+ if File.exists? lines
241
+ lines = File.open(lines,"r").readlines
242
+ else
243
+ raise "set_content String param should be a filename"
244
+ end
245
+ when Array
246
+ else
247
+ raise "Don't know how to handle data in set_content: #{lines.class} "
248
+ end
249
+ @list.replace lines
250
+ @repaint_required = true
251
+ end
252
+ alias :text :set_content
253
+ def get_window
254
+ @graphic
255
+ end
256
+ ### FOR scrollable ###
257
+ def repaint # textarea
258
+ #return unless @repaint_required # 2010-02-12 19:08 TRYING - won't let footer print if only col move
259
+ paint if @repaint_required
260
+ print_foot if @print_footer && !@suppress_borders && (@repaint_footer_required || @repaint_required)
261
+ end
262
+ def getvalue
263
+ @list
264
+ end
265
+
266
+ def map_keys
267
+ return if @keys_mapped
268
+ bind_key(Ncurses::KEY_LEFT){ cursor_backward }
269
+ bind_key(Ncurses::KEY_RIGHT){ cursor_forward }
270
+ bind_key(Ncurses::KEY_UP){ ret = up; get_window.ungetch(KEY_BTAB) if ret == :NO_PREVIOUS_ROW }
271
+ # the next was irritating if user wanted to add a row ! 2011-10-10
272
+ #bind_key(Ncurses::KEY_DOWN){ ret = down ; get_window.ungetch(KEY_TAB) if ret == :NO_NEXT_ROW }
273
+ bind_key(Ncurses::KEY_DOWN){ ret = down ; }
274
+ bind_key(?\C-a){ cursor_bol }
275
+ bind_key(?\C-e){ cursor_eol }
276
+ bind_key(?\C-n) { scroll_forward }
277
+ bind_key(?\C-p) { scroll_backward }
278
+ bind_key(?\C-[) { goto_start }
279
+ bind_key(?\C-]) { goto_end }
280
+
281
+ bind_key(KEY_BACKSPACE){ delete_prev_char if @editable }
282
+ bind_key(KEY_BSPACE){ delete_prev_char if @editable}
283
+ bind_key(?\M-d, :delete_word)
284
+ bind_key(?\M-f, :forward_word)
285
+
286
+ #bind_key(127){ delete_prev_char }
287
+ bind_key(330){ delete_curr_char if @editable }
288
+ #bind_key(?\C-k){ delete_eol }
289
+ #bind_key(?\C-_){ undo_delete_eol }
290
+ #bind_key(27){ set_buffer @original_value }
291
+ @keys_mapped = true
292
+ end
293
+
294
+ # textarea
295
+ def handle_key ch
296
+ @current_key = ch # I need some funcs to know what key they were mapped to
297
+ @buffer = @list[@current_index]
298
+ if @buffer.nil? and @list.length == 0
299
+ ## 2009-10-04 22:39
300
+ # what this newline does is , if we use << to append, data is appended
301
+ # to second line
302
+ @list << "\n" # changed space to newline so wrapping puts a line.
303
+ @current_index = 0 ; ## added 2009-10-04 21:47
304
+ @buffer = @list[@current_index]
305
+ end
306
+ ## 2009-10-04 20:48 i think the next line was resulting in a hang if buffer nil
307
+ # in sqlc on pressing Clear.
308
+ # if buffer is nil and user wants to enter something -- added UNHANDLED
309
+ return :UNHANDLED if @buffer.nil?
310
+ #$log.debug "TA: before: curpos #{@curpos} blen: #{@buffer.length}"
311
+ # on any line if the cursor is ahead of buffer length, ensure its on last position
312
+ # what if the buffer is somehow gt maxlen ??
313
+ if @curpos > @buffer.length
314
+ addcol(@buffer.length-@curpos)+1
315
+ @curpos = @buffer.length
316
+ end
317
+ #$log.debug "TA: after : curpos #{@curpos} blen: #{@buffer.length}, w: #{@width} max #{@maxlen}"
318
+
319
+ case ch
320
+ when KEY_ENTER, 10, KEY_RETURN
321
+ insert_break
322
+ when Ncurses.KEY_BACKSPACE, Ncurses.KEY_BSPACE
323
+ if @editable # checking here means that i can programmatically bypass!!
324
+ delete_prev_char
325
+ end
326
+ when Ncurses.KEY_DELETE, ?\C-d.getbyte(0) # delete char
327
+ if @editable
328
+ delete_curr_char
329
+ end
330
+ when ?\C-k.getbyte(0) # delete till eol
331
+ # i'ved added curpos == 0 since emacs deletes a line if cursor is at 0
332
+ # Earlier behavior was based on alpine which leaves a blank line
333
+ if @editable
334
+ #if @buffer == ""
335
+ if @buffer.chomp == "" || @curpos == 0
336
+ delete_line
337
+ else
338
+ delete_eol
339
+ end
340
+ end
341
+ #when ?\C-u.getbyte(0)
342
+ ## since textareas are editable we use a control key to increase
343
+ ## multiplier. Series is 4 16 64
344
+ #@multiplier = (@multiplier == 0 ? 4 : @multiplier *= 4)
345
+ #return 0
346
+ when ?\C-_.getbyte(0) # changed from C-u so i can use C-u for multipliers
347
+ undo
348
+ when ?\C-r.getbyte(0) # redo if UndoHandler installed
349
+ text_redo # won't accept name redo
350
+ #when @KEY_ASK_FIND_FORWARD
351
+ # ask_search_forward
352
+ #when @KEY_ASK_FIND_BACKWARD
353
+ # ask_search_backward
354
+ when @KEY_ASK_FIND
355
+ ask_search
356
+ when @KEY_FIND_MORE
357
+ find_more
358
+ #when @KEY_FIND_NEXT
359
+ # find_next
360
+ #when @KEY_FIND_PREV
361
+ # find_prev
362
+ else
363
+ #$log.debug(" textarea ch #{ch}")
364
+ ret = putc ch
365
+ if ret == :UNHANDLED
366
+ # check for bindings, these cannot override above keys since placed at end
367
+ ret = process_key ch, self
368
+ #$log.debug "TA process_key #{ch} got ret #{ret} in #{@name} "
369
+ return :UNHANDLED if ret == :UNHANDLED
370
+ end
371
+ end
372
+ set_form_row
373
+ set_form_col # testing 2008-12-26 19:37
374
+ $multiplier = 0 # reset only if key handled
375
+ return 0
376
+ end
377
+ # this is broken, delete_buffer could be a line or a string or array of lines
378
+ def undo_delete
379
+ # added 2008-11-27 12:43 paste delete buffer into insertion point
380
+ return if @delete_buffer.nil?
381
+ $log.warn "undo_delete is broken! perhaps cannot be used . textarea 347 "
382
+ # FIXME - can be an array
383
+ case @delete_buffer
384
+ when Array
385
+ # we need to unroll array, and it could be lines not just a string
386
+ str = @delete_buffer.first
387
+ else
388
+ str = @delete_buffer
389
+ end
390
+ @buffer.insert @curpos, str
391
+ set_modified
392
+ fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT, @current_index, @delete_buffer) # 2008-12-24 18:34
393
+ end
394
+ # FIXME - fire event not correct, not undo'ing correctly, check row and also slash r append
395
+ def insert_break
396
+ return -1 unless @editable
397
+ # insert a blank row and append rest of this line to cursor
398
+ $log.debug "ENTER PRESSED at #{@curpos}, on row #{@current_index}"
399
+ @delete_buffer = (delete_eol || "")
400
+ @list[@current_index] << "\r"
401
+ $log.debug "DELETE BUFFER #{@delete_buffer}"
402
+ @list.insert @current_index+1, @delete_buffer
403
+ @curpos = 0
404
+ down
405
+ col = @orig_col + @col_offset
406
+ setrowcol @row+1, col
407
+ # FIXME maybe this should be insert line since line inserted, not just data, undo will delete it
408
+ fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT_LINE, @current_index, @delete_buffer) # 2008-12-24 18:34
409
+ end
410
+ # set cursor on correct column
411
+ def set_form_col col1=@curpos
412
+ @curpos = col1
413
+ @cols_panned ||= 0
414
+ cursor_bounds_check
415
+
416
+ ## added win_col on 2009-12-28 20:21 for embedded forms BUFFERED TRYING OUT
417
+ win_col = 0 # 2010-02-07 23:19 new cursor stuff
418
+ #col = win_col + @orig_col + @col_offset + @curpos
419
+ #col = win_col + @orig_col + @col_offset + @curpos + @cols_panned
420
+ # 2010-01-14 13:31 changed orig_col to col for embedded forms, splitpanes.
421
+ col = win_col + @col + @col_offset + @curpos + @cols_panned
422
+ $log.debug "sfc: wc:#{win_col} col:#{@col}, coff:#{@col_offset}. cp:#{@curpos} colsp:#{@cols_panned} . "
423
+ #@form.setrowcol @form.row, col # added 2009-12-29 18:50 BUFFERED
424
+ $log.debug " TA calling setformrow col nil, #{col} "
425
+ setrowcol nil, col # added 2009-12-29 18:50 BUFFERED
426
+ @repaint_footer_required = true
427
+ end
428
+ def cursor_bounds_check
429
+ max = buffer_len()
430
+ @curpos = max if @curpos > max # check 2008-12-27 00:02
431
+ end
432
+ def buffer_len
433
+ @list[@current_index].nil? ? 0 : @list[@current_index].chomp().length
434
+ end
435
+ def do_current_row # :yields current row
436
+ yield @list[@current_index]
437
+ @buffer = @list[@current_index]
438
+ end
439
+ ##
440
+ # FIXME : if cursor at end of last line then forward takes cursor to start
441
+ # of last line (same line), should stop there.
442
+ def cursor_forward num=1
443
+ #$log.debug "next char cp #{@curpos}, #{@buffer.length}. wi: #{@width}"
444
+ #$log.debug "next char cp ll and ci #{@list.length}, #{@current_index}"
445
+ #if @curpos < @width and @curpos < maxlen-1 # else it will do out of box
446
+ return if at_eol? and at_last_line?
447
+ repeatm {
448
+ if @curpos < buffer_len()
449
+ @curpos += 1
450
+ addcol 1
451
+ else # trying this out 2008-12-26 20:18
452
+ @curpos = 0
453
+ down 1 # if not then multipler will trigger there too
454
+ end
455
+ cursor_bounds_check
456
+ }
457
+ end
458
+ ## added 2009-10-04 22:13
459
+ # returns whether cursor is at end of line
460
+ def at_eol?
461
+ if @curpos+1== @list[@current_index].length
462
+ return true
463
+ end
464
+ return false
465
+ end
466
+ ## added 2009-10-04 22:13
467
+ # returns whether at last line (required so that forward does not go to start)
468
+ def at_last_line?
469
+ return true if @list.length == @current_index + 1
470
+ return false
471
+ end
472
+ # FIXME : these 2 only require the footer to be repainted not everything
473
+ # We should be able to manage that. We need a repaint_footer_required.
474
+ # Setting repaint_required really slows performance when one presses the right arrow key
475
+ # since a repaint is happenign repeatedly for each key.
476
+ def addcol num
477
+ # @repaint_required = true # added 2010-01-15 23:59, so that footer is updated, sucks!
478
+ @repaint_footer_required = true # 2010-01-23 22:41
479
+ my_win = @form || @parent_component.form # 2010-02-12 12:51
480
+ my_win.addcol num
481
+ end
482
+ def addrowcol row,col
483
+ #@repaint_required = true # added 2010-01-15 23:59
484
+ @repaint_footer_required = true # 2010-01-23 22:41
485
+ my_win = @form || @parent_component.form # 2010-02-12 12:51
486
+ my_win.addrowcol row, col
487
+ end
488
+ ## 2009-10-04 23:01 taken care that you can't go back at start of textarea
489
+ # it was going onto border
490
+ def cursor_backward
491
+ #$log.debug "back char cp ll and ci #{@list.length}, #{@current_index}"
492
+ #$log.debug "back char cb #{@curpos}, #{@buffer.length}. wi: #{@width}"
493
+ return if @curpos == 0 and @current_index == 0 # added 2009-10-04 23:02
494
+ repeatm {
495
+ if @curpos > 0
496
+ @curpos -= 1
497
+ addcol -1
498
+ else # trying this out 2008-12-26 20:18
499
+ ret = up
500
+ cursor_eol if ret != -1
501
+ end
502
+ }
503
+ end
504
+ # private
505
+ # when backspace pressed in position zero if the previous line is filled we may have to bring
506
+ # down the last word and join, rather than go up
507
+ # FIXME : make logic simple. Append entire line to above line. Then go to maxlen if not a space,
508
+ # reverse to find last space. Lop off all after space and replace this line with that balance.
509
+ # UNDO and REDO has to work in this case too. FIXME bare in mind handlers when doing this
510
+ def join_to_prev_line
511
+ return -1 unless @editable
512
+ return if @current_index == 0
513
+ oldcurpos = @curpos
514
+ oldprow = @current_index
515
+ prev = @list[@current_index-1].chomp
516
+ prevlen = prev.length
517
+ # 2008-12-26 21:37 delete previous line if nothing there. This moves entire buffer up.
518
+ if prevlen == 0
519
+ delete_line @current_index-1
520
+ up
521
+ return
522
+ end
523
+ _maxlen = @maxlen || @width - @internal_width
524
+ space_left = _maxlen - prevlen
525
+ # prev line is full exit
526
+ return if space_left == 0
527
+
528
+ # get last space, if none, return
529
+ blank_found = @buffer.rindex(' ', space_left)
530
+ return unless blank_found # no word in the space i can carry up.
531
+ # get string for carrying up
532
+ carry_up = @buffer[0..blank_found]
533
+ result = @list[@current_index-1].chomp! # this has to be undone too.
534
+ @list[@current_index-1] << carry_up
535
+ #$log.debug "carry up: #{carry_up} prevrow:#{@list[@current_index -1]}"
536
+ # remove from curr line
537
+ @list[@current_index].slice!(0..carry_up.length-1)
538
+ $log.debug "carry up: #{carry_up} currrow:#{@list[@current_index]}"
539
+ #@list[@current_index] ||= ""
540
+ up
541
+ addrowcol -1,0
542
+ @curpos = prevlen
543
+ # if result not nil, then we need that to be recorded FIXME
544
+ fire_handler :CHANGE, InputDataEvent.new(oldcurpos,oldcurpos+carry_up.length, self, :DELETE, oldprow, carry_up)
545
+ fire_handler :CHANGE, InputDataEvent.new(prevlen,prevlen+carry_up.length, self, :INSERT, oldprow-1, carry_up)
546
+
547
+ ## BUG. carry full words up, or if no space then bring down last word of prev lien and join with first
548
+ #carry_up = words_in_length @buffer, space_left #@buffer[0..space_left] # XXX
549
+ #if carry_up.nil?
550
+ ## carry down last word
551
+ #prev_wd = remove_last_word @current_index-1
552
+ ## 2010-01-14 18:26 check added else crashing if C-h pressed with no data in line
553
+ #if !prev_wd.nil?
554
+ #@buffer.insert 0, prev_wd
555
+ #@curpos = prev_wd.length
556
+ #$log.debug " carry up nil! prev_wd (#{prev_wd}) len:#{prev_wd.length}"
557
+ #fire_handler :CHANGE, InputDataEvent.new(0,prev_wd.length, self, :INSERT, oldprow, prev_wd) # 2008-12-26 23:07
558
+ #end
559
+ #else
560
+ #$log.debug " carrying up #{carry_up.length} #{carry_up}, space: #{space_left}"
561
+ #@list[@current_index-1]=prev + carry_up
562
+ #space_left2 = @buffer[(carry_up.length+1)..-1]
563
+ #@list[@current_index]=space_left2 #if !space_left2.nil?
564
+ #@list[@current_index] ||= ""
565
+ #up
566
+ #addrowcol -1,0
567
+ #@curpos = prevlen
568
+ #fire_handler :CHANGE, InputDataEvent.new(oldcurpos,carry_up.length, self, :DELETE, oldprow, carry_up) # 2008-12-24 18:34
569
+ #fire_handler :CHANGE, InputDataEvent.new(prevlen,carry_up.length, self, :INSERT, oldprow-1, carry_up) # 2008-12-24 18:34
570
+ #end
571
+ ## FIXME -- can;t have a naked for reference here.
572
+ ##@form.col = @orig_col + @col_offset + @curpos
573
+ col1 = @orig_col + @col_offset + @curpos
574
+ setrowcol nil, col1 # 2010-02-12 13:09 RFED16
575
+
576
+ # $log.debug "carry up: nil" if carry_up.nil?
577
+ # $log.debug "listrow nil " if @list[@current_index].nil?
578
+ # $log.debug "carry up: #{carry_up} prow:#{@list[@current_index]}"
579
+ end
580
+ # private
581
+ # when backspace pressed in position zero if the previous line is filled we may have to bring
582
+ # down the last word and join, rather than go up
583
+ # FIXME : make logic simple. Append entire line to above line. Then go to maxlen if not a space,
584
+ # reverse to find last space. Lop off all after space and replace this line with that balance.
585
+ # UNDO and REDO has to work in this case too. FIXME bare in mind handlers when doing this
586
+ def old_join_to_prev_line
587
+ return -1 unless @editable
588
+ return if @current_index == 0
589
+ oldcurpos = @curpos
590
+ oldprow = @current_index
591
+ prev = @list[@current_index-1].chomp
592
+ prevlen = prev.length
593
+ # 2008-12-26 21:37 delete previous line if nothing there. This moves entire buffer up.
594
+ if prevlen == 0
595
+ delete_line @current_index-1
596
+ up
597
+ return
598
+ end
599
+ _maxlen = @maxlen || @width - @internal_width
600
+ space_left = _maxlen - prev.length
601
+ # BUG. carry full words up, or if no space then bring down last word of prev lien and join with first
602
+ carry_up = words_in_length @buffer, space_left #@buffer[0..space_left] # XXX
603
+ if carry_up.nil?
604
+ # carry down last word
605
+ prev_wd = remove_last_word @current_index-1
606
+ # 2010-01-14 18:26 check added else crashing if C-h pressed with no data in line
607
+ if !prev_wd.nil?
608
+ @buffer.insert 0, prev_wd
609
+ @curpos = prev_wd.length
610
+ $log.debug " carry up nil! prev_wd (#{prev_wd}) len:#{prev_wd.length}"
611
+ fire_handler :CHANGE, InputDataEvent.new(0,prev_wd.length, self, :INSERT, oldprow, prev_wd) # 2008-12-26 23:07
612
+ end
613
+ else
614
+ $log.debug " carrying up #{carry_up.length} #{carry_up}, space: #{space_left}"
615
+ @list[@current_index-1]=prev + carry_up
616
+ space_left2 = @buffer[(carry_up.length+1)..-1]
617
+ @list[@current_index]=space_left2 #if !space_left2.nil?
618
+ @list[@current_index] ||= ""
619
+ up
620
+ addrowcol -1,0
621
+ @curpos = prevlen
622
+ fire_handler :CHANGE, InputDataEvent.new(oldcurpos,carry_up.length, self, :DELETE, oldprow, carry_up) # 2008-12-24 18:34
623
+ fire_handler :CHANGE, InputDataEvent.new(prevlen,carry_up.length, self, :INSERT, oldprow-1, carry_up) # 2008-12-24 18:34
624
+ end
625
+ # FIXME -- can;t have a naked for reference here.
626
+ #@form.col = @orig_col + @col_offset + @curpos
627
+ col1 = @orig_col + @col_offset + @curpos
628
+ setrowcol nil, col1 # 2010-02-12 13:09 RFED16
629
+
630
+ # $log.debug "carry up: nil" if carry_up.nil?
631
+ # $log.debug "listrow nil " if @list[@current_index].nil?
632
+ # $log.debug "carry up: #{carry_up} prow:#{@list[@current_index]}"
633
+ end
634
+ ##
635
+ # return as many words as fit into len for carrying up..
636
+ # actually there is a case of when the next char (len+1) is a white space or word boundary. XXX
637
+ def words_in_length buff, len
638
+ return nil if len == 0
639
+ str = buff[0..len]
640
+ ix = str.rindex(/\s/)
641
+ $log.debug " str #{str} len #{len} ix #{ix} , buff #{buff}~"
642
+ return nil if ix.nil?
643
+ ix = ix > 0 ? ix - 1 : ix
644
+ $log.debug " str[]:#{str[0..ix]}~ len #{len} ix #{ix} , buff #{buff}~"
645
+ return str[0..ix]
646
+ end
647
+ # push the last word from given line to next
648
+ # I have modified it to push all words that are exceeding maxlen.
649
+ # This was needed for if i push 10 chars to next line, and the last word is less then the line will
650
+ # exceed. So i must push as many words as exceed length.
651
+ # 2010-09-07 22:31 this must not return nil, or previous will crash. This happens if no space in line.
652
+ def push_last_word lineno=@current_index
653
+ _maxlen = @maxlen || @width - @internal_width
654
+ #lastspace = @buffer.rindex(" ")
655
+ #lastspace = @list[lineno].rindex(/ \w/)
656
+ line = @list[lineno]
657
+ line = @list[lineno][0.._maxlen+1] if line.length > _maxlen
658
+ lastspace = line.rindex(/ \w/)
659
+ $log.debug " PUSH:2 #{lastspace},#{line},"
660
+ # fix to ensure something returned 2010-09-07 22:40
661
+ lastspace = _maxlen-1 unless lastspace # added 2010-09-07 22:29 XXXX
662
+
663
+ if !lastspace.nil?
664
+ lastchars = @list[lineno][lastspace+1..-1]
665
+ @list[lineno] = @list[lineno][0..lastspace]
666
+ $log.debug "PUSH_LAST:ls:#{lastspace},lw:#{lastchars},lc:#{lastchars[-1]},:#{@list[lineno]}$"
667
+ if lastchars[-1,1] == "\r" or @list[lineno+1].nil?
668
+ # open a new line and keep the 10 at the end.
669
+ append_row lineno, lastchars
670
+ else
671
+ # check for soft tab \n - NO EVEN THIS LOGIC IS WRONG.
672
+ #if lastchars[-1,1] == "\n"
673
+ if lastchars[-1,1] != ' ' and @list[lineno+1][0,1] !=' '
674
+ #@list[lineno+1].insert 0, lastchars + ' '
675
+ insert_wrap lineno+1, 0, lastchars + ' '
676
+ else
677
+ #@list[lineno+1].insert 0, lastchars
678
+ insert_wrap lineno+1, 0, lastchars
679
+ end
680
+ end
681
+ return lastchars, lastspace
682
+ end
683
+ return nil
684
+ end
685
+ ##
686
+ # this attempts to recursively insert into a row, seeing that any stuff exceeding is pushed down further.
687
+ # Yes, it should check for a para end and insert. Currently it could add to next para.
688
+ def insert_wrap lineno, pos, lastchars
689
+ _maxlen = @maxlen || @width - @internal_width
690
+ @list[lineno].insert pos, lastchars
691
+ len = @list[lineno].length
692
+ if len > _maxlen
693
+ push_last_word lineno #- sometime i may push down 10 chars but the last word is less
694
+ end
695
+ end
696
+ ##
697
+ # add one char. careful, i shoved a string in yesterday.
698
+ def putch char
699
+ _maxlen = @maxlen || @width - @internal_width
700
+ @buffer ||= @list[@current_index]
701
+ return -1 if !@editable #or @buffer.length >= _maxlen
702
+ #if @chars_allowed != nil # remove useless functionality
703
+ #return if char.match(@chars_allowed).nil?
704
+ #end
705
+ raise "putch expects only one char" if char.length != 1
706
+ oldcurpos = @curpos
707
+ #$log.debug "putch : pr:#{@current_index}, cp:#{@curpos}, char:#{char}, lc:#{@buffer[-1]}, buf:(#{@buffer})"
708
+ if @overwrite_mode
709
+ @buffer[@curpos] = char
710
+ else
711
+ @buffer.insert(@curpos, char)
712
+ end
713
+ @curpos += 1
714
+ #$log.debug "putch INS: cp:#{@curpos}, max:#{_maxlen}, buf:(#{@buffer.length})"
715
+ if @curpos-1 > _maxlen or @buffer.length()-1 > _maxlen
716
+ lastchars, lastspace = push_last_word @current_index
717
+ #$log.debug "last sapce #{lastspace}, lastchars:#{lastchars},lc:#{lastchars[-1]}, #{@list[@current_index]} "
718
+ ## wrap on word XX If last char is 10 then insert line
719
+ @buffer = @list[@current_index]
720
+ if @curpos-1 > _maxlen or @curpos-1 > @buffer.length()-1
721
+ ret = down
722
+ # keep the cursor in the same position in the string that was pushed down.
723
+ @curpos = oldcurpos - lastspace #lastchars.length # 0
724
+ end
725
+ end
726
+ set_form_row
727
+ @buffer = @list[@current_index]
728
+ set_form_col
729
+ @modified = true
730
+ fire_handler :CHANGE, InputDataEvent.new(oldcurpos,@curpos, self, :INSERT, @current_index, char) # 2008-12-24 18:34
731
+ @repaint_required = true
732
+ 0
733
+ end
734
+ # removes and returns last word in given line number, or nil if no whitespace
735
+ def remove_last_word lineno
736
+ @list[lineno].chomp!
737
+ line=@list[lineno]
738
+ lastspace = line.rindex(" ")
739
+ if !lastspace.nil?
740
+ lastchars = line[lastspace+1..-1]
741
+ @list[lineno].slice!(lastspace..-1)
742
+ $log.debug " remove_last: lastspace #{lastspace},#{lastchars},#{@list[lineno]}"
743
+ fire_handler :CHANGE, InputDataEvent.new(lastspace,lastchars.length, self, :DELETE, lineno, lastchars) # 2008-12-26 23:06
744
+ return lastchars
745
+ end
746
+ return nil
747
+ end
748
+
749
+ def putc c
750
+ if c >= 32 and c <= 126
751
+ begin
752
+ ret = putch c.chr
753
+ rescue => ex
754
+ # this does not prevent entry, it prevents updating
755
+ # often comes here if error in event block, not our fault
756
+ Ncurses.beep
757
+ $log.debug " ERROR IN PUTCH RTEXTAREA "
758
+ $log.debug( ex) if ex
759
+ $log.debug(ex.backtrace.join("\n")) if ex
760
+ end
761
+ if ret == 0
762
+ # addcol 1
763
+ set_modified
764
+ return 0
765
+ end
766
+ end
767
+ return :UNHANDLED
768
+ end
769
+ # move up one char from next row to current, used when deleting in a line
770
+ # should not be called if line ends in "\r"
771
+ def move_char_up
772
+ @list[@current_index] << @list[@current_index+1].slice!(0)
773
+ delete_line(@current_index+1) if next_line().length==0
774
+ end
775
+ # tries to move up as many as possible
776
+ # should not be called if line ends in "\r"
777
+ def move_chars_up
778
+ oldprow = @current_index
779
+ oldcurpos = @curpos
780
+ _maxlen = @maxlen || @width - @internal_width
781
+ space_left = _maxlen - @buffer.length
782
+ can_move = [space_left, next_line.length].min
783
+ carry_up = @list[@current_index+1].slice!(0, can_move)
784
+ @list[@current_index] << carry_up
785
+ delete_line(@current_index+1) if next_line().length==0
786
+ fire_handler :CHANGE, InputDataEvent.new(oldcurpos,oldcurpos+can_move, self, :INSERT, oldprow, carry_up) # 2008-12-24 18:34
787
+ end
788
+ ## returns next line, does not move to it,
789
+ def next_line
790
+ @list[@current_index+1]
791
+ end
792
+ def current_line
793
+ @list[@current_index]
794
+ end
795
+ def do_relative_row num
796
+ yield @list[@current_index+num]
797
+ end
798
+ def set_modified tf=true
799
+ @modified = tf
800
+ @repaint_required = tf
801
+ @repaint_footer_required = tf
802
+ # 2010-01-14 22:45 putting a check for form, so not necessary to have form set when appending data
803
+ @form.modified = true if tf and !@form.nil?
804
+ end
805
+ def cursor_eol
806
+ _maxlen = @maxlen || @width - @internal_width
807
+ $log.error "ERROR !!! bufferlen gt _maxlen #{@buffer.length}, #{_maxlen}" if @buffer.length > _maxlen
808
+ set_form_col current_line().chomp().length() #-1 needs to be one ahead 2011-10-10 TRYING OUT XXX
809
+ end
810
+ def cursor_bol
811
+ set_form_col 0
812
+ end
813
+ #def to_s this was just annoying in debugs
814
+ def get_text
815
+ l = getvalue
816
+ str = ""
817
+ old = " "
818
+ l.each_with_index do |line, i|
819
+ tmp = line.gsub("\n","")
820
+ tmp.gsub!("\r", "\n")
821
+ if old[-1,1] !~ /\s/ and tmp[0,1] !~ /\s/
822
+ str << " "
823
+ end
824
+ str << tmp
825
+ old = tmp
826
+ end
827
+ str
828
+ end
829
+ #alias :get_text :to_s
830
+ ## ---- for listscrollable ---- ##
831
+ def scrollatrow
832
+ if @suppress_borders
833
+ @height - 1
834
+ else
835
+ @height - 3
836
+ end
837
+ end
838
+ def row_count
839
+ @list.size
840
+ end
841
+ def paint
842
+ # not sure where to put this, once for all or repeat 2010-02-12 RFED16
843
+ #my_win = @form? @form.window : @target_window
844
+ #$log.warn "neither form not target window given!!! TA paint 751" unless my_win
845
+ raise "Height or width nil h:#{@height} , w: #{@width} " if @height.nil? || @width.nil?
846
+ print_borders if (@suppress_borders == false && @repaint_all) # do this once only, unless everything changes
847
+ rc = row_count
848
+ _maxlen = @maxlen || @width-@internal_width # TODO fix in other branches remove ||=
849
+ $log.debug " #{@name} textarea repaint width is #{@width}, height is #{@height} , maxlen #{_maxlen}/ #{@maxlen}, #{@graphic.name} "
850
+ tm = get_content
851
+ tr = @toprow
852
+ acolor = get_color $datacolor
853
+ h = scrollatrow()
854
+ r,c = rowcol
855
+ @longest_line = @width # _maxlen scroll uses width not maxlen
856
+ $log.debug " TA:::: #{tr} , #{h}, r #{r} c #{c} "
857
+ 0.upto(h) do |hh|
858
+ crow = tr+hh
859
+ if crow < rc
860
+ #focussed = @current_index == crow ? true : false
861
+ #selected = is_row_selected crow
862
+ content = tm[crow].chomp rescue ""
863
+ content.gsub!(/\t/, ' ') # don't display tab
864
+ content.gsub!(/[^[:print:]]/, '') # don't display non print characters
865
+ if !content.nil?
866
+ if content.length > _maxlen # only show _maxlen
867
+ @longest_line = content.length if content.length > @longest_line
868
+ content = content[@pcol..@pcol+_maxlen-1]
869
+ else
870
+ content = content[@pcol..-1]
871
+ end
872
+ end
873
+ #renderer = get_default_cell_renderer_for_class content.class.to_s
874
+ #renderer = cell_renderer()
875
+ #renderer.repaint @form.window, r+hh, c+(colix*11), content, focussed, selected
876
+ #renderer.repaint @form.window, r+hh, c, content, focussed, selected
877
+ @graphic.printstring r+hh, c, "%-*s" % [@width-@internal_width,content], acolor, @attr
878
+ if @search_found_ix == tr+hh
879
+ if !@find_offset.nil?
880
+ @graphic.mvchgat(y=r+hh, x=c+@find_offset, @find_offset1-@find_offset, Ncurses::A_NORMAL, $reversecolor, nil)
881
+ end
882
+ end
883
+
884
+ else
885
+ # clear rows
886
+ # TODO the spaces string can be stored once outside loop
887
+ @graphic.printstring r+hh, c, " " * (@width-@internal_width), acolor,@attr
888
+ end
889
+ end
890
+ show_caret_func
891
+
892
+ @table_changed = false
893
+ @repaint_required = false
894
+ @repaint_footer_required = true # 2010-01-23 22:41
895
+ @repaint_all = false # added 2010-01-14 for redrawing everything
896
+ end
897
+ def ask_search_forward
898
+ regex = get_string("Enter regex to search", 20, @last_regex||"")
899
+ ix = _find_next regex, @current_index
900
+ if ix.nil?
901
+ alert("No matching data for: #{regex}")
902
+ else
903
+ set_focus_on(ix)
904
+ set_form_col @find_offset
905
+ end
906
+ end
907
+ def undo
908
+ if @undo_handler
909
+ @undo_handler.undo
910
+ else
911
+ undo_delete
912
+ end
913
+ end
914
+ def text_redo
915
+ return unless @undo_handler
916
+ @undo_handler.redo
917
+ end
918
+ end # class textarea
919
+ ##
920
+ end # modul