rbhex-core 1.0.0

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