Index: geshifilter.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/geshifilter/geshifilter.module,v
retrieving revision 1.18.2.54
diff -u -u -p -r1.18.2.54 geshifilter.module
--- geshifilter.module	27 Feb 2008 13:43:38 -0000	1.18.2.54
+++ geshifilter.module	12 Apr 2008 17:43:26 -0000
@@ -9,8 +9,13 @@
 define('GESHIFILTER_DEFAULT_PLAINTEXT', 'GESHIFILTER_DEFAULT_PLAINTEXT');
 define('GESHIFILTER_DEFAULT_DONOTHING', 'GESHIFILTER_DEFAULT_DONOTHING');
 
+ // GeSHi CSS modes
+// Inline CSS
 define('GESHIFILTER_CSS_INLINE', 1);
-define('GESHIFILTER_CSS_CLASSES', 2);
+// Usage of CSS classes and an automatically managaged external stylesheet
+define('GESHIFILTER_CSS_CLASSES_AUTOMATIC', 2);
+// Only add CSS classes to markup, admin/themer is responsible for defining the CSS rules
+define('GESHIFILTER_CSS_CLASSES_ONLY', 3);
 
 define('GESHIFILTER_ATTRIBUTES_LANGUAGE', 'type lang language');
 define('GESHIFILTER_ATTRIBUTE_LINE_NUMBERING', 'linenumbers');
@@ -132,11 +137,18 @@ function geshifilter_menu($may_cache) {
       'type' => MENU_CALLBACK,
       'access' => user_access('administer site configuration'),
     );
+    // callback for generating CSS rules
+    $items[] = array(
+      'path' => 'admin/settings/geshifilter/generate_css',
+      'callback' => 'geshifilter_generate_language_css_rules',
+      'type' => MENU_CALLBACK,
+      'access' => user_access('administer site configuration'),
+    );
   }
   else {
     // Since the filtered content is cached, it is not possible to know on which
     // pages the css file is actually needed. Thus it is included on all pages.
-    if (_geshifilter_css_mode() == GESHIFILTER_CSS_CLASSES) {
+    if (variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE) == GESHIFILTER_CSS_CLASSES_AUTOMATIC) {
       if ($stylesheet_file = variable_get('geshifilter_languages_css', NULL)) {
         drupal_add_css($stylesheet_file);
       }
@@ -504,24 +516,25 @@ function geshifilter_admin_general_setti
     '#title' => t('Styling, layout and CSS'),
     '#collapsible' => TRUE,
   );
-  // CSS mode: CSS classes + external stylesheet is only possible with public downloads in a writable files directory
-  $directory = file_directory_path();
-  $external_css_possible = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
+
+  // CSS mode
   $form['geshifilter_styling']['geshifilter_css_mode'] = array(
     '#type' => 'radios',
     '#title' => t('CSS mode for syntax highlighting'),
-    '#description' => t('Inline CSS is easier to set up, does not depend on an external style sheets and is consequently more robust to copy/paste operations like content aggregation. However, usage of CSS classes and an external stylesheet (requires the public <a href="!filesystem">download method</a>) is generally considered to be the better way of styling and requires much less HTML code and bandwith. (GeSHi documentation: !link).',
+    '#options' => array(
+      GESHIFILTER_CSS_INLINE => t('Inline CSS style attributes.'),
+      GESHIFILTER_CSS_CLASSES_AUTOMATIC => t('Use CSS classes and an automatically managed external CSS style sheet.'),
+      GESHIFILTER_CSS_CLASSES_ONLY => t('Only add CSS classes to the markup.'),
+    ),
+    '#default_value' => variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE),
+    '#description' => t('Inline CSS is easier to set up, does not depend on an external style sheets and is consequently more robust to copy/paste operations like content aggregation. However, usage of CSS classes and an external stylesheet requires much less markup code and bandwidth. The external style sheet can be managed automatically by the GeSHi filter module, but this feature requires the public <a href="!filesystem">download method</a>. If the GeSHi filter is configured to only add the CSS classes to the markup, the administrator or themer is responsible for adding the appropriate CSS rules to the pages (e.g. based on <a href="!cssdefaults">these defaults</a>). (GeSHi documentation: !link).',
       array(
         '!link' => l('Using CSS Classes', 'http://qbnz.com/highlighter/geshi-doc.html#using-css-classes'),
         '!filesystem' => url('admin/settings/file-system'),
+        '!cssdefaults' => url('admin/settings/geshifilter/generate_css'),
       )),
-    '#disabled' => !$external_css_possible,
-    '#default_value' => $external_css_possible ? intval(variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE)) : GESHIFILTER_CSS_INLINE,
-    '#options' => array(
-      GESHIFILTER_CSS_INLINE => t('Inline CSS style attributes.'),
-      GESHIFILTER_CSS_CLASSES => t('CSS classes and external CSS style sheet.'),
-    ),
   );
+
   // Code container
   $form['geshifilter_styling']['geshifilter_code_container'] = array(
     '#type' => 'radios',
@@ -561,6 +574,10 @@ function geshifilter_admin_general_setti
     if (!$geshi_library['success']) {
       form_set_error('geshifilter_geshi_dir', $geshi_library['message']);
     }
+    // Check if automatically managed style sheet is posible
+    if ($form_values['geshifilter_css_mode'] == GESHIFILTER_CSS_CLASSES_AUTOMATIC && !_geshifilter_managed_external_stylesheet_possible()) {
+      form_set_error('geshifilter_css_mode', t('GeSHi filter can not automatically manage an external style sheet when the download method is private.'));
+    }
   }
 }
 
@@ -571,8 +588,8 @@ function geshifilter_admin_general_setti
   // normal system_settings_form processing
   system_settings_form_submit($form_id, $form_values);
   // regenerate language_css
-  if (_geshifilter_css_mode() == GESHIFILTER_CSS_CLASSES) {
-    _geshifilter_generate_languages_css();
+  if (variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE) == GESHIFILTER_CSS_CLASSES_AUTOMATIC) {
+    _geshifilter_generate_languages_css_file();
   }
   _geshifilter_clear_filter_cache();
 }
@@ -605,8 +622,8 @@ function geshifilter_admin_per_language_
   // normal system_settings_form processing
   system_settings_form_submit($form_id, $form_values);
   // regenerate language_css
-  if (_geshifilter_css_mode() == GESHIFILTER_CSS_CLASSES) {
-    _geshifilter_generate_languages_css();
+  if (variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE) == GESHIFILTER_CSS_CLASSES_AUTOMATIC) {
+    _geshifilter_generate_languages_css_file();
   }
   _geshifilter_clear_filter_cache();
 }
@@ -644,6 +661,18 @@ function geshifilter_requirements($phase
         'severity' => REQUIREMENT_OK,
       );
     }
+
+    // Warn if GeSHi filter is configured to automatically managed external stylesheet when it's not possible
+    if (variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE) == GESHIFILTER_CSS_CLASSES_AUTOMATIC && !_geshifilter_managed_external_stylesheet_possible()) {
+      $requirements[] = array(
+        'title' => 'GeSHi filter CSS mode',
+        'value' => t('GeSHi filter can not automatically manage an external style sheet when the download method is private.'),
+        'severity' => REQUIREMENT_ERROR,
+        'description' => t('Change the CSS mode of the <a href="!geshi">GeSHi filter</a> or change the <a href="!filesystem">download mode</a> to public',
+          array('!geshi' => url('admin/settings/geshifilter'), '!filesystem' => url('admin/settings/file-system'))),
+      );
+    }
+
     // check for filter conflicts
     if (geshifilter_admin_filter_conflicts(TRUE) > 0) {
       $requirements[] = array(
@@ -790,12 +819,13 @@ function _geshifilter_get_tags($format) 
 }
 
 /**
- * helper function for getting the CSS mode (considering the download method).
- */
-function _geshifilter_css_mode() {
-  $directory = file_directory_path();
-  $external_css_possible = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
-  return $external_css_possible ? intval(variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE)) : GESHIFILTER_CSS_INLINE;
+ * Helper function for checking if an automatically managed style sheet is possible
+ *
+ * @return boolean indicating if an automatically managed style sheet is possible
+ */
+function _geshifilter_managed_external_stylesheet_possible() {
+   $directory = file_directory_path();
+  return is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
 }
 
 /**
@@ -829,9 +859,36 @@ function geshifilter_clear_available_lan
 }
 
 /**
+ * Callback function for generating the CSS rules
+ *
+ * @return string with the CSS rules
+ */
+function _geshifilter_generate_languages_css_rules() {
+  $output = '';
+  $geshi_library = _geshifilter_check_geshi_library();
+  if ($geshi_library['loaded']) {
+    require_once('geshifilter.pages.inc');
+    $languages = _geshifilter_get_enabled_languages();
+    foreach ($languages as $langcode => $language_full_name) {
+      // create GeSHi object
+      $geshi = _geshifilter_GeSHi_factory('', $langcode);
+      _geshifilter_override_geshi_defaults($geshi, $langcode);
+      // add CSS rules for current language
+      $output .= $geshi->get_stylesheet(FALSE) ."\n";
+      // release GeSHi object
+      unset($geshi);
+    }
+  }
+  else {
+    drupal_set_message(t('Error while generating CSS rules: could not load GeSHi library.'), 'error');
+  }
+  return $output;
+}
+
+/**
  * Function for generating the external stylesheet.
  */
-function _geshifilter_generate_languages_css() {
+function _geshifilter_generate_languages_css_file() {
   $languages = _geshifilter_get_enabled_languages();
   // create files/geshifilter directory if not already available
   $path = file_directory_path() .'/geshifilter';
@@ -839,15 +896,8 @@ function _geshifilter_generate_languages
   // make stylesheet file name (depends on enabled languages)
   $stylesheet_file = $path .'/geshifilter-languages-'. substr(md5(serialize($languages)), 0, 8) .'.css';
   if (!file_exists($stylesheet_file)) {
-    require_once('geshifilter.pages.inc');
     // build stylesheet
-    $stylesheet = '';
-    foreach ($languages as $langcode => $language_full_name) {
-      $geshi = _geshifilter_GeSHi_factory('', $langcode);
-      _geshifilter_override_geshi_defaults($geshi, $langcode);
-      $stylesheet .= $geshi->get_stylesheet(FALSE) ."\n";
-      unset($geshi);
-    }
+    $stylesheet = _geshifilter_generate_languages_css_rules();
     // save stylesheet
     $ret = file_save_data($stylesheet, $stylesheet_file, FILE_EXISTS_REPLACE);
     if ($ret) {
@@ -860,3 +910,13 @@ function _geshifilter_generate_languages
     }
   }
 }
+
+/**
+ * Callback function for generating the CSS rules for the syntax highlighting
+ */
+function geshifilter_generate_language_css_rules() {
+  drupal_set_header("Content-type: text/css");
+  $output = _geshifilter_generate_languages_css_rules();
+  print($output);
+  exit();
+}
Index: geshifilter.pages.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/geshifilter/geshifilter.pages.inc,v
retrieving revision 1.3.2.2
diff -u -u -p -r1.3.2.2 geshifilter.pages.inc
--- geshifilter.pages.inc	18 Jan 2008 22:38:39 -0000	1.3.2.2
+++ geshifilter.pages.inc	12 Apr 2008 17:43:26 -0000
@@ -251,7 +251,8 @@ function geshifilter_geshi_process($sour
   $geshi = _geshifilter_GeSHi_factory($source_code, $lang);
 
   // CSS mode
-  if (_geshifilter_css_mode() == GESHIFILTER_CSS_CLASSES) {
+  $ccs_mode = variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE);
+  if ($ccs_mode == GESHIFILTER_CSS_CLASSES_AUTOMATIC || $ccs_mode == GESHIFILTER_CSS_CLASSES_ONLY) {
     $geshi->enable_classes(TRUE);
   }
   _geshifilter_override_geshi_defaults($geshi, $lang);
