bets 0.0.13 → 0.0.14
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/bin/bets +2 -2
- data/install.sh +3 -0
- data/lib/bets/version.rb +1 -1
- data/lib/bets.glade +971 -0
- data/lib/bets.rb +1058 -150
- data/lib/options.dat +0 -0
- data/lib/rules.rb +747 -0
- metadata +6 -2
data/lib/bets.rb
CHANGED
@@ -1,165 +1,1073 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require "rubygems"
|
4
3
|
require "bets/version"
|
5
|
-
require '
|
4
|
+
require 'gtk2'
|
5
|
+
require 'stringio'
|
6
|
+
require 'rules.rb'
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
class Parse
|
8
|
+
module RulesDebuger
|
9
|
+
class BetsGUI
|
10
10
|
def initialize
|
11
|
+
@dbg_buffers = {}
|
12
|
+
@edt_buffers = {}
|
13
|
+
@state = []
|
14
|
+
|
15
|
+
stdout_stream_recreate
|
16
|
+
|
17
|
+
@options = {}
|
18
|
+
@options[:curr_filename] = ''
|
19
|
+
@options[:curr_extension] = ''
|
20
|
+
|
21
|
+
# Загрузка сценария RAD
|
22
|
+
Gtk.init
|
23
|
+
builder = Gtk::Builder.new
|
24
|
+
builder.add_from_file(File.join(File.dirname(__FILE__), 'bets.glade'))
|
25
|
+
builder.connect_signals {|handler| method(handler) }
|
26
|
+
@imi_new = builder.get_object('imi_new')
|
27
|
+
@imi_open = builder.get_object('imi_open')
|
28
|
+
@imi_save = builder.get_object('imi_save')
|
29
|
+
@imi_save_as = builder.get_object('imi_save_as')
|
30
|
+
@mi_close = builder.get_object('mi_close')
|
31
|
+
@imi_quit = builder.get_object('imi_quit')
|
32
|
+
|
33
|
+
@mi_console = builder.get_object('mi_console')
|
34
|
+
@mi_files = builder.get_object('mi_files')
|
35
|
+
|
36
|
+
@mi_build = builder.get_object('mi_build')
|
37
|
+
@mi_debug = builder.get_object('mi_debug')
|
38
|
+
@mi_reset = builder.get_object('mi_reset')
|
39
|
+
@mi_play = builder.get_object('mi_play')
|
40
|
+
@mi_pause = builder.get_object('mi_pause')
|
41
|
+
@mi_slow = builder.get_object('mi_slow')
|
42
|
+
@mi_overstep = builder.get_object('mi_overstep')
|
43
|
+
@mi_step = builder.get_object('mi_step')
|
44
|
+
# toolbar
|
45
|
+
@tb_new = builder.get_object('tb_new')
|
46
|
+
@tb_open = builder.get_object('tb_open')
|
47
|
+
@tb_save = builder.get_object('tb_save')
|
48
|
+
@bt_close = builder.get_object('bt_close')
|
49
|
+
|
50
|
+
@tb_build = builder.get_object('tb_build')
|
51
|
+
@tbt_debug = builder.get_object('tbt_debug')
|
52
|
+
@tb_reset = builder.get_object('tb_reset')
|
53
|
+
@tbt_play = builder.get_object('tbt_play')
|
54
|
+
@tbt_pause = builder.get_object('tbt_pause')
|
55
|
+
@sb_delay = builder.get_object('sb_delay')
|
56
|
+
@adj_delay = builder.get_object('adj_delay')
|
57
|
+
@tbt_slow = builder.get_object('tbt_slow')
|
58
|
+
@tb_step = builder.get_object('tb_step')
|
59
|
+
@tb_overstep = builder.get_object('tb_overstep')
|
60
|
+
# Область состояния переменных
|
61
|
+
@trv_variables = builder.get_object('trv_variables')
|
62
|
+
renderer = Gtk::CellRendererText.new
|
63
|
+
column = Gtk::TreeViewColumn.new("Переменная", renderer, :text => 0)
|
64
|
+
@trv_variables.append_column(column)
|
65
|
+
column = Gtk::TreeViewColumn.new("Значение", renderer, :text => 1)
|
66
|
+
@trv_variables.append_column(column)
|
67
|
+
@ls_variables = Gtk::ListStore.new(String, String)
|
68
|
+
@trv_variables.model = @ls_variables
|
69
|
+
# Область файлов
|
70
|
+
@scw_files = builder.get_object('scw_files')
|
71
|
+
@trv_files = builder.get_object('trv_files')
|
72
|
+
|
73
|
+
@trv_files.modify_base(Gtk::STATE_NORMAL,Gdk::Color.parse('#EEEEEE'))
|
74
|
+
# @trv_files.modify_text(Gtk::STATE_NORMAL,Gdk::Color.parse('#FFFFFF'))
|
75
|
+
|
76
|
+
|
77
|
+
renderer = Gtk::CellRendererText.new
|
78
|
+
column = Gtk::TreeViewColumn.new("Файл", renderer, :text => 0)
|
79
|
+
@trv_files.append_column(column)
|
80
|
+
column = Gtk::TreeViewColumn.new("filename", renderer, :text => 1)
|
81
|
+
column.visible = false
|
82
|
+
@trv_files.append_column(column)
|
83
|
+
@ts_files = Gtk::TreeStore.new(String, String)
|
84
|
+
@trv_files.model = @ts_files
|
85
|
+
|
86
|
+
@hp_files = builder.get_object('hp_files')
|
87
|
+
|
88
|
+
# Область программы
|
89
|
+
@txv_program = builder.get_object('txv_program')
|
90
|
+
@tb_program = builder.get_object('tb_program')
|
91
|
+
# @txv_program.modify_base(Gtk::STATE_NORMAL,Gdk::Color.parse('#000000'))
|
92
|
+
# @txv_program.modify_text(Gtk::STATE_NORMAL,Gdk::Color.parse('#FFFFFF'))
|
93
|
+
@txv_program.modify_font(Pango::FontDescription.new('Monospace 12'))
|
94
|
+
@lb_filename = builder.get_object('lb_filename')
|
95
|
+
|
96
|
+
@hp_vars = builder.get_object('hp_vars')
|
97
|
+
# Область состояния стека
|
98
|
+
@txv_stack = builder.get_object('txv_stack')
|
99
|
+
@tb_stack = builder.get_object('tb_stack')
|
100
|
+
@txv_limit = builder.get_object('txv_limit')
|
101
|
+
@tb_limit = builder.get_object('tb_limit')
|
102
|
+
# Вывод консоли
|
103
|
+
@vb_stack = builder.get_object('vb_stack')
|
104
|
+
@txv_console = builder.get_object('txv_console')
|
105
|
+
@tb_console = builder.get_object('tb_console')
|
106
|
+
@vp_console = builder.get_object('vp_console')
|
107
|
+
@vb_footer = builder.get_object('vb_footer')
|
108
|
+
# Строка состояния
|
109
|
+
@pb_progress = builder.get_object('pb_progress')
|
110
|
+
|
111
|
+
# Окно
|
112
|
+
@wnd_main = builder.get_object('wnd_main')
|
113
|
+
|
114
|
+
cmd(:start)
|
115
|
+
|
116
|
+
begin
|
117
|
+
@options = File.open(File.join(File.dirname(__FILE__), "options.dat"), "rb") {|f| Marshal.load(f)}
|
118
|
+
rescue Exception => e
|
119
|
+
puts e
|
120
|
+
end
|
121
|
+
|
122
|
+
files = @options[:files]
|
123
|
+
if files != nil and files.length > 0
|
124
|
+
files.each do |f|
|
125
|
+
edt_openfile(f, true)
|
126
|
+
end
|
127
|
+
|
128
|
+
edt_openfile(@options[:curr_filename])
|
129
|
+
refresh_files
|
130
|
+
cmd(:editor)
|
131
|
+
end
|
132
|
+
|
133
|
+
@wnd_main.move(@options[:pos_x], @options[:pos_y]) if !@options[:pos_x].nil? and !@options[:pos_y].nil?
|
134
|
+
@wnd_main.set_default_size(@options[:width], @options[:heigh]) if !@options[:width].nil? and !@options[:heigh].nil?
|
135
|
+
@wnd_main.maximize if @options[:maximized]
|
136
|
+
@wnd_main.show
|
137
|
+
|
138
|
+
# @wnd_catalog = builder.get_object('wnd_catalog')
|
139
|
+
# @wnd_catalog.show
|
140
|
+
|
141
|
+
# Сброс
|
142
|
+
# Gtk::main_iteration_do(blocking = false) while Gtk::events_pending?
|
143
|
+
# on_tb_reset_clicked(@tb_reset)
|
144
|
+
# Основной цикл
|
145
|
+
|
146
|
+
@hp_files.position = @options[:hp_files] unless @options[:hp_files].nil?
|
147
|
+
@hp_vars.position = @hp_vars.max_position - @options[:hp_vars] unless @options[:hp_vars].nil?
|
148
|
+
@vp_console.position = @options[:vp_console] unless @options[:vp_console].nil?
|
149
|
+
Gtk.main
|
150
|
+
end
|
151
|
+
|
152
|
+
def on_wnd_main_delete_event(widget, event)
|
153
|
+
@options[:files] = []
|
154
|
+
auto = false
|
155
|
+
result = nil # Это корректирует глюк ruby интерпретатора
|
156
|
+
@edt_buffers.each do |k,v|
|
157
|
+
@options[:files] << k
|
158
|
+
if v.modified?
|
159
|
+
result = dialog_saveall_yes_no_cancel("Файл #{k} не сохранен! Сохранить?") unless auto
|
160
|
+
case result
|
161
|
+
when Gtk::Dialog::RESPONSE_CANCEL
|
162
|
+
return true
|
163
|
+
when Gtk::Dialog::RESPONSE_YES
|
164
|
+
File.open(k, 'wb') { |f| f.write(v.text) }
|
165
|
+
when Gtk::Dialog::RESPONSE_APPLY
|
166
|
+
File.open(k, 'wb') { |f| f.write(v.text) }
|
167
|
+
auto = true
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
@options[:hp_files] = @hp_files.position
|
173
|
+
@options[:hp_vars] = @hp_vars.max_position - @hp_vars.position
|
174
|
+
@options[:vp_console] = @vp_console.position
|
175
|
+
|
176
|
+
begin
|
177
|
+
File.open(File.join(File.dirname(__FILE__), "options.dat"), "wb") {|f| Marshal.dump(@options, f)}
|
178
|
+
rescue Exception => e
|
179
|
+
puts e
|
180
|
+
end
|
181
|
+
return false
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
def gtk_main_quit
|
186
|
+
Gtk.main_quit()
|
187
|
+
end
|
188
|
+
|
189
|
+
def on_wnd_main_configure_event(widget, event)
|
190
|
+
mask = Gdk::EventWindowState::MAXIMIZED
|
191
|
+
@options[:maximized] = @wnd_main.window.state & mask == mask
|
192
|
+
unless @options[:maximized]
|
193
|
+
@options[:width], @options[:heigh] = event.width, event.height
|
194
|
+
@options[:pos_x], @options[:pos_y] = event.x, event.y
|
195
|
+
end
|
196
|
+
false
|
197
|
+
end
|
198
|
+
|
199
|
+
def on_toolbutton_clicked(widget)
|
200
|
+
case widget.builder_name
|
201
|
+
when "tb_new"
|
202
|
+
@imi_new.activate
|
203
|
+
when "tb_open"
|
204
|
+
@imi_open.activate
|
205
|
+
when "tb_save"
|
206
|
+
@imi_save.activate
|
207
|
+
when "tb_save_as"
|
208
|
+
@imi_save_as.activate
|
209
|
+
when "bt_close"
|
210
|
+
@mi_close.activate
|
211
|
+
|
212
|
+
when "tb_build"
|
213
|
+
@mi_build.activate
|
214
|
+
when "tbt_debug"
|
215
|
+
@mi_debug.activate if widget.active? != @mi_debug.active?
|
216
|
+
when "tb_reset"
|
217
|
+
@mi_reset.activate
|
218
|
+
when "tbt_play"
|
219
|
+
@mi_play.active = true if widget.active? != @mi_play.active?
|
220
|
+
when "tbt_pause"
|
221
|
+
@mi_pause.active = true if widget.active? != @mi_pause.active?
|
222
|
+
when "tbt_slow"
|
223
|
+
@mi_slow.active = true if widget.active? != @mi_slow.active?
|
224
|
+
when "tb_step"
|
225
|
+
@mi_step.activate
|
226
|
+
when "tb_overstep"
|
227
|
+
@mi_overstep.activate
|
228
|
+
end
|
11
229
|
end
|
12
|
-
public
|
13
|
-
def parse
|
14
|
-
end
|
15
|
-
end
|
16
230
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
231
|
+
def on_menu_activate(widget)
|
232
|
+
case widget.builder_name
|
233
|
+
when "imi_new"
|
234
|
+
cmd(:new)
|
235
|
+
when "imi_open"
|
236
|
+
cmd(:load)
|
237
|
+
when "imi_save"
|
238
|
+
cmd(:save)
|
239
|
+
when "imi_save_as"
|
240
|
+
cmd(:save_as)
|
241
|
+
when "mi_close"
|
242
|
+
cmd(:close)
|
243
|
+
when "imi_quit"
|
244
|
+
cmd(:quit)
|
245
|
+
|
246
|
+
when "mi_console"
|
247
|
+
@vb_footer.visible = widget.active?
|
248
|
+
when "mi_files"
|
249
|
+
@scw_files.visible = widget.active?
|
250
|
+
when "mi_build"
|
251
|
+
cmd(:build)
|
252
|
+
when "mi_debug"
|
253
|
+
cmd(widget.active? ? :debug : :editor)
|
254
|
+
when "mi_reset"
|
255
|
+
cmd(:reset)
|
256
|
+
when "mi_play"
|
257
|
+
cmd(:play) if widget.active?
|
258
|
+
when "mi_pause"
|
259
|
+
cmd(:pause) if widget.active?
|
260
|
+
when "mi_slow"
|
261
|
+
cmd(:slow) if widget.active?
|
262
|
+
when "mi_step"
|
263
|
+
cmd(:step)
|
264
|
+
when "mi_overstep"
|
265
|
+
cmd(:overstep)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def cmd(command)
|
270
|
+
case command
|
271
|
+
when :start
|
272
|
+
@mode = :start
|
273
|
+
stdout_restore
|
274
|
+
@imi_new.sensitive =
|
275
|
+
@tb_new.sensitive =
|
276
|
+
@imi_open.sensitive =
|
277
|
+
@tb_open.sensitive = true
|
278
|
+
|
279
|
+
@mi_play.active =
|
280
|
+
@tbt_play.active =
|
281
|
+
@mi_pause.active =
|
282
|
+
@tbt_pause.active =
|
283
|
+
@mi_slow.active =
|
284
|
+
@tbt_slow.active =
|
285
|
+
|
286
|
+
@imi_save.sensitive =
|
287
|
+
@tb_save.sensitive =
|
288
|
+
@imi_save_as.sensitive =
|
289
|
+
@mi_close.sensitive =
|
290
|
+
@bt_close.sensitive =
|
291
|
+
@mi_build.sensitive =
|
292
|
+
@tb_build.sensitive =
|
293
|
+
@mi_debug.sensitive =
|
294
|
+
@tbt_debug.sensitive =
|
295
|
+
@mi_reset.sensitive =
|
296
|
+
@tb_reset.sensitive =
|
297
|
+
@mi_play.sensitive =
|
298
|
+
@tbt_play.sensitive =
|
299
|
+
@mi_pause.sensitive =
|
300
|
+
@tbt_pause.sensitive =
|
301
|
+
@mi_slow.sensitive =
|
302
|
+
@tbt_slow.sensitive =
|
303
|
+
@mi_step.sensitive =
|
304
|
+
@tb_step.sensitive =
|
305
|
+
@mi_overstep.sensitive =
|
306
|
+
@tb_overstep.sensitive =
|
307
|
+
@sb_delay.sensitive =
|
308
|
+
@txv_program.sensitive =
|
309
|
+
@txv_console.sensitive =
|
310
|
+
@vb_stack.visible =
|
311
|
+
@scw_files.visible = false
|
312
|
+
|
313
|
+
@lb_filename.text = ''
|
314
|
+
@txv_program.buffer = @tb_program
|
315
|
+
progress_reset
|
316
|
+
when :editor
|
317
|
+
@vm.halt unless @vm.nil?
|
318
|
+
edt_pop_state
|
319
|
+
@mode = :edit
|
320
|
+
stdout_restore
|
321
|
+
# вкл
|
322
|
+
@imi_new.sensitive =
|
323
|
+
@tb_new.sensitive =
|
324
|
+
@imi_open.sensitive =
|
325
|
+
@tb_open.sensitive =
|
326
|
+
@imi_save_as.sensitive =
|
327
|
+
@mi_close.sensitive =
|
328
|
+
@bt_close.sensitive =
|
329
|
+
@mi_build.sensitive =
|
330
|
+
@tb_build.sensitive =
|
331
|
+
@mi_debug.sensitive =
|
332
|
+
@tbt_debug.sensitive =
|
333
|
+
@txv_program.sensitive =
|
334
|
+
@txv_console.sensitive =
|
335
|
+
@scw_files.visible = true
|
336
|
+
# выкл
|
337
|
+
@tbt_debug.active =
|
338
|
+
@mi_play.active =
|
339
|
+
@tbt_play.active =
|
340
|
+
@mi_pause.active =
|
341
|
+
@tbt_pause.active =
|
342
|
+
@mi_slow.active =
|
343
|
+
@tbt_slow.active =
|
344
|
+
|
345
|
+
@mi_reset.sensitive =
|
346
|
+
@tb_reset.sensitive =
|
347
|
+
@mi_play.sensitive =
|
348
|
+
@tbt_play.sensitive =
|
349
|
+
@mi_pause.sensitive =
|
350
|
+
@tbt_pause.sensitive =
|
351
|
+
@sb_delay.sensitive =
|
352
|
+
@mi_slow.sensitive =
|
353
|
+
@tbt_slow.sensitive =
|
354
|
+
@mi_step.sensitive =
|
355
|
+
@tb_step.sensitive =
|
356
|
+
@mi_overstep.sensitive =
|
357
|
+
@tb_overstep.sensitive =
|
358
|
+
@trv_variables.visible =
|
359
|
+
@vb_stack.visible = false
|
360
|
+
|
361
|
+
edt_openfile(@options[:curr_filename])
|
362
|
+
|
363
|
+
@tb_save.sensitive = @txv_program.buffer.modified?
|
364
|
+
# Прервать текущую отладку
|
365
|
+
@debuger_mode = :default
|
366
|
+
@pause_flag = true
|
367
|
+
progress_reset
|
368
|
+
when :new
|
369
|
+
dialog = Gtk::FileChooserDialog.new("Save File", @wnd_main,
|
370
|
+
Gtk::FileChooser::ACTION_SAVE,
|
371
|
+
nil,
|
372
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
373
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
|
374
|
+
result = (dialog.run == Gtk::Dialog::RESPONSE_ACCEPT)
|
375
|
+
filename = dialog.filename
|
376
|
+
dialog.destroy
|
377
|
+
return unless result
|
378
|
+
return if File.exist?(filename) and
|
379
|
+
!dialog_ok_cancel("Файл с таким именем уже существует! Перезаписать?")
|
380
|
+
|
381
|
+
edt_openfile(filename)
|
382
|
+
File.open(filename, 'wb') { |f| f.write(@txv_program.buffer.text) }
|
383
|
+
|
384
|
+
cmd(:editor)
|
385
|
+
cmd(:not_modified)
|
386
|
+
refresh_files
|
387
|
+
when :load
|
388
|
+
# Прочее
|
389
|
+
dialog = Gtk::FileChooserDialog.new("Open File", @wnd_main,
|
390
|
+
Gtk::FileChooser::ACTION_OPEN,
|
391
|
+
nil,
|
392
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
393
|
+
[Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
|
394
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
395
|
+
edt_openfile(dialog.filename)
|
396
|
+
refresh_files
|
397
|
+
cmd(:editor)
|
398
|
+
cmd(:not_modified)
|
399
|
+
end
|
400
|
+
dialog.destroy
|
401
|
+
when :save
|
402
|
+
filename = @options[:curr_filename]
|
403
|
+
unless File.exist?(filename)
|
404
|
+
dialog = Gtk::FileChooserDialog.new("Save File", @wnd_main,
|
405
|
+
Gtk::FileChooser::ACTION_SAVE,
|
406
|
+
nil,
|
407
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
408
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
|
409
|
+
result = (dialog.run == Gtk::Dialog::RESPONSE_ACCEPT)
|
410
|
+
filename = dialog.filename
|
411
|
+
dialog.destroy
|
412
|
+
return unless result
|
413
|
+
buffer = @edt_buffers[@options[:curr_filename]]
|
414
|
+
@edt_buffers.delete @options[:curr_filename]
|
415
|
+
@edt_buffers[filename] = buffer
|
416
|
+
edt_set_curr_filename(filename)
|
417
|
+
end
|
418
|
+
File.open(filename, 'wb') { |f| f.write(@txv_program.buffer.text) } unless filename.empty?
|
419
|
+
cmd(:not_modified)
|
420
|
+
refresh_files
|
421
|
+
when :save_as
|
422
|
+
dialog = Gtk::FileChooserDialog.new("Save File", @wnd_main,
|
423
|
+
Gtk::FileChooser::ACTION_SAVE,
|
424
|
+
nil,
|
425
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
426
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
|
427
|
+
result = (dialog.run == Gtk::Dialog::RESPONSE_ACCEPT)
|
428
|
+
filename = dialog.filename
|
429
|
+
dialog.destroy
|
430
|
+
return unless result
|
431
|
+
buffer = @edt_buffers[@options[:curr_filename]]
|
432
|
+
@edt_buffers.delete @options[:curr_filename]
|
433
|
+
@edt_buffers[filename] = buffer
|
434
|
+
edt_set_curr_filename(filename)
|
435
|
+
File.open(filename, 'wb') { |f| f.write(@txv_program.buffer.text) } unless filename.empty?
|
436
|
+
cmd(:not_modified)
|
437
|
+
refresh_files
|
438
|
+
when :close
|
439
|
+
if @edt_buffers[@options[:curr_filename]].modified?
|
440
|
+
result = dialog_yes_no_cancel("Файл #{@options[:curr_filename]} не сохранен! Cохранить?")
|
441
|
+
case result
|
442
|
+
when Gtk::RESPONSE_YES
|
443
|
+
File.open(@options[:curr_filename], 'wb') { |f| f.write(@txv_program.buffer.text) }
|
444
|
+
when Gtk::RESPONSE_CANCEL
|
445
|
+
return
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
a = []
|
450
|
+
a = @edt_buffers.map { |f,b| f }
|
451
|
+
p = 0
|
452
|
+
a.each_index do |i|
|
453
|
+
p = i if a[i] == @options[:curr_filename]
|
454
|
+
end
|
455
|
+
if a[p+1].nil?
|
456
|
+
if a.length == 1
|
457
|
+
cmd(:start)
|
458
|
+
else
|
459
|
+
edt_openfile(a[p-1])
|
101
460
|
end
|
461
|
+
else
|
462
|
+
edt_openfile(a[p+1])
|
463
|
+
end
|
464
|
+
@edt_buffers.delete(a[p])
|
465
|
+
refresh_files
|
466
|
+
when :build
|
467
|
+
return unless edt_save_changes
|
468
|
+
stdout_stream_recreate
|
469
|
+
stdout_redirect
|
470
|
+
errors = build(@options[:curr_filename])
|
471
|
+
error_select(errors)
|
472
|
+
error_puts(errors)
|
473
|
+
when :debug
|
474
|
+
@vm.halt unless @vm.nil?
|
475
|
+
unless edt_save_changes
|
476
|
+
cmd(:editor)
|
477
|
+
return
|
102
478
|
end
|
479
|
+
edt_push_state
|
480
|
+
@mode = :debug
|
481
|
+
stdout_stream_recreate
|
482
|
+
stdout_redirect
|
483
|
+
|
484
|
+
# вкл
|
485
|
+
@tbt_debug.active =
|
486
|
+
@tbt_pause.active =
|
487
|
+
@mi_pause.active =
|
488
|
+
|
489
|
+
@mi_reset.sensitive =
|
490
|
+
@tb_reset.sensitive =
|
491
|
+
@mi_play.sensitive =
|
492
|
+
@tbt_play.sensitive =
|
493
|
+
@sb_delay.sensitive =
|
494
|
+
@mi_step.sensitive =
|
495
|
+
@tb_step.sensitive =
|
496
|
+
@mi_slow.sensitive =
|
497
|
+
@tbt_slow.sensitive =
|
498
|
+
@mi_overstep.sensitive =
|
499
|
+
@tb_overstep.sensitive =
|
500
|
+
@trv_variables.visible =
|
501
|
+
@vb_stack.visible = true
|
502
|
+
|
503
|
+
# выкл
|
504
|
+
@tbt_play.active =
|
505
|
+
@mi_play.active =
|
506
|
+
@tbt_slow.active =
|
507
|
+
@mi_slow.active =
|
508
|
+
|
509
|
+
@imi_new.sensitive =
|
510
|
+
@tb_new.sensitive =
|
511
|
+
@imi_open.sensitive =
|
512
|
+
@tb_open.sensitive =
|
513
|
+
@imi_save.sensitive =
|
514
|
+
@tb_save.sensitive =
|
515
|
+
@imi_save_as.sensitive =
|
516
|
+
@mi_close.sensitive =
|
517
|
+
@bt_close.sensitive =
|
518
|
+
@mi_build.sensitive =
|
519
|
+
@tb_build.sensitive =
|
520
|
+
@mi_pause.sensitive =
|
521
|
+
@tbt_pause.sensitive =
|
522
|
+
@txv_program.sensitive =
|
523
|
+
@scw_files.visible = false
|
524
|
+
debuger_reset
|
525
|
+
progress_reset
|
526
|
+
when :reset
|
527
|
+
cmd(:debug)
|
528
|
+
when :play
|
529
|
+
# вкл
|
530
|
+
@mi_play.active =
|
531
|
+
@tbt_play.active =
|
532
|
+
|
533
|
+
@mi_pause.sensitive =
|
534
|
+
@tbt_pause.sensitive =
|
535
|
+
@mi_slow.sensitive =
|
536
|
+
@tbt_slow.sensitive = true
|
537
|
+
# выкл
|
538
|
+
@mi_pause.active =
|
539
|
+
@tbt_pause.active =
|
540
|
+
@mi_slow.active =
|
541
|
+
@tbt_slow.active =
|
542
|
+
|
543
|
+
@mi_play.sensitive =
|
544
|
+
@tbt_play.sensitive =
|
545
|
+
@mi_step.sensitive =
|
546
|
+
@tb_step.sensitive =
|
547
|
+
@mi_overstep.sensitive =
|
548
|
+
@tb_overstep.sensitive =
|
549
|
+
@mi_slow.active =
|
550
|
+
@tbt_slow.active = false
|
551
|
+
# Прочее
|
552
|
+
@delay = 0
|
553
|
+
@pause_flag = false
|
554
|
+
@debuger_mode = :start
|
555
|
+
when :slow
|
556
|
+
# вкл
|
557
|
+
@mi_slow.active =
|
558
|
+
@tbt_slow.active =
|
559
|
+
|
560
|
+
@mi_pause.sensitive =
|
561
|
+
@tbt_pause.sensitive =
|
562
|
+
@mi_play.sensitive =
|
563
|
+
@tbt_play.sensitive = true
|
564
|
+
# выкл
|
565
|
+
@mi_pause.active =
|
566
|
+
@tbt_pause.active =
|
567
|
+
@mi_play.active =
|
568
|
+
@tbt_play.active =
|
569
|
+
|
570
|
+
@mi_play.sensitive =
|
571
|
+
@tbt_play.sensitive =
|
572
|
+
@mi_slow.sensitive =
|
573
|
+
@tbt_slow.sensitive =
|
574
|
+
@mi_step.sensitive =
|
575
|
+
@tb_step.sensitive =
|
576
|
+
@mi_overstep.sensitive =
|
577
|
+
@tb_overstep.sensitive = false
|
578
|
+
# Прочее
|
579
|
+
@debuger_mode = :default
|
580
|
+
@delay = @adj_delay.value
|
581
|
+
@pause_flag = false
|
582
|
+
when :pause
|
583
|
+
# вкл
|
584
|
+
@tbt_pause.active =
|
585
|
+
@mi_pause.active =
|
586
|
+
|
587
|
+
@mi_play.sensitive =
|
588
|
+
@tbt_play.sensitive =
|
589
|
+
@mi_slow.sensitive =
|
590
|
+
@tbt_slow.sensitive =
|
591
|
+
@mi_step.sensitive =
|
592
|
+
@tb_step.sensitive =
|
593
|
+
@mi_overstep.sensitive =
|
594
|
+
@tb_overstep.sensitive = true
|
595
|
+
# выкл
|
596
|
+
@mi_play.active =
|
597
|
+
@tbt_play.active =
|
598
|
+
@mi_slow.active =
|
599
|
+
@tbt_slow.active =
|
600
|
+
|
601
|
+
@mi_pause.sensitive =
|
602
|
+
@tbt_pause.sensitive = false
|
603
|
+
# Прочее
|
604
|
+
@debuger_mode = :default
|
605
|
+
@pause_flag = true
|
606
|
+
when :step
|
607
|
+
@delay = 0
|
608
|
+
@debuger_mode = :step
|
609
|
+
@pause_flag = false
|
610
|
+
when :overstep
|
611
|
+
@delay = 0
|
612
|
+
@debuger_mode = :overstep
|
613
|
+
@pause_flag = false
|
614
|
+
when :stop
|
615
|
+
# вкл
|
616
|
+
@mi_pause.active =
|
617
|
+
@tbt_pause.active = true
|
618
|
+
# выкл
|
619
|
+
@mi_play.active =
|
620
|
+
@tbt_play.active =
|
621
|
+
@mi_slow.active =
|
622
|
+
@tbt_slow.active =
|
623
|
+
|
624
|
+
@mi_pause.sensitive =
|
625
|
+
@tbt_pause.sensitive =
|
626
|
+
@mi_slow.sensitive =
|
627
|
+
@tbt_slow.sensitive =
|
628
|
+
@mi_play.sensitive =
|
629
|
+
@tbt_play.sensitive =
|
630
|
+
@mi_step.sensitive =
|
631
|
+
@tb_step.sensitive =
|
632
|
+
@mi_overstep.sensitive =
|
633
|
+
@tb_overstep.sensitive = false
|
634
|
+
# Прочее
|
635
|
+
message_out("[Выполнение программы окончено]")
|
636
|
+
refresh_vars_state
|
637
|
+
when :modified
|
638
|
+
refresh_modified(true)
|
639
|
+
progress_reset
|
640
|
+
when :not_modified
|
641
|
+
@edt_buffers[@options[:curr_filename]].modified = false
|
642
|
+
refresh_modified
|
643
|
+
when :quit
|
644
|
+
gtk_main_quit
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
def build(filename)
|
649
|
+
begin
|
650
|
+
filename = File.expand_path(filename)
|
651
|
+
text = File.open(filename, "r:UTF-8").read
|
652
|
+
rescue Exception => e
|
653
|
+
puts e
|
654
|
+
end
|
655
|
+
progress_reset
|
656
|
+
lexical = Rules::Lexical.new
|
657
|
+
lexical.set_progress_callback(self, :progress_callback)
|
658
|
+
lexical.analyze(text, filename)
|
659
|
+
syntax = Rules::Syntax.new
|
660
|
+
syntax.set_progress_callback(self, :progress_callback)
|
661
|
+
syntax.analyze(lexical.result)
|
662
|
+
if lexical.errors.length + syntax.errors.length > 0
|
663
|
+
progress_reset
|
664
|
+
return lexical.errors + syntax.errors
|
665
|
+
end
|
666
|
+
translator = Rules::Translator.new
|
667
|
+
translator.set_progress_callback(self, :progress_callback)
|
668
|
+
translator.translate(lexical.result, File.dirname(filename))
|
669
|
+
if translator.errors.length > 0
|
670
|
+
return translator.errors
|
671
|
+
progress_reset
|
672
|
+
end
|
673
|
+
@ids_map = translator.ids
|
674
|
+
@data_seg = translator.data_seg
|
675
|
+
@code_seg = translator.code_seg
|
676
|
+
@debug = translator.debug
|
677
|
+
@includes = translator.includes
|
678
|
+
return []
|
679
|
+
end
|
680
|
+
|
681
|
+
def debuger_reset
|
682
|
+
# Прервать текущую отладку
|
683
|
+
@debuger_mode = :default
|
684
|
+
@call_stack = []
|
685
|
+
@old_lex = nil
|
686
|
+
@old_lex_iter = nil
|
687
|
+
@dbg_buffers = {}
|
688
|
+
@delay = 0
|
689
|
+
@ip = nil
|
690
|
+
@pause_flag = true
|
691
|
+
|
692
|
+
errors = build(@options[:curr_filename])
|
693
|
+
if errors.length > 0
|
694
|
+
error_puts errors
|
695
|
+
error_select errors
|
696
|
+
cmd(:editor)
|
697
|
+
return
|
698
|
+
end
|
699
|
+
|
700
|
+
@vm = Rules::VM.new(@data_seg, @code_seg, @debug)
|
701
|
+
@vm.set_debug_callback(self, :debug_callback)
|
702
|
+
|
703
|
+
$export = []
|
704
|
+
errors = []
|
705
|
+
begin
|
706
|
+
@includes.each do |f|
|
707
|
+
load Gem::find_files("#{f}_rules.rb").last
|
708
|
+
@vm.extend(self.class.const_get("#{f.capitalize}Rules"))
|
103
709
|
end
|
710
|
+
rescue Exception => e
|
711
|
+
errors << {message: "Ошибка модуля: #{e}"}
|
712
|
+
error_puts errors
|
713
|
+
cmd(:editor)
|
714
|
+
return
|
104
715
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
716
|
+
|
717
|
+
refresh_vars_state
|
718
|
+
refresh_stack_state
|
719
|
+
@vm.run
|
720
|
+
end
|
721
|
+
|
722
|
+
|
723
|
+
def on_wnd_main_destroy
|
724
|
+
gtk_main_quit
|
725
|
+
end
|
726
|
+
|
727
|
+
def on_trv_files_cursor_changed(widget)
|
728
|
+
path, c = widget.cursor
|
729
|
+
iter = @ts_files.get_iter(path)
|
730
|
+
edt_openfile(iter[1])
|
731
|
+
end
|
732
|
+
|
733
|
+
def on_end_user_action(widget)
|
734
|
+
cmd(:modified) if @mode == :edit
|
735
|
+
begin
|
736
|
+
buffer_syntax_highlight widget, @options[:curr_filename]
|
737
|
+
rescue
|
738
|
+
end
|
739
|
+
end
|
740
|
+
|
741
|
+
def edt_buffer_new
|
742
|
+
buffer = Gtk::TextBuffer.new
|
743
|
+
buffer_connect_tags(buffer)
|
744
|
+
buffer.signal_connect("changed") { |widget| on_end_user_action(widget) }
|
745
|
+
return buffer
|
746
|
+
end
|
747
|
+
|
748
|
+
def edt_set_curr_filename(filename)
|
749
|
+
@options[:curr_filename] = filename
|
750
|
+
@options[:curr_extension] = filename.scan(/.*?\.([a-zA-z0-9]*)$/).flatten(1)[0]
|
751
|
+
refresh_modified
|
752
|
+
end
|
753
|
+
|
754
|
+
def edt_openfile(filename, bg = false)
|
755
|
+
filename = File.expand_path(filename)
|
756
|
+
buffer = @edt_buffers[filename]
|
757
|
+
if buffer.nil?
|
758
|
+
@edt_buffers[filename] = buffer = edt_buffer_new
|
759
|
+
if File.exist?(File.expand_path(filename))
|
760
|
+
buffer.text = File.open(File.expand_path(filename), "r:UTF-8").read
|
761
|
+
end
|
762
|
+
edt_set_curr_filename(filename) unless bg
|
763
|
+
buffer_syntax_highlight buffer, filename
|
764
|
+
buffer.modified = false
|
765
|
+
end
|
766
|
+
unless bg
|
767
|
+
edt_set_curr_filename(filename)
|
768
|
+
@txv_program.buffer = buffer
|
769
|
+
@imi_save.sensitive =
|
770
|
+
@tb_save.sensitive = buffer.modified?
|
771
|
+
end
|
772
|
+
end
|
773
|
+
|
774
|
+
def edt_save_changes
|
775
|
+
if @lb_filename.text =~ /.*?\*/
|
776
|
+
if dialog_ok_cancel("Сохранить изменения в файле '%s' ?" % @options[:curr_filename])
|
777
|
+
cmd(:save)
|
778
|
+
return true
|
779
|
+
else
|
780
|
+
return false
|
781
|
+
end
|
782
|
+
else
|
783
|
+
return true
|
784
|
+
end
|
785
|
+
end
|
786
|
+
|
787
|
+
def edt_push_state
|
788
|
+
state = {
|
789
|
+
:buffer => @txv_program.buffer,
|
790
|
+
:filename => @options[:curr_filename]
|
791
|
+
}
|
792
|
+
@state.push state
|
793
|
+
end
|
794
|
+
|
795
|
+
def edt_pop_state
|
796
|
+
return unless @state.length > 0
|
797
|
+
state = @state.pop
|
798
|
+
@txv_program.buffer = state[:buffer]
|
799
|
+
@lb_filename.text = state[:filename]
|
800
|
+
end
|
801
|
+
|
802
|
+
def refresh_modified(value = false)
|
803
|
+
modified = (value ? true : @edt_buffers[@options[:curr_filename]].modified?)
|
804
|
+
@imi_save.sensitive =
|
805
|
+
@tb_save.sensitive = modified
|
806
|
+
@lb_filename.text = @options[:curr_filename] + ( modified ? '*' : '')
|
807
|
+
end
|
808
|
+
|
809
|
+
def refresh_files
|
810
|
+
@ts_files.clear
|
811
|
+
@edt_buffers.each do |key, value|
|
812
|
+
item = @ts_files.append(nil)
|
813
|
+
item[0] = File.basename(key)
|
814
|
+
item[1] = key
|
815
|
+
@trv_files.selection.select_iter(item) if key == @options[:curr_filename]
|
816
|
+
end
|
817
|
+
end
|
818
|
+
|
819
|
+
def refresh_vars_state
|
820
|
+
@ls_variables.clear
|
821
|
+
@ids_map.each do |key, value|
|
822
|
+
next unless value[:type] == :var
|
823
|
+
item = @ls_variables.append
|
824
|
+
item[0] = key
|
825
|
+
item[1] = @vm.data[@ids_map[key][:addr]].to_s
|
826
|
+
end
|
827
|
+
end
|
828
|
+
|
829
|
+
def refresh_stack_state
|
830
|
+
@tb_stack.text = @vm.data_stack.reverse.to_s
|
831
|
+
@tb_limit.text = @vm.limit_stack.reverse.to_s
|
832
|
+
end
|
833
|
+
|
834
|
+
def refresh_console
|
835
|
+
@mi_console.active = true
|
836
|
+
@txv_console.buffer.text = @stdout_stream.string
|
837
|
+
@txv_console.scroll_to_iter(@txv_console.buffer.end_iter, 0.25, false, 0, 0)
|
838
|
+
end
|
839
|
+
|
840
|
+
def error_select(errors)
|
841
|
+
return unless errors.length > 0
|
842
|
+
puts errors
|
843
|
+
error = errors[0][:lexem]
|
844
|
+
edt_openfile(error[:filename])
|
845
|
+
refresh_files
|
846
|
+
buffer = @txv_program.buffer
|
847
|
+
b = buffer.get_iter_at_offset(error[:begin])
|
848
|
+
e = buffer.get_iter_at_offset(error[:begin]+error[:length])
|
849
|
+
buffer.apply_tag('error',b,e)
|
850
|
+
@txv_program.scroll_to_iter(b, 0.25, false, 0, 0)
|
851
|
+
end
|
852
|
+
|
853
|
+
def error_puts(errors)
|
854
|
+
# stdout_redirect
|
855
|
+
if errors.length > 0
|
856
|
+
errors.each do |e|
|
857
|
+
puts "[ошибка]: '#{e[:message]}' в строке #{e[:lexem][:line]}"
|
858
|
+
end
|
859
|
+
else
|
860
|
+
puts '[ошибок нет]'
|
861
|
+
end
|
862
|
+
refresh_console
|
863
|
+
# stdout_restore
|
864
|
+
end
|
865
|
+
|
866
|
+
def message_out(message)
|
867
|
+
# stdout_redirect
|
868
|
+
puts message
|
869
|
+
refresh_console
|
870
|
+
# stdout_restore
|
871
|
+
end
|
872
|
+
|
873
|
+
def stdout_stream_recreate
|
874
|
+
@stdout_stream = StringIO.new
|
875
|
+
@stdout_store = $stdout
|
876
|
+
end
|
877
|
+
|
878
|
+
def stdout_redirect
|
879
|
+
$stdout = @stdout_stream
|
880
|
+
end
|
881
|
+
|
882
|
+
def stdout_restore
|
883
|
+
$stdout = @stdout_store
|
884
|
+
end
|
885
|
+
|
886
|
+
def buffer_connect_tags(buffer)
|
887
|
+
buffer.create_tag("blue", {"underline" => Pango::UNDERLINE_SINGLE})
|
888
|
+
buffer.create_tag("number", {"foreground" => "#000000"})
|
889
|
+
buffer.create_tag("label", {"foreground" => "#000000"})
|
890
|
+
buffer.create_tag("brace", {"foreground" => "#000000"})
|
891
|
+
buffer.create_tag("operation", {"foreground" => "#000000"})
|
892
|
+
buffer.create_tag("var", {"foreground" => "#000000"})
|
893
|
+
buffer.create_tag("operator", {"foreground" => "#000099"})
|
894
|
+
buffer.create_tag("string", {"foreground" => "#777777"})
|
895
|
+
buffer.create_tag("word", {"foreground" => "#d93503"})
|
896
|
+
buffer.create_tag("comment", {"foreground" => "#004400"})
|
897
|
+
buffer.create_tag("error", {"foreground" => "#990000", "underline" => Pango::UNDERLINE_SINGLE })
|
898
|
+
end
|
899
|
+
|
900
|
+
def buffer_syntax_highlight(buffer, filename)
|
901
|
+
case @options[:curr_extension]
|
902
|
+
when 'rules'
|
903
|
+
hl_lexical = Rules::Lexical.new
|
904
|
+
hl_lexical.analyze(buffer.text, filename)
|
905
|
+
|
906
|
+
buffer.remove_all_tags(buffer.start_iter, buffer.end_iter)
|
907
|
+
|
908
|
+
hl_lexical.result.each do |l|
|
909
|
+
next if l[:filename] != filename
|
910
|
+
b = buffer.get_iter_at_offset(l[:begin])
|
911
|
+
e = buffer.get_iter_at_offset(l[:begin]+l[:length])
|
912
|
+
case l[:lexem]
|
913
|
+
when :label, :proc
|
914
|
+
buffer.apply_tag("label", b, e)
|
915
|
+
when :number, :float, :unary_minus
|
916
|
+
buffer.apply_tag("number", b, e)
|
917
|
+
when :l_brace, :r_brace
|
918
|
+
buffer.apply_tag("brace", b, e)
|
919
|
+
when :plus, :minus, :mul, :div
|
920
|
+
buffer.apply_tag("operation", b, e)
|
921
|
+
when :var,:wvar
|
922
|
+
buffer.apply_tag("var", b, e)
|
923
|
+
when :if_yes, :if_no, :else, :semicolon, :ret, :include, :true, :false, :ruby, :limiter
|
924
|
+
buffer.apply_tag("operator", b, e)
|
925
|
+
when :word
|
926
|
+
buffer.apply_tag("word", b, e)
|
927
|
+
when :string
|
928
|
+
buffer.apply_tag("string", b, e)
|
929
|
+
when :comment
|
930
|
+
buffer.apply_tag("comment", b, e)
|
931
|
+
end
|
932
|
+
end
|
933
|
+
end
|
934
|
+
end
|
935
|
+
|
936
|
+
def dialog_ok_cancel(message)
|
937
|
+
dialog = Gtk::MessageDialog.new(@wnd_main,
|
938
|
+
Gtk::Dialog::DESTROY_WITH_PARENT,
|
939
|
+
Gtk::MessageDialog::QUESTION,
|
940
|
+
Gtk::MessageDialog::BUTTONS_OK_CANCEL,
|
941
|
+
message)
|
942
|
+
result = (dialog.run == Gtk::Dialog::RESPONSE_OK)
|
943
|
+
dialog.destroy
|
944
|
+
return result
|
945
|
+
end
|
946
|
+
|
947
|
+
def dialog_yes_no_cancel(message)
|
948
|
+
dialog = Gtk::MessageDialog.new(@wnd_main,
|
949
|
+
Gtk::Dialog::DESTROY_WITH_PARENT,
|
950
|
+
Gtk::MessageDialog::QUESTION,
|
951
|
+
Gtk::MessageDialog::BUTTONS_NONE,
|
952
|
+
message)
|
953
|
+
dialog.add_buttons(
|
954
|
+
[Gtk::Stock::YES, Gtk::Dialog::RESPONSE_YES],
|
955
|
+
[Gtk::Stock::NO, Gtk::Dialog::RESPONSE_NO],
|
956
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
|
957
|
+
result = dialog.run
|
958
|
+
dialog.destroy
|
959
|
+
return result
|
960
|
+
end
|
961
|
+
|
962
|
+
|
963
|
+
def dialog_saveall_yes_no_cancel(message)
|
964
|
+
dialog = Gtk::MessageDialog.new(@wnd_main,
|
965
|
+
Gtk::Dialog::DESTROY_WITH_PARENT,
|
966
|
+
Gtk::MessageDialog::QUESTION,
|
967
|
+
Gtk::MessageDialog::BUTTONS_NONE,
|
968
|
+
message)
|
969
|
+
dialog.add_buttons(
|
970
|
+
["Сохранить все", Gtk::Dialog::RESPONSE_APPLY],
|
971
|
+
[Gtk::Stock::YES, Gtk::Dialog::RESPONSE_YES],
|
972
|
+
[Gtk::Stock::NO, Gtk::Dialog::RESPONSE_NO],
|
973
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL])
|
974
|
+
result = dialog.run
|
975
|
+
dialog.destroy
|
976
|
+
return result
|
977
|
+
end
|
978
|
+
|
979
|
+
def progress_callback(perc)
|
980
|
+
if (perc % @a == 0) or (perc == 100)
|
981
|
+
@pb_progress.text = "#{perc}%"
|
982
|
+
@pb_progress.fraction = perc * 0.01
|
983
|
+
Gtk::main_iteration_do(blocking = false) while Gtk::events_pending?
|
984
|
+
@a = Random.rand(2...10)
|
985
|
+
end
|
986
|
+
end
|
987
|
+
|
988
|
+
def progress_reset
|
989
|
+
@pb_progress.text = " "
|
990
|
+
@pb_progress.fraction = 0
|
991
|
+
@a = 1
|
992
|
+
end
|
993
|
+
# Функция обратного вызова для VM (вызываеться на каждый шаг программы)
|
994
|
+
def debug_callback(lex)
|
995
|
+
return if @debuger_mode == :start and lex[:lexem] != :stop
|
996
|
+
# Файл текущей лексемыg
|
997
|
+
filename = lex[:filename]
|
998
|
+
buffer = @dbg_buffers[filename]
|
999
|
+
if buffer.nil?
|
1000
|
+
# Создать новый буфер
|
1001
|
+
@dbg_buffers[filename] = buffer = Gtk::TextBuffer.new
|
1002
|
+
buffer_connect_tags(buffer)
|
1003
|
+
buffer.signal_connect("changed") { |widget| on_end_user_action(widget); }
|
1004
|
+
buffer.text = File.open(lex[:filename], "r:UTF-8").read
|
1005
|
+
buffer_syntax_highlight buffer, lex[:filename]
|
1006
|
+
# Переключить отображение на созданный буффер
|
1007
|
+
unless @debuger_mode == :overstep
|
1008
|
+
@txv_program.buffer = buffer
|
1009
|
+
@lb_filename.text = filename
|
155
1010
|
end
|
156
|
-
|
157
1011
|
end
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
1012
|
+
# Извлечь итераторы предыдущей лексемы и удалить на ней тег выделения
|
1013
|
+
@old_lex_iter[:buffer].remove_tag("blue", @old_lex_iter[:begin], @old_lex_iter[:end]) unless @old_lex_iter.nil?
|
1014
|
+
# Выделить текущую лексему
|
1015
|
+
b = buffer.get_iter_at_offset(lex[:begin])
|
1016
|
+
e = buffer.get_iter_at_offset(lex[:begin]+lex[:length])
|
1017
|
+
buffer.apply_tag("blue", b, e)
|
1018
|
+
@txv_program.scroll_to_iter(b, 0.25, false, 0, 0)
|
1019
|
+
# Сохранить буфер и итераторы текущей лексемы для последующей очистки от тегов
|
1020
|
+
@old_lex_iter = {buffer: buffer, begin: b, end: e}
|
1021
|
+
|
1022
|
+
# Если предыдущая лексема переменная, обновить ее значение в таблице переменных
|
1023
|
+
if !@old_lex.nil? and (@old_lex[:lexem] == :var or @old_lex[:lexem] == :wvar)
|
1024
|
+
@ls_variables.each do |m,p,i|
|
1025
|
+
value = (@old_lex[:lexem] == :wvar ? @old_lex[:value][1..-1] : @old_lex[:value])
|
1026
|
+
if value == i.get_value(0)
|
1027
|
+
i[1] = @vm.data[@ids_map[i.get_value(0)][:addr]].to_s
|
1028
|
+
end
|
1029
|
+
end
|
1030
|
+
Gtk::main_iteration_do(blocking = false) while Gtk::events_pending?
|
162
1031
|
end
|
1032
|
+
# Обновить содержимое окна состояния стека
|
1033
|
+
refresh_stack_state
|
1034
|
+
|
1035
|
+
# Обработка режимов отладки
|
1036
|
+
case @debuger_mode
|
1037
|
+
when :step
|
1038
|
+
@debuger_mode = :default
|
1039
|
+
@ip = nil
|
1040
|
+
@pause_flag = true
|
1041
|
+
when :overstep
|
1042
|
+
if !@ip.nil? and @vm.ip != @ip
|
1043
|
+
@pause_flag = false
|
1044
|
+
else
|
1045
|
+
@pause_flag = true
|
1046
|
+
@ip = nil
|
1047
|
+
end
|
1048
|
+
@ip = @vm.ip + 2 if lex[:lexem] == :var and @ids_map[lex[:value]][:type] == :proc
|
1049
|
+
end
|
1050
|
+
# Если отладчик не в автоматическом режиме, подключить буфер к виджету
|
1051
|
+
if @pause_flag or @delay != 0
|
1052
|
+
@txv_program.buffer = buffer
|
1053
|
+
@lb_filename.text = filename
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
# Если лексема :stop, перевести отладчи в конечное состояние
|
1057
|
+
cmd(:stop) if lex[:lexem] == :stop
|
1058
|
+
# Сохранить текущую лексему
|
1059
|
+
@old_lex = lex
|
1060
|
+
|
1061
|
+
# Задержка автоматического обхода
|
1062
|
+
if @delay > 0
|
1063
|
+
sleep @delay
|
1064
|
+
Gtk::main_iteration_do(blocking = false) while Gtk::events_pending?
|
1065
|
+
end
|
1066
|
+
|
1067
|
+
refresh_console
|
1068
|
+
# Ожидания действий пользователя
|
1069
|
+
sleep 0.1 while @pause_flag;
|
1070
|
+
end
|
163
1071
|
end
|
164
|
-
|
165
|
-
end
|
1072
|
+
|
1073
|
+
end
|