rbcurse-core 0.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.
- data/README.md +69 -0
- data/VERSION +1 -0
- data/examples/abasiclist.rb +151 -0
- data/examples/alpmenu.rb +46 -0
- data/examples/app.sample +17 -0
- data/examples/atree.rb +100 -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/todocsv.csv +28 -0
- data/examples/data/unix1.txt +21 -0
- data/examples/data/unix2.txt +11 -0
- data/examples/dbdemo.rb +487 -0
- data/examples/dirtree.rb +90 -0
- data/examples/newtabbedwindow.rb +100 -0
- data/examples/newtesttabp.rb +92 -0
- data/examples/tabular.rb +132 -0
- data/examples/tasks.rb +167 -0
- data/examples/term2.rb +83 -0
- data/examples/testkeypress.rb +72 -0
- data/examples/testlistbox.rb +158 -0
- data/examples/testmessagebox.rb +140 -0
- data/examples/testree.rb +106 -0
- data/examples/testwsshortcuts.rb +66 -0
- data/examples/testwsshortcuts2.rb +127 -0
- data/lib/rbcurse.rb +8 -0
- data/lib/rbcurse/core/docs/index.txt +73 -0
- data/lib/rbcurse/core/include/action.rb +40 -0
- data/lib/rbcurse/core/include/appmethods.rb +112 -0
- data/lib/rbcurse/core/include/bordertitle.rb +41 -0
- data/lib/rbcurse/core/include/chunk.rb +182 -0
- data/lib/rbcurse/core/include/io.rb +953 -0
- data/lib/rbcurse/core/include/listcellrenderer.rb +140 -0
- data/lib/rbcurse/core/include/listeditable.rb +317 -0
- data/lib/rbcurse/core/include/listscrollable.rb +590 -0
- data/lib/rbcurse/core/include/listselectable.rb +264 -0
- data/lib/rbcurse/core/include/multibuffer.rb +83 -0
- data/lib/rbcurse/core/include/orderedhash.rb +77 -0
- data/lib/rbcurse/core/include/ractionevent.rb +67 -0
- data/lib/rbcurse/core/include/rchangeevent.rb +27 -0
- data/lib/rbcurse/core/include/rhistory.rb +62 -0
- data/lib/rbcurse/core/include/rinputdataevent.rb +47 -0
- data/lib/rbcurse/core/include/vieditable.rb +170 -0
- data/lib/rbcurse/core/system/colormap.rb +163 -0
- data/lib/rbcurse/core/system/keyboard.rb +150 -0
- data/lib/rbcurse/core/system/keydefs.rb +30 -0
- data/lib/rbcurse/core/system/ncurses.rb +218 -0
- data/lib/rbcurse/core/system/panel.rb +162 -0
- data/lib/rbcurse/core/system/window.rb +901 -0
- data/lib/rbcurse/core/util/ansiparser.rb +117 -0
- data/lib/rbcurse/core/util/app.rb +1235 -0
- data/lib/rbcurse/core/util/basestack.rb +407 -0
- data/lib/rbcurse/core/util/bottomline.rb +1850 -0
- data/lib/rbcurse/core/util/colorparser.rb +71 -0
- data/lib/rbcurse/core/util/focusmanager.rb +31 -0
- data/lib/rbcurse/core/util/padreader.rb +189 -0
- data/lib/rbcurse/core/util/rcommandwindow.rb +587 -0
- data/lib/rbcurse/core/util/rdialogs.rb +619 -0
- data/lib/rbcurse/core/util/viewer.rb +149 -0
- data/lib/rbcurse/core/util/widgetshortcuts.rb +505 -0
- data/lib/rbcurse/core/widgets/applicationheader.rb +102 -0
- data/lib/rbcurse/core/widgets/box.rb +58 -0
- data/lib/rbcurse/core/widgets/divider.rb +310 -0
- data/lib/rbcurse/core/widgets/keylabelprinter.rb +178 -0
- data/lib/rbcurse/core/widgets/rcombo.rb +238 -0
- data/lib/rbcurse/core/widgets/rcontainer.rb +415 -0
- data/lib/rbcurse/core/widgets/rlink.rb +30 -0
- data/lib/rbcurse/core/widgets/rlist.rb +723 -0
- data/lib/rbcurse/core/widgets/rmenu.rb +939 -0
- data/lib/rbcurse/core/widgets/rmenulink.rb +22 -0
- data/lib/rbcurse/core/widgets/rmessagebox.rb +373 -0
- data/lib/rbcurse/core/widgets/rprogress.rb +118 -0
- data/lib/rbcurse/core/widgets/rtabbedpane.rb +615 -0
- data/lib/rbcurse/core/widgets/rtabbedwindow.rb +68 -0
- data/lib/rbcurse/core/widgets/rtextarea.rb +920 -0
- data/lib/rbcurse/core/widgets/rtextview.rb +780 -0
- data/lib/rbcurse/core/widgets/rtree.rb +787 -0
- data/lib/rbcurse/core/widgets/rwidget.rb +3040 -0
- data/lib/rbcurse/core/widgets/scrollbar.rb +143 -0
- data/lib/rbcurse/core/widgets/statusline.rb +94 -0
- data/lib/rbcurse/core/widgets/tabular.rb +264 -0
- data/lib/rbcurse/core/widgets/tabularwidget.rb +1211 -0
- data/lib/rbcurse/core/widgets/textpad.rb +516 -0
- data/lib/rbcurse/core/widgets/tree/treecellrenderer.rb +150 -0
- data/lib/rbcurse/core/widgets/tree/treemodel.rb +428 -0
- metadata +156 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
# ----------------------------------------------------------------------------- #
|
|
2
|
+
# File: textpad.rb
|
|
3
|
+
# Description: A class that displays text using a pad.
|
|
4
|
+
# The motivation for this is to put formatted text and not care about truncating and
|
|
5
|
+
# stuff. Also, there will be only one write, not each time scrolling happens.
|
|
6
|
+
# I found textview code for repaint being more complex than required.
|
|
7
|
+
# Author: rkumar http://github.com/rkumar/rbcurse/
|
|
8
|
+
# Date: 2011-11-09 - 16:59
|
|
9
|
+
# License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
|
|
10
|
+
# Last update: 2011-11-10 - 12:39
|
|
11
|
+
#
|
|
12
|
+
# == CHANGES
|
|
13
|
+
# == TODO
|
|
14
|
+
# when moving right, also don't pan straight away
|
|
15
|
+
# x add mappings and process key in handle_keys and other widget things
|
|
16
|
+
# - user can put text or list
|
|
17
|
+
# - handle putting data again and overwriting existing
|
|
18
|
+
# - formatted text
|
|
19
|
+
# - search and other features
|
|
20
|
+
# - can pad movement and other ops be abstracted into module for reuse
|
|
21
|
+
# / get scrolling like in vim (C-f e y b d)
|
|
22
|
+
# - alert issue of leaving a blank is poss due to using prefresh i/o copywin
|
|
23
|
+
#
|
|
24
|
+
# ----------------------------------------------------------------------------- #
|
|
25
|
+
#
|
|
26
|
+
require 'rbcurse'
|
|
27
|
+
require 'rbcurse/core/include/bordertitle'
|
|
28
|
+
|
|
29
|
+
include RubyCurses
|
|
30
|
+
module RubyCurses
|
|
31
|
+
extend self
|
|
32
|
+
class TextPad < Widget
|
|
33
|
+
include BorderTitle
|
|
34
|
+
|
|
35
|
+
dsl_accessor :suppress_border
|
|
36
|
+
# You may pass height, width, row and col for creating a window otherwise a fullscreen window
|
|
37
|
+
# will be created. If you pass a window from caller then that window will be used.
|
|
38
|
+
# Some keys are trapped, jkhl space, pgup, pgdown, end, home, t b
|
|
39
|
+
# This is currently very minimal and was created to get me started to integrating
|
|
40
|
+
# pads into other classes such as textview.
|
|
41
|
+
def initialize form=nil, config={}, &block
|
|
42
|
+
|
|
43
|
+
@editable = false
|
|
44
|
+
@focusable = true
|
|
45
|
+
@config = config
|
|
46
|
+
#@rows = FFI::NCurses.LINES-1
|
|
47
|
+
#@cols = FFI::NCurses.COLS-1
|
|
48
|
+
@prow = @pcol = 0
|
|
49
|
+
@startrow = 0
|
|
50
|
+
@startcol = 0
|
|
51
|
+
@list = []
|
|
52
|
+
super
|
|
53
|
+
|
|
54
|
+
# FIXME 0 as height craps out. need to make it LINES
|
|
55
|
+
|
|
56
|
+
@height = @height.ifzero(FFI::NCurses.LINES)
|
|
57
|
+
@width = @width.ifzero(FFI::NCurses.COLS)
|
|
58
|
+
@rows = @height
|
|
59
|
+
@cols = @width
|
|
60
|
+
@startrow = @row
|
|
61
|
+
@startcol = @col
|
|
62
|
+
#@suppress_border = config[:suppress_border]
|
|
63
|
+
@row_offset = @col_offset = 1
|
|
64
|
+
unless @suppress_border
|
|
65
|
+
@startrow += 1
|
|
66
|
+
@startcol += 1
|
|
67
|
+
@rows -=3 # 3 is since print_border_only reduces one from width, to check whether this is correct
|
|
68
|
+
@cols -=3
|
|
69
|
+
end
|
|
70
|
+
@row_offset = @col_offset = 0 if @suppress_borders
|
|
71
|
+
@top = @row
|
|
72
|
+
@left = @col
|
|
73
|
+
init_vars
|
|
74
|
+
end
|
|
75
|
+
def init_vars
|
|
76
|
+
@scrollatrows = @height - 3
|
|
77
|
+
@oldindex = @current_index = 0
|
|
78
|
+
@repaint_required = true
|
|
79
|
+
end
|
|
80
|
+
def rowcol #:nodoc:
|
|
81
|
+
return @row+@row_offset, @col+@col_offset
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
def create_pad
|
|
86
|
+
destroy if @pad
|
|
87
|
+
#@pad = FFI::NCurses.newpad(@content_rows, @content_cols)
|
|
88
|
+
@pad = @window.get_pad(@content_rows, @content_cols)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
# create and populate pad
|
|
93
|
+
def populate_pad
|
|
94
|
+
@_populate_needed = false
|
|
95
|
+
# how can we make this more sensible ? FIXME
|
|
96
|
+
@renderer ||= DefaultRubyRenderer.new if ".rb" == @filetype
|
|
97
|
+
@content_rows = @content.count
|
|
98
|
+
@content_cols = content_cols()
|
|
99
|
+
|
|
100
|
+
create_pad
|
|
101
|
+
|
|
102
|
+
Ncurses::Panel.update_panels
|
|
103
|
+
@content.each_index { |ix|
|
|
104
|
+
#FFI::NCurses.mvwaddstr(@pad,ix, 0, @content[ix])
|
|
105
|
+
render @pad, ix, @content[ix]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
public
|
|
111
|
+
# supply a custom renderer that implements +render()+
|
|
112
|
+
# @see render
|
|
113
|
+
def renderer r
|
|
114
|
+
@renderer = r
|
|
115
|
+
end
|
|
116
|
+
#
|
|
117
|
+
# default method for rendering a line
|
|
118
|
+
#
|
|
119
|
+
def render pad, lineno, text
|
|
120
|
+
if text.is_a? Chunks::ChunkLine
|
|
121
|
+
FFI::NCurses.wmove @pad, lineno, 0
|
|
122
|
+
a = get_attrib @attrib
|
|
123
|
+
|
|
124
|
+
show_colored_chunks text, nil, a
|
|
125
|
+
return
|
|
126
|
+
end
|
|
127
|
+
if @renderer
|
|
128
|
+
@renderer.render @pad, lineno, text
|
|
129
|
+
else
|
|
130
|
+
FFI::NCurses.mvwaddstr(@pad,lineno, 0, @content[lineno])
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# supply a filename as source for textpad
|
|
135
|
+
# Reads up file into @content
|
|
136
|
+
|
|
137
|
+
def filename(filename)
|
|
138
|
+
@file = filename
|
|
139
|
+
@filetype = File.extname filename
|
|
140
|
+
@content = File.open(filename,"r").readlines
|
|
141
|
+
@_populate_needed = true
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Supply an array of string to be displayed
|
|
145
|
+
# This will replace existing text
|
|
146
|
+
|
|
147
|
+
def text lines
|
|
148
|
+
@content = lines
|
|
149
|
+
@_populate_needed = true
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
## ---- the next 2 methods deal with printing chunks
|
|
153
|
+
# we should put it int a common module and include it
|
|
154
|
+
# in Window and Pad stuff and perhaps include it conditionally.
|
|
155
|
+
|
|
156
|
+
def print(string, width = width)
|
|
157
|
+
#return unless visible?
|
|
158
|
+
w = width == 0? Ncurses.COLS : width
|
|
159
|
+
FFI::NCurses.waddnstr(@pad,string.to_s, w) # changed 2011 dts
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def show_colored_chunks(chunks, defcolor = nil, defattr = nil)
|
|
163
|
+
#return unless visible?
|
|
164
|
+
chunks.each do |chunk| #|color, chunk, attrib|
|
|
165
|
+
case chunk
|
|
166
|
+
when Chunks::Chunk
|
|
167
|
+
color = chunk.color
|
|
168
|
+
attrib = chunk.attrib
|
|
169
|
+
text = chunk.text
|
|
170
|
+
when Array
|
|
171
|
+
# for earlier demos that used an array
|
|
172
|
+
color = chunk[0]
|
|
173
|
+
attrib = chunk[2]
|
|
174
|
+
text = chunk[1]
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
color ||= defcolor
|
|
178
|
+
attrib ||= defattr || NORMAL
|
|
179
|
+
|
|
180
|
+
#cc, bg = ColorMap.get_colors_for_pair color
|
|
181
|
+
#$log.debug "XXX: CHUNK textpad #{text}, cp #{color} , attrib #{attrib}. #{cc}, #{bg} "
|
|
182
|
+
FFI::NCurses.wcolor_set(@pad, color,nil) if color
|
|
183
|
+
FFI::NCurses.wattron(@pad, attrib) if attrib
|
|
184
|
+
print(text)
|
|
185
|
+
FFI::NCurses.wattroff(@pad, attrib) if attrib
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def formatted_text text, fmt
|
|
190
|
+
require 'rbcurse/core/include/chunk'
|
|
191
|
+
@formatted_text = text
|
|
192
|
+
@color_parser = fmt
|
|
193
|
+
#remove_all
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# write pad onto window
|
|
197
|
+
private
|
|
198
|
+
def padrefresh
|
|
199
|
+
FFI::NCurses.prefresh(@pad,@prow,@pcol, @startrow,@startcol, @rows + @startrow,@cols+@startcol);
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# convenience method to return byte
|
|
203
|
+
private
|
|
204
|
+
def key x
|
|
205
|
+
x.getbyte(0)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# length of longest string in array
|
|
209
|
+
def content_cols
|
|
210
|
+
longest = @content.max_by(&:length)
|
|
211
|
+
longest.length
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
public
|
|
215
|
+
def repaint
|
|
216
|
+
return unless @repaint_required
|
|
217
|
+
if @formatted_text
|
|
218
|
+
$log.debug "XXX: INSIDE FORMATTED TEXT "
|
|
219
|
+
|
|
220
|
+
l = RubyCurses::Utils.parse_formatted_text(@color_parser,
|
|
221
|
+
@formatted_text)
|
|
222
|
+
|
|
223
|
+
text(l)
|
|
224
|
+
@formatted_text = nil
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
populate_pad if @_populate_needed
|
|
228
|
+
#HERE we need to populate once so user can pass a renderer
|
|
229
|
+
@window ||= @graphic
|
|
230
|
+
unless @suppress_border
|
|
231
|
+
if @repaint_all
|
|
232
|
+
@window.print_border_only @top, @left, @height-1, @width, $datacolor
|
|
233
|
+
print_title
|
|
234
|
+
@window.wrefresh
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
padrefresh
|
|
239
|
+
@repaint_required = false
|
|
240
|
+
@repaint_all = false
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
#
|
|
244
|
+
# key mappings
|
|
245
|
+
#
|
|
246
|
+
def map_keys
|
|
247
|
+
@mapped_keys = true
|
|
248
|
+
bind_key([?g,?g]){ goto_start } # mapping double keys like vim
|
|
249
|
+
bind_key(279){ goto_start }
|
|
250
|
+
bind_keys([?G,277]){ goto_end }
|
|
251
|
+
bind_keys([?k,KEY_UP]){ up }
|
|
252
|
+
bind_keys([?j,KEY_DOWN]){ down }
|
|
253
|
+
bind_key(?\C-e){ scroll_window_down }
|
|
254
|
+
bind_key(?\C-y){ scroll_window_up }
|
|
255
|
+
bind_keys([32,338]){ scroll_forward }
|
|
256
|
+
bind_keys([?\C-b,339]){ scroll_backward }
|
|
257
|
+
bind_key([?',?']){ goto_last_position } # vim , goto last row position (not column)
|
|
258
|
+
#bind_key(?/, :ask_search)
|
|
259
|
+
#bind_key(?n, :find_more)
|
|
260
|
+
bind_key([?\C-x, ?>], :scroll_right)
|
|
261
|
+
bind_key([?\C-x, ?<], :scroll_left)
|
|
262
|
+
bind_key(?\M-l, :scroll_right)
|
|
263
|
+
bind_key(?\M-h, :scroll_left)
|
|
264
|
+
bind_key([?\C-x, ?\C-s], :saveas)
|
|
265
|
+
#bind_key(?r) { getstr("Enter a word: ") }
|
|
266
|
+
bind_key(?m, :disp_menu)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# goto first line of file
|
|
270
|
+
def goto_start
|
|
271
|
+
@oldindex = @current_index
|
|
272
|
+
@current_index = 0
|
|
273
|
+
@prow = 0
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# goto last line of file
|
|
277
|
+
def goto_end
|
|
278
|
+
@oldindex = @current_index
|
|
279
|
+
@current_index = @content_rows-1
|
|
280
|
+
@prow = @current_index - @scrollatrows
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# move down a line mimicking vim's j key
|
|
284
|
+
# @param [int] multiplier entered prior to invoking key
|
|
285
|
+
def down num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
|
|
286
|
+
@oldindex = @current_index if num > 10
|
|
287
|
+
@current_index += num
|
|
288
|
+
unless is_visible? @current_index
|
|
289
|
+
if @current_index > @scrollatrows
|
|
290
|
+
@prow += 1
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
$multiplier = 0
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# move up a line mimicking vim's k key
|
|
297
|
+
# @param [int] multiplier entered prior to invoking key
|
|
298
|
+
def up num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
|
|
299
|
+
@oldindex = @current_index if num > 10
|
|
300
|
+
@current_index -= num
|
|
301
|
+
unless is_visible? @current_index
|
|
302
|
+
if @prow > @current_index
|
|
303
|
+
$status_message.value = "1 #{@prow} > #{@current_index} "
|
|
304
|
+
@prow -= 1
|
|
305
|
+
else
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
$multiplier = 0
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# scrolls window down mimicking vim C-e
|
|
312
|
+
# @param [int] multiplier entered prior to invoking key
|
|
313
|
+
def scroll_window_down num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
|
|
314
|
+
@prow += num
|
|
315
|
+
if @prow > @current_index
|
|
316
|
+
@current_index += 1
|
|
317
|
+
end
|
|
318
|
+
#check_prow
|
|
319
|
+
$multiplier = 0
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# scrolls window up mimicking vim C-y
|
|
323
|
+
# @param [int] multiplier entered prior to invoking key
|
|
324
|
+
def scroll_window_up num=(($multiplier.nil? or $multiplier == 0) ? 1 : $multiplier)
|
|
325
|
+
@prow -= num
|
|
326
|
+
unless is_visible? @current_index
|
|
327
|
+
# one more check may be needed here TODO
|
|
328
|
+
@current_index -= num
|
|
329
|
+
end
|
|
330
|
+
$multiplier = 0
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# scrolls lines a window full at a time, on pressing ENTER or C-d or pagedown
|
|
334
|
+
def scroll_forward
|
|
335
|
+
@oldindex = @current_index
|
|
336
|
+
@current_index += @scrollatrows
|
|
337
|
+
@prow = @current_index - @scrollatrows
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# scrolls lines backward a window full at a time, on pressing pageup
|
|
341
|
+
# C-u may not work since it is trapped by form earlier. Need to fix
|
|
342
|
+
def scroll_backward
|
|
343
|
+
@oldindex = @current_index
|
|
344
|
+
@current_index -= @scrollatrows
|
|
345
|
+
@prow = @current_index - @scrollatrows
|
|
346
|
+
end
|
|
347
|
+
def goto_last_position
|
|
348
|
+
return unless @oldindex
|
|
349
|
+
tmp = @current_index
|
|
350
|
+
@current_index = @oldindex
|
|
351
|
+
@oldindex = tmp
|
|
352
|
+
bounds_check
|
|
353
|
+
end
|
|
354
|
+
def handle_key ch
|
|
355
|
+
return :UNHANDLED unless @content
|
|
356
|
+
map_keys unless @mapped_keys
|
|
357
|
+
|
|
358
|
+
@maxrow = @content_rows - @rows
|
|
359
|
+
@maxcol = @content_cols - @cols
|
|
360
|
+
@oldrow = @prow
|
|
361
|
+
@oldcol = @pcol
|
|
362
|
+
$log.debug "XXX: PAD got #{ch} "
|
|
363
|
+
begin
|
|
364
|
+
case ch
|
|
365
|
+
when key(?l)
|
|
366
|
+
@pcol += 1
|
|
367
|
+
when key(?$)
|
|
368
|
+
@pcol = @maxcol - 1
|
|
369
|
+
when key(?h)
|
|
370
|
+
if @pcol > 0
|
|
371
|
+
@pcol -= 1
|
|
372
|
+
end
|
|
373
|
+
when key(?q)
|
|
374
|
+
#throw :close
|
|
375
|
+
when ?0.getbyte(0)..?9.getbyte(0)
|
|
376
|
+
if ch == ?0.getbyte(0) && $multiplier == 0
|
|
377
|
+
# copy of C-a - start of line
|
|
378
|
+
@repaint_required = true if @pcol > 0 # tried other things but did not work
|
|
379
|
+
@pcol = 0
|
|
380
|
+
return 0
|
|
381
|
+
end
|
|
382
|
+
# storing digits entered so we can multiply motion actions
|
|
383
|
+
$multiplier *= 10 ; $multiplier += (ch-48)
|
|
384
|
+
return 0
|
|
385
|
+
when ?\C-c.getbyte(0)
|
|
386
|
+
$multiplier = 0
|
|
387
|
+
return 0
|
|
388
|
+
else
|
|
389
|
+
# check for bindings, these cannot override above keys since placed at end
|
|
390
|
+
begin
|
|
391
|
+
ret = process_key ch, self
|
|
392
|
+
rescue => err
|
|
393
|
+
$log.error " TEXTPAD ERROR #{err} "
|
|
394
|
+
$log.debug(err.backtrace.join("\n"))
|
|
395
|
+
alert err.to_s
|
|
396
|
+
# FIXME why does this result in a blank spot on screen till its refreshed again
|
|
397
|
+
# should not happen if its deleting its panel and doing an update panel
|
|
398
|
+
end
|
|
399
|
+
return :UNHANDLED if ret == :UNHANDLED
|
|
400
|
+
end
|
|
401
|
+
bounds_check
|
|
402
|
+
rescue => err
|
|
403
|
+
$log.debug( err) if err
|
|
404
|
+
$log.debug(err.backtrace.join("\n")) if err
|
|
405
|
+
alert "Got an exception in PadReader: #{err}. Check log"
|
|
406
|
+
$error_message.value = ""
|
|
407
|
+
ensure
|
|
408
|
+
end
|
|
409
|
+
return 0
|
|
410
|
+
end # while loop
|
|
411
|
+
|
|
412
|
+
# destroy the pad, this needs to be called from somewhere, like when the app
|
|
413
|
+
# closes or the current window closes , or else we could have a seg fault
|
|
414
|
+
# or some ugliness on the screen below this one (if nested).
|
|
415
|
+
|
|
416
|
+
# Now since we use get_pad from window, upon the window being destroyed,
|
|
417
|
+
# it will call this. Else it will destroy pad
|
|
418
|
+
def destroy
|
|
419
|
+
FFI::NCurses.delwin(@pad) if @pad # when do i do this ? FIXME
|
|
420
|
+
@pad = nil
|
|
421
|
+
end
|
|
422
|
+
def is_visible? index
|
|
423
|
+
j = index - @prow #@toprow
|
|
424
|
+
j >= 0 && j <= @scrollatrows
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
private
|
|
428
|
+
|
|
429
|
+
# check that current_index and prow are within correct ranges
|
|
430
|
+
# sets row (and someday col too)
|
|
431
|
+
# sets repaint_required
|
|
432
|
+
|
|
433
|
+
def bounds_check
|
|
434
|
+
r,c = rowcol
|
|
435
|
+
@current_index = 0 if @current_index < 0
|
|
436
|
+
@current_index = @content_rows-1 if @current_index > @content_rows-1
|
|
437
|
+
$status_message.value = "visible #{@prow} , #{@current_index} "
|
|
438
|
+
unless is_visible? @current_index
|
|
439
|
+
if @prow > @current_index
|
|
440
|
+
$status_message.value = "1 #{@prow} > #{@current_index} "
|
|
441
|
+
@prow -= 1
|
|
442
|
+
else
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
#end
|
|
446
|
+
check_prow
|
|
447
|
+
$log.debug "XXX: PAD BOUNDS ci:#{@current_index} , old #{@oldrow},pr #{@prow}, max #{@maxrow} "
|
|
448
|
+
@crow = @current_index + r - @prow
|
|
449
|
+
@crow = r if @crow < r
|
|
450
|
+
# 2 depends on whetehr suppressborders
|
|
451
|
+
@crow = @row + @height -2 if @crow >= r + @height -2
|
|
452
|
+
setrowcol @crow, nil
|
|
453
|
+
if @oldrow != @prow || @oldcol != @pcol
|
|
454
|
+
@repaint_required = true
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# check that prow and pcol are within bounds
|
|
460
|
+
|
|
461
|
+
def check_prow
|
|
462
|
+
@prow = 0 if @prow < 0
|
|
463
|
+
@pcol = 0 if @pcol < 0
|
|
464
|
+
if @prow > @maxrow-1
|
|
465
|
+
@prow = @maxrow-1
|
|
466
|
+
end
|
|
467
|
+
if @pcol > @maxcol-1
|
|
468
|
+
@pcol = @maxcol-1
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
# a test renderer to see how things go
|
|
472
|
+
class DefaultRubyRenderer
|
|
473
|
+
def render pad, lineno, text
|
|
474
|
+
bg = :black
|
|
475
|
+
fg = :white
|
|
476
|
+
att = NORMAL
|
|
477
|
+
cp = $datacolor
|
|
478
|
+
if text =~ /^\s*# /
|
|
479
|
+
fg = :red
|
|
480
|
+
cp = get_color($datacolor, fg, bg)
|
|
481
|
+
elsif text =~ /^\s*#/
|
|
482
|
+
fg = :blue
|
|
483
|
+
cp = get_color($datacolor, fg, bg)
|
|
484
|
+
elsif text =~ /^\s*class /
|
|
485
|
+
fg = :magenta
|
|
486
|
+
cp = get_color($datacolor, fg, bg)
|
|
487
|
+
elsif text =~ /^\s*def /
|
|
488
|
+
fg = :yellow
|
|
489
|
+
att = BOLD
|
|
490
|
+
cp = get_color($datacolor, fg, bg)
|
|
491
|
+
elsif text =~ /^\s*(begin|rescue|ensure|end)/
|
|
492
|
+
fg = :magenta
|
|
493
|
+
att = BOLD
|
|
494
|
+
cp = get_color($datacolor, fg, bg)
|
|
495
|
+
end
|
|
496
|
+
FFI::NCurses.wattron(pad,FFI::NCurses.COLOR_PAIR(cp) | att)
|
|
497
|
+
FFI::NCurses.mvwaddstr(pad, lineno, 0, text)
|
|
498
|
+
FFI::NCurses.wattroff(pad,FFI::NCurses.COLOR_PAIR(cp) | att)
|
|
499
|
+
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
if __FILE__ == $PROGRAM_NAME
|
|
504
|
+
require 'rbcurse/core/util/app'
|
|
505
|
+
App.new do
|
|
506
|
+
w = 50
|
|
507
|
+
w2 = FFI::NCurses.COLS-w-1
|
|
508
|
+
p = RubyCurses::TextPad.new @form, :height => FFI::NCurses.LINES, :width => w, :row => 0, :col => 0 , :title => " ansi "
|
|
509
|
+
fn = "../../../examples/color.2"
|
|
510
|
+
text = File.open(fn,"r").readlines
|
|
511
|
+
p.formatted_text(text, :ansi)
|
|
512
|
+
RubyCurses::TextPad.new @form, :filename => "textpad.rb", :height => FFI::NCurses.LINES, :width => w2, :row => 0, :col => w+1 , :title => " ruby "
|
|
513
|
+
#throw :close
|
|
514
|
+
#status_line
|
|
515
|
+
end
|
|
516
|
+
end
|