Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.85
diff -u -F^f -r1.85 module.inc
--- includes/module.inc	31 Aug 2006 22:12:15 -0000	1.85
+++ includes/module.inc	13 Sep 2006 19:34:46 -0000
@@ -130,7 +130,27 @@ function module_rebuild_cache() {
       db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, $file->info['description'], 'module', $file->filename, $file->status, $file->throttle, $bootstrap);
     }
   }
+  $files = _module_build_dependents($files);
+  return $files;
+}
 
+/**
+ * Find dependents; modules that are dependent on by other modules.
+ * Adds an array of dependents to the $file->info array.
+ * 
+ * @return 
+ *  The list of files array with dependents added where applicable.
+ */
+function _module_build_dependents($files) {
+  foreach($files as $filename => $file) {
+    if (is_array($file->info['dependencies'])) {
+      foreach ($file->info['dependencies'] as $dependency) {
+        if (!empty($files[$dependency]) && is_array($files[$dependency]->info)){
+          $files[$dependency]->info['dependents'][] = $filename;
+        }
+      }
+    }  	
+  }
   return $files;
 }
 
@@ -148,7 +168,17 @@ function module_rebuild_cache() {
  *   and variable_set() for that.
  * - You may not use double-quotes in a value.
  *
- * @param $filename
+ * Information stored in the module.info file:
+ * name - The real name of the module for display purposes.
+ * description - A brief description of the module.
+ * dependencies - A space delimited list of the short names (shortname) of other modules this module depends on.  
+ * 
+ * Example of .info file:
+ *   name = Forum
+ *   description = Enables threaded discussions about general topics.
+ *   dependencies = taxonomy comment
+ * 
+ *  @param $filename
  *   The file we are parsing.  Accepts file with relative or absolute path.
  * @return
  *   The info array.
@@ -159,6 +189,9 @@ function _module_parse_info_file($filena
   if (file_exists($filename)) {
     $info = parse_ini_file($filename);
   }
+  if(isset($info['dependencies'])) {
+    $info['dependencies'] = explode(" ", $info['dependencies']);
+  }  
   return $info;
 }
 
Index: modules/forum/forum.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.info,v
retrieving revision 1.1
diff -u -F^f -r1.1 forum.info
--- modules/forum/forum.info	31 Aug 2006 20:22:35 -0000	1.1
+++ modules/forum/forum.info	13 Sep 2006 19:34:46 -0000
@@ -1,4 +1,4 @@
 ; $Id: forum.info,v 1.1 2006/08/31 20:22:35 dries Exp $
 name = Forum
 description = Enables threaded discussions about general topics.
-
+dependencies = taxonomy comment
Index: modules/system/admin.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/admin.css,v
retrieving revision 1.7
diff -u -F^f -r1.7 admin.css
--- modules/system/admin.css	6 Sep 2006 08:35:59 -0000	1.7
+++ modules/system/admin.css	13 Sep 2006 19:34:46 -0000
@@ -39,6 +39,11 @@
   padding-right: 4px;
 }
 
+div.admin-missing, div.admin-required {
+  font-size:  0.9em;
+  color: #444;
+}
+
 /**
  * Formatting for status report
  */
@@ -63,3 +68,4 @@
 table.system-status-report tr.ok th {
   background-image: url('../../misc/watchdog-ok.png');
 }
+
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.369
diff -u -F^f -r1.369 system.module
--- modules/system/system.module	8 Sep 2006 23:13:00 -0000	1.369
+++ modules/system/system.module	13 Sep 2006 19:34:52 -0000
@@ -1217,49 +1217,185 @@ function system_themes_submit($form_id, 
 }
 
 /**
- * Menu callback; displays a listing of all modules.
+ * Menu callback; provides module enable/disable interface.
+ *
+ * Modules can be enabled or disabled and set for throttling if the throttle module is enabled.
+ * The list of modules gets populated by module.info files, which contain each module's name, 
+ * description and dependencies.
+ * \sa _module_parse_info_file for information on module.info descriptors.
+ *
+ * Dependency checking is performed to ensure that a module cannot be enabled if the module has 
+ * disabled dependencies and also to ensure that the module cannot be disabled if the module has 
+ * enabled dependents.
+ *
+ * @return
+ *    The form array.
  */
+
 function system_modules() {
-  // Get current list of modules
+  // Get current list of modules.
   $files = module_rebuild_cache();
+  
+  // Store module list for validation callback.
+  $form['validation_modules'] = array('#type' => 'value', '#value' => $files);
+  
+  // Create storage for disabled modules as browser will disable checkboxes.
+  $form['disabled_modules'] = array('#type' => 'value', '#value' => array());
 
+  // Array for disabling checkboxes in callback system_module_disable.
+  $disabled = array();
+  // Traverse the files retrieved and build the form.
   foreach ($files as $filename => $file) {
-    $info = $file->info;
-    $form['name'][$file->name] = array('#value' => $info['name']);
-    $form['description'][$file->name] = array('#value' => t($info['description']));
-    $options[$file->name] = '';
+    $form['name'][$filename] = array('#value' => $file->info['name']);
+    $form['description'][$filename] = array('#value' => t($file->info['description']));
+    $options[$filename] = '';
     if ($file->status) {
       $status[] = $file->name;
     }
     if ($file->throttle) {
       $throttle[] = $file->name;
     }
+
+    $missing_dependencies = array();
+    // Check for missing dependencies.
+    if (is_array($file->info['dependencies'])) {
+      foreach ($file->info['dependencies'] as $dependency) {
+        if (!isset($files[$dependency]) || !$files[$dependency]->status) {
+          $disabled[] = $filename;
+          if (isset($files[$dependency])) {
+            $missing_dependencies[] = $files[$dependency]->info['name']; 
+          } 
+          else {
+            $missing_dependencies[] = t('Please <a href="!modules">download</a> @dependency.', array('!modules' => 'http://drupal.org/project/Modules/', '@dependency' => $dependency));	
+          } 
+        }
+      }
+
+      // Add text for missing dependencies.
+      if (!empty($missing_dependencies)) {
+        $form['description'][$filename]['missing_dependencies'] = array(
+          '#value' => t('Missing dependencies: !missing_dependencies', array('!missing_dependencies' => implode(', ', $missing_dependencies))),
+          '#prefix' => '<div class="admin-missing">',
+          '#suffix' => '</div>',
+        );
+      }
+    }
+
+    // Mark dependents disabled so user can not remove modules being depended on.
+    $dependents = array();
+    if(is_array($file->info['dependents'])){
+      foreach ($file->info['dependents'] as $dependent) {
+        if ($files[$dependent]->status == 1) {
+          $dependents[] = $files[$dependent]->info['name'];        	
+          $form['disabled_modules']['#value'][$filename] = $file->status;
+          if (!in_array($filename, $disabled)) { 
+            $disabled[] = $filename;
+          }
+        }
+      }
+    }
+
+    // Add text for enabled dependents.
+    if(!empty($dependents)){
+      $form['description'][$filename]['required'] = array(
+        '#value' => t('Required by: @required', array('@required' => implode(', ', $dependents))),
+        '#prefix' => '<div class="admin-required">',
+        '#suffix' => '</div>',
+      );
+    }
   }
 
-  // Handle status checkboxes, including overriding the generated
-  // checkboxes for required modules.
-  $form['status'] = array('#type' => 'checkboxes', '#default_value' => $status, '#options' => $options);
-  $required = array('block', 'filter', 'node', 'system', 'user', 'watchdog');
-  foreach ($required as $require) {
-    $form['status'][$require] = array('#type' => 'hidden', '#value' => 1, '#suffix' => t('required'));
+  // Merge in required modules
+  foreach (array('block', 'filter', 'node', 'system', 'user', 'watchdog') as $required) {
+    $form['description'][$required]['core'] = array(
+      '#value' => t('Required for Drupal core'),
+      '#prefix' => '<div class="admin-required">',
+      '#suffix' => '</div>',
+    );
+    $disabled[] = $required;
   }
 
-  /**
-   * Handle throttle checkboxes, including overriding the generated checkboxes for required modules.
-   */
+  // Handle status checkboxes, including overriding 
+  // the generated checkboxes for required modules.
+  $form['status'] = array(
+    '#type' => 'checkboxes', 
+    '#default_value' => $status, 
+    '#options' => $options, 
+    '#process' => array( 
+      'expand_checkboxes' => array(), 
+      'system_module_disable' => array($disabled),
+    ),
+  );
+
+  // Handle throttle checkboxes, including overriding the 
+  // generated checkboxes for required modules.
   if (module_exists('throttle')) {
-    $form['throttle'] = array('#type' => 'checkboxes', '#default_value' => $throttle, '#options' => $options);
+    $form['throttle'] = array(
+      '#type' => 'checkboxes', 
+      '#default_value' => $throttle, 
+      '#options' => $options,
+    );
     $throttle_required = array_merge($required, array('throttle'));
     foreach ($throttle_required as $require) {
-      $form['throttle'][$require] = array('#type' => 'hidden', '#value' => 0, '#suffix' => t('required'));
+      $form['throttle'][$require] = array(
+        '#type' => 'hidden', 
+        '#value' => 0, 
+        '#suffix' => t('required'),
+      );
     }
   }
 
-  $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
+  $form['buttons']['submit'] = array(
+    '#type' => 'submit', 
+    '#value' => t('Save configuration'),
+  );
+
+  return $form;
+}
 
+/**
+ * Form process callback function to disable check boxes.
+ */
+function system_module_disable($form, $form_values, $disabled) {
+  foreach ($disabled as $key) {
+    $form[$key]['#attributes']['disabled'] = 'disabled';
+  }
   return $form;
 }
 
+/**
+ * Validate callback; performs dependency integrity checks to ensure that modules don't get added
+ * if dependencies fail.
+ */
+function system_modules_validate($form_id, $form_values, $form) {
+  // Recheck values for submitted dependency errors.
+  foreach ($form_values['validation_modules'] as $name => $module) {
+    $failed_dependencies = array();
+    // Is module enabled and does it have dependencies.
+    if (!$module->status && $form_values['status'][$name] && is_array($module->info['dependencies'])) {
+      foreach ($module->info['dependencies'] as $dependency) {
+        // Check if dependendency is enabled on the form.
+        if (!($form_values['status'][$dependency])) {
+          // Give appropriate task to enable dependency.
+          $failed_dependencies['dependencies'][$dependency] = isset($form_values['validation_modules'][$dependency]) ? $form_values['validation_modules'][$dependency]->info['name'] : $dependency;
+          $failed_dependencies['tasks'][] = t('Please enable the %dependent module to continue.', array('%dependent' => $failed_dependencies['dependencies'][$dependency])); 
+        }
+      }
+    }
+    if (!empty($failed_dependencies)) {
+      $t_argument = array(
+        '%module' => $form_values['validation_modules'][$name]->info['name'], 
+        '%dependency' => implode(', ', $failed_dependencies['dependencies']),
+        '!tasks' => theme('item_list',$failed_dependencies['tasks']),
+      );
+      form_set_error("status][$name", t('Could not enable the %module module, as it depends on %dependency. !tasks', $t_argument));
+    }
+  }
+}
+
+/**
+ * Theme call back for the modules form.
+ */
 function theme_system_modules($form) {
   foreach (element_children($form['name']) as $key) {
     $row = array();
@@ -1268,7 +1404,7 @@ function theme_system_modules($form) {
     if (module_exists('throttle')) {
       $row[] = array('data' => drupal_render($form['throttle'][$key]), 'align' => 'center');
     }
-    $row[] = drupal_render($form['name'][$key]);
+    $row[] = '<strong>'. drupal_render($form['name'][$key]) .'</strong>';
     $row[] = drupal_render($form['description'][$key]);
     $rows[] = $row;
   }
@@ -1285,13 +1421,18 @@ function theme_system_modules($form) {
   return $output;
 }
 
-
+/**
+ * Submit callback; handles modules form submission.
+ */
 function system_modules_submit($form_id, $form_values) {
   include_once './includes/install.inc';
   $new_modules = array();
 
-  // Enable/disable modules that have already been installed
-  foreach ($form_values['status'] as $key => $choice) {
+  // Merge in disabled active modules since they should be enabled.
+  // They don't appear because disabled checkboxes are not submited
+  // by browsers.
+  $modules = array_merge($form_values['status'],$form_values['disabled_modules']);
+  foreach ($modules as $key => $choice) {
     if ($choice) {
       if (drupal_get_installed_schema_version($key) == SCHEMA_UNINSTALLED) {
         $new_modules[] = $key;
