# Customization

This chapter describes how to change the start-up and runtime behaviors of Source-Navigator. You can also customize menu items and keyboard shortcuts for the Editor; for more information see "Editor" in the Source-Navigator User's Reference Guide.

## The profile File

A general configuration file, `.../share/etc/profile` , is a system-wide configuration file for GUI language and database cache size. These form the default values that all users inherit for all the tools.
If you would like to customize Source-Navigator for a specific user, you may create a file called %USERPROFILE%\.sn\profile (on Windows) or $HOME/.sn/profile (on UNIX) to contain the configuration for that user’s preferences.

### Configurable Settings

The settings that may be customized are `sn_language` and`encoding`, which designates the language of the GUI, and `sn_mailhost`, which tells Source-Navigator how to connect to your mailer.
The format for a user's `profile` file is `setting name:value`, one entry per line.

User-Specific Settings
Setting Name | Default | Possible Values
`sn_language` | `english` | `english`, `german`, or `japanese`
encoding | ISO8859-1 | see the character set encoding combo-box in the Project Preferences dialog
`sn_mailhost` | `mailhost` | `mailhost`, DNS name, or IP address of mailhost

An example `profile` file for the German user interface is:

    language:german
    sn_mailhost:mailhost

## The rc.tcl Start-up File

The information in the following section assumes that you are conversant with Tcl, which is used by Source-Navigator for program configuration tasks.
You can create a file called `rc.tcl` , which will be automatically loaded when Source-Navigator starts. If you have either a `.../share/etc/rc.tcl` or a `$HOME/.sn/rc.tcl` file, Source-Navigator reads and executes the file with the Tcl `source` command. The system-wide configuration file is read first; a user's own configuration file is read afterwards and can override the site-local defaults.
When a Source-Navigator project opens, a Tcl procedure called `sn_rc` (if it exists) is called with no input parameters. This enables you to:

- install additional Tcl programs.
- customize keyboard shortcuts.
- launch specific applications at start-up.

### Adding Events to the rc.tcl File

Many events in Source-Navigator have a corresponding Tcl procedure that is called when the event occurs. This provides the facility to control the appearance and behavior of each tool. You can choose whether or not to implement each of these Tcl procedures in `rc.tcl`; it is not mandatory to do so.

Events and Corresponding Tcl Procedures
Event | Procedure called (with parameters)
--- | ---
A new symbol browser is opened. | `sn_rc_symbolbrowser{window menu}`
A new window is created. | `sn_rc_mainwindow{window menu}`
A new editor view is created. | `sn_rc_editor{view text}`
A new class view is created. | `sn_rc_classbrowser{view canvas}`
A new grep window is opened. | `sn_rc_grep{view list}`
A new include view is created. | `sn_rc_include{view canvas}`
A new make window is opened. | `sn_rc_make{view list}`
A new retriever view is created. | `sn_rc_retriever{view list}`
A new cross-reference view is created. | `sn_rc_xref{view canvas}`
The preferences dialog is opened. | `sn_rc_preferences{win}`
The project editor dialog is opened. | `sn_rc_projecteditor{win menu}`
A project is opened. | `sn_rc_project_open{projectdb}`
The debugger is started. | `sn_rc_debugger{win debugwin}`
The version control browser is started. | `sn_rc_project_editor{win list}`
The retriever is started. | `sn_rc_retrieve{win list}`

Parameters for Tcl Event Procedures
Parameter | Description
--- | ---
`win` | The name of the Tk window widget. Referencing `$win.exp` returns the name of the Tk toolbar widget, and `$win.menu` returns the name of the Tk menu widget.
`view` | The name of the current view.
`list` | A window-specific list of data (for example, a list of filenames.)
`canvas` | The name of the Tk canvas widget used to draw graphs in those tools where it is applicable.
menu | The path to the menus.

When a Symbol Browser window is created, a Tcl procedure called `sn_rc_symbolbrowser` (if it exists) is called with the following input parameters:

- the name of the Symbol Browser window.
- the path of the menu.

### Changing Functionality Within the Symbol Browser

The following example script lists the names of the button widgets of a Symbol Browser toolbar:

    proc sn_rc_symbolbrowser {top menu} {

        set toolbar_frame $top.exp
        puts stdout [join [winfo children \
        $toolbar_frame] "\n"]
    }

which, when using the default toolbar, provides output similar to:

    .multisymbr-1.exp.tree
    .multisymbr-1.exp.class
    .multisymbr-1.exp.xref
    .multisymbr-1.exp.inc
    .multisymbr-1.exp.space
    .multisymbr-1.exp.retrfr

#### Example: Adding an xterm or DOS shell Toolbar Button

The following example code adds a new button that starts a DOS shell under Windows and an `xterm` application under UNIX:

    proc sn_rc_symbolbrowser {top menu} {
      global tcl_platform

      set tool_frame $top.exp

      # Set a variable that identifies the text widget on
      # the status bar.
      set info $top.msg.msg

      # Create a new button on the toolbar. Note that the
      # button's command invokes the command line tool
      # in the background so that Source-Navigator is not
      # blocked while the tool is running. On Win32, we emulate
      # `xterm' with `cmd'.

      if {!$tcl_platform(platform) != "windows"} {
        set cmdline "exec xterm -T {Source-Navigator} &"
        set description xterm
      } else {
        set cmdline "exec cmd /c start cmd"
        set description shell
      }
      button $tool_frame.xterm -text $description \
          -command $cmdline

      # Set the main window's status bar to read "xterm"
      # or "shell" when the mouse pointer is over the region
      # of the button.
      balloon_bind_info $tool_frame.xterm \
          "Starts a new $description"
      bind $tool_frame.xterm <Leave> "set $top.msg {}"

      # Pack this button onto the toolbar.
      pack $tool_frame.xterm -side left
    }

### Adding Menus and Submenus

You can use the rc.tcl file to add new menus to the menu bar or new menu items to existing menus.

#### Example: Adding an Extras Menu

The following example shows how to add a new menu with two submenus. The first procedure creates the menu and submenu items, and the next two are the procedures that each of the submenu items actually execute.

    proc sn_rc_symbolbrowser {win menu} {
      # Abbreviate the name of the menu to "extras".
      set extras $menu.extras
      # Create a new menu called "Extras".
      menu $extras -tearoff 0
      # Add a menu item to the menu. The second character is
      # the designated hot key. Place this menu fourth in
      # the menu bar.
      $menu insert 3 cascade -label Extras -underline 1 \
        -menu $extras
      # Add two items to the menu.
      $extras add command -label Functions -command \
        "custom_show_symbols Functions" -underline 0
      $extras add command -label Methods -command \
        "custom_show_symbols Methods" -underline 0
    }

    proc custom_show_symbols {symboltype} {
      # Set the scope appropriately.
      switch -- $symboltype {
        "Methods" {
          set scope "md"
        }
        default {
          set scope "fu"
        }
      }

      if {[info commands paf_db_$scope] == ""} {
        sn_error_dialog \
         "No symbols of the type <$scope> are available in the project."
         return
      }

      # Generate a unique name for our new top-level window
      # widget.
      set w .custom_win_$scope
      # See if the window already exists.
      if {![info exists $w]} {
        # Create a new top-level window with a unique name.
        toplevel $w
        # Change its title.
        wm title $w "[sn_read_option project-name] ($symboltype)"
        # Put a frame around this window and add scrollbars
        # that scroll through a listbox.
        frame $w.frm
        scrollbar $w.frm.scrollx -orient horizontal \
          -relief sunken -command "$w.frm.symlist xview"
        scrollbar $w.frm.scrolly -relief sunken \
          -command "$w.frm.symlist yview"
        # Create a listbox to hold the symbol names.
        listbox $w.frm.symlist -height 20 -width 40 \
          -xscrollcommand "$w.frm.scrollx set" \
          -yscrollcommand "$w.frm.scrolly set"
        # If the user double-clicks in the list box, find
        # the nearest entry in the list and pass the name of
        # the symbol to custom_edit_file. This will launch
        # us into the source file where that symbol is
        # defined.
        bind $w.frm.symlist <Double-1> {
          custom_edit_file [%W get [%W nearest %y]]
        }
        # Pack the widgets onto our new window.
        pack $w.frm.scrolly -side right -fill y
        pack $w.frm.scrollx -side bottom -fill x
        pack $w.frm.symlist -expand y -fill both
        pack $w.frm -fill both -expand y
      } else {
        # The window already exists, so just delete
        # everything from the listbox and we'll re-insert
        # the current items in the next step.
        $w.frm.symlist delete 0 end
      }
      # Put all of the database keys into the list.
      eval $w.frm.symlist insert end \
        [paf_db_$scope seq -data]
    }
    proc custom_edit_file {key} {
      # We have been passed the key of a record from either
      # the function or method database tables. We need to
      # determine the filename and line number for the
      # editor to jump into the source code.
      # The key of a record takes the form:
      # { name, start_position, filename }
      if {[llength $key] == 3} {
        set pos [lindex $key 1]
        set filename [lindex $key 2]
      } else {
        set pos [lindex $key 2]
        set filename [lindex $key 3]
      }
      sn_edit_file {} $filename $pos
    }

#### Adding a Menu Item to the Menu Bar

### Changing Functionality Within the Editor

All Source-Navigator Editor windows execute a Tcl procedure called `sn_rc_editor` (if it exists) at start-up. You can implement this procedure in the file `rc.tcl` as described in the section Adding Events to the rc.tcl File. The input parameters of this procedure are as follows:

- the name of the view.
- the name of the text widget.

#### Example: Adding or Changing Editor Keyboard Shortcuts

You can add or change keyboard shortcuts for the Editor using commands shown in the following example `rc.tcl` file. This example demonstrates how the built-in Editor can be customized to emulate other popular editors.
Note that the `bind` command assigns the key bindings Ctrl+A and Ctrl+E to move the cursor to the beginning and end of a line, respectively.
`proc sn_rc_editor {view text} {`

`set top [winfo toplevel $view]`
`set menu_frame $top.menu`
`set tool_frame $top.exp`

`# Bind Control-a to jump to the start of the line`
`# (like emacs).`
`bind $text <Control-a> {`
`%W mark set insert "insert linestart"`
`%W yview -pickplace insert`
`break`
`}`
`# Bind Control-e to jump to the end of the line`
`# (like emacs).`
`bind $text <Control-e> {`
`%W mark set insert "insert lineend"`
`%W yview -pickplace insert`
`break`
`}`
`}`

For more information about bindings, see Practical Programming in Tcl and Tk by Brent B. Welch, page 285.

#### Example: Changing Behavior of Editor Toolbar Buttons

The following example shows how to change the behavior of the Compile button so it compiles the current source file using the Java bytecode compiler rather than `gcc`.

Note: | This example only works when the extended toolbar buttons are enabled. To enable them, select File -> Project Preferences, then select the Extended toolbar buttons checkbox from the Edit tab of the Preferences Dialog.

    proc sn_rc_editor {view text} {
      set top [winfo toplevel $view]
      set menu_frame $top.menu
      set tool_frame $top.exp.editfr

    # MAKE SURE THAT THE EXTENDED TOOLBAR BUTTONS ARE ENABLED.

      # Reassign the command associated with the "compile" button.
      if {[winfo exists $tool_frame.compile]} {
        $tool_frame.compile config \
          -command "custom_compile $view"
      }
    }
    proc custom_compile {view} {

      # Save the preconfigured "make" command line; we need
      # to tamper with it in this procedure.
      set temp [sn_read_option make-command]
      # Extract the filename.
      set file [$view cget -filename]
      # Set the "make" command line appropriately.
      if {[string match {*.jav*} $file]} {
        sn_modify_option make-command "javac \"$file\""
      }

      # Byte-compile the source file.
      sn_make

      # Restore the "make" command line.
      sn_modify_option make-command $temp
    }

#### Example: Adding a Button to the Editor's Extended Toolbar

The following example shows how the Windows Notepad editor or the UNIX `vi` editor can be integrated into Editor's toolbar as an auxiliary editor.

Note: | This example only works when the extended toolbar buttons are enabled. To enable them, select File -> Project Preferences, then select the Extended toolbar buttons checkbox from the Edit tab of the Preferences Dialog.

    proc sn_rc_editor {view text} {
      global tcl_platform

      set topw [winfo toplevel $view]
      set tool_frame $topw.exp
      # On Windows call Notepad to edit a file.
      if {$tcl_platform(platform) == "windows"} {
        # Create a new button to edit the file using Notepad.
        button $tool_frame.vi -text Notepad \
          -command "exec notepad \[$view getfilename\]"
          balloon_bind_info $tool_frame.vi \
            "Edit current file using the Notepad editor."
      } else {
        # Create a new button to edit the file using vi
        button $tool_frame.vi -text vi \
          -command "exec xterm -T vi -e vi \[$view getfilename\]"
        balloon_bind_info $tool_frame.vi \
          "Edit current file using vi"
      }
      # Pack this button onto the toolbar.
      pack $tool_frame.vi -side left
    }

#### Example: Generating an HTML File of the Project Database

This example shows how you can display project database information in a format that is different from what Source-Navigator usually provides.

    proc html_doc {topw} {
      set actview [$topw ActiveWidget]
      set ed [MultiWindow& @@ list_find_editor $actview]
      if {$ed == ""} {
        bell; return
      }
      doc_start [list [$ed getfilename]]
    }
    proc sn_rc_editor {view editor} {
      # main window
      set topw [winfo toplevel $view]
      # add a menu entry for the html documentation
      set mn $topw.menu
      $mn.tools add command \
          -label "HTML Documentation" \
          -command "html_doc $topw"
    }

From the Editor, select Tools -> HTML Documentation, and Source-Navigator brings up a browser window containing definitions and cross-references of the symbols in your project.

#### Generating an HTML Representation of the Project Database

## Error Formats

Source-Navigator can receive and act upon messages from external tools such as a compiler or debugger through use of a configurable error format file that can be found in `.../share/etc/sn_cmp_g.pat`.
The contents of this error-format file is as follows; the comment above each regular expression illustrates the kind of text that the given expression can handle. More information on regular expressions can be found in the Grep chapter of the Source-Navigator User's Reference Guide.

    # Source-Navigator regular expressions for compiler,
    # debugger and grep patterns.

    # Source-Navigator supports also blanks, so the patterns
    # must be so defined that blanks could be a part of the filename

    # "filename.c", line 789
    "([^" ]+)",[ ]+line[ ]+([0-9]+)

    # filename.c, line 789
    ([^ ]+),[ ]+line[ ]+([0-9]+)

    # line 789, filename.c,
    line[ ]+([0-9]+),[ ]+([^, ]+)

    # [filename.c:789]
    \[([^\[: ]+):([0-9]+)\]

    # filename.c:789
    ([^: ]+):[ ]*([0-9]+)

    # filename.c(789)
    ([^ ]+\.[^ ]+)\(([0-9]+)\)

    # filename.c(789,11) or filename.c(789.11)
    ([^ ]+\.[^ ]+)\(([0-9]+[,.][ ]*[0-9]+)\)

    # /dir/filename.c, 789
    ([^/ ]+),[ ]+([0-9]+)

The lines beginning with the hash `#` symbol are comments showing matching patterns; the GNU regular expression describes the expressions. Every expression must contain two expressions enclosed in parentheses (for the file name and line number).