summaryrefslogtreecommitdiff
path: root/lib/leftpanel
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
committerAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
commit5b8466f7fae0e071c0f4eda13051c93313910028 (patch)
tree7061957f770e5e245ba00666dad912a2d44e7fdc /lib/leftpanel
Import Upstream version 1.3.7
Diffstat (limited to 'lib/leftpanel')
-rwxr-xr-xlib/leftpanel/filelist.tcl4824
-rwxr-xr-xlib/leftpanel/fsbrowser.tcl1164
-rwxr-xr-xlib/leftpanel/sfrwatches.tcl620
3 files changed, 6608 insertions, 0 deletions
diff --git a/lib/leftpanel/filelist.tcl b/lib/leftpanel/filelist.tcl
new file mode 100755
index 0000000..c5f5c14
--- /dev/null
+++ b/lib/leftpanel/filelist.tcl
@@ -0,0 +1,4824 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Provides:
+# - List of opened files
+# - List of project files
+# - Filesystem browser
+# - Management of opened files, project files and code editors
+# --------------------------------------------------------------------------
+
+# Import nesesary sources
+source "${::LIB_DIRNAME}/leftpanel/fsbrowser.tcl" ;# File system browser
+source "${::LIB_DIRNAME}/leftpanel/sfrwatches.tcl" ;# SRF Watches
+
+class FileList {
+ # Inherit content of some other clases
+ inherit RightPanel SFRWatches FSBrowser
+
+ ## COMMON
+ # String: Textvariable for dialog "Open with ..."
+ common open_with ${::CONFIG(OPEN_WITH_DLG)}
+ common open_with_cnfr 0 ;# Bool: Confirm dialog "Open with ..."
+ common count 0 ;# Instances counter
+ common file_indexes {} ;# List of line indexes (auxiliary variable for opening multiple files)
+ common ac_index_in_fl ;# Index of actual editor filelist
+ common default_encoding {utf-8} ;# Default encoding
+ common default_eol {lf} ;# Default EOL
+ common bookmark 0 ;# Auxiliary variable for popup menu for Icon Borders
+ common pmenu_cline 0 ;# Auxiliary variable for popup menu for Icon Borders
+ # Menu items to disable when entering simulator mode
+ common freezable_menu_items {
+ {New} {Close} {Close All} {Open}
+ }
+ # Font for opened file in project files list
+ common opened_file_font [font create \
+ -weight bold \
+ -slant roman \
+ -size -12 \
+ -family $::DEFAULT_FIXED_FONT \
+ ]
+ # Font for closed file in project files list
+ common closed_file_font [font create \
+ -weight normal \
+ -slant italic \
+ -size -12 \
+ -family $::DEFAULT_FIXED_FONT \
+ ]
+ # Font for icon borders
+ common icon_border_font [font create \
+ -size -12 \
+ -family $::DEFAULT_FIXED_FONT \
+ ]
+
+ common filelist {} ;# List of files to open
+ common open_files_cur_file {} ;# Name of file currently being opened
+ common open_files_progress 0 ;# True if opening files in progress
+ common open_files_abort 0 ;# Abort variable for open files ProgressDialog
+ common filedetails_visible 0 ;# Bool: Is file details window visible
+ common filedetails_after_ID ;# ID of timeout for show window "file details"
+
+ # Definition of popup menu for listbox of opened files
+ common OPENEDFILESMENU {
+ {command {Append to project} {} 0 "filelist_append_to_prj" {add}
+ "Append this file to the current project"}
+ {separator}
+ {command {New} {$edit:new} 0 "editor_new" {filenew}
+ "Create new file and open its editor"}
+ {separator}
+ {command {Open} {$edit:open} 0 "editor_open" {fileopen}
+ "Open an existing file"}
+ {separator}
+ {command {Save} {$edit:save} 0 "editor_save" {filesave}
+ "Save this file"}
+ {command {Save as} {$edit:save_as} 5 "editor_save_as" {filesaveas}
+ "Save this file under different name"}
+ {command {Save all} {$edit:save_all} 6 "editor_save_all" {save_all}
+ "Save all file in the list"}
+ {separator}
+ {command {Close} {$edit:close} 0 "editor_close 1 {}" {fileclose}
+ "Close this file"}
+ {command {Close All} {$edit:close_all} 4 "editor_close_all 1 0" {cancel}
+ "Close all files in the list"}
+ {separator}
+ {command {Bookmark} {} 4 "filelist_o_bookmark" {bookmark_add}
+ "Add/Remove bookmark for this file"}
+ {separator}
+ {command {Move up} {} 5 "filelist_move_up" {1uparrow}
+ "Move this file up in the list"}
+ {command {Move down} {} 5 "filelist_move_down" {1downarrow}
+ "Move this file down in the list"}
+ {command {Move to top} {} 8 "filelist_move_top" {top}
+ "Move this file to the top of the list"}
+ {command {Move to bottom} {} 12 "filelist_move_bottom" {bottom}
+ "Move this file to the bottom of the list"}
+ {separator}
+ {cascade "Sort items by" 11 "" .sort_by false 1 {
+ {command {Document Name} {} 9 "sort_file_list N 1" {} {}}
+ {command {File URL} {} 5 "sort_file_list U 1" {} {}}
+ {command {File Size in B} {} 5 "sort_file_list S 1" {} {}}
+ }}
+ {cascade "Open with" 6 "" .open_with false 1 {
+ {command {gvim} {} 1 "filelist_open_with 1 gvim" {gvim} {}}
+ {command {emacs} {} 1 "filelist_open_with 1 emacs" {emacs} {}}
+ {command {kwrite} {} 0 "filelist_open_with 1 kwrite" {kwrite} {}}
+ {command {gedit} {} 0 "filelist_open_with 1 gedit" {gedit} {}}
+ {command {other} {} 0 "filelist_open_with 1 other" {exec} {}}
+ }}
+ {separator}
+ {command {Hide the panel} {} 0 "filelist_show_hide" {2leftarrow}
+ "Hide this panel"}
+ }
+
+ # Definition of popup menu for notebook with opened files
+ common FILETABSPUMENU {
+ {command {Append to project} {} 0 "filelist_append_to_prj" {add}
+ "Append this file to the current project"}
+ {separator}
+ {command {Save} {$edit:save} 0 "editor_save" {filesave}
+ "Save this file"}
+ {command {Save as} {$edit:save_as} 5 "editor_save_as" {filesaveas}
+ "Save this file under different name"}
+ {command {Save all} {$edit:save_all} 6 "editor_save_all" {save_all}
+ "Save all file in the list"}
+ {separator}
+ {command {Close} {$edit:close} 0 "editor_close 1 {}" {fileclose}
+ "Close this file"}
+ {command {Close All} {$edit:close_all} 4 "editor_close_all 1 0" {cancel}
+ "Close all files in the list"}
+ {separator}
+ {command {Bookmark} {} 4 "filelist_o_bookmark" {bookmark_add}
+ "Add/Remove bookmark for this file"}
+ {separator}
+ {cascade "Open with" 6 "" .open_with false 1 {
+ {command {gvim} {} 1 "filelist_open_with 1 gvim" {gvim} {}}
+ {command {emacs} {} 1 "filelist_open_with 1 emacs" {emacs} {}}
+ {command {kwrite} {} 0 "filelist_open_with 1 kwrite" {kwrite} {}}
+ {command {gedit} {} 0 "filelist_open_with 1 gedit" {gedit} {}}
+ {command {other} {} 0 "filelist_open_with 1 other" {exec} {}}
+ }}
+ }
+
+ # Definition of popup menu for listbox of project files
+ common PROJECTFILESMENU {
+ {command {Remove file from the project} {} 0 "filelist_remove_file_from_project" {editdelete}
+ "Remove this file from the project"}
+ {command {Close file} {$edit:close} 0 "filelist_project_file_close"
+ {fileclose} "Close this file"}
+ {command {Open file} {} 0 "filelist_project_file_open" {fileopen}
+ "Open this file"}
+ {separator}
+ {command {Bookmark} {} 4 "filelist_p_bookmark" {bookmark_add}
+ "Add/Remove bookmark for this file"}
+ {separator}
+ {command {Move up} {} 5 "filelist_prj_move_up" {1uparrow}
+ "Move this item up"}
+ {command {Move down} {} 5 "filelist_prj_move_down" {1downarrow}
+ "Move this item down"}
+ {command {Move to top} {} 8 "filelist_prj_move_top" {top}
+ "Move this item to the top of the list"}
+ {command {Move to bottom} {} 12 "filelist_prj_move_bottom" {bottom}
+ "Move this item to the bottom of the list"}
+ {separator}
+ {cascade "Sort items by" 11 "" .sort_by false 1 {
+ {command {Document Name} {} 9 "sort_file_list N 0" {} {}}
+ {command {File URL} {} 5 "sort_file_list U 0" {} {}}
+ {command {File Size in B} {} 5 "sort_file_list S 0" {} {}}
+ }}
+ {cascade "Open with" 6 "" .open_with false 1 {
+ {command {gvim} {} 1 "filelist_open_with 0 gvim" {gvim} {}}
+ {command {emacs} {} 1 "filelist_open_with 0 emacs" {emacs} {}}
+ {command {kwrite} {} 0 "filelist_open_with 0 kwrite" {kwrite} {}}
+ {command {gedit} {} 0 "filelist_open_with 0 gedit" {gedit} {}}
+ {command {other} {} 0 "filelist_open_with 0 other" {exec} {}}
+ }}
+ {separator}
+ {command {Hide the panel} {} 0 "filelist_show_hide" {2leftarrow}
+ "Hide this panel"}
+ }
+
+ # Definition of popup menu icon border for list of of opened files
+ common OPENEDFILESIBMENU {
+ {checkbutton "Bookmark" "" {::FileList::bookmark} 1 0 0
+ {opened_files_bookmark ${::FileList::pmenu_cline}}}
+ }
+ # Definition of popup menu icon border for list of of project files
+ common PROJECTFILESIBMENU {
+ {checkbutton "Bookmark" "" {::FileList::bookmark} 1 0 0
+ {project_files_bookmark ${::FileList::pmenu_cline}}}
+ }
+
+ ## PUBLIC
+ public variable actualEditor ;# Object number of currently selected editor
+ public variable actualEditor2 -2 ;# Object number of currently selected editor in the second view
+ public variable ProjectDir ;# Reference to directory of actual project
+ public variable editors {} ;# list of editor objects
+ public variable iconBorder $::CONFIG(ICON_BORDER) ;# Bool: display Icon border
+ public variable lineNumbers $::CONFIG(LINE_NUMBERS) ;# Bool: display Line numbers
+
+ ## PRIVATE
+ # Bool: procedure switchfile will not forget its frame (cleared by procedure switchfile)
+ private variable do_not_forget_editor 0
+ private variable editor_close_in_progress 0 ;# Bool: Indicates than procedure editor_close is in progress
+ private variable pwin_orient {} ;# String multiview orientaion (horizontal or vertical)
+ private variable multiview_sash_pos 0 ;# Int: position of panedwindow sash for multiview
+ private variable selectedView 0 ;# Int: 0 == left/top view; 1 == right/bottom view
+ private variable splitted 0 ;# Bool: Editor is splitted
+ private variable main_frame ;# Widget: frame containing $multiview_paned_win or $pagesManager
+ private variable untitled_num -1 ;# Number of untitled entries in file list
+ private variable leftPanel ;# ID of the left panel
+ private variable notebook ;# ID of left panel Notebook
+ private variable parent ;# ID of parent container widget
+ private variable button_bar ;# ID of show/hide button (for listbox of files)
+ private variable lastItem ;# Descriptor of the last selected file
+ private variable obj_idx ;# Index of This object
+ private variable pagesManager ;# ID of frame for packing editors
+ private variable pagesManager2 ;# ID of frame for packing editors in second view
+ private variable multiview_paned_win ;# ID of paned window for $pagesManager and $pagesManager2
+ private variable listbox_opened_files ;# ID of ListBox of currently opened files
+ private variable listbox_opened_files_bm ;# ID of icon border for opened files
+ private variable opened_files_bookmarks {} ;# List: Bookmarks for opened files
+ private variable IB_o_menu ;# ID of popup menu for 'listbox_opened_files_bm'
+ private variable listbox_project_files ;# ID of ListBox of currently opened files
+ private variable listbox_project_files_bm ;# ID of icon border for project files
+ private variable project_files_bookmarks {} ;# List: Bookmarks for project files
+ private variable IB_p_menu ;# ID of popup menu for 'listbox_project_files_bm'
+ private variable last_sash ;# Last position of the paned window sash
+ private variable next_editor_button ;# ID of button "Next editor" -- tab "Opened files"
+ private variable prev_editor_button ;# ID of button "Prev editor" -- tab "Opened files"
+ private variable opened_files_scrollbar ;# ID of scrollbar for opened files visible
+ private variable o_scrollbar_visible 0 ;# Bool: Scrollbar for opened files visible
+ private variable project_files_scrollbar ;# ID of scrollbar for project files visible
+ private variable p_scrollbar_visible 0 ;# Bool: Scrollbar for project files visible
+ private variable opened_files_menu ;# ID of the popup menu asociated with list of opened files
+ private variable project_files_menu ;# ID of the popup menu asociated with list of project files
+ private variable filetabs_pu_menu
+ private variable frozen 0 ;# Bool: Simulator mode flag
+ private variable unsaved ;# List of editor objects with positive flag modified
+ private variable listbox_opened_files_frame ;# Frame for list of opened files
+ private variable listbox_project_files_frame ;# Frame for list of project files
+ private variable fs_browser_frame ;# Frame for file system browser
+ private variable sfr_watches_frame ;# Frame for SFR watches
+ private variable opened_files_buttonBox ;# ID of buttonBox in list of opened files
+ private variable project_files_buttonBox ;# ID of buttonBox in list of project files
+ private variable listbox_opened_files_top_frame ;# Identifier of button frame above listbox of files
+
+ private variable opened_search_entry ;# ID of search entry for opened files
+ private variable opened_search_clear_button ;# ID of button "Clear" on search panel -- opened files
+ private variable opened_files_highlighted_item {} ;# ID of currently highlighted item in opened files
+ private variable opened_files_hg_item_fg_clr {} ;# Fg. color of currently highlighted item in opened files
+ private variable project_search_entry ;# ID of search entry for project files
+ private variable project_search_clear_button ;# ID of button "Clear" on search panel -- project files
+ private variable project_files_highlighted_item {} ;# ID of currently highlighted item in project files
+ private variable project_files_hg_item_fg_clr {} ;# Fg. color of currently highlighted item in project files
+ private variable item_menu_invoked 0 ;# Bool: Item menu request
+ private variable editor_command_line_on 0 ;# Bool: Editor command line visible
+
+ private variable simulator_editor 0 ;# Int: Current file number (for simulator)
+ private variable file_switching_enabled 1 ;# Bool: Automatic file switching enabled
+ private variable simulator_editor_obj ;# Object: Code editor used by simulator
+
+ private variable active_page $::CONFIG(LEFT_PANEL_ACTIVE_PAGE) ;# Active page in the left panel
+ private variable PanelVisible $::CONFIG(LEFT_PANEL) ;# Bool: panel visible
+ private variable PanelSize $::CONFIG(LEFT_PANEL_SIZE) ;# Panel width (in pixels)
+
+ private variable editor_to_freeze_obj ;# Object: Editor to freeze after simulator startup
+ private variable filetabs_frm ;# Widget: Frame contaning the tab bar
+ private variable filetabs_nb ;# Widget: Tab bar's notebook widget
+
+ ## PROTECTED
+ protected variable file_count 0 ;# counter of opened files
+ protected variable editor_wdgs {} ;# list of editor widgets
+ protected variable file_descriptors {} ;# list of descriptors of opened files
+ protected variable file_eol {} ;# List of EOLs for opened editors
+ protected variable file_encoding {} ;# List of encodings for opened editors
+ protected variable file_ro_mode {} ;# List of read only flags for opened editors
+ protected variable file_sh {} ;# List of syntax highlight id's for opened editors
+
+ ## object constructor
+ constructor {} {
+ # increment instance counter
+ incr count
+ set obj_idx $count
+ }
+
+ ## Object destructor
+ destructor {
+ # Destroy editors
+ foreach editor $editors {
+ delete object $editor
+ }
+ # Unregister status bar tips for popup menus
+ menu_Sbar_remove $opened_files_menu
+ menu_Sbar_remove $project_files_menu
+ menu_Sbar_remove $filetabs_pu_menu
+ }
+
+ ## Initialize GUI components
+ # @parm String parentPane - Identifier of pane window in which it shoul be packed
+ # @parm String projectDir - Directory of current project
+ # @parm List filelist - List of files to open (full filenames including path)
+ # @parm Bool editor_sw_lock - Enable aoutomatic file switching during simulation
+ # @return void
+ public method initiate_FileList {parentPane projectDir FileList editor_sw_lock} {
+
+ # Object variables
+ set parent $parentPane ;# ID of parent container widget
+ set ProjectDir $projectDir ;# Reference to directory of actual project
+ set file_switching_enabled $editor_sw_lock
+
+ # Class variables
+ set filelist $FileList ;# List of files to open
+
+ # Create notebook frame
+ set leftPanel [frame $parentPane.frm_FileList_leftPanel]
+ # Create notebook
+ set notebook [NoteBook $leftPanel.nb_FileList \
+ -side top -arcradius 4 -bg {#EEEEEE} \
+ ]
+ # Create tab "Hide"
+ $notebook insert end "button_SH" -image ::ICONS::16::2leftarrow \
+ -raisecmd "$this filelist_show_hide" \
+ -helptext [mc "Hide this panel"]
+ # Create tab for list of opened files
+ set listbox_opened_files_frame [$notebook insert end "opened_files" \
+ -image ::ICONS::16::fileopen \
+ -raisecmd "$this Left_panel_set_active_page opened_files" \
+ -helptext [mc "Opened files"] \
+ ]
+ # Create tab for list of project files
+ set listbox_project_files_frame [$notebook insert end "project_files" \
+ -image ::ICONS::16::project_open \
+ -raisecmd "$this Left_panel_set_active_page project_files" \
+ -helptext [mc "Files in the project"] \
+ ]
+ # Create tab for file system browser
+ set fs_browser_frame [$notebook insert end "fs_browser" \
+ -image ::ICONS::16::exec \
+ -raisecmd "$this Left_panel_set_active_page fs_browser" \
+ -helptext [mc "Filesystem browser"] \
+ -createcmd [list $this CreateFSBrowserGUI] \
+ ]
+ # Create tab for SFR watches
+ set sfr_watches_frame [$notebook insert end "sfr_watches" \
+ -image ::ICONS::16::kcmmemory \
+ -raisecmd "$this Left_panel_set_active_page sfr_watches" \
+ -helptext [mc "List of SFR's"] \
+ -createcmd [list $this CreateSFRWatchesGUI] \
+ ]
+
+ # Prepare panel componenets but do not create GUI elements
+ PrepareFSBrowser $fs_browser_frame
+ PrepareSFRWatches $sfr_watches_frame
+
+
+ # Register notebook status bar tips
+ notebook_Sbar_set {filelist} [list \
+ button_SH [mc "Hide the panel"] \
+ opened_files [mc "Opended files"] \
+ project_files [mc "Files of the current project"] \
+ fs_browser [mc "Filesystem browser"] \
+ sfr_watches [mc "Special Function Registers"] \
+ ]
+ $notebook bindtabs <Enter> "notebook_Sbar filelist"
+ $notebook bindtabs <Leave> "Sbar {} ;#"
+
+ # Create listbox of opened files
+ set lsbox_frame [frame $listbox_opened_files_frame.lsbox_frame]
+ set listbox_opened_files_bm [text $lsbox_frame.icon_border \
+ -font $icon_border_font \
+ -cursor left_ptr \
+ -width 2 \
+ -bd 0 \
+ -pady 1 \
+ -highlightthickness 0 \
+ -bg {#DDDDDD} \
+ -exportselection 0 \
+ -takefocus 0 \
+ -cursor hand1 \
+ ]
+ $listbox_opened_files_bm tag configure center -justify center
+ $listbox_opened_files_bm delete 1.0 end
+ setStatusTip -widget $listbox_opened_files_bm \
+ -text [mc "Bookmarks for opened files"]
+ set listbox_opened_files [ListBox $lsbox_frame.listbox_opened_files \
+ -selectmode single -selectfill 0 -bg white \
+ -selectbackground white -highlightcolor {#BBBBFF} \
+ -selectforeground {#0000FF} -bd 1 \
+ -highlightthickness 0 -deltay 15 -padx 14 \
+ -yscrollcommand "$this filelist_o_scrollbar_set" \
+ ]
+ setStatusTip -widget $listbox_opened_files \
+ -text [mc "List of opened files"]
+ set opened_files_scrollbar [ttk::scrollbar \
+ $lsbox_frame.scrollbar \
+ -orient vertical \
+ -command "$this filelist_o_scroll" \
+ ]
+
+ # Create popup menu for icon border
+ set IB_o_menu $listbox_opened_files_bm.ib_o_menu
+ menuFactory $OPENEDFILESIBMENU $IB_o_menu 0 "$this " 0 {}
+
+ # Create bottom frame
+ set listbox_opened_files_bottom_frame [frame $listbox_opened_files_frame.bottom_frame]
+ set listbox_opened_files_bottom0_frame [frame $listbox_opened_files_bottom_frame.top]
+ set listbox_opened_files_bottom1_frame [frame $listbox_opened_files_bottom_frame.bottom]
+ # Create search panel
+ set opened_search_entry [ttk::entry $listbox_opened_files_bottom0_frame.entry \
+ -validatecommand "$this filelist_opened_search %P" \
+ -validate all \
+ -width 0 \
+ ]
+ DynamicHelp::add $opened_search_entry -text [mc "Search for file"]
+ setStatusTip -widget $opened_search_entry \
+ -text [mc "Search for certain file name in list of opened files"]
+ pack $opened_search_entry -side left -fill x -expand 1
+ set opened_search_clear_button [ttk::button \
+ $listbox_opened_files_bottom0_frame.clear_button \
+ -command "$opened_search_entry delete 0 end" \
+ -image ::ICONS::16::clear_left \
+ -state disabled \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $listbox_opened_files_bottom0_frame.clear_button -text [mc "Clear search entry box"]
+ setStatusTip -widget $opened_search_clear_button \
+ -text [mc "Clear search entry box"]
+ pack $opened_search_clear_button -side right -after $opened_search_entry
+ # Create buttons "Previous" and "Next"
+ set prev_editor_button [ttk::button \
+ $listbox_opened_files_bottom1_frame.prev \
+ -command {::X::__prev_editor} \
+ -image ::ICONS::16::1leftarrow \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $listbox_opened_files_bottom1_frame.prev \
+ -text [mc "Previous editor"]
+ pack $prev_editor_button -side left
+ setStatusTip -widget $prev_editor_button \
+ -text [mc "Switch to the previous editor"]
+ set next_editor_button [ttk::button \
+ $listbox_opened_files_bottom1_frame.next \
+ -command {::X::__next_editor} \
+ -image ::ICONS::16::1rightarrow \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $listbox_opened_files_bottom1_frame.next \
+ -text [mc "Next editor"]
+ pack $next_editor_button -side left
+ setStatusTip -widget $next_editor_button \
+ -text [mc "Switch to the next editor"]
+
+ # Frame for opened files
+ set listbox_opened_files_top_frame [frame \
+ $listbox_opened_files_frame.listbox_opened_files_top_frame]
+ # Button box for "Opened files"
+ set opened_files_buttonBox [frame \
+ $listbox_opened_files_top_frame.opened_files_buttonBox]
+ # Pages managers for editor(s), etc.
+ set main_frame [frame $parentPane.main_frame]
+
+ # Create filetabs notebook
+ set filetabs_frm [frame $main_frame.filetabs_frm -height 16]
+ pack [ttk::button $filetabs_frm.add_button \
+ -image ::ICONS::16::filenew \
+ -command {::X::__new} \
+ -style Flat.TButton \
+ ] -side left
+ set filetabs_nb [NoteBook $filetabs_frm.filetabs_nb \
+ -side top -arcradius 4 -bg {#EEEEEE} \
+ -font [font create -family {Helvetica} -size -12] \
+ ]
+ pack configure $filetabs_nb.c -fill x -expand 0
+ pack $filetabs_nb -fill x -anchor sw -side left -expand 1
+ $filetabs_nb bindtabs <Enter> "$this file_details_win_create_from_ftnb"
+ $filetabs_nb bindtabs <Leave> "$this file_details_win_hide"
+ $filetabs_nb bindtabs <Motion> "$this file_details_win_move"
+ $filetabs_nb bindtabs <ButtonRelease-3> "$this filetabs_nb_popup_menu %X %Y"
+ pack [ttk::button $filetabs_frm.close_button \
+ -image ::ICONS::16::fileclose \
+ -command {::X::__close} \
+ -style Flat.TButton \
+ ] -side right
+
+ set multiview_paned_win [panedwindow \
+ $main_frame.multiview_paned_win \
+ -sashwidth 2 \
+ -showhandle 0 \
+ -opaqueresize 1 \
+ -sashrelief flat \
+ ]
+ set pagesManager [frame $main_frame.pagesManager]
+ set pagesManager2 [frame $main_frame.pagesManager2]
+
+ # Create icon bar for "Opened files"
+ iconBarFactory $opened_files_buttonBox "$this " \
+ [string range $opened_files_buttonBox 1 end] ::ICONS::16:: {
+ {bookmark "Bookmark" {bookmark_add} {filelist_o_bookmark}
+ "Add/Remove bookmark"}
+ {separator}
+ {up "Move file up" {1uparrow} {filelist_move_up}
+ "Move selected file up in the list"}
+ {down "Move file down" {1downarrow} {filelist_move_down}
+ "Move selected file down in the list"}
+ {top "Move item to top" {top} {filelist_move_top}
+ "Move selected file to the top of the list"}
+ {bottom "Move item to bottom" {bottom} {filelist_move_bottom}
+ "Move selected file to the bottom of the list"}
+ }
+
+ # Pack GUI components of tab "Opened files"
+ pack $opened_files_buttonBox -side left
+ pack $listbox_opened_files_top_frame -side top -anchor w
+ pack $listbox_opened_files_bottom1_frame -side top
+ pack $listbox_opened_files_bottom0_frame -side top -fill x
+ pack $listbox_opened_files_bottom_frame -side bottom -fill x -pady 3
+ pack $lsbox_frame -side top -anchor nw -fill both -expand 1
+ pack $listbox_opened_files -side right -fill both -expand 1
+ pack $listbox_opened_files_bm -before $listbox_opened_files -fill y -side left
+
+ # Create list of project files
+ set ls_frame [frame $listbox_project_files_frame.ls_frame]
+ set listbox_project_files_bm [text $ls_frame.icon_border \
+ -font $icon_border_font \
+ -cursor left_ptr \
+ -width 2 \
+ -bd 0 \
+ -pady 1 \
+ -highlightthickness 0 \
+ -bg {#DDDDDD} \
+ -exportselection 0 \
+ -takefocus 0 \
+ -cursor hand1 \
+ ]
+ $listbox_project_files_bm delete 1.0 end
+ $listbox_project_files_bm tag configure center -justify center
+ setStatusTip -widget $listbox_project_files_bm \
+ -text [mc "Bookmarks for project files"]
+ set listbox_project_files [ListBox $ls_frame.listbox_project_files \
+ -selectmode single -highlightthickness 0 -bd 1 -padx 0 \
+ -selectbackground white -bg white -deltay 15 \
+ -selectforeground {#0000FF} -highlightcolor {#BBBBFF} \
+ -yscrollcommand "$this filelist_p_scrollbar_set" \
+ ]
+ setStatusTip -widget $listbox_project_files \
+ -text [mc "List of project files"]
+ set project_files_scrollbar [ttk::scrollbar \
+ $ls_frame.scrollbar \
+ -orient vertical \
+ -command "$this filelist_p_scroll" \
+ ]
+
+ # Create popup menu for icon border
+ set IB_p_menu $listbox_project_files.ib_o_menu
+ menuFactory $PROJECTFILESIBMENU $IB_p_menu 0 "$this " 0 {}
+
+ # Create search panel
+ set search_panel [frame $listbox_project_files_frame.search_panel]
+ set project_search_entry [ttk::entry $search_panel.entry \
+ -validatecommand "$this filelist_project_search %P" \
+ -validate all \
+ -width 0 \
+ ]
+ DynamicHelp::add $project_search_entry -text [mc "Search for file"]
+ setStatusTip -widget $project_search_entry \
+ -text [mc "Search for certain file name in list of project files"]
+ pack $project_search_entry -side left -fill x -expand 1
+ set project_search_clear_button [ttk::button \
+ $search_panel.clear_button \
+ -command "$project_search_entry delete 0 end" \
+ -image ::ICONS::16::clear_left \
+ -state disabled \
+ -style Flat.TButton \
+ ]
+ DynamicHelp::add $search_panel.clear_button \
+ -text [mc "Clear search entry box"]
+ setStatusTip -widget $project_search_clear_button \
+ -text [mc "Clear search entry box"]
+ pack $project_search_clear_button -side right -after $project_search_entry
+
+ # Create header (label and icon bar) for tab "Project files"
+ set topFrame [frame $listbox_project_files_frame.listbox_project_files_top_frame]
+ pack [label $topFrame.listbox_project_files_label \
+ -text [mc "Project files:"] -anchor w \
+ ] -fill x -side top -anchor w -pady 5
+ set project_files_buttonBox [frame $topFrame.listbox_project_files_buttonBox]
+ pack $project_files_buttonBox -side bottom -anchor w -expand 0
+
+ # Create icon bar for tab "Project files"
+ iconBarFactory $project_files_buttonBox "$this " \
+ [string range $project_files_buttonBox 1 end] ::ICONS::16:: {
+ {bookmark "Bookmark" {bookmark_add}
+ {filelist_p_bookmark}
+ "Add/Remove bookmark"}
+ {separator}
+ {open "Open this file" {fileopen}
+ {filelist_project_file_open}
+ "Open this file and create its own editor"}
+ {close "Close this file" {fileclose}
+ {filelist_project_file_close}
+ "Close this file and close its editor"}
+ {separator}
+ {remove "Remove this file from the project" {editdelete}
+ {filelist_remove_file_from_project}
+ "Exclude this file from list of files of this project"}
+ }
+
+ # Evaluate icon bars button states (tab "Project files")
+ FileList_project_disEna_buttons
+
+ # Pack frames of tab "Projet files"
+ pack $topFrame -fill x -side top -anchor w
+ pack $listbox_project_files -fill both -expand 1 -side right
+ pack $listbox_project_files_bm -before $listbox_project_files -fill y -side left
+ pack $search_panel -side bottom -fill x
+ pack $ls_frame -fill both -expand 1 -side top
+
+ ## Create button bar
+ set button_bar [frame $leftPanel.button_bar]
+ # Button "Show"
+ pack [ttk::button $button_bar.but_show \
+ -image ::ICONS::16::2rightarrow \
+ -command "$this filelist_show_hide" \
+ -style ToolButton.TButton \
+ ]
+ DynamicHelp::add $button_bar.but_show -text [mc "Show the panel"]
+ setStatusTip -widget $button_bar.but_show \
+ -text [mc "Show the panel"]
+ # Separator
+ pack [ttk::separator $button_bar.sep -orient horizontal] -fill x -pady 2
+
+ # Button "Instruction details"
+ pack [ttk::button $button_bar.but_opened \
+ -image ::ICONS::16::fileopen \
+ -style ToolButton.TButton \
+ -command "$this filelist_show_up opened_files" \
+ ]
+ DynamicHelp::add $button_bar.but_opened -text [mc "Currently opened files"]
+ setStatusTip -widget $button_bar.but_opened \
+ -text [mc "Currently opened files"]
+ # Button "opened files"
+ pack [ttk::button $button_bar.but_proj_open \
+ -image ::ICONS::16::project_open \
+ -style ToolButton.TButton \
+ -command "$this filelist_show_up project_files" \
+ ]
+ DynamicHelp::add $button_bar.but_proj_open -text [mc "Files in the current project"]
+ setStatusTip -widget $button_bar.but_proj_open \
+ -text [mc "Files of the current project"]
+ # Button "Filesystem browser"
+ pack [ttk::button $button_bar.but_fs_browser \
+ -image ::ICONS::16::exec \
+ -style ToolButton.TButton \
+ -command "$this filelist_show_up fs_browser" \
+ ]
+ DynamicHelp::add $button_bar.but_fs_browser -text [mc "Filesystem browser"]
+ setStatusTip -widget $button_bar.but_fs_browser \
+ -text [mc "Filesystem browser"]
+ # Button "SFR watches"
+ pack [ttk::button $button_bar.but_sfr_watches \
+ -image ::ICONS::16::kcmmemory \
+ -style ToolButton.TButton \
+ -command "$this filelist_show_up sfr_watches" \
+ ]
+ DynamicHelp::add $button_bar.but_sfr_watches -text [mc "SFR watches"]
+ setStatusTip -widget $button_bar.but_sfr_watches \
+ -text [mc "SFR watches"]
+
+ # Show the left panel
+ if {$PanelVisible != 0} {
+ pack $notebook -expand 1 -fill both
+
+ # Raise active page in the panel notebook
+ catch {
+ $notebook raise $active_page
+ }
+ } {
+ set last_sash $PanelSize
+ pack $button_bar -side top -anchor nw
+ }
+
+ # Insert left panel and editor pages manager into parent pane window
+ $parentPane add $leftPanel
+ $parentPane add $main_frame
+
+ # Set bindings for file lists
+ $listbox_opened_files bindText <ButtonRelease-3> "$this fileList_opened_filelist_item_popup %X %Y"
+ $listbox_opened_files bindText <Enter> "$this file_details_win_create O"
+ $listbox_opened_files bindText <Leave> "$this file_details_win_hide"
+ $listbox_opened_files bindText <Motion> "$this file_details_win_move"
+ bind $listbox_opened_files <<ListboxSelect>> "$this switchfile; break"
+ if {[winfo exists $listbox_opened_files.c]} {
+ bind $listbox_opened_files.c <Button-5> {%W yview scroll +5 units; break}
+ bind $listbox_opened_files.c <Button-4> {%W yview scroll -5 units; break}
+ bind $listbox_opened_files.c <ButtonRelease-3> "$this fileList_opened_filelist_popup %X %Y"
+ }
+
+ bind $listbox_opened_files_bm <<Selection>> "false_selection $listbox_opened_files_bm"
+ bind $listbox_opened_files_bm <Button-1> "$this filelist_opened_bookmark_xy %x %y"
+ bind $listbox_opened_files_bm <ButtonRelease-3> "$this filelist_opened_bm_popup_menu %X %Y %x %y"
+ bindtags $listbox_opened_files_bm $listbox_opened_files_bm
+
+ $listbox_project_files bindText <ButtonRelease-3> "$this fileList_project_filelist_item_popup %X %Y"
+ $listbox_project_files bindText <Double-Button-1> "$this filelist_project_file_open"
+ $listbox_project_files bindText <Enter> "$this file_details_win_create P"
+ $listbox_project_files bindText <Leave> "$this file_details_win_hide"
+ $listbox_project_files bindText <Motion> "$this file_details_win_move"
+ bind $listbox_project_files <<ListboxSelect>> "$this project_files_listbox_select"
+ if {[winfo exists $listbox_project_files.c]} {
+ bind $listbox_project_files.c <Button-5> {%W yview scroll +5 units; break}
+ bind $listbox_project_files.c <Button-4> {%W yview scroll -5 units; break}
+ bind $listbox_project_files.c <ButtonRelease-3> "$this fileList_project_filelist_popup %X %Y"
+ }
+
+ bind $listbox_project_files_bm <<Selection>> "false_selection $listbox_project_files_bm"
+ bind $listbox_project_files_bm <Button-1> "$this filelist_project_bookmark_xy %x %y"
+ bind $listbox_project_files_bm <ButtonRelease-3> "$this filelist_project_bm_popup_menu %X %Y %x %y"
+ bindtags $listbox_project_files_bm $listbox_project_files_bm
+
+ # Create popup menus
+ set opened_files_menu $listbox_opened_files.opened_files_menu
+ set project_files_menu $listbox_project_files.project_files_menu
+ set filetabs_pu_menu $filetabs_nb.filetabs_pu_menu
+ filelist_makePopupMenu
+
+ # Create Editor object for each file in $filelist and insert it into ListBox of opened files
+ open_files $filelist
+
+ # Initialize list of opened files
+ set actualEditor [lindex $filelist {1 0}]
+ set actualEditor2 [lindex $filelist {1 1}]
+ set multiview_sash_pos [lindex $filelist {1 2}]
+ set pwin_orient [lindex $filelist {1 3}]
+
+ ## Validate index of current editor(s)
+ if {
+ ![string is digit -strict $actualEditor]
+ ||
+ ($actualEditor >= [llength $editors])
+ ||
+ ($actualEditor < 0)
+ } then {
+ set actualEditor $actualEditor2
+ set splitted 0
+ }
+ if {
+ ![string is digit -strict $actualEditor2]
+ ||
+ ($actualEditor2 >= [llength $editors])
+ ||
+ ($actualEditor2 < 0)
+ ||
+ ($actualEditor2 == $actualEditor)
+ } then {
+ set actualEditor2 -1
+ set splitted 0
+ } else {
+ set splitted 1
+ }
+
+ ## Validate index of current editor in the first view
+ if {
+ [string is digit -strict $actualEditor]
+ &&
+ $actualEditor < [llength $editors]
+ &&
+ $actualEditor >= 0
+ } { ;# Valid value
+ $listbox_opened_files selection set [lindex [$listbox_opened_files items] $actualEditor]
+ set actualEditor -1
+ switchfile
+
+ } else { ;# Invalid value
+ set actualEditor -1
+ if {![llength $editors]} {
+ editor_new
+ } {
+ $listbox_opened_files selection set [lindex [$listbox_opened_files items] 0]
+ switchfile
+ }
+ }
+
+ # Validate selected view, sash orient and sash position
+ set selectedView [lindex $filelist {1 4}]
+ if {![string is bool -strict $selectedView]} {
+ set selectedView 0
+ }
+ if {$pwin_orient != {horizontal} && $pwin_orient != {vertical}} {
+ set pwin_orient {horizontal}
+ }
+ if {![string is digit -strict $multiview_sash_pos] || $multiview_sash_pos < 0} {
+ set multiview_sash_pos 0
+ }
+
+ # Pack editor pages manager
+ if {$splitted} {
+ pack $multiview_paned_win -fill both -expand 1
+ $multiview_paned_win configure -orient $pwin_orient
+ $multiview_paned_win add $pagesManager
+ $multiview_paned_win add $pagesManager2 -after $pagesManager
+
+ if {$pwin_orient == {vertical}} {
+ if {!$multiview_sash_pos} {
+ set multiview_sash_pos [expr {[winfo width $pagesManager] / 2}]
+ }
+ set minsize 300
+ } {
+ if {!$multiview_sash_pos} {
+ set multiview_sash_pos [expr {[winfo height $pagesManager] / 2}]
+ }
+ set minsize 80
+ }
+ $multiview_paned_win paneconfigure $pagesManager -minsize $minsize
+ $multiview_paned_win paneconfigure $pagesManager2 -minsize $minsize
+ pack [[lindex $editors $actualEditor2] cget -ed_sc_frame] \
+ -in $pagesManager2 -fill both -expand 1
+ } {
+ pack $pagesManager -fill both -expand 1
+ }
+ foreach editor $editors {
+ $editor configure_statusbar_menu !$splitted $splitted {} {}
+ }
+
+ # Set panel width
+ update idle
+ if {$PanelVisible != 0} {
+ $parent paneconfigure $leftPanel -minsize 155
+ $parent configure -sashwidth 2
+ $parent sash place 0 $PanelSize 0
+ } {
+ $parent paneconfigure $leftPanel -minsize 0
+ $parent configure -sashwidth 0
+ $parent sash place 0 25 2
+ bind $parent <Button> {break}
+ }
+ bind $parent <ButtonRelease-1> "$this left_panel_set_size"
+
+ # Update multiview sash position
+ if {$splitted} {
+ update idle
+ if {$pwin_orient == {vertical}} {
+ $multiview_paned_win sash place 0 0 $multiview_sash_pos
+ } {
+ $multiview_paned_win sash place 0 $multiview_sash_pos 0
+ }
+ }
+
+ show_hide_tab_bar
+ }
+
+ ## Prepare window file details
+ # @parm Char for - '0' == ListBox of opened files; 'P' == ListBox of project files
+ # @parm String item - Item ID
+ # @return void
+ public method file_details_win_create {for item} {
+ set filedetails_visible 0
+
+ set note {}
+
+ # Determinate full filename
+ if {$for == {O}} {
+ if {![$listbox_opened_files exists $item]} {
+ return
+ }
+ set shortname [$listbox_opened_files itemcget $item -text]
+ set filename [$listbox_opened_files itemcget $item -data]
+ set index [$listbox_opened_files index $item]
+ set encoding [lindex $file_encoding $index]
+ set eol [lindex $file_eol $index]
+ set read_only [lindex $file_ro_mode $index]
+ regexp -line -- {^.*$} [$this get_file_notes_data $index] note
+ } {
+ if {![$listbox_project_files exists $item]} {
+ return
+ }
+ set shortname [$listbox_project_files itemcget $item -text]
+ set data [$listbox_project_files itemcget $item -data]
+ if {[llength $data] < 5} {
+ set filename [lindex $data 0]
+ set eol [lindex $data 1]
+ set encoding [lindex $data 2]
+ set read_only [lindex $data 3]
+ } {
+ set filename "[lindex $data 5][lindex $data 0]"
+ set eol [lindex $data 8]
+ set encoding [lindex $data 9]
+ set read_only [lindex $data 2]
+ }
+ }
+
+ # Skip untitled files
+ if {$filename == {}} {return}
+
+ # Destroy previous window
+ catch {after cancel $filedetails_after_ID}
+ catch {destroy ${::FILEDETAILSWIN}}
+
+ # Create window
+ set ::FILEDETAILSWIN [frame .file_details_win -bg {#AADDFF}]
+ set file_details_win [frame ${::FILEDETAILSWIN}.frm -bg {#FFFFFF}]
+ bind ${::FILEDETAILSWIN} <Button-1> "catch {destroy ${::FILEDETAILSWIN}}"
+
+ # Determinate file type and set appropriate icon
+ set ext [string trimleft [file extension $filename] {.}]
+ if {$ext == {h}} {
+ set icon {source_h}
+ } elseif {$ext == {c}} {
+ set icon {source_c}
+ } elseif {$ext == {cxx} || $ext == {cpp} || $ext == {cc}} {
+ set icon {source_cpp}
+ } elseif {$ext == {asm}} {
+ set icon {asm}
+ } else {
+ set icon {ascii}
+ }
+
+ # Create header
+ set header [frame $file_details_win.header -bg {#AADDFF}]
+ pack [label $header.header \
+ -bg {#AADDFF} -text $shortname \
+ -justify left -pady 0 -padx 15 \
+ -compound left -anchor w \
+ -image ::ICONS::16::$icon \
+ ] -side left
+ if {$read_only == 1} {
+ pack [label $header.ro_text \
+ -bg {#AADDFF} -fg {#FF3333} \
+ -text [mc "(read only)"] \
+ -justify left -pady 0 \
+ ] -side left
+ }
+ pack $header -fill x
+
+ # Show error message if the file dosn't exist
+ if {![file exists $filename]} {
+ pack [label $file_details_win.message_label \
+ -text [mc "File does not exist"] \
+ -fg {#FF0000} \
+ ] -padx 80 -pady 40
+ catch {after cancel $filedetails_after_ID}
+ set filedetails_after_ID [after 750 "
+ set ::FileList::filedetails_visible 1
+ $this file_details_win_move"]
+ return
+ }
+
+ # Determinate informations about the file
+ set size [file size $filename] ;# Size in B
+ set mtime [file mtime $filename] ;# Modification time
+ if {!$::MICROSOFT_WINDOWS} { ;# Microsoft Windows has no file rights (compatible with posix rights)
+ set perms [file attributes $filename] ;# Owner - Group - Permissions
+ }
+
+ # Adjust the informations aboth the file
+ set mtime [clock format $mtime -format {%D %R}]
+ if {!$::MICROSOFT_WINDOWS} { ;# Microsoft Windows has no file rights (compatible with posix rights)
+ set owner "[lindex $perms 1] - [lindex $perms 3]"
+ set perms [lindex $perms 5]
+ set perms [string range $perms {end-3} end]
+ }
+ if {[enc2name $encoding] != {}} {
+ if {[string length $encoding] < 8} {
+ append encoding "\t"
+ }
+ append encoding "\t(" [enc2name [string trimright $encoding]] {)}
+ }
+ if {$size < 1024} {
+ append size { B}
+ } {
+ set kB [expr {$size / 1024}]
+ set B [expr {$size % 1024}]
+ set MB [expr {$kB / 1024}]
+ set kB [expr {$kB % 1024}]
+
+ set original_size $size
+ set size {}
+ if {$MB} {
+ append size $MB { MB }
+ }
+ if {$kB} {
+ append size $kB { kB }
+ }
+ if {$B} {
+ append size $B { B }
+ }
+ append size {(} $original_size { B)}
+ }
+ switch -- $eol {
+ {lf} {set eol "Unix\t\t(LF)"}
+ {crlf} {set eol "DOS\t\t(CRLF)"}
+ {cr} {set eol "Macintosh\t(CR)"}
+ }
+
+ # Create main frame (containing everything except the header)
+ set main_frame [frame $file_details_win.main_frame -bg {#FFFFFF}]
+
+ # Path
+ grid [label $main_frame.path_label \
+ -text [mc "Path:"] \
+ -fg {#0000AA} \
+ -anchor w -bg {#FFFFFF} \
+ ] -row 0 -column 0 -sticky w -pady 0
+ grid [label $main_frame.path_value \
+ -text [file dirname $filename] \
+ -anchor w -bg {#FFFFFF} \
+ ] -row 0 -column 1 -sticky w -pady 0
+
+ # Size
+ grid [label $main_frame.size_label \
+ -text [mc "Size:"] \
+ -fg {#0000AA} \
+ -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 1 -column 0 -sticky w -pady 0
+ grid [label $main_frame.size_value \
+ -text $size -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 1 -column 1 -sticky w -pady 0
+
+ # Modified
+ grid [label $main_frame.modified_label \
+ -text [mc "Modified:"] \
+ -fg {#0000AA} \
+ -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 2 -column 0 -sticky w -pady 0
+ grid [label $main_frame.modified_value \
+ -text $mtime -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 2 -column 1 -sticky w -pady 0
+
+ # Owner
+ if {!$::MICROSOFT_WINDOWS} { ;# Microsoft Windows has no file rights (compatible with posix rights)
+ grid [label $main_frame.owner_label \
+ -text [mc "Owner:"] \
+ -fg {#0000AA} \
+ -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 3 -column 0 -sticky w -pady 0
+ grid [label $main_frame.owner_value \
+ -text $owner -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 3 -column 1 -sticky w -pady 0
+
+ # Permissions
+ grid [label $main_frame.perms_label \
+ -text [mc "Permissions:"] \
+ -fg {#0000AA} -bg {#FFFFFF} \
+ -anchor w -pady 0 \
+ ] -row 4 -column 0 -sticky w -pady 0
+ grid [label $main_frame.perms_value \
+ -text $perms -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 4 -column 1 -sticky w -pady 0
+ }
+
+ if {!${::Editor::editor_to_use}} {
+ # Separator
+ grid [ttk::separator $main_frame.sep \
+ -orient horizontal \
+ ] -row 5 -column 0 -columnspan 2 -sticky we -pady 0
+
+ # Encoding
+ grid [label $main_frame.enc_label \
+ -text [mc "Encoding:"] \
+ -fg {#880033} \
+ -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 6 -column 0 -sticky w -pady 0
+ grid [label $main_frame.enc_value \
+ -text $encoding -anchor w \
+ -pady 0 -bg {#FFFFFF} \
+ ] -row 6 -column 1 -sticky w -pady 0
+
+ # EOL
+ grid [label $main_frame.eol_label \
+ -text [mc "EOL:"] -fg {#880033} \
+ -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 7 -column 0 -sticky w -pady 0
+ grid [label $main_frame.eol_value \
+ -text $eol -anchor w -pady 0 -bg {#FFFFFF} \
+ ] -row 7 -column 1 -sticky w -pady 0
+ }
+
+ # User note
+ if {$note != {} && $for == {O}} {
+ set w_max 350
+ set w [font measure ${::Todo::normal_font} $note]
+
+ if {$w > $w_max} {
+ set note [string range $note 0 [expr {int([string length $note] * $w_max/$w * 0.7)}]]
+ append note {...}
+ }
+
+ # Separator
+ grid [ttk::separator $main_frame.sep1 \
+ -orient horizontal \
+ ] -row 8 -column 0 -columnspan 2 -sticky we -pady 0
+ grid [label $main_frame.notes_value \
+ -anchor w -pady 0 -bg {#FFFFFF} \
+ -text $note -font ${::Todo::normal_font} \
+ -justify left -anchor w -wraplength $w_max \
+ ] -row 9 -column 0 -sticky w -pady 0 -columnspan 2
+ }
+
+ # Pack main frame
+ grid columnconfigure $main_frame 0 -minsize 90
+ pack $main_frame -fill both -expand 1 -padx 8 -pady 3
+ pack $file_details_win -fill both -expand 1 -padx 2 -pady 2
+
+ # After 750 ms show the window
+ catch {after cancel $filedetails_after_ID}
+ set filedetails_after_ID [after 750 "
+ set ::FileList::filedetails_visible 1
+ $this file_details_win_move"]
+ }
+
+ ## Move window "File details"
+ # @return void
+ public method file_details_win_move args {
+ # Abort if the window isn't visible
+ if {!$filedetails_visible} {return}
+
+ # Show the window
+ catch {
+ place ${::FILEDETAILSWIN} -anchor nw \
+ -x [expr {[winfo pointerx .] - [winfo rootx .] + 20}] \
+ -y [expr {[winfo pointery .] - [winfo rooty .] + 20}]
+ update
+ raise ${::FILEDETAILSWIN}
+ }
+ }
+
+ ## Hide window "File details"
+ # @return void
+ public method file_details_win_hide args {
+ set filedetails_visible 0 ;# Bool: Is file details window visible
+
+ # Hide window and cancel timeout
+ catch {after cancel $filedetails_after_ID}
+ catch {place forget ${::FILEDETAILSWIN}}
+ }
+
+ ## Define popup menus
+ # @return void
+ public method filelist_makePopupMenu {} {
+ if {[winfo exists $opened_files_menu]} {
+ destroy $opened_files_menu
+ }
+ if {[winfo exists $project_files_menu]} {
+ destroy $project_files_menu
+ }
+ if {[winfo exists $filetabs_pu_menu]} {
+ destroy $filetabs_pu_menu
+ }
+
+ menuFactory $PROJECTFILESMENU $project_files_menu 0 "$this " 0 {}
+ menuFactory $OPENEDFILESMENU $opened_files_menu 0 "$this " 0 {}
+ menuFactory $FILETABSPUMENU $filetabs_pu_menu 0 "$this " 0 {}
+
+ foreach program {gvim emacs kwrite gedit} \
+ program_name {gvim emacs kwrite gedit} \
+ {
+ if {!$::PROGRAM_AVALIABLE($program)} {
+ foreach menu [list $project_files_menu $opened_files_menu $filetabs_pu_menu] {
+ ${menu}.open_with entryconfigure [::mc $program_name] -state disabled
+ }
+ }
+ }
+ if {${::Editor::editor_to_use}} {
+ $opened_files_menu entryconfigure [::mc "Save"] -state disabled
+ $opened_files_menu entryconfigure [::mc "Save as"] -state disabled
+ $opened_files_menu entryconfigure [::mc "Save all"] -state disabled
+
+ $filetabs_pu_menu entryconfigure [::mc "Save"] -state disabled
+ $filetabs_pu_menu entryconfigure [::mc "Save as"] -state disabled
+ $filetabs_pu_menu entryconfigure [::mc "Save all"] -state disabled
+ }
+ }
+
+ ## Reload the current file
+ # @return Bool - result
+ public method filelist_reload_file {} {
+ if {$splitted && $selectedView} {
+ set editor_idx $actualEditor2
+ } {
+ set editor_idx $actualEditor
+ }
+ set editor [lindex $editors $editor_idx]
+
+ # Local variables
+ set fullFileName [$editor cget -fullFileName] ;# Full filename
+ set filename [$editor cget -filename] ;# Simple filename
+
+ if {
+ ![file exists $fullFileName] ||
+ [file isdirectory $fullFileName] ||
+ (!$::MICROSOFT_WINDOWS && ![file readable $fullFileName])
+ } {
+ tk_messageBox \
+ -title [mc "File not found"] \
+ -icon error \
+ -type ok \
+ -parent . \
+ -message [mc "The file selected for reload does not exist any more or it is not readable !"]
+ set fullFileName {}
+ }
+
+ if {$fullFileName != {}} {
+ # Prompt user is the file was modified
+ if {[$editor cget -modified] != 0} {
+ set response [tk_messageBox \
+ -title [mc "Are you sure ?"] \
+ -icon question \
+ -type yesno \
+ -parent . \
+ -message [mc "Reload of the file will change contents of the current editor. Are you sure you want that ?"] \
+ ]
+ if {$response != {yes}} {
+ Sbar [mc "Reload aborted"]
+ return 0
+ }
+ }
+
+ set enc [lindex $file_encoding $editor_idx]
+ set eol [lindex $file_eol $editor_idx]
+ set rom [lindex $file_ro_mode $editor_idx]
+ set sh [lindex $file_sh $editor_idx]
+
+ # Get number of the current line
+ set line [$editor get_current_line_number]
+ # Clear content of the current editor
+ if {[$editor cget -ro_mode]} {
+ [$editor cget -editor] configure -state normal
+ }
+ $editor clear_autocompletion_list
+ [$editor cget -editor] configure -autoseparators 0
+ [$editor cget -editor] delete 1.0 end
+ # Insert content of the file into the editor
+ set file [open $fullFileName r]
+ fconfigure $file -encoding $enc
+ set data {}
+ if {[regsub -all {[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F]} [read $file] {} data]} {
+ tk_messageBox -parent . \
+ -type ok -icon warning \
+ -title [mc "Binary File Opened - MCU 8015 IDE"] \
+ -message [mc "The file %s is binary, saving it will result corrupted file." $fullFileName]
+ }
+ [$editor cget -editor] insert end [regsub -all {\r\n?} $data "\n"]
+ if {[$editor cget -ro_mode]} {
+ [$editor cget -editor] configure -state disabled
+ }
+ close $file
+ $editor goto $line
+ [$editor cget -editor] edit separator
+ [$editor cget -editor] configure -autoseparators 1
+
+ # Set EOL and Encoding in ListBox of project files
+ foreach item [$listbox_project_files items] {
+ if {[$listbox_project_files itemcget $item -text] != $filename} {
+ continue
+ }
+ set data [$listbox_project_files itemcget $item -data]
+ if {[llength $data] > 5} {continue}
+ if {[lindex $data 0] != $fullFileName} {continue}
+ lset data 1 $eol
+ lset data 2 $enc
+ lset data 3 $rom
+ $listbox_project_files itemconfigure $item -data $data
+ }
+ }
+
+ # Reset status modified
+ [$editor cget -editor] edit modified 0
+ $editor recalc_status_modified 0
+ # Restore syntax highlight
+ rightPanel_clear_all_bookmarks
+ rightPanel_clear_all_breakpoints
+ rightPanel_clear_symbol_list
+ $editor parseAll
+
+ # Successful
+ return 1
+ }
+
+ ## Highlight all loaded source codes, import breakpoints and bookmarks etc.
+ # This function finalizes project initialization
+ # @return void
+ public method filelist_global_highlight {} {
+ # Class variables
+ set filelist [lreplace $filelist 0 1] ;# List of files to open (special format)
+
+ # Skip empty/invalid filelist
+ if {[lindex $filelist $actualEditor] == {}} {
+ rightPanel_enable
+ return
+ }
+
+ # Local variables
+ set ac $actualEditor ;# Number of actual editor
+ # Number of current line in the current editor
+ set ac_line [lindex $filelist [list $ac_index_in_fl 6]]
+
+ # Take care of the current editor
+ rightPanel_switch_editor_vars $ac
+ $this todo_switch_editor_vars $ac
+ [lindex $editors $ac] import_line_markers_data \
+ [lindex $filelist [list $ac_index_in_fl 9]] \
+ [lindex $filelist [list $ac_index_in_fl 10]]
+ [lindex $editors $ac] goto $ac_line
+
+ # Import bookmarks and breakpoints into all editors except the current one
+ set idx -1
+ set lines {}
+ foreach record $filelist {
+ # Skip closed files
+ if {[lindex $record 1] != {yes}} {continue}
+
+ # Detrminate file index
+ incr idx
+ set i [lindex $file_indexes $idx]
+ if {$i == {}} {
+ continue
+ }
+
+ # Skip current editor
+ if {$i == $ac} {
+ incr i
+ lappend lines $ac_line
+ continue
+ }
+ # Local variables
+ set editor [lindex $editors $i] ;# Reference to target editor object
+ set line [lindex $record 6] ;# Current line
+
+ # Adjust right panel
+ set actualEditor $i
+ rightPanel_switch_editor_vars $i
+ $this todo_switch_editor_vars $i
+ # Import bookmarks and breakpoints into editor
+ $editor import_line_markers_data \
+ [lindex $record 9] \
+ [lindex $record 10]
+ $editor goto $line
+ lappend lines $line
+ }
+
+ # Finalize
+ set filelist {}
+ set actualEditor $ac
+
+ # Adjust Right panel
+ rightPanel_enable
+ set i 0
+ foreach line $lines {
+ set editor [lindex $editors $i]
+ rightPanel_switch_editor_vars $i
+ $this todo_switch_editor_vars $i
+ $editor rightPanel_adjust $line
+ incr i
+ }
+ rightPanel_switch_editor $ac
+ $this todo_switch_editor $ac
+ if {${::ASMsyntaxHighlight::validation_L1}} {
+ [lindex $editors $actualEditor] parse_current_line
+ } {
+ [lindex $editors $actualEditor] adjust_instruction_details
+ }
+
+ set file_indexes {}
+ }
+
+ ## Switch from Normal mode to Simulator mode
+ # @return void
+ public method freeze {} {
+ # Set mode flag
+ set frozen 1
+ set simulator_editor_obj {}
+ set simulator_editor -1
+ # Freeze editor
+ if {$splitted && $selectedView} {
+ set editor_to_freeze $actualEditor2
+ } {
+ set editor_to_freeze $actualEditor
+ }
+ set idx 0
+ foreach editor $editors {
+ if {$idx == $editor_to_freeze} {
+ $editor freeze
+ set editor_to_freeze_obj $editor
+ } {
+ $editor disable
+ }
+ incr idx
+ }
+ FileList_project_disEna_buttons
+ # Disable some popupmenu items
+ foreach entry $freezable_menu_items {
+ $opened_files_menu entryconfigure [::mc $entry] -state disabled
+ }
+ $project_files_menu entryconfigure [::mc "Close file"] -state disabled
+ }
+
+ ## This method should be called immediately after simulator startup
+ #+ in order to inform editors about the change
+ # @return void
+ public method now_frozen {} {
+ $editor_to_freeze_obj now_frozen
+ }
+
+ ## Switch from Simulator mode to Normal mode
+ # @return void
+ public method thaw {} {
+ # Set mode flag
+ set frozen 0
+ # Thaw editors
+ foreach editor $editors {
+ $editor thaw
+ }
+ # Enable switching files
+ listBox_disEna_buttons \
+ [$listbox_opened_files selection get] \
+ [lindex $editors $actualEditor]
+ if {$splitted} {
+ listBox_disEna_buttons \
+ [$listbox_opened_files selection get] \
+ [lindex $editors $actualEditor]
+ }
+ # Enable some poupmenu items
+ foreach entry $freezable_menu_items {
+ $opened_files_menu entryconfigure [::mc $entry] -state normal
+ }
+ $project_files_menu entryconfigure [::mc "Close file"] -state normal
+
+ if {$simulator_editor_obj != {}} {
+ $listbox_opened_files itemconfigure [lindex \
+ $file_descriptors [lsearch -ascii -exact \
+ $editors $simulator_editor_obj \
+ ] \
+ ] -fg {#000000}
+ }
+ set simulator_editor_obj {}
+ }
+
+ ## Set variable containing ID of active page
+ # @parm String pageName - active page
+ # @return void
+ public method Left_panel_set_active_page {pageName} {
+ set active_page $pageName
+ }
+
+ ## Get mode flag
+ # @return Bool - current mode (1 == Simulation mode; 0 == Normal mode)
+ public method is_frozen {} {return $frozen}
+
+ ## Get current panel width
+ # @return Int - the width
+ public method getLeftPanelSize {} {
+ if {$PanelVisible} {
+ return $PanelSize
+ } {
+ return $last_sash
+ }
+ }
+
+ ## Set panel width acording to current sash position
+ # @return void
+ public method left_panel_set_size {} {
+ set PanelSize [lindex [$parent sash coord 0] 0]
+ }
+
+ ## Get ID of active page
+ # @return String - the active page
+ public method getLeftPanelActivePage {} {return $active_page}
+
+ ## Get value of panel visibility flag
+ # @return Bool - the flag (1 == Visible, 2 == Hidden)
+ public method isLeftPanelVisible {} {return $PanelVisible}
+
+ ## Show/Hide the left panel
+ # @return Bool - 1 == now displayed; 0 == now hidden
+ public method filelist_show_hide {} {
+ # Hide the panel
+ if {$PanelVisible} {
+ $parent paneconfigure $leftPanel -minsize 0
+
+ pack forget $notebook
+ # Show button bar
+ pack $button_bar -side top -anchor nw
+ # Move the paned window sash and remember current position
+ set last_sash [lindex [$parent sash coord 0] 0]
+ update idle
+ $parent sash place 0 25 2
+ # Hide the sash
+ bind $parent <Button> {break}
+ $parent configure -sashwidth 0
+ # done ...
+ set PanelVisible 0
+ return 0
+
+ # Show the panel
+ } {
+ $parent paneconfigure $leftPanel -minsize 155
+
+ $notebook raise $active_page
+ # Hide button bar
+ pack forget $button_bar
+ # Show the panel
+ pack $notebook -expand 1 -fill both
+ # Restore the paned window sash position to the previous state
+ update idle
+ $parent sash place 0 $last_sash 0
+ # Show the sash
+ bind $parent <Button> {}
+ $parent configure -sashwidth 2
+ # done ...
+ set PanelVisible 1
+ return 1
+ }
+ }
+
+ ## Change panel active page
+ # @parm String page - ID of the page to show
+ # @return void
+ public method filelist_show_up {page} {
+ if {!$PanelVisible} filelist_show_hide
+ $notebook raise $page
+ }
+
+ ## Move up currently selected item -- Opened files
+ # @return void
+ public method filelist_move_up {} {
+ # Local variables
+ set item [$listbox_opened_files selection get] ;# Item ID
+ set index [$listbox_opened_files index $item] ;# Item index
+ set target [expr {$index - 1}] ;# Target index
+
+ # 1st item cannot be moved up
+ if {$index == 0} {return}
+
+ # Move item in listbox
+ $listbox_opened_files move $item $target
+ # Move item in list of bookmarks and icon border
+ if {[lindex $opened_files_bookmarks $index] != [lindex $opened_files_bookmarks $target]} {
+ # Determinate bookmark flag for source and target index
+ set trg_bm [lindex $opened_files_bookmarks $target]
+ set idx_bm [lindex $opened_files_bookmarks $index]
+ # Move item in list of bookmarks
+ lset opened_files_bookmarks $target [lindex $opened_files_bookmarks $index]
+ lset opened_files_bookmarks $index $trg_bm
+ # Move item in icon border
+ incr target
+ incr index
+ $listbox_opened_files_bm delete $index.0 [list $index.0 lineend]
+ $listbox_opened_files_bm delete $target.0 [list $target.0 lineend]
+ if {$trg_bm} {
+ $listbox_opened_files_bm image create $index.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ if {$idx_bm} {
+ $listbox_opened_files_bm image create $target.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ }
+
+ # Reevaluate button states on icon bar
+ listBox_disEna_buttons $item [lindex $editors [lsearch $file_descriptors $item]]
+ }
+
+ ## Move down currently selected item -- Opened files
+ # @return void
+ public method filelist_move_down {} {
+ # Local variables
+ set item [$listbox_opened_files selection get] ;# Item ID
+ set index [$listbox_opened_files index $item] ;# Item index
+ set target [expr {$index + 1}] ;# Target index
+
+ # Last item cannot be moved up
+ if {[llength [$listbox_opened_files items]] == $index} {return}
+
+ # Move item in listbox
+ $listbox_opened_files move $item $target
+ # Move item in list of bookmarks and icon border
+ if {[lindex $opened_files_bookmarks $index] != [lindex $opened_files_bookmarks $target]} {
+ # Determinate bookmark flag for source and target index
+ set trg_bm [lindex $opened_files_bookmarks $target]
+ set idx_bm [lindex $opened_files_bookmarks $index]
+ # Move item in list of bookmarks
+ lset opened_files_bookmarks $target [lindex $opened_files_bookmarks $index]
+ lset opened_files_bookmarks $index $trg_bm
+ # Move item in icon border
+ incr target
+ incr index
+ $listbox_opened_files_bm delete $index.0 [list $index.0 lineend]
+ $listbox_opened_files_bm delete $target.0 [list $target.0 lineend]
+ if {$trg_bm} {
+ $listbox_opened_files_bm image create $index.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ if {$idx_bm} {
+ $listbox_opened_files_bm image create $target.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ }
+
+ # Reevaluate button states on icon bar
+ listBox_disEna_buttons $item [lindex $editors [lsearch $file_descriptors $item]]
+ }
+
+ ## Move to top currently selected item -- Opened files
+ # @return void
+ public method filelist_move_top {} {
+ # Local variables
+ set item [$listbox_opened_files selection get] ;# Item ID
+ set index [$listbox_opened_files index $item] ;# Item index
+
+ # Move item
+ $listbox_opened_files move $item 0
+ # Move item in list of bookmarks
+ set bm [lindex $opened_files_bookmarks $index]
+ set opened_files_bookmarks [lreplace $opened_files_bookmarks $index $index]
+ set opened_files_bookmarks [linsert $opened_files_bookmarks 0 $bm]
+ # Move item in icon border
+ incr index
+ $listbox_opened_files_bm delete $index.0 $index.0+1l
+ $listbox_opened_files_bm insert 1.0 "\n"
+ if {$bm} {
+ $listbox_opened_files_bm image create 1.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+
+ # Reevaluate button states on icon bar
+ listBox_disEna_buttons $item [lindex $editors [lsearch $file_descriptors $item]]
+ }
+
+ ## Move to bottom currently selected item -- Opened files
+ # @return void
+ public method filelist_move_bottom {} {
+ # Local variables
+ set item [$listbox_opened_files selection get] ;# Item ID
+ set index [$listbox_opened_files index $item] ;# Item index
+
+ # Move item in listbox
+ $listbox_opened_files move $item end
+ # Move item in list of bookmarks
+ set bm [lindex $opened_files_bookmarks $index]
+ set opened_files_bookmarks [lreplace $opened_files_bookmarks $index $index]
+ lappend opened_files_bookmarks $bm
+ # Move item in icon border
+ incr index
+ set end [llength $opened_files_bookmarks]
+ $listbox_opened_files_bm delete $index.0 $index.0+1l
+ $listbox_opened_files_bm insert $end.0 "\n"
+ if {$bm} {
+ $listbox_opened_files_bm image create $end.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+
+ # Reevaluate button states on icon bar
+ listBox_disEna_buttons $item [lindex $editors [lsearch $file_descriptors $item]]
+ }
+
+ ## Show up editor asociated with the currently selected item in the file list (opened files)
+ # @return void
+ public method switchfile {} {
+ # Ensure that autocompletion window is closed
+ ::Editor::close_completion_popup_window_NOW
+
+ # Determinate ID of the selected item
+ set item [$listbox_opened_files selection get]
+ set editor_idx [lsearch $file_descriptors $item]
+
+ # Adjust filetabs notebook
+ set page [lindex [$filetabs_nb pages] $editor_idx]
+ $filetabs_nb raise $page
+ $filetabs_nb see $page
+
+ # Conditionaly switch selected view
+ if {$splitted && $selectedView} {
+ if {$editor_idx == $actualEditor} {
+ set selectedView 0
+ }
+ } {
+ if {$editor_idx == $actualEditor2} {
+ set selectedView 1
+ }
+ }
+
+ # Show up the coresponding editor
+ rightPanel_switch_editor_vars $editor_idx
+ $this todo_switch_editor_vars $editor_idx
+ # Right/Bottom view selected
+ if {$splitted && $selectedView} {
+ if {$editor_idx != $actualEditor2} {
+ if {!$do_not_forget_editor && $actualEditor2 >= 0} {
+ set editor [lindex $editors $actualEditor2]
+ if {$editor != {}} {
+ pack forget [$editor cget -ed_sc_frame]
+ }
+ }
+ set actualEditor2 $editor_idx
+ pack [[lindex $editors $actualEditor2] cget -ed_sc_frame] \
+ -in $pagesManager2 -fill both -expand 1
+ }
+ set editor [lindex $editors $actualEditor2]
+
+ # Left/Top view selected
+ } {
+ if {$editor_idx != $actualEditor} {
+ if {!$do_not_forget_editor && $actualEditor >= 0} {
+ set editor [lindex $editors $actualEditor]
+ if {$editor != {}} {
+ pack forget [$editor cget -ed_sc_frame]
+ }
+ }
+ set actualEditor $editor_idx
+ pack [[lindex $editors $actualEditor] cget -ed_sc_frame] \
+ -in $pagesManager -fill both -expand 1
+ }
+ set editor [lindex $editors $actualEditor]
+ }
+
+ set do_not_forget_editor 0
+ $opened_search_entry delete 0 end
+ update idle
+ editor_procedure {} Configure {}
+ editor_procedure {} scroll {scroll +0 lines}
+ editor_procedure {} highlight_visible_area {}
+ update
+ rightPanel_switch_page $editor_idx
+ $this todo_switch_editor $editor_idx
+ # Set encoding and eol
+ set ::editor_encoding [lindex $file_encoding $editor_idx]
+ set ::editor_EOL [lindex $file_eol $editor_idx]
+ set ::editor_RO_MODE [lindex $file_ro_mode $editor_idx]
+ set ::editor_SH [lindex $file_sh $editor_idx]
+ # Adjust command line status
+ if {$editor_command_line_on} {
+ $editor cmd_line_force_on
+ } {
+ $editor cmd_line_force_off
+ }
+ # Adjust tab "Instruction details" on the right panel
+ if {${::ASMsyntaxHighlight::validation_L1}} {
+ $editor parse_current_line
+ } {
+ $editor adjust_instruction_details
+ }
+ # move arrow image
+ catch {$listbox_opened_files itemconfigure $lastItem -image {}}
+ $listbox_opened_files itemconfigure $item -image ::ICONS::16::2_rightarrow
+ set lastItem $item
+ # Reevaluate button states on left panel icon bar, program title bar and main menu and main toolbar
+ listBox_disEna_buttons $item $editor
+ ::X::adjust_title
+ ::X::adjust_mainmenu_and_toolbar_to_editor \
+ ${::editor_RO_MODE} [expr {[$editor get_language] == 1}]
+ # Focus on the editor
+ focus -force [$editor cget -editor]
+ }
+
+ ## Switch to the next editor
+ # @return void
+ public method next_editor {} {
+ if {$frozen} {return}
+ set index [$listbox_opened_files index [$listbox_opened_files selection get]]
+
+ if {$index >= ([llength $file_descriptors] - 1)} {return}
+ $listbox_opened_files selection set [$listbox_opened_files item [expr {$index + 1}]]
+ switchfile
+ }
+
+ ## Switch to the previous editor
+ # @return void
+ public method prev_editor {} {
+ if {$frozen} {return}
+ set index [$listbox_opened_files index [$listbox_opened_files selection get]]
+ if {$index} {
+ $listbox_opened_files selection set \
+ [$listbox_opened_files item [expr {$index - 1}]]
+ switchfile
+ }
+ }
+
+ ## Switch the last file in list of opened files
+ # @return void
+ public method switch_to_last {} {
+ if {$splitted} {
+ set item [expr {([llength $file_descriptors] - 1)}]
+ if {$item == $actualEditor || $item == $actualEditor2} {
+ set item {end-1}
+ }
+ } {
+ set item {end}
+ }
+ $listbox_opened_files selection set [lindex $file_descriptors $item]
+ switchfile
+ }
+
+ ## Enable/Disable buttons in opened files icon bar and popup menu
+ # @parm String item - ID of the current item
+ # @parm Object editor - reference to current editor object
+ # @return void
+ private method listBox_disEna_buttons {item editor} {
+
+ # Is the file part of the project ?
+ if {[getItemNameFromProjectList [$editor cget -fullFileName]] != {}} {
+ set state disabled
+ } {
+ set state normal
+ }
+ $opened_files_menu entryconfigure [::mc "Append to project"] -state $state
+ $filetabs_pu_menu entryconfigure [::mc "Append to project"] -state $state
+
+ # Items: "Move up" and "Move to top"
+ set item_idx [$listbox_opened_files index $item]
+ if {$item_idx == 0} {
+ set state disabled
+ } {
+ set state normal
+ }
+ $opened_files_menu entryconfigure [::mc "Move up"] -state $state
+ $opened_files_menu entryconfigure [::mc "Move to top"] -state $state
+ $prev_editor_button configure -state $state
+ ${opened_files_buttonBox}up configure -state $state
+ ${opened_files_buttonBox}top configure -state $state
+
+ # Items: "Move down" and "Move to bottom"
+ if {($item_idx + 1) >= [llength [$listbox_opened_files items]]} {
+ set state disabled
+ } {
+ set state normal
+ }
+ $opened_files_menu entryconfigure [::mc "Move down"] -state $state
+ $opened_files_menu entryconfigure [::mc "Move to bottom"] -state $state
+ $next_editor_button configure -state $state
+ ${opened_files_buttonBox}down configure -state $state
+ ${opened_files_buttonBox}bottom configure -state $state
+ }
+
+ ## Invoke popup menu for "Opened files"
+ # @parm Int x - absolute X coordinate
+ # @parm Int y - absolute Y coordinate
+ # @return void
+ public method fileList_opened_filelist_popup {x y} {
+ if {$item_menu_invoked} {
+ set item_menu_invoked 0
+ return
+ }
+
+ if {!${::Editor::editor_to_use}} {
+ $opened_files_menu entryconfigure [::mc "Save as"] -state disabled
+ $opened_files_menu entryconfigure [::mc "Save"] -state disabled
+
+ $filetabs_pu_menu entryconfigure [::mc "Save"] -state disabled
+ $filetabs_pu_menu entryconfigure [::mc "Save as"] -state disabled
+ }
+ foreach entry {
+ {Close} {Bookmark} {Move up}
+ {Move down} {Move to top} {Move to bottom}
+ {Open with} {Append to project}
+ } {
+ $opened_files_menu entryconfigure [::mc $entry] -state disabled
+ }
+
+ tk_popup $opened_files_menu $x $y
+ }
+
+ ## Invoke popup menu for "Opened files" -- for particular item
+ # note: This method should be associated with the 'bindtext' command
+ # @parm Int x - absolute X coordinate
+ # @parm Int y - absolute Y coordinate
+ # @parm String item - ID of selected item
+ # @return void
+ public method fileList_opened_filelist_item_popup {x y item} {
+ set item_menu_invoked 1
+
+ if {!${::Editor::editor_to_use}} {
+ $opened_files_menu entryconfigure [::mc "Save as"] -state normal
+ $opened_files_menu entryconfigure [::mc "Save"] -state normal
+
+ $filetabs_pu_menu entryconfigure [::mc "Save"] -state normal
+ $filetabs_pu_menu entryconfigure [::mc "Save as"] -state normal
+ }
+ foreach entry {
+ {Close} {Bookmark} {Move up}
+ {Move down} {Move to top} {Move to bottom}
+ {Open with}
+ } {
+ $opened_files_menu entryconfigure [::mc $entry] -state normal
+ }
+ # It is not so easy to open the file with an external editor on Microsoft Windows as
+ # it is on a POSIX system, that's why this feature is disabled here
+ if {$::MICROSOFT_WINDOWS} {
+ $opened_files_menu entryconfigure [::mc {Open with}] -state disabled
+ $filetabs_pu_menu entryconfigure [::mc {Open with}] -state disabled
+ }
+
+ $listbox_opened_files selection set $item
+ switchfile
+
+ # Enable/Disable item "Append to project"
+ set fullFileName [[lindex $editors [lsearch $file_descriptors $item]] cget -fullFileName]
+ if {$fullFileName == {} || [getItemNameFromProjectList $fullFileName] != {}} {
+ set state disabled
+ } {
+ set state normal
+ }
+ $opened_files_menu entryconfigure [::mc "Append to project"] -state $state
+
+ tk_popup $opened_files_menu $x $y
+ }
+
+ # ---------------------------------------------------------------------
+ # AUXILIARY DATA MANAGEMENT PROCEDURES
+ # ---------------------------------------------------------------------
+
+ ## Open all files in the given list
+ # @parm List filelist - files to open (spec. format)
+ # @return void
+ public method open_files {filelist} {
+ # NS variables
+ set file_indexes {} ;# List of line indexes (auxiliary variable for opening multiple files)
+ set ac_index_in_fl -1 ;# Index of actual editor filelist
+
+ # Local variables
+ set num_of_opened_files 0 ;# Number of opened files
+ set rfi 0 ;# Record field index
+ set open_files_progress 0 ;# Value for progress dialog (progress)
+ set open_files_abort 0 ;# Abort variable
+ set keep_order 1 ;# Bool: Keep order of files
+ set rec_i -1 ;# Record index (in $filelist)
+ set file_indexes_fb {} ;# Fallback file indexes
+ set unopened_files {} ;# List of files which were unable to open
+ set changed_files {} ;# List of files changed since last project save
+ set project_path [$this cget -projectPath] ;# Path to the project directory
+ set filelist_length [llength $filelist] ;# Length of the given filelist
+ set ac [lindex $filelist {1 0}] ;# Index of actual editor
+
+ ## Lists of files to open
+ # Ordered
+ set files_to_open__path [string repeat {{} } $filelist_length] ;# Path
+ set files_to_open__enc [string repeat {{} } $filelist_length] ;# Encoding
+ set files_to_open__eol [string repeat {{} } $filelist_length] ;# EOL
+ set files_to_open__bm [string repeat {{} } $filelist_length] ;# Bookmark flag
+ set files_to_open__ro [string repeat {{} } $filelist_length] ;# Read only flag
+ set files_to_open__sh [string repeat {{} } $filelist_length] ;# Syntax highlight
+ set files_to_open__nt [string repeat {{} } $filelist_length] ;# Notes for file
+ # Unordered
+ set files_to_open_path {} ;# Path
+ set files_to_open_enc {} ;# Encoding
+ set files_to_open_eol {} ;# EOL
+ set files_to_open_bm {} ;# Bookmark flag
+ set files_to_open_ro {} ;# Read only flag
+ set files_to_open_sh {} ;# Syntax highlight
+ set files_to_open_nt {} ;# Notes for file
+
+ # Abort if the given filelist is empty
+ if {!$filelist_length} {return}
+
+ # Iterate over records in $filelist
+ foreach record $filelist {
+ incr rec_i ;# Record index
+
+ # First 2 records have no meaning here
+ if {$rec_i < 2 || $record == {}} {continue}
+
+ # Parse record
+ set rfi 0
+ foreach var {
+ file_name active o_bookmark p_bookmark
+ file_index read_only file_line file_md5
+ file_path file_BMs file_BPs eol
+ enc sh notes
+ } {
+ set $var [lindex $record $rfi]
+ incr rfi
+ }
+
+ # Adjust file path
+ if {[string index $file_path 0] != {/}} {
+ set file_path "$project_path/$file_path"
+ }
+ # Determinate full file name
+ set full_file_name "$file_path$file_name"
+
+ # Check for file usebility
+ if {
+ ![file exists $full_file_name] ||
+ [file isdirectory $full_file_name] ||
+ (!$::MICROSOFT_WINDOWS && ![file readable $full_file_name])
+ } then {
+ lappend file_indexes_fb {}
+ lappend unopened_files $full_file_name
+ continue
+ }
+
+ # Compare file MD5
+ if {[catch {
+ if {[md5::md5 -hex -file $file_path$file_name] != $file_md5} {
+ lappend changed_files $file_path$file_name
+ }
+ }]} then {
+ tk_messageBox \
+ -icon warning \
+ -type ok \
+ -title [mc "Unknown error"] \
+ -message [mc "Raised error during md5 checking file %s. Maybe md5 extension is not correctly loaded." $file_name]
+ }
+
+ # Chech for valid EOL and Encoding
+ if {$eol != {lf} && $eol != {cr} && $eol != {crlf}} {
+ set eol $default_eol
+ puts stderr "Invalid EOL -- using default ($eol)"
+ }
+ if {$enc != {def} && [lsearch [encoding names] $enc] == -1} {
+ set enc $default_encoding
+ puts stderr "Invalid encoding -- using default ($default_encoding)"
+ }
+ if {![string is boolean -strict $read_only]} {
+ set read_only 0
+ puts stderr "Read only flag -- using default (0)"
+ }
+
+ # Insert bookmark to icon border for project files
+ if {[llength $project_files_bookmarks]} {
+ $listbox_project_files_bm insert end "\n"
+ }
+ if {$p_bookmark == 1} {
+ lappend project_files_bookmarks 1
+ $listbox_project_files_bm image create [list {end-1l} linestart] \
+ -image ::ICONS::16::bookmark -align center
+ } {
+ lappend project_files_bookmarks 0
+ }
+ $listbox_project_files_bm tag add center 0.0 end
+
+ # Register the file in the project
+ if {$active == {no}} {
+ if {[llength $record] < 5} {continue}
+ $listbox_project_files insert end #auto \
+ -font $closed_file_font -fill {#888888} \
+ -text $file_name \
+ -data [list $file_name $active \
+ $read_only $file_line \
+ $file_md5 $file_path \
+ $file_BMs $file_BPs \
+ $eol $enc \
+ $sh $notes \
+ ]
+ continue
+ } {
+ $listbox_project_files insert end #auto \
+ -font $opened_file_font -fill {#000000} \
+ -text $file_name -data [list $file_path$file_name $eol $enc $read_only]
+ if {![string is digit -strict $file_index]} {
+ set keep_order 0
+ }
+ }
+
+ # Adjust lists of file indexes
+ lappend file_indexes $file_index
+ lappend file_indexes_fb $num_of_opened_files
+
+ # Adjust list of files to open
+ lset files_to_open__path $file_index $file_path$file_name
+ lset files_to_open__enc $file_index $enc
+ lset files_to_open__eol $file_index $eol
+ lset files_to_open__bm $file_index $o_bookmark
+ lset files_to_open__ro $file_index $read_only
+ lset files_to_open__sh $file_index $sh
+ lset files_to_open__nt $file_index $notes
+ lappend files_to_open_path $file_path$file_name
+ lappend files_to_open_enc $enc
+ lappend files_to_open_eol $eol
+ lappend files_to_open_bm $o_bookmark
+ lappend files_to_open_ro $read_only
+ lappend files_to_open_sh $sh
+ lappend files_to_open_nt $notes
+
+ # Determinate index in file list for actual editor
+ if {$file_index == $ac} {
+ set ac_index_in_fl $rec_i
+ incr ac_index_in_fl -2
+ }
+
+ # Increment number of opened files
+ incr num_of_opened_files
+ }
+
+ # Invoke progress dialog
+ set max [llength $file_indexes_fb]
+ if {!$max} {set max 1}
+ create_progress_bar .prgDl \
+ . \
+ ::FileList::open_files_cur_file \
+ {} \
+ ::FileList::open_files_progress \
+ $max \
+ [mc "Opening project files"] \
+ ::ICONS::16::fileopen \
+ [mc "Abort"] \
+ {set ::FileList::open_files_abort 1}
+
+ # Adjust lists of files to open
+ if {!$keep_order} {
+ set files_to_open__path $files_to_open_path
+ set files_to_open__enc $files_to_open_enc
+ set files_to_open__eol $files_to_open_eol
+ set files_to_open__bm $files_to_open_bm
+ set files_to_open__ro $files_to_open_ro
+ set files_to_open__sh $files_to_open_sh
+ set files_to_open__nt $files_to_open_nt
+ set file_indexes $file_indexes_fb
+ }
+
+ # Check for validity of list of file indexes
+ if {$unopened_files != {}} {
+ set file_indexes $file_indexes_fb
+ } {
+ for {set i 0} {$i < $num_of_opened_files} {incr i} {
+ if {[lsearch -ascii -exact $file_indexes $i] == -1} {
+ set file_indexes $file_indexes_fb
+ break
+ }
+ }
+ }
+
+ # Open files
+ set i 0
+ set pos 0
+ foreach path $files_to_open__path \
+ enc $files_to_open__enc \
+ eol $files_to_open__eol \
+ bm $files_to_open__bm \
+ ro $files_to_open__ro \
+ sh $files_to_open__sh \
+ notes $files_to_open__nt \
+ {
+ incr pos
+ if {$path == {}} {
+ continue
+ }
+
+ # Abort process on user request
+ if {$open_files_abort} {
+ $listbox_project_files delete [$listbox_project_files items $i end]
+ if {$i} {
+ incr i -1
+ set file_indexes [lrange $file_indexes 0 $i]
+ set file_indexes_fb [lrange $file_indexes_fb 0 $i]
+ } {
+ set file_indexes {}
+ set file_indexes_fb {}
+ }
+
+ set filelist [lrange $filelist 0 $pos]
+ break
+ }
+
+ # Adjust progress dialog
+ incr open_files_progress
+ set open_files_cur_file [file tail $path]
+ update
+
+ # Open file
+ if {[openfile $path 0 . $enc $eol $ro 0 $sh] != {}} {
+ if {$bm == 1} {
+ opened_files_bookmark $i
+ }
+ $this set_file_notes_data $notes
+ }
+ incr i
+ }
+
+ # Invoke dialog "File(s) not found"
+ if {$unopened_files != {}} {
+ # Create toplevel window
+ set win [toplevel .file_not_found$obj_idx -class {Error dialog} -bg {#EEEEEE}]
+
+ # Create window header
+ pack [frame $win.frame1] -side top -fill x -anchor nw
+ pack [label $win.frame1.image \
+ -image ::ICONS::32::messagebox_critical \
+ ] -anchor nw -expand 0 -side left -padx 10 -pady 5
+ pack [label $win.frame1.header \
+ -text [mc "The following files could not be located:"] \
+ ] -side left -fill x
+
+ # Create text widget with scrollbar
+ pack [frame $win.frame2] -side top -expand 1 -fill both -pady 10 -padx 5
+ pack [text $win.frame2.text -height 5 -width 40 \
+ -yscrollcommand "$win.frame2.scrollbar set"] -side left -fill both -expand 1
+ pack [ttk::scrollbar $win.frame2.scrollbar \
+ -orient vertical \
+ -command "$win.frame2.text yview" \
+ ] -side right -fill y
+
+ # Insert list of unopened files into the text widgets
+ $win.frame2.text insert end [join $unopened_files "\n"]
+ $win.frame2.text configure -state disabled
+
+ bind $win.frame2.text <1> "focus $win.frame2.text"
+
+ # Create button "Ok"
+ pack [ttk::button $win.but_ok \
+ -text [mc "Ok"] \
+ -compound left \
+ -image ::ICONS::16::ok \
+ -command "
+ grab release $win
+ destroy $win
+ " \
+ ] -side bottom
+
+ # Dialog event bindings
+ bind $win <Return> "
+ grab release $win
+ destroy $win
+ "
+ bind $win <KP_Enter> "
+ grab release $win
+ destroy $win
+ "
+ bind $win <Escape> "
+ grab release $win
+ destroy $win
+ "
+
+ # Set window attributes
+ wm iconphoto $win ::ICONS::16::status_unknown
+ wm title $win [mc "File(s) not found"]
+ wm geometry $win 500x200
+ wm protocol $win WM_DELETE_WINDOW "
+ grab release $win
+ destroy $win
+ "
+ update
+ catch {grab $win}
+ raise $win
+ }
+
+ # Invoke dialog "File(s) changed"
+ if {$changed_files != {}} {
+ # Create dialog toplevel window
+ set win [toplevel .changed_files$obj_idx -class {File changed} -bg {#EEEEEE}]
+
+ # Create dialog header
+ pack [frame $win.frame1] -side top -fill x -anchor nw
+ pack [label $win.frame1.image -image ::ICONS::32::messagebox_info] \
+ -anchor nw -expand 0 -side left -padx 10 -pady 5
+ pack [label $win.frame1.header \
+ -text [mc "The following files were modified since last save:"] \
+ ] -side left -fill x
+
+ # Create text widget and scrollbar
+ pack [frame $win.frame2] -side top -expand 1 -fill both -pady 10 -padx 5
+ pack [text $win.frame2.text -height 5 -width 50 \
+ -yscrollcommand "$win.frame2.scrollbar set"] -side left -fill both -expand 1
+ pack [ttk::scrollbar $win.frame2.scrollbar \
+ -orient vertical \
+ -command "$win.frame2.text yview" \
+ ] -side right -fill y
+
+ # Insert info about changed files
+ foreach file $changed_files {
+ if {[file exists $file_path$file_name]} {
+ set time [clock format [file mtime $file_path$file_name] -format {%T %D}]
+ } {
+ set time " -----\t"
+ }
+ $win.frame2.text insert end "$time\t$file\n"
+ }
+ $win.frame2.text configure -state disabled
+
+ bind $win.frame2.text <1> "focus $win.frame2.text"
+
+ # Create button "Ok"
+ pack [ttk::button $win.but_ok \
+ -text [mc "Ok"] \
+ -compound left \
+ -image ::ICONS::16::ok \
+ -command "
+ grab release $win
+ destroy $win
+ " \
+ ] -side bottom -pady 5
+
+ # Set dialog event bindings
+ bind $win <Return> "
+ grab release $win
+ destroy $win
+ "
+ bind $win <KP_Enter> "
+ grab release $win
+ destroy $win
+ "
+ bind $win <Escape> "
+ grab release $win
+ destroy $win
+ "
+
+ # Set window attributes
+ wm iconphoto $win ::ICONS::16::info
+ wm title $win [mc "File(s) changed"]
+ wm geometry $win 500x200
+ wm protocol $win WM_DELETE_WINDOW "
+ grab release $win
+ destroy $win
+ "
+ update
+ catch {grab $win}
+ raise $win
+ }
+ }
+
+ ## Open file at the given location and with some additional options
+ # Alogorithm:
+ # * check if the file exists, if it doesn't then invoke an error message
+ # * if the file exists then open it and read its content
+ # * if the specified file path is an empty string then consider that file as a new one
+ # * check if that file in not already opened and if it is then focus on it and return
+ # * register that file in the class's internal variables
+ # * create a new editor for that file and eventualy display content of the file
+ # * focus on that newly created editor
+ #
+ # @parm String file_path - full file name including path, {} means create a new one
+ # @parm Bool ask - ask user about adding the file to the project
+ # @parm String parent - path to the parent widget (eg. dialog which invoked this procedure)
+ # @parm String enc - Character encoding
+ # @parm String eol - End of Line character identifier (one of {lf crlf cr})
+ # @parm Bool read_only - Read only flag
+ # @parm Bool fast - Open the file as fast as possible (only for creating new files)
+ # sh
+ # @return String - descriptor of the opened file
+ public method openfile {file_path ask parent enc eol read_only fast sh} {
+ set newfile 0 ;# Bool: created new virtual file
+
+ # Open an existing file
+ if {$file_path != {}} {
+ # Report error if the file does not exist
+ if {
+ !${::Editor::editor_to_use} && (
+ ![file exists $file_path] ||
+ ![file isfile $file_path] ||
+ (!$::MICROSOFT_WINDOWS && ![file readable $file_path])
+ )
+ } {
+ tk_messageBox \
+ -type ok \
+ -title [mc "File not found - MCU 8051 IDE"] \
+ -message [mc "File %s not found !" $file_path] \
+ -icon error
+ set newfile 1
+ }
+
+ # determine the filename
+ regexp {[^\\\/]+$} $file_path file_name
+
+ # Create a new file (untitled)
+ } else {
+ if {![regexp {untitled\d*} $file_descriptors]} {
+ set untitled_num -1
+ }
+ if {$untitled_num == -1} {
+ set file_name "untitled"
+ } {
+ set file_name "untitled$untitled_num"
+ }
+ incr untitled_num
+ set newfile 1
+ }
+ if {$file_name == {.#special:tmp}} {
+ if {![regexp {untitled\d*} $file_descriptors]} {
+ set untitled_num -1
+ }
+ if {$untitled_num == -1} {
+ set file_name "untitled"
+ } {
+ set file_name "untitled$untitled_num"
+ }
+ incr untitled_num
+ set newfile 1
+ }
+
+ # Check if the file isn't already opened
+ if {!$newfile} {
+ set idx 0
+ foreach editor $editors {
+ if {[$editor cget -fullFileName] == $file_path} {
+ set item [lindex $file_descriptors $idx]
+ $listbox_opened_files selection set $item
+ switchfile
+ set lastItem $item
+ Sbar [mc "File: %s is alredy opened." $file_path]
+ return {}
+ }
+ incr idx
+ }
+ }
+
+ # Adjust arguments 'eol' and 'enc'
+ if {$eol == {def}} {
+ set eol $default_eol
+ }
+ if {$enc == {def}} {
+ set enc $default_encoding
+ }
+
+ # Determinate unique file descriptor
+ set file_descriptor [regsub -all {_} $file_name {__}]
+ set file_descriptor [regsub -all {\.} $file_descriptor {_}]
+ set file_descriptor [regsub -all -- {-} $file_descriptor {--}]
+ set file_descriptor [regsub -all -- {\s} $file_descriptor {-}]
+ # Handle similar file descriptors of different files
+ while 1 {
+ if {[lsearch $file_descriptors $file_descriptor] != -1} {
+ append file_descriptor {_}
+ } {
+ break
+ }
+ }
+
+ # Register the file descriptor
+ lappend file_descriptors $file_descriptor
+ # Insert filename into ListBox of opened files
+ $listbox_opened_files insert end $file_descriptor \
+ -text $file_name -data $file_path -font $icon_border_font
+ if {[llength $opened_files_bookmarks]} {
+ $listbox_opened_files_bm insert end "\n"
+ }
+ lappend opened_files_bookmarks 0
+
+ if {$ask} {
+ # test if the file isn't already included in the project
+ set item [getItemNameFromProjectList $file_path]
+ if {$item != {}} {
+ set ask 0
+ }
+
+ if {!$ask} {
+ $listbox_project_files itemconfigure $item \
+ -font $opened_file_font \
+ -fg {#000000} \
+ -data [list $file_path $eol $enc $read_only]
+ }
+ }
+
+ if {$ask && $::FileList::ask__append_file_to_project} {
+ # Ask for append the file to the project
+ set ::FileList::dialog_response 0
+ set win [toplevel .append_to_the_project_dialog]
+
+ pack [label $win.label -text [mc "Do you want to append this file to the project ?\n%s" $file_name]] -fill x -pady 5 -padx 5
+
+ pack [frame $win.frm] -pady 5
+ pack [ttk::button $win.frm.yes_button -text [mc "Yes"] -command "
+ set ::FileList::dialog_response 1
+ grab release $win
+ destroy $win" \
+ ] -side left
+ bind $win.frm.yes_button <Return> "
+ set ::FileList::dialog_response 1
+ grab release $win
+ destroy $win"
+ bind $win.frm.yes_button <KP_Enter> "
+ set ::FileList::dialog_response 1
+ grab release $win
+ destroy $win"
+ pack [ttk::button $win.frm.no_button -text [mc "No"] -command "
+ grab release $win
+ destroy $win" \
+ ] -side left
+ bind $win.frm.no_button <Return> "
+ grab release $win
+ destroy $win"
+ bind $win.frm.no_button <KP_Enter> "
+ grab release $win
+ destroy $win"
+
+ pack [ttk::separator $win.sep -orient horizontal] -fill x -pady 10
+ pack [checkbutton $win.chb -text [mc "Do not ask again"] -onvalue 0 -offvalue 1 -variable ::FileList::ask__append_file_to_project] -anchor w
+ pack [text $win.tip -fg {#888888} -bg {#EEEEEE} -height 2 -width 0 -bd 0] -fill x
+ $win.tip insert end [mc "Tip: You can enable/disable this dialog in MCU 8051 IDE configuration dialog."]
+ $win.tip configure -state disabled
+
+ # Set window attributes
+ wm iconphoto $win ::ICONS::16::help
+ wm title $win [mc "Add file ?"]
+ wm resizable $win 0 0
+ wm transient $win .
+ catch {grab $win}
+ focus -force $win.frm.yes_button
+ wm protocol $win WM_DELETE_WINDOW "
+ grab release $win
+ destroy $win
+ "
+ raise $win
+ update
+ tkwait window $win
+
+ if {$::FileList::dialog_response } {
+ if {[llength $project_files_bookmarks]} {
+ $listbox_project_files_bm insert end "\n"
+ }
+ lappend project_files_bookmarks 0
+ $listbox_project_files insert end #auto \
+ -font $opened_file_font -fill {#000000} \
+ -text $file_name -data [list $file_path $eol $enc $read_only]
+ }
+ }
+
+ # Create editor object for the file
+ if {$file_path != {}} {
+ set data {}
+ if {!${::Editor::editor_to_use}} {
+ set file [open $file_path]
+ fconfigure $file -encoding $enc
+ if {[regsub -all {[\u0000-\u0008\u000B-\u000C\u000E-\u001F\u007F-\u009F]} [read $file] {} data]} {
+ tk_messageBox -parent . \
+ -type ok -icon warning \
+ -title [mc "Binary File Opened - MCU 8015 IDE"] \
+ -message [mc "The file %s is binary, saving it will result corrupted file." $file_path]
+ }
+ close $file
+ }
+
+ set editor [Editor "::editor${file_count}_$obj_idx" \
+ [expr {!$fast}] $eol $enc $read_only $file_switching_enabled $this \
+ $file_name $file_path "$this editor_procedure {} " \
+ [regsub -all {\r\n?} $data "\n"] $sh \
+ ]
+ } {
+ set editor [Editor "::editor${file_count}_$obj_idx" \
+ [expr {!$fast}] $eol $enc $read_only $file_switching_enabled $this \
+ $file_name $file_path "$this editor_procedure {} " {} $sh \
+ ]
+ }
+
+ # Determinate file type and set appropriate icon
+ set ext [string trimleft [file extension $file_name] {.}]
+ if {$ext == {h}} {
+ set icon {source_h}
+ } elseif {$ext == {c}} {
+ set icon {source_c}
+ } elseif {$ext == {cxx} || $ext == {cpp} || $ext == {cc}} {
+ set icon {source_cpp}
+ } elseif {$ext == {asm}} {
+ set icon {asm}
+ } else {
+ set icon {ascii}
+ }
+ $filetabs_nb insert end $file_descriptor \
+ -text $file_name -image ::ICONS::16::$icon \
+ -raisecmd "$this switch_file_from_filetabs $file_descriptor"
+ $filetabs_nb see $file_descriptor
+
+ # Conditionaly show Line Numbers and Icon Border
+ if {$iconBorder == 0} {
+ $editor hideLineNumbers
+ }
+ if {$lineNumbers == 0} {
+ $editor hideIconBorder
+ }
+
+ if {$sh == {}} {
+ set sh [$editor get_language]
+ }
+
+ # Editor text widget
+ lappend editor_wdgs [$editor cget -editor]
+ # Register Editor's object and widget and its frame
+ lappend editors $editor
+ lappend file_eol $eol
+ lappend file_encoding $enc
+ lappend file_ro_mode $read_only
+ lappend file_sh $sh
+
+ # Add editor to right panel
+ rightPanel_add_Editor [expr {!$fast}]
+ $this todo_add_Editor {}
+ $this todo_change_filename end $file_name
+ $editor goto 1
+
+ # Increment counter of opened files
+ incr file_count
+ # Return descriptor of the file
+ return $file_descriptor
+ }
+
+ ## Switch file from filetabs notebook
+ # @parm String page - Page ID
+ # @return void
+ public method switch_file_from_filetabs {page} {
+ $listbox_opened_files selection set $page
+ switchfile
+ }
+
+ ## Show file details windows from files tab (or something ...)
+ # $filetabs_nb bindtabs <Enter> "$this file_details_win_create_from_ftnb"
+ # @parm String page - Page ID
+ # @return void
+ public method file_details_win_create_from_ftnb {page} {
+ $this file_details_win_create O $page
+ }
+
+ ## Invoke popup menu for specific file from files tab (or something ...)
+ # $filetabs_nb bindtabs <ButtonRelease-3> "$this filetabs_nb_popup_menu %X %Y"
+ # @parm Int X - X coordinate
+ # @parm Int Y - Y coordinate
+ # @parm String page - Page ID
+ # @return void
+ public method filetabs_nb_popup_menu {X Y page} {
+ switch_file_from_filetabs $page
+
+ tk_popup $filetabs_pu_menu $X $Y
+ }
+
+ ## Save currently opened file under a given filename
+ # note: should be used only for saving untitled files !
+ # @parm String filename - Full file name including path
+ # @return bool - 1: (maybe) successful; 0: argument is empty
+ public method save_as {filename} {
+
+ # Handle empty argument
+ if {$filename == {}} {return 0}
+
+ # Adjust filename
+ if {!$::MICROSOFT_WINDOWS} { ;# POSIX way
+ if {![regexp "^(~|/)" $filename]} {
+ set filename "[$this cget -ProjectDir]/$filename"
+ }
+ } { ;# Microsoft windows way
+ if {![regexp "^\w:" $filename]} {
+ set filename [file join [$this cget -ProjectDir] $filename]
+ }
+ }
+ set filename [file normalize $filename]
+ if {[file extension $filename] == {}} {
+ append filename {.asm}
+ }
+ # Determinate file rootname
+ set rootname [file tail $filename]
+
+ # Ask user for overwrite existing file
+ if {[file exists $filename] && [file isfile $filename]} {
+ if {[tk_messageBox \
+ -type yesno \
+ -icon question \
+ -parent . \
+ -title [mc "Overwrite file"] \
+ -message [mc "A file name '%s' already exists. Are you sure you want to overwrite it ?" $rootname]
+ ] != {yes}
+ } {
+ return 1
+ }
+ }
+
+ # Change filename in the listbox of opened files
+ set item [$listbox_opened_files selection get]
+ $listbox_opened_files itemconfigure $item -text $rootname -data $filename
+ $filetabs_nb itemconfigure $item -text $rootname
+
+ # Determinate some additional informations
+ if {$splitted && $selectedView} {
+ set idx $actualEditor2
+ } {
+ set idx $actualEditor
+ }
+ set editor [lindex $editors $idx]
+ set fullFileName [$editor cget -fullFileName] ;# Original full filename
+ set original_rootname [$editor cget -filename] ;# Original file rootname
+
+ # Mark the file as opened (in listbox of project files)
+ foreach item [$listbox_project_files items] {
+ if {[$listbox_project_files itemcget $item -text] != $original_rootname} {
+ continue
+ }
+ set data [$listbox_project_files itemcget $item -data]
+ if {[llength $data] > 4} {continue}
+ if {[lindex $data 0] != $fullFileName} {continue}
+ lset data 0 $filename
+ $listbox_project_files itemconfigure $item -data $data -text $rootname
+ }
+
+ # Set new file name
+ $editor set_FileName $filename $rootname
+ $editor save
+ $this todo_change_filename $idx $rootname
+
+ # Ask for appending the file to the project
+ set response [tk_messageBox \
+ -title [mc "Add file ?"] \
+ -icon question -type yesno \
+ -parent $parent \
+ -message [mc "Do you want to append this file to the project ?\n%s" $rootname]
+ ]
+ if {$response == {yes}} {
+ filelist_append_to_prj
+ }
+
+ ::X::recent_files_add 1 $filename
+
+ # Done ...
+ return 1
+ }
+
+
+ # ---------------------------------------------------------------------
+ # EDITOR PROCEDURES
+ # ---------------------------------------------------------------------
+
+ ## Show/Hide line numbers
+ # @return void
+ public method show_hide_lineNumbers {} {
+ if {$lineNumbers} {
+ set lineNumbers 0
+ foreach editor $editors {$editor hideLineNumbers}
+ } {
+ set lineNumbers 1
+ foreach editor $editors {$editor showLineNumbers}
+ }
+ }
+
+ ## Show/Hide icon border
+ # @return void
+ public method show_hide_IconBorder {} {
+ if {$iconBorder} {
+ set iconBorder 0
+ foreach editor $editors {$editor hideIconBorder}
+ } {
+ set iconBorder 1
+ foreach editor $editors {$editor showIconBorder}
+ }
+ }
+
+ ## Get number of lines in the current editor
+ # @return Int - result
+ public method editor_linescount {} {
+ if {$splitted && $selectedView} {
+ set tmp $actualEditor2
+ } {
+ set tmp $actualEditor
+ }
+ set tmp [[lindex $editors $tmp] cget -lastEnd]
+ return [expr {$tmp-1}]
+ }
+
+ ## Get number of line with the insertion cursor
+ # @return Int - result
+ public method editor_actLineNumber {} {
+ if {$splitted && $selectedView} {
+ set idx $actualEditor2
+ } {
+ set idx $actualEditor
+ }
+ return [expr {int([[lindex $editor_wdgs $idx] index insert])}]
+ }
+
+ ## Call any editor procedure
+ # @parm Int objectNumber - Number of editor object to use, {} mean current editor
+ # @parm String procedure - name of the procedure
+ # @parm String arguments - list of arguments to pass that procedure
+ # @retrurn mixed - result of invoked procedure
+ public method editor_procedure {objectNumber procedure arguments} {
+ # Determinate editor number
+ if {$objectNumber == {}} {
+ if {$splitted && $selectedView} {
+ set objectNumber $actualEditor2
+ } {
+ set objectNumber $actualEditor
+ }
+ }
+ # Call editor procedure
+ set editor [lindex $editors $objectNumber]
+ if {$editor == {}} {
+ switch_to_last
+ update
+ }
+ return [eval "$editor $procedure $arguments"]
+ }
+
+ ## Compare two tag ranges (text widget tags)
+ # @parm TextIndex first - 1st text tag range to compare {TextIndex Bool__Start_or_End}
+ # @parm TextIndex second - 2nd text tag range to compare {TextIndex Bool__Start_or_End}
+ # @return Int - result (on of {-1 0 1})
+ proc editor__sort_tag_ranges {first second} {
+
+ # Local variables
+ set idx0 [split [lindex $first 0] {.}] ;# Adjusted 1st text index -- list: {Row Column}
+ set row0 [lindex $idx0 0] ;# Row (1st index)
+ set col0 [lindex $idx0 1] ;# Column (1st index)
+ set idx1 [split [lindex $second 0] {.}] ;# Adjusted 2nd text index -- list: {Row Column}
+ set row1 [lindex $idx1 0] ;# Row (2nd index)
+ set col1 [lindex $idx1 1] ;# Column (2nd index)
+ set StartEnd0 [lindex $first 2] ;# Bool: Start_or_End (1st index)
+ set StartEnd1 [lindex $second 2] ;# Bool: Start_or_End (2nd index)
+
+ # Compare rows
+ if {$row0 > $row1} {
+ return -1
+ } elseif {$row0 < $row1} {
+ return 1
+ }
+
+ # Compare columns
+ if {$col0 > $col1} {
+ return -1
+ } elseif {$col0 < $col1} {
+ return 1
+ }
+
+ # Compare "Start_or_End" flags
+ if {!$StartEnd0 && $StartEnd1} {
+ return 1
+ } elseif {$StartEnd0 && !$StartEnd1} {
+ return -1
+ } else {
+ return 0
+ }
+ }
+
+ ## Get list of project files
+ # @return List - result
+ public method get_project_files_list {} {
+ ## Local variables
+ # List header
+ if {$splitted} {
+ set _actualEditor2 $actualEditor2
+ } {
+ set _actualEditor2 -1
+ }
+ if {$splitted} {
+ if {$pwin_orient == {vertical}} {
+ set idx 1
+ } {
+ set idx 0
+ }
+ set multiview_sash_pos [lindex [$multiview_paned_win sash coord 0] $idx]
+ }
+ set file_list [list \
+ [llength $editors] \
+ [list \
+ $actualEditor \
+ $_actualEditor2 \
+ $multiview_sash_pos \
+ $pwin_orient \
+ $selectedView \
+ ] \
+ ]
+ # Project directory
+ set project_path [$this cget -projectPath]
+ append project_path {/}
+ # Lenght of the project directory path string
+ set project_path_length [string length $project_path]
+ # Opened files index
+ set opened_i 0
+
+ ## Create list of full paths of opened files (in order of listbox of opened files)
+ set opened_files {}
+ foreach item [$listbox_opened_files items] {
+ set file_path [$listbox_opened_files itemcget $item -data]
+ if {$file_path == {}} {continue}
+ lappend opened_files $file_path
+ }
+
+ # Iterate over items of ListBox of project files
+ set i -1
+ foreach item [$listbox_project_files items] {
+ incr i
+
+ # Determinate item data
+ set data [$listbox_project_files itemcget $item -data]
+
+ # Unopened file
+ if {[llength $data] > 4} {
+ # Set opened flag
+ lset data 1 {no}
+ # Set file path
+ set path [lindex $data 5]
+ if {[string first $project_path $path] == 0} {
+ lset data 5 [string range $path $project_path_length end]
+ }
+
+ # Append o-bookmark=0, p-bookmark=$bm and file index=0
+ set data [linsert $data 2 0 [lindex $project_files_bookmarks $i] 0]
+
+ # Append file record to the resulting list
+ lappend file_list $data
+
+ # Opened file
+ } {
+ # Find the file in list of opened files
+ foreach editor $editors {
+ # Local variables
+ set file_name [$editor cget -fullFileName] ;# Full file name
+
+ if {$file_name != [lindex $data 0]} {continue}
+
+ # Determinate true item data
+ set data [getFileInfo $editor {yes}]
+
+ # Set file path
+ set path [lindex $data 5]
+ if {[string first $project_path $path] == 0} {
+ lset data 5 [string range $path $project_path_length end]
+ }
+
+ # Determinate index in Listbox of opened files
+ set index [lsearch $opened_files $file_name]
+
+ # Append o-bookmark, p-bookmark and file index
+ set data [linsert $data 2 \
+ [lindex $opened_files_bookmarks $index] \
+ [lindex $project_files_bookmarks $i] \
+ $index]
+
+ # Append encoding and EOL info
+ lappend data \
+ [lindex $file_eol $opened_i] \
+ [lindex $file_encoding $opened_i] \
+ [lindex $file_sh $opened_i] \
+ [$this get_file_notes_data $i]
+
+ incr opened_i
+
+ # Append file record to the resulting list
+ lappend file_list $data
+ }
+ }
+ }
+
+ # Return the file list
+ return $file_list
+ }
+
+ ## Get opened file item data to use in filelists
+ # @see get_project_files_list
+ # @see editor_close
+ # @parm Object editor - Reference to editor object
+ # @parm String active - Active flag
+ # @return List - resulting data or '{}'
+ private method getFileInfo {editor active} {
+ # Determinate full file name
+ set file_name [$editor cget -fullFileName]
+ if {$file_name == {}} {return {}}
+
+ # Determinate file rootname, path and MD5 hex hash
+ regexp {[^\\\/]*$} $file_name name
+ regexp {^.*[\\\/]} $file_name path
+ if {[catch {
+ set md5_hash [md5::md5 -hex -hex -file $file_name]
+ }]} {
+ set md5_hash {}
+ }
+
+ set actual_line [$editor get_current_line_number] ;# Current line
+ set line_markers [$editor export_line_markers_data] ;# bookmarks and breakpoints
+ set bookmarks [lindex $line_markers 0] ;# Bookmarks
+ set breakpoints [lindex $line_markers 1] ;# Breakpoints
+
+ # Return result
+ return [list \
+ $name $active [$editor cget -ro_mode] \
+ $actual_line $md5_hash $path \
+ $bookmarks $breakpoints \
+ ]
+ }
+
+ ## Invoke dialog "Open file" (require NS 'X')
+ # @return void
+ public method editor_open {} {
+ X::__open
+ }
+
+ ## Save the current file
+ # @return void
+ public method editor_save {} {
+ if {$splitted && $selectedView} {
+ [lindex $editors $actualEditor2] save
+ } {
+ [lindex $editors $actualEditor] save
+ }
+ }
+
+ ## Save current file under a different name (reires NS 'X')
+ # @return void
+ public method editor_save_as {} {
+ X::__save_as
+ }
+
+ ## Call procedure save for each editor object in the current project
+ # note: in other words save all opened files
+ # @return void
+ public method editor_save_all {} {
+ foreach editor $editors {
+ $editor save
+ }
+ }
+
+ ## Create a new empty editor object inside the project and focus on it
+ # @return void
+ public method editor_new {} {
+ openfile {} 0 . def def 0 1 {}
+ switch_to_last
+ set editor [lindex $editors end]
+ update
+ $editor create_highlighting_tags
+ update
+ rightPanel_add_Editor__create_menu_and_tags
+ $editor parseAll
+ focus [$editor cget -editor]
+ }
+
+ ## Open a new editor containing the given data
+ # @parm String data - Data to insert into the editor
+ # @return void
+ public method background_open {data} {
+ if {!${::Editor::editor_to_use}} {
+ openfile {} 0 . def def 0 0 {}
+ set editor [lindex $editors end]
+ $editor insertData $data {}
+ [$editor cget -editor] edit modified 0
+ [$editor cget -editor] edit reset
+ } {
+ set dir [${::X::actualProject} cget -ProjectDir]
+ catch {
+ file delete -force -- [file join $dir .#special:tmp]
+ }
+
+ set file [open [file join $dir .#special:tmp] w 420]
+ puts -nonewline $file $data
+ close $file
+
+ openfile [file join $dir .#special:tmp] 0 . def def 0 0 {}
+ }
+ }
+
+ ## Close the current editor and optionaly save its data to some file
+ # note: if this procedure was executed to destroy the last
+ # remainig editor then a new one would be created !!!
+ # @parm Bool ask - Ask user for saving the file (if was modified)
+ # @parm Int editorIdx - number of editor to close, {} mean currently active editor
+ # @return Bool - Created a new editor ?
+ public method editor_close {ask editorIdx} {
+ if {$editor_close_in_progress} {return}
+ set editor_close_in_progress 1
+
+ # Determinate editor object reference
+ if {$editorIdx == {}} {
+ if {$splitted && $selectedView} {
+ set editorIdx $actualEditor2
+ } {
+ set editorIdx $actualEditor
+ }
+ } {
+ if {$editorIdx == $actualEditor} {
+ set selectedView 0
+ } elseif {$editorIdx == $actualEditor2} {
+ set selectedView 1
+ }
+ }
+ set editor [lindex $editors $editorIdx]
+
+ # Ask user for saving the file (if was modified)
+ if {$ask && [$editor cget -modified]} {
+ set response [tk_messageBox \
+ -type yesnocancel \
+ -title [mc "Close document - MCU 8051 IDE"] \
+ -icon question \
+ -default yes \
+ -message [mc "The document %s have been modified.\nDo you want to save it ?" [[lindex $editors $editorIdx] cget -fullFileName]]]
+
+ if {$response == {yes}} {
+ $editor save
+ } elseif {$response == {cancel}} {
+ set editor_close_in_progress 0
+ return {}
+ }
+ }
+
+ # Mark the file as unopened (in ListBox of project fies)
+ set items [$listbox_project_files items] ;# List of project files
+ set fullFileName [$editor cget -fullFileName] ;# Full filename of the current file
+ set rootname [$editor cget -filename] ;# Rootname of the current file
+ foreach item $items {
+ if {[$listbox_project_files itemcget $item -text] != $rootname} {
+ continue
+ }
+ set data [$listbox_project_files itemcget $item -data]
+ if {[llength $data] > 4} {continue}
+
+ if {[lindex $data 0] == $fullFileName} {
+ $listbox_project_files itemconfigure $item \
+ -fg {#888888} \
+ -font $closed_file_font \
+ -data [concat \
+ [getFileInfo $editor {no}] \
+ [lindex $file_eol $editorIdx] \
+ [lindex $file_encoding $editorIdx] \
+ [lindex $file_sh $editorIdx] \
+ [$this get_file_notes_data $editorIdx] \
+ ]
+ }
+ }
+
+ # Delete editor object and all its widgets
+ set file_descriptor [lindex $file_descriptors $editorIdx]
+ set item_index [$listbox_opened_files index $file_descriptor]
+ $listbox_opened_files delete $file_descriptor
+ $listbox_opened_files_bm delete [expr {$item_index + 1}].0 [expr {$item_index + 2}].0
+ set opened_files_bookmarks [lreplace $opened_files_bookmarks $item_index $item_index]
+ delete object $editor
+ rightPanel_remove_Editor $editorIdx
+ $this todo_remove_editor $editorIdx
+
+ $filetabs_nb delete $file_descriptor
+
+ # Adjust object variables
+ foreach var {editors file_descriptors editor_wdgs file_eol file_encoding file_ro_mode file_sh} {
+ set $var [lreplace [subst "\$$var"] $editorIdx $editorIdx]
+ }
+ if {$actualEditor > $editorIdx} {
+ incr actualEditor -1
+ }
+ if {$actualEditor2 > $editorIdx} {
+ incr actualEditor2 -1
+ }
+ if {$actualEditor == $editorIdx || $actualEditor2 == $editorIdx} {
+ set do_not_forget_editor 1
+ if {$actualEditor == $editorIdx} {
+ set actualEditor -1
+ }
+ if {$actualEditor2 == $editorIdx} {
+ set actualEditor2 -1
+ }
+
+ # Conditionaly open a new editor
+ if {$splitted} {
+ set min 2
+ } {
+ set min 1
+ }
+ if {[llength $file_descriptors] < $min} {
+ if {$min == 1} {
+ set file_count 0
+ }
+ Sbar [mc "Last editor window closed -> opening a new one ..."]
+ editor_new
+ set editor_close_in_progress 0
+ return 1
+ }
+ # Switch to last editor in the list
+ switch_to_last
+ }
+
+ set editor_close_in_progress 0
+ return 1
+ }
+
+ ## Close all editors in the list of opened files
+ # @parm Bool allowCancelButton - Display button "Cancel" in dialog "Save multiple files"
+ # @parm Bool projectClose - Should be 1 if closing project
+ # @return Bool - 1: all have been done smoothly; 0: user has been asked about modified files
+ public method editor_close_all {allowCancelButton projectClose} {
+ # Determinate number of editors to close
+ set editorCount [llength $file_descriptors]
+
+ # Create list of the modified ones
+ set unsaved {}
+ foreach editor $editors {
+ if {[$editor cget -modified]} {
+ lappend unsaved $editor
+ }
+ }
+
+ # Ask user for file save
+ if {$unsaved != {}} {
+ save_multiple_files $allowCancelButton
+ return 0
+ } {
+ if {!$projectClose} {
+ editor_force_close_all
+ }
+ return 1
+ }
+ }
+
+ ## Close all opened files without any warning
+ # @return void
+ public method editor_force_close_all {} {
+ # Determinate number of editors
+ set editorMaxIdx [llength $file_descriptors]
+ set editorMaxIdx [expr {$editorMaxIdx - 1}]
+
+ # Close editors
+ for {set i $editorMaxIdx} {$i >= 0} {incr i -1} {
+ editor_close 0 $i
+ }
+ }
+
+ ## Create special dialog to ask user which files should be saved
+ # Intended for closing multiple files
+ # note: * Using class variable 'unsaved' instead of any argument !!!
+ # * Depend on methods: save_multiple_files_DESTROY, save_multiple_files_CANCEL,
+ # save_multiple_files_SAVEALL, save_multiple_files_SAVESELECTED
+ # @parm allowCancelButton bool - 1: show 'Cancel' button; 0: nothing
+ # @return void
+ public method save_multiple_files {allowCancelButton} {
+
+ # Create a new toplevel window for the dialog
+ set dialog .save_multiple_files
+ toplevel $dialog
+
+ # Create the top part of dialog (Header and some icon)
+ pack [frame $dialog.topframe] -fill x -expand 1
+ pack [label $dialog.topframe.image -image ::ICONS::32::fileclose] -side left -padx 10
+ pack [label $dialog.topframe.message \
+ -text [mc "The following documents have been modified,\ndo you want to save them before closing ?"] \
+ ] -side right -fill x -expand 1
+
+ # Create the middle part of the dialog (list of unsaved files)
+ pack [tkk::labelframe $dialog.lf \
+ -text [mc "Unsaved files"] \
+ ] -fill both -expand 1 -pady 10 -padx 10
+ set i 0
+ foreach editorObj $unsaved {
+ pack [checkbutton $dialog.lf.chb$i \
+ -text [$editorObj cget -filename] \
+ -variable unsavedfile$i \
+ -image ::ICONS::16::kcmdf \
+ -compound left \
+ ] -anchor w -padx 10
+ incr i
+ }
+
+ # Create the bottom part of the dialog (buttons "Save selected", "Save all" etc.)
+ pack [ttk::separator $dialog.separator -orient horizontal] -fill x -expand 1
+ pack [frame $dialog.f]
+ # SAVESELECTED
+ pack [ttk::button $dialog.f.b_save_selected \
+ -text [mc "Save selected"] \
+ -compound left \
+ -image ::ICONS::16::filesave \
+ -command {${X::actualProject} save_multiple_files_SAVESELECTED} \
+ ] -side left
+ # SAVEALL
+ pack [ttk::button $dialog.f.b_save_all \
+ -text [mc "Save all"] \
+ -compound left \
+ -image ::ICONS::16::save_all \
+ -command {${X::actualProject} save_multiple_files_SAVEALL} \
+ ] -side left
+ # DESTROY
+ pack [ttk::button $dialog.f.b_discard \
+ -text [mc "Discard"] \
+ -compound left \
+ -image ::ICONS::16::editdelete \
+ -command {${X::actualProject} save_multiple_files_DESTROY} \
+ ] -side left
+ # CANCEL
+ if {$allowCancelButton} {
+ pack [ttk::button $dialog.f.b_cancel \
+ -text [mc "Cancel"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command {${X::actualProject} save_multiple_files_CANCEL} \
+ ] -side left
+ }
+
+ # Set dialog attributes (modal window)
+ wm iconphoto $dialog ::ICONS::16::exit
+ wm title $dialog [mc "Close files - MCU 8051 IDE"]
+ wm state $dialog normal
+ wm minsize $dialog 350 200
+ wm transient $dialog .
+ wm protocol $dialog WM_DELETE_WINDOW "
+ grab release $dialog
+ destroy $dialog
+ "
+ update
+ catch {
+ grab $dialog
+ }
+ raise $dialog
+ focus $dialog
+ tkwait window $dialog
+ }
+
+ ## Auxiliary procedure for method 'save_multiple_files'
+ # It should be executed on pressing button 'Save selected' dialog 'Save multiple files'
+ # This function saves all files selected in dialog 'Save multiple files'
+ # @return void
+ public method save_multiple_files_SAVESELECTED {} {
+ set i 0
+ foreach editor $unsaved {
+ set cnd [subst "\${::unsavedfile$i}"]
+ if {$cnd} {$editor save}
+ incr i
+ }
+ save_multiple_files_DESTROY
+ }
+
+ ## Auxiliary procedure for method 'save_multiple_files'
+ # It should be executed on pressing button 'Save all' dialog 'Save multiple files'
+ # @return void
+ public method save_multiple_files_SAVEALL {} {
+ foreach editor $unsaved {
+ $editor save
+ }
+ save_multiple_files_DESTROY
+ }
+
+ ## Auxiliary procedure for method 'save_multiple_files'
+ # It should be executed on pressing button 'Discard' in 'Save multiple files' dialog
+ # @return void
+ public method save_multiple_files_DESTROY {} {
+ set editorMaxIdx [llength $file_descriptors]
+ set editorMaxIdx [expr {$editorMaxIdx - 1}]
+ editor_force_close_all
+ save_multiple_files_CANCEL
+ }
+
+ ## Auxiliary procedure for method 'save_multiple_files'
+ # It should be executed on pressing button 'Cancel' in 'Save multiple files' dialog
+ # @return void
+ public method save_multiple_files_CANCEL {} {
+ destroy .save_multiple_files
+ }
+
+ ## Reevaluate state of buttons on icon bar in tab LProject files
+ # @return void
+ public method FileList_project_disEna_buttons {} {
+
+ # Determinate selected item
+ set item [$listbox_project_files selection get]
+
+ # Non empty selection
+ if {$item != {}} {
+ ${project_files_buttonBox}remove configure -state normal
+ ${project_files_buttonBox}bookmark configure -state normal
+
+ # Simulator engaged
+ if {$frozen} {
+ ${project_files_buttonBox}close configure -state disabled
+ ${project_files_buttonBox}open configure -state disabled
+
+ # Simulator disengaged
+ } {
+ # Opened file
+ if {[llength [$listbox_project_files itemcget $item -data]] < 5} {
+ ${project_files_buttonBox}close configure -state normal
+ ${project_files_buttonBox}open configure -state disabled
+
+ # Unopened file
+ } {
+ ${project_files_buttonBox}close configure -state disabled
+ ${project_files_buttonBox}open configure -state normal
+ }
+ }
+
+ # Nothing selected
+ } {
+ ${project_files_buttonBox}remove configure -state disabled
+ ${project_files_buttonBox}open configure -state disabled
+ ${project_files_buttonBox}close configure -state disabled
+ ${project_files_buttonBox}bookmark configure -state disabled
+ }
+ }
+
+ ## Invoke project files popup menu
+ # @parm Int X - relative X coordinate
+ # @parm Int Y - relative Y coordinate
+ # @return void
+ public method fileList_project_filelist_popup {X Y} {
+ if {$item_menu_invoked} {
+ set item_menu_invoked 0
+ return
+ }
+
+ foreach entry {
+ {Remove file from the project} {Close file} {Open file}
+ {Bookmark} {Move up} {Move down}
+ {Move to top} {Move to bottom} {Open with}
+ } {
+ $project_files_menu entryconfigure [::mc $entry] -state disabled
+ }
+
+ tk_popup $project_files_menu $X $Y
+ }
+
+ ## Invoke project files popup menu -- for particular item
+ # @parm Int X - relative X coordinate
+ # @parm Int Y - relative Y coordinate
+ # @parm String item - ID of the current item
+ # @return void
+ public method fileList_project_filelist_item_popup {X Y item} {
+ set item_menu_invoked 1
+
+ foreach entry {
+ {Remove file from the project} {Bookmark} {Open with}
+ } {
+ $project_files_menu entryconfigure [::mc $entry] -state normal
+ }
+
+ # It is not so easy to open the file with an external editor on Microsoft Windows as
+ # it is on a POSIX system, that's why this feature is disabled here
+ if {$::MICROSOFT_WINDOWS} {
+ $project_files_menu entryconfigure [::mc {Open with}] -state disabled
+ }
+
+ # Adjust ListBox selection
+ $listbox_project_files selection set $item
+
+ # Opened file
+ if {[llength [$listbox_project_files itemcget $item -data]] < 5} {
+ if {!$frozen} {
+ $project_files_menu entryconfigure [::mc "Close file"] -state normal
+ }
+ $project_files_menu entryconfigure [::mc "Open file"] -state disabled
+ # Unopened file
+ } {
+ if {!$frozen} {
+ $project_files_menu entryconfigure [::mc "Close file"] -state disabled
+ }
+ $project_files_menu entryconfigure [::mc "Open file"] -state normal
+ }
+
+ # Movement commands
+ if {[$listbox_project_files index $item] == 0} {
+ set state disabled
+ } {
+ set state normal
+ }
+ $project_files_menu entryconfigure [::mc "Move up"] -state $state
+ $project_files_menu entryconfigure [::mc "Move to top"] -state $state
+
+ if {[$listbox_project_files index $item] == ([llength [$listbox_project_files items]] - 1)} {
+ set state disabled
+ } {
+ set state normal
+ }
+ $project_files_menu entryconfigure [::mc "Move down"] -state $state
+ $project_files_menu entryconfigure [::mc "Move to bottom"] -state $state
+
+ # Invoke the menu
+ tk_popup $project_files_menu $X $Y
+ }
+
+ ## Move up current item in project filelist
+ # @return void
+ public method filelist_prj_move_up {} {
+ # Local variables
+ set item [$listbox_project_files selection get] ;# Item ID
+ set index [$listbox_project_files index $item] ;# Item index
+ set target [expr {$index - 1}] ;# Target index
+
+ # Check if the item can be moved
+ if {$index == 0} {return}
+
+ # Move item in listbox
+ $listbox_project_files move $item $target
+ # Move item in list of bookmarks and icon border
+ if {[lindex $project_files_bookmarks $index] != [lindex $project_files_bookmarks $target]} {
+ # Determinate bookmark flag for source and target index
+ set trg_bm [lindex $project_files_bookmarks $target]
+ set idx_bm [lindex $project_files_bookmarks $index]
+ # Move item in list of bookmarks
+ lset project_files_bookmarks $target [lindex $project_files_bookmarks $index]
+ lset project_files_bookmarks $index $trg_bm
+ # Move item in icon border
+ incr target
+ incr index
+ $listbox_project_files_bm delete $index.0 [list $index.0 lineend]
+ $listbox_project_files_bm delete $target.0 [list $target.0 lineend]
+ if {$trg_bm} {
+ $listbox_project_files_bm image create $index.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ if {$idx_bm} {
+ $listbox_project_files_bm image create $target.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ }
+ }
+
+ ## Move down current item in project filelist
+ # @return void
+ public method filelist_prj_move_down {} {
+ # Local variables
+ set item [$listbox_project_files selection get] ;# Item ID
+ set index [$listbox_project_files index $item] ;# Item index
+ set items [llength [$listbox_project_files items]] ;# Number of items in listbox
+ set target [expr {$index + 1}] ;# Target index
+
+ # Check if the item can be moved
+ if {$index == $items} {return}
+
+ # Move item in listbox
+ $listbox_project_files move $item $target
+ # Move item in list of bookmarks and icon border
+ if {[lindex $project_files_bookmarks $index] != [lindex $project_files_bookmarks $target]} {
+ # Determinate bookmark flag for source and target index
+ set trg_bm [lindex $project_files_bookmarks $target]
+ set idx_bm [lindex $project_files_bookmarks $index]
+ # Move item in list of bookmarks
+ lset project_files_bookmarks $target [lindex $project_files_bookmarks $index]
+ lset project_files_bookmarks $index $trg_bm
+ # Move item in icon border
+ incr target
+ incr index
+ $listbox_project_files_bm delete $index.0 [list $index.0 lineend]
+ $listbox_project_files_bm delete $target.0 [list $target.0 lineend]
+ if {$trg_bm} {
+ $listbox_project_files_bm image create $index.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ if {$idx_bm} {
+ $listbox_project_files_bm image create $target.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ }
+ }
+
+ ## Move to top current item in project filelist
+ # @return void
+ public method filelist_prj_move_top {} {
+ # Determinate index of the current item
+ set item [$listbox_project_files selection get]
+ set index [$listbox_project_files index $item]
+
+ # Check if the item can be moved
+ if {$index == 0} {return}
+
+ # Move item in listbox
+ $listbox_project_files move $item 0
+ # Move item in list of bookmarks
+ set bm [lindex $project_files_bookmarks $index]
+ set project_files_bookmarks [lreplace $project_files_bookmarks $index $index]
+ set project_files_bookmarks [linsert $project_files_bookmarks 0 $bm]
+ # Move item in icon border
+ incr index
+ $listbox_project_files_bm delete $index.0 $index.0+1l
+ $listbox_project_files_bm insert 1.0 "\n"
+ if {$bm} {
+ $listbox_project_files_bm image create 1.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ }
+
+ ## Move to bottom current item in project filelist
+ # @return void
+ public method filelist_prj_move_bottom {} {
+ # Determinate index of the current item and end index
+ set item [$listbox_project_files selection get]
+ set index [$listbox_project_files index $item]
+ set items [llength [$listbox_project_files items]]
+
+ # Check if the item can be moved
+ if {$index == $items} {return}
+
+ # Move item in listbox
+ $listbox_project_files move $item [expr {$items - 1}]
+ # Move item in list of bookmarks
+ set bm [lindex $project_files_bookmarks $index]
+ set project_files_bookmarks [lreplace $project_files_bookmarks $index $index]
+ lappend project_files_bookmarks $bm
+ # Move item in icon border
+ incr index
+ set end [llength $project_files_bookmarks]
+ $listbox_project_files_bm delete $index.0 $index.0+1l
+ $listbox_project_files_bm insert $end.0 "\n"
+ if {$bm} {
+ $listbox_project_files_bm image create $end.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ }
+
+ ## Open file from ListBox of project files
+ # Takes any set of arguments and discards them
+ # @return void
+ public method filelist_project_file_open args {
+ if {$frozen} {return}
+
+ # Local varibales
+ set item [$listbox_project_files selection get] ;# Item ID
+ set record [$listbox_project_files itemcget $item -data] ;# Item data
+
+ # If the file is already opended -- abort
+ if {[llength $record] == 4} {return}
+
+ # Parse item data
+ set ri 0
+ foreach var {file_name active ro file_line file_md5 file_path file_BMs file_BPs eol enc sh notes} {
+ set $var [lindex $record $ri]
+ incr ri
+ }
+
+ # Check for file existence
+ if {![file exists $file_path$file_name]} {
+ tk_messageBox \
+ -title [mc "File not found"] \
+ -icon error \
+ -type ok \
+ -message [mc "File %s could not be located at the specified location." $file_name]
+ return
+ }
+
+ # Verify file MD5 hash
+ if {[catch {
+ if {[md5::md5 -hex -file $file_path$file_name] != $file_md5} {
+ tk_messageBox \
+ -icon warning \
+ -type ok \
+ -title [mc "File changed"] \
+ -message [mc "File \"%s\" was modified since last project save\nTime: %s" $file_name [clock format [file mtime $file_path$file_name] -format {%T %D}]]
+ }
+ }]} then {
+ tk_messageBox \
+ -icon warning \
+ -type ok \
+ -title [mc "Unknown error"] \
+ -message [mc "Raised error during md5 checking file %s. Maybe md5 extension is not correctly loaded." $file_name]
+ }
+
+ # Open the file
+ if {[openfile $file_path$file_name 0 . $enc $eol $ro 0 $sh] != {}} {
+ set i [llength $editors]
+ incr i -1
+ set editor [lindex $editors $i]
+ rightPanel_switch_editor $i
+ $this todo_switch_editor $i
+ $editor import_line_markers_data $file_BMs $file_BPs
+ $editor goto $file_line
+ switch_to_last
+ incr i
+
+ $this set_file_notes_data $notes
+ }
+
+ # Adjust listbox of opened files
+ $listbox_project_files itemconfigure $item \
+ -font $opened_file_font -fg {#000000} -data [list $file_path$file_name $eol $enc $ro]
+
+ # Reevaluate iconbar
+ FileList_project_disEna_buttons
+ }
+
+ ## Close file in ListBox of project files
+ # @return void
+ public method filelist_project_file_close {} {
+ # Determinate filename
+ set item [$listbox_project_files selection get]
+ set filename [$listbox_project_files itemcget $item -data]
+ if {[llength $filename] > 4} {return}
+
+ # Determinate editor index
+ set filename [lindex $filename 0]
+ set idx 0
+ foreach editor $editors {
+ if {[$editor cget -fullFileName] == $filename} {break}
+ incr idx
+ }
+
+ # Close the editor
+ editor_close 1 $idx
+ FileList_project_disEna_buttons
+ }
+
+ ## Remove file from the project ListBox
+ # @return void
+ public method filelist_remove_file_from_project {} {
+ # Determinate item ID
+ set item [$listbox_project_files selection get]
+ set index [$listbox_project_files index $item]
+ # Remove item from the ListBox
+ $listbox_project_files delete $item
+ # Remove item from icon border and list of bookmarks
+ $listbox_project_files_bm delete [expr {$index + 1}].0 [expr {$index + 2}].0
+ set project_files_bookmarks [lreplace $project_files_bookmarks $index $index]
+ # Select the next item
+ set end [llength [$listbox_project_files items]]
+ incr end -1
+ if {$index > $end} {
+ set index $end
+ }
+ if {$index != -1} {
+ $listbox_project_files selection set \
+ [$listbox_project_files items $index]
+ }
+ # Reevaluate icon bar
+ FileList_project_disEna_buttons
+ }
+
+ ## Append the current file to the project
+ # @return void
+ public method filelist_append_to_prj {} {
+ # Index of the current file
+ set idx [lsearch $file_descriptors [$listbox_opened_files selection get]]
+ # Reference to editor object
+ set editor [lindex $editors $idx]
+
+ # Check if the file isn't already part of the project
+ set fullFileName [$editor cget -fullFileName]
+ if {$fullFileName == {} || [getItemNameFromProjectList $fullFileName] != {}} {
+ return
+ }
+
+ # Adjust ListBox of project files
+ $listbox_project_files insert end #auto \
+ -font $opened_file_font \
+ -fg {#000000} \
+ -text [$editor cget -filename] \
+ -data [list $fullFileName \
+ [lindex $file_eol $idx] \
+ [lindex $file_encoding $idx] \
+ [lindex $file_ro_mode $idx] \
+ ]
+
+ # Adjust icon border
+ if {[llength $project_files_bookmarks]} {
+ $listbox_project_files_bm insert end "\n"
+ }
+ lappend project_files_bookmarks 0
+
+ }
+
+ ## Translate full filename to item ID (in project files ListBox)
+ # @parm String fullFileName - full file name
+ # @return String - item ID or '{}'
+ private method getItemNameFromProjectList {fullFileName} {
+ # Get list of project file items
+ set items [$listbox_project_files items]
+
+ # Search for the given filename
+ foreach item $items {
+ # Determinate item data
+ set data [$listbox_project_files itemcget $item -data]
+
+ # Opened file
+ if {[llength $data] < 5} {
+ if {[lindex $data 0] == $fullFileName} {
+ return $item
+ }
+
+ # Unopened file
+ } {
+ if { "[lindex $data 5][lindex $data 0]" == $fullFileName} {
+ return $item
+ }
+ }
+ }
+
+ # Failed
+ return {}
+ }
+
+ ## Change encoding in the current editor
+ # @return void
+ public method change_encoding {} {
+ if {$splitted && $selectedView} {
+ set idx $actualEditor2
+ } {
+ set idx $actualEditor
+ }
+ if {[lindex $file_encoding $idx] == ${::editor_encoding}} {
+ return
+ }
+
+ # Configure editor
+ set original_encoding [lindex $file_encoding $idx]
+ lset file_encoding $idx ${::editor_encoding}
+ [lindex $editors $idx] configure -encoding ${::editor_encoding}
+ if {![filelist_reload_file]} {
+ set ::editor_encoding $original_encoding
+ lset file_encoding $idx $original_encoding
+ [lindex $editors $idx] configure -encoding $original_encoding
+ } {
+ # Configure list of project files
+ set filename [[lindex $editors $idx] cget -fullFileName]
+ foreach item [$listbox_project_files items] {
+ set data [$listbox_project_files itemcget $item -data]
+ if {[lindex $data 0] == $filename} {
+ lset data 2 ${::editor_encoding}
+ $listbox_project_files itemconfigure $item -data $data
+ break
+ }
+ }
+ }
+ }
+
+ ## Change EOL in the current editor
+ # @return void
+ public method change_EOL {} {
+ if {$splitted && $selectedView} {
+ set idx $actualEditor2
+ } {
+ set idx $actualEditor
+ }
+ if {[lindex $file_eol $idx] == ${::editor_EOL}} {
+ return
+ }
+
+ # Configure editor
+ lset file_eol $idx ${::editor_EOL}
+ [lindex $editors $idx] configure -eol ${::editor_EOL}
+
+ # Configure list of project files
+ set filename [[lindex $editors $idx] cget -fullFileName]
+ foreach item [$listbox_project_files items] {
+ set data [$listbox_project_files itemcget $item -data]
+ if {[lindex $data 0] == $filename} {
+ lset data 1 ${::editor_EOL}
+ $listbox_project_files itemconfigure $item -data $data
+ break
+ }
+ }
+ }
+
+ ## Change RO mode in the current editor
+ # @return void
+ public method switch_editor_RO_MODE {} {
+ if {$splitted && $selectedView} {
+ set idx $actualEditor2
+ } {
+ set idx $actualEditor
+ }
+ if {[lindex $file_ro_mode $idx] == ${::editor_RO_MODE}} {
+ return
+ }
+
+ # Configure editor
+ lset file_ro_mode $idx ${::editor_RO_MODE}
+ [lindex $editors $idx] change_RO_MODE ${::editor_RO_MODE}
+
+ # Configure list of project files
+ set filename [[lindex $editors $idx] cget -fullFileName]
+ foreach item [$listbox_project_files items] {
+ set data [$listbox_project_files itemcget $item -data]
+
+ # Unknown bug workaround :-(
+ if {[llength $data] < 4} {
+ puts "data == {$data}" ;# Dump
+ lappend data {}
+ }
+
+ if {[lindex $data 0] == $filename} {
+ lset data 3 ${::editor_RO_MODE}
+ $listbox_project_files itemconfigure $item -data $data
+ break
+ }
+ }
+ }
+
+ ## Adjust scrollbar for listbox of opened files
+ # @parm Float frac0 - 1st fraction
+ # @parm Float frac0 - 2nd fraction
+ # @return void
+ public method filelist_o_scrollbar_set {frac0 frac1} {
+ # Hide scrollbar
+ if {$frac0 == 0 && $frac1 == 1} {
+ if {$o_scrollbar_visible} {
+ pack forget $opened_files_scrollbar
+ set o_scrollbar_visible 0
+ }
+ # Show scrollbar
+ } {
+ if {!$o_scrollbar_visible} {
+ pack $opened_files_scrollbar \
+ -side left \
+ -fill y \
+ -before $listbox_opened_files_bm
+ set o_scrollbar_visible 1
+ }
+ # Adjust icon border
+ $listbox_opened_files_bm yview moveto $frac0
+ # Adjust scrollbar
+ $opened_files_scrollbar set $frac0 $frac1
+ }
+ }
+
+ ## Scroll synchronously listbox of opened files and its icon border
+ # @parm List - arguments for subcommand yview
+ # @return void
+ public method filelist_o_scroll args {
+ eval "$listbox_opened_files yview $args"
+ eval "$listbox_opened_files_bm yview $args"
+ }
+
+ ## Adjust scrollbar for listbox of opened files
+ # @parm Float frac0 - 1st fraction
+ # @parm Float frac0 - 2nd fraction
+ # @return void
+ public method filelist_p_scrollbar_set {frac0 frac1} {
+ # Hide scrollbar
+ if {$frac0 == 0 && $frac1 == 1} {
+ if {$p_scrollbar_visible} {
+ pack forget $project_files_scrollbar
+ set p_scrollbar_visible 0
+ }
+ # Show scrollbar
+ } {
+ if {!$p_scrollbar_visible} {
+ pack $project_files_scrollbar \
+ -side left \
+ -fill y \
+ -before $listbox_project_files_bm
+ set p_scrollbar_visible 1
+ }
+ # Adjust icon border
+ $listbox_project_files_bm yview moveto $frac0
+ # Adjust scrollbar
+ $project_files_scrollbar set $frac0 $frac1
+ }
+ }
+
+ ## Scroll synchronously listbox of project files and its icon border
+ # @parm List - arguments for subcommand yview
+ # @return void
+ public method filelist_p_scroll args {
+ eval "$listbox_project_files yview $args"
+ eval "$listbox_project_files_bm yview $args"
+ }
+
+ ## Validator function for search entry in tab of opened files
+ # @parm String content - String which to search for (in listbox of opened files)
+ # @return Bool - always 1
+ public method filelist_opened_search {content} {
+ # Empty input string
+ if {$content == {}} {
+ $opened_search_clear_button configure -state disabled
+ $opened_search_entry configure -style TEntry
+ opened_files_unhighlight_item
+ return 1
+ }
+
+ # Enable clear button
+ $opened_search_clear_button configure -state normal
+
+ # Search the listbox
+ foreach item [$listbox_opened_files items] {
+ if {![string first $content [$listbox_opened_files itemcget $item -text]]} {
+ $opened_search_entry configure -style StringFound.TEntry
+ opened_files_highlight_item $item
+ return 1
+ }
+ }
+
+ # Search failed
+ $opened_search_entry configure -style StringNotFound.TEntry
+ return 1
+ }
+
+
+ ## Highlight item in listbox of opened files
+ # @parm String item - item ID
+ # @return void
+ private method opened_files_highlight_item {item} {
+ opened_files_unhighlight_item
+ set opened_files_highlighted_item $item
+ set opened_files_hg_item_fg_clr [$listbox_opened_files itemcget $item -fg]
+ $listbox_opened_files itemconfigure $item -indent 10 -fg {#00DD00}
+ $listbox_opened_files see $item
+ }
+
+ ## Clear highlightion for currently highlighted item in listbox of opened files
+ # @return void
+ private method opened_files_unhighlight_item {} {
+ # If no item highlighted -> abort
+ if {$opened_files_highlighted_item == {}} {
+ return
+ }
+
+ # Unhighlight item
+ $listbox_opened_files itemconfigure \
+ $opened_files_highlighted_item \
+ -indent 0 -fg $opened_files_hg_item_fg_clr
+ set opened_files_hg_item_fg_clr {}
+ set opened_files_highlighted_item {}
+ }
+
+ ## Validator function for search entry in tab of project files
+ # @parm String content - String which to search for (in listbox of project files)
+ # @return Bool - always 1
+ public method filelist_project_search {content} {
+ # Empty input string
+ if {$content == {}} {
+ $project_search_clear_button configure -state disabled
+ $project_search_entry configure -style TEntry
+ project_files_unhighlight_item
+ return 1
+ }
+
+ # Enable clear button
+ $project_search_clear_button configure -state normal
+
+ # Search the listbox
+ foreach item [$listbox_project_files items] {
+ if {![string first $content [$listbox_project_files itemcget $item -text]]} {
+ $project_search_entry configure -style StringFound.TEntry
+ project_files_highlight_item $item
+ return 1
+ }
+ }
+
+ # Search failed
+ $project_search_entry configure -style StringNotFound.TEntry
+ return 1
+ }
+
+ ## Highlight item in listbox of project files
+ # @parm String item - item ID
+ # @return void
+ private method project_files_highlight_item {item} {
+ project_files_unhighlight_item
+ set project_files_highlighted_item $item
+ set project_files_hg_item_fg_clr [$listbox_project_files itemcget $item -fg]
+ $listbox_project_files itemconfigure $item -indent 10 -fg {#00DD00}
+ $listbox_project_files see $item
+ }
+
+ ## Clear highlightion for currently highlighted item in listbox of project files
+ # @return void
+ private method project_files_unhighlight_item {} {
+ # If no item highlighted -> abort
+ if {$project_files_highlighted_item == {}} {
+ return
+ }
+
+ # Unhighlight item
+ $listbox_project_files itemconfigure \
+ $project_files_highlighted_item \
+ -indent 0 -fg $project_files_hg_item_fg_clr
+ set project_files_hg_item_fg_clr {}
+ set project_files_highlighted_item {}
+ }
+
+ ## Binding for virtual event '<<ListboxSelect>>' for listbox of project files
+ # Clear search entry and unhighlight currently highlighted item (if any)
+ # @return void
+ public method project_files_listbox_select {} {
+ $project_search_entry delete 0 end
+ $this FileList_project_disEna_buttons
+ }
+
+ ## Add/Remove bookmark to/from item in listbox of opened files
+ # @parm Int x - Relative position in icon border (X axis)
+ # @parm Int y - Relative position in icon border (Y axis)
+ # @return void
+ public method filelist_opened_bookmark_xy {x y} {
+ opened_files_bookmark [expr {int([$listbox_opened_files_bm index @$x,$y]) - 1}]
+ }
+
+ ## Add/Remove bookmark to/from item in listbox of opened files
+ # Affects currently selected item
+ # @return void
+ public method filelist_o_bookmark {} {
+ opened_files_bookmark [$listbox_opened_files index \
+ [$listbox_opened_files selection get]]
+ }
+
+ ## Add/Remove bookmark to/from item in listbox of opened files
+ # @parm Int line - Target line (begins from zero)
+ # @return void
+ public method opened_files_bookmark {line} {
+ # Check for allowed range
+ if {$line >= [llength $opened_files_bookmarks]} {
+ return
+ }
+
+ set page [lindex [$listbox_opened_files items] $line]
+
+ # Remove bookmark
+ if {[lindex $opened_files_bookmarks $line]} {
+ lset opened_files_bookmarks $line 0
+ incr line
+ $listbox_opened_files_bm delete $line.0 [list $line.0 lineend]
+
+ set ext [string trimleft [file extension [$listbox_opened_files itemcget $page -text]] {.}]
+ if {$ext == {h}} {
+ set icon {source_h}
+ } elseif {$ext == {c}} {
+ set icon {source_c}
+ } elseif {$ext == {cxx} || $ext == {cpp} || $ext == {cc}} {
+ set icon {source_cpp}
+ } elseif {$ext == {asm}} {
+ set icon {asm}
+ } else {
+ set icon {ascii}
+ }
+ $filetabs_nb itemconfigure $page -image ::ICONS::16::$icon
+
+ # Add bookmark
+ } {
+ lset opened_files_bookmarks $line 1
+ incr line
+ $listbox_opened_files_bm image create $line.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+
+ $filetabs_nb itemconfigure $page -image ::ICONS::16::bookmark
+ }
+
+ $listbox_opened_files_bm tag add center 0.0 end
+ }
+
+ ## Invoke icon border popup menu -- list of opened files
+ # @parm Int x - Abolute position in icon border (X axis)
+ # @parm Int y - Abolute position in icon border (Y axis)
+ # @parm Int x - Relative position in icon border (X axis)
+ # @parm Int y - Relative position in icon border (Y axis)
+ # @return void
+ public method filelist_opened_bm_popup_menu {X Y x y} {
+ set pmenu_cline [expr {int([$listbox_opened_files_bm index @$x,$y]) - 1}]
+ set bookmark [lindex $opened_files_bookmarks $pmenu_cline]
+ tk_popup $IB_o_menu $X $Y
+ }
+
+ ## Add/Remove bookmark to/from item in listbox of project files
+ # @parm Int x - Relative position in icon border (X axis)
+ # @parm Int y - Relative position in icon border (Y axis)
+ # @return void
+ public method filelist_project_bookmark_xy {x y} {
+ project_files_bookmark [expr {int([$listbox_project_files_bm index @$x,$y]) - 1}]
+ }
+
+ ## Add/Remove bookmark to/from item in listbox of project files
+ # Affects currently selected item
+ # @return void
+ public method filelist_p_bookmark {} {
+ project_files_bookmark [$listbox_project_files index \
+ [$listbox_project_files selection get]]
+ }
+
+ ## Add/Remove bookmark to/from item in listbox of project files
+ # @parm Int line - Target line (begins from zero)
+ # @return void
+ public method project_files_bookmark {line} {
+ # Check for allowed range
+ if {($line < 0) || ($line >= [llength $project_files_bookmarks])} {
+ return
+ }
+
+ # Remove bookmark
+ if {[lindex $project_files_bookmarks $line]} {
+ lset project_files_bookmarks $line 0
+ incr line
+ $listbox_project_files_bm delete $line.0 [list $line.0 lineend]
+ # Add bookmark
+ } {
+ lset project_files_bookmarks $line 1
+ incr line
+ $listbox_project_files_bm image create $line.0 \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+
+ $listbox_project_files_bm tag add center 0.0 end
+ }
+
+ ## Invoke icon border popup menu -- list of project files
+ # @parm Int x - Abolute position in icon border (X axis)
+ # @parm Int y - Abolute position in icon border (Y axis)
+ # @parm Int x - Relative position in icon border (X axis)
+ # @parm Int y - Relative position in icon border (Y axis)
+ # @return void
+ public method filelist_project_bm_popup_menu {X Y x y} {
+ set pmenu_cline [expr {int([$listbox_project_files_bm index @$x,$y]) - 1}]
+ set bookmark [lindex $project_files_bookmarks $pmenu_cline]
+ tk_popup $IB_p_menu $X $Y
+ }
+
+ ## Clear flag "command line on"
+ # @return void
+ public method cmd_line_off {} {
+ set editor_command_line_on 0
+ if {$splitted} {
+ [lindex $editors $actualEditor2] cmd_line_force_off
+ }
+ [lindex $editors $actualEditor] cmd_line_force_off
+ }
+
+ ## Set flag "command line on"
+ # All editors in current project will focus on command line
+ # @return void
+ public method cmd_line_on {} {
+ set editor_command_line_on 1
+ if {$splitted} {
+ [lindex $editors $actualEditor2] cmd_line_force_on
+ }
+ [lindex $editors $actualEditor] cmd_line_force_on
+
+ if {$splitted && $selectedView} {
+ [lindex $editors $actualEditor2] cmd_line_focus 1
+ } {
+ [lindex $editors $actualEditor] cmd_line_focus 1
+ }
+ }
+
+ ## Split editor vertical
+ # @return void
+ public method split_vertical {} {
+ split_editor 1
+ }
+
+ ## Split editor horizontal
+ # @return void
+ public method split_horizontal {} {
+ split_editor 0
+ }
+
+ ## Close current view (if editor is splitted)
+ # If editor is already splitted this procedure will do nothing
+ # @return void
+ public method close_current_view {editor_object} {
+ if {!$splitted} {return}
+
+ # Save current sash position
+ if {$pwin_orient == {vertical}} {
+ set idx 1
+ } {
+ set idx 0
+ }
+ set multiview_sash_pos [lindex [$multiview_paned_win sash coord 0] $idx]
+
+ # Unmap paned window and the second pages manager and remap the first pages manager
+ $multiview_paned_win forget $pagesManager2
+ $multiview_paned_win forget $pagesManager
+ pack forget $multiview_paned_win
+ pack $pagesManager -fill both -expand 1
+
+ # Configure all editor status bar popup menus
+ foreach editor $editors {
+ $editor configure_statusbar_menu 1 0 {} {}
+ }
+
+ # Determinate which editor will be visible now
+ if {$editor_object != {}} {
+ set editor_object [lsearch $editors $editor_object]
+ if {$editor_object == $actualEditor2} {
+ set selectedView 1
+ } {
+ set selectedView 0
+ }
+ }
+
+ # Insure than the choosen editor (see above) is (in)visible
+ if {!$selectedView} {
+ $listbox_opened_files selection set [lindex $file_descriptors $actualEditor2]
+ }
+ set selectedView 0
+ set splitted 0
+ set actualEditor2 -1
+ switchfile
+ }
+
+ ## Syntax highlight changed from editor
+ # @parm Object editor_object - New active editor object reference
+ # @parm Int lang - -1 == unknown; 0 == Assembly language; 1 == C language
+ # @return void
+ public method filelist_editor_sh_changed {editor_object lang} {
+ lset file_sh [lsearch $editors $editor_object] $lang
+ }
+
+ ## Change active view if editor is splitted
+ # If editor is already splitted this procedure will do nothing
+ # @parm Object editor_object - New active editor object reference
+ # @return void
+ public method filelist_editor_selected {editor_object} {
+ if {!$splitted} {return}
+
+ # Search for the given object
+ set idx [lsearch $editors $editor_object]
+ if {$idx == $actualEditor} {
+ set selectedView 0
+ } elseif {$idx == $actualEditor2} {
+ set selectedView 1
+ }
+ rightPanel_switch_editor_vars $idx
+ $this todo_switch_editor_vars $idx
+
+ # Adjust selection in list of opened files
+ set item [lindex $file_descriptors $idx]
+ $listbox_opened_files selection set $item
+ catch {$listbox_opened_files itemconfigure $lastItem -image {}}
+ $listbox_opened_files itemconfigure $item -image ::ICONS::16::2_rightarrow
+ set lastItem $item
+
+ update
+ $filetabs_nb raise [lindex $file_descriptors $idx]
+ $filetabs_nb see [lindex $file_descriptors $idx]
+ rightPanel_switch_page $idx
+ $this todo_switch_editor $idx
+ listBox_disEna_buttons $item $editor_object
+ ::X::adjust_title
+ ::X::adjust_mainmenu_and_toolbar_to_editor \
+ ${::editor_RO_MODE} [expr {[$editor_object get_language] == 1}]
+ }
+
+ ## Split editor vertical or horizontal
+ # If editor is already splitted this procedure will do nothing
+ # @parm Bool vert_or_horz - 1 == Vertical; 0 == Horizontal
+ # @return void
+ private method split_editor {vert_or_horz} {
+ if {$splitted} {return}
+
+ # Determinate orientation
+ if {$vert_or_horz} {
+ set pwin_orient {horizontal}
+ } {
+ set pwin_orient {vertical}
+ }
+ $multiview_paned_win configure -orient $pwin_orient
+
+ # Validate sash position
+ if {!$multiview_sash_pos} {
+ set multiview_sash_pos [expr {[winfo width $pagesManager] / 2}]
+ }
+
+ # Unmap current pages manager and remap it with the second one into paned window
+ pack forget $pagesManager
+ pack $multiview_paned_win -fill both -expand 1
+ $multiview_paned_win add $pagesManager
+ $multiview_paned_win add $pagesManager2 -after $pagesManager
+
+ # Configure minimum size for panes
+ if {$vert_or_horz} {
+ set minsize 300
+ } {
+ set minsize 80
+ }
+ $multiview_paned_win paneconfigure $pagesManager -minsize $minsize
+ $multiview_paned_win paneconfigure $pagesManager2 -minsize $minsize
+
+ # Move paned window sash
+ update idle
+ if {$pwin_orient == {vertical}} {
+ $multiview_paned_win sash place 0 0 $multiview_sash_pos
+ } {
+ $multiview_paned_win sash place 0 $multiview_sash_pos 0
+ }
+
+ # Configure status bar popup menu for all opened editors
+ foreach editor $editors {
+ $editor configure_statusbar_menu 0 1 {} {}
+ }
+
+ # Show up some editor in the second view
+ set splitted 1
+ set selectedView 0
+ set len [llength $file_descriptors]
+ if {$len > 1} {
+ if {$actualEditor < ($len - 1)} {
+ set actualEditor2 [expr {$actualEditor + 1}]
+ } {
+ set actualEditor2 0
+ }
+ } {
+ set selectedView 1
+ editor_new
+ set selectedView 0
+ }
+ pack [[lindex $editors $actualEditor2] cget -ed_sc_frame] \
+ -in $pagesManager2 -fill both -expand 1
+ }
+
+ ## Sort items in list of opened files or project files
+ # @parm Char by - {S} == Size; {U} == URL; {N} == Name
+ # @parm Bool opened_project - 1 == List of opened files; 0 == List of project files
+ # @return void
+ public method sort_file_list {by opened_project} {
+ if {$opened_project} {
+ set listbox $listbox_opened_files
+ set bookmarks_text $listbox_opened_files_bm
+ set bookmarks_var {opened_files_bookmarks}
+ } {
+ set listbox $listbox_project_files
+ set bookmarks_text $listbox_project_files_bm
+ set bookmarks_var {project_files_bookmarks}
+ }
+
+ # Determinate list of values (strings or integers) to sort
+ set items {} ;# List of values to sort
+ set num_of_items 0 ;# Length of items
+ foreach item [$listbox items] {
+ switch -- $by {
+ {N} { ;# For sorting by name
+ lappend items [$listbox itemcget $item -text]
+ }
+ {U} { ;# For sorting by URL
+ set data [$listbox itemcget $item -data]
+ if {!$opened_project} {
+ # Unopened file
+ if {[llength $data] > 4} {
+ set data [lindex $data 5]
+
+ # Opened file
+ } {
+ set data [lindex $data 0]
+ }
+ }
+ lappend items $data
+ }
+ {S} { ;# For sorting by size
+ set path [$listbox itemcget $item -data]
+ if {!$opened_project} {
+ # Unopened file
+ if {[llength $path] > 4} {
+ set path [lindex $path 5]
+
+ # Opened file
+ } {
+ set path [lindex $path 0]
+ }
+ }
+ set size 0
+ catch {
+ set size [file size $path]
+ }
+ lappend items $size
+ }
+ }
+ incr num_of_items
+ }
+
+ # List of item indexes in new order (e.g. {0 2 1 3 4 5 7 6})
+ set new_order {}
+ for {set i 0} {$i < $num_of_items} {incr i} {
+ lappend new_order $i
+ }
+
+ ## Sort lists items and new_order using Bouble Sort
+ # By name of URL (string comparison)
+ if {$by == {N} || $by == {U}} {
+ for {set i 1} {$i < $num_of_items} {incr i} {
+ for {set j 1; set k 0} {$j < $num_of_items} {incr j; incr k} {
+ if {[string compare [lindex $items $k] [lindex $items $j]] < 0} {
+ set tmp [lindex $items $k]
+ lset items $k [lindex $items $j]
+ lset items $j $tmp
+
+ set tmp [lindex $new_order $k]
+ lset new_order $k [lindex $new_order $j]
+ lset new_order $j $tmp
+ }
+ }
+ }
+ # By size (integer comparison)
+ } {
+ for {set i 1} {$i < $num_of_items} {incr i} {
+ for {set j 1; set k 0} {$j < $num_of_items} {incr j; incr k} {
+ if {[lindex $items $k] > [lindex $items $j]} {
+ set tmp [lindex $items $k]
+ lset items $k [lindex $items $j]
+ lset items $j $tmp
+
+ set tmp [lindex $new_order $k]
+ lset new_order $k [lindex $new_order $j]
+ lset new_order $j $tmp
+ }
+ }
+ }
+ }
+
+ # Reorder list of bookmarks and
+ #+ determinate list of item descriptors in the new order.
+ #+ No GUI will be affected
+ set new_items_order {}
+ set bookmarks_new {}
+ set bookmarks_org [subst "\$$bookmarks_var"]
+ for {set i 0} {$i < $num_of_items} {incr i} {
+ set idx [lindex $new_order $i]
+ lappend new_items_order [$listbox items $idx]
+ lappend bookmarks_new [lindex $bookmarks_org $idx]
+ }
+ set $bookmarks_var $bookmarks_new
+
+ # Adjust GUI to the new order
+ $listbox reorder $new_items_order
+ $bookmarks_text delete 1.0 end
+ foreach bm $bookmarks_new {
+ if {$bm} {
+ $bookmarks_text image create insert \
+ -image ::ICONS::16::bookmark \
+ -align center
+ }
+ $bookmarks_text insert end "\n"
+ }
+ }
+
+ ## Open selected file with an external editor
+ # @parm Bool o_p - 1 == opened file; 0 == project file
+ # @parm String command - Command to execute the editor
+ # @return void
+ public method filelist_open_with {o_p command} {
+ # Determinate filename
+ if {$o_p} {
+ set item [$listbox_opened_files selection get]
+ if {![$listbox_opened_files exists $item]} {
+ return
+ }
+ set filename [$listbox_opened_files itemcget $item -data]
+ } {
+ set item [$listbox_project_files selection get]
+ if {![$listbox_project_files exists $item]} {
+ return
+ }
+ set data [$listbox_project_files itemcget $item -data]
+ if {[llength $data] < 5} {
+ set filename [lindex $data 0]
+ } {
+ set filename "[lindex $data 5][lindex $data 0]"
+ }
+ }
+
+ # Adjust editor command
+ if {$command == {other}} {
+ set command [open_with_other]
+ }
+ if {$command == {}} {
+ return
+ }
+
+ # Start external editor
+ if {[catch {
+ exec $command "$filename" &
+ }]} {
+ tk_messageBox \
+ -parent . \
+ -icon error \
+ -type ok \
+ -title [mc "Program not found"] \
+ -message [mc "Unable to execute \"%s\"" $command]
+ }
+ }
+
+ ## Open dialog "Open with other editor" and return text entered by user
+ # @return String - Command which executes exernal editor
+ private method open_with_other {} {
+ set ::FileList::open_with_cnfr 0
+
+ # Create toplevel window
+ set win [toplevel .open_with_other_dlg -class {Open with ...} -bg {#EEEEEE}]
+
+ # Create label, entryBox and horizontal separator
+ pack [label $win.lbl -text [mc "Enter command to execute:"]] -fill x -anchor w -padx 5
+ pack [ttk::entry $win.ent \
+ -textvariable ::FileList::open_with \
+ -width 0 \
+ ] -fill x -padx 10 -anchor w
+# pack [ttk::separator $win.sep -orient horizontal] -fill x -padx 5 -pady 10
+
+ bind $win.ent <Return> "grab release $win; destroy $win"
+ bind $win.ent <KP_Enter> "grab release $win; destroy $win"
+
+ # Create button frame
+ set buttonFrame [frame $win.buttonFrame]
+ pack [ttk::button $buttonFrame.ok \
+ -text [mc "Ok"] \
+ -compound left \
+ -image ::ICONS::16::ok \
+ -command "
+ set ::FileList::open_with_cnfr 1
+ grab release $win
+ destroy $win
+ " \
+ ] -side left
+ pack [ttk::button $buttonFrame.cancel \
+ -text [mc "Cancel"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command "
+ grab release $win
+ destroy $win
+ " \
+ ] -side left
+ pack $buttonFrame -side bottom -padx 5 -pady 5 -anchor e
+
+ # Set window attributes
+ wm iconphoto $win ::ICONS::16::terminal
+ wm title $win [mc "Open with other ..."]
+ wm minsize $win 320 80
+ wm transient $win .
+ catch {grab $win}
+ wm protocol $win WM_DELETE_WINDOW "
+ grab release $win
+ destroy $win
+ "
+ raise $win
+ update
+ $win.ent selection range 0 end
+ focus $win.ent
+ tkwait window $win
+
+ # Return result
+ if {${::FileList::open_with_cnfr}} {
+ return ${::FileList::open_with}
+ } {
+ return {}
+ }
+ }
+
+ ## Kill childern
+ # @return void
+ public method filelist_kill_childern {} {
+ foreach editor $editors {
+ $editor kill_childern
+ }
+ }
+
+ ## Focus and conditionaly open editor with the specified filename
+ # @parm String filename - Name of file
+ # @parm Bool suppress_error - Suppress error messages
+ # @return Bool - 1 == Success; 0 == Fail
+ public method fucus_specific_editor {filename suppress_error} {
+
+ # Search list of opened files
+ foreach item [$listbox_opened_files items] {
+ if {$filename == [$listbox_opened_files itemcget $item -text]} {
+ $listbox_opened_files selection set $item
+ switchfile
+ return 1
+ }
+ }
+ # Search list of project files
+ foreach item [$listbox_project_files items] {
+ if {$filename == [$listbox_project_files itemcget $item -text]} {
+ $listbox_project_files selection set $item
+ filelist_project_file_open
+ return 1
+ }
+ }
+
+ # Display error message
+ if {!$suppress_error} {
+ tk_messageBox \
+ -parent . \
+ -type ok \
+ -icon warning \
+ -title [mc "File not found"] \
+ -message [mc "Unable to find \"%s\" in list of opened files or project files" $filename]
+ }
+ return 0
+ }
+
+ ## Move simulator pointer in editor
+ # - Switch to specified editor and go to specified line
+ # @parm List line_info - Line information number {Line_number File_number}
+ # @retun void
+ public method move_simulator_line {line_info} {
+ set line_number [lindex $line_info 0]
+ set file_number [lindex $line_info 1]
+
+ if {$line_number == {}} {
+ return
+ }
+
+ if {[$this cget -programming_language]} {
+ $this cvarsview_load_local_variables [lindex $line_info 2] [lindex $line_info 3]
+ }
+
+ # Switch file
+ if {$file_number != {} && $simulator_editor != $file_number} {
+ # Gain target file name
+ set file_name [$this simulator_get_filename $file_number]
+
+ # Search for the given file and try to switch to it
+ if {$file_switching_enabled || $simulator_editor == -1} {
+ foreach item [$listbox_opened_files items] {
+ if {$file_name != [$listbox_opened_files itemcget $item -data]} {
+ continue
+ }
+
+ $listbox_opened_files selection set $item
+ if {$simulator_editor_obj != {}} {
+ $simulator_editor_obj disable
+ $listbox_opened_files itemconfigure [lindex \
+ $file_descriptors [lsearch -ascii -exact \
+ $editors $simulator_editor_obj \
+ ] \
+ ] -fg {#000000}
+ }
+ $listbox_opened_files itemconfigure $item -fg {#FF0000}
+ set simulator_editor_obj [lindex $editors \
+ [lsearch -ascii -exact $file_descriptors $item] \
+ ]
+ $simulator_editor_obj freeze
+ $simulator_editor_obj move_simulator_line $line_number
+ switchfile
+ set simulator_editor $file_number
+ return
+ }
+ }
+ Sbar [mc "Simulator: unable to switch to file: '%s'" $file_name]
+
+ # Move simulator pointer directly
+ } elseif {$simulator_editor_obj != {}} {
+ $simulator_editor_obj move_simulator_line $line_number
+ }
+ }
+
+ ## Get editor object used by simulator
+ # @return Object - Editor object
+ public method filelist_get_simulator_editor_obj {} {
+ return $simulator_editor_obj
+ }
+
+ ## Set "auto file switch" lock
+ # @parm Object from_obj - Editor object from which this procedure is called
+ # @parm Bool new_state - New state of the lock
+ # @return void
+ public method set_editor_lock {from_obj new_state} {
+ foreach editor $editors {
+ if {$editor == $from_obj} {
+ continue
+ }
+ $editor set_lock $new_state
+ }
+ set file_switching_enabled [expr {!$new_state}]
+ }
+
+ ## Get value of "auto file switch lock"
+ # This lock disables automatic file switching during sumulation
+ # @return Bool - 1 == unlocked; 0 == locked
+ public method get_file_switching_enabled {} {
+ return $file_switching_enabled
+ }
+
+ ## Redraw panel pane
+ # @return void
+ public method leftpanel_redraw_pane {} {
+ update idle
+ if {$PanelVisible != 0} {
+ $parent sash place 0 $PanelSize 0
+ }
+ }
+
+ ## Get object reference for the current editor
+ # @return Object - Active editor
+ public method get_current_editor_object {} {
+ if {$splitted && $selectedView} {
+ set editor_num $actualEditor2
+ } {
+ set editor_num $actualEditor
+ }
+ return [lindex $editors $editor_num]
+ }
+
+ ## Show or hide the tab bar
+ # @return void
+ public method show_hide_tab_bar {} {
+ # Show
+ if {${::CONFIG(SHOW_EDITOR_TAB_BAR)}} {
+ if {![winfo ismapped $filetabs_frm]} {
+ if {$splitted} {
+ set before $multiview_paned_win
+ } {
+ set before $pagesManager
+ }
+ pack $filetabs_frm -fill x -before $before
+
+ filelist_adjust_size_of_tabbar
+ }
+ # Hide
+ } {
+ if {[winfo ismapped $filetabs_frm]} {
+ pack forget $filetabs_frm
+ }
+ }
+ }
+
+ ## Special purpose method (see the usage in the code)
+ # It should be used to ensure that the height of the tab bat is not too big
+ # @return void
+ public method filelist_adjust_size_of_tabbar {} {
+ $filetabs_nb see [lindex [$filetabs_nb pages] 0]
+ update
+ catch {
+ $filetabs_nb.c configure -height 20
+ }
+ $filetabs_nb see [$filetabs_nb raise]
+
+ # Keep editor nice after adjustment of filestab height
+ if {!${::Editor::editor_to_use}} {
+ [get_current_editor_object] scroll scroll +0 lines
+ }
+ }
+
+ ## Call method Configure in both editors
+ # @return void
+ public method ensure_that_both_editors_are_properly_initialized {} {
+ if {$splitted} {
+ update
+ [lindex $editors $actualEditor] Configure
+ [lindex $editors $actualEditor2] Configure
+ }
+ }
+}
+set ::FileList::ask__append_file_to_project ${::CONFIG(ASK_ON_FILE_OPEN)}
diff --git a/lib/leftpanel/fsbrowser.tcl b/lib/leftpanel/fsbrowser.tcl
new file mode 100755
index 0000000..0a28d82
--- /dev/null
+++ b/lib/leftpanel/fsbrowser.tcl
@@ -0,0 +1,1164 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Implements file system browser for the left panel
+# --------------------------------------------------------------------------
+
+class FSBrowser {
+
+ # Definition of popup menu for filesystem browser, part: configure
+ common FSMENU_CONFIGURE {
+ {cascade "Sorting" 0 "" .sorting false 1 {
+ {radiobutton "By Name" "" {::KIFSD::FSD::config(sorting)}
+ {name} {filelist_fsb_reload} 3
+ "Sort files by name"}
+ {radiobutton "By Date" "" {::KIFSD::FSD::config(sorting)}
+ {date} {filelist_fsb_reload} 3
+ "Sort files by date"}
+ {radiobutton "By Size" "" {::KIFSD::FSD::config(sorting)}
+ {size} {filelist_fsb_reload} 3
+ "Sort files by size"}
+ {separator}
+ {checkbutton "Reverse" ""
+ {::KIFSD::FSD::config(reverse_sorting)} 1 0 0
+ {filelist_fsb_reload} "Decremental sorting"}
+ {checkbutton "Case insensitive" ""
+ {::KIFSD::FSD::config(case_insensitive)} 1 0 0
+ {filelist_fsb_reload} "Sorting mode ASCII / Dictionary"}
+ }}
+ {checkbutton "Show hidden files" ""
+ {::KIFSD::FSD::config(show_hidden_files)} 1 0 5
+ {filelist_fsb_reload} "Show / Ignore files starting with dot"}
+ }
+
+ # Definition of popup menu for filesystem browser, part: listbox
+ common FSMENU_LISTBOX {
+ {command {Up} {} 0 "filelist_fsb_up" {up}
+ "Go to parent folder"}
+ {command {Back} {} 0 "filelist_fsb_back" {left}
+ "Go back in history"}
+ {command {Forward} {} 0 "filelist_fsb_forward" {right}
+ "Go forward in history"}
+ {separator}
+ {command {Home} {} 0 "filelist_fsb_gohome" {gohome}
+ "Go to your home folder"}
+ {command {Reload} {} 1 "filelist_fsb_reload" {reload}
+ "Reload filelist"}
+ {separator}
+ {command {Rename} {} 0 "filelist_fsb_rename" {edit}
+ "Rename file"}
+ {command {Delete} {} 0 "filelist_fsb_delete" {editdelete}
+ "Delete file"}
+ {command {New folder} {} 0 "filelist_fsb_new_folder" {folder_new}
+ "Create new directory"}
+ {command {Bookmark folder} {} 0 "filelist_fsb_bookmark_this" {bookmark_add}
+ "Bookmark the current directory"}
+ {separator}
+ {command {Properties} {} 0 "filelist_fsb_properties" {}
+ "Show file properties"}
+ }
+
+ # Definition of popup menu for filesystem browser, part: bookmarks
+ common FSMENU_BOOKMARKS {
+ {command {Add bookmark} {} 0 "filelist_fsb_add_bookmark"
+ {bookmark_add} "Bookmark the current folder"}
+ {command {Edit bookmarks} {} 0 "filelist_fsb_edit_bookmarks"
+ {bookmark} "Invoke bookmark editor"}
+ {separator}
+ }
+
+ ## PRIVATE
+ private variable fs_browser_selected_item {} ;# Item selected by popup menu for filesystem browser
+ private variable fs_browser_selection_in_P 0 ;# Procedure "filelist_fsb_select" in progress
+ private variable fs_browser_listbox_top_frame ;# Top frame of filesystem browser
+ private variable forward_history {} ;# List of forward history (filesystem browser)
+ private variable back_history {} ;# List of backward history (filesystem browser)
+ private variable fs_browser_current_dir ;# Current directory (filesystem browser)
+ private variable fs_browser_conf_menu ;# ID of filesystem browser configuration menu
+ private variable fs_browser_dir_ok ;# Button: Confirm location
+ private variable fs_browser_listbox_menu ;# ID of popup menu for filesystem browser
+ private variable fs_browser_bm_menu ;# ID of bookmarks popup menu (filesystem browser)
+ private variable fs_browser_toolbar ;# ID of filesystem browser toolbar
+ private variable fs_browser_dir ;# ComboBox: Current directory
+ private variable fs_browser_listbox ;# ListBox: Files & Directories
+ private variable fs_browser_listbox_v_scrollbar ;# Vertical scrollbar for filesystem browser
+ private variable fs_browser_listbox_h_scrollbar ;# Horizontal scrollbar for filesystem browser
+ private variable fs_browser_filter ;# ComboBox: Filter
+ private variable item_menu_invoked 0 ;# Bool: Item menu request
+ # Current GLOB filter for filesystem browser
+ private variable fs_browser_current_mask ${::CONFIG(FS_BROWSER_MASK)}
+
+ # Variables related to object initialization
+ private variable parent
+ private variable gui_initialized 0
+
+ constructor {} {
+ # Configure local ttk styles
+ ttk::style configure FSBrowser_RedBg.TCombobox \
+ -fieldbackground {#FFDDDD}
+ ttk::style map FSBrowser_RedBg.TCombobox \
+ -fieldbackground [list {readonly !readonly} {#FFDDDD}]
+ }
+
+ destructor {
+ }
+
+ ## Prepare object for creating its GUI
+ # @parm Widget _parent - GUI parent widget
+ # @return void
+ public method PrepareFSBrowser {_parent} {
+ set parent $_parent
+ set gui_initialized 0
+ }
+
+ ## Create GUI of tab "File system browser"
+ # @return void
+ public method CreateFSBrowserGUI {} {
+ if {$gui_initialized} {return}
+ set gui_initialized 1
+
+ set fs_browser_current_dir [$this cget -projectPath]
+
+ # Toolbar
+ set fs_browser_toolbar [frame $parent.toolbar]
+ iconBarFactory $fs_browser_toolbar "$this " \
+ [string range $fs_browser_toolbar 1 end] ::ICONS::16:: {
+ {up "Up" {up} {filelist_fsb_up}
+ "Go to parent folder"}
+ {back "Back" {left} {filelist_fsb_back}
+ "Back in history"}
+ {forward "Forward" {right} {filelist_fsb_forward}
+ "Forward in history"}
+ {separator}
+ {bookmark "Bookmark" {bookmark_toolbar} {filelist_fsb_popup_bm_menu}
+ "Bookmark menu"}
+ {current "Current document folder" {next} {filelist_fsb_current_doc_folder}
+ "Go to directory containing the current document"}
+ {configure "Configure" {configure} {filelist_fsb_popup_config_menu}
+ "Filesystem browser configuration menu"}
+ }
+ ${fs_browser_toolbar}forward configure -state disabled
+ ${fs_browser_toolbar}back configure -state disabled
+
+ # Directory location bar
+ set fs_browser_dir_frame [frame $parent.dir_frame]
+ set fs_browser_dir [ttk::combobox $fs_browser_dir_frame.dir \
+ -validatecommand [list $this filelist_fsb_validate_dir %P] \
+ -width 1 \
+ -values {} \
+ -validate all \
+ ]
+ bind $fs_browser_dir <Return> [list $this filelist_fsb_dir_ok]
+ bind $fs_browser_dir <KP_Enter> [list $this filelist_fsb_dir_ok]
+ bind $fs_browser_dir <<ComboboxSelected>> "$this filelist_fsb_dir_ok"
+ DynamicHelp::add $fs_browser_dir -text [mc "Current directory"]
+ setStatusTip -widget $fs_browser_dir \
+ -text [mc "Directory location bar"]
+ set fs_browser_dir_ok [ttk::button $fs_browser_dir_frame.ok \
+ -style Flat.TButton \
+ -image ::ICONS::16::key_enter \
+ -command [list $this filelist_fsb_dir_ok] \
+ ]
+ DynamicHelp::add $fs_browser_dir_frame.ok -text [mc "Confirm directory location"]
+ setStatusTip -widget $fs_browser_dir_ok \
+ -text [mc "Confirm directory location"]
+ pack $fs_browser_dir -fill x -expand 1 -side left
+ pack $fs_browser_dir_ok -side right -after $fs_browser_dir
+
+ # ListBox of files and directories
+ set fs_browser_listbox_frame [frame $parent.lsbox_frame]
+ set fs_browser_listbox_top_frame [frame $fs_browser_listbox_frame.tp_frame]
+ set fs_browser_listbox [ListBox $fs_browser_listbox_top_frame.listbox \
+ -bg white -highlightthickness 0 -selectmode single -bd 1 \
+ -selectfill 1 -width 0 -height 10 -highlightcolor {#BBBBFF} \
+ -selectbackground {#8888FF} -selectforeground black \
+ -yscrollcommand "$this filelist_fsb_vscroll" \
+ -xscrollcommand "$this filelist_fsb_hscroll" \
+ ]
+ if {[winfo exists $fs_browser_listbox.c]} {
+ bind $fs_browser_listbox.c <Button-5> {%W yview scroll +5 units; break}
+ bind $fs_browser_listbox.c <Button-4> {%W yview scroll -5 units; break}
+ bind $fs_browser_listbox.c <ButtonRelease-3> \
+ [list $this filelist_fsb_popup_listbox_menu %X %Y]
+ }
+ bind $fs_browser_listbox <<ListboxSelect>> "catch {$this filelist_fsb_select}"
+ $fs_browser_listbox bindText <ButtonRelease-3> \
+ [list $this filelist_fsb_popup_listbox_item_menu %X %Y]
+ $fs_browser_listbox bindImage <ButtonRelease-3> \
+ [list $this filelist_fsb_popup_listbox_item_menu %X %Y]
+
+ # Scrollbars
+ set fs_browser_listbox_v_scrollbar [ttk::scrollbar \
+ $fs_browser_listbox_top_frame.scrollbar \
+ -orient vertical -command "$fs_browser_listbox yview" \
+ ]
+ set fs_browser_listbox_h_scrollbar [ttk::scrollbar \
+ $fs_browser_listbox_frame.scrollbar \
+ -orient horizontal -command "$fs_browser_listbox xview" \
+ ]
+
+ pack $fs_browser_listbox -fill both -expand 1 -side left
+ pack $fs_browser_listbox_top_frame -fill both -expand 1
+
+ # GLOB Filter
+ set fs_browser_bottom_frame [frame $parent.bottom_frame]
+ set fs_browser_filter [ttk::combobox $fs_browser_bottom_frame.filter \
+ -state readonly \
+ -width 0 \
+ -font ${::FileList::opened_file_font} \
+ -values {
+ {*.asm - Assembler}
+ {*.inc - INC files}
+ {*.c - C source}
+ {*.h - C header}
+ {*.lst - Code listing}
+ {* - All files}
+ } \
+ ]
+ bind $fs_browser_filter <Return> [list $this filelist_fsb_filter_ok]
+ bind $fs_browser_filter <KP_Enter> [list $this filelist_fsb_filter_ok]
+ bind $fs_browser_filter <<ComboboxSelected>> [list $this filelist_fsb_filter_ok]
+ DynamicHelp::add $fs_browser_filter -text [mc "Filter"]
+ setStatusTip -widget $fs_browser_filter \
+ -text [mc "File filter"]
+ set val [lsearch -exact -ascii {{*.asm} {*.inc} {*.c} {*.h} {*}} $fs_browser_current_mask]
+ if {$val == -1} {
+ set val 0
+ }
+ $fs_browser_filter current $val
+ pack $fs_browser_filter -fill x -expand 1 -side left
+
+ # Pack componets of filesystem browser
+ pack $fs_browser_toolbar -anchor w
+ pack $fs_browser_dir_frame -fill x -pady 3
+ pack $fs_browser_listbox_frame -fill both -expand 1
+ pack $fs_browser_bottom_frame -fill x -pady 3
+
+ # Create popup menus
+ set fs_browser_conf_menu $parent.conf_menu
+ set fs_browser_listbox_menu $parent.listbox_menu
+ set fs_browser_bm_menu $parent.bm_menu
+ filelist_fsb_makePopupMenu
+
+ # Initialize filesystem browser
+ filelist_fsb_change_dir $fs_browser_current_dir
+ filelist_fsb_refresh_bookmarks
+ }
+
+ ## Popup bookmarks menu for filesystem browser
+ # @return void
+ public method filelist_fsb_popup_bm_menu {} {
+ set x [winfo rootx ${fs_browser_toolbar}bookmark]
+ set y [winfo rooty ${fs_browser_toolbar}bookmark]
+ incr y [winfo height ${fs_browser_toolbar}bookmark]
+
+ tk_popup $fs_browser_bm_menu $x $y
+ }
+
+ ## Popup configuration menu for filesystem browser
+ # @return void
+ public method filelist_fsb_popup_config_menu {} {
+ set x [winfo rootx ${fs_browser_toolbar}configure]
+ set y [winfo rooty ${fs_browser_toolbar}configure]
+ incr y [winfo height ${fs_browser_toolbar}configure]
+
+ tk_popup $fs_browser_conf_menu $x $y
+ }
+
+ ## Popup filesystem browser listbox menu
+ # @parm Int x - Relative horizontal position of mouse pointer
+ # @parm Int y - Relative vertical position of mouse pointer
+ # @return void
+ public method filelist_fsb_popup_listbox_menu {x y} {
+ # If item menu was invoked then abort
+ if {$item_menu_invoked} {
+ set item_menu_invoked 0
+ return
+ }
+
+ # Configure and popup the menu
+ set fs_browser_selected_item {}
+ foreach entry {Rename Delete Properties} {
+ $fs_browser_listbox_menu entryconfigure [::mc $entry] -state disabled
+ }
+ tk_popup $fs_browser_listbox_menu $x $y
+ }
+
+ ## Popup filesystem browser listbox menu
+ # @parm Int x - Relative horizontal position of mouse pointer
+ # @parm Int y - Relative vertical position of mouse pointer
+ # @parm String item - Selected item (file of directory)
+ # @return void
+ public method filelist_fsb_popup_listbox_item_menu {x y item} {
+ if {[$fs_browser_listbox itemcget $item -text] == {..}} {
+ return
+ }
+
+ # Configure and popup the menu
+ set item_menu_invoked 1
+ foreach entry {Rename Delete Properties} {
+ $fs_browser_listbox_menu entryconfigure [::mc $entry] -state normal
+ }
+ set fs_browser_selected_item $item
+ tk_popup $fs_browser_listbox_menu $x $y
+ }
+
+ ## Change current directory in filesystem browser
+ # @parm String dir - New directory location
+ # @return void
+ public method filelist_fsb_change_dir {dir} {
+ if {!$gui_initialized} {CreateFSBrowserGUI}
+
+ if {$::MICROSOFT_WINDOWS} {
+ # Transform for instance "C:" to "C:/"
+ if {[regexp {^\w+:$} $dir]} {
+ append dir {/}
+ }
+ }
+
+ # Check if the given directory is valid
+ if {![file exists $dir] || ![file isdirectory $dir]} {
+ tk_messageBox -parent . \
+ -title [mc "Invalid directory"] \
+ -type ok -icon warning \
+ -message [mc "The specified directory does not exist:\n%s" $dir]
+ return
+ }
+
+ # Normalize path and configure toolbar (history control)
+ set dir [file normalize $dir]
+ if {$dir != $fs_browser_current_dir} {
+ lappend back_history $fs_browser_current_dir
+ set forward_history {}
+ $fs_browser_listbox_menu entryconfigure [::mc "Forward"] -state disabled
+ $fs_browser_listbox_menu entryconfigure [::mc "Back"] -state normal
+ ${fs_browser_toolbar}forward configure -state disabled
+ ${fs_browser_toolbar}back configure -state normal
+ }
+ set fs_browser_current_dir $dir
+
+ # Reload contents of browser ListBox
+ set tmp ${::KIFSD::FSD::config(detailed_view)}
+ set ::KIFSD::FSD::config(detailed_view) 0
+ $fs_browser_listbox delete [$fs_browser_listbox items]
+ foreach file [::KIFSD::FSD::dir_file_cmd $dir $fs_browser_current_mask] {
+
+ # Local variables
+ set filename {} ;# File name (if $file file)
+ set folder {} ;# Directory name (if $file is directory)
+ set fullname [lindex $file 0] ;# Full path
+ set text $fullname ;# Text to display
+
+ # Determinate icon
+ switch -- [lindex $file 1] {
+ u { ;# Parent directory
+ set image {up}
+ set folder {..}
+ }
+ d { ;# Directory
+ set image {fileopen}
+ set folder $fullname
+ }
+ f { ;# File
+ set image {ascii}
+ set filename $fullname
+ }
+ }
+
+ # Insert item into the listbox
+ $fs_browser_listbox insert end #auto \
+ -text $text \
+ -image ::ICONS::16::$image \
+ -data [list $filename $folder]
+ }
+ set ::KIFSD::FSD::config(detailed_view) $tmp
+
+ # Configure button "Up"
+ if {$dir == [file separator]} {
+ $fs_browser_listbox_menu entryconfigure [::mc "Up"] -state disabled
+ ${fs_browser_toolbar}up configure -state disabled
+ } {
+ $fs_browser_listbox_menu entryconfigure [::mc "Up"] -state normal
+ ${fs_browser_toolbar}up configure -state normal
+ }
+
+ # Fill directory location combobox
+ set values {}
+ set folder $dir
+ while 1 {
+ lappend values $folder
+ if {$folder == [file separator]} {break}
+ if {$::MICROSOFT_WINDOWS} {
+ if {[regexp {^\w+:[\\\/]?$} $folder]} {break}
+ }
+ set folder [file normalize [file join $folder {..}]]
+ }
+ foreach folder [::KIFSD::FSD::dir_cmd $dir 1] {
+ if {$folder == {..}} {continue}
+ lappend values [file join $dir $folder]
+ }
+ if {$::MICROSOFT_WINDOWS} { ;# Include drive letters on Microsoft Windows
+ foreach drive_letter {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} {
+ if {[file exists "${drive_letter}:/"]} {
+ lappend values "${drive_letter}:/"
+ }
+ }
+ }
+
+ $fs_browser_dir configure -values $values
+ $fs_browser_dir current 0
+ $fs_browser_dir icursor end
+ catch {
+ $fs_browser_dir.e xview end
+ }
+ }
+
+ ## Select file/directory to open
+ # This method should be connected to <<Selection>> event on FS browser ListBox
+ # @return void
+ public method filelist_fsb_select {} {
+ if {[$this is_frozen]} {
+ tk_messageBox \
+ -parent . \
+ -icon info \
+ -type ok \
+ -title [mc "Unable to compile"] \
+ -message [mc "Unable to open source file while simulator is engaged."]
+ return
+ }
+
+ if {$fs_browser_selection_in_P} {return}
+ set fs_browser_selection_in_P 1
+
+ # Determinate name of file/directory to open
+ set file [$fs_browser_listbox itemcget \
+ [$fs_browser_listbox selection get] -data]
+
+ # Open file
+ if {[lindex $file 0] != {}} {
+ set simplename $file
+ set file [file join $fs_browser_current_dir [lindex $file 0]]
+
+ # Check if the file seems to be valid source code
+ if {![regexp {\.(asm|inc|c|h|cpp|cc|cxx|lst)$} $file] || ([file size $file] > 1048576)} {
+ set response [tk_messageBox \
+ -parent . -type yesno \
+ -icon warning \
+ -title [mc "Open file %s" $simplename] \
+ -message [mc "This file does not look like a source code.\nDo you really want to open it ?"] \
+ ]
+ if {$response != {yes}} {
+ set fs_browser_selection_in_P 0
+ return
+ }
+ }
+
+ # Perform opening procedure
+ if {[$this openfile $file 1 . def def 0 0 {}] != {}} {
+ $this switch_to_last
+ update
+ $this editor_procedure {} parseAll {}
+
+ # Make LST read only
+ if {[file extension $file] == {.lst}} {
+ set ::editor_RO_MODE 1
+ $this switch_editor_RO_MODE
+ }
+
+ ::X::recent_files_add 1 $file
+ }
+
+ # Open directory
+ } {
+ filelist_fsb_change_dir \
+ [file join $fs_browser_current_dir [lindex $file 1]]
+ }
+ set fs_browser_selection_in_P 0
+ update
+ }
+
+ ## Invoke dialog to edit FS browser bookmarks
+ # @return void
+ public method filelist_fsb_edit_bookmarks {} {
+ catch {delete object fsd}
+ KIFSD::FSD fsd
+ fsd edit_bookmarks
+ delete object fsd
+ }
+
+ ## Synchronize bookmarks in FS browser with KIFSD (KI File selection dialog)
+ # This method shoul be called after FSD close
+ # @return void
+ public method filelist_fsb_refresh_bookmarks {} {
+ if {!$gui_initialized} {CreateFSBrowserGUI}
+
+ # Clear current bookmarks entries
+ if {[$fs_browser_bm_menu index end] > 2} {
+ $fs_browser_bm_menu delete 3 end
+ }
+ # Create new bookmark entries
+ foreach dir ${::KIFSD::FSD::config(bookmarks)} {
+ $fs_browser_bm_menu add command \
+ -label $dir -compound left \
+ -image ::ICONS::16::fileopen \
+ -command "$this filelist_fsb_change_dir {$dir}"
+ }
+ }
+
+ ## Bookmark current directory
+ # @return void
+ public method filelist_fsb_add_bookmark {} {
+ lappend ::KIFSD::FSD::config(bookmarks) $fs_browser_current_dir
+ $fs_browser_bm_menu add command \
+ -label $fs_browser_current_dir -compound left \
+ -image ::ICONS::16::fileopen \
+ -command "$this filelist_fsb_change_dir {$fs_browser_current_dir}"
+ }
+
+ ## Bookmark directory selected by popup menu
+ # @return void
+ public method filelist_fsb_bookmark_this {} {
+ # No item selected -> bookmark current directory
+ if {$fs_browser_selected_item == {}} {
+ filelist_fsb_add_bookmark
+ return
+ }
+
+ # Directory selected -> bookmark it
+ if {[lindex [$fs_browser_listbox itemcget $fs_browser_selected_item -data] 1] != {}} {
+ set tmp $fs_browser_current_dir
+ set fs_browser_current_dir [file join $fs_browser_current_dir \
+ [$fs_browser_listbox itemcget $fs_browser_selected_item -text]]
+ filelist_fsb_add_bookmark
+ set fs_browser_current_dir $tmp
+
+ # File selected -> bookmark current directory
+ } {
+ filelist_fsb_add_bookmark
+ }
+ }
+
+ ## Reload filesystem browser contents
+ # @return void
+ public method filelist_fsb_reload {} {
+ if {!$gui_initialized} {CreateFSBrowserGUI}
+ filelist_fsb_change_dir $fs_browser_current_dir
+ }
+
+ ## Go to parent directory (in FS browser)
+ # @return void
+ public method filelist_fsb_up {} {
+ filelist_fsb_change_dir [file join $fs_browser_current_dir {..}]
+ }
+
+ ## Go back in history (in FS browser)
+ # @return void
+ public method filelist_fsb_back {} {
+ # Gain new directory location
+ set folder [lindex $back_history end]
+ if {$folder == {}} {return}
+
+ # Adjust back and forward history
+ set back_history [lreplace $back_history end end]
+ lappend forward_history $fs_browser_current_dir
+
+ # Make backup for history lists
+ set tmp_forw_hist $forward_history
+ set tmp_back_hist $back_history
+
+ # Change current directory (go back in history)
+ filelist_fsb_change_dir $folder
+
+ # Restore history lists
+ set forward_history $tmp_forw_hist
+ set back_history $tmp_back_hist
+
+ # Configure toolbar and popup menu
+ if {![llength $back_history]} {
+ ${fs_browser_toolbar}back configure -state disabled
+ $fs_browser_listbox_menu entryconfigure [::mc "Back"] -state disabled
+ } {
+ ${fs_browser_toolbar}back configure -state normal
+ $fs_browser_listbox_menu entryconfigure [::mc "Back"] -state normal
+ }
+ $fs_browser_listbox_menu entryconfigure [::mc "Forward"] -state normal
+ ${fs_browser_toolbar}forward configure -state normal
+ }
+
+ ## Go forward in history (in FS browser)
+ # @return void
+ public method filelist_fsb_forward {} {
+ # Gain new directory location
+ set folder [lindex $forward_history end]
+ if {$folder == {}} {return}
+
+ # Adjust forward and back history
+ set forward_history [lreplace $forward_history end end]
+ lappend back_history $fs_browser_current_dir
+
+ # Make backup for history lists
+ set tmp_forw_hist $forward_history
+ set tmp_back_hist $back_history
+
+ # Change current directory (go forward in history)
+ filelist_fsb_change_dir $folder
+
+ # Restore history lists
+ set forward_history $tmp_forw_hist
+ set back_history $tmp_back_hist
+
+ # Configure toolbar and popup menu
+ if {![llength $forward_history]} {
+ ${fs_browser_toolbar}forward configure -state disabled
+ $fs_browser_listbox_menu entryconfigure [::mc "Forward"] -state disabled
+ } {
+ ${fs_browser_toolbar}forward configure -state normal
+ $fs_browser_listbox_menu entryconfigure [::mc "Forward"] -state normal
+ }
+ ${fs_browser_toolbar}back configure -state normal
+ $fs_browser_listbox_menu entryconfigure [::mc "Back"] -state normal
+ }
+
+ ## Change current directory to the current document folder
+ # @return void
+ public method filelist_fsb_current_doc_folder {} {
+ # Determinate path to current document
+ set file [$this editor_procedure {} getFileName {}]
+ if {[lindex $file 0] != {}} {
+ set dir [lindex $file 0]
+ } {
+ set dir $projectPath
+ }
+ # Change current directory
+ filelist_fsb_change_dir $dir
+ }
+
+ ## Rename selected file
+ # @return void
+ public method filelist_fsb_rename {} {
+ # Determina original and new name
+ set original [$fs_browser_listbox itemcget $fs_browser_selected_item -text]
+ set newname [$fs_browser_listbox edit $fs_browser_selected_item \
+ [$fs_browser_listbox itemcget $fs_browser_selected_item -text]]
+ if {$newname == {}} {
+ return
+ }
+
+ # Normalize file names (original and new)
+ set original [file join $fs_browser_current_dir $original]
+ set newname [file join $fs_browser_current_dir $newname]
+
+ # Rename file/directory
+ if {[catch {file rename -force $original $newname}]} {
+ tk_messageBox \
+ -parent . \
+ -type ok \
+ -icon warning \
+ -title [mc "Permission denied"] \
+ -message [mc "Unable to rename file:\n%s" $original]
+ }
+
+ # Refresh browser
+ filelist_fsb_reload
+ }
+
+ ## Delete selected file/directory
+ # @return void
+ public method filelist_fsb_delete {} {
+ set filename [$fs_browser_listbox itemcget $fs_browser_selected_item -text]
+
+ if {[tk_messageBox \
+ -parent . \
+ -type yesno \
+ -icon question \
+ -title [mc "Delete file"] \
+ -message [mc "Do you really want to delete file:\n%s" $filename]]
+ ==
+ {yes}
+ } {
+ if {[catch {file delete -force -- [file join $fs_browser_current_dir $filename]}]} {
+ tk_messageBox \
+ -parent . \
+ -type ok \
+ -icon warning \
+ -title [mc "Permission denied"] \
+ -message [mc "Unable to remove file:\n%s" $filename]
+ }
+ }
+ filelist_fsb_reload
+ }
+
+ ## Invoke dialog: "Create new directory" (FS browser)
+ # @return void
+ public method filelist_fsb_new_folder {} {
+ # Create dialog window
+ set dialog [toplevel .new_dir_dialog -class {New folder} -bg {#EEEEEE}]
+
+ # Create header
+ pack [label $dialog.header \
+ -justify left \
+ -text [mc "Create new folder in:\n%s" $fs_browser_current_dir] \
+ ] -side top -anchor w -padx 15 -pady 5
+ # Create EntryBox for name of new folder
+ pack [ttk::entry $dialog.entry -bg white \
+ ] -side top -fill x -expand 1 -padx 5 -pady 5
+
+ # Create bottom button bar
+ set button_frame [frame $dialog.bottom]
+ # - Button: Clear
+ pack [ttk::button $button_frame.clear \
+ -text [mc "Clear"] \
+ -compound left \
+ -image ::ICONS::16::clear_left \
+ -command "$dialog.entry delete 0 end"
+ ] -side left -expand 0
+ # - Button: OK
+ pack [ttk::button $button_frame.ok \
+ -text [mc "Ok"] \
+ -compound left \
+ -image ::ICONS::16::ok \
+ -command [list $this create_new_folder] \
+ ] -side left -expand 0
+ # - Button: Cancel
+ pack [ttk::button $button_frame.cancel \
+ -text [mc "Cancel"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command "grab release $dialog; destroy $dialog" \
+ ] -side left -expand 0
+ # Pack button frame
+ pack $button_frame -side bottom -anchor e -expand 0 -padx 5 -pady 5
+
+ # Configure dialog window
+ wm iconphoto $dialog ::ICONS::16::folder_new
+ wm title $dialog [mc "New folder"]
+ wm resizable $dialog 1 0
+ wm minsize $dialog 340 120
+ wm geometry $dialog 340x120
+ wm protocol $dialog WM_DELETE_WINDOW "
+ grab release $dialog
+ destroy $dialog
+ "
+ wm transient $dialog .
+ grab $dialog
+ raise $dialog
+ focus -force $dialog.entry
+ tkwait window $dialog
+ }
+
+ ## Create new directory (in FS browser)
+ # @return void
+ public method create_new_folder {} {
+ # Local variables
+ set dialog .new_dir_dialog ;# ID of dialog window
+ set folder [$dialog.entry get] ;# Name of folder to create
+ set error 0 ;# Bool: error occured
+
+ # Check for folder name validity
+ if {$folder == {}} {
+ set error 1
+ }
+
+ # Create new folder
+ if {$error || [catch {file mkdir [file join $fs_browser_current_dir $folder]}]} {
+ tk_messageBox -parent $dialog -icon warning -type ok \
+ -title [mc "Unable to create folder"] \
+ -message [mc "Unable to create the specified folder"]
+ } {
+ # Remove dialog and reload browser
+ grab release $dialog
+ destroy $dialog
+ filelist_fsb_reload
+ }
+ }
+
+ ## Invoke dialog: "File/Directory properties" (in FS browser)
+ # @return void
+ public method filelist_fsb_properties {} {
+ ## Determinate item properties
+ # - filename
+ # - full path
+ # - size
+ # - permissions
+ # - owner + group
+ # - modification time
+ # - access time
+ set name [$fs_browser_listbox itemcget $fs_browser_selected_item -data]
+ if {[lindex $name 0] == {}} {
+ set name [lindex $name 1]
+ set type [mc "Directory"]
+ } {
+ set name [lindex $name 0]
+ set type [mc "File"]
+ }
+ set fullname [file join $fs_browser_current_dir $name]
+ if {![file exists $fullname]} {
+ tk_messageBox \
+ -parent . \
+ -type ok \
+ -icon warning \
+ -title [mc "Unknown Error"] \
+ -message [mc "This file apparently does not exist"]
+ return
+ }
+ set size [file size $fullname]
+ append size { B}
+ set modified [clock format [file mtime $fullname] -format {%D %R}]
+ set accessed [clock format [file atime $fullname] -format {%D %R}]
+ if {!$::MICROSOFT_WINDOWS} { ;# Microsoft Windows has no file rights (compatible with posix rights)
+ set perms [file attributes $fullname]
+ set group [lindex $perms 1]
+ set owner [lindex $perms 3]
+ set perms [lindex $perms 5]
+ set perms [string range $perms {end-3} end]
+ foreach var {ur uw ux gr gw gx or ow ox} \
+ mask {0400 0200 0100 040 020 010 04 02 01} \
+ {
+ set ::KIFSD::FSD::item_properties($var) [expr {($perms & $mask) > 0}]
+ }
+ }
+
+
+ # Create dialog window componets
+ set dialog [toplevel .properties_dialog -class {File properties} -bg {#EEEEEE}] ;# Toplevel window itself
+ set nb [NoteBook $dialog.nb -bg {#EEEEEE}] ;# NoteBook
+ set bottom_frame [frame $dialog.bottom_frame] ;# Button frame
+
+ # Create tabs in NoteBook
+ $nb insert end general -text [mc "General"]
+ if {!$::MICROSOFT_WINDOWS} { ;# Microsoft Windows has no file rights (compatible with posix rights)
+ $nb insert end permission -text [mc "Permissions"]
+ }
+ $nb raise general
+
+ #
+ ## Create componets of tab "GENERAL"
+ #
+ set frame [frame [$nb getframe general].frame]
+ pack $frame -side top -anchor n -fill x -expand 1
+ set row 0
+ grid [label $frame.lbl_$row \
+ -text [mc "Name:"] -anchor w \
+ ] -column 0 -row $row -sticky w -pady 3
+ set ::KIFSD::FSD::item_properties(name) $name
+ grid [ttk::entry $frame.val_lbl_$row \
+ -validate all \
+ -textvariable ::KIFSD::FSD::item_properties(name) \
+ -validatecommand "::KIFSD::FSD::not_empty_entry_validator %W %P" \
+ ] -column 1 -row $row -sticky w -pady 3
+ incr row
+ foreach lbl {Type Location Size Modified Accessed} \
+ value [list $type $fs_browser_current_dir $size $modified $accessed] \
+ {
+ grid [label $frame.lbl_$row \
+ -text "$lbl:" -anchor w \
+ ] -column 0 -row $row -sticky w -pady 3
+ grid [label $frame.val_lbl_$row \
+ -text $value -anchor w \
+ ] -column 1 -row $row -sticky w -pady 3
+ incr row
+ }
+ grid columnconfigure $frame 0 -minsize 100
+
+ #
+ ## Create componets of tab "PERMISSIONS"
+ #
+ if {!$::MICROSOFT_WINDOWS} { ;# Microsoft Windows has no file rights (compatible with posix rights)
+ set frame [$nb getframe permission]
+ set ap_frame [ttk::labelframe $frame.ap_frame \
+ -text [mc "Access permissions"] \
+ ]
+ set i 0
+ foreach text {Class Read Write Exec Owner Group Others} \
+ row {0 0 0 0 1 2 3} \
+ col {0 1 2 3 0 0 0} \
+ {
+ grid [label $ap_frame.lbl_$i \
+ -text $text -justify center \
+ ] -row $row -column $col -sticky w -padx 4 -pady 4
+ incr i
+ }
+ foreach var {ur uw ux gr gw gx or ow ox} \
+ row {1 1 1 2 2 2 3 3 3} \
+ col {1 2 3 1 2 3 1 2 3} \
+ {
+ grid [checkbutton $ap_frame.check_$i \
+ -variable ::KIFSD::FSD::item_properties($var)
+ ] -row $row -column $col
+ incr i
+ }
+
+ grid columnconfigure $ap_frame 0 -minsize 70
+ grid columnconfigure $ap_frame 0 -weight 1
+ pack $ap_frame -side top -fill x -expand 1 -padx 5 -pady 5 -anchor nw
+
+ set own_frame [ttk::labelframe $frame.own_frame \
+ -text [mc "Ownership"] \
+ ]
+ grid [label $own_frame.owner_lbl \
+ -text [mc "Owner"] \
+ ] -row 0 -column 0 -padx 10 -pady 3 -sticky w
+ grid [label $own_frame.owner_val_lbl \
+ -text $owner -anchor w \
+ ] -row 0 -column 1 -padx 10 -pady 3 -sticky we
+ grid [label $own_frame.group_lbl \
+ -text [mc "Group"] \
+ ] -row 1 -column 0 -padx 10 -pady 3 -sticky w
+ grid [label $own_frame.group_val_lbl \
+ -text $group -anchor w \
+ ] -row 1 -column 1 -padx 10 -pady 3 -sticky we
+ grid columnconfigure $own_frame 0 -minsize 70
+ grid columnconfigure $own_frame 1 -weight 1
+ pack $own_frame -side top -fill x -expand 1 -padx 5 -pady 5
+ }
+
+ #
+ ## Create componets of bottom frame
+ #
+ pack [ttk::button $bottom_frame.ok \
+ -text [mc "Ok"] \
+ -compound left \
+ -image ::ICONS::16::ok \
+ -command "$this properties_ok $dialog $fullname" \
+ ] -side left
+ pack [ttk::button $bottom_frame.cancel \
+ -text [mc "Cancel"] \
+ -compound left \
+ -image ::ICONS::16::button_cancel \
+ -command "
+ grab release $dialog
+ destroy $dialog" \
+ ]
+
+ # Pack NoteBook and bottom frame
+ pack $nb -fill both -expand 1 -padx 10 -pady 5
+ pack $bottom_frame -anchor e -after $nb -padx 10 -pady 5
+
+ # Configure dialog window
+ wm title $dialog [mc "Item properties"]
+ wm minsize $dialog 280 320
+ wm protocol $dialog WM_DELETE_WINDOW "
+ grab release $dialog
+ destroy $dialog"
+ wm transient $dialog .
+ grab $dialog
+ raise $dialog
+ tkwait window $dialog
+ }
+
+ ## Binding to OK button in item properties dialog
+ # @parm String dialog - ID of dialog toplevel window
+ # @parm String file - Name of file related to the dialog
+ # @return void
+ public method properties_ok {dialog file} {
+ set error 0
+
+ # Determinate permissions (in decimal)
+ if {!$::MICROSOFT_WINDOWS} { ;# Microsoft Windows has no file rights (compatible with posix rights)
+ set perm 0
+ foreach var {ur uw ux gr gw gx or ow ox} \
+ val {256 128 64 32 16 8 4 2 1} {
+ if {$::KIFSD::FSD::item_properties($var)} {
+ incr perm $val
+ }
+ }
+ # Change permissions
+ if {[catch {file attributes $file -permissions "0[format {%o} $perm]"}]} {
+ set error 1
+ tk_messageBox -type ok -icon warning -parent $dialog \
+ -title [mc "Permission denied"] \
+ -message [mc "Unable to change permissions for file:\n%s" [file tail $file]]
+ }
+ }
+ set dir [file dirname $file]
+
+ # Set new file name
+ if {${::KIFSD::FSD::item_properties(name)} != [file tail $file]} {
+ if {[catch {
+ file rename -force -- \
+ $file [file join $dir \
+ ${::KIFSD::FSD::item_properties(name)}]}]
+ } {
+ set error 1
+ tk_messageBox -type ok -icon warning -parent $dialog \
+ -title [mc "Permission denied"] \
+ -message [mc "Unable to rename file:\n%s\n\t=>\n%s" [file tail $file] ${::KIFSD::FSD::item_properties(name)}]
+ }
+ filelist_fsb_reload
+ }
+
+ # If no error occured, close dialog
+ if {!$error} {
+ grab release $dialog
+ destroy $dialog
+ }
+ }
+
+ ## Go to home directory
+ # @return void
+ public method filelist_fsb_gohome {} {
+ filelist_fsb_change_dir {~}
+ }
+
+ ## Confirm new filter settings
+ # @return void
+ public method filelist_fsb_filter_ok {} {
+ set fs_browser_current_mask [$fs_browser_filter current]
+ switch -- $fs_browser_current_mask {
+ 0 {set fs_browser_current_mask {*.asm}}
+ 1 {set fs_browser_current_mask {*.inc}}
+ 2 {set fs_browser_current_mask {*.c}}
+ 3 {set fs_browser_current_mask {*.h}}
+ 4 {set fs_browser_current_mask {*.lst}}
+ 5 {set fs_browser_current_mask {*}}
+ }
+ filelist_fsb_reload
+ }
+
+ ## Validate content of directory location ComboBox
+ # @parm String content - Directory to validate
+ # @return Bool - always true
+ public method filelist_fsb_validate_dir {content} {
+ if {[file exists $content] && [file isdirectory $content]} {
+ $fs_browser_dir_ok configure -state normal
+ $fs_browser_dir configure -style TCombobox
+
+ # Fill directory location combobox
+ set folder $content
+ set values {}
+ while 1 {
+ lappend values $folder
+ if {$folder == [file separator]} {break}
+ if {$::MICROSOFT_WINDOWS} {
+ if {[regexp {^\w+:[\\\/]?$} $folder]} {break}
+ }
+ set folder [file normalize [file join $folder {..}]]
+ }
+ foreach folder [::KIFSD::FSD::dir_cmd $content 1] {
+ if {$folder == {..}} {continue}
+ lappend values [file join $content $folder]
+ }
+ if {$::MICROSOFT_WINDOWS} { ;# Include drive letters on Microsoft Windows
+ foreach drive_letter {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} {
+ if {[file exists "${drive_letter}:/"]} {
+ lappend values "${drive_letter}:/"
+ }
+ }
+ }
+ $fs_browser_dir configure -values $values
+ } {
+ $fs_browser_dir_ok configure -state disabled
+ $fs_browser_dir configure -style FSBrowser_RedBg.TCombobox
+ }
+
+ return 1
+ }
+
+ ## Confirm directory location in ComboBox
+ # @return void
+ public method filelist_fsb_dir_ok {} {
+ filelist_fsb_change_dir [$fs_browser_dir get]
+ }
+
+ ## Verticaly scroll FileSystem browser ListBox
+ # @parm Float frac0 - Fraction of top visible area
+ # @parm Float frac1 - Fraction of bottom visible area
+ # @return void
+ public method filelist_fsb_vscroll {frac0 frac1} {
+ # All content is in visible area -> unmap scrollbar
+ if {$frac0 == 0 && $frac1 == 1} {
+ if {[winfo ismapped $fs_browser_listbox_v_scrollbar]} {
+ pack forget $fs_browser_listbox_v_scrollbar
+ update
+ }
+
+ # Otherwise -> create scrollbar
+ } {
+ if {![winfo ismapped $fs_browser_listbox_v_scrollbar]} {
+ pack $fs_browser_listbox_v_scrollbar \
+ -after $fs_browser_listbox \
+ -fill y -expand 1
+ update
+ }
+ $fs_browser_listbox_v_scrollbar set $frac0 $frac1
+ }
+ }
+
+ ## Horizontaly scroll FileSystem browser ListBox
+ # @parm Float frac0 - Fraction of top visible area
+ # @parm Float frac1 - Fraction of bottom visible area
+ # @return void
+ public method filelist_fsb_hscroll {frac0 frac1} {
+ # All content is in visible area -> unmap scrollbar
+ if {$frac0 == 0 && $frac1 == 1} {
+ if {[winfo ismapped $fs_browser_listbox_h_scrollbar]} {
+ pack forget $fs_browser_listbox_h_scrollbar
+ update
+ }
+
+ # Otherwise -> create scrollbar
+ } {
+ if {![winfo ismapped $fs_browser_listbox_h_scrollbar]} {
+ pack $fs_browser_listbox_h_scrollbar \
+ -after $fs_browser_listbox_top_frame \
+ -side bottom -fill x -expand 0
+ update
+ }
+ $fs_browser_listbox_h_scrollbar set $frac0 $frac1
+ }
+ }
+
+ ## Recreate popup menus
+ # @return void
+ public method filelist_fsb_makePopupMenu {} {
+ if {!$gui_initialized} {return}
+ if {[winfo exists $fs_browser_conf_menu]} {
+ destroy $fs_browser_conf_menu
+ }
+ if {[winfo exists $fs_browser_listbox_menu]} {
+ destroy $fs_browser_listbox_menu
+ }
+ if {[winfo exists $fs_browser_bm_menu]} {
+ destroy $fs_browser_bm_menu
+ }
+
+ menuFactory $FSMENU_CONFIGURE $fs_browser_conf_menu 0 "$this " 0 {}
+ menuFactory $FSMENU_LISTBOX $fs_browser_listbox_menu 0 "$this " 0 {}
+ menuFactory $FSMENU_BOOKMARKS $fs_browser_bm_menu 0 "$this " 0 {}
+
+ if {![llength $back_history]} {
+ $fs_browser_listbox_menu entryconfigure [::mc "Back"] -state disabled
+ }
+ if {![llength $forward_history]} {
+ $fs_browser_listbox_menu entryconfigure [::mc "Forward"] -state disabled
+ }
+ }
+
+ ## Get current file mask
+ # @return String - Current mask
+ public method fs_browser_get_current_mask {} {
+ return $fs_browser_current_mask
+ }
+}
diff --git a/lib/leftpanel/sfrwatches.tcl b/lib/leftpanel/sfrwatches.tcl
new file mode 100755
index 0000000..ba47dc5
--- /dev/null
+++ b/lib/leftpanel/sfrwatches.tcl
@@ -0,0 +1,620 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+# Provides SFR watches for left panel
+# --------------------------------------------------------------------------
+
+class SFRWatches {
+
+ ## COMMON
+ # Font for addresses and register names
+ common main_font [font create \
+ -family $::DEFAULT_FIXED_FONT \
+ -size -14 \
+ -weight bold \
+ ]
+ # Just another font but not bold
+ common roman_font [font create \
+ -family $::DEFAULT_FIXED_FONT \
+ -size -14 \
+ ]
+ # Fonr for register entry boxes
+ common entry_font [font create \
+ -family $::DEFAULT_FIXED_FONT \
+ -size -12 \
+ -weight bold \
+ ]
+
+ ## PRIVATE
+ private variable text_widget ;# Widget: Text widget containing SFR watches
+ private variable scrollbar ;# Widget: Scrollbar for $text_widget
+ private variable search_entry ;# Widget: Search entry box at the bottom of the panel
+ private variable search_clear_but ;# Widget: Button "Clear" at the bottom of the panel
+ private variable main_left_frame ;# Widget: Frame containing $text_widget and its header label
+ private variable entry_count 0 ;# Int: Number of SFRs
+ private variable validation_ena 1 ;# Bool: SFR entry box validation enabled
+ private variable haddr2idx ;# Array: $haddr2idx($hex_addr) --> row_in_text_widget - 1
+ private variable addr2idx ;# Array: $addr2idx($dec_addr) --> row_in_text_widget - 1
+ private variable reg2idx ;# Array: $addr2idx($register_name_upppercase) --> row_in_text_widget - 1
+ private variable last_selected_line 0 ;# Int: Selected row in the text widget
+ private variable search_ena 1 ;# Bool: Search enabled
+ private variable menu ;# Widget: Popup menu for the text widget
+
+ # Variables related to object initialization
+ private variable parent ;# Parent GUI object (tempotary variable)
+ private variable gui_initialized 0 ;# GUI ready
+
+ constructor {} {
+ }
+
+ destructor {
+ if {$gui_initialized} {
+ menu_Sbar_remove $menu
+ }
+ }
+
+ ## Prepare object for creating its GUI
+ # @parm Widget _parent - parent container (some frame)
+ # @return void
+ public method PrepareSFRWatches {_parent} {
+ set parent $_parent
+ set gui_initialized 0
+ }
+
+ ## Initialize SFR watches GUI
+ # @return void
+ public method CreateSFRWatchesGUI {} {
+ if {$gui_initialized} {return}
+ set gui_initialized 1
+
+ set validation_ena 0
+ create_GUI
+ fill_gui
+ set validation_ena 1
+
+ if {![$this is_frozen]} {
+ sfr_watches_disable
+ }
+ }
+
+ ## Create entry box to embedd in the text widget
+ # @parm Int i - Entry index (row - 1)
+ # @parm String type - Entry type (hex or dec)
+ # @parm Int addr - SFR address (128..255)
+ # @parm String reg - SFR name (e.g. PSW)
+ # @return Widget - Created entry box
+ private method create_entry {i type addr reg} {
+ # Determinate entry box width
+ if {$type == {hex}} {
+ set width 2
+ } {
+ set width 3
+ }
+
+ # Create entry widget
+ set entry [entry $text_widget.${type}_entry_${i} \
+ -width $width -font $entry_font \
+ -bg {#FFFFFF} -validate all \
+ -takefocus 0 -highlightthickness 0 \
+ -disabledbackground {#FFFFFF} \
+ -vcmd "$this sfr_watches_validate ${type} $addr %P" \
+ -bd 0 -justify right \
+ ]
+
+ # Perform name correction for accumulators
+ if {$reg == {A} || $reg == {B}} {
+ append reg {_hex}
+ }
+
+ # Set event bindins
+ bind $entry <Motion> {help_window_show %X %Y}
+ bind $entry <Leave> {help_window_hide}
+ bind $entry <FocusIn> "$this unmark_entry $addr"
+ bind $entry <Enter> "$this create_help_window_ram $reg"
+ bind $entry <Button-1> "$this sfr_watches_select_line 0 [expr {$i + 1}] $type"
+ bind $entry <Key-Up> "$this sfr_watches_up $type 1"
+ bind $entry <Key-Down> "$this sfr_watches_down $type 1"
+ bind $entry <Key-Next> "$this sfr_watches_down $type 4"
+ bind $entry <Key-Prior> "$this sfr_watches_up $type 4"
+ bind $entry <Button-4> "$text_widget yview scroll -5 units"
+ bind $entry <Button-5> "$text_widget yview scroll +5 units"
+ if {$type == {hex}} {
+ bind $entry <Key-Right> "
+ focus $text_widget.dec_entry_${i}
+ $text_widget.dec_entry_${i} selection clear
+ update
+ $text_widget.dec_entry_${i} icursor 0"
+ } {
+ bind $entry <Key-Left> "
+ focus $text_widget.hex_entry_${i}
+ $text_widget.hex_entry_${i} selection clear
+ update
+ $text_widget.dec_entry_${i} icursor end"
+ }
+
+ return $entry
+ }
+
+ ## Complite GUI initialization (load all SFRs into the text widget)
+ # @return void
+ private method fill_gui {} {
+ set entry_count 0
+ set validation_ena 0
+
+ # Iterate over defined SFRs ({{addr name} ... })
+ foreach reg [$this simulator_get_sfrs] {
+ # Determinate hexadecimal address
+ set addr [lindex $reg 0]
+ set hex_addr [format %X $addr]
+ if {[string length $hex_addr] == 1} {
+ set hex_addr "0$hex_addr"
+ } elseif {[string length $hex_addr] == 3} {
+ set hex_addr [string replace $hex_addr 0 0]
+ }
+ # Determinate register name and make it 8 characters long
+ set reg [lindex $reg 1]
+ set reg_org $reg
+ switch -- $reg {
+ SBUFR {
+ set reg {SBUF R}
+ }
+ SBUFT {
+ set reg {SBUF T}
+ }
+ default {
+ set reg $reg
+ }
+ }
+ append reg [string repeat { } [expr {8 - [string length $reg]}]]
+
+ # Register this SFR
+ set haddr2idx($hex_addr) $entry_count
+ set addr2idx($addr) $entry_count
+ set reg2idx($reg_org) $entry_count
+
+ # Insert address and name into the text widget
+ $text_widget insert end $hex_addr
+ $text_widget insert end { }
+ $text_widget insert end $reg
+
+ # Set highlighting tags
+ set line [expr {int([$text_widget index insert])}]
+ $text_widget tag add tag_addr $line.0 $line.2
+ $text_widget tag add tag_name $line.3 $line.11
+
+ # Create and insert embedded entry boxes
+ set entry [create_entry $entry_count hex $addr $reg_org]
+ $entry insert 0 [$this getSfr $addr]
+ $text_widget window create end -window $entry -pady 0
+ $text_widget insert end { }
+ set entry [create_entry $entry_count dec $addr $reg_org]
+ $entry insert 0 [$this getSfrDEC $addr]
+ $text_widget window create end -window $entry -pady 0
+
+ # Finalize this row
+ $text_widget insert end "\n"
+ incr entry_count
+ }
+
+ # Remove the last line (empty line) and disable the text widget
+ $text_widget delete end-1l end
+ set validation_ena 1
+ }
+
+ ## Set value of SFR at current line to the specified value
+ # @parm String value - Hexadecimal value
+ # @return void
+ public method sfr_watches_set_current_to {value} {
+ set idx [expr {$last_selected_line - 1}]
+ set addr [lindex [$this simulator_get_sfrs] [list $idx 0]]
+
+ $this setSfr $addr $value
+ $this Simulator_GUI_sync S $addr
+ }
+
+ ## Create GUI elements of this panel
+ # @return void
+ private method create_GUI {} {
+ # Create and pack panel frames
+ set main_frame [frame $parent.main_frame]
+ set main_left_frame [frame $main_frame.left]
+ pack $main_left_frame -side left -fill both -expand 1
+ pack $main_frame -fill both -expand 1
+
+ # Create text widget and its header
+ pack [label $main_left_frame.header_label \
+ -anchor w -justify left -pady 0 -padx 2 \
+ -fg ${::Simulator_GUI::small_color} \
+ -font ${::Simulator_GUI::smallfont} \
+ -text "[mc {Register}] [mc {HEX}] [mc {DEC}]" -width 1 \
+ ] -fill x -pady 0 -anchor nw
+ set text_widget [text $main_left_frame.text \
+ -bg {#FFFFFF} -font $roman_font -bd 2 \
+ -width 0 -height 0 -wrap none \
+ -yscrollcommand "$this sfr_watches_scroll_set" \
+ -cursor left_ptr \
+ ]
+
+ # Create popup menu for the text widget
+ set menu $text_widget.menu
+ menuFactory {
+ {command {Set to 0x00} {} 9 "sfr_watches_set_current_to 00"
+ {} "Set this register to 0"}
+ {command {Set to 0xFF} {} 9 "sfr_watches_set_current_to FF"
+ {} "Set this register to 255"}
+ } $menu 0 "$this " 0 {}
+
+ # Set event bindings for the text widget
+ bindtags $text_widget $text_widget
+ foreach event {
+ <ButtonRelease-1> <B1-Enter> <B1-Leave>
+ <B2-Motion> <Button-5> <Button-4>
+ <MouseWheel>
+ } {
+ bind $text_widget $event [bind Text $event]
+ }
+ bind $text_widget <Button-1> \
+ "$this sfr_watches_select_line 0 \[expr {int(\[%W index @%x,%y\])}\] hex"
+ bind $text_widget <ButtonRelease-3> \
+ "$this sfr_watches_select_line 0 \[expr {int(\[%W index @%x,%y\])}\] hex
+ tk_popup $menu %X %Y"
+
+ # Pack the text widget and create its scrollbar
+ pack $text_widget -fill both -expand 1
+ set scrollbar [ttk::scrollbar $main_frame.scrollbar \
+ -orient vertical -command "$text_widget yview" \
+ ]
+
+ # Create bottom frame (search bar)
+ set search_frame [frame $parent.top]
+ pack [label $search_frame.lbl \
+ -text [mc "Search:"] \
+ ] -side left
+ set search_entry [ttk::entry $search_frame.entry \
+ -width 0 \
+ -validate all \
+ -validatecommand "$this sfr_watches_search_validate %P" \
+ ]
+ pack $search_entry -side left -fill x -expand 1
+ set search_clear_but [ttk::button $search_frame.button \
+ -style Flat.TButton \
+ -state disabled \
+ -image ::ICONS::16::clear_left \
+ -command "$search_entry delete 0 end" \
+ ]
+ pack $search_clear_but -side right -after $search_entry
+ pack $search_frame -fill x
+
+ # Create highlighting tags for the text widget
+ $text_widget tag configure tag_addr \
+ -foreground {#000000} -font $main_font
+ $text_widget tag configure tag_name \
+ -foreground {#0000DD} -font $main_font
+ $text_widget tag configure tag_curLine \
+ -background ${::RightPanel::selection_color_dark}
+ }
+
+ ## Adjust scrollbar
+ # @parm Float frac0 - 1st fraction
+ # @parm Float frac1 - 2nd fraction
+ # @return void
+ public method sfr_watches_scroll_set {frac0 frac1} {
+ # Hide scrollbar
+ if {$frac0 == 0 && $frac1 == 1} {
+ if {[winfo ismapped $scrollbar]} {
+ pack forget $scrollbar
+ }
+ # Show scrollbar
+ } {
+ if {![winfo ismapped $scrollbar]} {
+ pack $scrollbar \
+ -side left \
+ -fill y \
+ -after $main_left_frame
+ }
+ $scrollbar set $frac0 $frac1
+ }
+ }
+
+ ## Validate content of search entry box at the bottom bar
+ # @parm String string - String to validate
+ # @return Bool - Always 1
+ public method sfr_watches_search_validate {string} {
+ # Check if searching is enabled
+ if {!$search_ena} {return 1}
+
+ # Adjust state of clear button (+ clear selection on the text widget)
+ if {$string == {}} {
+ $search_clear_but configure -state disabled
+ $search_entry configure -style TEntry
+ sfr_watches_select_line 1 0 hex
+ return 1
+ } {
+ $search_clear_but configure -state normal
+ }
+
+ set string [string toupper $string]
+
+ # Perform case insensitive search for the given chunk of SFR name and address
+ foreach arr {reg2idx haddr2idx} {
+ foreach str [lsort -ascii -increasing [array names $arr]] {
+ # Search successful
+ if {![string first $string $str]} {
+ $search_entry configure -style StringFound.TEntry
+ sfr_watches_select_line 1 [expr {[subst "\${${arr}(${str})}"] + 1}] hex
+ return 1
+ }
+ }
+ }
+
+ # Search failed
+ $search_entry configure -style StringNotFound.TEntry
+ return 1
+ }
+
+ ## Select line in the text widget
+ # @parm Bool search - Invoked form search validator (do not clear search entry box)
+ # @parm Int line - Target line
+ # @parm String type - Entry box to select (hex or dec)
+ # @return void
+ public method sfr_watches_select_line {search line type} {
+
+ # Unselect the last selected line and determinate cursor position
+ if {$last_selected_line} {
+ $text_widget tag remove tag_curLine 0.0 end
+ $this simulator_reg_label_set_highlighted $last_selected_line 0
+ incr last_selected_line -1
+ foreach tp {dec hex} {
+ $text_widget.${tp}_entry_$last_selected_line selection clear
+ $text_widget.${tp}_entry_$last_selected_line configure \
+ -bg {#FFFFFF} -disabledbackground {#FFFFFF}
+ }
+ set cursor [$text_widget.${type}_entry_$last_selected_line index insert]
+ } {
+ set cursor 0
+ }
+
+ # Adjust last selected line (if 0 the return)
+ set last_selected_line $line
+ if {!$line} {
+ return
+ }
+
+
+ # Highlight this line as selected in the text widget
+ $text_widget tag add tag_curLine \
+ $last_selected_line.0 \
+ $last_selected_line.0+1l
+ $text_widget see $last_selected_line.0
+
+ # Highlight SFR on this line in simulator control panel
+ $this simulator_reg_label_set_highlighted $last_selected_line 1
+
+ # Adjust background color for entry boxes at this line
+ incr line -1
+ $text_widget.dec_entry_$line configure \
+ -fg ${Simulator::normal_color} \
+ -bg ${::RightPanel::selection_color_dark} \
+ -disabledbackground ${::RightPanel::selection_color_dark}
+ $text_widget.hex_entry_$line configure \
+ -fg ${Simulator::normal_color} \
+ -bg ${::RightPanel::selection_color_dark} \
+ -disabledbackground ${::RightPanel::selection_color_dark}
+
+ # Clear search entry box and focus and entry box at this line
+ if {!$search} {
+ $text_widget.${type}_entry_$line icursor $cursor
+ $text_widget.${type}_entry_$line selection range 0 end
+ focus $text_widget.${type}_entry_$line
+ set search_ena 0
+ $search_entry delete 0 end
+ set search_ena 1
+ }
+ }
+
+ ## Validator for SFR value entry boxes
+ # @parm String type - Entry box type (hex or dec)
+ # @parm Int addr - Register address
+ # @parm String value - String to validate
+ # @return Bool - Validation result
+ public method sfr_watches_validate {type addr value} {
+ # Prevent recursion
+ if {!$validation_ena} {return 1}
+ set validation_ena 0
+
+ # Validate value
+ if {$value == {}} {
+ set value 0
+ }
+ if {$type == {hex}} {
+ if {![string is xdigit $value]} {
+ set validation_ena 1
+ return 0
+ }
+ set value [expr "0x$value"]
+ } {
+ if {![string is digit $value]} {
+ set validation_ena 1
+ return 0
+ }
+ }
+ if {$value > 255 || $value < 0} {
+ set validation_ena 1
+ return 0
+ }
+
+ # Synchronize with engine and simulator control panel
+ $this setSfr $addr [format %X $value]
+ $this SimGUI_disable_sync
+ $this Simulator_GUI_sync S $addr
+ $this SimGUI_enable_sync
+
+ # Synchronize with the other one entry box
+ if {$type == {hex}} {
+ $text_widget.dec_entry_$addr2idx($addr) delete 0 end
+ $text_widget.dec_entry_$addr2idx($addr) insert 0 $value
+ } {
+ set value [format %X $value]
+ if {[string length $value] == 1} {
+ set value "0$value"
+ }
+ $text_widget.hex_entry_$addr2idx($addr) delete 0 end
+ $text_widget.hex_entry_$addr2idx($addr) insert 0 $value
+ }
+
+ # Done
+ set validation_ena 1
+ return 1
+ }
+
+ ## Remove all SFRs for the text widget and unregister them
+ # @return void
+ private method clear_gui {} {
+ if {!$gui_initialized} {return}
+
+ # Clear SFR name label highlight in simultor contol panel
+ if {$last_selected_line} {
+ $this simulator_reg_label_set_highlighted $last_selected_line 0
+ }
+
+ # Reset object variables
+ array unset haddr2idx
+ array unset addr2idx
+ array unset reg2idx
+ set last_selected_line 0
+ set entry_count 0
+
+ # Clear the text widget
+ $text_widget delete 1.0 end
+ foreach wdg [$text_widget window names] {
+ destroy $wdg
+ }
+ }
+
+ ## Set new value of certain SFR in this panel
+ # @parm Int addr - SFR address
+ # @parm Int new_val - New SFR value
+ # @return void
+ public method sfr_watches_sync {addr new_val} {
+ if {!$gui_initialized} {return}
+
+ # Prevent recursion
+ if {!$validation_ena} {return}
+ set validation_ena 0
+
+ # Check if this SFR is avaliable here
+ if {[lsearch [array names addr2idx] $addr] == -1} {
+ set validation_ena 1
+ return
+ }
+
+ # Determinate references of HEX and DEC entry boxes
+ set hex_entry $text_widget.hex_entry_$addr2idx($addr)
+ set dec_entry $text_widget.dec_entry_$addr2idx($addr)
+
+ # Highlight entry boxes
+ set org_val [$dec_entry get]
+ if {$org_val != $new_val} {
+ $hex_entry configure -fg ${::Simulator_GUI::hcolor}
+ $dec_entry configure -fg ${::Simulator_GUI::hcolor}
+ }
+
+ # Set decimal value
+ $dec_entry delete 0 end
+ $dec_entry insert 0 $new_val
+
+ # Set hexadecimal value
+ set new_val [format %X $new_val]
+ if {[string length $new_val] == 1} {
+ set new_val "0$new_val"
+ }
+ $hex_entry delete 0 end
+ $hex_entry insert 0 $new_val
+
+ # Reenable entry box value validations
+ set validation_ena 1
+ }
+
+ ## Enable this panel
+ # @return vois
+ public method sfr_watches_enable {} {
+ if {!$gui_initialized} {return}
+ $menu entryconfigure [::mc "Set to 0x00"] -state normal
+ $menu entryconfigure [::mc "Set to 0xFF"] -state normal
+ for {set i 0} {$i < $entry_count} {incr i} {
+ $text_widget.hex_entry_$i configure -state normal
+ $text_widget.dec_entry_$i configure -state normal
+ }
+ }
+
+ ## Disable this panel
+ # @return vois
+ public method sfr_watches_disable {} {
+ if {!$gui_initialized} {return}
+ $menu entryconfigure [::mc "Set to 0x00"] -state disabled
+ $menu entryconfigure [::mc "Set to 0xFF"] -state disabled
+ for {set i 0} {$i < $entry_count} {incr i} {
+ $text_widget.hex_entry_$i configure -state disabled
+ $text_widget.dec_entry_$i configure -state disabled
+ }
+ }
+
+ ## This function shuld be call after processor was changed
+ # Reload avaliable SFRs
+ # @return void
+ public method sfr_watches_commit_new_sfr_set {} {
+ if {!$gui_initialized} {return}
+ clear_gui
+ fill_gui
+ }
+
+ ## Move selected line up
+ # @parm String type - Which entry box should be selected (hex or dec)
+ # @parm Int lines - Number of lines to move by
+ # @return void
+ public method sfr_watches_up {type lines} {
+ set line $last_selected_line
+ incr line -$lines
+ if {$line <= 0} {
+ set line $entry_count
+ }
+
+ sfr_watches_select_line 0 $line $type
+ }
+
+ ## Move selected line down
+ # @parm String type - Which entry box should be selected (hex or dec)
+ # @parm Int lines - Number of lines to move by
+ # @return void
+ public method sfr_watches_down {type lines} {
+ set line $last_selected_line
+ incr line $lines
+ if {$line >= $entry_count} {
+ set line 0
+ }
+
+ sfr_watches_select_line 0 $line $type
+ }
+}