# FreeRIDE Ruby Integrated Development Environment # # Author: Rich Kilmer # Copyright (c) 2001, Richard Kilmer, rich@infoether.com # Licensed under the Ruby License require "rubyide_fox_gui/fxscintilla/scintilla_wrapper" require "rubyide_fox_gui/fxscintilla/global_properties" require "rubyide_fox_gui/fxscintilla/ruby_properties" require "rubyide_fox_gui/fxscintilla/ruby_autoindent" require "rubyide_fox_gui/fxscintilla/ruby_colourize" require "rubyide_fox_gui/fxscintilla/colour" require "rubyide_fox_gui/fxscintilla/style" require 'rbconfig' module Scintilla # define our own marker numbers MARKER_DBG_LINE = 0 MARKER_BRKPT = 1 MARKER_ACTIVE_BRKPT = 2 MARKER_ERROR_LINE = 3 MARKER_FOLD_OPEN = 4 MARKER_FOLD_CLOSED = 5 def _set_one_style(snum, style) set_style_set_italic(snum, style.italic?) if style.specified & Style::ITALIC != 0 set_style_set_bold(snum, style.bold?) if style.specified & Style::BOLD != 0 set_style_set_eol_filled(snum, style.eolfilled?) if style.specified & Style::EOLFILLED != 0 set_style_set_underline(snum, style.underline?) if style.specified & Style::UNDERLINE != 0 set_style_set_font(snum, style.font) if style.specified & Style::FONT != 0 set_style_set_size(snum, style.size) if style.specified & Style::SIZE != 0 set_style_set_fore(snum, style.fore) if style.specified & Style::FORE != 0 set_style_set_back(snum, style.back) if style.specified & Style::BACK != 0 set_style_set_case(snum, style.caseForce) if style.specified & Style::CASE_FORCE != 0 end def _set_styles @properties.each("style.") do |key, style| snum = key[6..-1].to_i _set_one_style(snum, style) unless snum == STYLE_DEFAULT end end def _setup set_lexer_language(@properties.language) language = get_lexer if ((language==SCLEX_HTML) || (language==SCLEX_XML)) style_bits = 7 else style_bits = 4 end set_key_words(0, @properties.keywords_1) if @properties.keywords_1 set_key_words(1, @properties.keywords_2) if @properties.keywords_2 set_key_words(2, @properties.keywords_3) if @properties.keywords_3 set_key_words(3, @properties.keywords_4) if @properties.keywords_4 set_key_words(4, @properties.keywords_5) if @properties.keywords_5 set_key_words(5, @properties.keywords_6) if @properties.keywords_6 _forward_property("fold") _forward_property("fold.compact") _forward_property("fold.comment") _forward_property("fold.comment.python") _forward_property("fold.quotes.python") _forward_property("fold.html") _forward_property("styling.within.preprocessor") _forward_property("tab.timmy.whinge.level") _forward_property("asp.default.language") # eol.mode is normally setup in global properties based # on the running platform case @properties["eol.mode"] when "LF" set_eol_mode(SC_EOL_LF) when "CR" set_eol_mode(SC_EOL_CR) when "CRLF" set_eol_mode(SC_EOL_CRLF) else # Assume all others are Unix set_eol_mode(SC_EOL_LF) end set_code_page @properties["code.page", 0] set_caret_fore @properties["caret.fore", Colour::BLACK] set_mouse_dwell_time @properties["dwell.period", SC_TIME_FOREVER] set_caret_width @properties["caret.width", 1] if @properties["caret.line.back"] set_caret_line_visible true set_caret_line_back @properties["caret.line.back"] else set_caret_line_visible false end set_call_tip_set_back @properties["calltip.back", Colour::WHITE] set_caret_period @properties["caret.period"] if @properties["caret.period"] cStrict = @properties["caret.policy.strict",0] ? CARET_STRICT : 0 cSlop = @properties["caret.policy.slop", 0] ? CARET_SLOP : 0 cLines = @properties["caret.policy.lines", 0] cXEven = @properties["caret.policy.xeven",1] ? CARET_XEVEN : 0 cXJumps= @properties["caret.policy.xjumps",0] ? CARET_XJUMPS : 0 set_x_caret_policy(cStrict | cSlop | cXEven | cXJumps, cLines) set_y_caret_policy(cStrict | cSlop | cXEven | cXJumps, cLines) vStrict = @properties["visible.policy.strict"] ? VISIBLE_STRICT : 0 vSlop = @properties["visible.policy.slop", 1] ? VISIBLE_SLOP : 0 vLines = @properties["visible.policy.lines",0] set_visible_policy(vStrict | vSlop, vLines) set_edge_column @properties["edge.column", 0] set_edge_mode @properties["edge.mode", EDGE_NONE] set_edge_colour @properties["edge.color", Colour::BLACK] if @properties["selection.fore"] set_sel_fore(1, @properties["selection.fore"]) else set_sel_fore(0, 0) end if @properties["selection.back"] set_sel_back(1, @properties["selection.back"]) else if @properties["selection.fore"] set_sel_back(0, 0) else set_sel_back(1, Color::BLACK) #must show selection somehow end end #[skipped calltip stuff] set_auto_c_set_ignore_case @properties["autocomplete.ignorecase", false] set_auto_c_set_choose_single @properties["autocomplete.choose.single", false] set_auto_c_set_cancel_at_start false style_reset_default _set_one_style(STYLE_DEFAULT, @properties["style.#{STYLE_DEFAULT}"]) set_style_clear_all _set_styles # begin ReadPropertiesIntial if @properties["view.indentation.whitespace", true] && @properties["view.whitespace", false] set_view_ws SCWS_VISIBLEALWAYS elsif @properties["view.whitespace", false] set_view_ws SCWS_VISIBLEAFTERINDENT else set_view_ws SCWS_INVISIBLE end set_indentation_guides @properties["view.indentation.guides", false] set_view_eol @properties["view.eol", false] set_zoom @properties["magnification", 0] # end ReadPropertiesInitial set_use_palette @properties["use.palette", false] set_print_magnification @properties["print.magnification", 0] set_print_colour_mode @properties["print.colour.mode", 0] set_margin_left @properties["blank.margin.left", 1] set_margin_right @properties["blank.margin.right", 1] set_margin_width_n(0, (@properties["line.numbers"].nil? ? 40 : @properties["line.numbers"]) ) set_margin_width_n(1, (@properties["margin.width"].nil? ? 20 : @properties["margin.width"]) ) set_margin_sensitive_n(1, true) set_margin_width_n(2, (@properties["fold.margin.width", 14]==0 ? 14 : @properties["fold.margin.width", 14])) set_margin_sensitive_n(2, true) set_buffered_draw @properties["buffered.draw", true] if @properties["word.characters"] set_word_chars @properties["word.characters"] else set_word_chars 0 end set_mod_event_mask SC_MOD_CHANGEFOLD set_use_tabs @properties["use.tabs", true] set_tab_indents @properties["tab.indents", true] set_back_space_un_indents @properties["backspace.unindents", true] set_tab_width @properties["tabsize", 2] set_indent @properties["indent.size"] if @properties["indent.size", 0] > 0 set_h_scroll_bar @properties["horizontal.scrollbar", true] set_fold_flags @properties["fold.flags", 0] =begin case @properties["fold.symbols", 0] when 0 #arrow pointing right for contracted folders, arrow pointing down for expanded _define_marker(SC_MARKNUM_FOLDEROPEN, SC_MARK_ARROW, Colour::BLACK, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDER, SC_MARK_ARROW, Colour::BLACK, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY, Colour::BLACK, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY, Colour::BLACK, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY, Colour::WHITE, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY, Colour::WHITE, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY, Colour::WHITE, Colour::BLACK) when 1 #plus for contracted, minus for expanded _define_marker(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS, Colour::WHITE, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDER, SC_MARK_PLUS, Colour::WHITE, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY, Colour::WHITE, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY, Colour::WHITE, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY, Colour::WHITE, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY, Colour::WHITE, Colour::BLACK) _define_marker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY, Colour::WHITE, Colour::BLACK) when 2 # like a flattened tree control using circular headers and curved joints _define_marker(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS, Colour::BLACK, Colour::DARK_GRAY) _define_marker(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS, Colour::BLACK, Colour::DARK_GRAY) _define_marker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE, Colour::BLACK, Colour::DARK_GRAY) _define_marker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNERCURVE, Colour::BLACK, Colour::DARK_GRAY) _define_marker(SC_MARKNUM_FOLDEREND, SC_MARK_CIRCLEPLUSCONNECTED, Colour::WHITE, Colour::DARK_GRAY) _define_marker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_CIRCLEMINUSCONNECTED, Colour::WHITE, Colour::DARK_GRAY) _define_marker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNERCURVE, Colour::WHITE, Colour::DARK_GRAY) when 3 # like a flattened tree control using square headers _define_marker(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS, Colour::BLACK, Colour::GRAY) _define_marker(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS, Colour::BLACK, Colour::GRAY) _define_marker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE, Colour::BLACK, Colour::GRAY) _define_marker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNER, Colour::BLACK, Colour::GRAY) _define_marker(SC_MARKNUM_FOLDEREND, SC_MARK_BOXPLUSCONNECTED, Colour::WHITE, Colour::GRAY) _define_marker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_BOXMINUSCONNECTED, Colour::WHITE, Colour::GRAY) _define_marker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNER, Colour::WHITE, Colour::GRAY) end #set_margin_type_n(2, SC_MARGIN_SYMBOL) set_margin_mask_n(2, (get_margin_mask_n(2) | \ (1< 0 ? true : false end def indentation_guides_visible=(status) @model.set_indentation_guides(status) end def are_indentation_guides_visible? @model.get_indentation_guides end def wrap_mode=(status) @model.wrap_mode = (status ? Scintilla::SC_WRAP_WORD : Scintilla::SC_WRAP_NONE) end def wrap_mode @model.get_wrap_mode == Scintilla::SC_WRAP_WORD ? true : false end def clear_all @model.clear_all end def undo @model.undo end def redo @model.redo end def cut @model.cut end def copy @model.copy end def paste @model.paste end def breakpoint_margin=(status) if status @model.set_margin_width_n(1, (@model.properties["line.numbers", 20] ==0 ? 20 : @model.properties["line.numbers", 20]) ) else @model.set_margin_width_n(1, 0 ) end end def modified? @modified end def modified=(flag) @modified = flag @epane_renderer.modified = flag if !@epane_renderer.nil? end def read_only=(status) @model.set_read_only(status) end alias :set_read_only :read_only= def read_only? @model.get_read_only end alias :get_read_only :read_only? def h_scroll_bar=(status) @model.set_h_scroll_bar(status) end alias :set_h_scroll_bar :h_scroll_bar= def h_scroll_bar? @model.get_h_scroll_bar end alias :get_h_scroll_bar :h_scroll_bar? ## # Highlight a given line in the text (error line). If line # number is nil then hide the marker # def show_errorline(line) if line.nil? @model.marker_delete_handle(@err_handle) unless @err_handle == nil return end l = line.to_i-1 # delete previous highlighted line and show the new one @model.marker_delete_handle(@err_handle) unless @err_handle == nil @err_handle = @model.marker_add(l, Scintilla::MARKER_ERROR_LINE) # scroll up/down if line not visible on screen @model.goto_line(l) end ## # Highlight a given line in the text (current debugger line). If line # number is nil then hide the marker # def show_debugline(line) if line.nil? @model.marker_delete_handle(@dbg_handle) unless @dbg_handle == nil return end l = line.to_i-1 if (@dbg_prev_line != nil) # reset the breakpoint marker to full red if there was one # on the previous line if ( @model.marker_get(@dbg_prev_line) & (1< 0 end ## # Set code folding status: on (true) or off (false) # def code_folding=(status) if status return if @model.get_margin_width_n(2) > 0 # restore initial fold margin length @model.set_margin_width_n(2, (@model.properties["fold.margin.width", 16] ==0 ? 16 : @model.properties["fold.margin.width", 16]) ) # update all lines with fold markers (not needed if markers are # not deleted) #0.upto(@model.get_line_count - 1) do |line| # update_fold(line) #end else return if @model.get_margin_width_n(2) == 0 # scan all lines to make sure all blocks are expanded and # delete all markers to prevent black lines to appear when # margin width is reduced to zero. (not needed if marker # background same color as editor background) 0.upto(@model.get_line_count - 1) do |line| fold_level = @model.get_fold_level(line) marker = @model.marker_get(line) if (fold_level & Scintilla::SC_FOLDLEVELHEADERFLAG)==Scintilla::SC_FOLDLEVELHEADERFLAG if @model.fold_expanded?(line) #@model.marker_delete(line, Scintilla::MARKER_FOLD_OPEN) unless (marker & (1< #{style.to_s}\n" @model._set_one_style(style_number, style) unless style_number.nil? end ## # reset all scintilla styles to default # def set_style_clear_all() @model.set_style_clear_all end ## # Add/Delete breakpoint on the given line # (add if there is none, delete if there is one) def toggle_breakpoint(line, notify=true) if ( @model.marker_get(line) & (1< place a breakpoint line = @model.line_from_position(position) if ((modifiers & SCMOD_SHIFT) == SCMOD_SHIFT && margin == 1) toggle_breakpoint(line) elsif margin==2 @model.toggle_fold(line) update_fold(line) end end def on_modified(position, modification_type, text, length, lines_added, line, fold_level_now, fold_level_prev) if modification_type==520 update_fold(line, fold_level_now) end end end