rbcurse 1.4.1 → 1.5.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/CHANGELOG +31 -0
  2. data/README.markdown +69 -11
  3. data/VERSION +1 -1
  4. data/lib/rbcurse.rb +5 -5
  5. metadata +10 -198
  6. data/Makefile +0 -21
  7. data/Manifest.txt +0 -91
  8. data/TODO +0 -372
  9. data/TODO2.txt +0 -118
  10. data/examples/README.txt +0 -67
  11. data/examples/abasiclist.rb +0 -33
  12. data/examples/alpmenu.rb +0 -42
  13. data/examples/app.rb +0 -859
  14. data/examples/app.sample +0 -10
  15. data/examples/appdirtree.rb +0 -75
  16. data/examples/appemail.rb +0 -191
  17. data/examples/appemaillb.rb +0 -308
  18. data/examples/appgcompose.rb +0 -315
  19. data/examples/atree.rb +0 -64
  20. data/examples/common/file.rb +0 -40
  21. data/examples/common/rmail.rb +0 -257
  22. data/examples/data.txt +0 -683
  23. data/examples/data/README.markdown +0 -9
  24. data/examples/data/brew.txt +0 -38
  25. data/examples/data/color.2 +0 -37
  26. data/examples/data/gemlist.txt +0 -60
  27. data/examples/data/lotr.txt +0 -12
  28. data/examples/data/ports.txt +0 -136
  29. data/examples/data/tasks.txt +0 -27
  30. data/examples/data/todocsv.csv +0 -28
  31. data/examples/data/unix1.txt +0 -21
  32. data/examples/data/unix2.txt +0 -11
  33. data/examples/dbdemo.rb +0 -495
  34. data/examples/deprecated/appgmail.rb +0 -952
  35. data/examples/deprecated/splitp.rb +0 -56
  36. data/examples/deprecated/testscrolllb.rb +0 -86
  37. data/examples/deprecated/testscrollp.rb +0 -88
  38. data/examples/deprecated/testscrollta.rb +0 -80
  39. data/examples/deprecated/testscrolltable.rb +0 -165
  40. data/examples/deprecated/testsplit.rb +0 -87
  41. data/examples/deprecated/testsplit2.rb +0 -123
  42. data/examples/deprecated/testsplit3.rb +0 -215
  43. data/examples/deprecated/testsplit3_1.rb +0 -244
  44. data/examples/deprecated/testsplit3a.rb +0 -215
  45. data/examples/deprecated/testsplit3b.rb +0 -237
  46. data/examples/deprecated/testsplitta.rb +0 -148
  47. data/examples/deprecated/testsplittv.rb +0 -142
  48. data/examples/deprecated/testsplittvv.rb +0 -144
  49. data/examples/deprecated/testtpane.rb +0 -215
  50. data/examples/deprecated/testtpane2.rb +0 -145
  51. data/examples/deprecated/testtpanetable.rb +0 -203
  52. data/examples/dirtree.rb +0 -88
  53. data/examples/experimental/resultsetdemo.rb +0 -280
  54. data/examples/experimental/testmform.rb +0 -35
  55. data/examples/experimental/testscroller.rb +0 -117
  56. data/examples/experimental/teststackflow.rb +0 -111
  57. data/examples/menu1.rb +0 -112
  58. data/examples/multispl.rb +0 -86
  59. data/examples/newmessagebox.rb +0 -130
  60. data/examples/newtabbedwindow.rb +0 -100
  61. data/examples/newtesttabp.rb +0 -121
  62. data/examples/qdfilechooser.rb +0 -68
  63. data/examples/rfe.rb +0 -1195
  64. data/examples/rfe_renderer.rb +0 -121
  65. data/examples/sqlc.rb +0 -454
  66. data/examples/sqlm.rb +0 -437
  67. data/examples/sqlt.rb +0 -408
  68. data/examples/status.txt +0 -68
  69. data/examples/table1.rb +0 -24
  70. data/examples/term2.rb +0 -84
  71. data/examples/test1.rb +0 -239
  72. data/examples/test2.rb +0 -674
  73. data/examples/testapp.rb +0 -44
  74. data/examples/testapp2.rb +0 -58
  75. data/examples/testchars.rb +0 -137
  76. data/examples/testcombo.rb +0 -91
  77. data/examples/testkeypress.rb +0 -66
  78. data/examples/testlistbox.rb +0 -113
  79. data/examples/testmenu.rb +0 -101
  80. data/examples/testmulticomp.rb +0 -70
  81. data/examples/testmulticontainer.rb +0 -94
  82. data/examples/testmultispl.rb +0 -199
  83. data/examples/testree.rb +0 -106
  84. data/examples/testtable.rb +0 -263
  85. data/examples/testtabp.rb +0 -107
  86. data/examples/testtodo.rb +0 -584
  87. data/examples/testvimsplit.rb +0 -112
  88. data/examples/testwsshortcuts.rb +0 -64
  89. data/examples/testwsshortcuts2.rb +0 -126
  90. data/examples/todo.db +0 -0
  91. data/examples/todo.yml +0 -191
  92. data/examples/viewtodo.rb +0 -574
  93. data/lib/rbcurse/action.rb +0 -40
  94. data/lib/rbcurse/app.rb +0 -1374
  95. data/lib/rbcurse/applicationheader.rb +0 -102
  96. data/lib/rbcurse/celleditor.rb +0 -112
  97. data/lib/rbcurse/checkboxcellrenderer.rb +0 -57
  98. data/lib/rbcurse/colormap.rb +0 -159
  99. data/lib/rbcurse/comboboxcellrenderer.rb +0 -30
  100. data/lib/rbcurse/common/ansiparser.rb +0 -117
  101. data/lib/rbcurse/common/appmethods.rb +0 -112
  102. data/lib/rbcurse/common/basestack.rb +0 -407
  103. data/lib/rbcurse/common/bordertitle.rb +0 -41
  104. data/lib/rbcurse/common/chunk.rb +0 -177
  105. data/lib/rbcurse/common/colorparser.rb +0 -71
  106. data/lib/rbcurse/common/keydefs.rb +0 -30
  107. data/lib/rbcurse/common/widgetshortcuts.rb +0 -302
  108. data/lib/rbcurse/defaultlistselectionmodel.rb +0 -79
  109. data/lib/rbcurse/deprecated/README.markdown +0 -12
  110. data/lib/rbcurse/deprecated/rscrollpane.rb +0 -512
  111. data/lib/rbcurse/deprecated/rsplitpane.rb +0 -894
  112. data/lib/rbcurse/deprecated/rsplitpane2.rb +0 -1009
  113. data/lib/rbcurse/deprecated/rviewport.rb +0 -204
  114. data/lib/rbcurse/experimental/README.markdown +0 -14
  115. data/lib/rbcurse/experimental/resultsettextview.rb +0 -585
  116. data/lib/rbcurse/experimental/stackflow.rb +0 -478
  117. data/lib/rbcurse/extras/bottomline.rb +0 -1850
  118. data/lib/rbcurse/extras/box.rb +0 -58
  119. data/lib/rbcurse/extras/directorylist.rb +0 -467
  120. data/lib/rbcurse/extras/directorytree.rb +0 -69
  121. data/lib/rbcurse/extras/divider.rb +0 -310
  122. data/lib/rbcurse/extras/focusmanager.rb +0 -31
  123. data/lib/rbcurse/extras/horizlist.rb +0 -203
  124. data/lib/rbcurse/extras/listselectable.rb +0 -264
  125. data/lib/rbcurse/extras/masterdetail.rb +0 -166
  126. data/lib/rbcurse/extras/menutree.rb +0 -63
  127. data/lib/rbcurse/extras/multiform.rb +0 -330
  128. data/lib/rbcurse/extras/multilinelabel.rb +0 -142
  129. data/lib/rbcurse/extras/newmessagebox.rb +0 -328
  130. data/lib/rbcurse/extras/newtabbedpane.rb +0 -612
  131. data/lib/rbcurse/extras/newtabbedwindow.rb +0 -68
  132. data/lib/rbcurse/extras/padreader.rb +0 -189
  133. data/lib/rbcurse/extras/rcomboedit.rb +0 -256
  134. data/lib/rbcurse/extras/resultsetbrowser.rb +0 -281
  135. data/lib/rbcurse/extras/rlink.rb +0 -27
  136. data/lib/rbcurse/extras/rmenulink.rb +0 -21
  137. data/lib/rbcurse/extras/scrollbar.rb +0 -143
  138. data/lib/rbcurse/extras/statusline.rb +0 -94
  139. data/lib/rbcurse/extras/stdscrwindow.rb +0 -309
  140. data/lib/rbcurse/extras/tableextended.rb +0 -40
  141. data/lib/rbcurse/extras/tabular.rb +0 -264
  142. data/lib/rbcurse/extras/tabularwidget.rb +0 -1150
  143. data/lib/rbcurse/extras/textpad.rb +0 -516
  144. data/lib/rbcurse/extras/viewer.rb +0 -136
  145. data/lib/rbcurse/io.rb +0 -850
  146. data/lib/rbcurse/keylabelprinter.rb +0 -178
  147. data/lib/rbcurse/listcellrenderer.rb +0 -140
  148. data/lib/rbcurse/listeditable.rb +0 -310
  149. data/lib/rbcurse/listkeys.rb +0 -37
  150. data/lib/rbcurse/listscrollable.rb +0 -564
  151. data/lib/rbcurse/listselectable.rb +0 -142
  152. data/lib/rbcurse/mapper.rb +0 -130
  153. data/lib/rbcurse/orderedhash.rb +0 -77
  154. data/lib/rbcurse/ractionevent.rb +0 -67
  155. data/lib/rbcurse/rbasiclistbox.rb +0 -768
  156. data/lib/rbcurse/rchangeevent.rb +0 -27
  157. data/lib/rbcurse/rcombo.rb +0 -238
  158. data/lib/rbcurse/rcommandwindow.rb +0 -587
  159. data/lib/rbcurse/rcontainer.rb +0 -415
  160. data/lib/rbcurse/rdialogs.rb +0 -451
  161. data/lib/rbcurse/rinputdataevent.rb +0 -47
  162. data/lib/rbcurse/rlistbox.rb +0 -1196
  163. data/lib/rbcurse/rmenu.rb +0 -939
  164. data/lib/rbcurse/rmessagebox.rb +0 -348
  165. data/lib/rbcurse/rmulticontainer.rb +0 -304
  166. data/lib/rbcurse/rmultisplit.rb +0 -722
  167. data/lib/rbcurse/rmultitextview.rb +0 -306
  168. data/lib/rbcurse/rpopupmenu.rb +0 -755
  169. data/lib/rbcurse/rprogress.rb +0 -118
  170. data/lib/rbcurse/rscrollform.rb +0 -418
  171. data/lib/rbcurse/rtabbedpane.rb +0 -1158
  172. data/lib/rbcurse/rtabbedwindow.rb +0 -167
  173. data/lib/rbcurse/rtable.rb +0 -1718
  174. data/lib/rbcurse/rtextarea.rb +0 -920
  175. data/lib/rbcurse/rtextview.rb +0 -761
  176. data/lib/rbcurse/rtree.rb +0 -780
  177. data/lib/rbcurse/rvimsplit.rb +0 -763
  178. data/lib/rbcurse/rwidget.rb +0 -2915
  179. data/lib/rbcurse/scrollable.rb +0 -301
  180. data/lib/rbcurse/table/tablecellrenderer.rb +0 -86
  181. data/lib/rbcurse/table/tabledatecellrenderer.rb +0 -98
  182. data/lib/rbcurse/tree/treecellrenderer.rb +0 -150
  183. data/lib/rbcurse/tree/treemodel.rb +0 -428
  184. data/lib/rbcurse/undomanager.rb +0 -188
  185. data/lib/rbcurse/vieditable.rb +0 -144
  186. data/lib/ver/keyboard.rb +0 -150
  187. data/lib/ver/keyboard2.rb +0 -170
  188. data/lib/ver/ncurses.rb +0 -218
  189. data/lib/ver/panel.rb +0 -162
  190. data/lib/ver/rpad.rb +0 -375
  191. data/lib/ver/window.rb +0 -882
  192. data/test/test_rbcurse.rb +0 -0
@@ -1,306 +0,0 @@
1
- =begin
2
- * Name: MultiTextView
3
- * Description View text in this widget for multiple files
4
- * This differs from multicontainer in that since all components are textviews, so they
5
- * are all gauranteed to be non-editable and thus we can map many more keys.
6
- * MultiContainer can only map Ctrl and Alt (Meta) keys.
7
- * Author: rkumar (arunachalesha)
8
- * file created 2010-03-11 08:05
9
- --------
10
- * License:
11
- Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
12
-
13
- =end
14
- require 'logger'
15
- require 'rbcurse'
16
- require 'rbcurse/rtextview'
17
- require 'rbcurse/listscrollable'
18
-
19
- #include Ncurses # FFI 2011-09-8
20
- include RubyCurses
21
- module RubyCurses
22
- extend self
23
-
24
- ##
25
- # A viewable read only box. Can scroll.
26
- # Extends TextView with ability to load more than one file or content
27
- # and switch between files (buffers).
28
- # NOTE: ideally, i should be able to dynamically add this functionality to either Textview
29
- # or TextArea or even ListBox or Table someday. Should then be a Module rather than a class.
30
- class MultiTextView < TextView
31
- include ListScrollable
32
-
33
- def initialize form = nil, config={}, &block
34
-
35
- super
36
- @bmanager = BufferManager.new self
37
-
38
- end
39
- def init_vars
40
- super
41
- bind_key(?:, :buffer_menu)
42
- bind_key(?e, :file_edit)
43
- bind_key([?\C-x, ?f], :file_edit)
44
- bind_key([?\C-x, ?k], :buffer_delete)
45
- bind_key([?\C-x, ?\C-b], :buffers_list)
46
- # easily cycle using p. n is used for next search.
47
- bind_key(?p, :buffer_previous)
48
- end
49
- ## returns current buffer
50
- # @return [RBuffer] current buffer
51
- def current_buffer
52
- @bmanager.current
53
- end
54
- ##
55
- # send in a list
56
- # e.g. set_content File.open("README.txt","r").readlines
57
- # set wrap at time of passing :WRAP_NONE :WRAP_WORD
58
- # @see add (add takes a title too which is required here)
59
- def set_content list, wrap = :WRAP_NONE
60
- ret = super
61
- # buff = @bmanager.add_content @list
62
- return ret
63
- end
64
- # multi-textview
65
- def handle_key ch
66
- # put list as current list and buffer too then super
67
- #@current_buffer = @bmanager.current
68
- #@list = @current_buffer.list
69
- @buffer = @list[@current_index]
70
- #@buffer = @bmanager.current
71
- ret = super
72
- # check for any keys not handled and check our own ones
73
- return ret #
74
- end
75
- ## prompt user for a filename to read in
76
- def getfilename prompt="Enter filename: ", maxlen=90
77
- tabc = Proc.new {|str| Dir.glob(str +"*") }
78
- config={}; config[:tab_completion] = tabc
79
- #config[:default] = "defaulT"
80
- $log.debug " inside getstr before call #{$error_message_row} + #{$error_message_col} "
81
- #ret, str = rbgetstr(@form.window, @row+@height-1, @col+1, prompt, maxlen, config)
82
- ret, str = rbgetstr(@form.window, $error_message_row, $error_message_col, prompt, maxlen, config)
83
- $log.debug " rbgetstr returned #{ret} , #{str} "
84
- return "" if ret != 0
85
- return str
86
- end
87
- # this is just a test of the simple "most" menu
88
- # can use this for next, prev, first, last, new, delete, overwrite etc
89
- def buffer_menu
90
- menu = PromptMenu.new self
91
- menu.add(menu.create_mitem( 'e', "edit a file", "opened file ", :file_edit ))
92
- menu.add(menu.create_mitem( 'o', "overwrite file", "opened a file ", :file_overwrite ))
93
- menu.add(menu.create_mitem( 'l', "list buffers", "list buffers ", :buffers_list ))
94
- item = menu.create_mitem( 'b', "Buffer Options", "Buffer Options" )
95
- menu1 = PromptMenu.new( self, "Buffer Options")
96
- menu1.add(menu1.create_mitem( 'n', "Next", "Switched to next buffer", :buffer_next ))
97
- menu1.add(menu1.create_mitem( 'p', "Prev", "Switched to previous buffer", :buffer_previous ))
98
- menu1.add(menu1.create_mitem( 'f', "First", "Switched to first buffer", :buffer_first ))
99
- menu1.add(menu1.create_mitem( 'l', "Last", "Switched to last buffer", :buffer_last ))
100
- menu1.add(menu1.create_mitem( 'd', "Delete", "Deleted buffer", :buffer_delete ))
101
- item.action = menu1
102
- menu.add(item)
103
- # how do i know what's available. the application or window should know where to place
104
- menu.display @form.window, $error_message_row, $error_message_col, $datacolor #, menu
105
- end
106
-
107
- %w[next previous first last].each do |pos|
108
- eval(
109
- "def _buffer_#{pos}
110
- @current_buffer = @bmanager.#{pos}
111
- set_current_buffer
112
- end"
113
- )
114
- end
115
-
116
- def buffer_next
117
- perror "No other buffer" and return if @bmanager.size < 2
118
-
119
- @current_buffer = @bmanager.next
120
- set_current_buffer
121
- end
122
- def buffer_previous
123
- perror "No other buffer" and return if @bmanager.size < 2
124
-
125
- @current_buffer = @bmanager.previous
126
- $log.debug " buffer_prev got #{@current_buffer} "
127
- set_current_buffer
128
- end
129
- def buffer_first
130
- @current_buffer = @bmanager.first
131
- $log.debug " buffer_first got #{@current_buffer} "
132
- set_current_buffer
133
- end
134
- def buffer_last
135
- @current_buffer = @bmanager.last
136
- $log.debug " buffer_last got #{@current_buffer} "
137
- set_current_buffer
138
- end
139
- def buffer_delete
140
- if @bmanager.size > 1
141
- @bmanager.delete_at
142
- @current_buffer = @bmanager.previous
143
- set_current_buffer
144
- else
145
- perror "Only one buffer. Cannot delete."
146
- end
147
- end
148
- def buffers_list
149
- menu = PromptMenu.new self
150
- @bmanager.each_with_index{ |b, ix|
151
- aproc = Proc.new { buffer_at(ix) }
152
- name = b.title
153
- num = ix + 1
154
- menu.add(menu.create_mitem( num.to_s, name, "Switched to buffer #{ix}", aproc ))
155
- }
156
- menu.display @form.window, $error_message_row, $error_message_col, $datacolor
157
- end
158
- # prompts user for filename and opens in buffer
159
- # Like vim's :e
160
- def file_edit
161
- file = getfilename()
162
- $log.debug " got file_edit: #{file} "
163
- return if file == ""
164
- add file, file
165
- end
166
- # load a file into the textview.
167
- # This is the preferred method since it lets us add a title too
168
- # Shucks, this misses wrap_style which the other one has
169
- # @param [String] filename
170
- def add file, title
171
- begin
172
- @current_buffer = @bmanager.add file, title
173
- $log.debug " file edit got cb : #{@current_buffer} "
174
- set_current_buffer
175
- rescue => err
176
- alert err.to_s
177
- Ncurses.beep
178
- return -1
179
- end
180
- end
181
- def buffer_at index
182
- @current_buffer = @bmanager.element_at index
183
- $log.debug " buffer_last got #{@current_buffer} "
184
- set_current_buffer
185
- end
186
- def set_current_buffer
187
- @current_index = @current_buffer.current_index
188
- @curpos = @current_buffer.curpos
189
- @title = @current_buffer.title
190
- @list = @current_buffer.list
191
- end
192
- def perror errmess
193
- #@form.window.print_error_message errmess
194
- alert errmess
195
- end
196
- end # class multitextview
197
- ##
198
- # Handles multiple buffers, navigation, maintenance etc
199
- # Instantiated at startup of MultiTextView
200
- #
201
- class BufferManager
202
- include Enumerable
203
- def initialize source
204
- @source = source
205
- @buffers = [] # contains RBuffer
206
- @counter = 0
207
- # for each buffer i need to store data, current_index (row), curpos (col offset) and title (filename).
208
- end
209
- def element_at index
210
- @buffers[index]
211
- end
212
- def each
213
- @buffers.each {|k| yield(k)}
214
- end
215
- ##
216
- # @return [RBuffer] current buffer/file
217
- ##
218
- def current
219
- @buffers[@counter]
220
- end
221
- ##
222
- # Would have liked to just return next buffer and not get lost in details of caller
223
- #
224
- # @return [RBuffer] next buffer/file
225
- ##
226
- def next
227
- @counter += 1
228
- @counter = 0 if @counter >= @buffers.size
229
- @buffers[@counter]
230
- end
231
- ##
232
- # @return [RBuffer] previous buffer/file
233
- ##
234
- def previous
235
- $log.debug " previous bs: #{@buffers.size}, #{@counter} "
236
- @counter -= 1
237
- return last() if @counter < 0
238
- $log.debug " previous ctr #{@counter} "
239
- @buffers[@counter]
240
- end
241
- def first
242
- @counter = 0
243
- @buffers[@counter]
244
- end
245
- def last
246
- @counter = @buffers.size - 1
247
- @buffers[@counter]
248
- end
249
- ##
250
- def delete_at index=@counter
251
- @buffers.delete_at index
252
- end
253
- def delete_by_name name
254
- @buffers.delete_if {|b| b.filename == name }
255
- end
256
- def insert filename, position, title=nil
257
- # read up file
258
- lines = File.open(filename,"r").readlines
259
- $log.debug "multitextview loaded #{filename}, #{lines.size} lines " if $log.debug?
260
- list = @source.set_content lines
261
- # set new RBuffer
262
- title = filename unless title
263
- raise "invalid value for list, Should be an array #{list.class} " unless list.is_a? Array
264
- anew = RBuffer.new(list, 0, 0, filename, title)
265
- #@buffers << anew
266
- @buffers.insert position, anew
267
- @counter = position
268
- return anew
269
- end
270
- def add filename, title=nil
271
- insert filename, @buffers.size, title
272
- end
273
- def insert_content str, position, title="UNTitled"
274
- case str
275
- when String
276
- # put str into list
277
- @source.set_content str
278
- list = @list
279
- when Array
280
- list = str
281
- end
282
- anew = RBuffer.new(list, 0, 0, "", title)
283
- #@buffers << anew
284
- @buffers.insert position, anew
285
- @counter = position
286
- return anew
287
- end
288
- # add content (array or str) to buffer list as a new buffer
289
- def add_content str, title="UNtitled"
290
- $log.debug " inside BUFFER MANAGER "
291
- insert_content str, @buffers.size, title
292
- end
293
- def size
294
- @buffers.size
295
- end
296
- alias :count :size
297
- def index buff
298
- return @buffers.index
299
- end
300
- end
301
- RBuffer = Struct.new(:list, :current_index, :curpos, :filename, :title) do
302
- def xxx
303
- end
304
- end
305
-
306
- end # modul
@@ -1,755 +0,0 @@
1
- =begin
2
- * Name: rpopupmenu - this is based on the crappy menubar code and needs a rewrite.
3
- * Description
4
- * Author: rkumar
5
- TODO
6
- - Action: may have to listen to Action property changes so enabled, name etc change can be reflected
7
- - menu bar : what to do if adding a menu, or option later.
8
- we dnt show disabld options in a way that user can know its disabled
9
- - separate file created on 2008-12-24 17:58
10
-
11
- Mnemonic should highlight the row if its a menu.
12
- NOTE : this program works but is one of the first programs and is untouched. It needs to be rewritten
13
- since its quite crappy.
14
- Also, we should move to Action classes as against just blokcs of code. And action class would have
15
- a user friendly string to identifiy the action, as well as a disabled option.
16
-
17
- I am prefixing class names since they are same as those in rmenu and there's
18
- some crashing happening when i first execcute rmenu in one app then rpopupmenu
19
- in another.
20
-
21
- --------
22
- * Date: 2008-11-14 23:43
23
- * License:
24
- Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
25
-
26
- =end
27
- require 'logger'
28
- require 'rbcurse'
29
- require 'rbcurse/action'
30
-
31
- #include Ncurses # FFI 2011-09-8
32
- include RubyCurses
33
- module RubyCurses
34
- extend self
35
-
36
-
37
- class PMenuSeparator
38
- attr_accessor :enabled
39
- attr_accessor :parent
40
- attr_accessor :row
41
- attr_accessor :col
42
- attr_accessor :width
43
- def initialize
44
- @enable = false
45
- end
46
- def repaint
47
- @parent.window.printstring( @row, 0, "|%s|" % ("-"*@width), $reversecolor)
48
- end
49
- def destroy
50
- end
51
- def on_enter
52
- end
53
- def on_leave
54
- end
55
- def to_s
56
- ""
57
- end
58
- end
59
- ##
60
- class PMenuItem
61
- attr_accessor :parent
62
- # attr_accessor :window
63
- attr_accessor :row
64
- attr_accessor :col
65
- attr_accessor :width
66
- attr_accessor :accelerator
67
- attr_accessor :enabled
68
- attr_accessor :mnemonic # changed reader to accessor
69
- def initialize txt, mnemonic=nil, &block
70
- @mnemonic = mnemonic
71
- text txt
72
- @enabled = true
73
- instance_eval &block if block_given?
74
- end
75
- ##
76
- # changed so ampersand can be mnemonic esp when action comes in
77
- def text s
78
- s = s.dup # since actions are being shared
79
- if (( ix = s.index('&')) != nil)
80
- s.slice!(ix,1)
81
- #@underline = ix unless @form.nil? # this setting a fake underline in messageboxes
82
- @mnemonic = s[ix,1]
83
- end
84
- @text = s
85
- end
86
- def to_s
87
- "#{@text} #{@accelerator}"
88
- end
89
- def command *args, &block
90
- $log.debug ">>>command : #{@text} "
91
- @command = block if block_given?
92
- @args = args
93
- end
94
- def on_enter
95
- $log.debug ">>>on enter Pmenuitem : #{@text} #{@row} #{@width} "
96
- highlight
97
- end
98
- def on_leave
99
- $log.debug ">>>on leave Pmenuitem : #{@text} "
100
- highlight false
101
- end
102
- ## XXX it could be a menu again
103
- def fire
104
- $log.debug ">>>fire Pmenuitem : #{@text} #{@command} "
105
- @command.call self, *@args if !@command.nil?
106
- @parent.clear_menus
107
- return :CLOSE # added 2009-01-02 00:09 to close only actions, not submenus
108
- end
109
- def highlight tf=true
110
- if tf
111
- color = $datacolor
112
- #@parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_NORMAL, color, nil)
113
- # above line did not work in vt100, 200 terminals, next works.
114
- @parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_REVERSE, $reversecolor, nil)
115
- else
116
- repaint
117
- end
118
- @parent.window.wrefresh
119
- end
120
- def repaint # menuitem.repaint
121
- if @parent.nil? or @parent.window.nil?
122
- $log.debug " #{self} parent nil"
123
- return
124
- end
125
- r = @row
126
- acolor = $reversecolor
127
- acolor = get_color($reversecolor, 'green', 'white') if !@enabled
128
- @parent.window.printstring( @row, 0, "|%-*s|" % [@width, @text], acolor)
129
- if !@accelerator.nil?
130
- @parent.window.printstring( r, (@width+1)-@accelerator.length, @accelerator, acolor)
131
- else
132
- #@parent.window.printstring( r, (@width+1)-1, ".", acolor)
133
- end
134
- if !@mnemonic.nil?
135
- m = @mnemonic
136
- ix = @text.index(m) || @text.index(m.swapcase)
137
- charm = @text[ix,1]
138
- #@parent.window.printstring( r, ix+1, charm, $datacolor) if !ix.nil?
139
- # prev line changed since not working in vt100 and vt200
140
- #@parent.window.printstring( r, ix+1, charm, $reversecolor, 'reverse') if !ix.nil?
141
- @parent.window.mvchgat(y=r, x=ix+1, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, acolor, nil)
142
- end
143
- end
144
- def destroy
145
- $log.debug "DESTRY menuitem #{@text}"
146
- end
147
- end
148
- class PMenu < PMenuItem
149
- attr_accessor :parent
150
- attr_accessor :row
151
- attr_accessor :col
152
- attr_accessor :width
153
- attr_accessor :enabled
154
- #attr_reader :text
155
- attr_reader :items
156
- attr_reader :window
157
- attr_reader :panel
158
- attr_reader :current_menu
159
- attr_reader :row_margin
160
- @@menus = []
161
- @@row = 0
162
- @@col = 0
163
-
164
- def initialize text, &block
165
- super text, nil, &block
166
- @items = []
167
- @enabled = true
168
- @current_menu = []
169
- instance_eval &block if block_given?
170
- @row ||=10
171
- @col ||=10
172
- @@menus ||= []
173
- end
174
- def to_s
175
- @text
176
- end
177
- def clear_menus
178
- @@menus = []
179
- end
180
- # create a Menuitem given an Action
181
- # if menuitem.kind_of? RubyCurses::Action
182
- def create_action_component action
183
- m = PMenuItem.new(action.name, action.mnemonic)
184
- m.command { action.call }
185
- m.accelerator = action.accelerator
186
- return m
187
- end
188
- # item could be menuitem or another menu or a string or a Action
189
- # support for action added 2009-01-21 18:08
190
- def add menuitem
191
- insert menuitem, @items.size
192
- return self
193
- end
194
- ##
195
- # added 2009-01-20 13:28 NEW
196
- def insert menuitem, ix
197
- if menuitem.kind_of? RubyCurses::Action
198
- menuitem = create_action_component menuitem
199
- end
200
- @items.insert ix, menuitem
201
- return self
202
- end
203
- def insert_separator ix
204
- @items.insert ix, PMenuSeparator.new
205
- end
206
- def add_separator
207
- @items << PMenuSeparator.new
208
- end
209
- def get_item i
210
- @items[i]
211
- end
212
- def remove n
213
- if n.is_a? Fixnum
214
- @items.delete_at n
215
- else
216
- @items.delete n
217
- end
218
- end
219
- # menu -
220
- def fire
221
- $log.debug "menu fire called: #{@text} "
222
- if @window.nil?
223
- #repaint
224
- create_window
225
- if !@parent.is_a? RubyCurses::PMenuBar
226
- $log.debug " ADDING self to current menu: #{self}"
227
- # xxx highlight true
228
- @parent.current_menu << self
229
- @@menus << self
230
-
231
- $log.debug "DDD #{@@menus} << #{self}"
232
- end
233
- else
234
- ### shouod this not just show ?
235
- $log.debug "menu fire called: #{@text} ELSE XXX WHEN IS THIS CALLED ? 658 "
236
- return @items[@active_index].fire # this should happen if selected. else selected()
237
- end
238
- #@action.call if !@action.nil?
239
- end
240
- # user has clicked down, we shoud display items
241
- # DRAW menuitems
242
- def repaint # menu.repaint
243
- return if @items.nil? or @items.empty?
244
- $log.debug "menu repaint: #{@text} row #{@row} col #{@col} "
245
- if !@parent.is_a? RubyCurses::PMenuBar
246
- @parent.window.printstring( @row, 0, "|%-*s>|" % [@width-1, @text], $reversecolor)
247
- # added 2009-01-23 00:49
248
- if !@mnemonic.nil?
249
- m = @mnemonic
250
- ix = @text.index(m) || @text.index(m.swapcase)
251
- charm = @text[ix,1]
252
- #@parent.window.printstring( r, ix+1, charm, $datacolor) if !ix.nil?
253
- # prev line changed since not working in vt100 and vt200
254
- #@parent.window.printstring( @row, ix+1, charm, $reversecolor, 'reverse') if !ix.nil?
255
- # 2009-01-23 13:03 replaced reverse with ul
256
- @parent.window.mvchgat(y=@row, x=ix+1, max=1, Ncurses::A_BOLD|Ncurses::A_UNDERLINE, $reversecolor, nil)
257
- end
258
- @parent.window.refresh
259
- end
260
- if @window.nil?
261
- #create_window
262
- else
263
- @window.show
264
- select_item 0
265
- @window.refresh
266
- end
267
- end
268
- ##
269
- # recursive if given one not enabled goes to next enabled
270
- def select_item ix0
271
- return if @items.nil? or @items.empty?
272
- $log.debug "insdie select item : #{ix0}"
273
- if !@active_index.nil?
274
- @items[@active_index].on_leave
275
- end
276
- previtem = @active_index
277
- @active_index = ix0
278
- if @items[ix0].enabled
279
- @items[ix0].on_enter
280
- else
281
- $log.debug "insdie sele nxt item ENABLED FALSE : #{ix0}"
282
- if @active_index > previtem
283
- select_next_item
284
- else
285
- select_prev_item
286
- end
287
- end
288
- @window.refresh
289
- end
290
- def select_next_item
291
- return if @items.nil? or @items.empty?
292
- $log.debug "insdie sele nxt item : #{@active_index}"
293
- @active_index = -1 if @active_index.nil?
294
- if @active_index < @items.length-1
295
- select_item @active_index + 1
296
- else
297
- # select_item 0
298
- end
299
- end
300
- def select_prev_item
301
- return if @items.nil? or @items.empty?
302
- $log.debug "insdie sele prv item : #{@active_index}"
303
- if @active_index > 0
304
- select_item @active_index - 1
305
- else
306
- #select_item @items.length-1
307
- end
308
- end
309
- def on_enter # menu.on_enter
310
- $log.debug "menu onenter: #{@text} #{@row} #{@col} "
311
- # call parent method. XXX
312
- if @parent.is_a? RubyCurses::PMenuBar
313
- @parent.window.printstring( @row, @col, " %s " % @text, $datacolor)
314
- else
315
- highlight
316
- end
317
- if !@window.nil? #and @parent.selected
318
- $log.debug "menu onenter: #{@text} calling window,show"
319
- @window.show
320
- select_item 0
321
- elsif @parent.is_a? RubyCurses::PMenuBar and @parent.selected
322
- # only on the top level do we open a window if a previous one was opened
323
- $log.debug "menu onenter: #{@text} calling repaint CLASS: #{@parent.class}"
324
- # repaint
325
- create_window
326
- end
327
- end
328
- def on_leave # menu.on_leave
329
- $log.debug "menu onleave: #{@text} #{@row} #{@col} "
330
- # call parent method. XXX
331
- if @parent.is_a? RubyCurses::PMenuBar
332
- @parent.window.printstring( @row, @col, " %s " % @text, $reversecolor)
333
- @window.hide if !@window.nil?
334
- else
335
- $log.debug "MENU SUBMEN. menu onleave: #{@text} #{@row} #{@col} will pop !! "
336
- # parent is a menu
337
- highlight false
338
- #@parent.current_menu.pop
339
- #@@menus.pop
340
- #destroy
341
- end
342
- end
343
- def highlight tf=true # menu
344
- $log.debug "MENU SUBMENU menu highlight: #{@text} #{@row} #{@col}, PW #{@parent.width} "
345
- color = tf ? $datacolor : $reversecolor
346
- att = tf ? Ncurses::A_REVERSE : Ncurses::A_NORMAL
347
- #@parent.window.mvchgat(y=@row, x=1, @width, Ncurses::A_NORMAL, color, nil)
348
- #@parent.window.mvchgat(y=@row, x=1, @parent.width, Ncurses::A_NORMAL, color, nil)
349
- # above line did not work with vt100/vt200 next does
350
- @parent.window.mvchgat(y=@row, x=1, @parent.width, att, $reversecolor, nil)
351
- @parent.window.wrefresh
352
- end
353
- def create_window # menu XXX
354
- margin = 3
355
- @width = array_width @items
356
- $log.debug "create window menu #{@text}: #{@row} ,#{@col},parent: #{@parent}, wd #{@width} "
357
- #$log.debug "create window menu parent: #{@parent.row}, " unless @parent.nil?
358
- @row_margin = 1 #+ @@row
359
- @row_margin = @parent.row+@parent.row_margin unless @parent.nil?
360
- #@row = @parent.row unless @parent.nil?
361
- @layout = { :height => @items.length+3, :width => @width+margin, :top => @row+@row_margin, :left => @col }
362
- @win = VER::Window.new(@layout)
363
- @window = @win
364
- @win.bkgd(Ncurses.COLOR_PAIR($datacolor));
365
- @panel = @win.panel
366
- @window.printstring( 0, 0, "+%s+" % ("-"*@width), $reversecolor)
367
- r = 1
368
- @items.each do |item|
369
- item.row = r
370
- item.col = 0
371
- item.col = @col+@width+margin # margins???
372
- item.width = @width
373
- #item.window = @window
374
- item.parent = self
375
- item.repaint
376
- #end
377
- r+=1
378
- end
379
- @window.printstring( r, 0, "+%s+" % ("-"*@width), $reversecolor)
380
- select_item 0
381
- @window.refresh
382
- return @window
383
- end
384
- # private
385
- def array_width a
386
- longest = a.max {|a,b| a.to_s.length <=> b.to_s.length }
387
- $log.debug "array width #{longest}"
388
- longest.to_s.length
389
- end
390
- def destroy
391
- $log.debug "DESTRY menu #{@text}"
392
- return if @window.nil?
393
- @visible = false
394
- panel = @window.panel
395
- Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
396
- @window.delwin if !@window.nil? # FFI
397
- @items.each do |item|
398
- #next if item == :SEPARATOR
399
- item.destroy
400
- end
401
- @window = nil
402
- end
403
- # menu LEFT, RIGHT, DOWN, UP, ENTER
404
- # item could be Pmenuitem or another menu
405
- #
406
- def handle_key ch
407
- #if !@current_menu.empty?
408
- # cmenu = @current_menu.last
409
- #else
410
- # cmenu = self
411
- #end
412
- if !@@menus.empty?
413
- cmenu = @@menus.last
414
- else
415
- cmenu = self
416
- end
417
- $log.debug " CMENU is #{cmenu}: #{@@menus} "
418
- case ch
419
- when KEY_DOWN
420
- cmenu.select_next_item
421
- when KEY_UP
422
- cmenu.select_prev_item
423
- when KEY_ENTER, 10, 13, 32 # added 32 2008-11-28 23:50
424
- return cmenu.fire
425
- when KEY_LEFT
426
- if cmenu.parent.is_a? RubyCurses::PMenu
427
- $log.debug "LEFT IN MENU : #{cmenu.parent.class} len: #{cmenu.parent.current_menu.length}"
428
- $log.debug "left IN MENU : #{cmenu.parent.class} len: #{cmenu.current_menu.length}"
429
- end
430
- if cmenu.parent.is_a? RubyCurses::PMenu and !cmenu.parent.current_menu.empty?
431
- $log.debug " ABOU TO DESTROY DUE TO LEFT"
432
- cmenu.parent.current_menu.pop
433
- @@menus.pop
434
- cmenu.destroy
435
- else
436
- $log.debug " returning UNHANDLED 370"
437
- return :UNHANDLED
438
- end
439
- when KEY_RIGHT
440
- $log.debug "RIGHTIN MENU : "
441
- if cmenu.parent.is_a? RubyCurses::PMenu
442
- $log.debug "right IN MENU : #{cmenu.parent.class} len: #{cmenu.parent.current_menu.length}"
443
- $log.debug "right IN MENU : #{cmenu.parent.class} len: #{cmenu.current_menu.length}"
444
- end
445
- if cmenu.parent.is_a? RubyCurses::PMenu and !cmenu.parent.current_menu.empty?
446
- $log.debug " ABOU TO DESTROY DUE TO RIGHT"
447
- cmenu.parent.current_menu.pop
448
- @@menus.pop
449
- cmenu.destroy
450
- end
451
- return :UNHANDLED
452
- else
453
- ret = check_mnemonics cmenu, ch
454
- return ret
455
- end
456
- end
457
- ##
458
- # checks given key against current menu's items and fires key if
459
- # added on 2008-11-27 12:07
460
- def check_mnemonics cmenu, ch
461
- # $log.debug "inside check_mnemonics #{ch}"
462
- key = ch.chr.downcase rescue ""
463
- cmenu.items.each_with_index do |item, ix|
464
- next if !item.respond_to? :mnemonic or item.mnemonic.nil?
465
- # $log.debug "inside check_mnemonics #{item.mnemonic}"
466
- if key == item.mnemonic.downcase
467
- cmenu.select_item ix # 2009-01-23 13:32 so focus moves to menu
468
- ret = item.fire
469
- return ret # 0 # 2009-01-23 00:43 Pmenuitem returns CLOSE, menu 0
470
- end
471
- end
472
- return :UNHANDLED
473
- end
474
- ## menu
475
- def show # menu.show
476
- $log.debug "show (menu) : #{@text} "
477
- if @window.nil?
478
- create_window
479
- end
480
- @window.show
481
- select_item 0
482
- end
483
- end
484
- class PopupMenu < PMenu
485
- def initialize text, &block
486
- @row_margin = 0
487
- @@row = 0
488
- @@col = 0
489
- super
490
- instance_eval &block if block_given?
491
- end
492
- def show component, x, y
493
- @component = component
494
- @@row = component.row
495
- @@col = component.col
496
- create_window
497
- handle_keys
498
- end
499
- def handle_keys # popup
500
- @toggle_key ||= 27 # default switch off with ESC, if nothing else defined
501
- begin
502
- catch(:menubarclose) do
503
- while((ch = @window.getchar()) != @toggle_key )
504
- case ch
505
- when -1
506
- next
507
- else
508
- ret = handle_key ch
509
- $log.debug " POPUP got #{ret} added 2009-01-21 18:18 "
510
- break if ret == :CLOSE
511
- end
512
- Ncurses::Panel.update_panels();
513
- Ncurses.doupdate();
514
-
515
- @window.wrefresh
516
- end
517
- end # catch
518
- ensure
519
- #ensure is required becos one can throw a :close
520
- @@menus = [] # added 2009-01-23 13:21
521
- destroy # Note that we destroy the menu bar upon exit
522
- end
523
- end
524
- def destroy
525
- $log.debug "DESTRY popup "
526
- @visible = false
527
- panel = @window.panel
528
- Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
529
- @window.delwin if !@window.nil? # FFI
530
- @items.each do |item|
531
- item.destroy
532
- end
533
- @window = nil
534
- end
535
- end # class
536
- ##
537
- # An application related menubar.
538
- # Currently, I am adding this to a form. But should this not be application specific ?
539
- # It should popup no matter which window you are on ?? XXX
540
- class PMenuBar
541
- attr_reader :items
542
- attr_reader :window
543
- attr_reader :panel
544
- attr_reader :selected
545
- attr_accessor :visible
546
- attr_accessor :active_index
547
- attr_accessor :state # normal, selected, highlighted
548
- attr_accessor :toggle_key # key used to popup, should be set prior to attaching to form
549
- def initialize &block
550
- @window = nil
551
- @active_index = 0
552
- @items = []
553
- @visible = false
554
- @cols = Ncurses.COLS-1
555
- instance_eval &block if block_given?
556
- end
557
- def focusable
558
- false
559
- end
560
- def add menu
561
- @items << menu
562
- return self
563
- end
564
- def next_menu
565
- $log.debug "next meu: #{@active_index} "
566
- if @active_index < @items.length-1
567
- set_menu @active_index + 1
568
- else
569
- set_menu 0
570
- end
571
- end
572
- def prev_menu
573
- $log.debug "prev meu: #{@active_index} "
574
- if @active_index > 0
575
- set_menu @active_index-1
576
- else
577
- set_menu @items.length-1
578
- end
579
- end
580
- def set_menu index
581
- $log.debug "set meu: #{@active_index} #{index}"
582
- menu = @items[@active_index]
583
- menu.on_leave # hide its window, if open
584
- @active_index = index
585
- menu = @items[@active_index]
586
- menu.on_enter #display window, if previous was displayed
587
- @window.wmove menu.row, menu.col
588
- # menu.show
589
- # menu.window.wrefresh # XXX we need this
590
- end
591
- # menubar LEFT, RIGHT, DOWN
592
- def handle_keys
593
- @selected = false
594
- @toggle_key ||= 27 # default switch off with ESC, if nothing else defined
595
- set_menu 0
596
- begin
597
- catch(:popupclose) do
598
- while((ch = @window.getchar()) != @toggle_key )
599
- $log.debug "menuubar inside handle_keys : #{ch}" if ch != -1
600
- case ch
601
- when -1
602
- next
603
- when KEY_DOWN
604
- $log.debug "insdie keyDOWN : #{ch}"
605
- if !@selected
606
- current_menu.fire
607
- else
608
- current_menu.handle_key ch
609
- end
610
-
611
- @selected = true
612
- when KEY_ENTER, 10, 13, 32
613
- @selected = true
614
- $log.debug " mb insdie ENTER : #{current_menu}"
615
- ret = current_menu.handle_key ch
616
- $log.debug "ret = #{ret} mb insdie ENTER : #{current_menu}"
617
- #break; ## 2008-12-29 18:00 This will close after firing
618
- #anything
619
- break if ret == :CLOSE
620
- when KEY_UP
621
- $log.debug " mb insdie keyUPP : #{ch}"
622
- current_menu.handle_key ch
623
- when KEY_LEFT
624
- $log.debug " mb insdie KEYLEFT : #{ch}"
625
- ret = current_menu.handle_key ch
626
- prev_menu if ret == :UNHANDLED
627
- #display_items if @selected
628
- when KEY_RIGHT
629
- $log.debug " mb insdie KEYRIGHT : #{ch}"
630
- ret = current_menu.handle_key ch
631
- next_menu if ret == :UNHANDLED
632
- else
633
- $log.debug " mb insdie ELSE : #{ch}"
634
- ret = current_menu.handle_key ch
635
- if ret == :UNHANDLED
636
- Ncurses.beep
637
- else
638
- break # we handled a menu action, close menubar (THIS WORKS FOR MNEMONICS ONLY and always)
639
- end
640
- end
641
- Ncurses::Panel.update_panels();
642
- Ncurses.doupdate();
643
-
644
- @window.wrefresh
645
- end
646
- end # catch
647
- ensure
648
- #ensure is required becos one can throw a :close
649
- destroy # Note that we destroy the menu bar upon exit
650
- end
651
- end
652
- def current_menu
653
- @items[@active_index]
654
- end
655
- def toggle
656
- @visible = !@visible
657
- if !@visible
658
- hide
659
- else
660
- show
661
- end
662
- end
663
- def hide
664
- @visible = false
665
- @window.hide if !@window.nil?
666
- end
667
- def show
668
- @visible = true
669
- if @window.nil?
670
- repaint # XXX FIXME
671
- else
672
- @window.show
673
- end
674
- end
675
- ## menubar
676
- def repaint
677
- return if !@visible
678
- @window ||= create_window
679
- @window.printstring( 0, 0, "%-*s" % [@cols," "], $reversecolor)
680
- c = 1; r = 0;
681
- @items.each do |item|
682
- item.row = r; item.col = c; item.parent = self
683
- @window.printstring( r, c, " %s " % item.text, $reversecolor)
684
- c += (item.text.length + 2)
685
- end
686
- @window.wrefresh
687
- end
688
- def create_window
689
- @layout = { :height => 1, :width => 0, :top => 0, :left => 0 }
690
- @win = VER::Window.new(@layout)
691
- @window = @win
692
- @win.bkgd(Ncurses.COLOR_PAIR(5));
693
- @panel = @win.panel
694
- return @window
695
- end
696
- def destroy
697
- $log.debug "DESTRY menubar "
698
- @visible = false
699
- panel = @window.panel
700
- Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
701
- @window.delwin if !@window.nil?
702
- @items.each do |item|
703
- item.destroy
704
- end
705
- @window = nil
706
- end
707
- end # menubar
708
-
709
- class PCheckBoxMenuItem < PMenuItem
710
- attr_reader :checkbox
711
- def initialize text, mnemonic=nil, &block
712
- @checkbox = CheckBox.new nil
713
- @checkbox.text text
714
- super
715
- end
716
- def onvalue
717
- @checkbox.onvalue onvalue
718
- end
719
- def offvalue
720
- @checkbox.onvalue offvalue
721
- end
722
- def text=(t) # stack level too deep if no = .????
723
- @checkbox.text t
724
- end
725
- ## added @ with text, else crashing on testmenu.rb
726
- def to_s
727
- " #{@text} "
728
- end
729
- def getvalue
730
- checkbox.getvalue
731
- end
732
- def getvalue_for_paint
733
- "|%-*s|" % [@width, checkbox.getvalue_for_paint]
734
- end
735
- def fire
736
- checkbox.toggle
737
- super
738
- repaint
739
- highlight true
740
- end
741
- def repaint
742
- @parent.window.printstring( row, 0, getvalue_for_paint, $reversecolor)
743
- parent.window.wrefresh
744
- end
745
- def method_missing(sym, *args)
746
- if checkbox.respond_to? sym
747
- $log.debug("calling CHECKBOXMENU #{sym} called #{args[0]}")
748
- checkbox.send(sym, args)
749
- else
750
- $log.error("ERROR CHECKBOXMENU #{sym} called")
751
- end
752
- end
753
-
754
- end
755
- end # modul