rbcurse 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CHANGELOG +1570 -0
  2. data/History.txt +6 -0
  3. data/Manifest.txt +54 -0
  4. data/README.txt +304 -0
  5. data/Rakefile +28 -0
  6. data/examples/qdfilechooser.rb +68 -0
  7. data/examples/rfe.rb +853 -0
  8. data/examples/rfe_renderer.rb +69 -0
  9. data/examples/test1.rb +242 -0
  10. data/examples/test2.rb +498 -0
  11. data/examples/testcombo.rb +95 -0
  12. data/examples/testkeypress.rb +61 -0
  13. data/examples/testmenu.rb +105 -0
  14. data/examples/testtable.rb +266 -0
  15. data/examples/testtabp.rb +106 -0
  16. data/examples/testtodo.rb +532 -0
  17. data/examples/viewtodo.rb +512 -0
  18. data/lib/rbcurse/action.rb +31 -0
  19. data/lib/rbcurse/applicationheader.rb +57 -0
  20. data/lib/rbcurse/celleditor.rb +120 -0
  21. data/lib/rbcurse/checkboxcellrenderer.rb +69 -0
  22. data/lib/rbcurse/colormap.rb +133 -0
  23. data/lib/rbcurse/comboboxcellrenderer.rb +45 -0
  24. data/lib/rbcurse/defaultlistselectionmodel.rb +49 -0
  25. data/lib/rbcurse/keylabelprinter.rb +143 -0
  26. data/lib/rbcurse/listcellrenderer.rb +99 -0
  27. data/lib/rbcurse/listkeys.rb +33 -0
  28. data/lib/rbcurse/listscrollable.rb +216 -0
  29. data/lib/rbcurse/listselectable.rb +67 -0
  30. data/lib/rbcurse/mapper.rb +108 -0
  31. data/lib/rbcurse/orderedhash.rb +77 -0
  32. data/lib/rbcurse/rcombo.rb +243 -0
  33. data/lib/rbcurse/rdialogs.rb +183 -0
  34. data/lib/rbcurse/rform.rb +845 -0
  35. data/lib/rbcurse/rinputdataevent.rb +36 -0
  36. data/lib/rbcurse/rlistbox.rb +804 -0
  37. data/lib/rbcurse/rmenu.rb +666 -0
  38. data/lib/rbcurse/rmessagebox.rb +325 -0
  39. data/lib/rbcurse/rpopupmenu.rb +754 -0
  40. data/lib/rbcurse/rtabbedpane.rb +259 -0
  41. data/lib/rbcurse/rtable.rb +1296 -0
  42. data/lib/rbcurse/rtextarea.rb +673 -0
  43. data/lib/rbcurse/rtextview.rb +335 -0
  44. data/lib/rbcurse/rwidget.rb +1731 -0
  45. data/lib/rbcurse/scrollable.rb +301 -0
  46. data/lib/rbcurse/selectable.rb +94 -0
  47. data/lib/rbcurse/table/tablecellrenderer.rb +85 -0
  48. data/lib/rbcurse/table/tabledatecellrenderer.rb +102 -0
  49. data/lib/rbcurse.rb +7 -0
  50. data/lib/ver/keyboard.rb +150 -0
  51. data/lib/ver/keyboard2.rb +170 -0
  52. data/lib/ver/ncurses.rb +102 -0
  53. data/lib/ver/window.rb +369 -0
  54. data/test/test_rbcurse.rb +0 -0
  55. metadata +118 -0
@@ -0,0 +1,845 @@
1
+ =begin
2
+ * Name: TextView and TextArea
3
+ * $Id$
4
+ * Description Our own form with own simple field to make life easier. Ncurses forms are great, but
5
+ * honestly the sequence sucks and is a pain after a while for larger scale work.
6
+ * We need something less restrictive.
7
+ * Author: rkumar (arunachalesha)
8
+ TODO
9
+ * Field/entry
10
+ - textvariable - bding field to a var so the var is updated
11
+ *
12
+
13
+ 2008-12-24 18:01 moved menu etc to rmenu.rb
14
+ --------
15
+ * Date: 2008-11-14 23:43
16
+ * License:
17
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
18
+
19
+ =end
20
+ require 'rubygems'
21
+ require 'ncurses'
22
+ require 'logger'
23
+ require 'rbcurse'
24
+ require 'rbcurse/scrollable'
25
+ require 'rbcurse/selectable'
26
+ require 'rbcurse/rinputdataevent'
27
+
28
+ include Ncurses
29
+ include RubyCurses
30
+ module RubyCurses
31
+ extend self
32
+
33
+ ## a multiline text editing widget
34
+ # TODO - giving data to user - adding newlines, and withog adding.
35
+ # - respect newlines for incoming data
36
+ #
37
+ class OldTextArea < Widget
38
+ include Scrollable
39
+ dsl_accessor :height
40
+ dsl_accessor :title
41
+ dsl_accessor :title_attrib # bold, reverse, normal
42
+ dsl_accessor :list # the array of data to be sent by user
43
+ dsl_accessor :maxlen # the array of data to be sent by user
44
+ attr_reader :toprow
45
+ attr_reader :prow
46
+ attr_reader :winrow
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
+ attr_accessor :modified # boolean, value modified or not 2009-01-08 12:29
51
+
52
+ def initialize form, config={}, &block
53
+ @focusable = true
54
+ @editable = true
55
+ @left_margin = 1
56
+ @row = 0
57
+ @col = 0
58
+ @curpos = 0
59
+ @show_focus = false
60
+ @list = []
61
+ super
62
+ @row_offset = @col_offset = 1
63
+ @orig_col = @col
64
+ # this does result in a blank line if we insert after creating. That's required at
65
+ # present if we wish to only insert
66
+ if @list.empty?
67
+ @list << "\r"
68
+ end
69
+ @scrollatrow = @height-2
70
+ @content_rows = @list.length
71
+ @win = @form.window
72
+ init_scrollable
73
+ print_borders
74
+ @maxlen ||= @width-2
75
+ end
76
+ def rowcol
77
+ # $log.debug "textarea rowcol : #{@row+@row_offset+@winrow}, #{@col+@col_offset}"
78
+ return @row+@row_offset+@winrow, @col+@col_offset
79
+ end
80
+ ##
81
+ # this avoids wrapping. Better to use the <<.
82
+ def Oinsert off0, *data
83
+ @list.insert off0, *data
84
+ # fire_handler :CHANGE, self # 2008-12-09 14:56 NOT SURE
85
+ end
86
+ # private
87
+ def wrap_text(txt, col = @maxlen)
88
+ $log.debug "inside wrap text for :#{txt}"
89
+ txt.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/,
90
+ "\\1\\3\n")
91
+ end
92
+ def remove_all
93
+ @list = []
94
+ end
95
+ ##
96
+ # trying to wrap and insert
97
+ def insert off0, data
98
+ if data.length > @maxlen
99
+ data = wrap_text data
100
+ # $log.debug "after wrap text done :#{data}"
101
+ data = data.split("\n")
102
+ data[-1] << "\r" #XXXX
103
+ else
104
+ data << "\r" if data[-1,1] != "\r" #XXXX
105
+ end
106
+ data.each do |row|
107
+ @list.insert off0, row
108
+ off0 += 1
109
+ end
110
+ #$log.debug " AFTER INSERT: #{@list}"
111
+ end
112
+ ##
113
+ # wraps line sent in if longer than maxlen
114
+ # Typically a line is sent in. We wrap and put a hard return at end.
115
+ def << data
116
+ if data.length > @maxlen
117
+ $log.debug "wrapped append for #{data}"
118
+ data = wrap_text data
119
+ $log.debug "after wrap text for :#{data}"
120
+ data = data.split("\n")
121
+ # 2009-01-01 22:24 the \n was needed so we would put a space at time of writing.
122
+ # we need a soft return so a space can be added when pushing down.
123
+ # commented off 2008-12-28 21:59
124
+ #data.each {|line| @list << line+"\n"}
125
+ data.each {|line| @list << line}
126
+ @list[-1] << "\r" #XXXX
127
+ else
128
+ $log.debug "normal append for #{data}"
129
+ data << "\r" if data[-1,1] != "\r" #XXXX
130
+ @list << data
131
+ end
132
+ goto_end if @auto_scroll # to test out.
133
+ self
134
+ end
135
+ def wrap_para line=@prow
136
+ line ||= 0
137
+ l=[]
138
+ while true
139
+ if @list[line].nil? or @list[line]=="" or @list[line]==13 #"\r"
140
+ break
141
+ end
142
+ $log.debug "lastchar #{@list[line][-1]}, appending: #{@list[line]}]"
143
+ t = @list[line]
144
+ l << t.strip
145
+ @list.delete_at line
146
+ break if t[-1]==13 # "\r"
147
+ # line += 1
148
+ end
149
+ str=l.join(" ")
150
+ $log.debug " sending insert : #{str}."
151
+ insert line, str
152
+ end
153
+ ##
154
+ # private
155
+ def print_borders
156
+ window = @form.window
157
+ color = $datacolor
158
+ window.print_border @row, @col, @height, @width, color
159
+ print_title
160
+ =begin
161
+ hline = "+%s+" % [ "-"*(width-((1)*2)) ]
162
+ hline2 = "|%s|" % [ " "*(width-((1)*2)) ]
163
+ window.printstring( row=startrow, col=startcol, hline, color)
164
+ print_title
165
+ (startrow+1).upto(startrow+height-1) do |row|
166
+ window.printstring(row, col=startcol, hline2, color)
167
+ end
168
+ window.printstring(startrow+height, col=startcol, hline, color)
169
+ =end
170
+
171
+ end
172
+ # private
173
+ def print_title
174
+ @form.window.printstring( @row, @col+(@width-@title.length)/2, @title, $datacolor, @title_attrib) unless @title.nil?
175
+ end
176
+ # text_area print footer
177
+ def print_foot
178
+ @footer_attrib ||= Ncurses::A_REVERSE
179
+ footer = "R: #{@prow+1}, C: #{@curpos}, #{@list.length} lines "
180
+ @form.window.printstring( @row + @height, @col+2, footer, $datacolor, @footer_attrib)
181
+ end
182
+ ### FOR scrollable ###
183
+ def get_content
184
+ @list
185
+ end
186
+ def get_window
187
+ @form.window
188
+ end
189
+ ### FOR scrollable ###
190
+ def repaint # textarea
191
+ paint
192
+ print_foot if @print_footer
193
+ end
194
+ def getvalue
195
+ @list
196
+ end
197
+ # textarea
198
+
199
+ def handle_key ch
200
+ @buffer = @list[@prow]
201
+ if @buffer.nil? and @list.length == 0
202
+ @list << "\n" # changed space to newline so wrapping puts a line.
203
+ @buffer = @list[@prow]
204
+ end
205
+ return if @buffer.nil?
206
+ $log.debug "TA: before: curpos #{@curpos} blen: #{@buffer.length}"
207
+ # on any line if the cursor is ahead of buffer length, ensure its on last position
208
+ # what if the buffer is somehow gt maxlen ??
209
+ if @curpos > @buffer.length
210
+ addcol(@buffer.length-@curpos)+1
211
+ @curpos = @buffer.length
212
+ end
213
+ $log.debug "TA: after : curpos #{@curpos} blen: #{@buffer.length}, w: #{@width} max #{@maxlen}"
214
+ pre_key
215
+ case ch
216
+ when ?\C-n
217
+ scroll_forward
218
+ when ?\C-p
219
+ scroll_backward
220
+ when ?\C-[
221
+ goto_start #cursor_start of buffer
222
+ when ?\C-]
223
+ goto_end # cursor_end of buffer
224
+ when KEY_UP
225
+ #select_prev_row
226
+ ret = up
227
+ when KEY_DOWN
228
+ ret = down
229
+ when KEY_ENTER, 10, 13
230
+ insert_break
231
+ when KEY_LEFT
232
+ cursor_backward
233
+ when KEY_RIGHT
234
+ cursor_forward
235
+ when KEY_BACKSPACE, 127
236
+ if @editable # checking here means that i can programmatically bypass!!
237
+ delete_prev_char
238
+ #fire_handler :CHANGE, self # 2008-12-22 15:23
239
+ end
240
+ when 330, ?\C-d # delete char
241
+ if @editable
242
+ delete_curr_char
243
+ #fire_handler :CHANGE, self # 2008-12-22 15:23
244
+ end
245
+ when ?\C-k # delete till eol
246
+ if @editable
247
+ if @buffer == ""
248
+ delete_line
249
+ #fire_handler :CHANGE, self # 2008-12-22 15:23
250
+ else
251
+ delete_eol
252
+ #fire_handler :CHANGE, self # 2008-12-22 15:23
253
+ end
254
+ end
255
+ when ?\C-u
256
+ undo_delete
257
+ when ?\C-a
258
+ cursor_bol
259
+ when ?\C-e
260
+ cursor_eol
261
+ #set_form_col @buffer.length
262
+ else
263
+ #$log.debug(" textarea ch #{ch}")
264
+ ret = putc ch
265
+ return ret if ret == :UNHANDLED
266
+ end
267
+ post_key
268
+ set_form_row
269
+ set_form_col # testing 2008-12-26 19:37
270
+ end
271
+ def undo_delete
272
+ # added 2008-11-27 12:43 paste delete buffer into insertion point
273
+ @buffer.insert @curpos, @delete_buffer unless @delete_buffer.nil?
274
+ fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT, @prow, @delete_buffer) # 2008-12-24 18:34
275
+ end
276
+ def insert_break
277
+ return -1 unless @editable
278
+ # insert a blank row and append rest of this line to cursor
279
+ $log.debug "ENTER PRESSED at #{@curpos}, on row #{@prow}"
280
+ @delete_buffer = (delete_eol || "")
281
+ @list[@prow] << "\r"
282
+ $log.debug "DELETE BUFFER #{@delete_buffer}"
283
+ @list.insert @prow+1, @delete_buffer
284
+ @curpos = 0
285
+ down
286
+ @form.col = @orig_col + @col_offset
287
+ #addrowcol 1,0
288
+ @form.row = @row + 1 + @winrow
289
+ #fire_handler :CHANGE, self # 2008-12-09 14:56
290
+ fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :INSERT, @prow, @delete_buffer) # 2008-12-24 18:34
291
+ end
292
+ # puts cursor on correct row.
293
+ def set_form_row
294
+ @form.row = @row + 1 + @winrow
295
+ end
296
+ # set cursor on correct column
297
+ def set_form_col col1=@curpos
298
+ @curpos = col1
299
+ cursor_bounds_check
300
+ @form.col = @orig_col + @col_offset + @curpos
301
+ $log.debug "sfc: #{@orig_col}, #{@col_offset}. #{@curpos}. "
302
+ end
303
+ def cursor_bounds_check
304
+ max = buffer_len()
305
+ @curpos = max if @curpos > max # check 2008-12-27 00:02
306
+ end
307
+ def buffer_len
308
+ @list[@prow].nil? ? 0 : @list[@prow].chomp().length
309
+ end
310
+ def do_current_row # :yields current row
311
+ yield @list[@prow]
312
+ @buffer = @list[@prow]
313
+ end
314
+ def delete_eol
315
+ return -1 unless @editable
316
+ pos = @curpos-1
317
+ @delete_buffer = @buffer[@curpos..-1]
318
+ # if pos is 0, pos-1 becomes -1, end of line!
319
+ @list[@prow] = pos == -1 ? "" : @buffer[0..pos]
320
+ $log.debug "delete EOL :pos=#{pos}, #{@delete_buffer}: row: #{@list[@prow]}:"
321
+ @buffer = @list[@prow]
322
+ cursor_backward if @curpos > 0 # now cursor back goes up to prev line
323
+ #fire_handler :CHANGE, self # 2008-12-09 14:56
324
+ fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :DELETE, @prow, @delete_buffer) # 2008-12-24 18:34
325
+ return @delete_buffer
326
+ end
327
+ def cursor_forward num=1
328
+ $log.debug "next char cp #{@curpos}, #{@buffer.length}. wi: #{@width}"
329
+ #if @curpos < @width and @curpos < @maxlen-1 # else it will do out of box
330
+ if @curpos < buffer_len()
331
+ @curpos += 1
332
+ addcol 1
333
+ else # trying this out 2008-12-26 20:18
334
+ @curpos = 0
335
+ down
336
+ end
337
+ cursor_bounds_check
338
+ end
339
+ def addcol num
340
+ @form.addcol num
341
+ end
342
+ def addrowcol row,col
343
+ @form.addrowcol row, col
344
+ end
345
+ def cursor_backward
346
+ if @curpos > 0
347
+ @curpos -= 1
348
+ addcol -1
349
+ else # trying this out 2008-12-26 20:18
350
+ ret = up
351
+ cursor_eol if ret != -1
352
+ end
353
+ end
354
+ def delete_line line=@prow
355
+ return -1 unless @editable
356
+ $log.debug "called delete line"
357
+ @delete_buffer = @list.delete_at line
358
+ @buffer = @list[@prow]
359
+ if @buffer.nil?
360
+ up
361
+ @form.row = @row + 1 + @winrow
362
+ end
363
+ #fire_handler :CHANGE, self # 2008-12-09 14:56
364
+ fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos+@delete_buffer.length, self, :DELETE, @prow, @delete_buffer) # 2008-12-24 18:34
365
+ end
366
+ def delete_curr_char num=1
367
+ return -1 unless @editable
368
+ num.times do
369
+ delete_at
370
+ set_modified
371
+ end
372
+ end
373
+ def delete_prev_char num=1
374
+ return -1 if !@editable
375
+ num.times do
376
+ if @curpos <= 0
377
+ join_to_prev_line
378
+ return
379
+ end
380
+ @curpos -= 1 if @curpos > 0
381
+ delete_at
382
+ set_modified
383
+ addcol -1
384
+ end
385
+ end
386
+ # private
387
+ # when backspace pressed in position zero if the previous line is filled we may have to bring
388
+ # down the last word and join, rather than go up
389
+ def join_to_prev_line
390
+ return -1 unless @editable
391
+ return if @prow == 0
392
+ oldcurpos = @curpos
393
+ oldprow = @prow
394
+ prev = @list[@prow-1].chomp
395
+ prevlen = prev.length
396
+ # 2008-12-26 21:37 delete previous line if nothing there. This moves entire buffer up.
397
+ if prevlen == 0
398
+ delete_line @prow-1
399
+ up
400
+ return
401
+ end
402
+ space_left = @maxlen - prev.length
403
+ # BUG. carry full words up, or if no space then bring down last word of prev lien and join with first
404
+ carry_up = words_in_length @buffer, space_left #@buffer[0..space_left] # XXX
405
+ if carry_up.nil?
406
+ # carry down last word
407
+ prev_wd = remove_last_word @prow-1
408
+ @buffer.insert 0, prev_wd
409
+ @curpos = prev_wd.length
410
+ $log.debug " carry up nil! prev_wd (#{prev_wd}) len:#{prev_wd.length}"
411
+ fire_handler :CHANGE, InputDataEvent.new(0,prev_wd.length, self, :INSERT, oldprow, prev_wd) # 2008-12-26 23:07
412
+ else
413
+ $log.debug " carrying up #{carry_up.length} #{carry_up}, space: #{space_left}"
414
+ @list[@prow-1]=prev + carry_up
415
+ space_left2 = @buffer[(carry_up.length+1)..-1]
416
+ @list[@prow]=space_left2 #if !space_left2.nil?
417
+ @list[@prow] ||= ""
418
+ up
419
+ addrowcol -1,0
420
+ @curpos = prevlen
421
+ fire_handler :CHANGE, InputDataEvent.new(oldcurpos,carry_up.length, self, :DELETE, oldprow, carry_up) # 2008-12-24 18:34
422
+ fire_handler :CHANGE, InputDataEvent.new(prevlen,carry_up.length, self, :INSERT, oldprow-1, carry_up) # 2008-12-24 18:34
423
+ end
424
+ @form.col = @orig_col + @col_offset + @curpos
425
+
426
+ # $log.debug "carry up: nil" if carry_up.nil?
427
+ # $log.debug "listrow nil " if @list[@prow].nil?
428
+ # $log.debug "carry up: #{carry_up} prow:#{@list[@prow]}"
429
+ end
430
+ ##
431
+ # return as many words as fit into len for carrying up..
432
+ # actually there is a case of when the next char (len+1) is a white space or word boundary. XXX
433
+ def words_in_length buff, len
434
+ return nil if len == 0
435
+ str = buff[0..len]
436
+ ix = str.rindex(/\s/)
437
+ $log.debug " str #{str} len #{len} ix #{ix} , buff #{buff}~"
438
+ return nil if ix.nil?
439
+ ix = ix > 0 ? ix - 1 : ix
440
+ $log.debug " str[]:#{str[0..ix]}~ len #{len} ix #{ix} , buff #{buff}~"
441
+ return str[0..ix]
442
+ end
443
+ # push the last word from given line to next
444
+ # I have modified it to push all words that are exceeding maxlen.
445
+ # This was needed for if i push 10 chars to next line, and the last word is less then the line will
446
+ # exceed. So i must push as many words as exceed length.
447
+ def push_last_word lineno=@prow
448
+ #lastspace = @buffer.rindex(" ")
449
+ #lastspace = @list[lineno].rindex(/ \w/)
450
+ line = @list[lineno]
451
+ line = @list[lineno][0..@maxlen+1] if line.length > @maxlen
452
+ lastspace = line.rindex(/ \w/)
453
+ $log.debug " PUSH:2 #{lastspace},#{line},"
454
+ if !lastspace.nil?
455
+ lastchars = @list[lineno][lastspace+1..-1]
456
+ @list[lineno] = @list[lineno][0..lastspace]
457
+ $log.debug "PUSH_LAST:ls:#{lastspace},lw:#{lastchars},lc:#{lastchars[-1]},:#{@list[lineno]}$"
458
+ if lastchars[-1,1] == "\r" or @list[lineno+1].nil?
459
+ # open a new line and keep the 10 at the end.
460
+ append_row lineno, lastchars
461
+ else
462
+ # check for soft tab \n - NO EVEN THIS LOGIC IS WRONG.
463
+ #if lastchars[-1,1] == "\n"
464
+ if lastchars[-1,1] != ' ' and @list[lineno+1][0,1] !=' '
465
+ #@list[lineno+1].insert 0, lastchars + ' '
466
+ insert_wrap lineno+1, 0, lastchars + ' '
467
+ else
468
+ #@list[lineno+1].insert 0, lastchars
469
+ insert_wrap lineno+1, 0, lastchars
470
+ end
471
+ end
472
+ return lastchars, lastspace
473
+ end
474
+ return nil
475
+ end
476
+ ##
477
+ # this attempts to recursively insert into a row, seeing that any stuff exceeding is pushed down further.
478
+ # Yes, it should check for a para end and insert. Currently it could add to next para.
479
+ def insert_wrap lineno, pos, lastchars
480
+ @list[lineno].insert pos, lastchars
481
+ len = @list[lineno].length
482
+ if len > @maxlen
483
+ push_last_word lineno #- sometime i may push down 10 chars but the last word is less
484
+ end
485
+ end
486
+ ##
487
+ # add one char. careful, i shoved a string in yesterday.
488
+ def putch char
489
+ @buffer ||= @list[@prow]
490
+ return -1 if !@editable #or @buffer.length >= @maxlen
491
+ if @chars_allowed != nil
492
+ return if char.match(@chars_allowed).nil?
493
+ end
494
+ raise "putch expects only one char" if char.length != 1
495
+ oldcurpos = @curpos
496
+ $log.debug "putch : pr:#{@prow}, cp:#{@curpos}, char:#{char}, lc:#{@buffer[-1]}, buf:(#{@buffer})"
497
+ @buffer.insert(@curpos, char)
498
+ @curpos += 1
499
+ $log.debug "putch INS: cp:#{@curpos}, max:#{@maxlen}, buf:(#{@buffer.length})"
500
+ if @curpos-1 > @maxlen or @buffer.length()-1 > @maxlen
501
+ lastchars, lastspace = push_last_word @prow
502
+ #$log.debug "last sapce #{lastspace}, lastchars:#{lastchars},lc:#{lastchars[-1]}, #{@list[@prow]} "
503
+ ## wrap on word XX If last char is 10 then insert line
504
+ @buffer = @list[@prow]
505
+ if @curpos-1 > @maxlen or @curpos-1 > @buffer.length()-1
506
+ ret = down
507
+ # keep the cursor in the same position in the string that was pushed down.
508
+ @curpos = oldcurpos - lastspace #lastchars.length # 0
509
+ end
510
+ end
511
+ set_form_row
512
+ @buffer = @list[@prow]
513
+ set_form_col
514
+ @modified = true
515
+ #fire_handler :CHANGE, self # 2008-12-09 14:56
516
+ fire_handler :CHANGE, InputDataEvent.new(oldcurpos,@curpos, self, :INSERT, @prow, char) # 2008-12-24 18:34
517
+ 0
518
+ end
519
+ def append_row lineno=@prow, chars=""
520
+ $log.debug "append row sapce:#{chars}."
521
+ @list.insert lineno+1, chars
522
+ end
523
+ ##
524
+ # removes and returns last word in given line number, or nil if no whitespace
525
+ def remove_last_word lineno
526
+ @list[lineno].chomp!
527
+ line=@list[lineno]
528
+ lastspace = line.rindex(" ")
529
+ if !lastspace.nil?
530
+ lastchars = line[lastspace+1..-1]
531
+ @list[lineno].slice!(lastspace..-1)
532
+ $log.debug " remove_last: lastspace #{lastspace},#{lastchars},#{@list[lineno]}"
533
+ fire_handler :CHANGE, InputDataEvent.new(lastspace,lastchars.length, self, :DELETE, lineno, lastchars) # 2008-12-26 23:06
534
+ return lastchars
535
+ end
536
+ return nil
537
+ end
538
+
539
+ def putc c
540
+ if c >= 32 and c <= 126
541
+ ret = putch c.chr
542
+ if ret == 0
543
+ # addcol 1
544
+ set_modified
545
+ return 0
546
+ end
547
+ end
548
+ return :UNHANDLED
549
+ end
550
+ # DELETE func
551
+ def delete_at index=@curpos
552
+ return -1 if !@editable
553
+ $log.debug "dele : #{@prow} #{@buffer} #{index}"
554
+ char = @buffer.slice!(@curpos,1) # changed added ,1 and take char for event
555
+ # if no newline at end of this then bring up prev character/s till maxlen
556
+ # NO WE DON'T DO THIS ANYLONGER 2008-12-26 21:09 lets see
557
+ =begin
558
+ if @buffer[-1,1]!="\r"
559
+ @buffer[-1]=" " if @buffer[-1,1]=="\n"
560
+ if !next_line.nil? and next_line.length > 0
561
+ move_chars_up
562
+ end
563
+ end
564
+ =end
565
+ #@modified = true 2008-12-22 15:31
566
+ set_modified true
567
+ #fire_handler :CHANGE, self # 2008-12-09 14:56
568
+ fire_handler :CHANGE, InputDataEvent.new(@curpos,@curpos, self, :DELETE, @prow, char) # 2008-12-24 18:34
569
+ end
570
+ # move up one char from next row to current, used when deleting in a line
571
+ # should not be called if line ends in "\r"
572
+ def move_char_up
573
+ @list[@prow] << @list[@prow+1].slice!(0)
574
+ delete_line(@prow+1) if next_line().length==0
575
+ end
576
+ # tries to move up as many as possible
577
+ # should not be called if line ends in "\r"
578
+ def move_chars_up
579
+ oldprow = @prow
580
+ oldcurpos = @curpos
581
+ space_left = @maxlen - @buffer.length
582
+ can_move = [space_left, next_line.length].min
583
+ carry_up = @list[@prow+1].slice!(0, can_move)
584
+ @list[@prow] << carry_up
585
+ delete_line(@prow+1) if next_line().length==0
586
+ fire_handler :CHANGE, InputDataEvent.new(oldcurpos,oldcurpos+can_move, self, :INSERT, oldprow, carry_up) # 2008-12-24 18:34
587
+ end
588
+ ## returns next line, does not move to it,
589
+ def next_line
590
+ @list[@prow+1]
591
+ end
592
+ def current_line
593
+ @list[@prow]
594
+ end
595
+ def do_relative_row num
596
+ yield @list[@prow+num]
597
+ end
598
+ def set_modified tf=true
599
+ @modified = tf
600
+ @form.modified = true if tf
601
+ end
602
+ def cursor_eol
603
+ $log.error "ERROR !!! bufferlen gt maxlen #{@buffer.length}, #{@maxlen}" if @buffer.length > @maxlen
604
+ set_form_col current_line().chomp().length()-1
605
+ end
606
+ def cursor_bol
607
+ set_form_col 0
608
+ end
609
+ def to_s
610
+ l = getvalue
611
+ str = ""
612
+ old = " "
613
+ l.each_with_index do |line, i|
614
+ tmp = line.gsub("\n","")
615
+ tmp.gsub!("\r", "\n")
616
+ if old[-1,1] !~ /\s/ and tmp[0,1] !~ /\s/
617
+ str << " "
618
+ end
619
+ str << tmp
620
+ old = tmp
621
+ end
622
+ str
623
+ end
624
+ end # class textarea
625
+ ##
626
+ # A viewable read only box. Can scroll.
627
+ # Intention is to be able to change content dynamically - the entire list.
628
+ # Use set_content to set content, or just update the list attrib
629
+ # TODO -
630
+ # - searching, goto line - DONE
631
+ class OldTextView < Widget
632
+ include Scrollable
633
+ dsl_accessor :height # height of viewport
634
+ dsl_accessor :title # set this on top
635
+ dsl_accessor :title_attrib # bold, reverse, normal
636
+ dsl_accessor :footer_attrib # bold, reverse, normal
637
+ dsl_accessor :list # the array of data to be sent by user
638
+ dsl_accessor :maxlen # max len to be displayed
639
+ attr_reader :toprow # the toprow in the view (offsets are 0)
640
+ attr_reader :prow # the row on which cursor/focus is
641
+ attr_reader :winrow # the row in the viewport/window
642
+ dsl_accessor :print_footer
643
+
644
+ def initialize form, config={}, &block
645
+ @focusable = true
646
+ @editable = false
647
+ @left_margin = 1
648
+ @row = 0
649
+ @col = 0
650
+ @show_focus = false # don't highlight row under focus
651
+ @list = []
652
+ super
653
+ @row_offset = @col_offset = 1
654
+ @orig_col = @col
655
+ # this does result in a blank line if we insert after creating. That's required at
656
+ # present if we wish to only insert
657
+ @scrollatrow = @height-2
658
+ @content_rows = @list.length
659
+ @win = @form.window
660
+ init_scrollable
661
+ print_borders
662
+ @maxlen ||= @width-2
663
+ end
664
+ ##
665
+ # send in a list
666
+ # e.g. set_content File.open("README.txt","r").readlines
667
+ #
668
+ def set_content list
669
+ @list = list
670
+ end
671
+ ## display this row on top
672
+ def top_row(*val)
673
+ if val.empty?
674
+ @toprow
675
+ else
676
+ @toprow = val[0] || 0
677
+ @prow = val[0] || 0
678
+ end
679
+ end
680
+ ## ---- for listscrollable ---- ##
681
+ def scrollatrow
682
+ @height - 2
683
+ end
684
+ def row_count
685
+ @list.length
686
+ end
687
+ ##
688
+ # returns row of first match of given regex (or nil if not found)
689
+ def find_first_match regex
690
+ @list.each_with_index do |row, ix|
691
+ return ix if !row.match(regex).nil?
692
+ end
693
+ return nil
694
+ end
695
+ def rowcol
696
+ #$log.debug "textarea rowcol : #{@row+@row_offset+@winrow}, #{@col+@col_offset}"
697
+ return @row+@row_offset+@winrow, @col+@col_offset
698
+ end
699
+ def wrap_text(txt, col = @maxlen)
700
+ $log.debug "inside wrap text for :#{txt}"
701
+ txt.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/,
702
+ "\\1\\3\n")
703
+ end
704
+ def print_borders
705
+ window = @form.window
706
+ color = $datacolor
707
+ window.print_border @row, @col, @height, @width, color
708
+ print_title
709
+ =begin
710
+ hline = "+%s+" % [ "-"*(width-((1)*2)) ]
711
+ hline2 = "|%s|" % [ " "*(width-((1)*2)) ]
712
+ window.printstring(row=startrow, col=startcol, hline, color)
713
+ print_title
714
+ (startrow+1).upto(startrow+height-1) do |row|
715
+ window.printstring( row, col=startcol, hline2, color)
716
+ end
717
+ window.printstring( startrow+height, col=startcol, hline, color)
718
+ =end
719
+
720
+ end
721
+ def print_title
722
+ @form.window.printstring( @row, @col+(@width-@title.length)/2, @title, $datacolor, @title_attrib) unless @title.nil?
723
+ end
724
+ def print_foot
725
+ @footer_attrib ||= Ncurses::A_REVERSE
726
+ footer = "R: #{@prow+1}, C: #{@curpos}, #{@list.length} lines "
727
+ @form.window.printstring( @row + @height, @col+2, footer, $datacolor, @footer_attrib)
728
+ end
729
+ ### FOR scrollable ###
730
+ def get_content
731
+ @list
732
+ end
733
+ def get_window
734
+ @form.window
735
+ end
736
+ ### FOR scrollable ###
737
+ def repaint # textview
738
+ paint
739
+ print_foot if @print_footer
740
+ end
741
+ def getvalue
742
+ @list
743
+ end
744
+ # textview
745
+ # [ ] scroll left right DONE
746
+ def handle_key ch
747
+ @buffer = @list[@prow]
748
+ if @buffer.nil? and @list.length == 0
749
+ @list << "\r"
750
+ @buffer = @list[@prow]
751
+ end
752
+ return if @buffer.nil?
753
+ $log.debug " before: curpos #{@curpos} blen: #{@buffer.length}"
754
+ if @curpos > @buffer.length
755
+ addcol(@buffer.length-@curpos)+1
756
+ @curpos = @buffer.length
757
+ end
758
+ $log.debug "TV after loop : curpos #{@curpos} blen: #{@buffer.length}"
759
+ pre_key
760
+ case ch
761
+ when ?\C-n
762
+ scroll_forward
763
+ when ?\C-p
764
+ scroll_backward
765
+ when ?0, ?\C-[
766
+ goto_start #start of buffer # cursor_start
767
+ when ?\C-]
768
+ goto_end # end / bottom cursor_end
769
+ when KEY_UP
770
+ #select_prev_row
771
+ ret = up
772
+ #addrowcol -1,0 if ret != -1 or @winrow != @oldwinrow # positions the cursor up
773
+ @form.row = @row + 1 + @winrow
774
+ when KEY_DOWN
775
+ ret = down
776
+ @form.row = @row + 1 + @winrow
777
+ when KEY_LEFT
778
+ cursor_backward
779
+ when KEY_RIGHT
780
+ cursor_forward
781
+ when KEY_BACKSPACE, 127
782
+ cursor_backward
783
+ when 330
784
+ cursor_backward
785
+ when ?\C-a
786
+ # take care of data that exceeds maxlen by scrolling and placing cursor at start
787
+ set_form_col 0
788
+ @pcol = 0
789
+ when ?\C-e
790
+ # take care of data that exceeds maxlen by scrolling and placing cursor at end
791
+ blen = @buffer.rstrip.length
792
+ if blen < @maxlen
793
+ set_form_col blen
794
+ else
795
+ @pcol = blen-@maxlen
796
+ set_form_col @maxlen-1
797
+ end
798
+ else
799
+ $log.debug("TEXTVIEW XXX ch #{ch}")
800
+ return :UNHANDLED
801
+ end
802
+ post_key
803
+ # XXX 2008-11-27 13:57 trying out
804
+ set_form_row
805
+ end
806
+ # puts cursor on correct row.
807
+ def set_form_row
808
+ @form.row = @row + 1 + @winrow
809
+ end
810
+ # set cursor on correct column tview
811
+ def set_form_col col=@curpos
812
+ @curpos = col
813
+ @form.col = @orig_col + @col_offset + @curpos
814
+ end
815
+ def cursor_forward
816
+ if @curpos < @width and @curpos < @maxlen-1 # else it will do out of box
817
+ @curpos += 1
818
+ addcol 1
819
+ else
820
+ # XXX 2008-11-26 23:03 trying out
821
+ @pcol += 1 if @pcol <= @buffer.length
822
+ end
823
+ end
824
+ def addcol num
825
+ @form.addcol num
826
+ end
827
+ def addrowcol row,col
828
+ @form.addrowcol row, col
829
+ end
830
+ def cursor_backward
831
+ if @curpos > 0
832
+ @curpos -= 1
833
+ addcol -1
834
+ elsif @pcol > 0 # XXX added 2008-11-26 23:05
835
+ @pcol -= 1
836
+ end
837
+ end
838
+ def next_line
839
+ @list[@prow+1]
840
+ end
841
+ def do_relative_row num
842
+ yield @list[@prow+num]
843
+ end
844
+ end # class textview
845
+ end # modul