Index: geshifilter.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/geshifilter/geshifilter.admin.inc,v
retrieving revision 1.20
diff -u -b -u -p -r1.20 geshifilter.admin.inc
--- geshifilter.admin.inc	27 Jun 2009 12:54:15 -0000	1.20
+++ geshifilter.admin.inc	27 Jun 2009 16:45:09 -0000
@@ -246,6 +246,7 @@ function geshifilter_admin_general_setti
   if (variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE) == GESHIFILTER_CSS_CLASSES_AUTOMATIC) {
     _geshifilter_generate_languages_css_file();
   }
+  // Always clear the filter cache.
   _geshifilter_clear_filter_cache();
 }
 
@@ -486,7 +487,8 @@ function _geshifilter_flush_language_def
  */
 function _geshifilter_clear_filter_cache() {
   $message = FALSE;
-  // iterate over input formats
+
+  // Iterate over input formats and clear the ones GeSHi filter is active in.
   foreach (filter_formats() as $format => $input_format) {
     // Get the filters in this input format
     $filters = filter_list_format($format);
@@ -496,7 +498,12 @@ function _geshifilter_clear_filter_cache
       $message = TRUE;
     }
   }
-  // show a message that the filter cache was cleared
+
+  // Clear the geshifilter entries in the cache_filter table,
+  // created by geshifilter_geshi_process().
+  cache_clear_all('geshifilter:', 'cache_filter', TRUE);
+
+  // Show a message that the filter cache was cleared.
   if ($message) {
     drupal_set_message(t('GeSHi filter cleared the filter cache for the appropriate input formats.'));
   }
Index: geshifilter.pages.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/geshifilter/geshifilter.pages.inc,v
retrieving revision 1.10
diff -u -b -u -p -r1.10 geshifilter.pages.inc
--- geshifilter.pages.inc	4 Jan 2009 17:44:38 -0000	1.10
+++ geshifilter.pages.inc	27 Jun 2009 16:45:09 -0000
@@ -311,6 +311,15 @@ function geshifilter_geshi_process($sour
     drupal_set_message($geshi_library['message'], 'error');
     return $source_code;
   }
+
+   // Check for a cached version of this source code and return it if available.
+   // @todo: Use a dedicated table instead of using cache_filter? If so,
+   // also take care of the flushing in _geshifilter_clear_filter_cache().
+  $cache_id = "geshifilter:$lang:$line_numbering:$line_numbering:$inline_mode" . md5($source_code);
+  if ($cached = cache_get($cache_id, 'cache_filter')) {
+    return $cached->data;
+  }
+
   // remove leading/trailing newlines
   $source_code = trim($source_code, "\n\r");
   // create GeSHi object
@@ -341,6 +350,11 @@ function geshifilter_geshi_process($sour
     }
     $source_code = '<div class="geshifilter">'. $geshi->parse_code() .'</div>';
   }
+
+  // Store in cache with a minimum expiration time of 1 day.
+  cache_set($cache_id, $source_code, 'cache_filter', time() + (60 * 60 * 24));
+
+
   return $source_code;
 }
 
Index: geshifield/geshifield.info
===================================================================
RCS file: geshifield/geshifield.info
diff -N geshifield/geshifield.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ geshifield/geshifield.info	27 Jun 2009 16:45:09 -0000
@@ -0,0 +1,7 @@
+; $Id$
+name = "GeSHi field"
+description = "Provides a CCK field for source code with GeSHI syntax highlighting."
+package = "Filters"
+core = 6.x
+dependencies[] = content
+dependencies[] = geshifilter
Index: geshifield/geshifield.install
===================================================================
RCS file: geshifield/geshifield.install
diff -N geshifield/geshifield.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ geshifield/geshifield.install	27 Jun 2009 16:45:09 -0000
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Install and unistall related function for the GeSHi Field module.
+ *
+ * @todo check this content_notify stuff.
+ */
+
+/**
+ * Implementation of hook_install().
+ */
+function geshifield_install() {
+  content_notify('install', 'geshifield');
+}
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function geshifield_uninstall() {
+  content_notify('uninstall', 'geshifield');
+}
+
+/**
+ * Implementation of hook_enable().
+ */
+function geshifield_enable() {
+  content_notify('enable', 'geshifield');
+}
+
+/**
+ * Implementation of hook_disable().
+ */
+function geshifield_disable() {
+  content_notify('disable', 'geshifield');
+}
Index: geshifield/geshifield.module
===================================================================
RCS file: geshifield/geshifield.module
diff -N geshifield/geshifield.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ geshifield/geshifield.module	27 Jun 2009 16:45:09 -0000
@@ -0,0 +1,237 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Defines a CCK field for source code with GeSHi syntax highlighting.
+ *
+ * @todo: is the GeSHi CSS file always loaded when needed?
+ */
+
+/**
+ * Implementation of hook_theme().
+ */
+function geshifield_theme() {
+  return array(
+    'geshifield_textarea' => array(
+       'arguments' => array('element' => NULL),
+    ),
+    'geshifield_formatter_default' => array(
+       'arguments' => array('element' => NULL),
+    ),
+    'geshifield_formatter_nohighlighting' => array(
+       'arguments' => array('element' => NULL),
+    ),
+    'geshifield_formatter_trimmed' => array(
+       'arguments' => array('element' => NULL),
+    ),
+  );
+}
+
+
+/**
+ * Implementation of hook_field_info().
+ */
+function geshifield_field_info() {
+  return array(
+    'geshifield' => array(
+      // @todo: better label? "Source code field"?
+      'label' => t('GeSHi field'),
+      'description' => t('Source code text field with GeSHi syntax highlighting.'),
+    )
+  );
+}
+
+/**
+ * Implementation of hook_field_settings().
+ */
+function geshifield_field_settings($op, $field) {
+  switch ($op) {
+    case 'database columns':
+      $columns =  array(
+        'sourcecode' => array(
+          'type' => 'text',
+          'size' => 'big',
+          'not null' => FALSE,
+          'sortable' => TRUE,
+          'views' => TRUE, //@todo what does this do?
+        ),
+        'language' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => FALSE,
+          'sortable' => TRUE,
+          'views' => TRUE, //@todo what does this do?
+        ),
+      );
+      return $columns;
+  }
+}
+
+
+/**
+ * Implementation of hook_field().
+ */
+function geshifield_field($op, &$node, $field, &$items, $teaser, $page) {
+  // Nothing to do here.
+  // Typically only the validition operation is needed in this hook
+  // but for geshifield even this is not needed.
+}
+
+/**
+ * Implementation of hook_content_is_empty().
+ */
+function geshifield_content_is_empty($item, $field) {
+  return empty($item['sourcecode']);
+}
+
+/**
+ * Implementation of hook_widget_info().
+ */
+function geshifield_widget_info() {
+  return array(
+    'geshifield_textarea' => array(
+      'label' => t('Source code text area'),
+      'field types' => array('geshifield'),
+      // Let CCK core handle multiple values.
+      'multiple values' => CONTENT_HANDLE_CORE,
+      'callbacks' => array(
+        // Do not provide default values through CCK core's
+        // default value handling. @todo: or should we?
+        'default value' => CONTENT_CALLBACK_NONE,
+      ),
+    ),
+  );
+  // @todo provide a file upload widget too.
+}
+
+/**
+ * Implementation of hook_elements().
+ */
+function geshifield_elements() {
+  $elements = array(
+    'geshifield_textarea' => array(
+      '#input' => TRUE,
+      '#process' => array('geshifield_textarea_process' ),
+    ),
+  );
+  return $elements;
+}
+
+/**
+ * Process callback for geshifield_textarea widget.
+ */
+function geshifield_textarea_process($element, $edit, &$form_state, $form) {
+  module_load_include('inc', 'geshifilter');
+
+  $defaults = $element['#value'];
+  $field = content_fields($element['#field_name'], $element['#type_name']);
+
+  $enabled_languages = _geshifilter_get_enabled_languages();
+  // @todo: also add "no highlighting" options.
+
+  $element['sourcecode'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Source code'),
+    '#default_value' => $defaults['sourcecode'],
+    '#required' => $field['required'],
+    '#rows' => $field['widget']['rows'],
+    '#description' => t($field['widget']['description']),
+  );
+
+  $element['language'] = array(
+    '#type' => 'select',
+    '#title' => t('Syntax highlighting mode'),
+    '#default_value' => $defaults['language'],
+    '#options' => $enabled_languages,
+    '#description' => t('Select the syntax highlighting mode to use for the source code.'),
+  );
+
+  return $element;
+}
+
+/**
+ * Theming function for the geshifield_textarea widget
+ */
+function theme_geshifield_textarea(&$element) {
+  return theme( 'form_element', $element, $element['#children'] );
+}
+
+/**
+ * Implementation of hook_widget_settings().
+ */
+function geshifield_widget_settings($op, $widget) {
+  switch ($op) {
+    case 'form':
+      $form = array();
+      $form['rows'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Default number of rows in text area'),
+        '#description' => t('The default number of rows to provide in the text area for entering the source code.'),
+        '#default_value' => isset($widget['rows']) ? $widget['rows'] : 20,
+        '#required' => TRUE,
+      );
+      // @todo add an option for the default language
+      return $form;
+      break;
+
+    case 'validate':
+      if (!is_numeric($widget['rows']) || intval($widget['rows']) != $widget['rows'] || $widget['rows'] <= 0 || $widget['rows'] > 100) {
+        form_set_error('rows', t('The number of rows must be an integer between 1 and 100.'));
+      }
+      break;
+
+    case 'save':
+      return array('rows');
+      break;
+  }
+}
+
+/**
+ * Implementation of hook_widget().
+ */
+function geshifield_widget(&$form, &$form_state, $field, $items, $delta = 0) {
+  $element = array(
+    '#type' => $field['widget']['type'],
+    '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
+  );
+  return $element;
+}
+
+/**
+ * Implementation of hook_field_formatter_info().
+ */
+function geshifield_field_formatter_info() {
+  $formatters = array(
+    'default' => array(
+      'label' => t('Default'),
+      'field types' => array('geshifield'),
+    ),
+    'nohighlighting' => array(
+      'label' => t('No syntax highlighting'),
+      'field types' => array('geshifield'),
+    ),
+    'trimmed' => array(
+      'label' => t('Trimmed'),
+      'field types' => array('geshifield'),
+    ),
+  );
+  return $formatters;
+}
+
+
+function theme_geshifield_formatter_default($element) {
+  // @todo: These theme functions seem to be called more than expected for some reason.
+  module_load_include('inc', 'geshifilter', 'geshifilter.pages');
+  return geshifilter_geshi_process($element['#item']['sourcecode'], $element['#item']['language']);
+}
+
+function theme_geshifield_formatter_nohighlighting($element) {
+  module_load_include('inc', 'geshifilter', 'geshifilter.pages');
+  return geshifilter_geshi_process($element['#item']['sourcecode'], 'text');
+}
+
+function theme_geshifield_formatter_trimmed($element) {
+  module_load_include('inc', 'geshifilter', 'geshifilter.pages');
+  return geshifilter_geshi_process(node_teaser($element['#item']['sourcecode']), $element['#item']['language']);
+}
