Index: CHANGELOG.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/CHANGELOG.txt,v
retrieving revision 1.166
diff -u -p -r1.166 CHANGELOG.txt
--- CHANGELOG.txt	26 Sep 2009 05:37:56 -0000	1.166
+++ CHANGELOG.txt	20 Oct 2009 02:26:00 -0000
@@ -11,6 +11,7 @@ Wysiwyg 7.x-3.x, xxxx-xx-xx
 
 Wysiwyg 6.x-3.x, xxxx-xx-xx
 ---------------------------
+#462146 by TwoD, et al: Added support for CKeditor.
 #489156 by sun: Removed orphan global 'showToggle' JS setting.
 #462146 by sun, Niels Hackius: Fixed version detection for CKeditor.
 #545210 by sun: Fixed default value for editor toggle link.
Index: editors/ckeditor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/editors/ckeditor.inc,v
retrieving revision 1.2
diff -u -p -r1.2 ckeditor.inc
--- editors/ckeditor.inc	10 Aug 2009 22:54:40 -0000	1.2
+++ editors/ckeditor.inc	20 Oct 2009 02:26:00 -0000
@@ -17,11 +17,15 @@ function wysiwyg_ckeditor_editor() {
     'libraries' => array(
       '' => array(
         'title' => 'Default',
-        'files' => array('ckeditor.js'),
+        'files' => array(
+          'ckeditor.js' => array('preprocess' => FALSE),
+        ),
       ),
       'src' => array(
         'title' => 'Source',
-        'files' => array('ckeditor_source.js'),
+         'files' => array(
+          'ckeditor_source.js' => array('preprocess' => FALSE),
+        ),
       ),
     ),
     'version callback' => 'wysiwyg_ckeditor_version',
@@ -29,6 +33,13 @@ function wysiwyg_ckeditor_editor() {
     'settings callback' => 'wysiwyg_ckeditor_settings',
     'plugin callback' => 'wysiwyg_ckeditor_plugins',
     'plugin settings callback' => 'wysiwyg_ckeditor_plugin_settings',
+    'proxy plugin' => array(
+      'drupal' => array(
+        'load' => TRUE,
+        'proxy' => TRUE,
+      ),
+    ),
+    'proxy plugin settings callback' => 'wysiwyg_ckeditor_proxy_plugin_settings',
     'versions' => array(
       '3.0.3665' => array(
         'js files' => array('ckeditor-3.0.js'),
@@ -76,7 +87,17 @@ function wysiwyg_ckeditor_version($edito
  *   theme name.
  */
 function wysiwyg_ckeditor_themes($editor, $profile) {
-  return array('default');
+  // @todo Skins are not themes but this will do for now.
+  $path = $editor['library path'] . '/skins/';
+  $dir_handle = @opendir($path) or drupal_set_message('Unable to open ' . $path, $type = 'error');
+  $themes = array();  
+  while ($file = readdir($dir_handle)) {
+    if($file!="." && $file!=".." && $file!="CVS" && $file!=".svn") {
+      $themes[] = $file;
+    }
+  }
+  closedir($dir_handle);
+  return $themes;
 }
 
 /**
@@ -95,23 +116,27 @@ function wysiwyg_ckeditor_themes($editor
  */
 function wysiwyg_ckeditor_settings($editor, $config, $theme) {
   $settings = array(
-    'basePath' => base_path() . $editor['library path'] . '/',
-    'SkinPath' => base_path() . $editor['library path'] . '/editor/skins/' . $theme . '/',
-    'Width' => '100%',
-    'Height' => 420,
+    'baseHref' => base_path(),
+    'width' => '100%',
+    'height' => 420,
+    // Skin is not really the same as theme.
+    'theme' => 'default',
+    'skin' => $theme,
     // By default, CKeditor converts most characters into HTML entities. Since
     // it does not support a custom definition, but Drupal supports Unicode, we
     // disable at least the additional character sets. CKeditor always converts
     // XML default characters '&', '<', '>'.
     // @todo Check whether completely disabling ProcessHTMLEntities is an option.
-    'IncludeLatinEntities' => FALSE,
-    'IncludeGreekEntities' => FALSE,
+    'entities_latin' => FALSE,
+    'entities_greek' => FALSE,
   );
+  $extra_plugins = array();
   if (isset($config['block_formats'])) {
-    $settings['FontFormats'] = strtr($config['block_formats'], array(',' => ';'));
+    // @todo This is now format_tags and needs format_[tag] settings per tag.
+    //$settings['FontFormats'] = strtr($config['block_formats'], array(',' => ';'));
   }
   if (isset($config['apply_source_formatting'])) {
-    $settings['FormatOutput'] = $settings['FormatSource'] = $config['apply_source_formatting'];
+    $settings['apply_source_formatting'] = $config['apply_source_formatting'];
   }
 
   if (isset($config['css_setting'])) {
@@ -119,11 +144,24 @@ function wysiwyg_ckeditor_settings($edit
       // CKeditor only supports one CSS file currently.
       $settings['contentsCss'] = reset(wysiwyg_get_css());
     }
-    else if ($config['css_setting'] == 'self' && isset($config['css_path'])) {
+    elseif ($config['css_setting'] == 'self' && isset($config['css_path'])) {
       $settings['contentsCss'] = strtr($config['css_path'], array('%b' => base_path(), '%t' => path_to_theme()));
     }
   }
 
+  // Language
+  if (isset($config['language'])) {
+    $settings['language'] = $config['language'];
+  }
+  // Resizing button
+  if (isset($config['resizing'])) {
+    $settings['resize_enabled'] = $config['resizing'];
+  }
+  //Toolbar location
+  if (isset($config['toolbar_loc'])) {
+    $settings['toolbarLocation'] = $config['toolbar_loc'];
+  }
+
   if (!empty($config['buttons'])) {
     $settings['toolbar'] = array();
     $plugins = wysiwyg_get_plugins($editor['name']);
@@ -139,6 +177,22 @@ function wysiwyg_ckeditor_settings($edit
           if ($type == 'buttons') {
             $settings['toolbar'][] = $button;
           }
+          // Add external Drupal plugins to the list of extensions.
+          if ($type == 'buttons' && !empty($plugins[$plugin]['proxy'])) {
+            $extra_plugins[] = $button;
+          }
+          // Add external plugins to the list of extensions.
+          elseif ($type == 'buttons' && empty($plugins[$plugin]['internal'])) {
+            $extra_plugins[] = $plugin;
+          }
+          // Add internal buttons that also need to be loaded as extension.
+          elseif ($type == 'buttons' && !empty($plugins[$plugin]['load'])) {
+            $extra_plugins[] = $plugin;
+          }
+          // Add plain extensions.
+          elseif ($type == 'extensions' && !empty($plugins[$plugin]['load'])) {
+            $extra_plugins[] = $plugin;
+          }
           // Allow plugins to add or override global configuration settings.
           if (!empty($plugins[$plugin]['options'])) {
             $settings = array_merge($settings, $plugins[$plugin]['options']);
@@ -146,6 +200,9 @@ function wysiwyg_ckeditor_settings($edit
         }
       }
     }
+    if (!empty($extra_plugins)) {
+      $settings['extraPlugins'] = implode(',', $extra_plugins);
+    }
     // For now, all buttons are placed into one row.
     if (!empty($settings['toolbar'])) {
       $settings['toolbar'] = array($settings['toolbar']);
@@ -164,12 +221,16 @@ function wysiwyg_ckeditor_plugin_setting
     // Register all plugins that need to be loaded.
     if (!empty($plugin['load'])) {
       $settings[$name] = array();
-      // Add path for native external plugins; internal ones do not need a path.
+      // Add path for native external plugins.
       if (empty($plugin['internal']) && isset($plugin['path'])) {
         $settings[$name]['path'] = base_path() . $plugin['path'];
       }
-      if (!empty($plugin['languages'])) {
-        $settings[$name]['languages'] = $plugin['languages'];
+      // Force native internal plugins to use the standard path.
+      else {
+        $settings[$name]['path'] = base_path() . $editor['library path'] . '/plugins/' . $name . '/';
+      }
+      if (!empty($plugin['filename'])) {
+        $settings[$name]['fileName'] = $plugin['filename'];
       }
     }
   }
@@ -177,7 +238,29 @@ function wysiwyg_ckeditor_plugin_setting
 }
 
 /**
+ * Build a JS settings array for Drupal plugins loaded via the proxy plugin.
+ */
+function wysiwyg_ckeditor_proxy_plugin_settings($editor, $profile, $plugins) {
+  $settings = array();
+  foreach ($plugins as $name => $plugin) {
+    // Populate required plugin settings.
+    $settings[$name] = $plugin['dialog settings'] + array(
+      'title' => $plugin['title'],
+      'icon' => base_path() . $plugin['icon path'] . '/' . $plugin['icon file'],
+      'iconTitle' => $plugin['icon title'],
+      // @todo These should only be set if the plugin defined them.
+      'css' => base_path() . $plugin['css path'] . '/' . $plugin['css file'],
+    );
+  }
+  return $settings;
+}
+
+/**
  * Return internal plugins for this editor; semi-implementation of hook_wysiwyg_plugin().
+ *
+ * Excluded native plugins: About, Button, Checkbox, Form, HiddenField,
+ * ImageButton, NewPage, PageBreak, Print, Radio, Select, Save, TextField,
+ * Textarea, Templates.
  */
 function wysiwyg_ckeditor_plugins($editor) {
   $plugins = array(
@@ -186,7 +269,7 @@ function wysiwyg_ckeditor_plugins($edito
         'Bold' => t('Bold'), 'Italic' => t('Italic'), 'Underline' => t('Underline'),
         'StrikeThrough' => t('Strike-through'),
         'JustifyLeft' => t('Align left'), 'JustifyCenter' => t('Align center'), 'JustifyRight' => t('Align right'), 'JustifyFull' => t('Justify'),
-        'UnorderedList' => t('Bullet list'), 'OrderedList' => t('Numbered list'),
+        'BulletedList' => t('Bullet list'), 'NumberedList' => t('Numbered list'),
         'Outdent' => t('Outdent'), 'Indent' => t('Indent'),
         'Undo' => t('Undo'), 'Redo' => t('Redo'),
         'Link' => t('Link'), 'Unlink' => t('Unlink'), 'Anchor' => t('Anchor'),
@@ -194,20 +277,20 @@ function wysiwyg_ckeditor_plugins($edito
         'TextColor' => t('Forecolor'), 'BGColor' => t('Backcolor'),
         'Superscript' => t('Superscript'), 'Subscript' => t('Subscript'),
         'Blockquote' => t('Blockquote'), 'Source' => t('Source code'),
-        'Rule' => t('Horizontal rule'),
+        'HorizontalRule' => t('Horizontal rule'),
         'Cut' => t('Cut'), 'Copy' => t('Copy'), 'Paste' => t('Paste'),
         'PasteText' => t('Paste Text'), 'PasteWord' => t('Paste from Word'),
         'ShowBlocks' => t('Show blocks'),
         'RemoveFormat' => t('Remove format'),
         'SpecialChar' => t('Character map'),
         'About' => t('About'),
-        'FontFormat' => t('HTML block format'), 'FontName' => t('Font'), 'FontSize' => t('Font size'), 'Style' => t('Font style'),
+        'Format' => t('HTML block format'), 'Font' => t('Font'), 'FontSize' => t('Font size'), 'Styles' => t('Font style'),
         'Table' => t('Table'),
         'Find' => t('Search'), 'Replace' => t('Replace'), 'SelectAll' => t('Select all'),
         'CreateDiv' => t('Create DIV container'),
         'Flash' => t('Flash'), 'Smiley' => t('Smiley'),
         'FitWindow' => t('FitWindow'),
-        'SpellCheck' => t('Check spelling'),
+        'SpellChecker' => t('Check spelling'), 'Scayt' => t('Check spelling as you type'),
       ),
       'internal' => TRUE,
     ),
Index: editors/js/ckeditor-3.0.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/editors/js/ckeditor-3.0.js,v
retrieving revision 1.2
diff -u -p -r1.2 ckeditor-3.0.js
--- editors/js/ckeditor-3.0.js	26 Sep 2009 05:37:57 -0000	1.2
+++ editors/js/ckeditor-3.0.js	20 Oct 2009 02:26:00 -0000
@@ -1,6 +1,36 @@
 // $Id: ckeditor-3.0.js,v 1.2 2009/09/26 05:37:57 sun Exp $
 (function($) {
 
+Drupal.wysiwyg.editor.init.ckeditor = function(settings) {
+  CKEDITOR.on('focus', function(ev) {
+    Drupal.wysiwyg.activeId = ev.editor.name;
+  });
+  // Plugins must only be loaded once. Only the settings from the first format
+  // will be used but they're identical anyway.
+  var registeredPlugins = {};
+  for (var format in settings) {
+    if (Drupal.settings.wysiwyg.plugins[format]) {
+      // Register native external plugins.
+      // Array syntax required; 'native' is a predefined token in JavaScript.
+      for (var pluginName in Drupal.settings.wysiwyg.plugins[format]['native']) {
+        if (!registeredPlugins[pluginName]) {
+          var plugin = Drupal.settings.wysiwyg.plugins[format]['native'][pluginName];
+          CKEDITOR.plugins.addExternal(pluginName, plugin.path, plugin.fileName);
+          registeredPlugins[pluginName] = true;
+        }
+      }
+      // Register Drupal plugins.
+      for (var pluginName in Drupal.settings.wysiwyg.plugins[format].drupal) {
+        if (!registeredPlugins[pluginName]) {
+          Drupal.wysiwyg.editor.instance.ckeditor.addPlugin(pluginName, Drupal.settings.wysiwyg.plugins[format].drupal[pluginName], Drupal.settings.wysiwyg.plugins.drupal[pluginName]);
+          registeredPlugins[pluginName] = true;
+        }
+      }
+    }
+  }
+};
+
+
 /**
  * Attach this editor to a target element.
  */
@@ -8,6 +38,75 @@ Drupal.wysiwyg.editor.attach.ckeditor = 
   // Apply editor instance settings.
   CKEDITOR.config.customConfig = '';
 
+  settings.on = {
+    // Event handlers.
+    instanceReady: function(ev) {
+      var editor = ev.editor;
+      var dtd = CKEDITOR.dtd;
+      var tags = CKEDITOR.tools.extend( {}, dtd.$block, dtd.$listItem, dtd.$tableContent );
+      if (settings.apply_source_formatting) {
+        // Mimic FCKeditor output.
+        for (var tag in tags) {
+          if (tag == 'pre') {
+            continue;
+          }
+          this.dataProcessor.writer.setRules(tag, {
+            indent: true,
+            breakBeforeOpen: true,
+            breakAfterOpen: false,
+            breakBeforeClose: false,
+            breakAfterClose: true
+          });
+        }
+      }
+      else {
+        // No indents or linebreaks;
+        for (var key in tags) {
+          if (tag == 'pre') {
+            continue;
+          }
+          this.dataProcessor.writer.setRules(tag, {
+            indent: false,
+            breakBeforeOpen: false,
+            breakAfterOpen: false,
+            breakBeforeClose: false,
+            breakAfterClose: false
+          });
+        }
+      }
+    },
+
+    pluginsLoaded: function(ev) {
+      // Override the conversion methods to let Drupal plugins modify the data.
+      var editor = ev.editor;
+      if (editor.dataProcessor) {
+        editor.dataProcessor.toHtml = CKEDITOR.tools.override(editor.dataProcessor.toHtml, function(originalToHtml) {
+          // Convert raw data for display in WYSIWYG mode.
+          return function(data, fixForBody) {
+            for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+              if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
+                data = Drupal.wysiwyg.plugins[plugin].attach(data, Drupal.settings.wysiwyg.plugins.drupal[plugin], editor.name);
+                data = Drupal.wysiwyg.instances[params.field].prepareContent(data);
+              }
+            }
+            return originalToHtml.call(this, data, fixForBody);
+          };
+        });
+        editor.dataProcessor.toDataFormat = CKEDITOR.tools.override(editor.dataProcessor.toDataFormat, function(originalToDataFormat) {
+          // Convert WYSIWYG mode content to raw data.
+          return function(data, fixForBody) {
+            for (var plugin in Drupal.settings.wysiwyg.plugins[params.format].drupal) {
+              if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
+                data = Drupal.wysiwyg.plugins[plugin].detach(data, Drupal.settings.wysiwyg.plugins.drupal[plugin], editor.name);
+              }
+            }
+            return originalToDataFormat.call(this, data, fixForBody);
+          };
+        });
+  		}
+    }
+  };
+
   // Attach editor.
   CKEDITOR.replace(params.field, settings);
 };
@@ -33,4 +132,48 @@ Drupal.wysiwyg.editor.detach.ckeditor = 
   }
 };
 
+Drupal.wysiwyg.editor.instance.ckeditor = {
+  addPlugin: function(pluginName, settings, pluginSettings) {
+    CKEDITOR.plugins.add(pluginName, {
+      // Wrap Drupal plugin in a proxy pluygin.
+      init: function(editor) {
+        if (settings.css) {
+          editor.on('mode', function(ev) {
+            if (ev.editor.mode == 'wysiwyg') {
+              // Inject CSS files directly into the editing area head tag.
+              $('head', $('#cke_contents_' + ev.editor.name + ' iframe').eq(0).contents()).append('<link rel="stylesheet" href="' + settings.css + '" type="text/css" >');
+            }
+          });
+        }
+        if (typeof Drupal.wysiwyg.plugins[pluginName].invoke == 'function') {
+          var pluginCommand = {
+            exec: function(editor) {
+              var data = { format: 'html', node: editor.getSelection().getSelectedElement() };
+              // @todo This is NOT the same as data.node.
+              data.content = data.node ? data.node.innerHTML : '';
+              Drupal.wysiwyg.plugins[pluginName].invoke(data, pluginSettings, editor.name);
+            }
+          };
+          editor.addCommand(pluginName, pluginCommand);
+        }
+        editor.ui.addButton(pluginName, {
+          label: settings.iconTitle,
+          command: pluginName,
+          icon: settings.icon
+        });
+
+        // @todo Add button state handling.
+      }
+    });
+  },
+  prepareContent: function(content) {
+    // @todo Don't know if we need this yet.
+    return content;
+  },
+  insert: function(content) {
+    content = this.prepareContent(content);
+    CKEDITOR.instances[this.field].insertHtml(content);
+  }
+};
+
 })(jQuery);
