diff --git a/README.txt b/README.txt
index 61cd9ac..b057014 100644
--- a/README.txt
+++ b/README.txt
@@ -11,23 +11,27 @@ default.  From within vim, use
 
 :help vimfiles
 
-for details.  If you have downloaded these files as ultimate_vimrc.tgz and your
+for details.  If you have downloaded these files as vimrc.tar.gz and your
 vimfiles directory is ~/.vim, then this should work on UNIX-like systems:
 
 $ cd ~/.vim
-$ tar xzf path/to/ultimate_vimrc.tgz --strip-components 1 --exclude=README.txt
+$ tar xzf path/to/vimrc.tar.gz --strip-components 1 --exclude=README.txt
+
+Note:  if there are filename conflicts, then tar will silently remove the
+existing files.
 
 When you are done, you should have the following directory structure inside your
 vimfiles directory:
 
         doc/drupal.txt
+        drupal6.tags
+        drupal7.tags
         ftdetect/drupal.vim
         ftplugin/drini.vim
         ftplugin/drupal.vim
-        ftplugin/javascript_drupal.vim
-        ftplugin/php_drupal.vim
         plugin/drupal.vim
         syntax/drini.vim
+        syntax/drupal.vim
 
 In order to use the tags defined in the help file, start vim and do
         :helptags ~/.vim/doc
@@ -36,6 +40,28 @@ In order to use the tags defined in the help file, start vim and do
 for details.  After this step, you should be able to read the documentation with
         :help drupal.txt
 
+INSTALLATION WITH PATHOGEN
+
+If you use http://www.vim.org/scripts/script.php?script_id=2332 (pathogen) then
+you can install this project anywhere you like.  One suggestion is to rename
+the directory from vimrc/ to drupal/ and then place it in your bundle/
+directory.  Explicitly, the documentation will be
+
+        ~/.vim/bundle/drupal/doc/drupal.txt (Linux, Mac, etc.)
+        ~\vimfiles\bundle\drupal\doc\drupal.txt (Windows)
+
+Another suggestion is to keep this project with your other Drupal files.  For
+example, if you put this project under ~/drupalstuff/bundle/, so that the
+documentation is ~/drupalstuff/bundle/vimrc/doc/drupal.txt, then add
+
+        :call pathogen#infect(~/drupalstuff/bundle)
+
+to your vimrc file.  (The Windows variant is left as an exercise.)
+
+In either case, you can use the command
+        :Helptags
+instead of :helptags, and let pathogen figure out the path for you.
+
 AUTOCOMPLETION IN .INFO FILES
 
 The drini (DRupal INI) filetype is used for .info and similar files.  The
diff --git a/doc/drupal.txt b/doc/drupal.txt
index 5860ede..cc83d3d 100644
--- a/doc/drupal.txt
+++ b/doc/drupal.txt
@@ -6,10 +6,12 @@
 
 1. Installation						|drupal-installation|
 2. Filetype detection					|drupal-filetypes|
-3. Global settings					|drupal-global|
-4. PHP settings						|drupal-PHP|
+3. Drupal plugin					|drupal-plugin|
+4. Drupal filetype plugin				|drupal-ftplugin|
 5. Editing .info files					|drupal-info|
-6. Updates and support					|drupal-update|
+6. Tag searches for Drupal core				|drupal-tags|
+7. Drupal/PHP omni-completion				|ft-drupal-omni|
+8. Updates and support					|drupal-update|
 
 The functionality mentioned here is provided by several files.  See the
 installation section.
@@ -18,11 +20,10 @@ installation section.
 1. Installation						*drupal-installation*
 
 Copy the files, other than README.txt, into your |vimfiles| directory.  If you
-have downloaded these files as ultimate_vimrc.tgz and your vimfiles directory
+have downloaded these files as vimrc.tar.gz and your vimfiles directory
 is ~/.vim, then this should work on UNIX-like systems: >
 	$ cd ~/.vim
-	$ tar tzf path/to/ultimate_vimrc.tgz
-	$ tar xzf path/to/ultimate_vimrc.tgz \
+	$ tar xzf path/to/vimrc.tar.gz \
 		--strip-components 1 --exclude=README.txt
 Note:  if there are filename conflicts, then tar will silently remove the
 existing files.
@@ -30,15 +31,49 @@ existing files.
 When you are done, you should have the following directory structure inside
 your |vimfiles| directory: >
 	doc/drupal.txt
+	drupal6.tags
+	drupal7.tags
 	ftdetect/drupal.vim
-	ftplugin/php_drupal.vim
+	ftplugin/drini.vim
+	ftplugin/drupal.vim
 	plugin/drupal.vim
+	syntax/drini.vim
+	syntax/drupal.vim
 
 In order to use the tags defined in this help file, start vim and >
 	:helptags ~/.vim/doc
 (assuming that this file is installed as ~/.vim/doc/drupal.txt).  See
 |add-local-help| for details.
 
+INSTALLATION WITH PATHOGEN
+
+If you use http://www.vim.org/scripts/script.php?script_id=2332 (pathogen) then
+you can install this project anywhere you like.  One suggestion is to rename
+the directory from vimrc/ to drupal/ and then place it in your bundle/
+directory.  Explicitly, the documentation will be >
+        ~/.vim/bundle/drupal/doc/drupal.txt (Linux, Mac, etc.)
+        ~\vimfiles\bundle\drupal\doc\drupal.txt (Windows)
+Another suggestion is to keep this project with your other Drupal files.  For
+example, if you put this project under ~/drupalstuff/bundle/, so that the
+documentation is ~/drupalstuff/bundle/vimrc/doc/drupal.txt, then add >
+        :call pathogen#infect(~/drupalstuff/bundle)
+to your vimrc file.  (The Windows variant is left as an exercise.)
+
+In either case, you can use the command >
+        :Helptags
+instead of |:helptags|, and let pathogen figure out the path for you.
+
+AUTOCOMPLETION IN .INFO FILES
+
+The drini (DRupal INI) filetype is used for .info and similar files.  The
+syntax/drini.vim included in this project defines keywords that can be
+auto-completed using syntaxcomplete.vim, but this requires version 8.0 of that
+script.  Version 7.0 is included in the vim 7.3 distribution (in the autoload/
+directory) and is also available from
+http://www.vim.org/scripts/script.php?script_id=3172 .  As of late 2011, the
+only way to get version 8.0 is to patch version 7.0 with the patch at
+http://drupal.org/node/1303122#comment-5213300 .
+
 TODO:  There should be a way to install with drush.
 
 ==============================================================================
@@ -47,34 +82,120 @@ TODO:  There should be a way to install with drush.
 The file ftdetect/drupal.vim ensures that files with these extensions are
 recognized as PHP: >
 	.module, .php, .install, .inc, .profile, .theme, .engine, .test
-and these are recognized as INI format: >
+and these are recognized as drini (DRupal INI) format: >
 	.info, .make, .build
 This assumes that you have |filetype| detection on.  See also |ftdetect|.
 
 ==============================================================================
-3. Global settings					*drupal-global*
+3. Drupal plugin					*drupal-plugin*
 
+GLOBAL OPTIONS						*drupal-global*
 The file plugin/drupal.vim sets several |options|.  These will apply whether
-or not you are editing Drupal-related files.  In addition, it sets |filetype|
-detection and |ftplugin| support on; sets global variables used by the
-|php-syntax| file; defines several key mappings; and it highlights trailing
-whitespace and PHP comment lines longer than 80 characters.
+or not you are editing Drupal-related files:
+	'backspace'=2
+	'nocompatible'
+	'encoding'=utf-8
+	'fileformats'=unix
+	'formatoptions'=1
+	'history'=300
+	'hlsearch'
+	'incsearch'
+	'linebreak'
+	'number'
+	'pastetoggle'=<F2>
+	'ruler'
+	'scrolloff'=2
+	'showmatch'
+	'showmode'
+	'undodir'=~/.vim_runtime/undodir
+	'undofile'
+	'wildmode'=longest,list
+
+GLOBAL MAPPINGS							*drupal-maps*
+The script defines the following mappings: >
+	:nn [5C <C-W>w
+	:nn [5R <C-W>W
+	:map <S-u> :redo<cr>
+	:map <C-n> :tabn<cr>
+	:map <C-p> :tabp<cr>
+
+DRUPAL MAGIC			*drupal-magic* *DrupalInit* *b:Drupal_info*
+When you edit a Drupal file, the script tries to find the root of your Drupal
+installation and a .info file for your current project.  If it succeeds, then
+it defines the |buffer-variable| b:Drupal_info, a |Dictionary| with the
+following keys:
+	DRUPAL_ROOT:	the path to your Drupal installation
+	INFO_FILE:	the path to your project's .info file
+	OPEN_COMMAND:	a command for opening URL's on your system
+	TYPE:		"module" or "theme", as appropriate for the project
+	CORE:		the Drupal main version number
+Explicitly, b:Drupal_info.OPEN_COMMAND is set to "open" on Mac OS X,
+"cygstart" on Windows/Cygwin, "cmd /c start" on other Windows, and "xdg-open"
+on UNIX-like systems.
+
+The script always defines all these keys.  If it cannot determine a reasonable
+value, it will use an empty string.
+
+The |drupal-ftplugin| file uses b:Drupal_info.DRUPAL_ROOT to define the
+environment variable $DRUPAL_ROOT.  This is done using a |BufEnter|
+autocommand, so the variable will be set correctly even if you switch between
+files related to different versions of Drupal.
+
+MISCELLANEOUS						*drupal-miscellaneous*
+In addition, this script
+	- sets |:filetype| detection and |ftplugin| support on;
+	- sets the global variables php_htmlInStrings and
+	  php_parent_error_open used by the |php-syntax| file;
+	- tells vim to jump to the last position when reopening a file;
+	- and it highlights trailing whitespace as Error in Drupal files.
 
 ==============================================================================
-4. PHP settings						*drupal-PHP*
+4. Drupal filetype plugin			*ft-drupal* *drupal-ftplugin*
 
-The file ftplugin/php_drupal.vim sets the following options when editing PHP
+When editing a Drupal file, "drupal" is added as a secondary 'filetype'.  For
+example, 'filetype' may be set to "php.drupal" when editing a PHP file or to
+"css.drupal" when editing a CSS file.  When this happens, ftplugin/drupal.vim
+is |:source|d.
+
+LOCAL OPTIONS						*ft-drupal-options*
+The ftplugin file sets the following options:
+	'autoindent'
+	'expandtab'
+	'formatoptions'+=croql
+	'formatoptions'-=t
+	'nojoinspaces'
+	'shiftwidth'=2
+	'smartindent'
+	'smarttab'
+	'tabstop'=2
+	'tags'
+	'textwidth'=80
+This helps you to follow Drupal coding standards:  vim will indent with
+spaces, not tabs, and vim will not add a second line when joining a line
+ending in "." to the line below.  Comments (both doc blocks and //-style) will
+automatically break at 80 characters, and you can reformat them with |gq|.
+
+The 'tags' option is modified only if the CORE and DRUPAL_ROOT keys are
+defined in |b:Drupal_info|.  See |drupal-tags| and |ft-drupal-omni|.
+
+							*ft-drupal-syntax*
+The script syntax/drupal.vim also encourages you to follow Drupal coding
+standards by highlighting comments as errors if they are longer than 80
+characters.
+
+PHP SETTINGS						*drupal-PHP*
+The file ftplugin/drupal.vim sets the following options when editing PHP
 files:
-	'ignorecase', 'smartcase', 'smartindent', 'smarttab', 'expandtab',
-	'tabstop'=2, 'shiftwidth'=2, 'autoindent', 'comments', 'textwidth',
-	'formatoptions'
-Comments (both doc blocks and //-style) will automatically break at 80
-characters, and can be reformatted with |gq|.  You can start a doc block with
+	'comments'
+	'ignorecase'
+	'smartcase'
+You can start a doc block with
 "/**<CR>" and the indentation and comment leader will be inserted.  To end the
 block, just type "<CR>/" and the inserted "* " will automatically turn into
 "*/".  To delete the automatically inserted "// ", you can use <C-U>.
 
-It also defines the following mappings:
+LOCAL MAPPINGS						*drupal-local-maps*
+The ftplugin file also defines the following buffer-local mappings:
 
 gl	Custom SVN blame		*drupal-SVN-blame* *drupal-gl*
 					*drupal-API* *drupal-\da*
@@ -82,7 +203,7 @@ gl	Custom SVN blame		*drupal-SVN-blame* *drupal-gl*
 					*drupal-drush-API* *drupal-\dda*
 \dda	Lookup the API docs for a drush function under cursor.
 					*drupal-variable* *drupal-\dv*
-\dv	Get the value of the drupal variable under cursor.
+\dv	Get the value of the drupal variable under cursor.  (Requires drush.)
 
 You can define the |maplocalleader| variable to be something other than the
 default if you do not want these maps to start with a backslash.
@@ -109,7 +230,37 @@ only way to get version 8.0 is to start with 7.0 and apply the patch at
 http://drupal.org/node/1303122#comment-5213300 .
 
 ==============================================================================
-6. Updates and support			*drupal-update* *drupal-support*
+6. Tag searches for Drupal core	*drupal6.tags* *drupal7.tags* *drupal-tags*
+
+If the scripts can determine the root of your Drupal installation, then they
+will set the environment variable $DRUPAL_ROOT and add the appropriate tags
+file (currently drupal6.tags or drupal7.tags) to the 'tags' option.  This lets
+you use vim's |tag-commands| to jump to functions and more that are defined in
+Drupal core.  For example, if the cursor is on the start of the line >
+	drupal_set_message('Hello, world!');
+then you can use <C-W>] to open drupal/includes/bootstrap.inc in a new window
+and jump to the definition of drupal_set_message().  See also section |29.1|
+in the user manual and |window-tag|.
+
+==============================================================================
+7. Drupal/PHP omni-completion				*ft-drupal-omni*
+
+The default |ftplugin| for PHP sets the 'omnifunc' option to use the PHP
+omni-completion script included in the standard vim distribution.  This script
+can use tags files to offer completions.  It always completes standard PHP
+functions.  If the scripts in this project can determine the root of your
+Drupal installation, then Drupal core functions and more can be completed.  If
+you provide tags files for your own projects, or contributed modules and
+themes, then their functions will also be completed.
+
+To trigger omnicompletion, type <C-X><C-O> in Insert mode.  For example, you
+can type >
+	drupal_se<C-X><C-O>
+to find 15 possible completions, including drupal_send_headers() and
+drupal_set_message().  See |compl-omni|.
+
+==============================================================================
+8. Updates and support			*drupal-update* *drupal-support*
 
 For the latest version of this project, see http://drupal.org/project/vimrc .
 To file a bug report or feature request, see the corresponding issues queue:
diff --git a/ftdetect/drupal.vim b/ftdetect/drupal.vim
index d563427..d924b61 100644
--- a/ftdetect/drupal.vim
+++ b/ftdetect/drupal.vim
@@ -1,11 +1,10 @@
 " Set filetype for Drupal PHP files.
-autocmd BufRead,BufNewFile *.module set filetype=php.drupal
-autocmd BufRead,BufNewFile *.php set filetype=php.drupal
-autocmd BufRead,BufNewFile *.install set filetype=php.drupal
-autocmd BufRead,BufNewFile *.inc set filetype=php.drupal
-autocmd BufRead,BufNewFile *.profile set filetype=php.drupal
-autocmd BufRead,BufNewFile *.theme set filetype=php.drupal
-autocmd BufRead,BufNewFile *.engine set filetype=php.drupal
-autocmd BufRead,BufNewFile *.test set filetype=php.drupal
-" info and make files use INI syntax.
-autocmd BufRead,BufNewFile *.{info,make,build} set filetype=drini.drupal
+autocmd BufRead,BufNewFile *.module set filetype=php
+autocmd BufRead,BufNewFile *.php set filetype=php
+autocmd BufRead,BufNewFile *.install set filetype=php
+autocmd BufRead,BufNewFile *.inc set filetype=php
+autocmd BufRead,BufNewFile *.profile set filetype=php
+autocmd BufRead,BufNewFile *.theme set filetype=php
+autocmd BufRead,BufNewFile *.engine set filetype=php
+autocmd BufRead,BufNewFile *.test set filetype=php
+autocmd BufRead,BufNewFile *.{info,make,build} set filetype=drini
diff --git a/ftplugin/drupal.vim b/ftplugin/drupal.vim
index b95be7e..922f19b 100644
--- a/ftplugin/drupal.vim
+++ b/ftplugin/drupal.vim
@@ -1,5 +1,5 @@
-" This file contains common Drupal-related settings.  It is :source'd by the
-" *_drupal.vim files in this directory; there is no drupal filetype.
+" We never :set ft=drupal.  This filetype is always added to another, as in
+" :set ft=php.drupal or :set ft=css.drupal.
 
 setl nojoinspaces            "No second space when joining lines that end in "."
 setl autoindent              "Auto indent based on previous line
@@ -21,45 +21,49 @@ setl formatoptions+=croql
 " Custom SVN blame
 vmap <buffer> gl :<C-U>!svn blame <C-R>=expand("%:P") <CR> \| sed -n <C-R>=line("'<") <CR>,<C-R>=line("'>") <CR>p <CR>
 
-" Return a string that can be used to open URL's (and other things).
-" Usage:
-" let open = s:OpenCommand()
-" if strlen(open) | execute '!' . open . ' http://example.com' | endif
-" See http://www.dwheeler.com/essays/open-files-urls.html
-if !exists('*s:OpenCommand')
+" {{{ @var $DRUPAL_ROOT
+" plugin/drupal.vim defines several useful strings in b:Drupal_info.
+" There is no such thing as buffer-local environment variables, so call this
+" each time you enter a Drupal buffer.
+augroup Drupal
+  autocmd BufEnter <buffer> if strlen(b:Drupal_info.DRUPAL_ROOT) |
+	\ let $DRUPAL_ROOT = b:Drupal_info.DRUPAL_ROOT | endif
+augroup END
+do Drupal BufEnter <buffer>
+" }}}
 
-function s:OpenCommand()
-if has('macunix') && executable('open')
-  return 'open'
+" The tags file can be used for PHP omnicompletion even if $DRUPAL_ROOT == ''.
+" If $DRUPAL_ROOT is set correctly, then the tags file can be used for tag
+" searches.
+" TODO:  If we do not know which version of Drupal core, add no tags file or
+" all?
+if strlen(b:Drupal_info.CORE)
+  let &l:tags .= ',' . expand('<sfile>:p:h:h') . '/drupal' . b:Drupal_info.CORE . '.tags'
 endif
-if has('win32unix') && executable('cygstart')
-  return 'cygstart'
-endif
-if has('unix') && executable('xdg-open')
-  return 'xdg-open'
-endif
-if (has('win32') || has('win64')) && executable('cmd')
-  return 'cmd /c start'
-endif
-  return ''
-endfun
+
+if !exists('*s:OpenURL')
 
 function s:OpenURL(base)
-  let open = s:OpenCommand()
+  let open = b:Drupal_info.OPEN_COMMAND
   if open == ''
     return
   endif
   let func =  shellescape(expand('<cword>'))
   if a:base == 'api.d.o'
-    execute '!' . open . ' http://api.drupal.org/' . func
+    if strlen(b:Drupal_info.CORE)
+      execute '!' . open . ' http://api.drupal.org/api/search/' .
+	    \ b:Drupal_info.CORE . '/' . func
+    else
+      execute '!' . open . ' http://api.drupal.org/' . func
+    endif
   else
     execute '!' . open . ' ' . a:base . func
   endif
 endfun
 
-endif " !exists('*s:OpenCommand')
+endif " !exists('*s:OpenURL')
 
-if strlen(s:OpenCommand())
+if strlen(b:Drupal_info.OPEN_COMMAND)
   " Lookup the API docs for a drupal function under cursor.
   nnoremap <buffer> <LocalLeader>da :silent call <SID>OpenURL('api.d.o')<CR><C-L>
 
@@ -69,3 +73,16 @@ endif
 
 " Get the value of the drupal variable under cursor.
 nnoremap <buffer> <LocalLeader>dv :execute "!drush vget ".shellescape(expand("<cword>"), 1)<CR>
+
+" PHP specific settings.
+" In ftdetect/drupal.vim we set ft=php.drupal.  This means that the settings
+" here will come after those set by the PHP ftplugins.  In particular, we can
+" override the 'comments' setting.
+
+if &ft =~ '\<php\>'
+  setl ignorecase              "Ignore case in search
+  setl smartcase               "Only ignore case when all letters are lowercase
+  setl comments=sr:/**,m:*\ ,ex:*/,://
+  "  Format comment blocks.  Just type / on a new line to close.
+  "  Recognize // (but not #) style comments.
+endif
diff --git a/ftplugin/javascript_drupal.vim b/ftplugin/javascript_drupal.vim
deleted file mode 100644
index 17afa0b..0000000
--- a/ftplugin/javascript_drupal.vim
+++ /dev/null
@@ -1,13 +0,0 @@
-" Source the default ftplugin so that it does not change our settings.
-" Uncomment the next line if it is needed.
-" runtime! ftplugin/javascript.vim
-
-" Get common settings and mappings for Drupal.
-source <sfile>:h/drupal.vim
-
-" Settings specific to javascript/Drupal go here.
-
-" Is javascript a case-insensitive language?
-
-" setl ignorecase              "Ignore case in search
-" setl smartcase               "Only ignore case when all letters are lowercase
diff --git a/ftplugin/php_drupal.vim b/ftplugin/php_drupal.vim
deleted file mode 100644
index 08276b4..0000000
--- a/ftplugin/php_drupal.vim
+++ /dev/null
@@ -1,12 +0,0 @@
-" Source the default ftplugin so that it does not change our settings.
-" Specifically, the 'comments' option gets clobbered by html.vim.
-runtime! ftplugin/php.vim
-
-" Get common settings and mappings for Drupal.
-source <sfile>:h/drupal.vim
-
-setl ignorecase              "Ignore case in search
-setl smartcase               "Only ignore case when all letters are lowercase
-setl comments=sr:/**,m:*\ ,ex:*/,://
-"  Format comment blocks.  Just type / on a new line to close.
-"  Recognize // (but not #) style comments.
diff --git a/plugin/drupal.vim b/plugin/drupal.vim
index 656afce..3ea5bd1 100644
--- a/plugin/drupal.vim
+++ b/plugin/drupal.vim
@@ -48,33 +48,39 @@ map <S-u> :redo<cr>
 map <C-n> :tabn<cr>
 map <C-p> :tabp<cr>
 
+" {{{
+" Everything from here on assumes that autocommands are available.
+" }}}
+if !has("autocmd")
+  finish
+endif
+
 " Uncomment the following to have Vim jump to the last position when
 " reopening a file
-if has("autocmd")
- au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$")
- \| exe "normal! g'\"" | endif
-endif
+au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$")
+      \| exe "normal! g'\"" | endif
 
-" Highlight long comments and trailing whitespace.
-" It is not good practice to include syntax items in a plugin file, but we do
-" it here, with Syntax autocommands, because syntax files do not follow the
-" same naming conventions as ftplugin files, so we cannot use (for example)
-" syntax/php_drupal.vim .
-" Adapted from http://vim.wikia.com/wiki/Highlight_unwanted_spaces
-highlight default link drupalExtraWhitespace Error
-highlight default link drupalOverLength Error
 augroup Drupal
   " Remove ALL autocommands for the Drupal group.
   autocmd!
-  autocmd Syntax php syn match drupalOverLength "\%81v.*" containedin=phpComment contained
-  autocmd Syntax css syn match drupalOverLength "\%81v.*" containedin=cssComment contained
+  " s:DrupalInit() will create the buffer-local Dictionary b:Drupal_info
+  " containing useful information for ftplugins and syntax files.  It will
+  " also add drupal as a secondary filetype.  This will load the ftplugins and
+  " syntax files drupal.vim after the usual ones.
+  autocmd FileType php,css,javascript,drini call s:DrupalInit()
+
+  " Highlight trailing whitespace.
   autocmd BufWinEnter * call s:ToggleWhitespaceMatch('BufWinEnter')
   autocmd BufWinLeave * call s:ToggleWhitespaceMatch('BufWinLeave')
   autocmd InsertEnter * call s:ToggleWhitespaceMatch('InsertEnter')
   autocmd InsertLeave * call s:ToggleWhitespaceMatch('InsertLeave')
 augroup END
+highlight default link drupalExtraWhitespace Error
+
+" Adapted from http://vim.wikia.com/wiki/Highlight_unwanted_spaces
 function! s:ToggleWhitespaceMatch(event)
-  if &ft != 'php' && &ft != 'css'
+  " Bail out unless the filetype is php.drupal, css.drupal, ...
+  if &ft !~ '\<drupal\>'
     return
   endif
   if a:event == 'BufWinEnter'
@@ -93,3 +99,177 @@ function! s:ToggleWhitespaceMatch(event)
     call matchadd('drupalExtraWhitespace', '\s\+$', 10, w:whitespace_match_number)
   endif
 endfunction
+
+" Borrowed from autoload/pathogen.vim:
+let s:slash = !exists("+shellslash") || &shellslash ? '/' : '\'
+
+" {{{ @function s:DrupalInit()
+" Save some information in the buffer-local Dictionary b:Drupal_info for use
+" by ftplugin and syntax scripts.  The keys are
+" - DRUPAL_ROOT
+"   path to the Drupal root
+" - INFO_FILE
+"   path to the .info file of the containing module, theme, etc.
+" - TYPE
+"   'module' or 'theme' or 'make'
+" - OPEN_COMMAND
+"   'open' or 'xdg-open' or 'cmd /c start', depending on the OS
+" In all cases, the values will be '' if we cannot make a reasonable guess.
+" {{{
+function! s:DrupalInit()
+  " Expect something like /var/www/drupal-7.9/sites/all/modules/ctools
+  let path = expand('%:p')
+  let directory = fnamemodify(path, ':h')
+  let info = {'DRUPAL_ROOT': s:DrupalRoot(directory),
+	\ 'INFO_FILE': s:InfoPath(directory)}
+  let info.OPEN_COMMAND = s:OpenCommand()
+  let info.TYPE = s:IniType(info.INFO_FILE)
+  let info.CORE = s:CoreVersion(info.INFO_FILE)
+  if info.CORE == '' && info.DRUPAL_ROOT != ''
+    let INFO_FILE = info.DRUPAL_ROOT . '/modules/system/system.info'
+    if filereadable(INFO_FILE)
+      let info.CORE = s:CoreVersion(INFO_FILE)
+    endif
+  endif
+
+  " @var b:Drupal_info
+  let b:Drupal_info = info
+  " TODO:  If we are not inside a Drupal directory, maybe skip this.  Wait
+  " until someone complains that we are munging his non-Drupal php files.
+  set ft+=.drupal
+endfun
+" }}} }}}
+
+" {{{ @function s:IniType()
+" Try to guess which part of the path is the Drupal root directory.
+"
+" @param path
+"   A string representing a system path.
+"
+" @return
+"   A string representing the Drupal root, '' if not found.
+" {{{
+function! s:DrupalRoot(path)
+  let markers = ['index.php', 'cron.php', 'modules', 'themes', 'sites']
+  " On *nix, start with '', but on Windows typically start with 'C:'.
+  let droot = matchstr(a:path, '[^\' . s:slash . ']*')
+  for part in split(matchstr(a:path, '\' . s:slash . '.*'), s:slash)
+    let droot .= s:slash . part
+    " This would be easier if it did not have to work on Windows.
+    let ls = glob(droot . s:slash . '*') . "\<C-J>"
+    let is_drupal_root = 1
+    for marker in markers
+      if match(ls, '\' . s:slash . marker . "\<C-J>") == -1
+	let is_drupal_root = 0
+	break
+      endif
+    endfor
+    " If all the markers are there, then this looks like a Drupal root.
+    if is_drupal_root
+      return droot
+    endif
+  endfor
+  return ''
+endfun
+" }}} }}}
+
+" {{{ @function s:IniType()
+" Try to find the .info file of the module, theme, etc. containing a path.
+"
+" @param path
+"   A string representing a system path.
+"
+" @return
+"   A string representing the path of the .info file, '' if not found.
+" {{{
+function! s:InfoPath(path)
+  let dir = a:path
+  while dir =~ '\' . s:slash
+    let infopath = glob(dir . s:slash . '*.{info,make,build}')
+    if strlen(infopath)
+      return infopath
+    endif
+    " No luck yet, so go up one directory.
+    let dir = substitute(dir, '\' . s:slash . '[^\' . s:slash . ']*$', '', '')
+  endwhile
+  return ''
+endfun
+" }}} }}}
+
+" Return a string that can be used to open URL's (and other things).
+" Usage:
+" let open = s:OpenCommand()
+" if strlen(open) | execute '!' . open . ' http://example.com' | endif
+" See http://www.dwheeler.com/essays/open-files-urls.html
+function! s:OpenCommand()
+if has('macunix') && executable('open')
+  return 'open'
+endif
+if has('win32unix') && executable('cygstart')
+  return 'cygstart'
+endif
+if has('unix') && executable('xdg-open')
+  return 'xdg-open'
+endif
+if (has('win32') || has('win64')) && executable('cmd')
+  return 'cmd /c start'
+endif
+  return ''
+endfun
+
+" {{{ @function s:CoreVersion(info_path)
+" Find the version of Drupal core by parsing the .info file.
+"
+" @param info_path
+"   A string representing the path to the .info file.
+"
+" @return
+"   A numeric string representing the Drupal core version.
+" {{{
+function! s:CoreVersion(info_path)
+  " Find the Drupal core version.
+  if a:info_path == '' || !filereadable(a:info_path)
+    return ''
+  endif
+  let lines = readfile(a:info_path, '', 500)
+  let core_re = '^\s*core\s*=\s*\zs\d\+\ze\.x\s*$'
+  let core_line = matchstr(lines, core_re)
+  return matchstr(core_line, core_re)
+endfun
+" }}} }}}
+
+" {{{ @function s:IniType(info_path)
+" Find the type (module, theme, make) by parsing the path.
+"
+" @param info_path
+"   A string representing the path to the .info file.
+"
+" @return
+"   A string:  module, theme, make
+" {{{
+" TODO:  How do we recognize a Profiler .info file?
+function! s:IniType(info_path)
+  let ext = fnamemodify(a:info_path, ':e')
+  if ext == 'make' || ext == 'build'
+    return 'make'
+  else
+    " If the extension is not 'info' at this point, I do not know how we got
+    " here.
+    let m_index = strridx(a:info_path, s:slash . 'modules' . s:slash)
+    let t_index = strridx(a:info_path, s:slash . 'themes' . s:slash)
+    " If neither matches, try a case-insensitive search.
+    if m_index == -1 && t_index == -1
+      let m_index = matchend(a:info_path, '\c.*\' . s:slash . 'modules\' . s:slash)
+      let t_index = matchend(a:info_path, '\c.*\' . s:slash . 'themes\' . s:slash)
+    endif
+    if m_index > t_index
+      return 'module'
+    elseif m_index < t_index
+      return 'theme'
+    endif
+    " We are not inside a themes/ directory, nor a modules/ directory.  Do not
+    " guess.
+    return ''
+  endif
+endfun
+" }}} }}}
diff --git a/syntax/drupal.vim b/syntax/drupal.vim
new file mode 100644
index 0000000..14ef848
--- /dev/null
+++ b/syntax/drupal.vim
@@ -0,0 +1,13 @@
+" We never :set ft=drupal.  This filetype is always added to another, as in
+" :set ft=php.drupal or :set ft=css.drupal.
+
+" Highlight long comments.  The order of these two commands matters!
+syn match drupalOverLength "\%>80v[^*/].*" containedin=@drupalComment contained
+syn match drupalOverLength "\%81v.*\*\/"me=e-2 containedin=@drupalComment contained
+" Add <syntax>Comment.* to the @drupalComment cluster for all applicable
+" syntax types.
+let s:syntax = substitute(&syntax, '\.drupal\>', '', 'g')
+execute 'syn cluster drupalComment contains=' .
+      \ substitute(s:syntax, '\.\|$', 'Comment.*,', 'g')
+
+highlight default link drupalOverLength Error
