Index: sifr.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/sifr/sifr.install,v
retrieving revision 1.5
diff -u -p -r1.5 sifr.install
--- sifr.install	30 Jan 2007 21:55:05 -0000	1.5
+++ sifr.install	11 Aug 2007 01:52:47 -0000
@@ -8,6 +8,7 @@ function sifr_install(){
     case 'mysqli':
       db_query("CREATE TABLE {sifr} (
           rid int(10) NOT NULL default '0',
+          plugin VARCHAR(50) NOT NULL default '',
           name varchar(50) NOT NULL default '',
           font varchar(100) NOT NULL default '',
           selector varchar(255) NOT NULL default '',
@@ -71,3 +72,22 @@ function sifr_update_2() {
   }
   return $ret;
 }
+
+/**
+ * Add plugin name to rules table.
+ */
+function sifr_update_3() {
+  $ret = array();
+  switch ($GLOBALS['db_type']) {
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql("ALTER TABLE {sifr} ADD plugin VARCHAR(50) NOT NULL default '' AFTER rid");
+      $ret[] = update_sql("UPDATE {sifr} SET plugin = 'sifr'");
+      break;
+
+    case 'pgsql':
+      break;
+  }
+  return $ret;
+}
+
Index: sifr.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/sifr/sifr.module,v
retrieving revision 1.19
diff -u -p -r1.19 sifr.module
--- sifr.module	18 Aug 2007 14:43:44 -0000	1.19
+++ sifr.module	18 Aug 2007 14:56:53 -0000
@@ -19,7 +19,7 @@ function sifr_menu($may_cache) {
   $access = user_access('administer site configuration');
   if ($may_cache) {
     $items[] = array(
-      'title' => t('sIFR'),
+      'title' => t('Text replacement'),
       'path' => 'admin/settings/sifr',
       'description' => t('Configure which HTML text elements in your theme are rendered with Flash-based fonts.'),
       'access' => $access,
@@ -37,7 +37,8 @@ function sifr_menu($may_cache) {
       'title' => t('Add rule'),
       'path' => 'admin/settings/sifr/addrule',
       'access' => $access,
-      'callback' => 'sifr_edit_rule',
+      'callback' => 'drupal_get_form',
+      'callback arguments' => 'sifr_add_rule',
       'type' => MENU_LOCAL_TASK,
       'weight' => -1,
     );
@@ -57,7 +58,7 @@ function sifr_menu($may_cache) {
       'type' => MENU_CALLBACK,
     );
     $items[] = array(
-      'title' => t('Download sifr file'),
+      'title' => t('Download font file'),
       'path' => 'sifr/download',
       'callback' => 'sifr_octet_download',
       'access' => $access,
@@ -96,18 +97,41 @@ function sifr_menu($may_cache) {
 }
 
 /**
+ * Retrieve available plugins.
+ */
+function sifr_plugins() {
+  $dir = drupal_get_path('module', 'sifr') .'/plugins';
+  $listing = file_scan_directory($dir, '.+\.inc', array('.', '..', 'CVS', '.svn'), 0, FALSE, 'name');
+  foreach ($listing as $plugin) {
+    include_once($plugin->filename);
+    $function = $plugin->name .'_sifr_plugin';
+    if (function_exists($function)) {
+      $listing[$plugin->name] = $function();
+    }
+    else {
+      // Prevent use of malformed plugins.
+      unset($listing[$plugin->name]);
+    }
+  }
+  
+  return $listing;
+}
+
+/**
  * List the rules
  */
 function sifr_rules() {
+  $plugins = sifr_plugins();
   $rules   = sifr_get_rules();
   $mypath  = drupal_get_path('module', 'sifr');
-  $header  = array(t('Rule Name'), t('CSS Selector'), t('Font'), t('Colors'), '', '');
+  $header  = array(t('Plugin'), t('Rule Name'), t('CSS Selector'), t('Font'), t('Colors'), '', '');
   $editimg = theme('image', $mypath .'/images/editor.png');
   $delimg  = theme('image', $mypath .'/images/delete.png');
   drupal_add_css(drupal_get_path('module', 'sifr') .'/sifr.css', 'module', 'all', FALSE);
   foreach ($rules as $r) {
     $fontroot = substr($r['font'], strrpos($r['font'], '/') + 1);
     $rows[] = array(
+      $r['plugin'],
       $r['name'],
       $r['selector'],
       $fontroot,
@@ -124,18 +148,24 @@ function sifr_rules() {
   $output .= theme_table($header, $rows, array('style' => 'width:100%; clear:both;'));
   $output .= '<p>';
   $output .= l(t('Add another rule'), 'admin/settings/sifr/addrule') .'</p>';
-  $output .= l(theme('image', $mypath .'/images/sifr.png', 'sIFR', 'Link to the sIFR', array()), 'http://www.mikeindustries.com/sifr/', array(), NULL, NULL, FALSE, TRUE);
+  
+  // Display logos of supported plugins.
+  $output .= '<h4>'. t('Supported plugins') .'</h4>';
+  $plugins = sifr_plugins();
+  foreach ($plugins as $plugin) {
+    $output .= l(theme('image', $mypath .'/plugins/'. $plugin['name'] .'.png', $plugin['title'], 'Visit homepage of '. $plugin['title'], array()), $plugin['url'], array(), NULL, NULL, FALSE, TRUE);
+  }
   
   return $output;
 }
 
 /**
- * Manage the .swf files
+ * Manage font files.
  */
 function sifr_manage() {
   $sifr = str_replace(' ', "%20", sifr_find_sifr());
   
-  drupal_set_title(t('Manage sIFR fonts'));
+  drupal_set_title(t('Manage text replacement fonts'));
   
   $delimg  = theme('image', drupal_get_path('module', 'sifr') .'/images/delete.png');
   $filedir = file_directory_path() .'/sifr';
@@ -158,42 +188,30 @@ function sifr_manage() {
 function sifr_upload() {
   $form['#attributes'] = array('enctype' => 'multipart/form-data');
   
-  $instructions = t('
-  <h3>Good places to find sIFR fonts:</h3>
-  <ul>
-    <li><a href="http://sifrfonts.com/">SIFRfonts.com</a></li>
-    <li><a href="http://www.fontsmack.com/">Font Smack</a></li>
-    <li><a href="http://www.isarie.com/?p=17">Stefan Isarie</a></li>
-  </ul>
-  <p>Just download \'em from there and upload \'em here.</p>
-  
-  <h3>To create your own sIFR font files:</h3>
-    <ol>
-      <li>Download these files to the same directory: !files</li>
-      <li>Open sifr.fla in Macromedia Flash.</li>
-      <li>Double-click the invisible textbox in the middle of the stage. If the &quot;Properties&quot; palette is not already visible, open it by selecting &quot;Window > Properties&quot;, and select which font you\'d like to use from the drop down menu. If you select a TrueType font, you can also create bold and italic styles for your font by clicking on the &quot;I&quot; or &quot;B&quot; buttons. The standard sifr.fla file contains most of the English characters you will generally need. If you need to embed additional characters or languages, click the &quot;Character&quot; button and select more characters from there.</li>
-      <li>To export the new file, choose &quot;File > Export&quot; and save as fontname.swf</li>
-      <li>Upload the your font file below.</li>
-    </ol>',
-    array(
-      '!files' => l('sifr.fla', 'sifr/download/sifr.fla') .', '. l('customize_me.as', 'sifr/download/customize_me.as') .', '. l('dont_customize_me.as', 'sifr/download/dont_customize_me.as')
-      )
-  );
+  // Display instructions for each plugin.
   $form['instructions'] = array(
-    '#type' => 'fieldset',
-    '#collapsible' => TRUE,
-    '#collapsed' => TRUE,
-    '#title' => t('Instructions'),
-    '#attributes' => array('style' => 'margin-top: 15px'),
-  );
-  $form['instructions']['instructions'] = array(
-    '#type' => 'markup',
-    '#value' => $instructions,
+    '#value' => '<p />',
   );
+  $plugins = sifr_plugins();
+  foreach ($plugins as $plugin) {
+    $function = $plugin['name'] .'_sifr_plugin_instructions';
+    if (function_exists($function)) {
+      $form['instructions'][$plugin['name']] = array(
+        '#type' => 'fieldset',
+        '#collapsible' => TRUE,
+        '#collapsed' => TRUE,
+        '#title' => t('@plugin instructions', array('@plugin' => $plugin['title'])),
+      );
+      $form['instructions'][$plugin['name']]['instructions'] = array(
+        '#type' => 'markup',
+        '#value' => $function(),
+      );
+    }
+  }
   $form['sifrfile'] = array(
     '#type' => 'file',
-    '#title' => t('Upload sIFR font file'),
-    '#description' => t('Select the .swf file that you created using the instructions above.'),
+    '#title' => t('Upload font file'),
+    '#description' => t('Select the font file that you created using the instructions above.'),
     '#size' => 40,
   );
   $form[] = array(
@@ -225,7 +243,47 @@ function sifr_upload_submit($form_id, $f
 }
 
 /**
- * Edit or create a new rule
+ * Create a new text replacement rule.
+ * 
+ * Since multiple text replacement plugins can support the same font file types
+ * we need to ask for the plugin to use before a rule can be created.
+ */
+function sifr_add_rule() {
+  $form = array();
+  
+  $form['plugin_select'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Text replacement plugin'),
+  );
+  $form['plugin'] = array(
+    '#type' => 'value',
+    '#required' => TRUE,
+  );
+  foreach (sifr_plugins() as $plugin) {
+    $form['plugin_select'][$plugin['name']] = array(
+      '#type' => 'radio',
+      '#title' => $plugin['title'],
+      '#name' => 'plugin',
+      '#return_value' => $plugin['name'],
+    );
+  }
+  
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Next'),
+  );
+  
+  return $form;
+}
+
+function sifr_add_rule_submit($form_id, $values) {
+  if (isset($values['plugin'])) {
+    drupal_goto('admin/settings/sifr/edit/'. check_plain($values['plugin']));
+  }
+}
+
+/**
+ * Edit a text replacement rule.
  *
  * @param $edit
  * an array or object of rule parameters
@@ -242,6 +300,9 @@ function sifr_edit_rule($edit = NULL) {
       $rule = sifr_load_rule($edit);
     }
   }
+  else if (is_string($edit)) {
+    $rule['plugin'] = check_plain($edit);
+  }
   $font_select = $rule       = (array)$rule;
   $rules                     = array();
   
@@ -250,13 +311,13 @@ function sifr_edit_rule($edit = NULL) {
   $font_select['linkcolor']  = '#000000';
   $font_select['hovercolor'] = '#000000';
   $font_select['bgcolor']    = '#FFFFFF';
-  $fonts                     = sifr_get_fonts();
+  $fonts                     = sifr_get_fonts($rule['plugin']);
   foreach ($fonts as $path => $name) {
     $font_select['selector'] = "#font-". str_replace(array(' ', '_'), '-', $name);
     $font_select['font']     = $path;
     $rules[]                 = sifr_render_rule_js($font_select);
   }
-  drupal_add_js(sifr_wrap_rules($rules), 'inline');
+  drupal_add_js(sifr_wrap_rules($rule['plugin'], $rules, TRUE), 'inline');
   
   drupal_add_css(drupal_get_path('module', 'sifr') .'/sifr.css', 'module', 'all', FALSE);
   
@@ -266,11 +327,17 @@ function sifr_edit_rule($edit = NULL) {
 function sifr_rule($edit) {
   if ($edit['rid']) {
     $form['rid'] = array('#type' => 'hidden', '#value' => $edit['rid']);
-    drupal_set_title(t('Edit sIFR rule %s', array('%s' => $edit['name'])));
+    drupal_set_title(t('Edit replacement rule %s', array('%s' => $edit['name'])));
   }
   else {
-    drupal_set_title(t('Add a new sIFR rule'));
+    drupal_set_title(t('Add a new text replacement rule'));
   }
+  $form['plugin'] = array(
+    '#type' => 'value',
+    '#value' => $edit['plugin'],
+    '#required' => TRUE,
+  );
+
   $form['basics'] = array(
     '#type' => 'fieldset',
     '#title' => t('Basics'),
@@ -319,7 +386,7 @@ function sifr_rule($edit) {
     '#required' => TRUE,
   );
   
-  $fonts = sifr_get_fonts();
+  $fonts = sifr_get_fonts($edit['plugin']);
   foreach ($fonts as $path => $name) {
     $form['basics']['font']['font'][]['font'] = array(
       '#type' => 'radio',
@@ -493,8 +560,8 @@ function sifr_delete_rule_form_submit($f
     $rule = sifr_load_rule($form_values['rid']);
     db_query('DELETE FROM {sifr} WHERE rid = %d', $form_values['rid']);
     drupal_set_message(t('Rule %name has been deleted.', array('%name' => $rule['name'])));
-    variable_del('sifr_rules');
-    sifr_css_screen(FALSE);
+    sifr_render_rules_js($rule['plugin']);
+    sifr_css_screen($rule['plugin'], FALSE);
   }
 }
 
@@ -533,19 +600,33 @@ function sifr_fontdelete_confirm_form_su
  *
  * @return array
  *   Keyed array for select field
+ * @todo Search in current theme for font files (preferred upload location).
  */
-function sifr_get_fonts() {
+function sifr_get_fonts($plugin = NULL) {
   $selects = array();
   
+  // Build file mask.
+  $mask = array();
+  $plugins = sifr_plugins();
+  if (isset($plugin) && isset($plugins[$plugin])) {
+    $mask = $plugins[$plugin]['file_masks'];
+  }
+  else {
+    foreach ($plugins as $plugin) {
+      $mask = array_merge($mask, $plugin['file_masks']);
+    }
+  }
+  $mask = implode('|', $mask);
+  
   // scan files/sifr
   $dir = file_create_path('sifr');
-  $listings = file_scan_directory($dir, '.*\.(swf)', array('.', '..', 'CVS', '.svn'), 0, FALSE);
+  $listings = file_scan_directory($dir, $mask, array('.', '..', 'CVS', '.svn'), 0, FALSE);
   foreach ((array)$listings as $listing) {
     $selects[$listing->filename] = $listing->name;
   }
   // scan modules/sifr/sifr
   $dir = sifr_find_sifr();
-  $listings = file_scan_directory($dir, '.*\.(swf)', array('.', '..', 'CVS', '.svn'), 0, FALSE);
+  $listings = file_scan_directory($dir, $mask, array('.', '..', 'CVS', '.svn'), 0, FALSE);
   foreach ((array)$listings as $listing) {
     $selects[$listing->filename] = $listing->name;
   }
@@ -555,12 +636,20 @@ function sifr_get_fonts() {
 /**
  * Fetch rules from database.
  *
+ * @param string $plugin
+ *   An optional plugin name to limit the query.
+ *
  * @return
  *   An array of rules.
  */
-function sifr_get_rules() {
+function sifr_get_rules($plugin = NULL) {
   $rules = array();
-  $result = db_query('SELECT * FROM {sifr} ORDER BY weight');
+  if (isset($plugin)) {
+    $result = db_query("SELECT * FROM {sifr} WHERE plugin = '%s' ORDER BY weight", check_plain($plugin));
+  }
+  else {
+    $result = db_query('SELECT * FROM {sifr} ORDER BY weight');
+  }
   while ($r = db_fetch_array($result)) {
     $rules[$r['rid']] = $r;
   }
@@ -616,13 +705,9 @@ function sifr_save_rule($edit) {
   db_query("INSERT INTO {sifr} ($keys) VALUES ($valsubs) ", $vals);
   drupal_set_message(t('%rule saved.', array('%rule' => $edit['name'])));
   // Create the CSS file.
-  sifr_css_screen(FALSE);
-  variable_del('sifr_rules');
-}
-
-function sifr_rule_delete($rid) {
-  db_query('DELETE FROM {sifr} WHERE rid = %d', $rid);
-  drupal_set_message(t('Rule deleted.'));
+  sifr_css_screen($edit['plugin'], FALSE);
+  // Create the JS file.
+  sifr_render_rules_js($edit['plugin']);
   variable_del('sifr_rules');
 }
 
@@ -656,107 +741,105 @@ function sifr_find_sifr() {
   return $file->dir ? $file->dir : FALSE;
 }
 
+/**
+ * Add JavaScripts and Stylesheets for all active plugins to all pages.
+ */
 function sifr_all_pages() {
   static $done;
   if ($done) {
     return;
   }
-  $sifrdir = variable_get('sifr_dir', FALSE);
-  // no variable set? scan the dir
-  if (!$sifrdir) {
-    $sifrdir = urlencode(sifr_find_sifr());
-  }
-  // still can't find it? display an error
-  if (!$sifrdir) {
-    drupal_set_message(t('The sIFR library is in not installed correctly. Please download from <a href="http://www.mikeindustries.com/sifr/">http://www.mikeindustries.com/sifr/</a> and place in Drupal\'s modules/sifr/ directory.'), 'error');
-  }
-  else {
-    $path = $sifrdir .'/';
-    drupal_add_css(file_directory_path() .'/sifr/sifr-screen.css', 'module', 'screen');
-    drupal_add_css($path .'sIFR-print.css', 'module', 'print');
-    drupal_add_js($path .'sifr.js');
-    drupal_add_js(sifr_render_rules_js(), 'inline');
+  $plugins = sifr_plugins();
+  $active_plugins = variable_get('sifr_plugins', array());
+  $dir = file_directory_path() .'/sifr/';
+  foreach ($plugins as $plugin) {
+    if (in_array($plugin['name'], $active_plugins)) {
+      $function = $plugin['name'] .'_sifr_load';
+      if (function_exists($function)) {
+        $function();
+      }
+      drupal_add_css($dir . $plugin['name'] .'-screen.css', 'module', 'screen');
+      drupal_add_js($dir . $plugin['name'] .'-rules.js');
+    }
   }
   $done = true;
 }
 
-function sifr_render_rules_js() {
-  $rules = variable_get('sifr_rules', null);
-  if (isset($rules)) {
-    return $rules;
+/**
+ * Save text replacement JavaScript files for each plugin.
+ */
+function sifr_render_rules_js($edited_plugin = NULL) {
+  $dir = file_create_path('sifr');
+  if (!file_check_directory($dir, 1)) {
+    drupal_set_message(t('Cannot create directory %sifr.', array('%sifr' => $dir)), 'error');
+    return;
   }
   
   $rules = array();
   
-  foreach (sifr_get_rules() as $rule) {
-    $rules[] = sifr_render_rule_js($rule);
+  // Render JavaScript rules for each plugin.
+  foreach (sifr_get_rules($edited_plugin) as $rule) {
+    $rules[$rule['plugin']][] = sifr_render_rule_js($rule);
   }
   
-  $output = sifr_wrap_rules($rules);
-  variable_set('sifr_rules', $output);
-  return $output;
+  // Wrap rules with execution handler and save to files.
+  foreach ($rules as $plugin => $plugin_rules) {
+    $plugin_js = sifr_wrap_rules($plugin, $plugin_rules);
+    $filename = check_plain($plugin) .'-rules.js';
+    if ($file = file_save_data($plugin_js, $dir .'/'. $filename, FILE_EXISTS_REPLACE)) {
+      drupal_set_message(t('JavaScript file !file saved.', array('!file' => l($filename, $dir .'/'. $filename))));
+    }
+    else {
+      drupal_set_message(t('JavaScript file !file could not be saved.', array('!file' => $dir .'/'. $filename)), 'error');
+    }
+  }
+
+  // Store active plugins in a variable.
+  $active_plugins = array();
+  foreach (sifr_get_rules() as $rule) {
+    $active_plugins[] = $rule['plugin'];
+  }
+  variable_set('sifr_plugins', $active_plugins);
 }
 
+/**
+ * Return a single JavaScript text replacement rule.
+ */
 function sifr_render_rule_js($rule) {
-  $properties = array();
-  // convert spaces in filename
-  $fontpath = base_path() . str_replace('%2F', '/', rawurlencode($rule['font']));
-  $properties['sFlashSrc']      = $fontpath;
-  $properties['sColor']         = $rule['color'];
-  $properties['sLinkColor']     = $rule['linkcolor'];
-  $properties['sHoverColor']    = $rule['hovercolor'];
-  $properties['sBgColor']       = $rule['bgcolor'];
-  $properties['nPaddingTop']    = is_numeric($rule['paddingtop']) ? $rule['paddingtop'] : null;
-  $properties['nPaddingRight']  = is_numeric($rule['paddingright']) ? $rule['paddingright'] : null;
-  $properties['nPaddingBottom'] = is_numeric($rule['paddingbottom']) ? $rule['paddingbottom'] : null;
-  $properties['nPaddingLeft']   = is_numeric($rule['paddingleft']) ? $rule['paddingleft'] : null;
-  switch ($rule['transparent']) {
-    case '1':
-      $properties['sWmode'] = 'transparent';
-      break;
-    
-    case '2':
-      $properties['sWmode'] = 'opaque';
-      break;
-  }
-  $properties['sCase'] = in_array($rule['lettercase'], array('upper', 'lower')) ? $rule['lettercase'] : '';
-  $vars = array();
-  if ($rule['underline']) {
-    $vars[] = 'underline=true';
-  }
-  if (in_array($rule['textalign'], array('left', 'center', 'right'))) {
-    $vars[] = 'textalign='. $rule['textalign'];
-  }
-  $properties['sFlashVars'] = implode($vars, '&');
-  
-  $output = 'sIFR.replaceElement("'. $rule['selector'] .'", named({';
-  foreach ($properties as $property => $value) {
-    if (!empty($value)) {
-      $output .= $property .': "'. $value .'", ';
-    }
+  $plugins = sifr_plugins();
+  $function = $rule['plugin'] .'_sifr_render_rule_js';
+  if (function_exists($function)) {
+    return $function($rule);
+  }
+  else {
+    $message = t("Error: @plugin does not provide a method to build JavaScript text replacement invocations.", array('@plugin' => $rule['plugin']));
+    drupal_set_message($message, 'error');
+    return '  /* '. $message ." */\n";
   }
-  $output = substr($output, 0, -2);
-  $output .= '}));';
-  
-  return $output;
 }
 
-function sifr_wrap_rules($rules) {
+/**
+ * Wrap execution handler around JavaScript rules.
+ */
+function sifr_wrap_rules($plugin, $rules, $inline = FALSE) {
   $output = '';
-  if (is_array($rules) && count($rules)) {
+  if (is_array($rules) && $inline) {
     $output .= "\n//<![CDATA['\n";
-    $output .= "if(typeof sIFR == \"function\") {\n";
-    foreach ($rules as $rule) {
-      $output .= '  '. $rule ."\n";
+  }
+  if (is_array($rules)) {
+    $plugins = sifr_plugins();
+    $function = $plugin .'_sifr_wrap_rules';
+    if (function_exists($function)) {
+      $output .= $function($rules);
     }
-    $output .= "};\n";
+  }
+  if (is_array($rules) && $inline) {
     $output .= "//]]>\n";
   }
-  
   return $output;
 }
 
-function sifr_css_screen($print = TRUE) {
+function sifr_css_screen($plugin, $print = TRUE) {
   if ($print) {
     header("Content-type: text/css");
     header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
@@ -765,57 +848,31 @@ function sifr_css_screen($print = TRUE) 
     header("Cache-Control: post-check=0, pre-check=0", FALSE);
     header("Pragma: no-cache");
   }
-  $output = "/* These are standard sIFR styles... do not modify */
-
-.sIFR-flash {
-  visibility: visible !important;
-  margin: 0;
-}
-
-.sIFR-replaced {
-  visibility: visible !important;
-}
-
-span.sIFR-alternate {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 0;
-  height: 0;
-  display: block;
-  overflow: hidden;
-}
-
-/* Hide Adblock Object tab: the text should show up just fine, not poorly with a tab laid over it. */
-.sIFR-flash + div[adblocktab=true] {
-  display: none !important;
-}
-
-/* These \"decoy\" styles are used to hide the browser text before it is replaced... the negative-letter spacing in this case is used to make the browser text metrics match up with the sIFR text metrics since the sIFR text in this example is so much narrower... your own settings may vary... any weird sizing issues you may run into are usually fixed by tweaking these decoy styles */
-
-";
   
-  foreach (sifr_get_rules() as $rule) {
-    $fontsize       = trim($rule['fontsize']) ? "  font-size: $rule[fontsize];\n" : '';
-    $letterspacing  = trim($rule['letterspacing']) ? "  letter-spacing: $rule[letterspacing];\n" : '';
-    $rule['selector'] = str_replace(',', ', .sIFR-hasFlash ', $rule['selector']);
-    $output .= "
-.sIFR-hasFlash $rule[selector] {
-  visibility: hidden;
-$fontsize$letterspacing}
-";
+  $plugin   = check_plain($plugin);
+  $plugins  = sifr_plugins();
+  $function = $plugin .'_sifr_css_screen';
+  if (function_exists($function)) {
+    $output = $function(sifr_get_rules($plugin));
+  }
+  else {
+    $message = t("Error: @plugin does not provide a method to build a CSS file.", array('@plugin' => $plugin));
+    drupal_set_message($message, 'error');
+    return '  /* '. $message ." */\n";
   }
+  
   $dir = file_create_path('sifr');
   if (file_check_directory($dir, 1)) {
-    if ($file = file_save_data($output, $dir .'/sifr-screen.css', FILE_EXISTS_REPLACE)) {
-      drupal_set_message(t('CSS file saved.'));
+    $filename = $plugin .'-screen.css';
+    if ($file = file_save_data($output, $dir .'/'. $filename, FILE_EXISTS_REPLACE)) {
+      drupal_set_message(t('CSS file !file saved.', array('!file' => l($filename, $dir .'/'. $filename))));
     }
     else {
-      drupal_set_message(t('CSS file could not be saved.'), 'error');
+      drupal_set_message(t('CSS file !file could not be saved.', array('!file' => $dir .'/'. $filename)), 'error');
     }
   }
   else {
-    drupal_set_message(t('Cannot create sifr directory in files.'), 'error');
+    drupal_set_message(t('Cannot create directory %sifr.', array('%sifr' => $dir)), 'error');
   }
   if ($print) {
     print $output;
@@ -845,6 +902,6 @@ function sifr_octet_download($file) {
 }
 
 function _sifr_fields() {
-  return array('rid', 'name', 'font', 'selector', 'color', 'linkcolor', 'hovercolor', 'bgcolor', 'transparent', 'weight', 'letterspacing', 'fontsize', 'paddingtop', 'paddingright', 'paddingbottom', 'paddingleft', 'textalign', 'underline', 'lettercase');
+  return array('rid', 'plugin', 'name', 'font', 'selector', 'color', 'linkcolor', 'hovercolor', 'bgcolor', 'transparent', 'weight', 'letterspacing', 'fontsize', 'paddingtop', 'paddingright', 'paddingbottom', 'paddingleft', 'textalign', 'underline', 'lettercase');
 }
 
Index: plugins/sifr.inc
===================================================================
RCS file: plugins/sifr.inc
diff -N plugins/sifr.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ plugins/sifr.inc	17 Aug 2007 19:21:36 -0000
@@ -0,0 +1,189 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Text replacement API sIFR plugin.
+ */
+
+/**
+ * Return plugin information.
+ */
+function sifr_sifr_plugin() {
+  return array(
+    'name' => 'sifr',
+    'title' => 'sIFR',
+    'url' => 'http://www.mikeindustries.com/sifr/',
+    'dependencies' => array('sifr.js', 'sIFR-print.css'),
+    'file_masks' => array('.+\.swf'),
+  );
+}
+
+/**
+ * Return plugin instructions.
+ */
+function sifr_sifr_plugin_instructions() {
+  return t('
+  <h3>Good places to find sIFR fonts:</h3>
+  <ul>
+    <li><a href="http://sifrfonts.com/">SIFRfonts.com</a></li>
+    <li><a href="http://www.fontsmack.com/">Font Smack</a></li>
+    <li><a href="http://www.isarie.com/?p=17">Stefan Isarie</a></li>
+  </ul>
+  <p>Just download \'em from there and upload \'em here.</p>
+  
+  <h3>To create your own sIFR font files:</h3>
+    <ol>
+      <li>Download these files to the same directory: !files</li>
+      <li>Open sifr.fla in Macromedia Flash.</li>
+      <li>Double-click the invisible textbox in the middle of the stage. If the &quot;Properties&quot; palette is not already visible, open it by selecting &quot;Window > Properties&quot;, and select which font you\'d like to use from the drop down menu. If you select a TrueType font, you can also create bold and italic styles for your font by clicking on the &quot;I&quot; or &quot;B&quot; buttons. The standard sifr.fla file contains most of the English characters you will generally need. If you need to embed additional characters or languages, click the &quot;Character&quot; button and select more characters from there.</li>
+      <li>To export the new file, choose &quot;File > Export&quot; and save as fontname.swf</li>
+      <li>Upload the your font file below.</li>
+    </ol>',
+    array(
+      '!files' => l('sifr.fla', 'sifr/download/sifr.fla') .', '. l('customize_me.as', 'sifr/download/customize_me.as') .', '. l('dont_customize_me.as', 'sifr/download/dont_customize_me.as')
+      )
+  );
+}
+
+/**
+ * Perform plugin installation checks.
+ */
+function sifr_sifr_setup() {
+  // Check cache folder.
+  $dir = file_create_path('sifr');
+  if (!file_check_directory($dir, 1)) {
+    drupal_set_message(t('The sIFR working directory !dir is not writable.', array('!dir' => $dir)), 'error');
+  }
+}
+
+/**
+ * Render a single Javascript text replacement rule.
+ */
+function sifr_sifr_render_rule_js($rule) {
+  $properties = array();
+  // convert spaces in filename
+  $fontpath = base_path() . str_replace('%2F', '/', rawurlencode($rule['font']));
+  $properties['sFlashSrc']      = $fontpath;
+  $properties['sColor']         = $rule['color'];
+  $properties['sLinkColor']     = $rule['linkcolor'];
+  $properties['sHoverColor']    = $rule['hovercolor'];
+  $properties['sBgColor']       = $rule['bgcolor'];
+  $properties['nPaddingTop']    = is_numeric($rule['paddingtop']) ? $rule['paddingtop'] : null;
+  $properties['nPaddingRight']  = is_numeric($rule['paddingright']) ? $rule['paddingright'] : null;
+  $properties['nPaddingBottom'] = is_numeric($rule['paddingbottom']) ? $rule['paddingbottom'] : null;
+  $properties['nPaddingLeft']   = is_numeric($rule['paddingleft']) ? $rule['paddingleft'] : null;
+  switch ($rule['transparent']) {
+    case '1':
+      $properties['sWmode'] = 'transparent';
+      break;
+    
+    case '2':
+      $properties['sWmode'] = 'opaque';
+      break;
+  }
+  $properties['sCase'] = in_array($rule['lettercase'], array('upper', 'lower')) ? $rule['lettercase'] : '';
+  $vars = array();
+  if ($rule['underline']) {
+    $vars[] = 'underline=true';
+  }
+  if (in_array($rule['textalign'], array('left', 'center', 'right'))) {
+    $vars[] = 'textalign='. $rule['textalign'];
+  }
+  $properties['sFlashVars'] = implode($vars, '&');
+  
+  $output = 'sIFR.replaceElement("'. $rule['selector'] .'", named({';
+  foreach ($properties as $property => $value) {
+    if (!empty($value)) {
+      $output .= $property .': "'. $value .'", ';
+    }
+  }
+  $output = substr($output, 0, -2);
+  $output .= '}));';
+  
+  return $output;
+}
+
+/**
+ * Wrap execution handler around JavaScript rules.
+ */
+function sifr_sifr_wrap_rules($rules) {
+  $output = '';
+  if (is_array($rules)) {
+    $output .= "if(typeof sIFR == \"function\") {\n";
+    foreach ($rules as $rule) {
+      $output .= '  '. $rule ."\n";
+    }
+    $output .= "};\n";
+  }
+  
+  return $output;
+}
+
+/**
+ * Render a CSS file for this plugin.
+ */
+function sifr_sifr_css_screen($rules) {
+  $output = "/* These are standard sIFR styles... do not modify */
+
+.sIFR-flash {
+  visibility: visible !important;
+  margin: 0;
+}
+
+.sIFR-replaced {
+  visibility: visible !important;
+}
+
+span.sIFR-alternate {
+  position: absolute;
+  left: 0;
+  top: 0;
+  width: 0;
+  height: 0;
+  display: block;
+  overflow: hidden;
+}
+
+/* Hide Adblock Object tab: the text should show up just fine, not poorly with a tab laid over it. */
+.sIFR-flash + div[adblocktab=true] {
+  display: none !important;
+}
+
+/* These \"decoy\" styles are used to hide the browser text before it is replaced... the negative-letter spacing in this case is used to make the browser text metrics match up with the sIFR text metrics since the sIFR text in this example is so much narrower... your own settings may vary... any weird sizing issues you may run into are usually fixed by tweaking these decoy styles */
+
+";
+  
+  foreach ($rules as $rule) {
+    $fontsize       = trim($rule['fontsize']) ? "  font-size: $rule[fontsize];\n" : '';
+    $letterspacing  = trim($rule['letterspacing']) ? "  letter-spacing: $rule[letterspacing];\n" : '';
+    $rule['selector'] = str_replace(',', ', .sIFR-hasFlash ', $rule['selector']);
+    $output .= "
+.sIFR-hasFlash $rule[selector] {
+  visibility: hidden;
+$fontsize$letterspacing}
+";
+  }
+  
+  return $output;
+}
+
+/**
+ * Load plugin JavaScript and stylesheet files.
+ */
+function sifr_sifr_load() {
+  $sifrdir = variable_get('sifr_dir', FALSE);
+  // no variable set? scan the dir
+  if (!$sifrdir) {
+    $sifrdir = urlencode(sifr_find_sifr());
+  }
+  // still can't find it? display an error
+  if (!$sifrdir) {
+    drupal_set_message(t('The sIFR library is in not installed correctly. Please download from <a href="http://www.mikeindustries.com/sifr/">http://www.mikeindustries.com/sifr/</a> and place in Drupal\'s modules/sifr/ directory.'), 'error');
+  }
+  else {
+    drupal_add_js($sifrdir .'/sifr.js');
+    drupal_add_css($sifrdir .'/sIFR-print.css', 'module', 'print');
+  }
+}
+
Index: plugins/sifr.png
===================================================================
RCS file: plugins/sifr.png
diff -N plugins/sifr.png
Binary files /dev/null and sifr.png differ
