--- ./biblio.admin.inc.orig     2008-06-27 22:50:24.000000000 +0200
+++ ./biblio.admin.inc  2008-08-07 12:36:18.000000000 +0200
@@ -228,6 +228,26 @@
   // Add profile page settings... this is done in a fucntion so it can be reused elsewhere
   _biblio_get_user_profile_form($form);
   //
+  $form['search'] = array(
+    '#type' => 'fieldset',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#title' => t('Search'),
+  );
+  $form['search']['biblio_search'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable a search box on the biblio page.'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('biblio_search', 0),
+    '#description' => t('Shows a search box on the biblio page that returns drupal search results in the biblio style.')
+  );
+  $form['search']['biblio_index'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Re-/Index a biblio node when creating or updating.'),
+    '#return_value' => 1,
+    '#default_value' => variable_get('biblio_index', 0),
+    '#description' => t('A biblio node must be indexed for the drupal search to know its content. You need to check this option if you want to search for a biblio node that you just created or updated. Otherwise you must wait for the cron job to reindex nodes.')
+  );
   $form['sort'] = array(
     '#type' => 'fieldset',
     '#collapsible' => TRUE,
--- ./biblio.css.orig   2008-05-14 23:29:07.000000000 +0200
+++ ./biblio.css        2008-08-07 12:36:18.000000000 +0200
@@ -1,4 +1,24 @@
 /** Node admin filter **/
+.biblio-search, .biblio-inline div {  
+  display: inline;
+}
+
+.biblio-inline { 
+  margin-bottom: 10px;
+}
+
+.biblio-search input {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+
+.biblio-fieldset {
+  margin-top: -1em;
+  border: none;
+  margin-bottom: 0px;
+  padding: 0px 0px 5px 0px;
+  display: inline;
+}
 #biblio-filter ul {
   padding:                    1px;
   margin:                     1px;
--- ./biblio.install.orig       2008-06-27 22:49:30.000000000 +0200
+++ ./biblio.install    2008-08-07 12:36:18.000000000 +0200
@@ -61,6 +61,8 @@
   variable_del('biblio_rowsperblock');
   variable_del('biblio_show_profile');
   variable_del('biblio_show_profile_tab');
+  variable_del('biblio_search');
+  variable_del('biblio_index');
   variable_del('biblio_sort');
   variable_del('biblio_sort_tabs');
   variable_del('biblio_style');
--- ./biblio.module.orig        2008-07-02 15:11:32.000000000 +0200
+++ ./biblio.module     2008-08-07 12:36:18.000000000 +0200
@@ -569,7 +569,8 @@
   drupal_goto($base, $options);
 }
 function biblio_nodeapi(& $node, $op, $teaser, $page) {
-  switch ($op) {
+  if ($node->type == 'biblio') {
+    switch ($op) {
     case 'delete revision' :
       db_query('DELETE FROM {biblio} WHERE vid = %d', $node->vid);
       db_query('DELETE FROM {biblio_contributor} WHERE nid = %d AND vid = %d', array($node->nid, $node->vid));
@@ -585,6 +586,23 @@
            }
            break;
       */
+    case 'insert':
+      if (variable_get('biblio_index',0)) {
+        _node_index_node($node); 
+        search_update_totals();
+      }
+      break;
+    case 'update':
+      if (variable_get('biblio_index',0)) {
+        // _node_index_node performs a node_load without resetting the node_load cache,
+        // so it would index the old version. We reset the cache here.
+        // Don't assign node_load to $node because node_load resets e.g. the menus mlid etc.
+        $mynode = node_load($node->nid, NULL, TRUE);
+        _node_index_node($mynode);
+        search_update_totals();
+      }
+      break;  
+    }
   }
 }
 function biblio_node_form_submit(& $node) {
--- ./biblio.pages.inc.orig     2008-05-27 04:17:44.000000000 +0200
+++ ./biblio.pages.inc  2008-08-08 14:17:06.000000000 +0200
@@ -23,6 +23,27 @@
 
 function biblio_db_search() {
 
+  // Drupal search? It returns an array of search results. We store the nids
+  // of the result nodes and make them a "where n.nid in {..}" filter.
+  // After installing the filter, we can go on as usual.
+  if ($keys = _get_biblio_search_filter()) {
+    // Only search in biblio nodes. If we have a list of nids, don't re-search.
+    //  The list is reset when submitting a new search.
+    if (!_get_biblio_search_filter('nodelist')) {
+      if ($result = node_search('search',$keys.' type:biblio')) {
+        $node_list = '';
+        foreach ($result as $res) {
+          $node_list .= $res['node']->nid.",";
+        }
+      }
+      else {
+        // No node search result. Make sure we find nothing, too. Node -1 does not exist.
+        $node_list = '-1';
+      }
+      $_SESSION['biblio_filter'] = array(array('search',rtrim($node_list,','),$keys));
+    }
+  }
+
   $arg_list = func_get_args();
   $inline = in_array('inline', $arg_list);
   $inline = in_array('profile',$arg_list)?'profile':$inline;
@@ -250,6 +271,18 @@
               $sortby = "ORDER BY b.biblio_year %s, SUBSTRING(n.title,1,1) ASC, b.biblio_type ASC ";
           } //end switch
           break;
+        case 'search':
+         $term = explode("?",array_shift($arg_list));
+         // Search filter has a third component, the keywords, here useless. Drop it.
+         array_shift($arg_list);
+         $result_nids = split(',', $term[0]);
+         $where[] = "n.nid in (".db_placeholders($result_nids).")";
+         foreach ($result_nids as $result_nid) {
+           $terms[] = db_escape_string($result_nid);
+           array_push($args, $type, $result_nid);
+         }
+         $operator = NULL;
+         break;
         default:
           $fields = biblio_get_db_fields();
           $term = explode("?",array_shift($arg_list));
@@ -309,6 +342,10 @@
     $pub_type["$option->tid"] = $option->name;
   }
   if (!$inline) {
+    // Search box. Has same permissions as the filter tab.
+    if (variable_get('biblio_search',0) && user_access('show filter tab')) {
+      $content .= drupal_get_form('biblio_search_form');
+    }
     // Add some links to the top of the page to change the sorting/ordering...
     $order = ($attrib['order'] == "desc" || $attrib['order'] == "DESC")?"asc":"desc";
     if ( biblio_access('export')) {
@@ -355,7 +392,18 @@
     $session = &$_SESSION['biblio_filter'];
     // if there are any filters in place, print them at the top of the list
     if (count($args)) {
-      $content .= '<div class="biblio-current-filters"><b>'.t('Filters').': </b>';
+      // If we have a search filter, it's the only and thus first one.
+      $type = $args[0];
+      if ($type == 'search') {
+        $type = 'search';
+        $content .= '<div class="biblio-current-filters"><b>'.t('Search results for ').'</b>';
+        $search_keys =_get_biblio_search_filter();
+        $content .= '<em>'.$search_keys.'</em>';
+        // The while loop is now superflous.
+        $args = array ();
+      } else {
+        $content .= '<div class="biblio-current-filters"><b>'.t('Filters').': </b>';
+      }
       $i = 0;
       while ($args) {
         $type = $args[0];
@@ -385,7 +433,11 @@
        $link_options['query']   .= "order=" . $_GET['order'];
           }
 
-      $content .= '&nbsp;&nbsp;'.l('['.t('Clear All Filters').']',"$base/filter/clear", $link_options);
+      if ($type == 'search') {
+        $content .= '&nbsp;&nbsp;'.l('['.t('Reset Search').']',"$base/filter/clear", $link_options);
+      } else {
+        $content .= '&nbsp;&nbsp;'.l('['.t('Clear All Filters').']',"$base/filter/clear", $link_options);
+      }
       $content .= '</div>';
     }
   }
@@ -465,6 +517,98 @@
   if ($inline === "profile")  return $content;
 
 }
+
+
+/**
+ * Add a search field on the main biblio page.
+ */
+function biblio_search_form(&$form_state) {
+ $form = array(
+    '#attributes' => array('class' => 'biblio-search'),
+  );
+  $form['module'] = array('#type' => 'value', '#value' => $type);
+
+  // Uncomment to collapse the search box.
+  //$form['basic'] = array(
+  //  '#attributes' => array('class' => 'biblio-fieldset'),
+  //  '#type' => 'fieldset',
+  //  '#collapsible' => TRUE,
+  //  '#collapsed' => TRUE,
+  //  '#title' => t('Quick Search'),
+  //  '#description' => '',
+  //  );
+
+  $form['basic']['inline'] = array('#prefix' => '<div class="biblio-inline">', '#suffix' => '</div>');
+  $form['basic']['inline']['keys'] = array(
+    '#type' => 'textfield',
+    '#title' => '',
+    '#default_value' => '',
+    '#size' => 25,
+    '#maxlength' => 255,
+  );
+  $form['basic']['inline']['submit'] = array('#type' => 'submit', '#value' => t('Biblio search'));
+  return $form;
+}
+
+/**
+ * We must validate the keyword length before calling node_search. Otherwise
+ * we would store a keyword of e.g. length 1, but do_search would complain about
+ * it later and resend us to the input form. But since the keyword was stored already
+ * we could never again display the page without errors
+ */
+function biblio_search_form_validate($form, &$form_state) {
+  // Empty searchbox finds everything.
+  $keys = $form_state['values']['keys'];
+  if ($keys != '')  {
+    $query = search_parse_query($form_state['values']['keys']);
+    if ($query[2] == '') {
+      form_set_error('keys', t('You must include at least one positive keyword with @count characters or more.', array('@count' => variable_get('minimum_word_size', 3))));
+    }
+  }
+}
+
+
+/**
+ * When we submit a search, we revoke all current filters since search
+ * and filtering are considered two different concepts things* conceptually.
+ *
+ * But we store the results as a filter (which is just a list of node ids that
+ * matched the search request) so that we can reorder or export the search
+ * results like with any other filter.  The filter has three components:
+ * ('search',<list of node ids>,<search keywords>).
+ * The second component, the filter value, is empty when submitting keywords.
+ * In biblio_db_search we fill the second component with the list of nids
+ * matching our keywords, as returned by node_search.  We store the keywords
+ * only for showing them in "Search results for <keywords>".
+ */
+function biblio_search_form_submit($form, &$form_state) {
+  $keys = $form_state['values']['keys'];
+  if ($keys != '')  {
+    $_SESSION['biblio_filter'] = array(array('search','',$keys));
+    $base =  variable_get('biblio_base', 'biblio');
+    $form_state['redirect'] = $base;
+  }
+  else {
+    // No keywords. Remove former search keys if any. Leaves other filters intact.
+    if (_get_biblio_search_filter()){
+      $_SESSION['biblio_filter'] = array();
+    }
+  }
+}
+
+function _get_biblio_search_filter($arg = 'keys') {
+  if (variable_get('biblio_search',0) &&
+      is_array($_SESSION['biblio_filter']) &&
+      is_array($_SESSION['biblio_filter'][0]) &&
+      in_array('search',$_SESSION['biblio_filter'][0])) {
+    switch ($arg) {
+    case 'keys': return $_SESSION['biblio_filter'][0][2]; break;
+    case 'nodelist': return $_SESSION['biblio_filter'][0][1]; break;
+    }
+  }
+}
+
+
 function _get_biblio_filters() {
 
   $fields = " b.biblio_year, t.name , t.tid ";
@@ -513,7 +657,8 @@
 }
 
 function biblio_form_filter() {
-  $session = &$_SESSION['biblio_filter'];
+  // No longer use &$_SESSION so that we can alter $session in case of the search filter.
+  $session = $_SESSION['biblio_filter'];
   $session = is_array($session) ? $session : array();
   $filters = _get_biblio_filters();
 
@@ -524,6 +669,11 @@
   );
   foreach ($session as $filter) {
     list($type, $value) = $filter;
+    // Don't show the search filter. Reset $session because of the $count(session) below.
+    if ($type == 'search') {
+      $session = array ();
+      break;
+    }
     if ($type == 'category') {
       // Load term name from DB rather than search and parse options array.
       $value = module_invoke('taxonomy', 'get_term', $value);
@@ -548,7 +698,7 @@
 
   $form['filters']['filter'] = array('#type' => 'radios', '#options' => $names, '#default_value' => 'aid');
   $form['filters']['buttons']['submit'] = array('#type' => 'submit', '#value' => (count($session) ? t('Refine') : t('Filter')));
-  if (count($session)) {
+  if (count($session) && $type != 'search') {
     $form['filters']['buttons']['undo'] = array('#type' => 'submit', '#value' => t('Undo'));
     $form['filters']['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
   }
@@ -557,6 +707,10 @@
 }
 
 function biblio_form_filter_submit($form, &$form_state) {
+  // If the search filter was set, remove it now.
+  if(_get_biblio_search_filter()){
+    $_SESSION['biblio_filter'] = array ();
+  }
   $op = $form_state['values']['op'];
   $filters = _get_biblio_filters();
   switch ($op) {
