Index: editors/fckeditor.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/editors/fckeditor.inc,v
retrieving revision 1.11
diff -u -p -r1.11 fckeditor.inc
--- editors/fckeditor.inc	13 Feb 2009 02:22:19 -0000	1.11
+++ editors/fckeditor.inc	25 Feb 2009 01:15:15 -0000
@@ -27,6 +27,14 @@ function wysiwyg_fckeditor_editor() {
     'themes callback' => 'wysiwyg_fckeditor_themes',
     'settings callback' => 'wysiwyg_fckeditor_settings',
     'plugin callback' => 'wysiwyg_fckeditor_plugins',
+    'plugin settings callback' => 'wysiwyg_fckeditor_plugin_settings',
+    'proxy plugin' => array(
+      'drupal' => array(
+        'load' => TRUE,
+        'proxy' => TRUE,
+      ),
+    ),
+    'proxy plugin settings callback' => 'wysiwyg_fckeditor_proxy_plugin_settings',
     'versions' => array(
       2.6 => array(
         'js files' => array('fckeditor-2.6.js'),
@@ -157,6 +165,35 @@ function wysiwyg_fckeditor_themes($edito
 }
 
 /**
+ * Build a JS settings array of native external plugins that need to be loaded separately.
+ *
+ * @todo Required for FCKeditor?  If not, wysiwyg_add_plugin_settings() needs
+ *   an overhaul.
+ */
+function wysiwyg_fckeditor_plugin_settings($editor, $profile, $plugins) {
+  $settings = array();
+  return $settings;
+}
+
+/**
+ * Build a JS settings array for Drupal plugins loaded via the proxy plugin.
+ */
+function wysiwyg_fckeditor_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 FCKeditor; semi-implementation of hook_wysiwyg_plugin().
  */
 function wysiwyg_fckeditor_plugins($editor) {
Index: editors/js/fckeditor-2.6.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/wysiwyg/editors/js/fckeditor-2.6.js,v
retrieving revision 1.13
diff -u -p -r1.13 fckeditor-2.6.js
--- editors/js/fckeditor-2.6.js	5 Feb 2009 01:34:35 -0000	1.13
+++ editors/js/fckeditor-2.6.js	25 Feb 2009 01:12:27 -0000
@@ -11,10 +11,15 @@ Drupal.wysiwyg.editor.attach.fckeditor =
   if (settings.buttons) {
     FCKinstance.ToolbarSet = settings.ToolbarSet;
   }
+  delete settings.buttons;
+
+  // Load Drupal plugins.
+  for (var plugin in Drupal.settings.wysiwyg.plugins.fckeditor.drupal) {
+    Drupal.wysiwyg.editor.instance.fckeditor.addPlugin(plugin, Drupal.settings.wysiwyg.plugins.fckeditor.drupal[plugin], Drupal.settings.wysiwyg.plugins.drupal[plugin]);
+  }
 
   // Apply input format configuration.
   FCKinstance.Config.format = params.format;
-  delete settings.buttons;
   for (var setting in settings) {
     FCKinstance.Config[setting] = settings[setting];
   }
@@ -45,3 +50,92 @@ Drupal.wysiwyg.editor.detach.fckeditor =
   }
 };
 
+Drupal.wysiwyg.editor.instance.fckeditor = {
+  addPlugin: function(plugin, settings, pluginSettings) {
+    if (typeof Drupal.wysiwyg.plugins[plugin] != 'object') {
+      return;
+    }
+    return;
+    tinymce.create('tinymce.plugins.' + plugin, {
+      /**
+       * Initialize the plugin, executed after the plugin has been created.
+       *
+       * @param ed
+       *   The tinymce.Editor instance the plugin is initialized in.
+       * @param url
+       *   The absolute URL of the plugin location.
+       */
+      init: function(ed, url) {
+        // Register an editor command for this plugin, invoked by the plugin's button.
+        ed.addCommand(plugin, function() {
+          if (typeof Drupal.wysiwyg.plugins[plugin].invoke == 'function') {
+            var data = { format: 'html', node: ed.selection.getNode(), content: ed.selection.getContent() };
+            Drupal.wysiwyg.plugins[plugin].invoke(data, pluginSettings, ed.id);
+          }
+        });
+
+        // Register the plugin button.
+        ed.addButton(plugin, {
+          title : settings.iconTitle,
+          cmd : plugin,
+          image : settings.icon
+        });
+
+        // Load custom CSS for editor contents on startup.
+        ed.onInit.add(function() {
+          if (settings.css) {
+            ed.dom.loadCSS(settings.css);
+          }
+        });
+
+        // Attach: Replace plain text with HTML representations.
+        ed.onBeforeSetContent.add(function(ed, data) {
+          if (typeof Drupal.wysiwyg.plugins[plugin].attach == 'function') {
+            data.content = Drupal.wysiwyg.plugins[plugin].attach(data.content, pluginSettings, ed.id);
+            data.content = Drupal.wysiwyg.editor.instance.tinymce.prepareContent(data.content);
+          }
+        });
+
+        // Detach: Replace HTML representations with plain text.
+        ed.onGetContent.add(function(ed, data) {
+          if (typeof Drupal.wysiwyg.plugins[plugin].detach == 'function') {
+            data.content = Drupal.wysiwyg.plugins[plugin].detach(data.content, pluginSettings, ed.id);
+          }
+        });
+
+        // isNode: Return whether the plugin button should be enabled for the
+        // current selection.
+        ed.onNodeChange.add(function(ed, command, node) {
+          if (typeof Drupal.wysiwyg.plugins[plugin].isNode == 'function') {
+            command.setActive(plugin, Drupal.wysiwyg.plugins[plugin].isNode(node));
+          }
+        });
+      },
+
+      /**
+       * Return information about the plugin as a name/value array.
+       */
+      getInfo: function() {
+        return {
+          longname: settings.title
+        };
+      }
+    });
+
+    // Register plugin.
+    tinymce.PluginManager.add(plugin, tinymce.plugins[plugin]);
+  },
+
+  openDialog: function(dialog, params) {
+  },
+
+  closeDialog: function(dialog) {
+  },
+
+  prepareContent: function(content) {
+  },
+
+  insert: function(content) {
+  }
+};
+
