Index: /CKEditor/trunk/_dev/_thirdparty/console_getopt/Getopt.php
===================================================================
--- /CKEditor/trunk/_dev/_thirdparty/console_getopt/Getopt.php	(revision 2935)
+++ /CKEditor/trunk/_dev/_thirdparty/console_getopt/Getopt.php	(revision 2935)
@@ -0,0 +1,290 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP Version 5                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2004 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at the following url:           |
+// | http://www.php.net/license/3_0.txt.                                  |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Author: Andrei Zmievski <andrei@php.net>                             |
+// +----------------------------------------------------------------------+
+//
+// $Id: Getopt.php,v 1.4 2007/06/12 14:58:56 cellog Exp $
+
+require_once 'PEAR.php';
+
+/**
+ * Command-line options parsing class.
+ *
+ * @author Andrei Zmievski <andrei@php.net>
+ *
+ */
+class Console_Getopt {
+    /**
+     * Parses the command-line options.
+     *
+     * The first parameter to this function should be the list of command-line
+     * arguments without the leading reference to the running program.
+     *
+     * The second parameter is a string of allowed short options. Each of the
+     * option letters can be followed by a colon ':' to specify that the option
+     * requires an argument, or a double colon '::' to specify that the option
+     * takes an optional argument.
+     *
+     * The third argument is an optional array of allowed long options. The
+     * leading '--' should not be included in the option name. Options that
+     * require an argument should be followed by '=', and options that take an
+     * option argument should be followed by '=='.
+     *
+     * The return value is an array of two elements: the list of parsed
+     * options and the list of non-option command-line arguments. Each entry in
+     * the list of parsed options is a pair of elements - the first one
+     * specifies the option, and the second one specifies the option argument,
+     * if there was one.
+     *
+     * Long and short options can be mixed.
+     *
+     * Most of the semantics of this function are based on GNU getopt_long().
+     *
+     * @param array  $args           an array of command-line arguments
+     * @param string $short_options  specifies the list of allowed short options
+     * @param array  $long_options   specifies the list of allowed long options
+     *
+     * @return array two-element array containing the list of parsed options and
+     * the non-option arguments
+     *
+     * @access public
+     *
+     */
+    function getopt2($args, $short_options, $long_options = null)
+    {
+        return Console_Getopt::doGetopt(2, $args, $short_options, $long_options);
+    }
+
+    /**
+     * This function expects $args to start with the script name (POSIX-style).
+     * Preserved for backwards compatibility.
+     * @see getopt2()
+     */
+    function getopt($args, $short_options, $long_options = null)
+    {
+        return Console_Getopt::doGetopt(1, $args, $short_options, $long_options);
+    }
+
+    /**
+     * The actual implementation of the argument parsing code.
+     */
+    function doGetopt($version, $args, $short_options, $long_options = null)
+    {
+        // in case you pass directly readPHPArgv() as the first arg
+        if (PEAR::isError($args)) {
+            return $args;
+        }
+        if (empty($args)) {
+            return array(array(), array());
+        }
+        $opts     = array();
+        $non_opts = array();
+
+        settype($args, 'array');
+
+        if ($long_options) {
+            sort($long_options);
+        }
+
+        /*
+         * Preserve backwards compatibility with callers that relied on
+         * erroneous POSIX fix.
+         */
+        if ($version < 2) {
+            if (isset($args[0]{0}) && $args[0]{0} != '-') {
+                array_shift($args);
+            }
+        }
+
+        reset($args);
+        while (list($i, $arg) = each($args)) {
+
+            /* The special element '--' means explicit end of
+               options. Treat the rest of the arguments as non-options
+               and end the loop. */
+            if ($arg == '--') {
+                $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
+                break;
+            }
+
+            if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) {
+                $non_opts = array_merge($non_opts, array_slice($args, $i));
+                break;
+            } elseif (strlen($arg) > 1 && $arg{1} == '-') {
+                $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args);
+                if (PEAR::isError($error))
+                    return $error;
+            } elseif ($arg == '-') {
+                // - is stdin
+                $non_opts = array_merge($non_opts, array_slice($args, $i));
+                break;
+            } else {
+                $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args);
+                if (PEAR::isError($error))
+                    return $error;
+            }
+        }
+
+        return array($opts, $non_opts);
+    }
+
+    /**
+     * @access private
+     *
+     */
+    function _parseShortOption($arg, $short_options, &$opts, &$args)
+    {
+        for ($i = 0; $i < strlen($arg); $i++) {
+            $opt = $arg{$i};
+            $opt_arg = null;
+
+            /* Try to find the short option in the specifier string. */
+            if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':')
+            {
+                return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt");
+            }
+
+            if (strlen($spec) > 1 && $spec{1} == ':') {
+                if (strlen($spec) > 2 && $spec{2} == ':') {
+                    if ($i + 1 < strlen($arg)) {
+                        /* Option takes an optional argument. Use the remainder of
+                           the arg string if there is anything left. */
+                        $opts[] = array($opt, substr($arg, $i + 1));
+                        break;
+                    }
+                } else {
+                    /* Option requires an argument. Use the remainder of the arg
+                       string if there is anything left. */
+                    if ($i + 1 < strlen($arg)) {
+                        $opts[] = array($opt,  substr($arg, $i + 1));
+                        break;
+                    } else if (list(, $opt_arg) = each($args)) {
+                        /* Else use the next argument. */;
+                        if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) {
+                            return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt");
+                        }
+                    } else {
+                        return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt");
+                    }
+                }
+            }
+
+            $opts[] = array($opt, $opt_arg);
+        }
+    }
+
+    /**
+     * @access private
+     *
+     */
+    function _isShortOpt($arg)
+    {
+        return strlen($arg) == 2 && $arg[0] == '-' && preg_match('/[a-zA-Z]/', $arg[1]);
+    }
+
+    /**
+     * @access private
+     *
+     */
+    function _isLongOpt($arg)
+    {
+        return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
+            preg_match('/[a-zA-Z]+$/', substr($arg, 2));
+    }
+
+    /**
+     * @access private
+     *
+     */
+    function _parseLongOption($arg, $long_options, &$opts, &$args)
+    {
+        @list($opt, $opt_arg) = explode('=', $arg, 2);
+        $opt_len = strlen($opt);
+
+        for ($i = 0; $i < count($long_options); $i++) {
+            $long_opt  = $long_options[$i];
+            $opt_start = substr($long_opt, 0, $opt_len);
+            $long_opt_name = str_replace('=', '', $long_opt);
+
+            /* Option doesn't match. Go on to the next one. */
+            if ($long_opt_name != $opt) {
+                continue;
+            }
+
+            $opt_rest  = substr($long_opt, $opt_len);
+
+            /* Check that the options uniquely matches one of the allowed
+               options. */
+            if ($i + 1 < count($long_options)) {
+                $next_option_rest = substr($long_options[$i + 1], $opt_len);
+            } else {
+                $next_option_rest = '';
+            }
+            if ($opt_rest != '' && $opt{0} != '=' &&
+                $i + 1 < count($long_options) &&
+                $opt == substr($long_options[$i+1], 0, $opt_len) &&
+                $next_option_rest != '' &&
+                $next_option_rest{0} != '=') {
+                return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous");
+            }
+
+            if (substr($long_opt, -1) == '=') {
+                if (substr($long_opt, -2) != '==') {
+                    /* Long option requires an argument.
+                       Take the next argument if one wasn't specified. */;
+                    if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) {
+                        return PEAR::raiseError("Console_Getopt: option --$opt requires an argument");
+                    }
+                    if (Console_Getopt::_isShortOpt($opt_arg) || Console_Getopt::_isLongOpt($opt_arg)) {
+                        return PEAR::raiseError("Console_Getopt: option requires an argument --$opt");
+                    }
+                }
+            } else if ($opt_arg) {
+                return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument");
+            }
+
+            $opts[] = array('--' . $opt, $opt_arg);
+            return;
+        }
+
+        return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
+    }
+
+    /**
+    * Safely read the $argv PHP array across different PHP configurations.
+    * Will take care on register_globals and register_argc_argv ini directives
+    *
+    * @access public
+    * @return mixed the $argv PHP array or PEAR error if not registered
+    */
+    function readPHPArgv()
+    {
+        global $argv;
+        if (!is_array($argv)) {
+            if (!@is_array($_SERVER['argv'])) {
+                if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
+                    return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)");
+                }
+                return $GLOBALS['HTTP_SERVER_VARS']['argv'];
+            }
+            return $_SERVER['argv'];
+        }
+        return $argv;
+    }
+
+}
+
+?>
Index: /CKEditor/trunk/_dev/_thirdparty/console_getopt/PEAR.php
===================================================================
--- /CKEditor/trunk/_dev/_thirdparty/console_getopt/PEAR.php	(revision 2935)
+++ /CKEditor/trunk/_dev/_thirdparty/console_getopt/PEAR.php	(revision 2935)
@@ -0,0 +1,1118 @@
+<?php
+/**
+ * PEAR, the PHP Extension and Application Repository
+ *
+ * PEAR class and PEAR_Error class
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Sterling Hughes <sterling@php.net>
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V.Cox <cox@idecnet.com>
+ * @author     Greg Beaver <cellog@php.net>
+ * @copyright  1997-2008 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    CVS: $Id: PEAR.php,v 1.104 2008/01/03 20:26:34 cellog Exp $
+ * @link       http://pear.php.net/package/PEAR
+ * @since      File available since Release 0.1
+ */
+
+/**#@+
+ * ERROR constants
+ */
+define('PEAR_ERROR_RETURN',     1);
+define('PEAR_ERROR_PRINT',      2);
+define('PEAR_ERROR_TRIGGER',    4);
+define('PEAR_ERROR_DIE',        8);
+define('PEAR_ERROR_CALLBACK',  16);
+/**
+ * WARNING: obsolete
+ * @deprecated
+ */
+define('PEAR_ERROR_EXCEPTION', 32);
+/**#@-*/
+define('PEAR_ZE2', (function_exists('version_compare') &&
+                    version_compare(zend_version(), "2-dev", "ge")));
+
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+    define('OS_WINDOWS', true);
+    define('OS_UNIX',    false);
+    define('PEAR_OS',    'Windows');
+} else {
+    define('OS_WINDOWS', false);
+    define('OS_UNIX',    true);
+    define('PEAR_OS',    'Unix'); // blatant assumption
+}
+
+// instant backwards compatibility
+if (!defined('PATH_SEPARATOR')) {
+    if (OS_WINDOWS) {
+        define('PATH_SEPARATOR', ';');
+    } else {
+        define('PATH_SEPARATOR', ':');
+    }
+}
+
+$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
+$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
+$GLOBALS['_PEAR_destructor_object_list'] = array();
+$GLOBALS['_PEAR_shutdown_funcs']         = array();
+$GLOBALS['_PEAR_error_handler_stack']    = array();
+
+@ini_set('track_errors', true);
+
+/**
+ * Base class for other PEAR classes.  Provides rudimentary
+ * emulation of destructors.
+ *
+ * If you want a destructor in your class, inherit PEAR and make a
+ * destructor method called _yourclassname (same name as the
+ * constructor, but with a "_" prefix).  Also, in your constructor you
+ * have to call the PEAR constructor: $this->PEAR();.
+ * The destructor method will be called without parameters.  Note that
+ * at in some SAPI implementations (such as Apache), any output during
+ * the request shutdown (in which destructors are called) seems to be
+ * discarded.  If you need to get any debug information from your
+ * destructor, use error_log(), syslog() or something similar.
+ *
+ * IMPORTANT! To use the emulated destructors you need to create the
+ * objects by reference: $obj =& new PEAR_child;
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V. Cox <cox@idecnet.com>
+ * @author     Greg Beaver <cellog@php.net>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.7.1
+ * @link       http://pear.php.net/package/PEAR
+ * @see        PEAR_Error
+ * @since      Class available since PHP 4.0.2
+ * @link        http://pear.php.net/manual/en/core.pear.php#core.pear.pear
+ */
+class PEAR
+{
+    // {{{ properties
+
+    /**
+     * Whether to enable internal debug messages.
+     *
+     * @var     bool
+     * @access  private
+     */
+    var $_debug = false;
+
+    /**
+     * Default error mode for this object.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_mode = null;
+
+    /**
+     * Default error options used for this object when error mode
+     * is PEAR_ERROR_TRIGGER.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_options = null;
+
+    /**
+     * Default error handler (callback) for this object, if error mode is
+     * PEAR_ERROR_CALLBACK.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_default_error_handler = '';
+
+    /**
+     * Which class to use for error objects.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_error_class = 'PEAR_Error';
+
+    /**
+     * An array of expected errors.
+     *
+     * @var     array
+     * @access  private
+     */
+    var $_expected_errors = array();
+
+    // }}}
+
+    // {{{ constructor
+
+    /**
+     * Constructor.  Registers this object in
+     * $_PEAR_destructor_object_list for destructor emulation if a
+     * destructor object exists.
+     *
+     * @param string $error_class  (optional) which class to use for
+     *        error objects, defaults to PEAR_Error.
+     * @access public
+     * @return void
+     */
+    function PEAR($error_class = null)
+    {
+        $classname = strtolower(get_class($this));
+        if ($this->_debug) {
+            print "PEAR constructor called, class=$classname\n";
+        }
+        if ($error_class !== null) {
+            $this->_error_class = $error_class;
+        }
+        while ($classname && strcasecmp($classname, "pear")) {
+            $destructor = "_$classname";
+            if (method_exists($this, $destructor)) {
+                global $_PEAR_destructor_object_list;
+                $_PEAR_destructor_object_list[] = &$this;
+                if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+                    register_shutdown_function("_PEAR_call_destructors");
+                    $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+                }
+                break;
+            } else {
+                $classname = get_parent_class($classname);
+            }
+        }
+    }
+
+    // }}}
+    // {{{ destructor
+
+    /**
+     * Destructor (the emulated type of...).  Does nothing right now,
+     * but is included for forward compatibility, so subclass
+     * destructors should always call it.
+     *
+     * See the note in the class desciption about output from
+     * destructors.
+     *
+     * @access public
+     * @return void
+     */
+    function _PEAR() {
+        if ($this->_debug) {
+            printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
+        }
+    }
+
+    // }}}
+    // {{{ getStaticProperty()
+
+    /**
+    * If you have a class that's mostly/entirely static, and you need static
+    * properties, you can use this method to simulate them. Eg. in your method(s)
+    * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
+    * You MUST use a reference, or they will not persist!
+    *
+    * @access public
+    * @param  string $class  The calling classname, to prevent clashes
+    * @param  string $var    The variable to retrieve.
+    * @return mixed   A reference to the variable. If not set it will be
+    *                 auto initialised to NULL.
+    */
+    function &getStaticProperty($class, $var)
+    {
+        static $properties;
+        if (!isset($properties[$class])) {
+            $properties[$class] = array();
+        }
+        if (!array_key_exists($var, $properties[$class])) {
+            $properties[$class][$var] = null;
+        }
+        return $properties[$class][$var];
+    }
+
+    // }}}
+    // {{{ registerShutdownFunc()
+
+    /**
+    * Use this function to register a shutdown method for static
+    * classes.
+    *
+    * @access public
+    * @param  mixed $func  The function name (or array of class/method) to call
+    * @param  mixed $args  The arguments to pass to the function
+    * @return void
+    */
+    function registerShutdownFunc($func, $args = array())
+    {
+        // if we are called statically, there is a potential
+        // that no shutdown func is registered.  Bug #6445
+        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+            register_shutdown_function("_PEAR_call_destructors");
+            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+        }
+        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
+    }
+
+    // }}}
+    // {{{ isError()
+
+    /**
+     * Tell whether a value is a PEAR error.
+     *
+     * @param   mixed $data   the value to test
+     * @param   int   $code   if $data is an error object, return true
+     *                        only if $code is a string and
+     *                        $obj->getMessage() == $code or
+     *                        $code is an integer and $obj->getCode() == $code
+     * @access  public
+     * @return  bool    true if parameter is an error
+     */
+    function isError($data, $code = null)
+    {
+        if (is_a($data, 'PEAR_Error')) {
+            if (is_null($code)) {
+                return true;
+            } elseif (is_string($code)) {
+                return $data->getMessage() == $code;
+            } else {
+                return $data->getCode() == $code;
+            }
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ setErrorHandling()
+
+    /**
+     * Sets how errors generated by this object should be handled.
+     * Can be invoked both in objects and statically.  If called
+     * statically, setErrorHandling sets the default behaviour for all
+     * PEAR objects.  If called in an object, setErrorHandling sets
+     * the default behaviour for that object.
+     *
+     * @param int $mode
+     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
+     *
+     * @param mixed $options
+     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
+     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *
+     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
+     *        to be the callback function or method.  A callback
+     *        function is a string with the name of the function, a
+     *        callback method is an array of two elements: the element
+     *        at index 0 is the object, and the element at index 1 is
+     *        the name of the method to call in the object.
+     *
+     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
+     *        a printf format string used when printing the error
+     *        message.
+     *
+     * @access public
+     * @return void
+     * @see PEAR_ERROR_RETURN
+     * @see PEAR_ERROR_PRINT
+     * @see PEAR_ERROR_TRIGGER
+     * @see PEAR_ERROR_DIE
+     * @see PEAR_ERROR_CALLBACK
+     * @see PEAR_ERROR_EXCEPTION
+     *
+     * @since PHP 4.0.5
+     */
+
+    function setErrorHandling($mode = null, $options = null)
+    {
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $setmode     = &$this->_default_error_mode;
+            $setoptions  = &$this->_default_error_options;
+        } else {
+            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
+            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+        }
+
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+    }
+
+    // }}}
+    // {{{ expectError()
+
+    /**
+     * This method is used to tell which errors you expect to get.
+     * Expected errors are always returned with error mode
+     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
+     * and this method pushes a new element onto it.  The list of
+     * expected errors are in effect until they are popped off the
+     * stack with the popExpect() method.
+     *
+     * Note that this method can not be called statically
+     *
+     * @param mixed $code a single error code or an array of error codes to expect
+     *
+     * @return int     the new depth of the "expected errors" stack
+     * @access public
+     */
+    function expectError($code = '*')
+    {
+        if (is_array($code)) {
+            array_push($this->_expected_errors, $code);
+        } else {
+            array_push($this->_expected_errors, array($code));
+        }
+        return sizeof($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ popExpect()
+
+    /**
+     * This method pops one element off the expected error codes
+     * stack.
+     *
+     * @return array   the list of error codes that were popped
+     */
+    function popExpect()
+    {
+        return array_pop($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ _checkDelExpect()
+
+    /**
+     * This method checks unsets an error code if available
+     *
+     * @param mixed error code
+     * @return bool true if the error code was unset, false otherwise
+     * @access private
+     * @since PHP 4.3.0
+     */
+    function _checkDelExpect($error_code)
+    {
+        $deleted = false;
+
+        foreach ($this->_expected_errors AS $key => $error_array) {
+            if (in_array($error_code, $error_array)) {
+                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
+                $deleted = true;
+            }
+
+            // clean up empty arrays
+            if (0 == count($this->_expected_errors[$key])) {
+                unset($this->_expected_errors[$key]);
+            }
+        }
+        return $deleted;
+    }
+
+    // }}}
+    // {{{ delExpect()
+
+    /**
+     * This method deletes all occurences of the specified element from
+     * the expected error codes stack.
+     *
+     * @param  mixed $error_code error code that should be deleted
+     * @return mixed list of error codes that were deleted or error
+     * @access public
+     * @since PHP 4.3.0
+     */
+    function delExpect($error_code)
+    {
+        $deleted = false;
+
+        if ((is_array($error_code) && (0 != count($error_code)))) {
+            // $error_code is a non-empty array here;
+            // we walk through it trying to unset all
+            // values
+            foreach($error_code as $key => $error) {
+                if ($this->_checkDelExpect($error)) {
+                    $deleted =  true;
+                } else {
+                    $deleted = false;
+                }
+            }
+            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+        } elseif (!empty($error_code)) {
+            // $error_code comes alone, trying to unset it
+            if ($this->_checkDelExpect($error_code)) {
+                return true;
+            } else {
+                return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+            }
+        } else {
+            // $error_code is empty
+            return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
+        }
+    }
+
+    // }}}
+    // {{{ raiseError()
+
+    /**
+     * This method is a wrapper that returns an instance of the
+     * configured error class with this object's default error
+     * handling applied.  If the $mode and $options parameters are not
+     * specified, the object's defaults are used.
+     *
+     * @param mixed $message a text error message or a PEAR error object
+     *
+     * @param int $code      a numeric error code (it is up to your class
+     *                  to define these if you want to use codes)
+     *
+     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
+     *
+     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
+     *                  specifies the PHP-internal error level (one of
+     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *                  If $mode is PEAR_ERROR_CALLBACK, this
+     *                  parameter specifies the callback function or
+     *                  method.  In other error modes this parameter
+     *                  is ignored.
+     *
+     * @param string $userinfo If you need to pass along for example debug
+     *                  information, this parameter is meant for that.
+     *
+     * @param string $error_class The returned error object will be
+     *                  instantiated from this class, if specified.
+     *
+     * @param bool $skipmsg If true, raiseError will only pass error codes,
+     *                  the error message parameter will be dropped.
+     *
+     * @access public
+     * @return object   a PEAR error object
+     * @see PEAR::setErrorHandling
+     * @since PHP 4.0.5
+     */
+    function &raiseError($message = null,
+                         $code = null,
+                         $mode = null,
+                         $options = null,
+                         $userinfo = null,
+                         $error_class = null,
+                         $skipmsg = false)
+    {
+        // The error is yet a PEAR error object
+        if (is_object($message)) {
+            $code        = $message->getCode();
+            $userinfo    = $message->getUserInfo();
+            $error_class = $message->getType();
+            $message->error_message_prefix = '';
+            $message     = $message->getMessage();
+        }
+
+        if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
+            if ($exp[0] == "*" ||
+                (is_int(reset($exp)) && in_array($code, $exp)) ||
+                (is_string(reset($exp)) && in_array($message, $exp))) {
+                $mode = PEAR_ERROR_RETURN;
+            }
+        }
+        // No mode given, try global ones
+        if ($mode === null) {
+            // Class error handler
+            if (isset($this) && isset($this->_default_error_mode)) {
+                $mode    = $this->_default_error_mode;
+                $options = $this->_default_error_options;
+            // Global error handler
+            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
+                $mode    = $GLOBALS['_PEAR_default_error_mode'];
+                $options = $GLOBALS['_PEAR_default_error_options'];
+            }
+        }
+
+        if ($error_class !== null) {
+            $ec = $error_class;
+        } elseif (isset($this) && isset($this->_error_class)) {
+            $ec = $this->_error_class;
+        } else {
+            $ec = 'PEAR_Error';
+        }
+        if (intval(PHP_VERSION) < 5) {
+            // little non-eval hack to fix bug #12147
+            include 'PEAR/FixPHP5PEARWarnings.php';
+            return $a;
+        }
+        if ($skipmsg) {
+            $a = new $ec($code, $mode, $options, $userinfo);
+        } else {
+            $a = new $ec($message, $code, $mode, $options, $userinfo);
+        }
+        return $a;
+    }
+
+    // }}}
+    // {{{ throwError()
+
+    /**
+     * Simpler form of raiseError with fewer options.  In most cases
+     * message, code and userinfo are enough.
+     *
+     * @param string $message
+     *
+     */
+    function &throwError($message = null,
+                         $code = null,
+                         $userinfo = null)
+    {
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $a = &$this->raiseError($message, $code, null, null, $userinfo);
+            return $a;
+        } else {
+            $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
+            return $a;
+        }
+    }
+
+    // }}}
+    function staticPushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+        $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        $stack[] = array($def_mode, $def_options);
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $def_mode = $mode;
+                $def_options = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $def_mode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $def_options = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    function staticPopErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
+        $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        switch ($mode) {
+            case PEAR_ERROR_EXCEPTION:
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                // class/object method callback
+                if (is_callable($options)) {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+        return true;
+    }
+
+    // {{{ pushErrorHandling()
+
+    /**
+     * Push a new error handler on top of the error handler options stack. With this
+     * you can easily override the actual error handler for some code and restore
+     * it later with popErrorHandling.
+     *
+     * @param mixed $mode (same as setErrorHandling)
+     * @param mixed $options (same as setErrorHandling)
+     *
+     * @return bool Always true
+     *
+     * @see PEAR::setErrorHandling
+     */
+    function pushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $def_mode    = &$this->_default_error_mode;
+            $def_options = &$this->_default_error_options;
+        } else {
+            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+            $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        }
+        $stack[] = array($def_mode, $def_options);
+
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    // }}}
+    // {{{ popErrorHandling()
+
+    /**
+    * Pop the last error handler used
+    *
+    * @return bool Always true
+    *
+    * @see PEAR::pushErrorHandling
+    */
+    function popErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        if (isset($this) && is_a($this, 'PEAR')) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ loadExtension()
+
+    /**
+    * OS independant PHP extension load. Remember to take care
+    * on the correct extension name for case sensitive OSes.
+    *
+    * @param string $ext The extension name
+    * @return bool Success or not on the dl() call
+    */
+    function loadExtension($ext)
+    {
+        if (!extension_loaded($ext)) {
+            // if either returns true dl() will produce a FATAL error, stop that
+            if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
+                return false;
+            }
+            if (OS_WINDOWS) {
+                $suffix = '.dll';
+            } elseif (PHP_OS == 'HP-UX') {
+                $suffix = '.sl';
+            } elseif (PHP_OS == 'AIX') {
+                $suffix = '.a';
+            } elseif (PHP_OS == 'OSX') {
+                $suffix = '.bundle';
+            } else {
+                $suffix = '.so';
+            }
+            return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
+        }
+        return true;
+    }
+
+    // }}}
+}
+
+// {{{ _PEAR_call_destructors()
+
+function _PEAR_call_destructors()
+{
+    global $_PEAR_destructor_object_list;
+    if (is_array($_PEAR_destructor_object_list) &&
+        sizeof($_PEAR_destructor_object_list))
+    {
+        reset($_PEAR_destructor_object_list);
+        if (PEAR::getStaticProperty('PEAR', 'destructlifo')) {
+            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
+        }
+        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
+            $classname = get_class($objref);
+            while ($classname) {
+                $destructor = "_$classname";
+                if (method_exists($objref, $destructor)) {
+                    $objref->$destructor();
+                    break;
+                } else {
+                    $classname = get_parent_class($classname);
+                }
+            }
+        }
+        // Empty the object list to ensure that destructors are
+        // not called more than once.
+        $_PEAR_destructor_object_list = array();
+    }
+
+    // Now call the shutdown functions
+    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
+        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
+            call_user_func_array($value[0], $value[1]);
+        }
+    }
+}
+
+// }}}
+/**
+ * Standard PEAR error class for PHP 4
+ *
+ * This class is supserseded by {@link PEAR_Exception} in PHP 5
+ *
+ * @category   pear
+ * @package    PEAR
+ * @author     Stig Bakken <ssb@php.net>
+ * @author     Tomas V.V. Cox <cox@idecnet.com>
+ * @author     Gregory Beaver <cellog@php.net>
+ * @copyright  1997-2006 The PHP Group
+ * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
+ * @version    Release: 1.7.1
+ * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
+ * @see        PEAR::raiseError(), PEAR::throwError()
+ * @since      Class available since PHP 4.0.2
+ */
+class PEAR_Error
+{
+    // {{{ properties
+
+    var $error_message_prefix = '';
+    var $mode                 = PEAR_ERROR_RETURN;
+    var $level                = E_USER_NOTICE;
+    var $code                 = -1;
+    var $message              = '';
+    var $userinfo             = '';
+    var $backtrace            = null;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * PEAR_Error constructor
+     *
+     * @param string $message  message
+     *
+     * @param int $code     (optional) error code
+     *
+     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
+     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
+     * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
+     *
+     * @param mixed $options   (optional) error level, _OR_ in the case of
+     * PEAR_ERROR_CALLBACK, the callback function or object/method
+     * tuple.
+     *
+     * @param string $userinfo (optional) additional user/debug info
+     *
+     * @access public
+     *
+     */
+    function PEAR_Error($message = 'unknown error', $code = null,
+                        $mode = null, $options = null, $userinfo = null)
+    {
+        if ($mode === null) {
+            $mode = PEAR_ERROR_RETURN;
+        }
+        $this->message   = $message;
+        $this->code      = $code;
+        $this->mode      = $mode;
+        $this->userinfo  = $userinfo;
+        if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
+            $this->backtrace = debug_backtrace();
+            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
+                unset($this->backtrace[0]['object']);
+            }
+        }
+        if ($mode & PEAR_ERROR_CALLBACK) {
+            $this->level = E_USER_NOTICE;
+            $this->callback = $options;
+        } else {
+            if ($options === null) {
+                $options = E_USER_NOTICE;
+            }
+            $this->level = $options;
+            $this->callback = null;
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+            } else {
+                $format = $options;
+            }
+            printf($format, $this->getMessage());
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            trigger_error($this->getMessage(), $this->level);
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $msg = $this->getMessage();
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+                if (substr($msg, -1) != "\n") {
+                    $msg .= "\n";
+                }
+            } else {
+                $format = $options;
+            }
+            die(sprintf($format, $msg));
+        }
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_callable($this->callback)) {
+                call_user_func($this->callback, $this);
+            }
+        }
+        if ($this->mode & PEAR_ERROR_EXCEPTION) {
+            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
+            eval('$e = new Exception($this->message, $this->code);throw($e);');
+        }
+    }
+
+    // }}}
+    // {{{ getMode()
+
+    /**
+     * Get the error mode from an error object.
+     *
+     * @return int error mode
+     * @access public
+     */
+    function getMode() {
+        return $this->mode;
+    }
+
+    // }}}
+    // {{{ getCallback()
+
+    /**
+     * Get the callback function/method from an error object.
+     *
+     * @return mixed callback function or object/method array
+     * @access public
+     */
+    function getCallback() {
+        return $this->callback;
+    }
+
+    // }}}
+    // {{{ getMessage()
+
+
+    /**
+     * Get the error message from an error object.
+     *
+     * @return  string  full error message
+     * @access public
+     */
+    function getMessage()
+    {
+        return ($this->error_message_prefix . $this->message);
+    }
+
+
+    // }}}
+    // {{{ getCode()
+
+    /**
+     * Get error code from an error object
+     *
+     * @return int error code
+     * @access public
+     */
+     function getCode()
+     {
+        return $this->code;
+     }
+
+    // }}}
+    // {{{ getType()
+
+    /**
+     * Get the name of this error/exception.
+     *
+     * @return string error/exception name (type)
+     * @access public
+     */
+    function getType()
+    {
+        return get_class($this);
+    }
+
+    // }}}
+    // {{{ getUserInfo()
+
+    /**
+     * Get additional user-supplied information.
+     *
+     * @return string user-supplied information
+     * @access public
+     */
+    function getUserInfo()
+    {
+        return $this->userinfo;
+    }
+
+    // }}}
+    // {{{ getDebugInfo()
+
+    /**
+     * Get additional debug information supplied by the application.
+     *
+     * @return string debug information
+     * @access public
+     */
+    function getDebugInfo()
+    {
+        return $this->getUserInfo();
+    }
+
+    // }}}
+    // {{{ getBacktrace()
+
+    /**
+     * Get the call backtrace from where the error was generated.
+     * Supported with PHP 4.3.0 or newer.
+     *
+     * @param int $frame (optional) what frame to fetch
+     * @return array Backtrace, or NULL if not available.
+     * @access public
+     */
+    function getBacktrace($frame = null)
+    {
+        if (defined('PEAR_IGNORE_BACKTRACE')) {
+            return null;
+        }
+        if ($frame === null) {
+            return $this->backtrace;
+        }
+        return $this->backtrace[$frame];
+    }
+
+    // }}}
+    // {{{ addUserInfo()
+
+    function addUserInfo($info)
+    {
+        if (empty($this->userinfo)) {
+            $this->userinfo = $info;
+        } else {
+            $this->userinfo .= " ** $info";
+        }
+    }
+
+    // }}}
+    // {{{ toString()
+    function __toString()
+    {
+        return $this->getMessage();
+    }
+    // }}}
+    // {{{ toString()
+
+    /**
+     * Make a string representation of this object.
+     *
+     * @return string a string with an object summary
+     * @access public
+     */
+    function toString() {
+        $modes = array();
+        $levels = array(E_USER_NOTICE  => 'notice',
+                        E_USER_WARNING => 'warning',
+                        E_USER_ERROR   => 'error');
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_array($this->callback)) {
+                $callback = (is_object($this->callback[0]) ?
+                    strtolower(get_class($this->callback[0])) :
+                    $this->callback[0]) . '::' .
+                    $this->callback[1];
+            } else {
+                $callback = $this->callback;
+            }
+            return sprintf('[%s: message="%s" code=%d mode=callback '.
+                           'callback=%s prefix="%s" info="%s"]',
+                           strtolower(get_class($this)), $this->message, $this->code,
+                           $callback, $this->error_message_prefix,
+                           $this->userinfo);
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            $modes[] = 'print';
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            $modes[] = 'trigger';
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $modes[] = 'die';
+        }
+        if ($this->mode & PEAR_ERROR_RETURN) {
+            $modes[] = 'return';
+        }
+        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
+                       'prefix="%s" info="%s"]',
+                       strtolower(get_class($this)), $this->message, $this->code,
+                       implode("|", $modes), $levels[$this->level],
+                       $this->error_message_prefix,
+                       $this->userinfo);
+    }
+
+    // }}}
+}
+
+/*
+ * Local Variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
Index: /CKEditor/trunk/_dev/docs_build/docs_build.bat
===================================================================
--- /CKEditor/trunk/_dev/docs_build/docs_build.bat	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/docs_build.bat	(revision 2935)
@@ -0,0 +1,17 @@
+@ECHO OFF
+::
+:: Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+:: For licensing, see LICENSE.html or http://ckeditor.com/license
+::
+:: Build the _docs/api documentation files.
+::
+
+ECHO Building the API document at _docs/api...
+
+del /F /Q "../../_docs/api/*.*"
+
+java -jar ../_thirdparty/jsdoc-toolkit/jsrun.jar ../_thirdparty/jsdoc-toolkit/app/run.js -c=docs_build.conf
+
+:: php ../fixlineends/fixlineends.php --eolstripwhite --eofnewline --eofstripwhite --nohidden --nosystem ../../_docs/api/
+
+ECHO Finished!
Index: /CKEditor/trunk/_dev/docs_build/docs_build.conf
===================================================================
--- /CKEditor/trunk/_dev/docs_build/docs_build.conf	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/docs_build.conf	(revision 2935)
@@ -0,0 +1,36 @@
+﻿/*
+	This is an example of one way you could set up a configuration file to more
+	conveniently define some commandline options. You might like to do this if
+	you frequently reuse the same options. Note that you don't need to define
+	every option in this file, you can combine a configuration file with
+	additional options on the commandline if your wish.
+
+	You would include this configuration file by running JsDoc Toolkit like so:
+	java -jar jsrun.jar app/run.js -c=conf/sample.conf
+
+*/
+
+{
+	// Source files to parse.
+	_:
+	[
+		'../../_source/core/',
+		'../../_source/plugins/',
+		'../../_source/lang/en.js'
+	],
+
+	// Document all functions, even uncommented ones.
+	a: true,
+
+	// Recursively, up to 100 directories depth.
+	r: 100,
+
+	// use this directory as the output directory
+	d: '../../_docs/api',
+
+	// Template.
+	t: 'template',
+
+	// Verbose mode.
+	v: true
+}
Index: /CKEditor/trunk/_dev/docs_build/template/allclasses.tmpl
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/allclasses.tmpl	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/allclasses.tmpl	(revision 2935)
@@ -0,0 +1,26 @@
+<div align="center">
+	{+new Link().toFile("index.html").withText("Code Index")+}
+	| {+new Link().toFile("files.html").withText("File Index")+}
+</div>
+<hr />
+<h2>Namespaces</h2>
+<ul class="classList">
+	<for each="thisClass" in="data">
+		<if test="thisClass.isNamespace && thisClass.alias != '_global_'">
+			<li>
+				{+ new Link().toClass(thisClass.alias) +}
+			</li>
+		</if>
+	</for>
+</ul>
+<h2>Classes</h2>
+<ul class="classList">
+	<for each="thisClass" in="data">
+		<if test="!thisClass.isNamespace">
+			<li>
+				{+ new Link().toClass(thisClass.alias) +}
+			</li>
+		</if>
+	</for>
+</ul>
+<hr />
Index: /CKEditor/trunk/_dev/docs_build/template/allfiles.tmpl
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/allfiles.tmpl	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/allfiles.tmpl	(revision 2935)
@@ -0,0 +1,53 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+	<head>
+		<meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}"" />
+		{! Link.base = ""; /* all generated links will be relative to this */ !}
+		<title>File Index - CKEditor 3.0 JavaScript API Documentation</title>
+		<meta name="generator" content="JsDoc Toolkit" />
+		
+		<style type="text/css">
+		{+include("static/default.css")+}
+		</style>
+	</head>
+	
+	<body>
+		{+include("static/header.html")+}
+		
+		<div id="index">
+			{+publish.classesIndex+}
+		</div>
+		
+		<div id="content">
+			<h1 class="classTitle">File Index</h1>
+			
+			<for each="item" in="data">
+			<div>
+				<h2>{+new Link().toSrc(item.alias).withText(item.name)+}</h2>
+				<if test="item.desc">{+resolveLinks(summarize(item.desc))+}</if>
+				<dl>
+					<if test="item.author">
+						<dt class="heading">Author:</dt>
+						<dd>{+item.author+}</dd>
+					</if>
+					<if test="item.version">
+						<dt class="heading">Version:</dt>
+							<dd>{+item.version+}</dd>
+					</if>
+					{! var locations = item.comment.getTag('location').map(function($){return $.toString().replace(/(^\$ ?| ?\$$)/g, '').replace(/^HeadURL: https:/g, 'http:');}) !}
+					<if test="locations.length">
+						<dt class="heading">Location:</dt>
+							<for each="location" in="locations">
+							<dd><a href="{+location+}">{+location+}</a></dd>
+							</for>
+					</if>
+				</dl>
+			</div>
+			<hr />
+			</for>
+			
+		</div>
+		{+include("static/footer.html")+}
+	</body>
+</html>
Index: /CKEditor/trunk/_dev/docs_build/template/class.tmpl
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/class.tmpl	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/class.tmpl	(revision 2935)
@@ -0,0 +1,536 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+	<head>
+		<meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}" />
+		<meta name="generator" content="JsDoc Toolkit" />
+		{! Link.base = "../"; /* all generated links will be relative to this */ !}
+		<title>{+data.alias+} - CKEditor 3.0 JavaScript API Documentation</title>
+
+		<style type="text/css">
+			{+include("static/default.css")+}
+		</style>
+	</head>
+
+	<body>
+<!-- ============================== header ================================= -->	
+		<!-- begin static/header.html -->
+		{+include("static/header.html")+}
+		<!-- end static/header.html -->
+
+<!-- ============================== classes index ============================ -->
+		<div id="index">
+			<!-- begin publish.classesIndex -->
+			{+publish.classesIndex+}
+			<!-- end publish.classesIndex -->
+		</div>
+		
+		<div id="content">
+<!-- ============================== class title ============================ -->
+			<h1 class="classTitle">
+				{!
+					var classType = "";
+					
+					if (data.isBuiltin()) {
+						classType += "Built-In ";
+					}
+					
+					if (data.isNamespace) {
+						if (data.is('FUNCTION')) {
+							classType += "Function ";
+						}
+						classType += "Namespace ";
+					}
+					else {
+						classType += "Class ";
+					}
+				!}
+				{+classType+}{+data.alias+}
+			</h1>
+
+<!-- ============================== class summary ========================== -->			
+			<p class="description">
+				<if test="data.augments.length"><br />Extends
+					{+
+						data.augments
+						.sort()
+						.map(
+							function($) { return new Link().toSymbol($); }
+						)
+						.join(", ")
+					+}.<br />
+				</if>
+			
+				{+resolveLinks(data.classDesc)+}
+				
+				<if test="!data.isBuiltin()">{# isn't defined in any file #}
+					<br /><i>Defined in: </i> {+ ckeditor_FileLink( data.srcFile ) +}.
+				</if>
+			</p>
+
+<!-- ============================== constructor summary ==================== -->			
+			<if test="!data.isBuiltin() && (data.isNamespace || data.is('CONSTRUCTOR'))">
+			<table class="summaryTable" cellspacing="0" summary="A summary of the constructor documented in the class {+data.alias+}.">
+				<caption>{+classType+}Summary</caption>
+				<thead>
+					<tr>
+						<th scope="col">Constructor Attributes</th>
+						<th scope="col">Constructor Name and Description</th>
+					</tr>
+				</thead>
+				<tbody>
+					<tr>
+						<td class="attributes">{!
+							if (data.isPrivate) output += "&lt;private&gt; ";
+							if (data.isInner) output += "&lt;inner&gt; ";
+						!}&nbsp;</td>
+						<td class="nameDescription" {!if (data.comment.getTag("hilited").length){output += 'style="color: red"'}!}>
+							<div class="fixedFont">
+								<b>{+ new Link().toSymbol(data.alias).inner('constructor')+}</b><if test="classType != 'Namespace '">{+ makeSignature(data.params) +}</if>
+							</div>
+							<div class="description">{+resolveLinks(summarize(data.desc))+}</div>
+						</td>
+					</tr>
+				</tbody>
+			</table>
+			</if>
+
+<!-- ============================== properties summary ===================== -->
+			<if test="data.properties.length">
+
+				{! var ownConstants = data.properties.filter(function($){return $.memberOf == data.alias && !$.isNamespace && $.isConstant}).sort( ckeditor_sortByType ); !}
+				<if test="ownConstants.length">
+				<table class="summaryTable" cellspacing="0" summary="A summary of the constants documented in the class {+data.alias+}.">
+					<caption>Constants Summary</caption>
+					<thead>
+						<tr>
+							<th scope="col">Constant Attributes</th>
+							<th scope="col">Constant Name and Description</th>
+						</tr>
+					</thead>
+					<tbody>
+					<for each="member" in="ownConstants">
+						<tr>
+							<td class="attributes">{!
+								if (member.isPrivate) output += "&lt;private&gt; ";
+								if (member.isInner) output += "&lt;inner&gt; ";
+								if (member.isStatic) output += "&lt;static&gt; ";
+							!}&nbsp;</td>
+							<td class="nameDescription">
+								<div class="fixedFont">
+								<if test="member.isStatic && member.memberOf != '_global_'">{+member.memberOf+}.</if><b>{+new Link().toSymbol(member.alias).withText(member.name)+}</b>
+								</div>
+								<div class="description">{+resolveLinks(summarize(member.desc))+}</div>
+							</td>
+						</tr>
+					</for>
+					</tbody>
+				</table>
+				</if>
+
+				{! var ownProperties = data.properties.filter(function($){return $.memberOf == data.alias && !$.isNamespace && !$.isConstant}).sort( ckeditor_sortByType ); !}
+				<if test="ownProperties.length">
+				<table class="summaryTable" cellspacing="0" summary="A summary of the fields documented in the class {+data.alias+}.">
+					<caption>Field Summary</caption>
+					<thead>
+						<tr>
+							<th scope="col">Field Attributes</th>
+							<th scope="col">Field Name and Description</th>
+						</tr>
+					</thead>
+					<tbody>
+					<for each="member" in="ownProperties">
+						<tr>
+							<td class="attributes">{!
+								if (member.isPrivate) output += "&lt;private&gt; ";
+								if (member.isInner) output += "&lt;inner&gt; ";
+								if (member.isStatic) output += "&lt;static&gt; ";
+								if (member.isConstant) output += "&lt;constant&gt; ";
+							!}&nbsp;</td>
+							<td class="nameDescription">
+								<div class="fixedFont">
+								<if test="member.isStatic && member.memberOf != '_global_'">{+member.memberOf+}.</if><b>{+new Link().toSymbol(member.alias).withText(member.name)+}</b>
+								</div>
+								<div class="description">{+resolveLinks(summarize(member.desc))+}</div>
+							</td>
+						</tr>
+					</for>
+					</tbody>
+				</table>
+				</if>
+				
+				<if test="data.inheritsFrom.length">
+				<dl class="inheritsList">
+				{!
+					var borrowedMembers = data.properties.filter(function($) {return $.memberOf != data.alias});
+					
+					var contributers = [];
+					borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
+					for (var i = 0, l = contributers.length; i < l; i++) {
+						output +=
+							"<dt>Fields borrowed from class "+new Link().toSymbol(contributers[i])+": </dt>"
+							+
+							"<dd>" +
+							borrowedMembers
+							.filter(
+								function($) { return $.memberOf == contributers[i] }
+							)
+							.sort(makeSortby("name"))
+							.map(
+								function($) { return new Link().toSymbol($.alias).withText($.name) }
+							)
+							.join(", ")
+							+
+							"</dd>";
+					}
+				!}
+				</dl>
+				</if>
+			</if>
+
+<!-- ============================== methods summary ======================== -->
+			<if test="data.methods.length">
+				{! var ownMethods = data.methods.filter(function($){return $.memberOf == data.alias  && !$.isNamespace}).sort( ckeditor_sortByType ); !}
+				<if test="ownMethods.length">
+				<table class="summaryTable" cellspacing="0" summary="A summary of the methods documented in the class {+data.alias+}.">
+					<caption>Method Summary</caption>
+					<thead>
+						<tr>
+							<th scope="col">Method Attributes</th>
+							<th scope="col">Method Name and Description</th>
+						</tr>
+					</thead>
+					<tbody>
+					<for each="member" in="ownMethods">
+						<tr>
+							<td class="attributes">{!
+								if (member.isPrivate) output += "&lt;private&gt; ";
+								if (member.isInner) output += "&lt;inner&gt; ";
+								if (member.isStatic) output += "&lt;static&gt; ";
+							!}&nbsp;</td>
+							<td class="nameDescription">
+								<div class="fixedFont"><if test="member.isStatic && member.memberOf != '_global_'">{+member.memberOf+}.</if><b>{+new Link().toSymbol(member.alias).withText(member.name)+}</b>{+makeSignature(member.params)+}
+								</div>
+								<div class="description">{+resolveLinks(summarize(member.desc))+}</div>
+							</td>
+						</tr>
+					</for>
+					</tbody>
+				</table>
+				</if>
+				
+				<if test="data.inheritsFrom.length">
+				<dl class="inheritsList">
+				{!
+					var borrowedMembers = data.methods.filter(function($) {return $.memberOf != data.alias});
+					var contributers = [];
+					borrowedMembers.map(function($) {if (contributers.indexOf($.memberOf) < 0) contributers.push($.memberOf)});
+					for (var i = 0, l = contributers.length; i < l; i++) {
+						output +=
+							"<dt>Methods borrowed from class "+new Link().toSymbol(contributers[i])+": </dt>"
+							+
+							"<dd>" +
+							borrowedMembers
+							.filter(
+								function($) { return $.memberOf == contributers[i] }
+							)
+							.sort(makeSortby("name"))
+							.map(
+								function($) { return new Link().toSymbol($.alias).withText($.name) }
+							)
+							.join(", ")
+							+
+							"</dd>";
+					}
+				
+				!}
+				</dl>
+				</if>
+			</if>
+
+<!-- ============================== constructor details ==================== -->		
+			<if test="!data.isBuiltin() && (data.isNamespace || data.is('CONSTRUCTOR'))">
+			<div class="details"><a name="constructor"> </a>
+				<div class="sectionTitle">
+					{+classType+}Detail
+				</div>
+				
+				<div class="fixedFont" style="float:left">{!
+					if (data.isPrivate) output += "&lt;private&gt; ";
+					if (data.isInner) output += "&lt;inner&gt; ";
+				!}
+						<b>{+ data.alias +}</b><if test="classType != 'Namespace '">{+ makeSignature(data.params) +}</if>
+				</div>
+
+				<div style="float:right">
+					<span class="heading">Since:</span>
+						<if test="data.since">
+							{+ data.since +}
+						<else />
+							3.0
+						</if>
+				</div>
+				<div style="clear:both"></div>
+				
+				<div class="description">
+					{+resolveLinks(data.desc)+}
+					<if test="data.author"><br /><i>Author: </i>{+data.author+}.</if>
+				</div>
+				
+				<if test="data.example.length">
+				<for each="example" in="data.example">
+					<if test="example.desc">
+						<pre class="code">{+example+}</pre>
+					</if>
+				</for>
+				<else />
+					<pre class="code"><span style="color:red">NO EXAMPLE AVAILABLE</span></pre>
+				</if>
+				
+				
+					<if test="data.params.length">
+						<dl class="detailList">
+						<dt class="heading">Parameters:</dt>
+						<for each="item" in="data.params">
+							<dt>
+								<span class="light fixedFont">{{+ new Link().toSymbol(item.type || 'Undefined') +}}</span> <b>{+item.name+}</b>
+								<if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
+							</dt>
+								<dd>{+resolveLinks(item.desc)+}</dd>
+						</for>
+						</dl>
+					</if>
+					<if test="data.deprecated">
+						<dl class="detailList">
+						<dt class="heading">Deprecated:</dt>
+						<dt>
+							{+resolveLinks(data.deprecated)+}
+						</dt>
+						</dl>
+					</if>
+					<if test="data.exceptions.length">
+						<dl class="detailList">
+						<dt class="heading">Throws:</dt>
+						<for each="item" in="data.exceptions">
+							<dt>
+								<span class="light fixedFont">{{+ new Link().toSymbol(item.type || 'Undefined') +}}</span> <b>{+item.name+}</b>
+							</dt>
+								<dd>{+resolveLinks(item.desc)+}</dd>
+						</for>
+						</dl>
+					</if>
+					<if test="data.returns.length">
+						<dl class="detailList">
+						<dt class="heading">Returns:</dt>
+						<for each="item" in="data.returns">
+								<dd><span class="light fixedFont">{{+ new Link().toSymbol(item.type || 'Undefined') +}}</span> {+resolveLinks(item.desc)+}</dd>
+						</for>
+						</dl>
+					</if>
+					<if test="data.requires.length">
+						<dl class="detailList">
+						<dt class="heading">Requires:</dt>
+						<for each="item" in="data.requires">
+							<dd>{+ resolveLinks(item) +}</dd>
+						</for>
+						</dl>
+					</if>
+					<if test="data.see.length">
+						<dl class="detailList">
+						<dt class="heading">See:</dt>
+						<for each="item" in="data.see">
+							<dd>{+ new Link().toSymbol(item) +}</dd>
+						</for>
+						</dl>
+					</if>
+
+			</div>
+			</if>
+
+<!-- ============================== field details ========================== -->		
+			<if test="defined(ownProperties) && ownProperties.length">
+				<div class="sectionTitle">
+					Field Detail
+				</div>
+				<for each="member" in="ownProperties">
+					<a name="{+Link.symbolNameToLinkName(member)+}"> </a>
+					<div class="fixedFont" style="float:left">{!
+						if (member.isPrivate) output += "&lt;private&gt; ";
+						if (member.isInner) output += "&lt;inner&gt; ";
+						if (member.isStatic) output += "&lt;static&gt; ";
+						if (member.isConstant) output += "&lt;constant&gt; ";
+					!}
+					
+					<span class="light">{{+ new Link().toSymbol( member.type || 'Undefined') +}}</span>
+					<if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name+}</b>
+					
+					</div>
+					<div style="float:right">
+						<span class="heading">Since:</span>
+							<if test="member.since">
+								{+ member.since +}
+							<else />
+								3.0
+							</if>
+					</div>
+					<div style="clear:both"></div>
+					<div class="description">
+						{+resolveLinks(member.desc)+}
+						<if test="member.srcFile != data.srcFile">
+							<br />
+							<i>Defined in: </i> {+ ckeditor_FileLink( member.srcFile ) +}.
+						</if>
+						<if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
+					</div>
+					
+					<if test="member.example.length">
+					<for each="example" in="member.example">
+						<if test="example.desc">
+							<pre class="code">{+example+}</pre>
+						</if>
+					</for>
+					<else />
+						<pre class="code"><span style="color:red">NO EXAMPLE AVAILABLE</span></pre>
+					</if>
+
+						<if test="member.deprecated">
+							<dl class="detailList">
+							<dt class="heading">Deprecated:</dt>
+							<dt>
+								{+ member.deprecated +}
+							</dt>
+							</dl>
+						</if>
+						<if test="member.see.length">
+							<dl class="detailList">
+							<dt class="heading">See:</dt>
+							<for each="item" in="member.see">
+							<dd>{+ new Link().toSymbol(item) +}</dd>
+							</for>
+							</dl>
+						</if>
+						<if test="member.defaultValue">
+							<dl class="detailList">
+							<dt class="heading">Default Value:</dt>
+							<dd>
+								{+resolveLinks(member.defaultValue)+}
+							</dd>
+							</dl>
+						</if>
+
+					<if test="!$member_last"><hr /></if>
+				</for>
+			</if>
+
+<!-- ============================== method details ========================= -->		
+			<if test="defined(ownMethods) && ownMethods.length">
+				<div class="sectionTitle">
+					Method Detail
+				</div>
+				<for each="member" in="ownMethods">
+					<a name="{+Link.symbolNameToLinkName(member)+}"> </a>
+					<div class="fixedFont" style="float:left">{!
+						if (member.isPrivate) output += "&lt;private&gt; ";
+						if (member.isInner) output += "&lt;inner&gt; ";
+						if (member.isStatic) output += "&lt;static&gt; ";
+					!}
+					
+					<span class="light">{{+ new Link().toSymbol( member.type || 'Undefined') +}}</span>
+					<if test="member.isStatic && member.memberOf != '_global_'"><span class="light">{+member.memberOf+}.</span></if><b>{+member.name+}</b>{+makeSignature(member.params)+}
+					
+					</div>
+					<div style="float:right">
+						<span class="heading">Since:</span>
+							<if test="member.since">
+								{+ member.since +}
+							<else />
+								3.0
+							</if>
+					</div>
+					<div style="clear:both"></div>
+					<div class="description">
+						{+resolveLinks(member.desc)+}
+						<if test="member.srcFile != data.srcFile">
+							<br />
+							<i>Defined in: </i> {+ ckeditor_FileLink( member.srcFile ) +}.
+						</if>
+						<if test="member.author"><br /><i>Author: </i>{+member.author+}.</if>
+					</div>
+					
+					<if test="member.example.length">
+					<for each="example" in="member.example">
+						<if test="example.desc">
+							<pre class="code">{+example+}</pre>
+						</if>
+					</for>
+					<else />
+						<pre class="code"><span style="color:red">NO EXAMPLE AVAILABLE</span></pre>
+					</if>
+					
+						<if test="member.params.length">
+							<dl class="detailList">
+							<dt class="heading">Parameters:</dt>
+							<for each="item" in="member.params">
+								<dt>
+									<span class="light fixedFont">{{+ new Link().toSymbol(item.type || 'Undefined') +}}</span> <b>{+item.name+}</b>
+									<if test="item.isOptional"><i>Optional<if test="item.defaultValue">, Default: {+item.defaultValue+}</if></i></if>
+								</dt>
+								<dd>{+resolveLinks(item.desc)+}</dd>
+							</for>
+							</dl>
+						</if>
+						<if test="member.deprecated">
+							<dl class="detailList">
+							<dt class="heading">Deprecated:</dt>
+							<dt>
+								{+member.deprecated+}
+							</dt>
+							</dl>
+						</if>
+						<if test="member.exceptions.length">
+							<dl class="detailList">
+							<dt class="heading">Throws:</dt>
+							<for each="item" in="member.exceptions">
+								<dt>
+									<span class="light fixedFont">{{+ new Link().toSymbol(item.type || 'Undefined') +}}</span> <b>{+item.name+}</b>
+								</dt>
+								<dd>{+resolveLinks(item.desc)+}</dd>
+							</for>
+							</dl>
+						</if>
+						<if test="member.returns.length">
+							<dl class="detailList">
+							<dt class="heading">Returns:</dt>
+							<for each="item" in="member.returns">
+								<dd><span class="light fixedFont">{{+ new Link().toSymbol(item.type || 'Undefined') +}}</span> {+resolveLinks(item.desc)+}</dd>
+							</for>
+							</dl>
+						</if>
+						<if test="member.requires.length">
+							<dl class="detailList">
+							<dt class="heading">Requires:</dt>
+							<for each="item" in="member.requires">
+								<dd>{+ resolveLinks(item) +}</dd>
+							</for>
+							</dl>
+						</if>
+						<if test="member.see.length">
+							<dl class="detailList">
+							<dt class="heading">See:</dt>
+							<for each="item" in="member.see">
+								<dd>{+ new Link().toSymbol(item) +}</dd>
+							</for>
+							</dl>
+						</if>
+
+					<if test="!$member_last"><hr /></if>
+				</for>
+			</if>
+			
+			<hr />
+		</div>
+		
+<!-- ============================== footer ================================= -->
+		{+include("static/footer.html")+}
+	</body>
+</html>
Index: /CKEditor/trunk/_dev/docs_build/template/index.tmpl
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/index.tmpl	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/index.tmpl	(revision 2935)
@@ -0,0 +1,50 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+	<head>
+		<meta http-equiv="content-type" content="text/html; charset={+IO.encoding+}"" />
+		
+		<title>CKEditor 3.0 JavaScript API Documentation</title>
+		<meta name="generator" content="JsDoc Toolkit" />
+		
+		<style type="text/css">
+		{+include("static/default.css")+}
+		</style>
+	</head>
+	
+	<body>
+		{+include("static/header.html")+}
+		
+		<div id="index">
+			{+publish.classesIndex+}
+		</div>
+		
+		<div id="content">
+			<h1 class="classTitle">Namespace Index</h1>
+			
+			<for each="thisClass" in="data">
+				<if test="thisClass.isNamespace && thisClass.alias != '_global_'">
+					<div>
+						<h2>{+(new Link().toSymbol(thisClass.alias))+}</h2>
+						{+resolveLinks(summarize(thisClass.classDesc))+}
+					</div>
+					<hr />
+				</if>
+			</for>
+
+			<h1 class="classTitle">Class Index</h1>
+			
+			<for each="thisClass" in="data">
+				<if test="!thisClass.isNamespace">
+					<div>
+						<h2>{+(new Link().toSymbol(thisClass.alias))+}</h2>
+						{+resolveLinks(summarize(thisClass.classDesc))+}
+					</div>
+					<hr />
+				</if>
+			</for>
+			
+		</div>
+		{+include("static/footer.html")+}
+	</body>
+</html>
Index: /CKEditor/trunk/_dev/docs_build/template/publish.js
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/publish.js	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/publish.js	(revision 2935)
@@ -0,0 +1,214 @@
+function publish(symbolSet) {
+	publish.conf = {  // trailing slash expected for dirs
+		ext: ".html",
+		outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/",
+		templatesDir: JSDOC.opt.t.replace( /\/+$/, '' ) + '/',
+		symbolsDir: "symbols/",
+		srcDir: "symbols/src/"
+	};
+	if (!IO.exists(publish.conf.templatesDir)) {
+		publish.conf.templatesDir = SYS.userDir.replace( /\\/g, '/' ).replace( /\/+$/ ) + '/' + JSDOC.opt.t.replace( /\/+$/, '' ) + '/';
+	}
+
+	if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) {
+		Link.prototype._makeSrcLink = function(srcFilePath) {
+			return "&lt;"+srcFilePath+"&gt;";
+		}
+	}
+
+	IO.mkPath((publish.conf.outDir+"symbols/src").split("/"));
+
+	// used to check the details of things being linked to
+	Link.symbolSet = symbolSet;
+
+	try {
+		var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl");
+		var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl");
+	}
+	catch(e) {
+		print(e.message);
+		quit();
+	}
+
+	// filters
+	function hasNoParent($) {return ($.memberOf == "")}
+	function isaFile($) {return ($.is("FILE"))}
+	function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)}
+
+	var symbols = symbolSet.toArray();
+
+	var files = JSDOC.opt.srcFiles;
+ 	for (var i = 0, l = files.length; i < l; i++) {
+ 		var file = files[i];
+ 		var srcDir = publish.conf.outDir + "symbols/src/";
+		makeSrcFile(file, srcDir);
+ 	}
+
+ 	var classes = symbols.filter(isaClass).sort(makeSortby("alias"));
+
+	Link.base = "../";
+ 	publish.classesIndex = classesTemplate.process(classes); // kept in memory
+
+	for (var i = 0, l = classes.length; i < l; i++) {
+		var symbol = classes[i];
+		var output = "";
+		output = classTemplate.process(symbol);
+
+		IO.saveFile(publish.conf.outDir+"symbols/", symbol.alias+publish.conf.ext, output);
+	}
+
+	// regenrate the index with different relative links
+	Link.base = "";
+	publish.classesIndex = classesTemplate.process(classes);
+
+	try {
+		var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl");
+	}
+	catch(e) { print(e.message); quit(); }
+
+	var classesIndex = classesindexTemplate.process(classes);
+	IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex);
+	classesindexTemplate = classesIndex = classes = null;
+
+	try {
+		var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl");
+	}
+	catch(e) { print(e.message); quit(); }
+
+	var documentedFiles = symbols.filter(isaFile);
+	var allFiles = [];
+
+	for (var i = 0; i < files.length; i++) {
+		allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */")));
+	}
+
+	for (var i = 0; i < documentedFiles.length; i++) {
+		var offset = files.indexOf(documentedFiles[i].alias);
+		allFiles[offset] = documentedFiles[i];
+	}
+
+	allFiles = allFiles.sort( ckeditor_sortFiles );
+
+	var filesIndex = fileindexTemplate.process(allFiles);
+	IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex);
+	fileindexTemplate = filesIndex = files = null;
+}
+
+
+/** Just the first sentence. Should not break on dotted variable names. */
+function summarize(desc) {
+	if (typeof desc != "undefined")
+		return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc;
+}
+
+/** make a symbol sorter by some attribute */
+function makeSortby(attribute) {
+	return function(a, b) {
+		if (a[attribute] != undefined && b[attribute] != undefined) {
+			a = a[attribute].toLowerCase();
+			b = b[attribute].toLowerCase();
+			if (a < b) return -1;
+			if (a > b) return 1;
+			return 0;
+		}
+	}
+}
+
+function include(path) {
+	var path = publish.conf.templatesDir+path;
+	return IO.readFile(path);
+}
+
+function makeSrcFile(path, srcDir, name) {
+	if (JSDOC.opt.s) return;
+
+	if (!name) {
+		name = path.replace(/.*\.\.?[\\\/](.*)/g, "$1").replace(/[\\\/]/g, "_");
+		name = name.replace(/\:/g, "_");
+	}
+
+	var src = {path: path, name:name, charset: IO.encoding, hilited: ""};
+
+	if (defined(JSDOC.PluginManager)) {
+		JSDOC.PluginManager.run("onPublishSrc", src);
+	}
+
+	if (src.hilited) {
+		IO.saveFile(srcDir, name+publish.conf.ext, src.hilited);
+	}
+}
+
+function makeSignature(params) {
+	if (!params) return "()";
+	var signature = "("
+	+
+	params.filter(
+		function($) {
+			return $.name.indexOf(".") == -1; // don't show config params in signature
+		}
+	).map(
+		function($) {
+			return $.name;
+		}
+	).join(", ")
+	+
+	")";
+	return signature;
+}
+
+/** Find symbol {@link ...} strings in text and turn into html links */
+function resolveLinks(str, from) {
+	str = str.replace(/\{@link ([^} ]+) ?\}/gi,
+		function(match, symbolName) {
+			return new Link().toSymbol(symbolName);
+		}
+	);
+
+	return str;
+}
+
+function ckeditor_sortFiles( a, b )
+{
+	a = a.srcFile.replace( /.*[\\\/]/, '' );
+	b = b.srcFile.replace( /.*[\\\/]/, '' );
+	return a < b ? -1 : a > b ? 1 : 0;
+}
+
+/** Sorts a symbol by its type */
+function ckeditor_sortByType( a, b )
+{
+	var weightA =
+		a.isConstant ? 1 :
+		a.isStatic ? 2 :
+		a.isPrivate ? 3 :
+		a.isInner ? 4 : 5;
+
+	var weightB =
+		b.isConstant ? 1 :
+		b.isStatic ? 2 :
+		b.isPrivate ? 3 :
+		b.isInner ? 4 : 5;
+
+	if ( weightA == weightB )
+	{
+		weightA = a.name.toLowerCase();
+		weightB = b.name.toLowerCase();
+	}
+
+	return weightA < weightB ? -1 : weightA > weightB ? 1 : 0;
+}
+
+function ckeditor_FileLink( filePath )
+{
+	var text = filePath;
+
+	if ( /_source/.test( text ) )
+	{
+		text = text.replace( /[\/\\]+/g, '/' );
+		text = text.replace( /.*_source\/+/, '' );
+
+		return new Link().toSrc( filePath ).withText( text );
+	}
+
+	return new Link().toSrc( filePath );
+}
Index: /CKEditor/trunk/_dev/docs_build/template/static/default.css
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/static/default.css	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/static/default.css	(revision 2935)
@@ -0,0 +1,160 @@
+/* default.css */
+body
+{
+	font: 12px "Lucida Grande", Tahoma, Arial, Helvetica, sans-serif;
+}
+
+.header
+{
+	clear: both;
+	background-color: #ccc;
+	padding: 8px;
+}
+
+h1
+{
+	font-size: 150%;
+	font-weight: bold;
+	padding: 0;
+	margin: 1em 0 0 .3em;
+}
+
+hr
+{
+	border: none 0;
+	border-top: 1px solid #7F8FB1;
+	height: 1px;
+}
+
+pre.code
+{
+	display: block;
+	padding: 8px;
+	border: 1px dashed #ccc;
+}
+
+#index
+{
+	margin-top: 24px;
+	float: left;
+	width: 160px;
+	position: absolute;
+	left: 8px;
+	background-color: #F3F3F3;
+	padding: 8px;
+}
+
+#content
+{
+	margin-left: 190px;
+}
+
+.classList
+{
+	list-style-type: none;
+	padding: 0;
+	margin: 0 0 0 8px;
+	font-family: arial, sans-serif;
+	font-size: 1em;
+	overflow: auto;
+}
+
+.classList li
+{
+	padding: 0;
+	margin: 0 0 8px 0;
+}
+
+.summaryTable { width: 100%; }
+
+h1.classTitle
+{
+	font-size:170%;
+	line-height:130%;
+}
+
+h2 { font-size: 110%; }
+caption, div.sectionTitle
+{
+	background-color: #7F8FB1;
+	color: #fff;
+	font-size:130%;
+	text-align: left;
+	padding: 2px 6px 2px 6px;
+	border: 1px #7F8FB1 solid;
+}
+
+div.sectionTitle { margin-bottom: 8px; }
+.summaryTable thead { display: none; }
+
+.summaryTable td
+{
+	vertical-align: top;
+	padding: 4px;
+	border-bottom: 1px #7F8FB1 solid;
+	border-right: 1px #7F8FB1 solid;
+}
+
+/*col#summaryAttributes {}*/
+.summaryTable td.attributes
+{
+	border-left: 1px #7F8FB1 solid;
+	width: 140px;
+	text-align: right;
+}
+
+td.attributes, .fixedFont
+{
+	line-height: 15px;
+	color: #002EBE;
+	font-family: "Courier New",Courier,monospace;
+	font-size: 13px;
+}
+
+.summaryTable td.nameDescription
+{
+	text-align: left;
+	font-size: 13px;
+	line-height: 15px;
+}
+
+.summaryTable td.nameDescription, .description
+{
+	line-height: 15px;
+	padding: 4px;
+	padding-left: 4px;
+}
+
+.summaryTable { margin-bottom: 8px; }
+
+ul.inheritsList
+{
+	list-style: square;
+	margin-left: 20px;
+	padding-left: 0;
+}
+
+.detailList {
+	margin-left: 20px;
+	line-height: 15px;
+}
+.detailList dt { margin-left: 20px; }
+
+.detailList .heading
+{
+	font-weight: bold;
+	padding-bottom: 6px;
+	margin-left: 0;
+}
+
+.light, td.attributes, .light a:link, .light a:visited
+{
+	color: #777;
+	font-style: italic;
+}
+
+.fineprint
+{
+	text-align: right;
+	font-size: 10px;
+}
Index: /CKEditor/trunk/_dev/docs_build/template/static/footer.html
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/static/footer.html	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/static/footer.html	(revision 2935)
@@ -0,0 +1,3 @@
+<div class="fineprint" style="clear:both">
+	&copy; 2003 - 2008 Frederico Caldeira Knabben (<a href="http://www.fredck.com/">FredCK.com</a>). All rights reserved
+</div>
Index: /CKEditor/trunk/_dev/docs_build/template/static/header.html
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/static/header.html	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/static/header.html	(revision 2935)
@@ -0,0 +1,4 @@
+<div id="header">
+	<h1>CKEditor 3.0 JavaScript API Documentation</h1>
+	<hr />
+</div>
Index: /CKEditor/trunk/_dev/docs_build/template/static/index.html
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/static/index.html	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/static/index.html	(revision 2935)
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+	<title>Generated Javascript Documentation</title>
+</head>
+<frameset cols="20%,80%">
+	<frame src="allclasses-frame.html" name="packageFrame" />
+	<frame src="splash.html" name="classFrame" />
+	<noframes>
+		<body>
+		<p>
+		This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+		</p>
+		</body>
+	</noframes>
+</frameset>
+</html>
Index: /CKEditor/trunk/_dev/docs_build/template/symbol.tmpl
===================================================================
--- /CKEditor/trunk/_dev/docs_build/template/symbol.tmpl	(revision 2935)
+++ /CKEditor/trunk/_dev/docs_build/template/symbol.tmpl	(revision 2935)
@@ -0,0 +1,35 @@
+<symbol alias="{+data.alias+}">
+	<name>{+data.name+}</name>
+	<memberOf>{+data.memberOf+}</memberOf>
+	<isStatic>{+data.isStatic+}</isStatic>
+	<isa>{+data.isa+}</isa>
+	<desc>{+data.desc+}</desc>
+	<classDesc>{+data.classDesc+}</classDesc>
+	
+	<methods><for each="method" in="data.methods">
+		<method>
+			<name>{+method.name+}</name>
+			<memberOf>{+method.memberOf+}</memberOf>
+			<isStatic>{+method.isStatic+}</isStatic>
+			<desc>{+method.desc+}</desc>
+			<params><for each="param" in="method.params">
+				<param>
+					<type>{+param.type+}</type>
+					<name>{+param.name+}</name>
+					<desc>{+param.desc+}</desc>
+					<defaultValue>{+param.defaultValue+}</defaultValue>
+				</param></for>
+			</params>
+		</method></for>
+	</methods>
+	
+	<properties><for each="property" in="data.properties">
+		<property>
+			<name>{+property.name+}</name>
+			<memberOf>{+property.memberOf+}</memberOf>
+			<isStatic>{+property.isStatic+}</isStatic>
+			<desc>{+property.desc+}</desc>
+			<type>{+property.type+}</type>
+		</property></for>
+	</properties>
+</symbol>
Index: /CKEditor/trunk/_dev/dtd_test/dtd_test.html
===================================================================
--- /CKEditor/trunk/_dev/dtd_test/dtd_test.html	(revision 2935)
+++ /CKEditor/trunk/_dev/dtd_test/dtd_test.html	(revision 2935)
@@ -0,0 +1,65 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>CKEDITOR.dtd Contents</title>
+	<script type="text/javascript">
+	//<![CDATA[
+
+// Define the CKEDITOR namespace.
+var CKEDITOR = {};
+
+	//]]>
+	</script>
+	<script type="text/javascript" src="../../_source/core/tools.js"></script>
+	<script type="text/javascript" src="../../_source/core/dtd.js"></script>
+</head>
+<body>
+	<h1>
+		CKEDITOR.dtd Contents
+	</h1>
+	<table border="1">
+		<script type="text/javascript">
+		//<![CDATA[
+
+var entries = [];
+
+// Get all entries.
+for ( var p in CKEDITOR.dtd )
+{
+	var children = [];
+	for ( var c in CKEDITOR.dtd[p] )
+	{
+		children.push( c );
+	}
+	children.sort();
+	entries.push( [ p, children.join(', ') ] );
+}
+
+// Sort them alphabetically.
+entries.sort( function( a, b )
+	{
+		a = a[0];
+		b = b[0];
+
+		return a < b ? -1 :
+			a > b ? 1 : 0;
+	});
+
+// Writes the list.
+for ( var i = 0 ; i < entries.length ; i++ )
+{
+	document.write(
+		'<tr><td><b>' + entries[i][0] + '</b></td><td>' +
+		entries[i][1] +
+		'</td></tr>' );
+}
+
+		//]]>
+		</script>
+	</table>
+</body>
+</html>
Index: /CKEditor/trunk/_dev/fixlineends/fixlineends.bat
===================================================================
--- /CKEditor/trunk/_dev/fixlineends/fixlineends.bat	(revision 2935)
+++ /CKEditor/trunk/_dev/fixlineends/fixlineends.bat	(revision 2935)
@@ -0,0 +1,7 @@
+@ECHO OFF
+::
+:: Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+:: For licensing, see LICENSE.html or http://ckeditor.com/license
+::
+
+php fixlineends.php --excluderegex=/(?:_dev[\\\/]_thirdparty)/ --eolstripwhite --eofnewline --eofstripwhite --nohidden --nosystem ../../
Index: /CKEditor/trunk/_dev/fixlineends/fixlineends.php
===================================================================
--- /CKEditor/trunk/_dev/fixlineends/fixlineends.php	(revision 2935)
+++ /CKEditor/trunk/_dev/fixlineends/fixlineends.php	(revision 2935)
@@ -0,0 +1,607 @@
+#!/usr/bin/php -q
+<?php
+/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+
+Script for automatic line-ending corrections.
+Requires PHP5 to run: http://www.gophp5.org/ ;)
+*/
+
+error_reporting(E_ALL);
+
+/**
+ * Carriage return
+ *
+ */
+define('CR', "\r");
+/**
+ * Line feed
+ *
+ */
+define('LF', "\n");
+/**
+ * Carriage return + Line feed
+ *
+ */
+define('CRLF', "\r\n");
+
+/**
+ * Array, where:
+ *  file extension is the key
+ *  value is the new line character
+ */
+$list = array();
+$list["readme"] = CRLF;
+$list["afp"] = CRLF;
+$list["afpa"] = CRLF;
+$list["ascx"] = CRLF;
+$list["asp"] = CRLF;
+$list["aspx"] = CRLF;
+$list["bat"] = CRLF;
+$list["cfc"] = CRLF;
+$list["cfm"] = CRLF;
+$list["cgi"] = LF;
+$list["code"] = CRLF;
+$list["command"] = CRLF;
+$list["conf"] = CRLF;
+$list["css"] = CRLF;
+$list["dtd"] = CRLF;
+$list["htaccess"] = CRLF;
+$list["htc"] = CRLF;
+$list["htm"] = CRLF;
+$list["html"] = CRLF;
+$list["js"] = CRLF;
+$list["jsp"] = CRLF;
+$list["lasso"] = CRLF;
+$list["pack"] = CRLF;
+$list["php"] = CRLF;
+$list["pl"] = LF;
+$list["py"] = CRLF;
+$list["sample"] = CRLF;
+$list["sh"] = LF;
+$list["txt"] = CRLF;
+$list["xml"] = CRLF;
+
+/**
+ * Do not modify anything below
+ * use command line arguments to modify script's behaviour
+ */
+
+/**
+ * Strip whitespace from the end of file
+ * @var boolean $eofstripwhite
+ */
+$eofstripwhite = false;
+/**
+ * Strip whitespace from the end of line
+ * @var boolean $eolstripwhite
+ */
+$eolstripwhite = false;
+/**
+ * Force new line character at the end of file
+ * @var boolean $eofnewline
+ */
+$eofnewline = false;
+/**
+ * Windows only
+ * If set to true, archive files/folders are skipped
+ * @var boolean $noarchive
+ */
+$noarchive = false;
+/**
+ * Windows only
+ * If set to true, hidden files/folders are skipped
+ * @var boolean $nohidden
+ */
+$nohidden = false;
+/**
+ * Windows only
+ * If set to true, system files/folders are skipped
+ * @var boolean $nosystem
+ */
+$nosystem = false;
+/**
+ * If set to true, dot files are skipped
+ * @var boolean $nodotfiles
+ */
+$nodotfiles = false;
+/**
+ * How deep to recurse into subdirectories
+ * -1 to disable
+ *  0 to fix only current directory
+ *
+ * @var integer $maxdepth
+ */
+$maxdepth = -1;
+/**
+ * If set, regex is used to exclude files
+ * Warning: preg_match format expected
+ * example:
+ * --excluderegex = "/(\.\w+)$/"
+ *
+ * @var string $excluderegex
+ */
+$excluderegex = "";
+
+/**
+ * Set to true if script is launched in Windows
+ * @var boolean $windows
+ */
+$windows = (strtolower(substr(PHP_OS, 0, 3)) == "win");
+
+/**
+ * Count saved bytes
+ * @var integer $saved_bytes
+ */
+$saved_bytes = 0;
+
+/**
+ * Filter file list using regular expression (negative result)
+ *
+ */
+class NegRegexFilter extends FilterIterator
+{
+    protected $regex;
+    public function __construct(Iterator $it, $regex)
+    {
+        parent::__construct($it);
+        $this->regex=$regex;
+    }
+    public function accept()
+    {
+        return !preg_match($this->regex, $this->current());
+    }
+}
+
+/**
+ * Filter file list using regular expression
+ *
+ */
+class RegexFilter extends FilterIterator
+{
+    protected $regex;
+    public function __construct(Iterator $it, $regex)
+    {
+        parent::__construct($it);
+        $this->regex=$regex;
+    }
+    public function accept()
+    {
+        return preg_match($this->regex, $this->current());
+    }
+}
+
+/**
+ * Filter file list by depth
+ *
+ */
+class DepthFilter extends FilterIterator
+{
+    protected $depth;
+    public function __construct(Iterator $it, $depth)
+    {
+        parent::__construct($it);
+        $this->depth=$depth;
+    }
+    public function accept()
+    {
+        return $this->getInnerIterator()->getDepth()<$this->depth;
+    }
+}
+
+/**
+ * Fix new line characters in given file
+ * Returns true if file was changed
+ *
+ * @param string $path relative or absolute path name to file
+ * @param string $nl name of a constant that holds new line character (CRLF|CR|LF)
+ * @return bool
+ */
+function fixFile($path, $nl) {
+
+    $contents = file($path);
+    $size = filesize($path);
+    if ($contents === false) {
+        echo "\rERROR: couldn't read the " . $path . " file". "\n";
+        return false;
+    }
+
+    $modified = false;
+    $new_content = "";
+    $contents_len = sizeof($contents);
+
+    if ($GLOBALS['eofstripwhite']) {
+        $lines_processed=0;
+        //iterate through lines, from the end of file
+        for ($i=$contents_len-1; $i>=0; $i--) {
+            $old_line = $contents[$i];
+            $contents[$i] = rtrim($contents[$i]);
+            if ($old_line !== $contents[$i]) {
+                if (!$GLOBALS['eofnewline'] || $old_line !== $contents[$i] . constant($nl) || $lines_processed>0) {
+                    $modified = true;
+                }
+            }
+
+            if (empty($contents[$i])) {
+                //we have an empty line at the end of file, just skip it
+                unset($contents[$contents_len--]);
+            }
+            else {
+                if ($GLOBALS['eofnewline']) {
+                    $contents[$i] .= constant($nl);
+                    if ($old_line !== $contents[$i]) {
+                        $modified = true;
+                    }
+                }
+                //we have found non-empty line, there is no need to go further
+                break;
+            }
+            $lines_processed++;
+        }
+    }
+
+    for ($i=0; $i<$contents_len; $i++) {
+        $is_last_line = ($i == $contents_len-1);
+        $line = $contents[$i];
+
+        switch ($nl)
+        {
+            case 'CRLF':
+                if (substr($line, -2) !== CRLF) {
+                    if (substr($line, -1) === LF || substr($line, -1) === CR) {
+                        $line = substr($line, 0, -1) . CRLF;
+                        $modified = true;
+                    }
+                    elseif(strlen($line)) {
+                        if (!$is_last_line) {
+                            echo "\rERROR: wrong line ending: " . $path . "@line " . ($i+1) . "\n";
+                            return false;
+                        }
+                        elseif(!$GLOBALS['eofstripwhite']) {
+                            $line = $line . CRLF;
+                            $modified = true;
+                        }
+                    }
+                }
+                break;
+
+            case 'CR':
+                if (substr($line, -1) !== CR) {
+                    if (substr($line, -1) === LF) {
+                        $line = substr($line, 0, -1) . CR;
+                        $modified = true;
+                    }
+                    elseif(strlen($line)) {
+                        if (!$is_last_line) {
+                            echo "\rERROR: wrong line ending: " . $path . "@line " . ($i+1) . "\n";
+                            return false;
+                        }
+                        elseif(!$GLOBALS['eofstripwhite']) {
+                            $line = $line . CR;
+                            $modified = true;
+                        }
+                    }
+                }
+                break;
+
+            case 'LF':
+                if(substr($line, -2) === CRLF) {
+                    $line = substr($line, 0, -2) . LF;
+                    $modified = true;
+                }
+                elseif (substr($line, -1) !== LF) {
+                    if (substr($line, -1) === CR) {
+                        $line = substr($line, 0, -1) . LF;
+                        $modified = true;
+                    }
+                    elseif(strlen($line)) {
+                        if (!$is_last_line) {
+                            echo "\rERROR: wrong line ending: " . $path . "@line " . ($i+1) . "\n";
+                            return false;
+                        }
+                        elseif(!$GLOBALS['eofstripwhite']) {
+                            $line = $line . LF;
+                            $modified = true;
+                        }
+                    }
+                }
+                break;
+        }
+        if ($GLOBALS['eolstripwhite']) {
+            $before = strlen($line);
+            $line = preg_replace("/(?:\x09|\x20)+((?:\r|\n)+)$/", "$1", $line);
+            if (strlen($line) != $before) {
+                $modified = true;
+            }
+        }
+        $new_content .= $line;
+    }
+
+    if ($modified) {
+        $fp = fopen($path, "wb");
+        if (!$fp) {
+            echo "\rERROR: couldn't open the " . $path . " file". "\n";
+            return false;
+        }
+        else {
+            if (flock($fp, LOCK_EX)) {
+                fwrite($fp, $new_content);
+                flock($fp, LOCK_UN);
+                echo "\rMODIFIED to " . $nl . ": " . $path ;
+                if ($GLOBALS['eolstripwhite']) {
+                    $saved = $size - strlen($new_content);
+                    $GLOBALS['saved_bytes'] += $saved;
+                    if ($saved>0) {
+                        echo " (saved " . $saved . "B)";
+                    }
+                    else if ($saved<0) {
+                        echo " (" . abs($saved) . "B added)";
+                    }
+                }
+                echo "\n";
+            } else {
+                echo "\rERROR: couldn't lock the " . $path . " file". "\n";
+                return false;
+            }
+            fclose($fp);
+        }
+    }
+
+    return $modified;
+}
+
+/**
+ * Fix ending lines in all files at given path
+ *
+ * @param string $path
+ */
+function fixPath($path)
+{
+    if (is_file($path)) {
+        $ext = strtolower(substr($path, strrpos($path, ".")));
+        foreach (array('CRLF', 'LF', 'CR') as $nl) {
+            //find out what's the correct line ending and fix file
+            //no need to process further
+            if (in_array($ext, $GLOBALS['extList'][$nl])) {
+                echo "Fixing single file:\n";
+                fixFile($path, $nl);
+                break;
+            }
+        }
+
+    }
+    else {
+        $dir = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), true);
+
+        if ($GLOBALS['maxdepth'] > -1) {
+            $dir = new DepthFilter($dir, $GLOBALS['maxdepth']+1);
+        }
+
+        $dir = new NegRegexFilter($dir, "/\/(\.svn|CVS)/");
+
+        if ($GLOBALS['excluderegex']) {
+            $dir = new NegRegexFilter($dir, $GLOBALS['excluderegex']);
+        }
+
+        foreach (array('CRLF', 'LF', 'CR') as $nl) {
+
+            $filtered_dir = new RegexFilter($dir, "/\.(".implode("|", $GLOBALS['extList'][$nl]).")$/i");
+
+            $extensions = array();
+            $j = 0;
+            $progressbar = "|/-\\";
+            foreach ($filtered_dir as $file) {
+                if (!is_dir($file)) {
+                    $basename = basename($file);
+
+                    //skip dot files
+                    if ($GLOBALS['nodotfiles']) {
+                        if (strpos($basename, ".") === 0) {
+                            continue;
+                        }
+                    }
+
+                    if ($GLOBALS['windows']) {
+                        $attribs = trim(substr(shell_exec("attrib " . $file), 0, 5));
+                        //skip archive files
+                        if ($GLOBALS['noarchive'] && false !== strpos($attribs, "A")) {
+                            print "\r ".$progressbar[$j++ % 4]. " ". str_pad(basename($file), 35, " ", STR_PAD_RIGHT)." SKIPPED";
+                            continue;
+                        }
+                        //skip hidden files
+                        if ($GLOBALS['nohidden'] && false !== strpos($attribs, "H")) {
+                            print "\r ".$progressbar[$j++ % 4]. " ". str_pad(basename($file), 35, " ", STR_PAD_RIGHT)." SKIPPED";
+                            continue;
+                        }
+                        //skip system files
+                        if ($GLOBALS['nosystem'] && false !== strpos($attribs, "S")) {
+                            print "\r ".$progressbar[$j++ % 4]. " ". str_pad(basename($file), 35, " ", STR_PAD_RIGHT)." SKIPPED";
+                            continue;
+                        }
+                    }
+
+                    fixFile($file, $nl);
+                    print "\r ".$progressbar[$j++ % 4]. " ". str_pad(basename($file), 35, " ", STR_PAD_RIGHT);
+                }
+            }
+        }
+    }
+}
+
+function printHelp() {
+    $help = <<<HELP
+
+SYNOPSIS
+       php fixlineends.php [options] PATH [PATH2...]
+
+DESCRIPTION
+       Traverse recursively all the paths given and fix line endings
+       in each file.
+
+OPTIONS
+       --eofnewline
+            force new line character at the end of file
+
+       --eofstripwhite
+            strip whitespace from the end of file
+
+       --eolstripwhite
+            strip whitespace from the end of line (spaces, tabs)
+
+       --excluderegex=regex
+            use regex to exclude files, preg_match() format expected
+
+       --help
+            display this help and exit
+
+       --noarchive
+            if set to true, archive files are skipped (Windows only)
+
+       --nodotfiles
+            if set to true, dot files are skipped
+
+       --nohidden
+            if set to true, hidden files are skipped (Windows only)
+
+       --nosystem
+            if set to true, system files are skipped (Windows only)
+
+       --maxdepth
+            fix line ends only if file is N or fewer levels below
+            the command line argument; Use --max-depth=0 to omit
+            subdirectories
+
+EXAMPLES
+            php fixlineends.php --eofstripwhite --eofnewline --maxdepth=1
+                --nodotfiles --excluderegex=/\_private/ .
+
+       This command fixes line endings in current directory and in
+       subdirectories placed one level below. Dot files are skipped.
+       Paths that match "_private" are skipped. White chars are stripped
+       at the end of file. New line character is added to the end of file
+       (if required).
+
+
+HELP;
+    echo $help;
+}
+
+function translateCommandArgs($args) {
+    $paths = $args[1];
+
+    foreach ($paths as $path) {
+        if (!is_dir($path) && !is_file($path)) {
+            die("Entered path is invalid: " . $path);
+        }
+    }
+
+    foreach ($args[0] as $arg) {
+        if (!isset($arg[0])) {
+            continue;
+        }
+        switch ($arg[0]) {
+            case '--noarchive':
+                $GLOBALS['noarchive'] = true;
+                break;
+
+            case '--help':
+                printHelp();
+                die();
+                break;
+
+            case '--maxdepth':
+                $GLOBALS['maxdepth'] = intval($arg[1]);
+                break;
+
+            case '--nohidden':
+                $GLOBALS['nohidden'] = true;
+                break;
+
+            case '--nosystem':
+                $GLOBALS['nosystem'] = true;
+                break;
+
+            case '--nodotfiles':
+                $GLOBALS['nodotfiles'] = true;
+                break;
+
+            case '--excluderegex':
+                $GLOBALS['excluderegex'] = $arg[1];
+                break;
+
+            case '--eofnewline':
+                $GLOBALS['eofnewline'] = true;
+                break;
+
+            case '--eofstripwhite':
+                $GLOBALS['eofstripwhite'] = true;
+                break;
+
+            case '--eolstripwhite':
+                $GLOBALS['eolstripwhite'] = true;
+                break;
+        }
+    }
+
+    return $paths;
+}
+
+//$extList holds the associative array of extensions
+//key is the name of a constant that holds the line character
+$extList = array();
+$extList['CRLF'] = $extList['CR'] = $extList['LF'] = array();
+
+foreach ($list as $ext => $nl) {
+    $extRegex = preg_quote($ext);
+    switch ($nl) {
+        case CRLF:
+            $extList['CRLF'][] = $extRegex;
+            break;
+        case LF:
+            $extList['LF'][] = $extRegex;
+            break;
+        case CR:
+            $extList['CR'][] = $extRegex;
+            break;
+        default:
+            die("Unknown line ending");
+            break;
+    }
+}
+
+if ($_SERVER['argc']>1) {
+	include "../_thirdparty/console_getopt/Getopt.php";
+
+    if ($windows) {
+        $longoptions = array("eofstripwhite", "eofnewline", "eolstripwhite", "help", "noarchive", "nohidden", "nosystem", "nodotfiles", "maxdepth=", "excluderegex=");
+    }
+    else {
+        $longoptions = array("eofstripwhite", "eofnewline", "eolstripwhite", "help", "nodotfiles", "maxdepth=", "excluderegex=");
+    }
+
+    $con  = new Console_Getopt;
+    $args = $con->readPHPArgv();
+    $options = $con->getopt($args, null, $longoptions);
+
+    if (PEAR::isError($options)) {
+        die($options->getMessage());
+    }
+
+    $paths = translateCommandArgs($options);
+    foreach ($paths as $path) {
+        fixPath($path);
+    }
+}
+else {
+    printHelp();
+    die();
+}
+
+print "\rDone!".str_repeat(" ",40)."\n";
+if ($saved_bytes>0) {
+    echo "saved " . $saved_bytes . "B";
+}
+else if ($saved_bytes<0) {
+    echo abs($saved_bytes) . "B added";
+}
Index: /CKEditor/trunk/_dev/jslint/lint.bat
===================================================================
--- /CKEditor/trunk/_dev/jslint/lint.bat	(revision 2935)
+++ /CKEditor/trunk/_dev/jslint/lint.bat	(revision 2935)
@@ -0,0 +1,28 @@
+@ECHO OFF
+::
+:: Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+:: For licensing, see LICENSE.html or http://ckeditor.com/license
+::
+:: Calls the JavaScript Lint (jsl) with the predefined configurations.
+:: If a file name is passed as a parameter it writes there the results,
+:: otherwise it simply outputs it.
+::
+
+IF "%1"=="" GOTO NoParam
+
+ECHO Generating %1...
+bin\jsl -conf lint.conf -nofilelisting -nologo > %1
+
+ECHO.
+ECHO Process completed.
+ECHO.
+
+GOTO End
+
+:NoParam
+
+"../_thirdparty/jsl/jsl.exe" -conf lint.conf -nofilelisting -nologo
+
+ECHO.
+
+:End
Index: /CKEditor/trunk/_dev/jslint/lint.conf
===================================================================
--- /CKEditor/trunk/_dev/jslint/lint.conf	(revision 2935)
+++ /CKEditor/trunk/_dev/jslint/lint.conf	(revision 2935)
@@ -0,0 +1,146 @@
+#
+# Configuration File for JavaScript Lint 0.3.0
+# Developed by Matthias Miller (http://www.JavaScriptLint.com)
+#
+# This configuration file can be used to lint a collection of scripts, or to enable
+# or disable warnings for scripts that are linted via the command line.
+#
+
+### Warnings
+# Enable or disable warnings based on requirements.
+# Use "+WarningName" to display or "-WarningName" to suppress.
+#
++no_return_value              # function {0} does not always return a value
++duplicate_formal             # duplicate formal argument {0}
++equal_as_assign              # test for equality (==) mistyped as assignment (=)?{0}
++var_hides_arg                # variable {0} hides argument
++redeclared_var               # redeclaration of {0} {1}
++anon_no_return_value         # anonymous function does not always return a value
++missing_semicolon            # missing semicolon
++meaningless_block            # meaningless block; curly braces have no impact
+-comma_separated_stmts        # multiple statements separated by commas (use semicolons?)
++unreachable_code             # unreachable code
++missing_break                # missing break statement
+-missing_break_for_last_case  # missing break statement for last case in switch
++comparison_type_conv         # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
+-inc_dec_within_stmt          # increment (++) and decrement (--) operators used as part of greater statement
++useless_void                 # use of the void type may be unnecessary (void is always undefined)
++multiple_plus_minus          # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
++use_of_label                 # use of label
+-block_without_braces         # block statement without curly braces
++leading_decimal_point        # leading decimal point may indicate a number or an object member
++trailing_decimal_point       # trailing decimal point may indicate a number or an object member
++octal_number                 # leading zeros make an octal number
++nested_comment               # nested comment
++misplaced_regex              # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
+-ambiguous_newline            # unexpected end of line; it is ambiguous whether these lines are part of the same statement
++empty_statement              # empty statement or extra semicolon
+-missing_option_explicit      # the "option explicit" control comment is missing
++partial_option_explicit      # the "option explicit" control comment, if used, must be in the first script tag
++dup_option_explicit          # duplicate "option explicit" control comment
++useless_assign               # useless assignment
++ambiguous_nested_stmt        # block statements containing block statements should use curly braces to resolve ambiguity
++ambiguous_else_stmt          # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
+-missing_default_case         # missing default case in switch statement
++duplicate_case_in_switch     # duplicate case in switch statements
++default_not_at_end           # the default case is not at the end of the switch statement
+-legacy_cc_not_understood     # couldn't understand control comment using /*@keyword@*/ syntax
++jsl_cc_not_understood        # couldn't understand control comment using /*jsl:keyword*/ syntax
++useless_comparison           # useless comparison; comparing identical expressions
++with_statement               # with statement hides undeclared variables; use temporary variable instead
++trailing_comma_in_array      # extra comma is not recommended in array initializers
++assign_to_function_call      # assignment to a function call
++parseint_missing_radix       # parseInt missing radix parameter
+
+### Output format
+# Customize the format of the error message.
+#    __FILE__ indicates current file path
+#    __FILENAME__ indicates current file name
+#    __LINE__ indicates current line
+#    __ERROR__ indicates error message
+#
+# Visual Studio syntax (default):
++output-format __FILE__(__LINE__): __ERROR__
+# Alternative syntax:
+#+output-format __FILE__:__LINE__: __ERROR__
+
+
+### Context
+# Show the in-line position of the error.
+# Use "+context" to display or "-context" to suppress.
+#
++context
+
+
+### Semicolons
+# By default, assignments of an anonymous function to a variable or
+# property (such as a function prototype) must be followed by a semicolon.
+#
++lambda_assign_requires_semicolon
+
+
+### Control Comments
+# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
+# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
+# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
+# although legacy control comments are enabled by default for backward compatibility.
+#
++legacy_control_comments
+
+
+### JScript Function Extensions
+# JScript allows member functions to be defined like this:
+#     function MyObj() { /*constructor*/ }
+#     function MyObj.prototype.go() { /*member function*/ }
+#
+# It also allows events to be attached like this:
+#     function window::onload() { /*init page*/ }
+#
+# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
+#
+-jscript_function_extensions
+
+
+### Defining identifiers
+# By default, "option explicit" is enabled on a per-file basis.
+# To enable this for all files, use "+always_use_option_explicit"
++always_use_option_explicit
+
+# Define certain identifiers of which the lint is not aware.
+# (Use this in conjunction with the "undeclared identifier" warning.)
+#
+# Common uses for webpages might be:
++define window
++define document
++define location
++define navigator
++define setTimeout
++define clearTimeout
++define ActiveXObject
++define XMLHttpRequest
++define DOMParser
++define XMLSerializer
++define console
++define CKEDITOR
+
+### Interactive
+# Prompt for a keystroke before exiting.
+#+pauseatend
+
+
+### Files
+# Specify which files to lint
+# Use "+recurse" to enable recursion (disabled by default).
+# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
+# or "+process Folder\Path\*.htm".
+#
+#+process jsl-test.js
++recurse
+
++process ../../_source/*.js
++process ../../_source/*.html
++process ../../_samples/*.js
++process ../../_samples/*.html
++process ../../ckeditor_source.js
++process ../../ckeditor_basic_source.js
++process ../../config.js
Index: /CKEditor/trunk/_dev/jslint/lint.sh
===================================================================
--- /CKEditor/trunk/_dev/jslint/lint.sh	(revision 2935)
+++ /CKEditor/trunk/_dev/jslint/lint.sh	(revision 2935)
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+# For licensing, see LICENSE.html or http://ckeditor.com/license
+#
+# Calls the JavaScript Lint (jsl) with the predefined configurations.
+# If a file name is passed as a parameter it writes there the results,
+# otherwise it simply outputs it.
+#
+
+if [ "$1" = "" ]
+then
+	../_thirdparty/jsl/jsl -conf lint.conf -nofilelisting -nologo
+else
+	echo Generating $1 ...
+	../_thirdparty/jsl/jsl -conf lint.conf -nofilelisting -nologo > $1
+	echo
+	echo Process completed.
+fi
Index: /CKEditor/trunk/_dev/packager/package.bat
===================================================================
--- /CKEditor/trunk/_dev/packager/package.bat	(revision 2935)
+++ /CKEditor/trunk/_dev/packager/package.bat	(revision 2935)
@@ -0,0 +1,9 @@
+::
+:: Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+:: For licensing, see LICENSE.html or http://ckeditor.com/license
+::
+
+@ECHO OFF
+CLS
+
+java -jar ckpackager/js.jar -opt -1 ckpackager/ckpackager.js ../../ckeditor.pack
Index: /CKEditor/trunk/_dev/packager/packagefilegen.html
===================================================================
--- /CKEditor/trunk/_dev/packager/packagefilegen.html	(revision 2935)
+++ /CKEditor/trunk/_dev/packager/packagefilegen.html	(revision 2935)
@@ -0,0 +1,122 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Package File Generator - CKEditor</title>
+	<script type="text/javascript">
+	//<![CDATA[
+
+// Firebug has been presented some bugs with console. It must be "initialized"
+// before the page load to work.
+// FIXME: Remove the following in the future, if Firebug gets fixed.
+if ( typeof console != 'undefined' )
+	console.log();
+
+function generate()
+{
+	document.getElementById( 'basic' ).contentWindow.generate();
+	document.getElementById( 'full' ).contentWindow.generate();
+
+	var CKEDITOR = document.getElementById( 'full' ).contentWindow.CKEDITOR;
+
+	var output = document.getElementById( 'output' );
+	output.value = document.getElementById( 'header' ).value + '\r\n\r\n';
+
+	var output2 = document.getElementById( 'output_ckpackager' );
+	output2.value = document.getElementById( 'header_ckpackager' ).value + '\r\n\r\n';
+
+	output.value += '\t<Constants removeDeclaration="false">\r\n';
+	output2.value +=
+		''		+	'constants :'	+ '\r\n' +
+		'\t'	+		'{'			+ '\r\n';
+
+	var hasConst = false;
+
+	for ( var prop in CKEDITOR )
+	{
+		var typeOfProp = typeof CKEDITOR[ prop ];
+		if ( /^[A-Z\d$_]+$/.test( prop ) && typeOfProp != 'object' && typeOfProp != 'function' && typeOfProp != 'undefined' )
+		{
+			if ( hasConst )
+				output2.value += ',\r\n';
+			else
+				hasConst = true;
+			output.value += '\t\t<Constant name="CKEDITOR.' + prop + '" value="' + CKEDITOR[ prop ] + '" />\r\n';
+			output2.value += '\t\t\'CKEDITOR.' + prop + '\' : ' + CKEDITOR[ prop ];
+		}
+	}
+
+	output2.value += '\r\n';
+
+	output.value += '\t</Constants>\r\n\r\n';
+	output2.value +=
+		'\t'	+		'},'		+ '\r\n\r\n';
+
+	output.value += document.getElementById( 'basic' ).contentDocument.getElementById( 'output' ).value + '\r\n';
+	output.value += document.getElementById( 'full' ).contentDocument.getElementById( 'output' ).value + '\r\n';
+
+	output.value += '</Package>\r\n';
+
+	output2.value +=
+		''		+	'packages :'	+ '\r\n' +
+		'\t'	+		'['			+ '\r\n';
+
+	output2.value += document.getElementById( 'basic' ).contentDocument.getElementById( 'output_ckpackager' ).value + '\r\n';
+	output2.value += document.getElementById( 'full' ).contentDocument.getElementById( 'output_ckpackager' ).value + '\r\n';
+
+	output2.value +=
+		'\t'	+		']'			+ '\r\n';
+
+	// Ignore the old FCKpackager stuff now. We should clean up everything later.
+	// output.style.display = '';
+	output2.style.display = '';
+}
+
+	//]]>
+	</script>
+</head>
+<body>
+	<form action="">
+		<p>
+			<input type="button" value="Generate" onclick="generate();" />
+		</p>
+		<p>
+			<textarea id="output" cols="80" rows="15" style="width: 100%; display: none"></textarea>
+		</p>
+		<p>
+			<textarea id="output_ckpackager" cols="80" rows="15" style="width: 100%; display: none"></textarea>
+		</p>
+		<iframe id="basic" src="packagefilegen_basic.html" style="position: absolute; left: -1000px">
+		</iframe>
+		<iframe id="full" src="packagefilegen_full.html" style="position: absolute; left: -1000px">
+		</iframe>
+		<textarea id="header" cols="80" rows="10" style="display: none">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
+&lt;!--
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+--&gt;
+&lt;Package&gt;
+
+	&lt;Header&gt;&lt;![CDATA[/*
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+*/
+]]&gt;&lt;/Header&gt;</textarea>
+		<textarea id="header_ckpackager" cols="80" rows="10" style="display: none">/*
+ * CKPackager - Sample Package file
+ */
+
+header :
+	'/*'																			+ '\n' +
+	'Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.'	+ '\n' +
+	'For licensing, see LICENSE.html or http://ckeditor.com/license'				+ '\n' +
+	'*/'																			+ '\n' +
+	'\n',
+
+noCheck : false,</textarea>
+	</form>
+</body>
+</html>
Index: /CKEditor/trunk/_dev/packager/packagefilegen_basic.html
===================================================================
--- /CKEditor/trunk/_dev/packager/packagefilegen_basic.html	(revision 2935)
+++ /CKEditor/trunk/_dev/packager/packagefilegen_basic.html	(revision 2935)
@@ -0,0 +1,101 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Package File Generator - CKEditor</title>
+	<script type="text/javascript" src="../../ckeditor_basic_source.js"></script>
+	<script type="text/javascript">
+	//<![CDATA[
+
+// Firebug has been presented some bugs with console. It must be "initialized"
+// before the page load to work.
+// FIXME: Remove the following in the future, if Firebug gets fixed.
+if ( typeof console != 'undefined' )
+	console.log();
+
+var downloaded = [];
+
+CKEDITOR.on( 'download', function( event )
+	{
+		downloaded.push( event.data );
+	});
+
+function generate()
+{
+	var output = document.getElementById( 'output' );
+	var output2 = document.getElementById( 'output_ckpackager' );
+
+	output.value = '\t<PackageFile path="ckeditor_basic.js">\r\n';
+	output2.value =
+		'\t\t'		+	'{'										+ '\r\n' +
+		'\t\t\t'	+		'output : \'ckeditor_basic.js\','	+ '\r\n' +
+		'\t\t\t'	+		'wrap : true,'						+ '\r\n' +
+		'\t\t\t'	+		'files :'							+ '\r\n' +
+		'\t\t\t\t'	+			'['								+ '\r\n';
+
+	var appendedFiles = {},
+		hasFile = false;
+	var appendFile = function( filePath )
+	{
+		if ( appendedFiles[ filePath ] )
+			return;
+
+		appendedFiles[ filePath ] = true;
+
+		if ( hasFile )
+			output2.value += ',\r\n';
+		else
+			hasFile = true;
+
+		output.value += '\t\t<File path="' + filePath + '" />\r\n';
+		output2.value += '\t\t\t\t\t\'' + filePath + '\'';
+	};
+
+	appendFile( '_source/core/ckeditor_base.js' );
+
+	for ( var i = 0 ; i < CKEDITOR.loader.loadedScripts.length ; i++ )
+	{
+		var path = CKEDITOR.loader.loadedScripts[i].replace( CKEDITOR.basePath, '' );
+		appendFile( '_source/' + path + '.js' );
+	}
+
+	for ( var i = 0 ; i < downloaded.length ; i++ )
+	{
+		var path = downloaded[i].replace( CKEDITOR.basePath, '' );
+
+		if ( path == 'config.js' )
+			continue;
+
+		appendFile( path );
+	}
+
+	output2.value += '\r\n';
+
+	output.value += '\t</PackageFile>\r\n';
+	output2.value +=
+		'\t\t\t\t'	+			']'								+ '\r\n' +
+		'\t\t'		+	'},'									+ '\r\n';
+
+	// Ignore the old FCKpackager stuff now. We should clean up everything later.
+	// output.style.display = '';
+	output2.style.display = '';
+}
+
+	//]]>
+	</script>
+</head>
+<body>
+	<p>
+		<input type="button" value="Generate" onclick="generate();" />
+	</p>
+	<p>
+		<textarea id="output" rows="10" cols="80" style="width: 100%; display: none"></textarea>
+	</p>
+	<p>
+		<textarea id="output_ckpackager" rows="10" cols="80" style="width: 100%; display: none"></textarea>
+	</p>
+</body>
+</html>
Index: /CKEditor/trunk/_dev/packager/packagefilegen_full.html
===================================================================
--- /CKEditor/trunk/_dev/packager/packagefilegen_full.html	(revision 2935)
+++ /CKEditor/trunk/_dev/packager/packagefilegen_full.html	(revision 2935)
@@ -0,0 +1,128 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
+For licensing, see LICENSE.html or http://ckeditor.com/license
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Package File Generator - CKEditor</title>
+	<script type="text/javascript" src="../../ckeditor_source.js"></script>
+	<script type="text/javascript">
+	//<![CDATA[
+
+// Firebug has been presented some bugs with console. It must be "initialized"
+// before the page load to work.
+// FIXME: Remove the following in the future, if Firebug gets fixed.
+if ( typeof console != 'undefined' )
+	console.log();
+
+var downloaded = [];
+
+CKEDITOR.on( 'download', function( event )
+	{
+		downloaded.push( event.data );
+	});
+
+function generate()
+{
+	var output = document.getElementById( 'output' );
+	var output2 = document.getElementById( 'output_ckpackager' );
+
+	output.value = '\t<PackageFile path="ckeditor.js">\r\n';
+	output2.value =
+		'\t\t'		+	'{'										+ '\r\n' +
+		'\t\t\t'	+		'output : \'ckeditor.js\','			+ '\r\n' +
+		'\t\t\t'	+		'wrap : true,'						+ '\r\n' +
+		'\t\t\t'	+		'files :'							+ '\r\n' +
+		'\t\t\t\t'	+			'['								+ '\r\n';
+
+	var appendedFiles = {},
+		hasFile = false;
+	var appendFile = function( filePath, commented )
+	{
+		if ( appendedFiles[ filePath ] )
+			return;
+
+		appendedFiles[ filePath ] = true;
+
+		if ( hasFile )
+			output2.value += ',\r\n';
+		else
+			hasFile = true;
+
+		if ( commented )
+		{
+			output.value += '<!--\t';
+			output2.value += '//';
+		}
+		else
+			output.value += '\t\t';
+
+		output.value += '<File path="' + filePath + '" />';
+		output2.value += '\t\t\t\t\t\'' + filePath + '\'';
+
+		if ( commented )
+			output.value += ' -->';
+
+		output.value += '\r\n';
+	};
+
+	appendFile( '_source/core/ckeditor_base.js' );
+
+	for ( var i = 0 ; i < CKEDITOR.loader.loadedScripts.length ; i++ )
+	{
+		var path = CKEDITOR.loader.loadedScripts[i].replace( CKEDITOR.basePath, '' );
+		appendFile( '_source/' + path + '.js' );
+	}
+
+	for ( var i = 0 ; i < downloaded.length ; i++ )
+	{
+		var path = downloaded[i].replace( CKEDITOR.basePath, '' );
+
+		if ( path == 'config.js' )
+			continue;
+
+		appendFile( path, /\/lang\/(?:)/.test( path ) );
+	}
+
+	output2.value += '\r\n';
+
+	output.value += '\t</PackageFile>\r\n';
+	output2.value +=
+		'\t\t\t\t'	+			']'								+ '\r\n' +
+		'\t\t'		+	'}'									+ '\r\n';
+
+	// Ignore the old FCKpackager stuff now. We should clean up everything later.
+	// output.style.display = '';
+	output2.style.display = '';
+}
+
+	//]]>
+	</script>
+</head>
+<body>
+	<form action="">
+		<p>
+			<label for="editor1">
+				Editor 1:</label><br />
+			<textarea name="editor1" rows="10" cols="80">&lt;p&gt;This is some &lt;strong&gt;sample text&lt;/strong&gt;. You are using &lt;a href="http://www.fckeditor.net/"&gt;FCKeditor&lt;/a&gt;.&lt;/p&gt;</textarea>
+			<script type="text/javascript">
+			//<![CDATA[
+
+			  CKEDITOR.replace( 'editor1' );
+
+			//]]>
+			</script>
+		</p>
+		<p>
+			<input type="button" value="Generate" onclick="generate();" />
+		</p>
+		<p>
+			<textarea id="output" rows="10" cols="80" style="width: 100%; display: none"></textarea>
+		</p>
+		<p>
+			<textarea id="output_ckpackager" rows="10" cols="80" style="width: 100%; display: none"></textarea>
+		</p>
+	</form>
+</body>
+</html>
