Index: boxes.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/boxes/boxes.admin.inc,v
retrieving revision 1.5.2.1
diff -u -p -r1.5.2.1 boxes.admin.inc
--- boxes.admin.inc	25 Apr 2010 18:41:54 -0000	1.5.2.1
+++ boxes.admin.inc	19 May 2010 16:43:13 -0000
@@ -69,6 +69,33 @@ function boxes_delete_form_submit($form,
 }
 
 /**
+ * Block/Box conversion confirmation form.
+ */
+function boxes_convert_form($form_state, $module, $delta) {
+  $form['module'] = array('#type' => 'hidden', '#value' => $module);
+  $form['delta'] = array('#type' => 'hidden', '#value' => $delta);
+  switch ($module) {
+    case 'block':
+      return confirm_form($form, t('Are you sure you want to convert this block to a box?'), 'admin/build/block', '', t('Convert'), t('Cancel'));
+      break;
+    case 'boxes':
+      return confirm_form($form, t('Are you sure you want to convert this box to a block?'), 'admin/build/block', '', t('Convert'), t('Cancel'));
+      break;
+    case 'default':
+      drupal_not_found();
+      die();
+  }
+}
+
+/**
+ * Submit handler for boxes_convert_form
+ */
+function boxes_convert_form_submit($form, &$form_state) {
+  boxes_convert($form_state['values']['module'], $form_state['values']['delta']);
+  $form_state['redirect'] = 'admin/build/block';
+}
+
+/**
  * Form for in page editing.
  */
 function boxes_box_inline_form(&$form_state, $box, $block) {
Index: boxes.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/boxes/boxes.module,v
retrieving revision 1.10.2.3
diff -u -p -r1.10.2.3 boxes.module
--- boxes.module	26 Apr 2010 17:51:24 -0000	1.10.2.3
+++ boxes.module	19 May 2010 16:43:13 -0000
@@ -40,6 +40,13 @@ function boxes_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'boxes.admin.inc',
   );
+  $items['boxes/convert/%/%'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('boxes_convert_form', 2, 3),
+    'access callback' => 'boxes_access_admin',
+    'type' => MENU_CALLBACK,
+    'file' => 'boxes.admin.inc',
+  );
   return $items;
 }
 
@@ -228,6 +235,114 @@ function boxes_load_reset() {
 }
 
 /**
+ * Loader for blocks.
+ */
+function boxes_load_block($delta = NULL) {
+  $where = '';
+  if (isset($delta)) {
+    $where = " AND blocks.delta = '%s'";
+  }
+  $sql = "SELECT boxes.body, boxes.info AS description, boxes.format, blocks.delta, blocks.title, blocks.bid
+          FROM {blocks}
+          INNER JOIN {boxes} ON boxes.bid = blocks.delta
+          WHERE blocks.module = 'block'". $where;
+  $query = db_query($sql, $delta);
+  while ($block = db_fetch_object($query)) {
+    $blocks[$block->delta] = $block;
+  }
+  if (isset($delta)) {
+    return $blocks[$delta];
+  }
+  return $blocks;
+}
+
+/**
+ * Converts blocks to boxes or boxes to blocks.
+ *
+ * @param $module
+ *   String of the controlling module.
+ * @param $delta
+ *   String of the delta for the block or box to convert.
+ */
+function boxes_convert($module, $delta) {
+  // Depending on what the module is we convert to the other.
+  switch ($module) {
+    case 'block':
+      // Load the block information.
+      $block = boxes_load_block($delta);
+      
+      // Remove {boxes} entry.
+      db_query("DELETE FROM {boxes} WHERE bid = %d", $delta);
+      
+      // Update the {blocks} entry.
+      // We have to update the delta because when a new block is created
+      // we will run into duplicate keys.
+      ctools_include('cleanstring');
+      $block->delta = ctools_cleanstring($block->description .'_'. $delta);
+      $block->module = 'boxes';
+      drupal_write_record('blocks', $block, 'bid');
+      
+      // Update the {blocks_roles} entry (if any).
+      $query = db_query("SELECT rid FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta);
+      while ($result = db_fetch_object($query)) {
+        db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta);
+        $record = array(
+          'module' => 'boxes',
+          'delta' => $block->delta,
+          'rid' => $result->rid,
+        );
+        drupal_write_record('blocks_roles', $record);
+      }
+      
+      // Create the {box} record.
+      $block->plugin_key = 'simple';
+      $block->options = array('body' => $block->body, 'format' => $block->format);
+      unset($block->body);
+      unset($block->format);
+      unset($block->bid);
+      drupal_write_record('box', $block);
+      break;
+      
+    case 'boxes':
+      // Load the box information.
+      $box = boxes_load($delta);
+      
+      // Create {boxes} entry.
+      // Bid is autoincremental here, so once we insert we need to make sure
+      // that all deltas match. Luckily drupal_write_record() makes this easy.
+      $boxes = new stdClass();
+      $boxes->info = $box->description;
+      $boxes->body = $box->options['body'];
+      $boxes->format = $box->options['format'];
+      drupal_write_record('boxes', $boxes);
+      $new_delta = $boxes->bid;
+      
+      // Update the {blocks} entry.
+      $blocks = new stdClass();
+      $blocks->bid = db_result(db_query("SELECT bid FROM {blocks} WHERE module = 'boxes' and delta = '%s'", $delta));      
+      $blocks->module = 'block';
+      $blocks->delta = $new_delta;
+      drupal_write_record('blocks', $blocks, 'bid');
+      
+      // Update the {blocks_roles} entry (if any).
+      $query = db_query("SELECT rid FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta);
+      while ($result = db_fetch_object($query)) {
+        db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta);
+        $record = array(
+          'module' => 'block',
+          'delta' => $new_delta,
+          'rid' => $result->rid,
+        );
+        drupal_write_record('blocks_roles', $record);
+      }
+      
+      // Remove the {box} record.
+      db_query("DELETE FROM {box} WHERE delta = '%s'", $delta);
+      break;
+  }
+}
+
+/**
  * Common element of the box fom
  */
 function boxes_box_form($box) {
@@ -296,8 +411,9 @@ function boxes_block_delete_submit($form
  */
 function boxes_form_block_admin_display_form_alter(&$form, $form_state) {
   foreach (element_children($form) as $i) {
-    if ($form[$i]['module']['#value'] == 'boxes') {
-      $delta = $form[$i]['delta']['#value'];
+    $module = $form[$i]['module']['#value'];
+    $delta = $form[$i]['delta']['#value'];
+    if ($module == 'boxes') {
       if (strpos($delta, 'add__') !== 0) {
         $box = boxes_load($delta);
         if (($box->export_type & EXPORT_IN_DATABASE) && ($box->export_type & EXPORT_IN_CODE)) {
@@ -312,6 +428,11 @@ function boxes_form_block_admin_display_
         }
       }
     }
+    // Add convert link.
+    if (($module == 'block' || $module == 'boxes') && strpos($delta, 'add__') !== 0) {
+      $module_opp = $module == 'block' ? 'box' : 'block';
+      $form[$i]['configure']['#value'] .= '|'. l(t('convert to @type', array('@type' => $module_opp)), 'boxes/convert/'. $module .'/'. $delta);
+    }
   }
 }
 
