Sophie

Sophie

distrib > Fedora > 16 > i386 > by-pkgid > 2f3faeccae36080f0037e6821cfc3ed7 > files > 5

cscope-15.7a-7.fc16.src.rpm

diff -up /dev/null cscope-15.7a/contrib/cctree.txt
--- /dev/null	2011-05-25 12:40:15.391845002 -0400
+++ cscope-15.7a/contrib/cctree.txt	2011-05-26 14:45:02.905838546 -0400
@@ -0,0 +1,537 @@
+*CCTree.txt*	Plugin for C Call-Tree Explorer *CCTree*
+
+Author: Hari Rangarajan (First.Last AT gmail DOT com)
+Last Change: 20 May 2011
+
+CCTree version 1.51
+
+For Vim version 7.0 and above
+
+==============================================================================
+
+1. Overview                                     |CCTree-overview|
+2. Downloads                                    |CCTree-download|
+3. Installation                                 |CCTree-installation|
+4. Configuration				|CCTree-configuration|
+5. Features                                     |CCTree-features|
+6. Limitations                                  |CCTree-limitations|
+7. FAQ & TIPS                                   |CCTree-faq|
+8. History                                      |CCTree-history|
+9. Thanks                                       |CCTree-thanks|
+ 
+==============================================================================
+1. Overview~
+                                                *CCTree-overview*
+
+Plugin generates dependency-trees for symbols using a cscope database in Vim.
+Basic cross-referencing includes functions and macros. Enhanced symbol
+processing covers macros, typedefs, enums, and global variables.
+
+Requires Cscope and works best with C code.
+
+==============================================================================
+2. Downloads~
+                                                *CCTree-download*
+
+You can download the latest release of the script from this url :
+    http://www.vim.org/scripts/script.php?script_id=2368
+
+
+Cscope packages can be found here:
+    http://cscope.sourceforge.net/
+    http://code.google.com/p/cscope-win32/
+    
+
+==============================================================================
+3. Installation~
+                                                *CCTree-installation*
+
+Copy this file to ~/.vim/plugins/ or to /vimfiles/plugins/  (on Win32
+platforms) 
+
+It should also be possible to load it as a filetype plugin ~/.vim/ftplugin/c/
+Need to set :filetype plugin on 
+
+
+==============================================================================
+CONFIGURATION					*CCTree-configuration*
+4. Options~
+
+You can customize behavior by changing the following variable settings
+                    
+4.1.1 Cscope Symbol Database~
+                                                *CCTreeCscopeDb*
+
+Cscope database file, g:CCTreeCscopeDb = "cscope.out"
+
+4.1.2 Call-tree Depth~
+                                                *CCTreeRecursiveDepth* 
+Maximum call levels,   g:CCTreeRecursiveDepth = 3
+
+4.1.3 Call-tree Minimum Visible Depth~
+                                                *CCTreeMinVisibleDepth*
+Maximum visible(unfolded) level, g:CCTreeMinVisibleDepth = 3
+
+4.1.4 Call-tree window display~
+
+4.4.1 Orientation~
+                                                *CCTreeOrientation*
+Orientation of window,  g:CCTreeOrientation = "leftabove"
+ (standard vim options for split: [right|left][above|below])
+
+4.5 Direction~
+                                                *CCTreeWindowVertical* 
+Use Vertical window, g:CCTreeWindowVertical = 1
+
+4.5.1 Dimensions~
+
+These settings determine the layout of the CCTree preview window.
+
+4.5.2 Horizontal Window Settings~
+                                                *CCTreeWindowHeight* 
+ Horizontal window, g:CCTreeWindowHeight, default is -1.
+
+4.5.2 Vertical Window Settings~
+                                                *CCTreeWindowMinWidth* 
+                                                *CCTreeWindowWidth* 
+ Minimum width for window, g:CCTreeWindowMinWidth = 40.
+ g:CCTreeWindowWidth = -1, auto-select best width to fit.
+
+
+4.6 Call-tree display format~
+                                                *CCTreeDisplayMode*
+Display format, g:CCTreeDisplayMode, default: 1
+
+Values: 1 -- Ultra-compact (takes minimum screen width)
+        2 -- Compact       (Takes little more space)
+        3 -- Wide          (Takes copious amounts of space)
+
+For vertical splits, 1 and 2 are good, while 3 is good for horizontal
+displays.
+
+4.7. Dynamic Call-tree highlighting~
+                                                *CCTreeHilightCallTree*
+
+Enable/disable dynamic call-tree highlighting, default: 1
+
+
+4.7.1 Syntax items~
+                                               *CCTreeSymbol* *CCTreeHiSymbol*
+CCTreeSymbol is the symbol name.
+CCTreeHiSymbol is the highlighted call tree functions.
+
+                                               *CCTreeMarkers* *CCTreeHiMarkers*
+CCTreeMarkers include  "|","+--->".
+CCTreeHiMarkers is the same as CCTreeMarkers except these denote the 
+highlighted call-tree.
+
+    
+   
+==============================================================================
+COMMAND LIST 						*CCTree-commands-list*
+
+Database Management~
+      CCTreeLoadDB                <dbname>
+      CCTreeAppendDB              <dbname>
+      CCTreeUnLoadDB             
+      CCTreeShowLoadedDBs
+				Refer to |CCTree-usage|
+
+Native Xref Database~
+      CCTreeLoadXRefDB		 <dbname>
+      CCTreeSaveXRefDB		 <dbname>
+				
+				Refer to |CCTree-fast-loading|
+	
+Symbol tracing~
+      CCTreeTraceForward          <symbolname>
+      CCTreeTraceReverse          <symbolname>     
+      CCTreeRecurseDepthPlus     
+      CCTreeRecurseDepthMinus    
+				Refer to |CCTree-explore-source|
+Trace Management~
+      CCTreeWindowSaveCopy
+      CCTreeWindowHiCallTree   
+				Refer to |CCTree-preview-window|
+
+Dynamic configuration~
+      CCTreeOptsEnable <option>    (<tab> for auto-complete)
+      CCTreeOptsDisable <option>   (<tab> for auto-complete)
+      CCTreeOptsToggle <option>    (<tab> for auto-complete)
+      Options~
+            DynamicTreeHiLights: Control dynamic tree highlighting
+	    UseUnicodeSymbols: 	 Use of UTF-8 special characters for tree
+            UseConceal: Use (+Conceal) feature instead of 'ignore'
+                    syntax highlighting. Allows CCTree window
+                    to be exported in HTML without syntax markup
+                    characters. (Vim 7.3+ only)
+                                            *CCTree-Enhanced-Symbol-Processing*
+            EnhancedSymbolProcessing: Cross-reference enums, macros,
+                    global variables, typedefs (WARNING: Database
+                    processing speeds will be slow).
+ 
+SHORTCUT KEYS						*CCTree-Key-Map*	
+Default Mappings~
+							*CCTree-Default-Key-Map*   
+      Get reverse call tree for symbol  <C-\><
+      Get forward call tree for symbol  <C-\>>
+      Increase depth of tree and update <C-\>=
+      Decrease depth of tree and update <C-\>-
+
+      Open symbol in other window       <CR>
+      Preview symbol in other window    <Ctrl-P>
+
+      Save copy of preview window       <C-\>y
+      Highlight current call-tree flow  <C-l>
+      Compress(Fold) call tree view     zs
+      (This is useful for viewing long
+       call trees which span across
+       multiple pages)
+
+Custom user-mappings	
+							*CCTree-Custom-Key-Map*
+    Users can custom-map the short-cut keys by 
+    overriding the following variables in their
+    Vim start-up configuration            
+>
+     let g:CCTreeKeyTraceForwardTree = '<C-\>>' 
+     let g:CCTreeKeyTraceReverseTree = '<C-\><' 
+     let g:CCTreeKeyHilightTree = '<C-l>'        " Static highlighting
+     let g:CCTreeKeySaveWindow = '<C-\>y' 
+     let g:CCTreeKeyToggleWindow = '<C-\>w' 
+     let g:CCTreeKeyCompressTree = 'zs'     " Compress call-tree 
+     let g:CCTreeKeyDepthPlus = '<C-\>=' 
+     let g:CCTreeKeyDepthMinus = '<C-\>-'
+<  
+
+==============================================================================
+FEATURES 						*CCTree-features*
+
+5.1. Symbol database~
+							*CCTree-usage*
+Build cscope database, for example:
+> cscope -b -i cscope.files
+ [Tip: add -c option to build uncompressed databases for faster
+    load speeds]
+
+Load database~
+>
+	:CCTreeLoadDB
+<
+	(Please note that it might take a while depending on the 
+	 database size)
+
+A database name, i.e., my_cscope.out, can be specified with the command. If
+not provided, a prompt will ask for the filename; default is cscope.out.
+	
+Unload database ~
+ >
+ 	:CCTreeUnLoadDB
+<
+Append database~
+ >
+	:CCTreeAppendDB
+<
+    Allows multiple cscope files to be loaded and cross-referenced
+    Illustration: >
+    :CCTreeAppendDB ./cscope.out
+    :CCTreeAppendDB ./dir1/cscope.out
+    :CCTreeAppendDB ./dir2/cscope.out
+<
+    A database name, i.e., my_cscope.out, can be specified with 
+    the command. If not provided, a prompt will ask for the 
+    filename; default is cscope.out.
+
+FASTER DATABASE LOADING					*CCTree-fast-loading*
+
+Save native Xref Db~
+>
+	:CCTreeSaveXRefDb  cctree.out
+<
+This command will save the cross-referenced symbols currently loaded into 
+memory into a serialized format  for faster loading.
+
+Load native XRef Db~
+>
+	:CCTreeLoadXRefDb  cctree.out
+<
+This command will load cross-referenced symbols from the previously saved
+native format database.
+
+ccglue~
+                                                       *CCTree-ccglue*
+
+Check out the ccglue project at http://ccglue.sourceforge.net for an external
+tool that can build cctree-compatible xref databases.
+
+
+5.2. Exploring source-code~
+							*CCTree-explore-source*
+
+Get reverse call tree for symbol  <C-\><
+>
+	:CCTreeTraceReverse <symbolname>     
+<
+
+Get forward call tree for symbol  <C-\>>
+>
+	:CCTreeTraceForward <symbolname>
+<
+Increase depth of tree and update <C-\>=
+>
+	:CCTreeRecurseDepthPlus     
+<
+Decrease depth of tree and update <C-\>-
+>
+	:CCTreeRecurseDepthMinus    
+<
+5.3. Preview Window~
+						 *CCTree-preview-window*
+Open symbol in other window       <CR>
+Preview symbol in other window    <Ctrl-P>
+
+5.4. Syntax Coloring~
+						 *CCTree-Syntax*
+CCTreeHiXXXX allows dynamic highlighting of the call-tree.  To observe the
+effect, move the cursor to the function to highlight the current call-tree.
+This option can be turned off using the setting, *CCTreeHilightCallTree* . 
+
+For faster highlighting, the value of 'updatetime' can be changed.
+
+5.5 Support for large database files~
+				*CCTree-LargeDatabase* *CCTree-LargeFile*
+Vimscript does not have an API for reading files line-by-line. This
+becomes a problem when parsing large databases. CCTree can overcome
+the limitation using an external utility (i.e., GNU coreutils: split)
+or VimScript's perl interpreter interface (:version must indicate +perl)
+
+5.5.1 Using GNU Coreutils (split/cat)~
+				*CCTree-Tools-split* *CCTree-Tools-cat*
+	The following settings are tailored to suit GNU coreutils split; the
+default settings should work with no changes on typical linux/unix distros.
+Monopoly OSes will require installation of unixutils or equivalent.
+
+External command is setup with the following parameters~
+>
+	let g:CCTreeSplitProgCmd = 
+		'PROG_SPLIT SPLIT_OPT SPLIT_SIZE IN_FILE OUT_FILE_PREFIX'
+<
+
+Break-down of individual parameters~
+The split utility is assumed to be on the path; otherwise, specify full path
+	g:CCTreeSplitProg = 'split'
+
+Option for splitting files (-C or -l)~
+>
+	let g:CCTreeSplitProgOption = '-C'
+<
+If split program does not support -C, then this parameter must be set to 
+the number of lines in the split files
+>
+	let g:CCTreeDbFileSplitLines = -1
+<
+Largest filesize Vimscript can handle; file sizes greater than this will
+be temporarily split
+>
+	let g:CCTreeDbFileMaxSize  = 40000000 (40 Mbytes)
+<
+Sample system command~
+Typical:
+>
+	split -C 40000000 inputFile outputFilePrefix
+<
+ When g:CCTreeDbFileSplitLines is set to 10000 (-C options will be ignored)
+>
+	split -l 10000 inputFile outputFilePrefix
+<
+						*CCTree-Tools-Perl*
+						*CCTree-Tools-Perl-LargeFile*
+Enabling perl interface~
+
+	By default, perl usage is disabled. Set
+>
+	let g:CCTreeUsePerl = 1 
+<		 to enable the perl interface.
+
+	Perl interface is typically faster than native Vimscript.
+	This option can be used independent of the file size
+
+	For more info on setting up perl interface
+	:help |perl-using| or :help |perl-dynamic|
+
+5.6.	Miscellaneous				*CCTree-Miscellaneous*
+
+	UTF-8 usage				*CCTree-UTF8-Symbols*
+            UTF-8 symbols should work fine on the majority of
+        X11 systems; however, some terminals might cause problems.
+
+        To use symbols for drawing the tree, this option can be enabled.
+>
+            let g:CCTreeUseUTF8Symbols = 1 
+<
+        The options interface (CCTreeOptsxxx) can be used to 
+        modify options on-the-fly.
+
+==============================================================================
+6. Limitations~
+                                                *CCTree-limitations*
+
+The following are known limitations:
+
+Basic Symbol Processing:
+  (1) The accuracy of the call-tree will only be as good as the cscope database
+generation.  (NOTE: Different flavors of Cscope have some known limitations
+due to the lexical analysis engine. This results in incorrectly identified
+function blocks, etc.)
+
+Enhanced Symbol Processing:
+  (1) Cscope does not mark-up nameless enums correctly; hence,
+CCTree cannot recognize nameless enum symbols.
+
+
+==============================================================================
+7. FAQ~
+                                                *CCTree-faq*
+
++ I see strange characters "!#@" on my screen when dynamic highlighting is
+enabled. Why do I see them?
+  
+Check :hi ignore. You will see something like
+hi ignore ctermfg=white guifg=bg
+    
+  For console, white must be your background color; for GUI, guifg must be set
+to bg.
+
+==============================================================================
+8. History~
+                                                *CCTree-history*
+Version 1.51: May 18, 2011
+      1. Robust error reporting when external (split/cat) utils fail
+
+Version 1.50: May 6, 2011
+      1. Support cross-referencing of global variables, macros,
+         enums, and typedefs.
+
+Version 1.40: April 22, 2011
+      1. Maintain order of functions called during forward tracing
+
+Version 1.39: April 18, 2011
+      1. Use +Conceal feature for highlighting (only Vim 7.3)
+
+Version 1.33: April 5, 2011
+      1. Load and trace CCTree native XRefDb directly from disk
+      2. Fix AppendDB command when 'ignorecase' is set
+
+Version 1.26: March 28, 2011
+      1. Fix macro cross-referencing limitation
+      2. Correct native xref file format
+
+Version 1.21: March 21, 2011
+      1. Support serialization of loaded
+                cscope databases (for faster loading)
+
+Version 1.07: March 09, 2011
+      1. Fix new keymaps incorrectly applied to buffer
+      2. CCTreeOptsToggle command for toggling options
+
+Version 1.04: March 06, 2011
+      1. Customization for key mappings
+      2. Dynamic configuration of UI variables
+      3. Folding long call-trees to show current path dynamically
+
+Version 1.01: March 04, 2011
+      1. Make UTF-8 symbols for tree optional
+
+Version 1.00: March 02, 2011
+      1. Staging release for upcoming features
+         - Complete refactoring of code to take 
+                advantage of VimScript's OO features
+      2. Faster decompression of symbols
+      3. Display related changes
+         - Use of unicode symbols for tree
+      4. Bugfixes related to multi-database loading
+               
+Version 0.90: February 18, 2011
+      1. Support for large databases using external split utility or perl
+         interface
+
+Version 0.85: February 9, 2011
+      1. Significant increase in database loading and decompression speeds
+
+Version 0.80: February 4, 2011
+      1. Reduce memory usage by removing unused xref symbols
+
+Version 0.75: June 23, 2010
+	  1. Support for saving CCTree preview window; multiple 
+    	CCTree windows can now be open
+
+ersion 0.71: May 11, 2010
+	  1. Fix script bug
+
+Version 0.70: May 8, 2010
+	  1. Functionality to load multiple cscope databases
+
+Version 0.65: July 12, 2009
+	  1. Toggle preview window
+
+Version 0.61: December 24, 2008
+      1. Fixed bug when processing include files
+      2. Remove 'set ruler' option
+
+Version 0.60: November 26, 2008
+      1. Added support for source-file dependency tree
+
+Version 0.50: October 17, 2008
+      1. Optimizations for compact memory foot-print and 
+         improved compressed-database load speeds
+
+Version 0.41: October 6, 2008
+       1. Minor fix: Compressed cscope databases will load
+       incorrectly if encoding is not 8-bit
+
+Version 0.4: September 28, 2008
+      1. Rewrite of display-related code
+      2. New syntax hightlighting
+      3. Dynamic highlighting for call-trees
+      4. Support for new window modes (vertical, horizontal)  
+      5. New display format option for compact or wide call-trees
+      6. Preview window fix
+
+Version 0.3: September 21, 2008
+      1. Support compressed cscope databases
+      2. Display window related bugs fixed
+      3. More intuitive display and folding capabilities
+    
+Version 0.2: September 12, 2008
+      (Patches from Yegappan Lakshmanan, thanks!)
+      1. Support for using the plugin in Vi-compatible mode
+      2. Filtering out unwanted lines before processing the db
+      3. Command-line completion for the commands
+      4. Using the cscope db from any directory
+
+Version 0.1: August 31,2008
+      1. Cross-referencing support for only functions and macros
+         (Note: Functions inside macro definitions will be incorrectly
+         attributed to the top level calling function)
+
+
+==============================================================================
+9. Thanks~
+                                                 *CCTree-thanks*
+
+
+   Qaiser Durrani                 (ver 1.51 -- Reporting issues with SunOS)
+   Ben Fritz                      (ver 1.39 -- Suggestion/Testing for 
+                                                        conceal feature)
+   Ben Fritz                      (ver 1.26 -- Bug report)
+   Frank Chang                    (ver 1.0x -- testing/UI enhancement 
+                                                            ideas/bug fixes)
+   Arun Chaganty/Timo Tiefel	  (Ver 0.60 -- bug report)
+   Michael Wookey                 (Ver 0.40 -- Testing/bug report/patches)
+   Yegappan Lakshmanan            (Ver 0.20 -- Patches)
+
+   The Vim Community, ofcourse :)
+
+
+vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
+
diff -up /dev/null cscope-15.7a/contrib/cctree.vim
--- /dev/null	2011-05-25 12:40:15.391845002 -0400
+++ cscope-15.7a/contrib/cctree.vim	2011-05-26 14:45:02.906838571 -0400
@@ -0,0 +1,3398 @@
+" C Call-Tree Explorer (CCTree) <CCTree.vim>
+"
+"
+" Script Info and Documentation
+"=============================================================================
+"    Copyright: Copyright (C) August 2008 - 2011, Hari Rangarajan
+"               Permission is hereby granted to use and distribute this code,
+"               with or without modifications, provided that this copyright
+"               notice is copied with it. Like anything else that's free,
+"               cctree.vim is provided *as is* and comes with no
+"               warranty of any kind, either expressed or implied. In no
+"               event will the copyright holder be liable for any damamges
+"               resulting from the use of this software.
+"
+" Name Of File: CCTree.vim
+"  Description: C Call-Tree Explorer Vim Plugin
+"   Maintainer: Hari Rangarajan <hari.rangarajan@gmail.com>
+"          URL: http://vim.sourceforge.net/scripts/script.php?script_id=2368
+"  Last Change: May 18, 2011
+"      Version: 1.51
+"
+"=============================================================================
+"
+"  {{{ Description:
+"       Plugin generates dependency-trees for symbols using a cscope database
+"  in Vim.
+"  }}}
+"  {{{ Requirements: 1) Vim 7.xx , 2) Cscope
+"
+"                Tested on Unix and the following Win32 versions:
+"                + Cscope, mlcscope (WIN32)
+"                       http://code.google.com/p/cscope-win32/
+"                       http://www.bell-labs.com/project/wwexptools/packages.html
+"  }}}
+"  {{{ Installation:
+"               Copy this file to ~/.vim/plugins/
+"               or to /vimfiles/plugins/  (on Win32 platforms)
+"
+"               It might also be possible to load it as a filetype plugin
+"               ~/.vim/ftplugin/c/
+"
+"               Need to set :filetype plugin on
+"
+"  }}}
+"  {{{ Usage:
+"           Build cscope database, for example:
+"           > cscope -b -i cscope.files
+"               [Tip: add -c option to build uncompressed databases for faster
+"               load speeds]
+"
+"           Load database with command ":CCTreeLoadDB"
+"           (Please note that it might take a while depending on the
+"           database size)
+"
+"           Append database with command ":CCTreeAppendDB"
+"            Allows multiple cscope files to be loaded and cross-referenced
+"            Illustration:
+"            :CCTreeAppendDB ./cscope.out
+"            :CCTreeAppendDB ./dir1/cscope.out
+"            :CCTreeAppendDB ./dir2/cscope.out
+"
+"           A database name, i.e., my_cscope.out, can be specified with
+"           the command. If not provided, a prompt will ask for the
+"           filename; default is cscope.out.
+"
+"           To show loaded databases, use command ":CCTreeShowLoadedDBs"
+"
+"           To unload all databases, use command ":CCTreeUnLoadDB"
+"            Note: There is no provision to unload databases individually
+"
+"           To save the current set of databases loaded in to memory onto disk
+"           in native CCTree XRef format, use command ":CCTreeSaveXRefDB"
+"
+"           To load a saved native CCTree XRef format file, use
+"           command ":CCTreeLoadXRefDB"
+"
+"           To load a saved native CCTree XRef format file, use
+"           command ":CCTreeLoadXRefDBFromDisk"
+"
+"           Notes: No merging database support for CCTree native DB's [at present].
+"
+"
+"            To have multiple CCTree preview windows, use ":CCTreeWindowSaveCopy"
+"            Note: Once saved, only the depth of the preview window can be changed
+"
+"           Default Mappings:
+"             Get reverse call tree for symbol  <C-\><
+"             Get forward call tree for symbol  <C-\>>
+"             Increase depth of tree and update <C-\>=
+"             Decrease depth of tree and update <C-\>-
+"
+"             Open symbol in other window       <CR>
+"             Preview symbol in other window    <Ctrl-P>
+"
+"              Save copy of preview window       <C-\>y
+"             Highlight current call-tree flow  <C-l>
+"             Compress(Fold) call tree view     zs
+"             (This is useful for viewing long
+"              call trees which span across
+"              multiple pages)
+"
+"           Custom user-mappings:
+"           Users can custom-map the short-cut keys by
+"           overriding the following variables in their
+"           Vim start-up configuration
+"
+"            g:CCTreeKeyTraceForwardTree = '<C-\>>'
+"            g:CCTreeKeyTraceReverseTree = '<C-\><'
+"            g:CCTreeKeyHilightTree = '<C-l>'        " Static highlighting
+"            g:CCTreeKeySaveWindow = '<C-\>y'
+"            g:CCTreeKeyToggleWindow = '<C-\>w'
+"            g:CCTreeKeyCompressTree = 'zs'     " Compress call-tree
+"            g:CCTreeKeyDepthPlus = '<C-\>='
+"            g:CCTreeKeyDepthMinus = '<C-\>-'
+"
+"          Command List:
+"             CCTreeLoadDB                <dbname>
+"             CCTreeAppendDB              <dbname>
+"             CCTreeLoadXRefDB            <dbname>
+"             CCTreeSaveXRefDB            <dbname>
+"             CCTreeLoadXRefDBFromDisk    <dbname>
+"
+"             CCTreeUnLoadDB
+"             CCTreeShowLoadedDBs
+"
+"             CCTreeTraceForward          <symbolname>
+"             CCTreeTraceReverse          <symbolname>
+"             CCTreeRecurseDepthPlus
+"             CCTreeRecurseDepthMinus
+"             CCTreeWindowSaveCopy
+"
+"          Only in preview window:
+"             CCTreeWindowHiCallTree   (same as <C-l> shorcut)
+"                   Highlight calling tree for keyword at cursor
+"
+"          Dynamic configuration:
+"             CCTreeOptsEnable <option>    (<tab> for auto-complete)
+"             CCTreeOptsDisable <option>   (<tab> for auto-complete)
+"             CCTreeOptsToggle <option>   (<tab> for auto-complete)
+"             Options:
+"                   DynamicTreeHiLights: Control dynamic tree highlighting
+"                   UseUnicodeSymbols: Use of UTF-8 special characters for
+"                                      tree
+"                   UseConceal: Use (+Conceal) feature instead of 'ignore'
+"                               syntax highlighting. Allows CCTree window
+"                               to be exported in HTML without syntax markup
+"                               characters. (Vim 7.3+ only)
+"                   EnhancedSymbolProcessing: Cross-reference enums, macros,
+"                               global variables, typedefs (Warning: Database
+"                               processing speeds will be slow).
+"
+"
+"
+"          Settings:
+"               Customize behavior by changing the variable settings
+"
+"               UTF-8 usage:
+"                   UTF-8 symbols should work fine on the majority of
+"               X11 systems; however, some terminals might cause problems.
+"
+"               To use symbols for drawing the tree, this option can be enabled.
+"                   g:CCTreeUseUTF8Symbols = 1
+"               The options interface (CCTreeOptsxxx) can be used to
+"               modify options on-the-fly.
+"
+"               Cscope database file, g:CCTreeCscopeDb = "cscope.out"
+"               Maximum call levels,   g:CCTreeRecursiveDepth = 3
+"               Maximum visible(unfolded) level, g:CCTreeMinVisibleDepth = 3
+"               Orientation of window,  g:CCTreeOrientation = "topleft"
+"                (standard vim options for split: [right|left][above|below])
+"
+"               Use Vertical window, g:CCTreeWindowVertical = 1
+"                   Min width for window, g:CCTreeWindowMinWidth = 40
+"                   g:CCTreeWindowWidth = -1, auto-select best width to fit
+"
+"               Horizontal window, g:CCTreeWindowHeight, default is -1
+"
+"
+"               Display format, g:CCTreeDisplayMode, default 1
+"
+"               Values: 1 -- Ultra-compact (takes minimum screen width)
+"                       2 -- Compact       (Takes little more space)
+"                       3 -- Wide          (Takes copious amounts of space)
+"
+"               For vertical splits, 1 and 2 are good, while 3 is good for
+"               horizontal displays
+"
+"               NOTE: To get older behavior, add the following to your vimrc
+"               let g:CCTreeDisplayMode = 3
+"               let g:CCTreeWindowVertical = 0
+"
+"               Syntax Coloring:
+"                    CCTreeSymbol is the symbol name
+"                    CCTreeMarkers include  "|","+--->"
+"
+"                    CCTreeHiSymbol is the highlighted call tree functions
+"                    CCTreeHiMarkers is the same as CCTreeMarkers except
+"                           these denote the highlighted call-tree
+"
+"
+"                    CCTreeHiXXXX allows dynamic highlighting of the call-tree.
+"                    To observe the effect, move the cursor to the function to
+"                    highlight the current call-tree. This option can be
+"                    turned off using the setting, g:CCTreeHilightCallTree.
+"                    For faster highlighting, the value of 'updatetime' can be
+"                    changed.
+"
+"               Support for large database files:
+"                 Vimscript does not have an API for reading files line-by-line. This
+"                becomes a problem when parsing large databases. CCTree can overcome
+"                the limitation using an external utility (i.e., GNU coreutils: split)
+"                or VimScript's perl interpreter interface (:version must indicate +perl)
+"
+"                The following settings are tailored to suit GNU coreutils split; the default
+"                settings should work with no changes on typical linux/unix distros
+"                (Monopoly OSes will require installation of unixutils or equivalent)
+"
+"                External command is setup with the following parameters:
+"                g:CCTreeSplitProgCmd = 'PROG_SPLIT SPLIT_OPT SPLIT_SIZE IN_FILE OUT_FILE_PREFIX'
+"
+"                Break-down of individual parameters:
+"                The split utility is assumed to be on the path; otherwise, specify full path
+"                            g:CCTreeSplitProg = 'split'
+"
+"                Option for splitting files (-C or -l)
+"                            g:CCTreeSplitProgOption = '-C'
+"                 If split program does not support -C, then this parameter must be set to
+"                 the number of lines in the split files
+"                         g:CCTreeDbFileSplitLines = -1
+"                Largest filesize Vimscript can handle; file sizes greater than this will
+"                be temporarily split
+"                        g:CCTreeDbFileMaxSize  = 40000000 (40 Mbytes)
+"
+"                Sample system command:
+"                Typical:
+"                        split -C 40000000 inputFile outputFilePrefix
+"
+"                 When g:CCTreeDbFileSplitLines is set to 10000 (-C options will be ignored)
+"                        split -l 10000 inputFile outputFilePrefix
+"
+"
+"                Using perl interface:
+"                        By default, perl usage is disabled. Set
+"                        g:CCTreeUsePerl = 1  to enable the perl interface.
+"
+"                        Perl interface is typically faster than native Vimscript.
+"                        This option can be used independent of the file size
+"
+"                        For more info on setting up perl interface
+"                        :help perl-using or :help perl-dynamic
+"
+"               Writing large Xref Databases:
+"                   CCTree can use external utilities to write extremely large files beyond
+"               VimScripts capabilities. It requires the use of an external tool that can
+"               join text files (i.e., 'cat' in unix). This utility is triggered if the size
+"               of the file being written exceeds g:CCTreeDbFileMaxSize (40 Mb or as configured)
+"
+"               The join utility command is configured by default as follows:
+"               let CCTreeJoinProgCmd = 'PROG_JOIN JOIN_OPT IN_FILES > OUT_FILE'
+"
+"               let  g:CCTreeJoinProg = 'cat'           " PROG_JOIN
+"               let  g:CCTreeJoinProgOpts = ""          " JOIN_OPT
+"
+"
+"  }}}
+"  {{{ Limitations:
+"           Basic Symbol Processing:
+"               The accuracy of the call-tree will only be as good as the cscope
+"           database generation.
+"               NOTE: Different flavors of Cscope have some known
+"                 limitations due to the lexical analysis engine. This results
+"                 in incorrectly identified function blocks, etc.
+"           Enhanced Symbol Processing:
+"               (1) Cscope does not mark-up nameless enums correctly; hence,
+"               CCTree cannot recognize nameless enum symbols.
+"  }}}
+"  {{{ History:
+"           Version 1.51: May 18, 2011
+"                 1. Robust error reporting when external (split/cat) utils fail
+"           Version 1.50: May 6, 2011
+"                 1. Support cross-referencing of global variables, macros,
+"                    enums, and typedefs.
+"           Version 1.40: April 22, 2011
+"                 1. Maintain order of functions called during forward tracing
+"           Version 1.39: April 18, 2011
+"                 1. Use +Conceal feature for highlighting (only Vim 7.3)
+"           Version 1.33: April 5, 2011
+"                 1. Load and trace CCTree native XRefDb directly from disk
+"                 2. Fix AppendDB command when 'ignorecase' is set
+"           Version 1.26: March 28, 2011
+"                 1. Fix macro cross-referencing limitation
+"                 2. Correct native xref file format
+"           Version 1.21: March 21, 2011
+"                 1. Support serialization of loaded
+"                           cscope databases (for faster loading)
+"           Version 1.07: March 09, 2011
+"                 1. Fix new keymaps incorrectly applied to buffer
+"                 2. CCTreeOptsToggle command for toggling options
+"
+"           Version 1.04: March 06, 2011
+"                 1. Customization for key mappings
+"                 2. Dynamic configuration of UI variables
+"                 3. Folding long call-trees to show current path dynamically
+"
+"           Version 1.01: March 04, 2011
+"                 1. Make UTF-8 symbols for tree optional
+"
+"           Version 1.00: March 02, 2011
+"                 1. Staging release for upcoming features
+"                    - Complete refactoring of code to take
+"                           advantage of VimScript's OO features
+"                 2. Faster decompression of symbols
+"                 3. Display related changes
+"                    - Use of unicode symbols for tree
+"                 4. Bugfixes related to multi-database loading
+"
+"            Version 0.90: February 18, 2011
+"                  1. Support for large databases using external split utility or perl
+"                     interface
+"
+"           Version 0.85: February 9, 2011
+"                 1. Significant increase in database loading and decompression speeds
+"
+"           Version 0.80: February 4, 2011
+"                 1. Reduce memory usage by removing unused xref symbols
+"
+"           Version 0.75: June 23, 2010
+"                     1. Support for saving CCTree preview window; multiple
+"                        CCTree windows can now be open
+"
+"          Version 0.71: May 11, 2010
+"                     1. Fix script bug
+
+"           Version 0.70: May 8, 2010
+"                     1. Functionality to load multiple cscope databases
+"
+"           Version 0.65: July 12, 2009
+"                     1. Toggle preview window
+"
+"           Version 0.61: December 24, 2008
+"                 1. Fixed bug when processing include files
+"                 2. Remove 'set ruler' option
+"
+"           Version 0.60: November 26, 2008
+"                 1. Added support for source-file dependency tree
+"
+"           Version 0.50: October 17, 2008
+"                 1. Optimizations for compact memory foot-print and
+"                    improved compressed-database load speeds
+"
+"           Version 0.41: October 6, 2008
+"                  1. Minor fix: Compressed cscope databases will load
+"                  incorrectly if encoding is not 8-bit
+"
+"           Version 0.4: September 28, 2008
+"                  1. Rewrite of "tree-display" code
+"                  2. New syntax hightlighting
+"                  3. Dynamic highlighting for call-trees
+"                  4. Support for new window modes (vertical, horizontal)
+"                  5. New display format option for compact or wide call-trees
+"                  NOTE: defaults for tree-orientation set to vertical
+"
+"           Version 0.3:
+"               September 21, 2008
+"                 1. Support compressed cscope databases
+"                 2. Display window related bugs fixed
+"                 3. More intuitive display and folding capabilities
+"
+"           Version 0.2:
+"               September 12, 2008
+"               (Patches from Yegappan Lakshmanan, thanks!)
+"                 1. Support for using the plugin in Vi-compatible mode.
+"                 2. Filtering out unwanted lines before processing the db.
+"                 3. Command-line completion for the commands.
+"                 4. Using the cscope db from any directory.
+"
+"           Version 0.1:
+"                August 31,2008
+"                 1. Cross-referencing support for only functions and macros
+"                    Functions inside macro definitions will be incorrectly
+"                    attributed to the top level calling function
+"
+"   }}}
+"   {{{ Thanks:
+"
+"    Qaiser Durrani                 (ver 1.51 -- Reporting issues with SunOS)
+"    Ben Fritz                      (ver 1.39 -- Suggestion/Testing for conceal feature)
+"    Ben Fritz                      (ver 1.26 -- Bug report)
+"    Frank Chang                    (ver 1.0x -- testing/UI enhancement ideas/bug fixes)
+"    Arun Chaganty/Timo Tiefel            (Ver 0.60 -- bug report)
+"    Michael Wookey                 (Ver 0.4 -- Testing/bug report/patches)
+"    Yegappan Lakshmanan            (Ver 0.2 -- Patches)
+"
+"    The Vim Community, ofcourse :)
+"=============================================================================
+"    }}}
+
+" {{{ Init
+if !exists('loaded_cctree') && v:version >= 700
+  " First time loading the cctree plugin
+  let loaded_cctree = 1
+else
+  "finish
+endif
+
+" Line continuation used here
+let s:cpo_save = &cpoptions
+set cpoptions&vim
+
+" Trick to get the current script ID
+map <SID>xx <SID>xx
+let s:sid = substitute(maparg('<SID>xx'), '<SNR>\(\d\+_\)xx$', '\1', '')
+unmap <SID>xx
+"}}}
+" {{{ Global variables; Modify in .vimrc to modify default behavior
+" {{{General
+if !exists('CCTreeCscopeDb')
+    let CCTreeCscopeDb = "cscope.out"
+endif
+" revisit
+if !exists('CCTreeDb')
+    let CCTreeDb = "cctree.out"
+endif
+if !exists('CCTreeRecursiveDepth')
+    let CCTreeRecursiveDepth = 3
+endif
+if !exists('CCTreeMinVisibleDepth')
+    let CCTreeMinVisibleDepth = 3
+endif
+if !exists('CCTreeEnhancedSymbolProcessing')
+    let CCTreeEnhancedSymbolProcessing = 0
+endif
+" }}}
+" {{{ Custom user-key mappings
+if !exists('CCTreeKeyTraceForwardTree')
+    let g:CCTreeKeyTraceForwardTree = '<C-\>>'
+endif
+if !exists('CCTreeKeyTraceReverseTree')
+    let g:CCTreeKeyTraceReverseTree = '<C-\><'
+endif
+if !exists('CCTreeKeyHilightTree')
+    let g:CCTreeKeyHilightTree = '<C-l>'        " Static highlighting
+endif
+if !exists('CCTreeKeySaveWindow ')
+    let g:CCTreeKeySaveWindow = '<C-\>y'
+endif
+if !exists('CCTreeKeyToggleWindow ')
+    let g:CCTreeKeyToggleWindow = '<C-\>w'
+endif
+if !exists('CCTreeKeyCompressTree ')
+    let g:CCTreeKeyCompressTree = 'zs'     " Compress call-tree
+endif
+if !exists('CCTreeKeyDepthPlus')
+    let g:CCTreeKeyDepthPlus = '<C-\>='
+endif
+if !exists('CCTreeKeyDepthMinus')
+    let g:CCTreeKeyDepthMinus = '<C-\>-'
+endif
+" }}}
+" {{{ CCTree UI settings
+if !exists('CCTreeOrientation')
+    let CCTreeOrientation = "topleft"
+endif
+if !exists('CCTreeWindowVertical')
+    let CCTreeWindowVertical = 1
+endif
+if !exists('CCTreeWindowWidth')
+    " -1 is auto select best width
+    let CCTreeWindowWidth = -1
+endif
+if !exists('CCTreeWindowMinWidth')
+    let CCTreeWindowMinWidth = 25
+endif
+if !exists('CCTreeWindowHeight')
+    let CCTreeWindowHeight = -1
+endif
+if !exists('CCTreeDisplayMode')
+    let CCTreeDisplayMode = 1
+endif
+if !exists('CCTreeHilightCallTree')
+    let CCTreeHilightCallTree = 1
+endif
+" }}}
+" {{{ Split prog
+if !exists('CCTreeSplitProgCmd')
+    let CCTreeSplitProgCmd = 'PROG_SPLIT SPLIT_OPT SPLIT_SIZE IN_FILE OUT_FILE_PREFIX'
+endif
+
+if !exists('CCTreeSplitProg')
+    "PROG_SPLIT
+    let CCTreeSplitProg = 'split'
+endif
+
+if !exists('CCTreeSplitProgOption')
+    "SPLIT_OPT
+    let CCTreeSplitProgOption = '-C'
+endif
+
+if !exists('CCTreeDbFileSplitLines')
+    " if SPLIT_OPT is -l
+    " If split program does not support -C, then this parameter must be set to
+    " the number of lines in the split files
+    let CCTreeDbFileSplitLines = -1
+endif
+
+if !exists('CCTreeSplitProgCmd')
+    let CCTreeSplitProgCmd = 'PROG_SPLIT SPLIT_OPT SPLIT_SIZE IN_FILE OUT_FILE_PREFIX'
+endif
+
+if !exists('CCTreeDbFileMaxSize')
+    " if SPLIT_OPT is -C
+    let CCTreeDbFileMaxSize = 40000000 "40 Mbytes
+endif
+
+" }}}
+" {{{ Join/Cat prog
+if !exists('CCTreeJoinProgCmd')
+    let CCTreeJoinProgCmd = 'PROG_JOIN JOIN_OPT IN_FILES > OUT_FILE'
+endif
+
+if !exists('CCTreeJoinProg')
+    "PROG_JOIN
+    let CCTreeJoinProg = 'cat'
+endif
+
+if !exists('CCTreeJoinProgOpts')
+    let CCTreeJoinProgOpts = ""
+endif
+" }}}
+" {{{ Misc (perl)
+if !exists('CCTreeUsePerl')
+    " Disabled by default
+    let CCTreeUsePerl = 0
+if 0        " Auto-detect perl interface (Experimental code)
+    if has('perl)
+perl << PERL_EOF
+        VIM::DoCommand("let CCTreeUsePerl = 1");
+PERL_EOF
+    endif
+endif
+endif
+
+if has('conceal')
+    let s:CCTreeUseConceal = 1
+else
+    let s:CCTreeUseConceal = 0
+endif
+
+if !exists('CCTreeUseUTF8Symbols')
+    let CCTreeUseUTF8Symbols = 0
+endif
+" }}}
+" }}}
+" {{{ Plugin related local variables
+let s:pluginname = 'CCTree'
+let s:windowtitle = 'CCTree-View'
+let s:windowsavetitle = 'CCTree-View-Copy'
+
+let s:DBClasses = { 'cscopeid': 'Cscope', 'cctreexref' : 'CCTree XRef'}
+let s:DBStorage = { 'memory': 'Memory', 'disk' : 'Disk'}
+
+" }}}
+" {{{ Turn on/off debugs
+let s:tag_debug=0
+
+" Use the Decho plugin for debugging
+function! DBGecho(...)
+    if s:tag_debug
+        Decho(a:000)
+    endif
+endfunction
+
+function! DBGredir(...)
+    if s:tag_debug
+        Decho(a:000)
+    endif
+endfunction
+
+function! Pause()
+    call input("sasasD", "asdads")
+endfunction
+" }}}
+" {{{ Progress bar (generic, numeric, rolling)
+let s:GenericProgressBar= {
+                \ 'depth': 0,
+                \ 'depthChar': '',
+                \ 'currentChar': 0,
+                \ 'updateTime': 0,
+                \ 'rangeChars': [],
+                \ 'formatStr' : '',
+                \ 'units' : ''
+                \ }
+
+function! s:GenericProgressBar.mCreate(rangechars, depthchar, fmtStr)
+    let pbr = deepcopy(s:GenericProgressBar)
+    unlet pbr.mCreate
+
+    let pbr.rangeChars = a:rangechars
+    let pbr.depthChar = a:depthchar
+    let pbr.formatStr = a:fmtStr
+
+    return pbr
+endfunction
+
+function! s:GenericProgressBar.mSetDepth(val) dict
+    let self.depth = a:val
+endfunction
+
+function! s:GenericProgressBar.mUpdate() dict
+    let staticchars = repeat(self.depthChar, self.depth)
+    let displayStr = substitute(self.formatStr, "\@PROGRESS\@",
+                       \ staticchars . self.rangeChars[self.currentChar], "")
+    call s:StatusLine.mSetExtraInfo(displayStr)
+endfunction
+
+function! s:GenericProgressBar.mDone()
+        call s:StatusLine.mSetExtraInfo("")
+endfunction
+
+let s:ProgressBarRoll = {
+                        \ 'updateTime' : 0,
+                        \ 'curTime' : 0
+                        \}
+
+function! s:ProgressBarRoll.mCreate(rollchars, depthChar) dict
+    let gpbr = s:GenericProgressBar.mCreate(a:rollchars, a:depthChar, "\@PROGRESS\@")
+    let pbr = extend(gpbr, deepcopy(s:ProgressBarRoll))
+    unlet pbr.mCreate
+
+    let pbr.curTime = localtime()
+
+    return pbr
+endfunction
+
+function! s:ProgressBarRoll.mTick(count) dict
+    if (localtime() - self.curTime) > self.updateTime
+        let self.currentChar += 1
+        if self.currentChar == len(self.rangeChars)
+            let self.currentChar = 0
+        endif
+        let self.curTime = localtime()
+        call self.mUpdate()
+    endif
+endfunction
+
+let s:ProgressBarNumeric = {
+                \ 'progress1current' : 0,
+                \ 'progressmax' : 0,
+                \ 'progress1percent' : 0,
+                \ 'progresspercent' : 0,
+                \}
+
+function! s:ProgressBarNumeric.mCreate(maxcount, unit) dict
+        let gpbr = s:GenericProgressBar.mCreate(range(0,200), '',
+            \ "Processing \@PROGRESS\@\%, total ". a:maxcount . " " . a:unit)
+        let progressbar = extend(gpbr, deepcopy(s:ProgressBarNumeric))
+        unlet progressbar.mCreate
+
+        let progressbar.progressmax = a:maxcount
+        let progressbar.progress1percent = a:maxcount/100
+
+        let progressbar.units = a:unit
+
+        return progressbar
+endfunction
+
+
+function! s:ProgressBarNumeric.mTick(count) dict
+        let self.progress1current += a:count
+        if self.progress1percent <= self.progress1current
+            let tmp =  (self.progress1current/self.progress1percent)
+            let self.progresspercent += tmp
+            let self.progress1current -= tmp * self.progress1percent
+            let self.currentChar += 1
+            call self.mUpdate()
+        endif
+endfunction
+
+" }}}
+" {{{ Status line
+let s:StatusLine = {
+                    \ 'symlastprogress' : 0,
+                    \ 'symprogress' : 0,
+                    \ 'cursym' : 0,
+                    \ 'savedStatusLine' : '',
+                    \ 'statusextra' : '',
+                    \ 'local':0
+                    \}
+
+function! s:StatusLine.mInit() dict
+    let self.savedStatusLine = &l:statusline
+    setlocal statusline=%{CCTreeStatusLine()}
+endfunction
+
+function! s:StatusLine.mRestore() dict
+    let self.currentstatus = ''
+    let self.statusextra = ''
+
+    let &l:statusline = s:StatusLine.savedStatusLine
+    redrawstatus
+endfunction
+
+function! s:StatusLine.mSetInfo(msg) dict
+    let s:StatusLine.currentstatus = a:msg
+    redrawstatus
+endfunction
+
+function! s:StatusLine.mSetExtraInfo(msg) dict
+    let s:StatusLine.statusextra = a:msg
+    redrawstatus
+endfunction
+
+function! CCTreeStatusLine()
+    return   s:pluginname. " ".
+           \ s:StatusLine.currentstatus . " -- ".
+           \ s:StatusLine.statusextra
+endfunction
+"}}}
+" {{{ Shell command interface
+
+let s:ShellCmds = {'shellOutput': ''}
+
+function! s:ShellCmds.mSplit(inFile, outFile)
+        let cmdEx = substitute(g:CCTreeSplitProgCmd, "PROG_SPLIT", g:CCTreeSplitProg,"")
+        let cmdEx = substitute(cmdEx, "SPLIT_OPT", g:CCTreeSplitProgOption,"")
+        if g:CCTreeDbFileSplitLines != -1
+                let cmdEx = substitute(cmdEx, "SPLIT_SIZE", g:CCTreeDbFileSplitLines,"")
+        else
+                let cmdEx = substitute(cmdEx, "SPLIT_SIZE", g:CCTreeDbFileMaxSize,"")
+        endif
+        let cmdEx = substitute(cmdEx, "IN_FILE", a:inFile,"")
+        let cmdEx = substitute(cmdEx, "OUT_FILE_PREFIX", a:outFile,"")
+
+        return cmdEx
+endfunction
+
+function! s:ShellCmds.mJoin(inFileList, outFile)
+        let cmdEx = substitute(g:CCTreeJoinProgCmd, "PROG_JOIN", g:CCTreeJoinProg,"")
+        let cmdEx = substitute(cmdEx, "JOIN_OPT", g:CCTreeJoinProgOpts,"")
+        let cmdEx = substitute(cmdEx, "IN_FILES", a:inFileList,"")
+        let cmdEx = substitute(cmdEx, "OUT_FILE", a:outFile,"")
+
+        return cmdEx
+endfunction
+
+function! s:ShellCmds.mExec(cmd)
+    let s:shellOutput= system(a:cmd)
+    if s:shellOutput != ''
+         " Failed
+         return s:CCTreeRC.Error
+    endif
+    return s:CCTreeRC.Success
+endfunction
+
+" }}}
+
+" {{{ Virtual file interface
+let s:vFile = {}
+
+function! s:vFile.mCreate(fname, mode)
+    if a:mode == 'r'
+        return s:vFileR.mCreate(a:fname)
+    elseif a:mode == 'w'
+        return s:vFileW.mCreate(a:fname)
+    endif
+    return -1
+endfunction
+
+let s:vFileW = {
+            \ 'splitfiles' : [],
+            \ 'totSplits' : 0,
+            \ 'lines' : [],
+            \ 'fileSize' : 0
+            \}
+
+function! s:vFileW.mCreate(fname)  dict
+        let vfile =  deepcopy(s:vFileW)
+        unlet vfile.mCreate
+        let vfile.link = a:fname
+
+        return vfile
+endfunction
+
+function! s:vFileW.mCreateSplit()  dict
+    " first split, create name
+    if self.totSplits == 0
+        let self.tlink =  tempname()
+    endif
+    let fname = self.tlink .'_'. self.totSplits
+    call writefile(self.lines, fname)
+    call add(self.splitfiles, fname)
+    let self.lines = []
+    let self.totSplits += 1
+endfunction
+
+function! s:vFileW.mTestForSplit()  dict
+    if self.fileSize > g:CCTreeDbFileMaxSize
+        call self.mCreateSplit()
+    endif
+endfunction
+
+function! s:vFileW.mAddFileSize(size)  dict
+    let self.fileSize += a:size
+endfunction
+
+function! s:vFileW.mWriteList(linelist)  dict
+    call extend(self.lines, a:linelist)
+    call self.mTestForSplit()
+endfunction
+
+function! s:vFileW.mWriteLine(line)  dict
+    call add(self.lines, a:line)
+    call self.mAddFileSize(len(a:line))
+    call self.mTestForSplit()
+endfunction
+
+function! s:vFileW.mClose()  dict
+    if self.totSplits == 0
+        call writefile(self.lines, self.link)
+    else
+        " force remaining lines into a new split
+        call self.mCreateSplit()
+        " now join all of them
+        let filelist = join(self.splitfiles, " ")
+        let cmdEx = s:ShellCmds.mJoin(filelist, self.link)
+        if s:ShellCmds.mExec(cmdEx) != s:CCTreeRC.Success
+            let msg =  s:shellOutput ."Shell command: ".cmdEx. " failed!".
+                        \ " Refer help to setup split/join utils."
+            call s:CCTreeUtils.mWarningPrompt(msg)
+        endif
+    endif
+    for afile in self.splitfiles
+       call delete(afile)
+    endfor
+    return 0
+endfunction
+
+let s:vFileR = {
+            \ 'splitfiles' : [],
+            \ 'currentSplitIdx' : 0,
+            \ 'totSplits' : 0,
+            \ 'lines' : [],
+            \ 'valid' : 0,
+            \ 'mode' : ""
+            \}
+
+
+function! s:vFileR.mIsLargeFile()  dict
+        if (getfsize(self.link) > g:CCTreeDbFileMaxSize)
+                return 1
+        endif
+        return 0
+endfunction
+
+function! s:vFileR.mCreate(fname)  dict
+        let vfile =  deepcopy(s:vFileR)
+        unlet vfile.mCreate
+        let vfile.link = a:fname
+        let vfile.valid = filereadable(a:fname)
+        let vfile.size = getfsize(a:fname)
+
+        return vfile
+endfunction
+
+function! s:vFileR.mOpen()  dict
+        if self.mode == 'w'
+            " no need to do anything
+            return 0
+        endif
+
+        if self.mIsLargeFile() == 0
+                "little trick to keep interface uniform when we don't split
+                call add(self.splitfiles, self.link)
+                let self.totSplits = 1
+        else
+                let tmpDb = tempname()
+                let cmdEx = s:ShellCmds.mSplit(self.link, tmpDb)
+
+                if s:ShellCmds.mExec(cmdEx) != s:CCTreeRC.Success
+                     let msg =  s:shellOutput ."Shell command: ".cmdEx. " failed!".
+                             \ " Refer help to setup split/join utils."
+                     call s:CCTreeUtils.mWarningPrompt(msg)
+                     return -1
+                else
+                     let self.splitfiles = split(expand(tmpDb."*"), "\n")
+                endif
+                if empty(self.splitfiles)
+                     return -1
+                endif
+        endif
+        let self.totSplits = len(self.splitfiles)
+        return 0
+endfunction
+
+function! s:vFileR.mRead()  dict
+        if (self.currentSplitIdx >= len(self.splitfiles))
+                " out of bounds
+                return -1
+        endif
+        let self.lines = readfile(self.splitfiles[self.currentSplitIdx])
+        let self.currentSplitIdx += 1
+        return 0
+endfunction
+
+function! s:vFileR.mRewind()  dict
+        let self.currentSplitIdx = 0
+        let self.lines = []
+endfunction
+
+
+function! s:vFileR.mClose()  dict
+        if self.totSplits == 1
+            return
+        endif
+        for afile in self.splitfiles
+           call delete(afile)
+        endfor
+endfunction
+"}}}
+" {{{Stop watch
+let s:StopWatch = {
+                        \ 'text' : "(no reltime feature)",
+                          \}
+
+function! s:StopWatch.mCreate()        dict
+    let stopWatch = deepcopy(s:StopWatch)
+    unlet stopWatch.mCreate
+
+    call stopWatch.mReset()
+    return stopWatch
+endfunction
+
+function! s:StopWatch.mReset()        dict
+    if has('reltime')
+        let self.startRTime = reltime()
+    else
+        let self.startRTime = localtime()
+    endif
+endfunction
+
+function! s:StopWatch.mSnapElapsed()  dict
+    if has('reltime')
+        let self.text = reltimestr(reltime(self.startRTime))
+    else
+        let self.text = localtime() - self.startRTime
+    endif
+endfunction
+
+function! s:StopWatch.mGetText()   dict
+        return self.text
+endfunction
+"}}}
+" {{{ Digraph character compression/decompression routines
+
+let s:CharMaps = {
+                    \'savedEncoding' : '',
+                    \'mapkind' : ''
+                    \}
+
+" The encoding needs to be changed to 8-bit, otherwise we can't swap special
+" 8-bit characters; restore after done
+function! s:CharMaps.mInitTranslator() dict
+        if self.mapkind ==  'Alpha'
+            let self.savedEncoding = &encoding
+            let &encoding="latin1"
+        endif
+endfunction
+
+function! s:CharMaps.mDoneTranslator() dict
+        if self.mapkind ==  'Alpha'
+            let &encoding=self.savedEncoding
+        endif
+endfunction
+
+function! s:CharMaps.CrossProduct(seq1, seq2) dict
+    let cpSeq = []
+    for dc1 in range(strlen(a:seq1))
+        for dc2 in range(strlen(a:seq2))
+           call add(cpSeq, a:seq1[dc1].a:seq2[dc2])
+        endfor
+    endfor
+    return cpSeq
+endfunction
+
+let s:TranslateMap = {}
+
+function! s:TranslateMap.mCreate (srcsym, destsym, mapkind, regex) dict
+    let dicttable = extend(deepcopy(s:CharMaps), deepcopy(s:TranslateMap))
+    unlet dicttable.CrossProduct
+
+    let dicttable.mappings = {}
+
+    " map lower
+    let maxsym = min([len(a:srcsym),len (a:destsym)])
+
+    let index = 0
+    while (index < maxsym)
+        let dicttable.mappings[a:srcsym[index]] =  a:destsym[index]
+        let index += 1
+    endwhile
+    " Need mapping lens, we assume it's constant across the board
+    let dicttable.mapsrclen = len(a:srcsym[0])
+    let dicttable.regex = a:regex
+
+
+    if a:mapkind == 'Alpha'
+        let dicttable.mTranslate = dicttable.mTranslateAlpha
+    elseif a:mapkind == 'Numeric'
+        let dicttable.mTranslate = dicttable.mTranslateNumeric
+    endif
+
+    let dicttable.mapkind = a:mapkind
+
+    unlet dicttable.mTranslateNumeric
+    unlet dicttable.mTranslateAlpha
+
+    return dicttable
+endfunction
+
+
+function! s:TranslateMap.mTranslateNumeric(value) dict
+    let index = 0
+    let retval = ""
+
+    " remember to deal with multi-byte characters
+    while index < len(a:value)
+        let char1 = char2nr(a:value[index])
+        if has_key(self.mappings, char1)
+                let newmap = self.mappings[char1]
+        else
+                " take only the first character
+                let newmap = a:value[index]
+        endif
+        let retval .= newmap
+        let index += 1
+    endwhile
+    return retval
+endfunction
+
+function! s:TranslateMap.mTranslateAlpha(value) dict
+    let retval = substitute(a:value, self.regex, '\=self.mappings[submatch(1)]', "g")
+    return retval
+endfunction
+
+function! s:CCTreeGetXRefDbMaps(maptype, mapkind)
+        let dichar1 = ",0123456789"
+        let dichar2 = ",0123456789"
+
+        return s:CCTreeCreateGenericMaps(a:maptype, a:mapkind, dichar1, dichar2)
+endfunction
+
+function! s:CCTreeGetCscopeMaps(maptype, mapkind)
+        let dichar1 = " teisaprnl(of)=c"
+        let dichar2 = " tnerpla"
+
+        return s:CCTreeCreateGenericMaps(a:maptype, a:mapkind, dichar1, dichar2)
+endfunction
+
+
+function! s:CCTreeCreateGenericMaps(maptype, mapkind, dichar1, dichar2)
+        let s:CharMaps.mapkind = a:mapkind
+        call s:CharMaps.mInitTranslator()
+        if a:mapkind == 'Numeric'
+            let ab = map(range(128,255), 'v:val')
+        elseif a:mapkind == 'Alpha'
+            let ab = map(range(128,255), 'nr2char(v:val)')
+        else
+            return {}
+        endif
+        let ac =  s:CharMaps.CrossProduct(a:dichar1, a:dichar2)
+        if a:maptype == 'Compress'
+                let maps = s:TranslateMap.mCreate(ac, ab, a:mapkind,
+                                \'\(['.a:dichar1.']['.a:dichar2.']\)\C')
+        elseif a:maptype == 'Uncompress'
+                let maps = s:TranslateMap.mCreate(ab, ac, a:mapkind,
+                                \'\([\d128-\d255]\)')
+        endif
+        call s:CharMaps.mDoneTranslator()
+        return maps
+endfunction
+" }}}
+" {{{ Unique list filter object
+
+let s:UniqList = {}
+
+function! s:UniqList.mFilterEntries(lstval) dict
+        let valdict = {}
+        let reslist = ''
+        for aval in a:lstval
+            if !has_key(valdict, aval)
+                let valdict[aval] = ''
+                let reslist .= (aval . ",")
+            endif
+        endfor
+        return reslist
+endfunction
+
+let s:CCTreeUniqListFilter = deepcopy(s:UniqList)
+function! s:CCTreeMakeCommaListUnique(clist)
+        let entries = split(a:clist, ",")
+        if len(entries) > 0
+            return s:CCTreeUniqListFilter.mFilterEntries(entries)
+        endif
+        return ""
+endfunction
+" }}}
+" {{{ Buffer/Window
+func! s:FindOpenBuffer(filename)
+    let bnrHigh = bufnr("$")
+    "tabpagebuflist(tabpagenr())
+
+    for bufnrs in range(1, bnrHigh)
+        if (bufexists(bufnrs) == 1 && bufname(bufnrs) == a:filename && bufloaded(bufnrs) != 0 )
+            return bufnrs
+        endif
+    endfor
+    " Could not find the buffer
+    return 0
+endfunction
+
+func! s:FindOpenWindow(filename)
+    let bufnr = s:FindOpenBuffer(a:filename)
+    if (bufnr > 0)
+       let newWinnr = bufwinnr(bufnr)
+       if newWinnr != -1
+               exec newWinnr.'wincmd w'
+               return 1
+       endif
+    endif
+    " Could not find the buffer
+    return 0
+endfunction
+" }}}
+" {{{ Utils library
+
+let s:Utils = {}
+
+" Use this function to determine the correct "g" flag
+" for substitution
+function! s:Utils.mGetSearchFlag(gvalue)
+    let ret = (!a:gvalue)* (&gdefault) + (!&gdefault)*(a:gvalue)
+    if ret == 1
+        return 'g'
+    endif
+    return ''
+endfunc
+
+" Strlen works for multibyte characters
+function! s:Utils.mStrlenEx(val)
+    return strlen(substitute(a:val, ".", "x", "g"))
+endfunc
+" }}}
+" {{{ Generic db loader interface
+let s:GenericDbLdr = {
+        \ 'fDBName' : '',
+        \ 'class' : 'Generic',
+        \ }
+
+function! s:GenericDbLdr.mCreate(fname) dict
+    let gdb = deepcopy(s:GenericDbLdr)
+    unlet gdb.mCreate
+    let gdb.fDBName = a:fname
+
+    if !filereadable(a:fname)
+        return s:CCTreeRC.Error
+    endif
+
+    return gdb
+endfunction
+
+function! s:GenericDbLdr.mParseDbHeader(gRdr)
+    let header = readfile(self.fDBName, "", a:gRdr.headerLines)
+    return a:gRdr.mParseDbHeader(header)
+endfunction
+
+let s:XRefMemDbLdr = {
+                     \ 'class' : s:DBStorage.memory
+                     \}
+
+function! s:XRefMemDbLdr.mCreate(fname) dict
+    let gdb = s:GenericDbLdr.mCreate(a:fname)
+    if type(gdb) != type({})
+        return gdb
+    endif
+    let mdb = extend(gdb, deepcopy(s:XRefMemDbLdr))
+    unlet mdb.mCreate
+
+    return mdb
+endfunction
+
+if has('perl') && g:CCTreeUsePerl == 1
+" Perl function
+function! s:XRefMemDbLdr.mLoadFileIntoXRefDb(xRefDb, gRdr)  dict
+    let stage = 1
+    for afltr in a:gRdr.opts
+        let stageidxstr = 'Stage ('.stage.'/'.len(a:gRdr.opts).') '
+        call s:StatusLine.mSetInfo(stageidxstr. ': (PERL) Loading database ')
+        call a:gRdr.mProcessingStateInit()
+        let pBar = s:ProgressBarNumeric.mCreate(getfsize(self.fDBName), "bytes")
+        echomsg 'filtering '. afltr
+perl << PERL_EOF
+    #use strict;
+    #use warnings FATAL => 'all';
+    #use warnings NONFATAL => 'redefine';
+
+    my $filebytes = 0;
+    my $filterpat = VIM::Eval("afltr");
+
+    open (CSCOPEDB, VIM::Eval("self.fDBName")) or die "File trouble!";
+    #VIM::DoCommand("echomsg '".$filterpat."'");
+
+    while (<CSCOPEDB>) {
+        $filebytes += length($_);
+        chomp($_);
+
+        if ($_ !~ $filterpat) {
+                next;
+        }
+        VIM::DoCommand("call pBar.mTick(".$filebytes.")");
+        $filebytes = 0;
+        VIM::DoCommand("call a:gRdr.mProcessSymbol(a:xRefDb, '".$_."')");
+    }
+    VIM::DoCommand("call pBar.mDone()");
+    close(CSCOPEDB);
+PERL_EOF
+        call a:gRdr.mProcessingStateDone()
+        let stage += 1
+    endfor
+endfunction
+else
+" Native Vim function
+function! s:XRefMemDbLdr.mLoadFileIntoXRefDb(xRefDb, gRdr) dict
+        let vDbFile = s:vFile.mCreate(self.fDBName, "r")
+        if vDbFile.valid == 0
+            return -1
+        endif
+        if vDbFile.mIsLargeFile() == 1
+                call s:StatusLine.mSetExtraInfo('Database '
+                        \.' >'.g:CCTreeDbFileMaxSize .' bytes. Splitting '.
+                        \'into smaller chunks... (this may take some time)')
+        endif
+        try
+                if vDbFile.mOpen() == 0
+                        call self.mReadFileIntoXRefDb(vDbFile,
+                                                \ a:xRefDb,
+                                                \ a:gRdr)
+                endif
+        finally
+                call vDbFile.mClose()
+        endtry
+endfunction
+endif
+
+function! s:XRefMemDbLdr.mReadFileIntoXRefDb(vDbFile, xrefdb, gRdr)
+    let stage = 0
+    for afltr in a:gRdr.opts
+        call a:vDbFile.mRewind()
+        let stage += 1
+        call a:gRdr.mProcessingStateInit()
+        while 1 == 1
+            if a:vDbFile.mRead() == -1
+                break
+            endif
+            let stageidxstr = 'Stage ('.stage.'/'.len(a:gRdr.opts).') '
+            let fileidxstr = '('.a:vDbFile.currentSplitIdx.'/'.a:vDbFile.totSplits.') '
+            call s:StatusLine.mSetInfo(stageidxstr. ': Reading database chunk '.fileidxstr)
+            " Filter-out lines that doesn't have relevant information
+            let plist = a:gRdr.mReadLinesFromFile(a:vDbFile, afltr)
+            let pBar = s:ProgressBarNumeric.mCreate(len(plist), "items")
+            call s:StatusLine.mSetInfo(stageidxstr.': Analyzing database chunk '.fileidxstr)
+            call self.mProcessListIntoXrefDb(plist, a:gRdr, a:xrefdb, pBar)
+            call pBar.mDone()
+            " clean-up memory
+            call garbagecollect()
+        endwhile
+        call a:gRdr.mProcessingStateDone()
+    endfor
+endfunction
+
+function! s:XRefMemDbLdr.mProcessListIntoXrefDb(symbols, rdr, xrefdb, pbar)
+    for a in a:symbols
+        call a:pbar.mTick(1)
+        call a:rdr.mProcessSymbol(a:xrefdb, a)
+    endfor
+endfunction
+
+function! s:GenericDbLdr.mParseDbHeader(gRdr)
+    let header = readfile(self.fDBName, "", a:gRdr.headerLines)
+    return a:gRdr.mParseDbHeader(header)
+endfunction
+
+" }}}
+" {{{ Generic Disk DB Ldr
+let s:XRefDiskDbLdr = {
+        \ 'class' : s:DBStorage.disk
+        \ }
+
+function! s:XRefDiskDbLdr.mCreate(fname) dict
+    let gdb = s:GenericDbLdr.mCreate(a:fname)
+    if type(gdb) != type({})
+        return gdb
+    endif
+    let mdb = extend(gdb, deepcopy(s:XRefDiskDbLdr))
+    unlet mdb.mCreate
+
+    return mdb
+endfunction
+
+function! s:XRefDiskDbLdr.mLoadFileIntoXRefDb(xRefDb, gRdr) dict
+    call a:xRefDb.mSetLink(self.fDBName)
+endfunction
+
+"}}}
+" {{{ Xref disk DB
+let s:XRefDiskDb = {
+                        \ 'link':'',
+                        \ 'savedTags': '',
+                        \ 'class' : s:DBStorage.disk
+                        \ }
+
+function! s:XRefDiskDb.mCreate() dict
+       let fdb = deepcopy(s:XRefDiskDb)
+       unlet fdb.mCreate
+       let fdb.maps = s:CCTreeGetXRefDbMaps('Uncompress', 'Numeric')
+
+       return fdb
+endfunction
+
+function! s:XRefDiskDb.mSetLink(filedb) dict
+       let self.link = a:filedb
+        " revisit, do parse header here
+endfunction
+
+function! s:XRefDiskDb.mClear() dict
+        " do nothing
+endfunction
+
+function! s:XRefDiskDb.mInitState() dict
+        let self.savedTags = &tags
+        let &tags = self.link
+endfunction
+
+function! s:XRefDiskDb.mRestoreState() dict
+        let &tags = self.savedTags
+endfunction
+
+function! s:XRefDiskDb.mDecodeTagEntry(tagentry) dict
+        let itms = split(a:tagentry.name, "#")
+        let a:tagentry.n = itms[1]
+        let a:tagentry.idx = itms[0]
+
+        " Vim taglist() drops empty fields, so need to protect
+        if has_key(a:tagentry, 'c')
+            let a:tagentry.c = self.maps.mTranslate(a:tagentry.c)
+        else
+            let a:tagentry.c = ''
+        endif
+        if has_key(a:tagentry, 'p')
+            let a:tagentry.p = self.maps.mTranslate(a:tagentry.p)
+        else
+            let a:tagentry.p = ''
+        endif
+
+        return a:tagentry
+endfunction
+
+function! s:XRefDiskDb.mGetSymbolIdFromName(symname) dict
+        let symtagline = taglist('\#'.a:symname.'$')
+        let g:xyz = symtagline
+        let asym = self.mDecodeTagEntry(symtagline[0])
+        return asym.idx
+endfunction
+
+function! s:XRefDiskDb.mGetSymbolFromId(symid) dict
+        let symtagline = taglist('^'.a:symid.'\#')
+        if empty(symtagline)
+            echomsg "Failed to locate ".a:symid
+        else
+            return self.mDecodeTagEntry(symtagline[0])
+        endif
+        return {}
+endfunction
+
+function! s:XRefDiskDb.mGetSymbolIds() dict
+    " illegal
+    let symtaglines = taglist('^.')
+    return keys(self.symidhash)
+endfunction
+
+function! s:XRefDiskDb.mGetSymbolNames(lead) dict
+    if empty(a:lead)
+        let symtaglines = taglist('^.')
+    else
+        let symtaglines = taglist('#'.a:lead)
+    endif
+    let alist = []
+    for atag in symtaglines
+        let acctreesym = self.mDecodeTagEntry(atag)
+        call add(alist, acctreesym.n)
+    endfor
+    return alist
+endfunction
+" }}}
+" {{{ TagFile utils
+let s:CCTreeTagDbRdr = {'class': 'CCTreeXrefDb',
+                    \ 'headerLines' : 4,
+                    \ 'compressed' : 0,
+                    \ 'opts': ['v:val !~ "^[\!]"'],
+                    \ 'perl_opts': "^[^\!]",
+                    \ 'mapPreKeys': {'c':'','p':''},
+                    \ 'mapPostKeys': {'c':'','p':''}
+                    \ }
+
+function! s:CCTreeTagDbRdr.mCreate(fname) dict
+    let cctxdbrdr = deepcopy(s:CCTreeTagDbRdr)
+    unlet cctxdbrdr.mCreate
+
+    return cctxdbrdr
+endfunction
+
+function! s:CCTreeTagDbRdr.mRequirePreProcessing() dict
+    return s:CCTreeRC.False
+endfunction
+
+function! s:CCTreeTagDbRdr.mRequirePostProcessing() dict
+    return s:CCTreeRC.True
+endfunction
+
+function! s:CCTreeTagDbRdr.mRequireCleanup() dict
+    " Clean-up all symbols [never]
+    return s:CCTreeRC.False
+endfunction
+
+function! s:CCTreeTagDbRdr.mGetPreProcessingMaps() dict
+    return s:CCTreeGetXRefDbMaps('Compress', 'Alpha')
+endfunction
+
+function! s:CCTreeTagDbRdr.mGetPostProcessingMaps() dict
+    return s:CCTreeGetXRefDbMaps('Uncompress', 'Alpha')
+endfunction
+
+
+function! s:CCTreeTagDbRdr.mParseDbHeader(hdr) dict
+    " just check line 3 for sanity
+    if a:hdr[2] =~ "CCTree"
+        return s:CCTreeRC.Success
+    endif
+    return s:CCTreeRC.Error
+endfunction
+
+function! s:CCTreeTagDbRdr.mProcessingStateInit() dict
+endfunction
+
+function! s:CCTreeTagDbRdr.mProcessingStateDone() dict
+endfunction
+
+function! s:CCTreeTagDbRdr.mReadLinesFromFile(vdbFile, filtercmds) dict
+    " Hard-coded assumptions here about format for performance
+    if empty(get(a:vdbFile.lines, 0)) != 1 && a:vdbFile.lines[0][0] == "!"
+    " filter out the first few lines starting with "!"
+        call remove(a:vdbFile.lines, 0, self.headerLines-1)
+    endif
+    return a:vdbFile.lines
+endfunction
+
+function! s:CCTreeTagDbRdr.mProcessSymbol(xrefdb, aline) dict
+    let cctreesym = self.mDecodeTagLine(a:aline)
+    call a:xrefdb.mInsertSym(cctreesym.idx, cctreesym)
+    " we really don't need idx any longer
+    unlet cctreesym.idx
+endfunction
+
+function! s:CCTreeTagDbRdr.mDecodeTagLine(tagline) dict
+
+        let items = split(a:tagline, "\t")
+        let newsym = s:CCTreeSym.mCreate("")
+        try
+            let [newsym.idx, newsym.n] = split(items[0], '#')
+        catch
+            echomsg "problem decoding ". a:tagline
+        endtry
+
+        "let newsym.idx = strpart(items[0], 0, idxBr)
+        "let newsym.n =  items[0][ idxBr+1 : -2] "strpart(items[0], idxBr+1, strlen(items[0])-1)
+        if empty(get(items, 3)) != 1
+            let newsym.c = items[3][2:]
+        endif
+        if empty(get(items, 4)) != 1
+            let newsym.p = items[4][2:]
+        endif
+        return newsym
+endfunction
+
+" }}}
+" {{{ Generic Db Serializer
+let s:GenericDbSerializer = {}
+
+function! s:GenericDbSerializer.mCreate(xrefdb) dict
+    let gDbSerializer = deepcopy(s:GenericDbSerializer)
+    let gDbSerializer.xrefdb = a:xrefdb
+    return gDbSerializer
+endfunction
+
+function! s:GenericDbSerializer.mWriteXRefDbToFile(fname,
+                                            \ gWriter) dict
+    call s:StatusLine.mInit()
+    try
+        call s:StatusLine.mSetInfo('Writing XRefDb')
+        let vDbFile = s:vFile.mCreate(a:fname, "w")
+        call vDbFile.mWriteList(a:gWriter.mBuildHeader())
+        call self.mWriteSymsToFile(vDbFile, a:gWriter)
+    finally
+        call vDbFile.mClose()
+        call s:StatusLine.mRestore()
+    endtry
+endfunction
+
+function! s:GenericDbSerializer.mWriteSymsToFile(dstVFile,
+                                            \ gWriter) dict
+    let pBar = s:ProgressBarNumeric.mCreate(self.xrefdb.mGetSymbolCount(),
+                                                    \ "items")
+    call a:gWriter.mInitWriting()
+    " write syms
+    for asymid in sort(self.xrefdb.mGetSymbolIds())
+        let  acctreesym = self.xrefdb.mGetSymbolFromId(asymid)
+        call a:dstVFile.mWriteLine(a:gWriter.mBuildTagLine(acctreesym,
+                        \ asymid))
+        call pBar.mTick(1)
+    endfor
+    call pBar.mDone()
+    call a:gWriter.mDoneWriting()
+endfunction
+" }}}
+" {{{ CCTreeTagDb Writer
+let s:CCTreeTagDbWriter = {}
+
+function! s:CCTreeTagDbWriter.mCreate(tmaps) dict
+    let dbwriter = deepcopy(s:CCTreeTagDbWriter)
+    unlet dbwriter.mCreate
+
+
+    let dbwriter.tmaps = a:tmaps
+    return dbwriter
+endfunction
+
+function! s:CCTreeTagDbWriter.mInitWriting() dict
+    call self.tmaps.mInitTranslator()
+endfunction
+
+function! s:CCTreeTagDbWriter.mDoneWriting() dict
+    call self.tmaps.mDoneTranslator()
+endfunction
+
+function! s:CCTreeTagDbWriter.mBuildHeader() dict
+    let hdr = []
+    call add(hdr, "!_TAG_FILE_FORMAT\t2\t/extended format; --format=1 will not append ;\" to lines/")
+    call add(hdr, "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/")
+    call add(hdr, "!_TAG_PROGRAM_NAME\t\tCCTree (Vim plugin)//")
+    call add(hdr, "!_TAG_PROGRAM_URL\thttp://vim.sourceforge.net/scripts/script.php?script_id=2368\t/site/")
+    return hdr
+endfunction
+
+
+function! s:CCTreeTagDbWriter.mBuildTagLine(sym, symid) dict
+        let basetag = a:symid .'#'. a:sym.n."\t"."\t"."/^\$/".";\""
+        let cm =  self.tmaps.mTranslate(a:sym.c)
+        let pm =  self.tmaps.mTranslate(a:sym.p)
+
+        let basetag .= "\tc:". self.tmaps.mTranslate(a:sym.c)
+        let basetag .= "\tp:". self.tmaps.mTranslate(a:sym.p)
+
+        return basetag
+endfunction
+" }}}
+" {{{ CCTree constants
+let s:CCTreeRC = {
+                    \ 'Error' : -1,
+                    \ 'True' : 1,
+                    \ 'False' : 0,
+                    \ 'Success' : 2
+                    \ }
+"}}}
+" {{{ CCTree DB Obj
+" Symbol definition
+
+let s:CCTreeSym = {
+                    \'k': "",
+                    \'n': "",
+                    \'c': "",
+                    \'p': ""
+                    \}
+
+function! s:CCTreeSym.mCreate(name, kind)
+    let sym = deepcopy(s:CCTreeSym)
+    unlet sym.mCreate
+    let sym.n = a:name
+    let sym.k = a:kind
+    return sym
+endfunction
+
+
+" }}}
+" {{{ GenericXref, XrefDb
+let s:GenericXRef = {}
+
+function! s:GenericXRef.mCreate(filedb) dict
+       let gxref = deepcopy(s:GenericXRef)
+       return gxref
+endfunction
+
+function! s:GenericXRef.mInitState() dict
+endfunction
+
+function! s:GenericXRef.mRestoreState() dict
+endfunction
+" {{{ XRef Database object
+let s:xRefMemDb = {
+        \ 'symuniqid': 0,
+        \ 'symidhash' : {},
+        \ 'symnamehash' : {},
+        \ 'class' : s:DBStorage.memory
+        \}
+
+
+function s:xRefMemDb.mCreate()   dict
+        let dbObj = deepcopy(s:xRefMemDb)
+        unlet dbObj.mCreate
+
+        return dbObj
+endfunction
+
+function s:xRefMemDb.mInitState()   dict
+endfunction
+
+function s:xRefMemDb.mRestoreState()   dict
+endfunction
+
+function s:xRefMemDb.mClear()   dict
+    let self.symidhash = {}
+    let self.symnamehash = {}
+    let self.symuniqid = 0
+endfunction
+
+function! s:xRefMemDb.mInsertSym(idx, cctreesym)  dict
+    let self.symuniqid = max([self.symuniqid, a:idx])
+    let self.symidhash[a:idx] = a:cctreesym
+    let self.symnamehash[a:cctreesym.n] = a:idx
+endfunction
+
+function! s:xRefMemDb.mRemoveSymById(symidx)  dict
+    call self.mRemoveSymByName(acctreesym.n)
+    call remove(self.symidhash, a:symidx)
+endfunction
+
+function! s:xRefMemDb.mRemoveSymByName(symname)  dict
+    call remove(self.symnamehash, a:symname)
+endfunction
+
+function! s:xRefMemDb.mAddSym(name, kind)    dict
+    if !has_key(self.symnamehash, a:name)
+        let self.symnamehash[a:name] = self.symuniqid
+        let self.symidhash[self.symuniqid] =
+                            \s:CCTreeSym.mCreate(a:name, a:kind)
+        let self.symuniqid += 1
+    endif
+    let asymid = self.symnamehash[a:name]
+    if a:kind != ""
+        let asym = self.symidhash[asymid]
+        let asym.k = a:kind
+    endif
+    return asymid
+endfunction
+
+function! s:xRefMemDb.mMarkXRefSyms(funcentryidx, newfuncidx) dict
+    let self.symidhash[a:funcentryidx]['c'] .= (",". a:newfuncidx)
+    let self.symidhash[a:newfuncidx]['p'] .= (",". a:funcentryidx)
+endfunction
+
+function! s:xRefMemDb.mGetSymbolFromName(symname) dict
+    return self.symidhash[self.symnamehash[a:symname]]
+endfunction
+
+function! s:xRefMemDb.mGetSymbolIdFromName(symname) dict
+    if has_key(self.symnamehash, a:symname)
+        return self.symnamehash[a:symname]
+    else
+        return s:CCTreeRC.Error
+    endif
+endfunction
+
+function! s:xRefMemDb.mGetSymbolFromId(symid) dict
+    return self.symidhash[a:symid]
+endfunction
+
+function! s:xRefMemDb.mGetSymbolIds() dict
+    return keys(self.symidhash)
+endfunction
+
+function! s:xRefMemDb.mGetSymbolNames(lead) dict
+    let syms = keys(self.symnamehash)
+    if empty(a:lead) != 1
+        return filter(syms, 'v:val =~? a:lead')
+    endif
+    return syms
+endfunction
+
+function! s:xRefMemDb.mGetSymbolCount() dict
+    return len(self.symnamehash)
+endfunction
+
+function! s:xRefMemDb.mTranslateSymbols(map, tkeys) dict
+    call a:map.mInitTranslator()
+    let pBar = s:ProgressBarNumeric.mCreate(len(self.symnamehash), "items")
+
+    for asym in keys(self.symnamehash)
+        let idx = self.symnamehash[asym]
+        let val = self.symidhash[idx]
+        if has_key(a:tkeys, 'n')
+            let uncmpname = a:map.mTranslate(asym)
+            if (asym != uncmpname)
+                "Set up new entry
+                let self.symnamehash[uncmpname] = idx
+                " free the old entry
+                call remove(self.symnamehash, asym)
+                " Set uncompressed name
+                let val.n = uncmpname
+            endif
+        endif
+        if has_key(a:tkeys, 'p')
+            let val.p = a:map.mTranslate(val.p)
+        endif
+        if has_key(a:tkeys, 'c')
+            let val.c = a:map.mTranslate(val.c)
+        endif
+        call pBar.mTick(1)
+    endfor
+    call pBar.mDone()
+    call a:map.mDoneTranslator()
+endfunction
+
+function! s:xRefMemDb.mCleanSymbols () dict
+    let pBar = s:ProgressBarNumeric.mCreate(len(self.symnamehash), "items")
+    for asym in keys(self.symnamehash)
+        let idx = self.symnamehash[asym]
+        let val = self.symidhash[idx]
+        if empty(val.p) && empty(val.c)
+            call remove(self.symnamehash, asym)
+            call remove(self.symidhash, idx)
+        else
+            let val.p = s:CCTreeMakeCommaListUnique(val.p)
+            let val.c = s:CCTreeMakeCommaListUnique(val.c)
+        endif
+        call pBar.mTick(1)
+    endfor
+    call pBar.mDone()
+endfunction
+"}}}
+"}}} End of Xref
+" {{{ Tracer
+let s:CallTree = {
+                    \ 'symbol' : ""
+                    \ }
+function! s:CallTree.mCreate(name) dict
+    let ct = deepcopy(s:CallTree)
+    unlet ct.mCreate
+
+    let ct.symbol = a:name
+
+    return ct
+endfunction
+
+function! s:CallTree.mAddChildLink(childTree) dict
+    if !has_key(self, 'childlinks')
+        let self.childlinks = []
+    endif
+    call add(self.childlinks, a:childTree)
+endfunction
+
+let s:XRefTracer = {
+                    \}
+
+function! s:XRefTracer.mCreate(xrefdb) dict
+    let xreftracer = deepcopy(s:XRefTracer)
+    let xreftracer.xrefdb = a:xrefdb
+
+    return xreftracer
+endfunction
+
+function! s:XRefTracer.mInitTracing() dict
+    call self.xrefdb.mInitState()
+endfunction
+
+function! s:XRefTracer.mDoneTracing() dict
+    call self.xrefdb.mRestoreState()
+endfunction
+
+function! s:XRefTracer.mGetSymbolIdXRef(symid, direction) dict
+    let acctreesym = self.xrefdb.mGetSymbolFromId(a:symid)
+    let symidslist = split(
+                    \s:CCTreeMakeCommaListUnique(acctreesym[a:direction]), ",")
+    return symidslist
+endfunction
+
+function! s:XRefTracer.mBuildForSymbol(symid, curdepth, maxdepth,
+                                      \ direction, pbar) dict
+    if (a:curdepth > a:maxdepth)
+        return {}
+    endif
+
+    call a:pbar.mSetDepth(a:curdepth)
+    let asym = self.xrefdb.mGetSymbolFromId(a:symid)
+    " revisit
+    if empty(asym)
+        return {}
+    endif
+
+    let rtree = s:CallTree.mCreate(asym['n'])
+
+    for entry in self.mGetSymbolIdXRef(a:symid, a:direction)
+        call a:pbar.mTick(1)
+        let ctree =
+                \self.mBuildForSymbol(entry, a:curdepth+1, a:maxdepth,
+                                            \a:direction, a:pbar)
+        call rtree.mAddChildLink(ctree)
+    endfor
+    return rtree
+endfunction
+" }}}
+
+" {{{ Cscope Reader
+
+
+let s:CscopeDbRdrState = {
+    \'curfuncidx': -1,
+    \'curfileidx': -1,
+    \'curmacroidx': -1,
+    \'curenumidx': -1,
+    \ }
+
+function! s:CscopeDbRdrState.mCreate() dict
+    return deepcopy(s:CscopeDbRdrState)
+endfunction
+
+let s:CscopeDbRdrSymTags = {
+            \'func'  : '$}',
+            \'macro' : '#\)',
+            \'file' : '@\~',
+            \'enum' : 'em',
+            \'global' : 'g',
+            \'typedef' : 't',
+            \}
+
+let s:CscopeDbSymFilter = ['v:val =~ "^\t[#`$}@\~\)]"']
+let s:CscopeDbSymEnhFilter = ['v:val =~ "^\t[emgt#`$}@~)]"',
+                            \ 'v:val =~ "^\\a\\|^\t[)$}#]"']
+
+let s:CscopeDbSymFilterPerl = ['^\t[\`\#\$\}\@\~\)]']
+let s:CscopeDbSymEnhFilterPerl = ['^\t[\`\#\$\}\@\~\)emgt]',
+                                \ '^[A-Za-z]|^\t[\#\$\}\)]']
+
+let s:CscopeDbRdr = {
+                    \ 'class': 'Cscope',
+                    \ 'headerLines' : 1,
+                    \ 'compressed' : 0,
+                    \ 'opts': [],
+                    \ 'perl_opts': '',
+                    \ 'mapPreKeys': {'n':''},
+                    \ 'mapPostKeys': {'n':''}
+                    \}
+
+function! s:CscopeDbRdr.mCreate(fname, enhanced) dict
+    let csdbrdr = deepcopy(s:CscopeDbRdr)
+    unlet csdbrdr.mCreate
+
+    if a:enhanced == 1
+        if g:CCTreeUsePerl == 1
+            let csdbrdr.opts = s:CscopeDbSymEnhFilterPerl
+        else
+            let csdbrdr.opts = s:CscopeDbSymEnhFilter
+        endif
+    else
+        if g:CCTreeUsePerl == 1
+            let csdbrdr.opts = s:CscopeDbSymFilterPerl
+        else
+            let csdbrdr.opts = s:CscopeDbSymFilter
+        endif
+    endif
+    return csdbrdr
+endfunction
+
+function! s:CscopeDbRdr.mProcessingStateInit() dict
+    let self.iState = s:CscopeDbRdrState.mCreate()
+endfunction
+
+function! s:CscopeDbRdr.mProcessingStateDone() dict
+    " discard state
+    unlet self.iState
+endfunction
+
+function! s:CscopeDbRdr.mReadLinesFromFile(vDbFile, filtercmds) dict
+    return s:CCTreeUtils.mFilter(a:vDbFile.lines, a:filtercmds)
+endfunction
+
+function! s:CscopeDbRdr.mParseDbHeader(dbHeader) dict
+    if a:dbHeader[0] =~ "cscope"
+        if (a:dbHeader[0] !~ "cscope.*\-c")
+            let self.compressed =  s:CCTreeRC.True
+        else
+            let self.compressed =  s:CCTreeRC.False
+        endif
+        return s:CCTreeRC.Success
+    endif
+    return s:CCTreeRC.Error
+endfunction
+
+function! s:CscopeDbRdr.mRequirePreProcessing() dict
+    return (self.compressed == 1)? s:CCTreeRC.True : s:CCTreeRC.False
+endfunction
+
+function! s:CscopeDbRdr.mRequirePostProcessing() dict
+    return (self.compressed == 1)? s:CCTreeRC.True : s:CCTreeRC.False
+endfunction
+
+function! s:CscopeDbRdr.mRequireCleanup() dict
+    " Clean-up all symbols [always]
+    return s:CCTreeRC.True
+endfunction
+
+function! s:CscopeDbRdr.mGetPreProcessingMaps() dict
+    return s:CCTreeGetCscopeMaps('Compress', 'Alpha')
+endfunction
+
+function! s:CscopeDbRdr.mGetPostProcessingMaps() dict
+    return s:CCTreeGetCscopeMaps('Uncompress', 'Alpha')
+endfunction
+
+function! s:CscopeDbRdr.mProcessSymbol(xrefdb, symbol) dict
+    try
+        if a:symbol[0] == "\t"
+            return self.mProcessTaggedSymbol(a:xrefdb, a:symbol)
+        else
+            return self.mProcessUnTaggedSymbol(a:xrefdb, a:symbol)
+        endif
+    catch
+        echomsg 'Problem with '. a:symbol
+    endtry
+endfunction
+
+function! s:CscopeDbRdr.mProcessUnTaggedSymbol(xrefdb, symbol) dict
+       let cursymidx = a:xrefdb.mGetSymbolIdFromName(a:symbol)
+       if cursymidx != s:CCTreeRC.Error
+           if self.iState.curfuncidx != -1
+               call a:xrefdb.mMarkXRefSyms(self.iState.curfuncidx, cursymidx)
+           elseif self.iState.curmacroidx != -1
+               call a:xrefdb.mMarkXRefSyms(self.iState.curmacroidx, cursymidx)
+           endif
+       endif
+endfunction
+
+function! s:CscopeDbRdr.mProcessTaggedSymbol(xrefdb, symbol) dict
+        if self.iState.curmacroidx != -1
+            if a:symbol[1] == "`"
+                call a:xrefdb.mMarkXRefSyms(self.iState.curmacroidx,
+                                \ a:xrefdb.mAddSym(a:symbol[2:], ""))
+            elseif a:symbol[1] == ')'
+                let self.iState.curmacroidx = -1
+            endif
+        elseif self.iState.curfuncidx != -1
+            " inside function
+            if a:symbol[1] == "`"
+                call a:xrefdb.mMarkXRefSyms(self.iState.curfuncidx,
+                                \ a:xrefdb.mAddSym(a:symbol[2:], ""))
+            elseif a:symbol[1] == "}"
+               let self.iState.curfuncidx = -1
+            elseif a:symbol[1] == "#"
+                let self.iState.curmacroidx = a:xrefdb.mAddSym(a:symbol[2:], 'm')
+            endif
+        elseif self.iState.curenumidx != -1
+            if a:symbol[1] == "m"
+                call a:xrefdb.mMarkXRefSyms(self.iState.curenumidx,
+                                \ a:xrefdb.mAddSym(a:symbol[2:], "em"))
+            else
+                " just reprocess the symbol after changing state
+                let self.iState.curenumidx = -1
+                call self.mProcessTaggedSymbol(a:xrefdb, a:symbol)
+            endif
+        elseif a:symbol[1] == "$"
+            let self.iState.curfuncidx = a:xrefdb.mAddSym(a:symbol[2:], "f")
+        elseif a:symbol[1] == "#"
+           let self.iState.curmacroidx = a:xrefdb.mAddSym(a:symbol[2:], "d")
+        elseif a:symbol[1] == "~"
+            call a:xrefdb.mMarkXRefSyms(self.iState.curfileidx,
+                                       \a:xrefdb.mAddSym(a:symbol[3:], "i"))
+        elseif a:symbol[1] == "e"
+           let self.iState.curenumidx = a:xrefdb.mAddSym(a:symbol[2:],  "e")
+        elseif a:symbol[1] == "g"
+            call a:xrefdb.mAddSym(a:symbol[2:], "g")
+        elseif a:symbol[1] == "@"
+            if a:symbol[2] != ""
+                let self.iState.curfileidx =
+                                    \a:xrefdb.mAddSym(a:symbol[2:], "F")
+            endif
+        endif
+endfunction
+
+" }}}
+" {{{ CCTree helper library
+let s:CCTreeUtils = {}
+
+function! s:CCTreeUtils.mDetectDB(class)
+    if a:class == s:DBClasses.cctreexref
+        if filereadable(g:CCTreeDb)
+        return g:CCTreeDb
+        endif
+    elseif a:class == s:DBClasses.cscopeid
+        if filereadable(g:CCTreeCscopeDb)
+            return g:CCTreeCscopeDb
+        endif
+    endif
+    return ''
+endfunction
+
+function! s:CCTreeUtils.mFilter(lines, filtercmd) dict
+        let retlst = []
+        let progr = len(a:lines)/100
+        let pBar = s:ProgressBarNumeric.mCreate(len(a:lines), "items")
+        while len(a:lines) > 0
+                if progr <= len(a:lines)
+                        let tmplist = remove(a:lines, 0, progr)
+                else
+                        let tmplist = remove(a:lines, 0, len(a:lines)-1)
+                endif
+                call filter(tmplist, a:filtercmd)
+                call pBar.mTick(progr)
+                call extend(retlst, tmplist)
+        endwhile
+        call pBar.mDone()
+        return retlst
+endfunction
+
+function! s:CCTreeUtils.mWarningPrompt(msg) dict
+    echohl WarningMsg
+    let a = input(s:pluginname. ": ". a:msg)
+    echohl None
+endfunction
+
+function! s:CCTreeUtils.mWarningMsg(msg) dict
+    echohl WarningMsg
+    echomsg s:pluginname. ": ". a:msg
+    echohl None
+endfunction
+
+function! s:CCTreeUtils.mInfoMsg(msg) dict
+    echohl Title
+    echomsg s:pluginname. ": ". a:msg
+    echohl None
+endfunction
+
+function! s:CCTreeUtils.mWrite(msg) dict
+    echo s:pluginname. ": ". a:msg
+endfunction
+
+" }}}
+" {{{  CCTree DB management
+let s:CCTreeXrefDbEntry = {
+                     \  'type': '',
+                     \  'fname' : '',
+                     \  'fsize' : 0,
+                     \  'fdate' : 0
+                     \}
+
+function! s:CCTreeXrefDbEntry.mCreate(fname, type) dict
+    let xrefdbent = deepcopy(s:CCTreeXrefDbEntry)
+    unlet xrefdbent.mCreate
+
+    let xrefdbent.type = a:type
+    let xrefdbent.fname = simplify(getcwd().'/'.a:fname)
+    let xrefdbent.fsize = getfsize(a:fname)
+    let xrefdbent.fdate = strftime("%c", getftime(a:fname))
+    return xrefdbent
+endfunction
+
+let s:CCTreeDBList = {
+                        \'loadedDBs' : []
+                        \ }
+
+function! s:CCTreeDBList.mCreate() dict
+    let dbList = deepcopy(s:CCTreeDBList)
+    unlet dbList.mCreate
+
+    return dbList
+endfunction
+
+function! s:CCTreeDBList.mShowLoaded() dict
+    let i = 1
+    call s:CCTreeUtils.mWrite(s:pluginname.": List of loaded cscope databases")
+    call s:CCTreeUtils.mWrite("---------------------------------------")
+   for aDBEnt in self.loadedDBs
+        call s:CCTreeUtils.mWrite(i." ".aDBEnt.fname. " ".
+                                    \ " (".aDBEnt.type.") ".
+                                    \ aDBEnt.fsize. " bytes ".
+                                    \ aDBEnt.fdate)
+        let i = i + 1
+   endfor
+endfunction
+
+function! s:CCTreeDBList.mClearAll() dict
+    let self.loadedDBs = []
+endfunction
+
+function! s:CCTreeDBList.mIsEmpty() dict
+    if empty(self.loadedDBs)
+        return s:CCTreeRC.True
+    endif
+    return s:CCTreeRC.False
+endfunction
+
+" Load the cscope db into the global cctree xref db
+function! s:CCTreeDBList.mCreateDbLoaderAndReader(dbName, dbclass, storageclass) dict
+    let dbUser = s:CCTreeCmdLine.mInputDBName('Load', a:dbName, a:dbclass)
+    if dbUser == ''
+        call s:CCTreeUtils.mWarningMsg('Filename required')
+        "User cancel, do nothing
+        return
+    endif
+
+    " Create generic Db loader object
+    if a:storageclass == s:DBStorage.disk
+        let gDbLdr = s:XRefDiskDbLdr.mCreate(dbUser)
+    elseif a:storageclass == s:DBStorage.memory
+        let gDbLdr = s:XRefMemDbLdr.mCreate(dbUser)
+    endif
+
+    if type(gDbLdr) != type({})
+        call s:CCTreeUtils.mWarningMsg(a:dbclass.' database ' . a:dbName .
+            \ ' not found.')
+        return s:CCTreeRC.Error
+    endif
+
+    " Create new DB reader object
+    if a:storageclass == s:DBStorage.memory
+        if a:dbclass == s:DBClasses.cscopeid
+            let gDbRdr = s:CscopeDbRdr.mCreate(dbUser, g:CCTreeEnhancedSymbolProcessing)
+        elseif a:dbclass == s:DBClasses.cctreexref
+            let gDbRdr = s:CCTreeTagDbRdr.mCreate(dbUser)
+        else
+            return s:CCTreeRC.Error
+        endif
+        if gDbLdr.mParseDbHeader(gDbRdr) == s:CCTreeRC.Error
+            call s:CCTreeUtils.mWarningMsg(gDbRdr.class.' database ' . a:dbName .
+                \ ' format is not parseable.')
+            return s:CCTreeRC.Error
+        endif
+    else
+        let gDbRdr = {}
+    endif
+
+    return {'loader': gDbLdr, 'reader': gDbRdr}
+endfunction
+
+function! s:CCTreeDBList.mAddDbToList(dbName, type)
+    let aDBEnt = s:CCTreeXrefDbEntry.mCreate(a:dbName, a:type)
+    call add(self.loadedDBs, aDBEnt)
+endfunction
+
+" Merge the cscope db into the global cctree xref db
+function! s:CCTreeDBList.mMerge(dbName, xRefDb, class)
+    " Check if merge can be supported
+    if self.loadedDBs[0].type == s:DBStorage.disk
+        call s:CCTreeUtils.mInfoMsg("Cannot merge with DBs traced from disk")
+        return
+    endif
+    " Create db loader, reader
+    let gObjs = self.mCreateDbLoaderAndReader(a:dbName, a:class, s:DBStorage.memory)
+
+    if type(gObjs) == type({})
+        " if Db is compressed, then we need to compress our symbols first
+        let swatch = s:StopWatch.mCreate()
+        if self.mLoadDB(gObjs.loader, a:xRefDb,
+                            \ gObjs.reader) != s:CCTreeRC.Error
+            call self.mAddDbToList(gObjs.loader.fDBName, gObjs.loader.class)
+            let msg = "Done merging databases. xRef Symbol Count: "
+                                     \.a:xRefDb.mGetSymbolCount()
+                                     \.". Time taken: ".swatch.mGetText()." secs"
+            call s:CCTreeUtils.mInfoMsg(msg)
+        endif
+        " Load will auto decompress the symbols
+    endif
+endfunction
+
+" Load the cscope db into the global cctree xref db
+function! s:CCTreeDBList.mAddNew(dbName, xRefDb, dbclass, storageclass)
+    " Create db loader, reader
+    let gObjs = self.mCreateDbLoaderAndReader(a:dbName, a:dbclass, a:storageclass)
+
+    if type(gObjs) == type({})
+        let swatch = s:StopWatch.mCreate()
+        if self.mLoadDB(gObjs.loader, a:xRefDb,
+                            \ gObjs.reader) != s:CCTreeRC.Error
+            call self.mAddDbToList(gObjs.loader.fDBName, gObjs.loader.class)
+            call swatch.mSnapElapsed()
+            if a:storageclass == s:DBStorage.memory
+                let msg = "Done loading database. xRef Symbol Count: "
+                                     \.a:xRefDb.mGetSymbolCount()
+                                     \.". Time taken: ".swatch.mGetText()." secs"
+            else
+                let msg = "Disk Xref database loaded for tracing"
+            endif
+            call s:CCTreeUtils.mInfoMsg(msg)
+        endif
+    endif
+endfunction
+
+function! s:CCTreeDBList.mLoadDB(gDbLdr, xRefDb, gRdr)
+    let rc = s:CCTreeRC.Success
+    try
+        let swatch = s:StopWatch.mCreate()
+        call s:StatusLine.mInit()
+        " if compression, then we need to compress our symbols first
+        if !empty(a:gRdr) && a:gRdr.mRequirePreProcessing() == s:CCTreeRC.True
+            call s:StatusLine.mSetInfo('Pre-processing existing symbols')
+            call a:xRefDb.mTranslateSymbols(a:gRdr.mGetPreProcessingMaps(),
+                                            \ a:gRdr.mapPreKeys)
+        endif
+        call garbagecollect()
+        call s:StatusLine.mSetInfo('Loading database')
+        call a:gDbLdr.mLoadFileIntoXRefDb(a:xRefDb, a:gRdr)
+        if !empty(a:gRdr) && a:gRdr.mRequireCleanup() == s:CCTreeRC.True
+            call s:StatusLine.mSetInfo('Symbol clean-up')
+            call a:xRefDb.mCleanSymbols()
+        endif
+        call garbagecollect()
+        if !empty(a:gRdr) && a:gRdr.mRequirePostProcessing() == s:CCTreeRC.True
+            call s:StatusLine.mSetInfo('Post-processing loaded symbols')
+            call a:xRefDb.mTranslateSymbols(a:gRdr.mGetPostProcessingMaps(),
+                                                \ a:gRdr.mapPostKeys)
+        endif
+        call swatch.mSnapElapsed()
+        " restore normalcy
+        call garbagecollect()
+        redraw
+
+    catch /^Vim:Interrupt$/        " catch interrupts (CTRL-C)
+        call s:CCTreeUtils.mWarningMsg('Loading aborted.')
+        let rc = s:CCTreeRC.Error
+    finally
+        call s:StatusLine.mRestore()
+    endtry
+    return rc
+endfunction
+"}}}
+" {{{ UI Input related
+let s:CCTreeUI = {}
+
+
+function! s:CCTreeUI.mInputDBName(dbName, class, action)
+    let dbUser = a:dbName
+    let dbUser = input(a:action. ' database ('. a:class. '): ', a:dbName, 'file')
+    return dbUser
+endfunction
+" }}}
+" {{{ CCTree Markers
+let s:TreeMarkers_UTF8 = {
+                            \ 'splitT' : nr2char(0x251c),
+                             \ 'arrowR' : nr2char(0x25c0),
+                            \ 'arrowF' : nr2char(0x25B6),
+                            \ 'extV' : nr2char(0x2502),
+                            \ 'extH': nr2char(0x2500),
+                            \ 'depth': nr2char(0x25BC)
+                            \}
+
+let s:TreeMarkers_Text = {
+                            \ 'splitT' : '+',
+                            \ 'arrowF' : '>',
+                            \ 'arrowR' : '<',
+                            \ 'extV' : '|',
+                            \ 'extH': '-',
+                            \ 'depth': 'depth:'
+                            \}
+
+let s:CCTreeMarkers = {
+                        \ 'icons':{}
+                        \ }
+function! s:CCTreeMarkers.mCreate() dict
+    let treeMarkers = deepcopy(s:CCTreeMarkers)
+
+    if &encoding == 'utf-8' && g:CCTreeUseUTF8Symbols == 1
+        let treeMarkers.icons = deepcopy(s:TreeMarkers_UTF8)
+    else
+        " default choice
+        let treeMarkers.icons = deepcopy(s:TreeMarkers_Text)
+    endif
+
+    let treeMarkers.icons.arrowSyms = treeMarkers.icons.arrowF . treeMarkers.icons.arrowR
+    let treeMarkers.icons.vertSyms = treeMarkers.icons.splitT . treeMarkers.icons.extV
+
+    return treeMarkers
+endfunction
+
+function! s:CCTreeMarkers.mGetArrow(direction) dict
+    if a:direction == 'p'
+        return self.icons.arrowR
+    elseif a:direction == 'c'
+        return self.icons.arrowF
+    endif
+    return '?'
+endfunction
+" }}}
+" {{{ User key mappings
+let s:CCTreeKeyMappings = {
+                    \ 'CTreeF': g:CCTreeKeyTraceForwardTree,
+                    \ 'CTreeR': g:CCTreeKeyTraceReverseTree,
+                    \ 'CTreeHilight': g:CCTreeKeyHilightTree,
+                    \ 'CTreeWSave': g:CCTreeKeySaveWindow,
+                    \ 'CTreeWToggle': g:CCTreeKeyToggleWindow,
+                    \ 'CTreeCompress': g:CCTreeKeyCompressTree,
+                    \ 'CTreeDepthMinus': g:CCTreeKeyDepthMinus,
+                    \ 'CTreeDepthPlus': g:CCTreeKeyDepthPlus
+                    \}
+" }}}
+" {{{ CCTreeWindow
+let s:CCTreeWindow =  {
+                        \ 'hiKeyword': '',
+                        \ 'hiKeywordLine':'',
+                        \ 'lastbufname':'',
+                        \ 'treeMarkers': s:CCTreeMarkers.mCreate()}
+
+function! s:CCTreeWindow.mCreate() dict
+    let win = deepcopy(s:CCTreeWindow)
+    unlet win.mCreate
+
+    return win
+endfunction
+
+function! s:CCTreeWindow.mLeave()
+    call s:FindOpenWindow(self.lastbufname)
+endfunction
+
+
+" Definition of a keyword...
+let s:CCTreeKeywordRegEx = '[A-Za-z0-9_\\\.\/]\+'
+
+function! s:CCTreeWindow.mGetKeywordAtCursor() dict
+    let curline = line(".")
+    let self.hiKeyword = ''
+    if foldclosed(curline) == -1
+        let curkeyword = matchstr(getline("."), s:CCTreeKeywordRegEx)
+        if curkeyword != ''
+            if curkeyword != self.hiKeyword || curline != self.hiKeywordLine
+                let self.hiKeyword = curkeyword
+                let self.hiKeywordLine = line(".")
+                return s:CCTreeRC.Success
+            endif
+        else
+            return s:CCTreeRC.Error
+        endif
+    endif
+    if self.hiKeyword == ''
+        return s:CCTreeRC.Error
+    endif
+    return s:CCTreeRC.Success
+endfunction
+
+function! s:CCTreeWindow.mBuildStatusLine(pState, title, items)
+    let needcomma = 0
+    let rtitle = a:title. ' ('. a:pState.keyword
+    let rtitle .= '['
+    if has_key(a:items, "depth")
+        let rtitle .= self.treeMarkers.icons.depth
+        let rtitle .= a:pState.depth
+        let needcomma = 1
+    endif
+    if has_key(a:items, "direction")
+        if needcomma == 1
+            let rtitle .= ','
+        endif
+
+        let rtitle .= self.treeMarkers.mGetArrow(a:pState.direction)
+    endif
+    let rtitle .= '])'
+
+    return rtitle
+endfunction
+
+function! CCTreeWindowPreviewStatusLine()
+    " get global
+    " this is a hack
+    let pState = s:CCTreeGlobals.PreviewState
+    let tMarkers = s:CCTreeGlobals.Window.treeMarkers
+
+    return  s:CCTreeGlobals.Window.mBuildStatusLine(
+                \ s:CCTreeGlobals.PreviewState,
+                \ s:windowtitle,
+                \ {'depth':''}
+                \)
+endfunction
+
+function! s:CCTreeWindow.mPreviewSave(savetitle) dict
+    if s:FindOpenWindow(s:windowtitle) == 1
+        setlocal modifiable
+        call self.mClearMarks(b:displayTree)
+        setlocal nomodifiable
+             setlocal statusline=%-F
+               silent! exec ":f ". a:savetitle
+        return s:CCTreeRC.Success
+    endif
+    return s:CCTreeRC.Error
+endfunction
+
+function! s:CCTreeWindow.mIsOpen() dict
+    if s:FindOpenBuffer(s:windowtitle) > 0
+        return s:CCTreeRC.True
+    endif
+    return s:CCTreeRC.False
+endfunction
+
+function! s:CCTreeWindow.mClose() dict
+    if s:FindOpenWindow(s:windowtitle) == 1
+        silent! q!
+    endif
+endfunction
+
+function! s:CCTreeWindow.mDisplayToggle() dict
+    if s:FindOpenWindow(s:windowtitle) == 1
+        silent! hide
+    else
+        let winbufnr = s:FindOpenBuffer(s:windowtitle)
+        if winbufnr > 0
+           call self.mEnter()
+           silent! exec "buf ".winbufnr
+           call self.mResize()
+           silent! wincmd p
+        else
+           call s:CCTreeUtils.mWarningMsg(" No active window found.")
+        endif
+    endif
+endfunction
+
+function! s:CCTreeWindow.mResize() dict
+    if g:CCTreeWindowVertical == 1
+        if g:CCTreeWindowWidth == -1
+            exec "vertical resize ". b:maxwindowlen
+        else
+            exec "vertical resize ". g:CCTreeWindowWidth
+        endif
+    else
+        if g:CCTreeWindowHeight != -1
+            let &winminheight = g:CCTreeWindowHeight
+           exec "resize".g:CCTreeWindowHeight
+        endif
+    endif
+endfunction
+
+function! s:CCTreeWindow.mDisplayTree(atree, direction) dict
+    let incctreewin = 1
+    if (bufname('%') != s:windowtitle)
+        let incctreewin = self.mEnter()
+    endif
+
+    setlocal modifiable
+    silent 1,$d
+    let b:maxwindowlen = g:CCTreeWindowMinWidth
+    let b:displayTree = s:DisplayTree.mCreate(a:atree,
+                    \ a:direction, self.treeMarkers)
+    call s:CCTreeDisplay.mPopulateTreeInCurrentBuffer(b:displayTree)
+    exec "normal gg"
+
+    " Need to force this again
+    let &l:foldlevel=g:CCTreeMinVisibleDepth
+    setlocal nomodifiable
+    call self.mResize()
+    if (incctreewin == 0)
+        call s:CCTreeWindow.mLeave()
+    endif
+endfunction
+
+function! s:CCTreeWindow.mExtractTreeSymbols(dtree)
+    let symlist = {}
+    for aentry in a:dtree.entries
+        let symlist[aentry.symbol] = 0
+    endfor
+    return symlist
+endfunction
+
+function! s:CCTreeWindow.mEnter() dict
+    let self.lastbufname = bufname("%")
+    let foundWindow = s:FindOpenWindow(s:windowtitle)
+    if foundWindow == 0
+        if g:CCTreeWindowVertical == 1
+            exec  g:CCTreeOrientation." vsplit ". s:windowtitle
+            set winfixwidth
+        else
+            exec  g:CCTreeOrientation." split ". s:windowtitle
+            set winfixheight
+        endif
+
+        setlocal buftype=nofile
+        setlocal bufhidden=hide
+        setlocal noswapfile
+        setlocal nonumber
+        setlocal nowrap
+        setlocal nobuflisted
+
+        if s:CCTreeUseConceal == 1
+            setlocal cole=3
+            setlocal cocu=nv
+        endif
+
+        setlocal statusline=%=%{CCTreeWindowPreviewStatusLine()}
+
+        call self.mInitSyntax(self.treeMarkers.icons)
+        let cpo_save = &cpoptions
+        set cpoptions&vim
+
+        call s:CCTreeBufferKeyMappingsCreate(s:CCTreeKeyMappings)
+
+        command! -buffer -nargs=0 CCTreeWindowHiCallTree
+                                \ call s:CCTreeGlobals.mCursorHoldHandleEvent()
+
+        exec 'nnoremap <buffer> <silent> '.s:CCTreeKeyMappings.CTreeHilight.
+                                                 \' :CCTreeWindowHiCallTree<CR>'
+        exec 'nnoremap <buffer> <silent> '.s:CCTreeKeyMappings.CTreeCompress.
+                                                 \ ' :2,.foldclose!<CR>zv'
+
+        nnoremap <buffer> <silent> <C-p>  :CCTreePreviewBufferUsingTag<CR>
+        nnoremap <buffer> <silent> <CR>  :CCTreeLoadBufferUsingTag<CR>
+        nnoremap <buffer> <silent> <2-LeftMouse> :CCTreeLoadBufferUsingTag<CR>
+
+        let &cpoptions = cpo_save
+    endif
+    setlocal foldmethod=expr
+    setlocal foldexpr=CCTreeFoldExpr(getline(v:lnum))
+    setlocal foldtext=CCTreeFoldText()
+    let &l:foldlevel=g:CCTreeMinVisibleDepth
+
+    return foundWindow
+endfunction
+" }}}
+" {{{ Dynamic call-tree highlighting using
+" syntax highlight tricks
+"
+" There are 3 types of lines, marked with the start character [\s, !, #]
+" Also @ is used to mark the path that is going up
+
+function! s:CCTreeWindow.mMarkCallTree(dtree, keyword) dict
+    let declevel = -1
+    let treelst = a:dtree.entries
+    let curLine = line(".")
+
+    let declevel = treelst[curLine-1].level
+
+    let targetlevel = declevel
+    for idx in range(curLine, 1, -1)
+        let aentry = treelst[idx-1]
+
+
+        " Find our keyword
+        let linemarker = 0
+        " Skip folds
+        if declevel != -1 && foldclosed(idx) == -1
+            if targetlevel == aentry.level
+                let linemarker = 1
+                let targetlevel -= 1
+            endif
+            let aline = a:dtree.mGetNotationalTxt(aentry.level, targetlevel+1, linemarker, 1)
+                            \ . aentry.symbol
+            call setline(idx, aline)
+        endif
+    endfor
+endfunction
+
+function! s:CCTreeWindow.mClearMarks(dtree) dict
+    for idx in range(line(".")+1, line("$"))
+        let breakout = (getline(idx)[0] !~ "[!#]")
+        if breakout == 1
+            break
+        endif
+        let aentry = a:dtree.entries[idx-1]
+        let aline = a:dtree.mGetNotationalTxt(aentry.level, -1, 0, 0)
+                    \ . aentry.symbol
+        call setline(idx, aline)
+    endfor
+endfunction
+
+function! s:CCTreeWindow.mInitSyntax(markers) dict
+        "syntax match CCTreePathMark /\s[|+]/ contained
+        exec 'syntax match CCTreePathMark /\s['. a:markers.vertSyms . ']/ contained'
+        "syntax match CCTreeArrow  /-*[<>]/ contained
+        exec 'syntax match CCTreeArrow  /'.a:markers.extH.'*['. a:markers.arrowSyms .']/ contained'
+
+        syntax match CCTreeSymbol  / [A-Za-z0-9_\.\\\/]\+/  contained
+        syntax region CCTreeSymbolLine start="^\s" end="$" contains=CCTreeArrow,CCTreePathMark,CCTreeSymbol oneline
+
+        "syntax match CCTreeHiArrow  /-*[<>]/ contained
+        exec 'syntax match CCTreeHiArrow  /'. a:markers.extH .'*['. a:markers.arrowSyms .']/ contained'
+        syntax match CCTreeHiSymbol  / [A-Za-z0-9_\.\\\/]\+/  contained
+
+        "syntax match CCTreeHiPathMark /\s[|+]/ contained
+        exec 'syntax match CCTreeHiPathMark /\s[' . a:markers.vertSyms . ']/ contained'
+
+        if s:CCTreeUseConceal == 1
+            syntax match CCTreeMarkExcl  /^[!#]/ contained conceal
+            syntax match CCTreeMarkTilde /@/  contained conceal
+        else
+            syntax match CCTreeMarkExcl  /^[!#]/ contained
+            syntax match CCTreeMarkTilde /@/  contained
+        endif
+        "syntax region CCTreeUpArrowBlock start="@"  end=/[|+]/  contains=CCTreeMarkTilde contained oneline
+        exec 'syntax region CCTreeUpArrowBlock start="@"  end=/['. a:markers.vertSyms .']/  contains=CCTreeMarkTilde contained oneline'
+
+        syntax region CCTreeHiSymbolLine start="!" end="$" contains=CCTreeMarkExcl,
+                \ CCTreeUpArrowBlock,
+                \ CCTreeHiSymbol,CCTreeHiArrow,CCTreeHiPathMark oneline
+
+        syntax region CCTreeMarkedSymbolLine start="#" end="$" contains=CCTreeMarkExcl,
+                        \ CCTreeMarkTilde,CCTreePathMark,
+                        \ CCTreeArrow,CCTreeSymbol,CCTreeUpArrowBlock oneline
+endfunction
+
+
+" }}}
+" {{{ CCTreeDisplay
+
+let s:CCTreeDisplay = {}
+
+function! s:CCTreeDisplay.mPopulateTreeInCurrentBuffer(dtree)
+    let linelist = []
+    for aentry in a:dtree.entries
+        let aline = a:dtree.mGetNotationalTxt(aentry.level, -1, 0, 0)
+                        \ . aentry.symbol
+        let len = s:Utils.mStrlenEx(aline)
+        let b:maxwindowlen = max([len+1, b:maxwindowlen])
+        call add(linelist, aline)
+    endfor
+    call setline(".", linelist)
+endfunction
+
+
+
+" }}}
+" {{{ CCTree command line interface
+let s:CCTreeCmdLine = {}
+
+
+function! s:CCTreeCmdLine.mLoadDBFromDisk(dbName) dict
+        call s:CCTreeGlobals.mUnLoadDBs()
+        let s:CCTreeGlobals.XRefDb = s:XRefDiskDb.mCreate()
+        call s:CCTreeGlobals.DbList.mAddNew(a:dbName,
+                                \ s:CCTreeGlobals.XRefDb, s:DBClasses.cctreexref, "Disk")
+endfunction
+
+" Unload current db's and load new one
+" There is no selective unloading
+function! s:CCTreeCmdLine.mLoadDB(db_name, class) dict
+        call s:CCTreeGlobals.mSetupEncodingChangeAutoCmd(0)
+        call s:CCTreeGlobals.mUnLoadDBs()
+        let s:CCTreeGlobals.XRefDb = s:xRefMemDb.mCreate()
+        call s:CCTreeGlobals.DbList.mAddNew(a:db_name,
+                                \ s:CCTreeGlobals.XRefDb, a:class, s:DBStorage.memory)
+        call s:CCTreeGlobals.mSetupAutoCmds()
+endfunction
+
+function! s:CCTreeCmdLine.mInputDBName(action, dbName, class) dict
+    if a:dbName == ''
+        let dbUser = s:CCTreeUI.mInputDBName(
+                            \ s:CCTreeUtils.mDetectDB(a:class),
+                            \ a:class, a:action)
+    else
+        let dbUser = a:dbName
+    endif
+    return dbUser
+endfunction
+
+function! s:CCTreeCmdLine.mSaveDB(dbName, class) dict
+    let dbUser = self.mInputDBName('Save', a:dbName, a:class)
+    if dbUser == ''
+        call s:CCTreeUtils.mWarningMsg('Filename required')
+        return
+    endif
+    call s:CCTreeGlobals.Window.mClose()
+    call s:CCTreeGlobals.mSetupEncodingChangeAutoCmd(0)
+    call s:CCTreeGlobals.mWriteXRefDbToFile(dbUser)
+    call s:CCTreeGlobals.mSetupAutoCmds()
+    call s:CCTreeGlobals.mUpdateForCurrentSymbol()
+endfunction
+
+" Merge current db with new one
+function! s:CCTreeCmdLine.mMergeDB(db_name, class) dict
+        "call s:CCTreeGlobals.Window.mClose()
+        call s:CCTreeGlobals.DbList.mMerge(a:db_name, s:CCTreeGlobals.XRefDb, a:class)
+endfunction
+
+
+" }}}
+" {{{ CCTree Buffer mappings
+function! s:CCTreeWindowGetHiKeyword()
+    let keyw = expand("<cword>")
+    let keyf = expand("<cfile>")
+
+    let syms = s:CCTreeGlobals.mGetPreviewTreeSymbols()
+
+    if keyw != keyf
+        if has_key(syms, keyf)
+            return keyf
+        elseif has_key(syms, keyw)
+            return keyw
+        endif
+    else
+        return keyw
+    endif
+    return ''
+endfunction
+
+
+" Keymappings used common to source files and CCTree window
+function! s:CCTreeBufferKeyMappingsCreate(kmaps)
+     let func_expr = '<SNR>'.s:sid.'CCTreeWindowGetHiKeyword()'
+     exec 'nnoremap <buffer> <silent> '.a:kmaps.CTreeR.' :CCTreeTraceReverse <C-R>='.
+                                                  \ func_expr.'<CR><CR>'
+     exec 'nnoremap <buffer> <silent> '.a:kmaps.CTreeF.' :CCTreeTraceForward <C-R>='
+                                                \ .func_expr.'<CR><CR>'
+
+     exec 'nnoremap <silent> '.a:kmaps.CTreeWSave. ' :CCTreeWindowSaveCopy<CR>'
+     exec 'nnoremap <silent> '.a:kmaps.CTreeWToggle. ' :CCTreeWindowToggle<CR>'
+
+     exec 'nnoremap <buffer> <silent> '.a:kmaps.CTreeDepthPlus.
+                                    \ ' :CCTreeRecurseDepthPlus<CR>'
+     exec 'nnoremap <buffer> <silent> '.a:kmaps.CTreeDepthMinus.
+                                    \ ' :CCTreeRecurseDepthMinus<CR>'
+endfunction
+
+augroup CCTreeMaps
+au!
+" Header files get detected as cpp?
+" This is a bug in Vim 7.2, a patch needs to be applied to the runtime c
+" syntax files
+" For now, use this hack to make *.h files work
+autocmd FileType *   if &ft == 'c'|| &ft == 'cpp' |
+                   \ call s:CCTreeBufferKeyMappingsCreate(s:CCTreeKeyMappings)|
+                   \ endif
+augroup END
+
+
+" }}}
+" {{{ Tree building
+
+let s:DisplayTreeEntry = {
+                     \ 'symbol': "",
+                     \ 'level': -1
+                     \ }
+
+function! s:DisplayTreeEntry.mCreate(sym, level) dict
+    let te = deepcopy(s:DisplayTreeEntry)
+    let te.symbol = a:sym
+    let te.level = a:level
+    unlet te.mCreate
+
+    return te
+endfunction
+
+let s:calltreemaxdepth = 10
+let s:DisplayTree = {
+                    \ 'entries': [],
+                    \ 'levelMaxLen': repeat([255], s:calltreemaxdepth),
+                    \ 'notTxt': {}
+                    \ }
+
+function! s:DisplayTree.mCreate(calltree, direction, markers) dict
+    let dt = deepcopy(s:DisplayTree)
+    call dt.mBuildTreeForLevel(a:calltree, 0)
+    call dt.mBuildNotationalTxtMarkers(a:direction, a:markers.icons)
+
+    unlet dt.mBuildTreeForLevel
+    unlet dt.mCreate
+
+    return dt
+endfunction
+
+function! s:DisplayTree.mBuildTreeForLevel(ctree, level)
+    if !has_key(a:ctree, 'symbol')
+        return
+    endif
+
+    if g:CCTreeDisplayMode == 3
+       let curlevellen = strlen(a:ctree.symbol) + a:level + 2
+       let self.levelMaxLen[a:level] = min([self.levelMaxLen[a:level],
+                                        \ curlevellen])
+    endif
+
+
+    let aentry = s:DisplayTreeEntry.mCreate(a:ctree.symbol, a:level)
+    call add(self.entries, aentry)
+
+    if has_key(a:ctree, 'childlinks')
+        for alink in a:ctree['childlinks']
+            call self.mBuildTreeForLevel(alink, a:level+1)
+        endfor
+    endif
+endfunction
+
+
+function! s:DisplayTree.mBuildNotationalTxtMarkers(direction, markerSyms) dict
+   " REVISIT
+   if a:direction == 'p'
+        let directiontxt = a:markerSyms.arrowR . " "
+    elseif a:direction == 'c'
+        let directiontxt = a:markerSyms.arrowF . " "
+   endif
+
+
+   let self.notTxt.arrowHead = a:markerSyms.splitT
+   let self.notTxt.arrow = directiontxt
+   let self.notTxt.arrowLead = a:markerSyms.extH
+   let self.notTxt.sep = a:markerSyms.extV
+   if s:CCTreeUseConceal == 1
+       let concealspace = " "
+   else
+       let concealspace = ""
+   endif
+
+   let self.notTxt.symHighlighter= concealspace . "@"
+
+   let self.notTxt.hiSymbolMarker = "!".concealspace
+   let self.notTxt.hiBranchMarker = "#".concealspace
+
+   let self.notTxt.cache = {}
+
+endfunction
+
+function! s:DisplayTree.mGetNotationalTxt(depth, hiDepth, hiSym, hiPath) dict
+    let notkey = join(a:000, ":")
+    if has_key(self.notTxt.cache,notkey) == 1
+        return self.notTxt.cache[notkey]
+    else
+        return self.mBuildNotationalTxt(a:depth, a:hiDepth, a:hiSym, a:hiPath)
+    endif
+endfunction
+
+function! s:DisplayTree.mBuildNotationalTxt(depth, hiDepth, hiSym, hiPath) dict
+    let hiBranch = 0
+    let curDepth = a:depth
+    if 0
+        let Aspace = "A"
+        let Bspace = "B"
+        let Cspace = "C"
+        let Sspace = "S"
+        let Xspace = "X"
+        let Zspace = "Z"
+        let Fspace = "1"
+    else
+        let Aspace = " "
+        let Bspace = " "
+        let Cspace = " "
+        let Sspace = " "
+        let Xspace = " "
+        let Zspace = " "
+        let Fspace = " "
+    endif
+
+    if g:CCTreeDisplayMode == 1
+        let arrowLeads = self.notTxt.arrowLead
+    elseif g:CCTreeDisplayMode >= 2
+        let arrowLeads = repeat(self.notTxt.arrowLead, a:depth)
+    endif
+
+    let indentSpace = ""
+    if g:CCTreeDisplayMode == 2
+        if curDepth > 0
+            let  indentSpace = repeat(Aspace, curDepth)
+        endif
+    elseif g:CCTreeDisplayMode == 3
+        if curDepth > 0
+            let indentSpace = repeat(Aspace, self.levelMaxLen[curDepth-1])
+        endif
+    endif
+    let notTxt = self.notTxt.arrowHead. arrowLeads . self.notTxt.arrow
+    if a:hiDepth == a:depth
+        let notTxt = indentSpace . self.notTxt.symHighlighter . notTxt
+        let hiBranch = 1
+    else
+        let notTxt = indentSpace. Cspace. notTxt
+    endif
+    let curDepth -= 1
+
+    let indentSpace = ""
+    while (curDepth > 0)
+        if g:CCTreeDisplayMode == 2
+            let  indentSpace = repeat(Bspace, curDepth)
+        elseif g:CCTreeDisplayMode == 3
+            let indentSpace = repeat(Bspace, self.levelMaxLen[curDepth-1])
+        endif
+        let notTxt = self.notTxt.sep . notTxt
+        if a:hiDepth == curDepth && a:hiPath == 1
+            let notTxt = indentSpace . self.notTxt.symHighlighter . notTxt
+            let hiBranch = 1
+        else
+            let notTxt = indentSpace. Cspace. notTxt
+        endif
+        let curDepth -= 1
+    endwhile
+    if curDepth == 0
+        " curdepth is  0
+        if a:hiDepth == curDepth  && a:hiPath == 1
+            let notTxt = self.notTxt.symHighlighter . notTxt
+            let hiBranch = 1
+        else
+            let notTxt = Fspace . notTxt
+        endif
+        let curDepth -= 1
+    endif
+    " adjust space
+    if a:depth > 0
+        let notTxt = Xspace . notTxt
+    endif
+    if hiBranch == 1
+        if a:hiSym == 1
+            let notTxt = self.notTxt.hiSymbolMarker . notTxt
+        else
+            let notTxt = self.notTxt.hiBranchMarker . notTxt
+        endif
+    else
+            let notTxt = Sspace . notTxt
+    endif
+    return notTxt
+endfunction
+
+"}}}
+" {{{ Preview window Folding
+function! CCTreeFoldExpr(line)
+    if !exists('b:displayTree') || v:lnum > len(b:displayTree.entries)
+        return 0
+    endif
+
+    let lvl = b:displayTree.entries[v:lnum-1].level
+    if lvl == 0
+        let lvl = 1
+    endif
+    return '>'.lvl
+endfunction
+
+
+function! CCTreeFoldText()
+    if s:CCTreeUseConceal == 1
+        let line = substitute(getline(v:foldstart), '[!@#]', '' , 'g')
+    else
+        let line = substitute(getline(v:foldstart), '[!@#]', ' ' , 'g')
+    endif
+    return line. " (+". (v:foldend - v:foldstart).
+                \  ')'. repeat(" ", winwidth(0))
+endfunction
+" }}}
+" {{{ Syntax coloring definitions
+"Standard display
+highlight default link CCTreeSymbol  Function
+highlight default link CCTreeMarkers LineNr
+highlight default link CCTreeArrow CCTreeMarkers
+highlight default link CCTreePathMark CCTreeArrow
+highlight default link CCTreeHiPathMark CCTreePathMark
+
+" highlighted display
+highlight default link CCTreeHiKeyword Macro
+highlight default link CCTreeHiSymbol  TODO
+highlight default link CCTreeHiMarkers NonText
+highlight default link CCTreeHiArrow  CCTreeHiMarkers
+highlight default link CCTreeUpArrowBlock CCTreeHiArrow
+
+highlight default link CCTreeMarkExcl Ignore
+highlight default link CCTreeMarkTilde Ignore
+"}}}
+" {{{  CCTree global state
+
+let s:CCTreePreviewState = {
+                    \ 'keyword':'',
+                    \ 'direction': '',
+                    \ 'depth' : ''
+                    \}
+
+function! s:CCTreePreviewState.mCreate()
+    let state = deepcopy(s:CCTreePreviewState)
+    unlet state.mCreate
+
+    return state
+endfunction
+
+function! s:CCTreePreviewState.mStore(symbol, direction)
+    let self.keyword = a:symbol
+    let self.direction = a:direction
+endfunction
+" }}}
+" {{{ CCTree global objects
+
+let s:CCTreeGlobals = {
+                        \ 'XRefDb': {},
+                        \ 'DbList': s:CCTreeDBList.mCreate(),
+                        \ 'PreviewState': s:CCTreePreviewState.mCreate(),
+                        \ 'Window': s:CCTreeWindow.mCreate()
+                        \}
+
+let g:CCTreeGlobals = s:CCTreeGlobals
+
+function! s:CCTreeGlobals.mEnable(opt) dict
+    if (has_key(s:CCTreeOptions, a:opt))
+        call s:CCTreeOptions[a:opt](1)
+    else
+        call s:CCTreeUtils.mWarningMsg('Invalid option')
+    endif
+endfunction
+
+function! s:CCTreeGlobals.mDisable(opt) dict
+    if (has_key(s:CCTreeOptions, a:opt))
+        call s:CCTreeOptions[a:opt](0)
+    else
+        call s:CCTreeUtils.mWarningMsg('Invalid option')
+    endif
+endfunction
+
+function! s:CCTreeGlobals.mToggle(opt) dict
+    if (has_key(s:CCTreeOptions, a:opt))
+        call s:CCTreeOptions[a:opt](-1)
+    else
+        call s:CCTreeUtils.mWarningMsg('Invalid option')
+    endif
+endfunction
+
+function! s:CCTreeGlobals.mGetSymNames(lead) dict
+    call self.XRefDb.mInitState()
+    let syms = self.XRefDb.mGetSymbolNames(a:lead)
+    call self.XRefDb.mRestoreState()
+    return syms
+endfunction
+
+
+function! s:CCTreeGlobals.mGetCallsForSymbol(name, depth, direction) dict
+    let pbar = s:ProgressBarRoll.mCreate(['-','\','|','/'], '*')
+    call s:StatusLine.mSetInfo('Building ')
+    redrawstatus!
+    " Create tracer
+    let xtracer = s:XRefTracer.mCreate(self.XRefDb)
+    call xtracer.mInitTracing()
+    let symid = self.XRefDb.mGetSymbolIdFromName(a:name)
+    let xrefs = xtracer.mBuildForSymbol(symid,
+                      \ a:depth, self.PreviewState.depth, a:direction, pbar)
+    call xtracer.mDoneTracing()
+    return xrefs
+endfunction
+
+function! s:CCTreeGlobals.mShowLoadedDBs() dict
+    call self.DbList.mShowLoaded()
+endfunction
+
+function! s:CCTreeGlobals.mUnLoadDBs() dict
+    call s:CCTreeGlobals.Window.mClose()
+    if !empty(s:CCTreeGlobals.XRefDb)
+        call s:CCTreeGlobals.XRefDb.mClear()
+    endif
+    call s:CCTreeGlobals.DbList.mClearAll()
+endfunction
+
+function! s:CCTreeGlobals.mSetPreviewState(name, depth, direction) dict
+    let self.PreviewState.keyword = a:name
+    let self.PreviewState.direction = a:direction
+    let self.PreviewState.depth = a:depth
+endfunction
+
+function! s:CCTreeGlobals.mUpdateForCurrentSymbol() dict
+    if self.DbList.mIsEmpty() == s:CCTreeRC.True
+        return s:CCTreeRC.Error
+    endif
+    if self.PreviewState.keyword != ''
+        let swatch = s:StopWatch.mCreate()
+        " Move this function to globals?
+        call s:StatusLine.mInit()
+        let atree = self.mGetCallsForSymbol(self.PreviewState.keyword,
+                        \ 0,
+                        \ self.PreviewState.direction)
+        call s:StatusLine.mRestore()
+        call self.Window.mDisplayTree(atree, self.PreviewState.direction)
+
+        call swatch.mSnapElapsed()
+    endif
+endfunction
+
+
+function! s:CCTreeGlobals.mGetPreviewTreeSymbols()
+        " REVIST
+        if exists('b:displayTree')
+            return self.Window.mExtractTreeSymbols(b:displayTree)
+        end
+        return {}
+endfunction
+
+function! s:CCTreeGlobals.mSanitizeCallDepth() dict
+    let error = 0
+    if self.PreviewState.depth >= s:calltreemaxdepth
+        self.PreviewState.depth = s:calltreemaxdepth
+        let error = 1
+    elseif self.PreviewState.depth < 1
+        let self.PreviewState.depth = 1
+        let error = 1
+    endif
+
+    if error == 1
+        call s:CCTreeUtils.mWarningMsg('Depth out of bounds')
+    endif
+    return error
+endfunction
+
+function! s:CCTreeGlobals.mRecursiveDepthIncrease() dict
+    let self.PreviewState.depth += 1
+    if self.mSanitizeCallDepth() == 0
+        call self.mUpdateForCurrentSymbol()
+    endif
+endfunction
+
+function! s:CCTreeGlobals.mRecursiveDepthDecrease() dict
+    let self.PreviewState.depth -= 1
+    if self.mSanitizeCallDepth() == 0
+        call self.mUpdateForCurrentSymbol()
+    endif
+endfunction
+
+function! s:CCTreeGlobals.mDisplayToggle() dict
+    call self.Window.mDisplayToggle()
+endfunction
+
+function! s:CCTreeGlobals.mSetupAutoCmds() dict
+    augroup CCTreeGeneral
+        au!
+    augroup END
+    call s:CCTreeGlobals.mSetupCursorMoveAutoCmd(g:CCTreeHilightCallTree)
+    call s:CCTreeGlobals.mSetupEncodingChangeAutoCmd(g:CCTreeUseUTF8Symbols)
+endfunction
+
+function! s:CCTreeGlobals.mSetupCursorMoveAutoCmd(enable) dict
+        if a:enable == 1
+            exec 'autocmd CCTreeGeneral CursorMoved '.s:windowtitle.' call s:CCTreeGlobals.mCursorHoldHandleEvent()'
+        else
+            exec 'autocmd! CCTreeGeneral CursorMoved '.s:windowtitle
+        endif
+endfunction
+
+function! s:CCTreeGlobals.mSetupEncodingChangeAutoCmd(enable) dict
+        return
+        if a:enable == 1
+            autocmd CCTreeGeneral EncodingChanged * call s:CCTreeGlobals.mEncodingChangedHandleEvent()
+        else
+            autocmd! CCTreeGeneral EncodingChanged *
+        endif
+endfunction
+
+function! s:CCTreeGlobals.mPreviewSave() dict
+    let rtitle = s:CCTreeGlobals.Window.mBuildStatusLine(
+                \ s:CCTreeGlobals.PreviewState,
+                \ s:windowsavetitle,
+                \ {'depth':'', 'direction':''}
+                \)
+
+    if self.Window.mPreviewSave(rtitle) == s:CCTreeRC.Success
+        call s:CCTreeUtils.mInfoMsg('Window saved as '. rtitle .
+                    \ '. New window will be opened on next usage.')
+    else
+        call s:CCTreeUtils.mWarningMsg('No active window found to be saved.')
+    endif
+endfunction
+
+function! s:CCTreeGlobals.mWriteXRefDbToFile(fname) dict
+    " create db serializer and writer
+    let gDbSz = s:GenericDbSerializer.mCreate(self.XRefDb)
+    let gDbWriter = s:CCTreeTagDbWriter.mCreate(
+                                \ s:CCTreeGetXRefDbMaps('Compress', 'Alpha'))
+    call gDbSz.mWriteXRefDbToFile(a:fname, gDbWriter)
+endfunction
+
+function! s:CCTreeGlobals.mReadToXRefDb(fname) dict
+    call s:StatusLine.mInit()
+    call s:StatusLine.mSetInfo('Reading XRefDb')
+    let vDbFile = s:vFile.mCreate(a:fname, "r")
+    if vDbFile.mIsLargeFile() == 1
+            call s:StatusLine.mSetExtraInfo('Xref DB '
+                    \.' >'.g:CCTreeDbFileMaxSize .' bytes. Splitting '.
+                    \'into smaller chunks... (this may take some time)')
+    endif
+    try
+        if vDbFile.mOpen() == 0
+            call s:TagFile.mReadToXRefDb(self.XRefDb, vDbFile)
+        endif
+    finally
+        call vDbFile.mClose()
+        call s:StatusLine.mRestore()
+        call self.DbList.mAddDbToList(a:fname, s:DBStorage.memory)
+    endtry
+endfunction
+
+function! s:CCTreeGlobals.mCursorHoldHandleEvent() dict
+    if self.Window.mGetKeywordAtCursor() != s:CCTreeRC.Error
+       setlocal modifiable
+       call self.Window.mClearMarks(b:displayTree)
+       call self.Window.mMarkCallTree(b:displayTree,
+                            \ self.Window.hiKeyword)
+       setlocal nomodifiable
+    endif
+endfunction
+
+function! s:CCTreeGlobals.mEncodingChangedHandleEvent() dict
+    let self.Window.treeMarkers = s:CCTreeMarkers.mCreate()
+    if self.Window.mIsOpen() == s:CCTreeRC.True
+        call self.Window.mClose()
+        call self.mUpdateForCurrentSymbol()
+    endif
+endfunction
+
+
+function! s:CCTreeGlobals.mInit() dict
+    call self.mSetupAutoCmds()
+endfunction
+
+" }}}
+" {{{ CCTree options
+function! s:CCTreeSetUseCallTreeHiLights(val)
+    if a:val == -1
+        let g:CCTreeHilightCallTree = !g:CCTreeHilightCallTree
+    else
+        let g:CCTreeHilightCallTree = a:val
+    endif
+    call s:CCTreeGlobals.mSetupAutoCmds()
+endfunction
+
+function! s:CCTreeSetUseUtf8Symbols(val)
+    if a:val == -1
+        let g:CCTreeUseUTF8Symbols = !g:CCTreeUseUTF8Symbols
+    else
+        let g:CCTreeUseUTF8Symbols = a:val
+    endif
+    call s:CCTreeGlobals.mEncodingChangedHandleEvent()
+endfunction
+
+function! s:CCTreeSetUseConceal(val)
+    if a:val == -1
+        let s:CCTreeUseConceal = !s:CCTreeUseConceal
+    else
+        let s:CCTreeUseConceal = a:val
+    endif
+    if !has('conceal')
+        call s:CCTreeUtils.mWarningMsg('+conceal feature not available')
+        let s:CCTreeUseConceal = 0
+    endif
+endfunction
+
+function! s:CCTreeSetEnhancedSymbolProcessing(val)
+    if a:val == -1
+        let g:CCTreeEnhancedSymbolProcessing = !g:CCTreeEnhancedSymbolProcessing
+    else
+        let g:CCTreeEnhancedSymbolProcessing = a:val
+    endif
+endfunction
+
+function! s:CCTreeOptionsList(arglead, cmdline, cursorpos)
+    let opts = keys(s:CCTreeOptions)
+    if a:arglead == ''
+        return opts
+    else
+        return filter(opts, 'v:val =~? a:arglead')
+    endif
+endfunction
+
+let s:CCTreeOptions = {'UseUnicodeSymbols': function('s:CCTreeSetUseUtf8Symbols'),
+            \ 'DynamicTreeHiLights': function('s:CCTreeSetUseCallTreeHiLights'),
+            \ 'UseConceal': function('s:CCTreeSetUseConceal'),
+            \ 'EnhancedSymbolProcessing': function('s:CCTreeSetEnhancedSymbolProcessing')
+            \}
+
+" }}}
+" {{{ Vim tags interface
+
+" CCTreeCompleteKwd
+" Command line completion function to return names from the db
+function! s:CCTreeCompleteKwd(arglead, cmdline, cursorpos)
+    let syms = s:CCTreeGlobals.mGetSymNames(a:arglead)
+    if a:arglead == ''
+        return syms
+    else
+        return filter(syms, 'v:val =~? a:arglead')
+    endif
+endfunction
+
+function! s:CCTreeTraceTreeForSymbol(sym_arg, direction)
+    if s:CCTreeGlobals.DbList.mIsEmpty() == s:CCTreeRC.True
+        call s:CCTreeUtils.mWarningMsg('No database loaded')
+        return
+    endif
+
+    let symbol = a:sym_arg
+    if symbol == ''
+        let symbol = input('Trace symbol: ', expand('<cword>'),
+                    \ 'customlist,<SNR>' . s:sid . 'CCTreeCompleteKwd')
+        if symbol == ''
+            return
+        endif
+    endif
+    let symmatch = s:CCTreeGlobals.mGetSymNames(symbol)
+    if len(symmatch) > 0 && index(symmatch, symbol) >= 0
+        call s:CCTreeGlobals.mSetPreviewState(symbol,
+                                            \ g:CCTreeRecursiveDepth,
+                                            \ a:direction)
+        call s:CCTreeGlobals.mUpdateForCurrentSymbol()
+    else
+        call s:CCTreeUtils.mWarningMsg('Symbol not found')
+    endif
+endfunction
+
+
+
+
+function! s:CCTreeGlobals.mLoadBufferFromKeyword()
+    " REVISIT
+    if s:CCTreeGlobals.Window.mGetKeywordAtCursor() == s:CCTreeRC.Error
+        call s:CCTreeUtils.mWarningMsg('No keyword at cursor')
+        return
+    endif
+
+    let hiKeyword = s:CCTreeGlobals.Window.hiKeyword
+    try
+        wincmd p
+    catch
+        call s:CCTreeUtils.mWarningMsg('No buffer to load file')
+    finally
+        if (cscope_connection() > 0)
+            try
+                exec "cs find g ". hiKeyword
+            catch
+                " cheap hack
+                exec "cs find f ". hiKeyword
+            endtry
+        else
+            try
+                " Ctags is smart enough to figure the path
+                exec "tag ".fnamemodify(hiKeyword, ":t")
+            catch /^Vim\%((\a\+)\)\=:E433/
+                call s:CCTreeUtils.mWarningMsg('Tag file not found')
+            catch /^Vim\%((\a\+)\)\=:E426/
+                call s:CCTreeUtils.mWarningMsg('Tag '. hiKeyword .' not found')
+                wincmd p
+            endtry
+        endif
+    endtry
+endfunction
+
+function! s:CCTreeGlobals.mPreviewBufferFromKeyword()
+    if self.Window.mGetKeywordAtCursor() == s:CCTreeRC.Error
+        call s:CCTreeUtils.mWarningMsg('No keyword found')
+        return
+    endif
+
+    let hiKeyword = s:CCTreeGlobals.Window.hiKeyword
+    silent! wincmd P
+    if !&previewwindow
+        wincmd p
+    endif
+    try
+        exec "ptag ". hiKeyword
+    catch
+        call s:CCTreeUtils.mWarningMsg('Tag '.hiKeyword. ' not found')
+    endtry
+endfunction
+
+" }}}
+" {{{ Define commands
+command! -nargs=? -complete=file CCTreeLoadXRefDBFromDisk
+                                        \ call s:CCTreeCmdLine.mLoadDBFromDisk(<q-args>)
+command! -nargs=? -complete=file CCTreeLoadDB  call s:CCTreeCmdLine.mLoadDB(<q-args>, s:DBClasses.cscopeid)
+command! -nargs=? -complete=file CCTreeLoadXRefDB  call s:CCTreeCmdLine.mLoadDB(<q-args>, s:DBClasses.cctreexref)
+command! -nargs=? -complete=file CCTreeSaveXRefDB  call s:CCTreeCmdLine.mSaveDB(<q-args>, s:DBClasses.cctreexref)
+command! -nargs=? -complete=file CCTreeAppendDB  call s:CCTreeCmdLine.mMergeDB(<q-args>, s:DBClasses.cscopeid)
+command! -nargs=0 CCTreeUnLoadDB               call s:CCTreeGlobals.mUnLoadDBs()
+command! -nargs=0 CCTreeShowLoadedDBs          call s:CCTreeGlobals.mShowLoadedDBs()
+command! -nargs=? -complete=customlist,s:CCTreeCompleteKwd
+        \ CCTreeTraceForward call s:CCTreeTraceTreeForSymbol(<q-args>, 'c')
+command! -nargs=? -complete=customlist,s:CCTreeCompleteKwd CCTreeTraceReverse
+            \ call s:CCTreeTraceTreeForSymbol(<q-args>, 'p')
+command! -nargs=0 CCTreeLoadBufferUsingTag call s:CCTreeGlobals.mLoadBufferFromKeyword()
+command! -nargs=0 CCTreePreviewBufferUsingTag call s:CCTreeGlobals.mPreviewBufferFromKeyword()
+command! -nargs=0 CCTreeRecurseDepthPlus call s:CCTreeGlobals.mRecursiveDepthIncrease()
+command! -nargs=0 CCTreeRecurseDepthMinus call s:CCTreeGlobals.mRecursiveDepthDecrease()
+" Preview Window
+command! -nargs=0 CCTreeWindowToggle         call s:CCTreeGlobals.mDisplayToggle()
+command! -nargs=0 CCTreeWindowSaveCopy call s:CCTreeGlobals.mPreviewSave()
+" Run-time dynamic options
+command! -nargs=1 -complete=customlist,s:CCTreeOptionsList CCTreeOptsEnable call s:CCTreeGlobals.mEnable(<q-args>)
+command! -nargs=1 -complete=customlist,s:CCTreeOptionsList CCTreeOptsDisable call s:CCTreeGlobals.mDisable(<q-args>)
+command! -nargs=1 -complete=customlist,s:CCTreeOptionsList CCTreeOptsToggle call s:CCTreeGlobals.mToggle(<q-args>)
+"}}}
+" {{{ finish (and init)
+call s:CCTreeGlobals.mInit()
+" restore 'cpo'
+let &cpoptions = s:cpo_save
+unlet s:cpo_save
+" vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1
+" }}}