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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/CHANGELOG +2000 -0
- data/LICENSE +56 -0
- data/README.md +44 -0
- data/examples/abasiclist.rb +179 -0
- data/examples/alpmenu.rb +50 -0
- data/examples/app.sample +19 -0
- data/examples/atree.rb +100 -0
- data/examples/bline.rb +136 -0
- data/examples/common/file.rb +45 -0
- data/examples/data/README.markdown +9 -0
- data/examples/data/brew.txt +38 -0
- data/examples/data/color.2 +37 -0
- data/examples/data/gemlist.txt +60 -0
- data/examples/data/lotr.txt +12 -0
- data/examples/data/ports.txt +136 -0
- data/examples/data/table.txt +37 -0
- data/examples/data/tasks.csv +88 -0
- data/examples/data/tasks.txt +27 -0
- data/examples/data/todo.txt +10 -0
- data/examples/data/todo.txt.bak +10 -0
- data/examples/data/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +502 -0
- data/examples/dirtree.rb +94 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +146 -0
- data/examples/tasks.rb +178 -0
- data/examples/term2.rb +84 -0
- data/examples/testbuttons.rb +296 -0
- data/examples/testcombo.rb +102 -0
- data/examples/testfields.rb +195 -0
- data/examples/testkeypress.rb +72 -0
- data/examples/testlistbox.rb +170 -0
- data/examples/testmessagebox.rb +140 -0
- data/examples/testprogress.rb +116 -0
- data/examples/testree.rb +106 -0
- data/examples/testwsshortcuts.rb +66 -0
- data/examples/testwsshortcuts2.rb +128 -0
- data/lib/rbhex.rb +6 -0
- data/lib/rbhex/core/docs/index.txt +73 -0
- data/lib/rbhex/core/include/action.rb +80 -0
- data/lib/rbhex/core/include/actionmanager.rb +49 -0
- data/lib/rbhex/core/include/appmethods.rb +214 -0
- data/lib/rbhex/core/include/bordertitle.rb +48 -0
- data/lib/rbhex/core/include/chunk.rb +203 -0
- data/lib/rbhex/core/include/io.rb +553 -0
- data/lib/rbhex/core/include/listbindings.rb +74 -0
- data/lib/rbhex/core/include/listcellrenderer.rb +140 -0
- data/lib/rbhex/core/include/listeditable.rb +317 -0
- data/lib/rbhex/core/include/listscrollable.rb +663 -0
- data/lib/rbhex/core/include/listselectable.rb +271 -0
- data/lib/rbhex/core/include/multibuffer.rb +83 -0
- data/lib/rbhex/core/include/orderedhash.rb +77 -0
- data/lib/rbhex/core/include/ractionevent.rb +73 -0
- data/lib/rbhex/core/include/rchangeevent.rb +27 -0
- data/lib/rbhex/core/include/rhistory.rb +95 -0
- data/lib/rbhex/core/include/rinputdataevent.rb +47 -0
- data/lib/rbhex/core/include/vieditable.rb +172 -0
- data/lib/rbhex/core/include/widgetmenu.rb +66 -0
- data/lib/rbhex/core/system/colormap.rb +165 -0
- data/lib/rbhex/core/system/keyboard.rb +150 -0
- data/lib/rbhex/core/system/keydefs.rb +30 -0
- data/lib/rbhex/core/system/ncurses.rb +236 -0
- data/lib/rbhex/core/system/panel.rb +162 -0
- data/lib/rbhex/core/system/window.rb +913 -0
- data/lib/rbhex/core/util/ansiparser.rb +119 -0
- data/lib/rbhex/core/util/app.rb +1228 -0
- data/lib/rbhex/core/util/basestack.rb +410 -0
- data/lib/rbhex/core/util/bottomline.rb +1859 -0
- data/lib/rbhex/core/util/colorparser.rb +77 -0
- data/lib/rbhex/core/util/focusmanager.rb +31 -0
- data/lib/rbhex/core/util/padreader.rb +192 -0
- data/lib/rbhex/core/util/rcommandwindow.rb +604 -0
- data/lib/rbhex/core/util/rdialogs.rb +574 -0
- data/lib/rbhex/core/util/viewer.rb +149 -0
- data/lib/rbhex/core/util/widgetshortcuts.rb +506 -0
- data/lib/rbhex/core/version.rb +5 -0
- data/lib/rbhex/core/widgets/applicationheader.rb +103 -0
- data/lib/rbhex/core/widgets/box.rb +58 -0
- data/lib/rbhex/core/widgets/divider.rb +310 -0
- data/lib/rbhex/core/widgets/keylabelprinter.rb +194 -0
- data/lib/rbhex/core/widgets/rcombo.rb +253 -0
- data/lib/rbhex/core/widgets/rcontainer.rb +415 -0
- data/lib/rbhex/core/widgets/rlink.rb +30 -0
- data/lib/rbhex/core/widgets/rlist.rb +696 -0
- data/lib/rbhex/core/widgets/rmenu.rb +958 -0
- data/lib/rbhex/core/widgets/rmenulink.rb +22 -0
- data/lib/rbhex/core/widgets/rmessagebox.rb +387 -0
- data/lib/rbhex/core/widgets/rprogress.rb +118 -0
- data/lib/rbhex/core/widgets/rtabbedpane.rb +634 -0
- data/lib/rbhex/core/widgets/rtabbedwindow.rb +70 -0
- data/lib/rbhex/core/widgets/rtextarea.rb +960 -0
- data/lib/rbhex/core/widgets/rtextview.rb +739 -0
- data/lib/rbhex/core/widgets/rtree.rb +768 -0
- data/lib/rbhex/core/widgets/rwidget.rb +3277 -0
- data/lib/rbhex/core/widgets/scrollbar.rb +143 -0
- data/lib/rbhex/core/widgets/statusline.rb +113 -0
- data/lib/rbhex/core/widgets/tabular.rb +264 -0
- data/lib/rbhex/core/widgets/tabularwidget.rb +1142 -0
- data/lib/rbhex/core/widgets/textpad.rb +995 -0
- data/lib/rbhex/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/rbhex/core/widgets/tree/treemodel.rb +428 -0
- data/rbhex-core.gemspec +32 -0
- 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
|