public function maketbodyrows($query, $rowdesc, $callback=null, &$retresult=false, $delim=false) {
    // $rowdesc is the <tr>...</tr> for this row
    // <tr><td>fieldname</td>...</tr>

    list($result, $num) = $this->query($query, true);
    if(!$num) {
      return false;
    }
      
    if($retresult !== false) $retresult = $result;

    // Set up delimiters

    $rdelimlft = $rdelimrit = "";
    
    if(!$delim) {
      $sdelimlft = $rdelimlft = ">";
      $sdelimrit = $rdelimrit = "<";
    } else {
      if(is_array($delim)) {
        $sdelimlft = $delim[0];
        $sdelimrit = $delim[1];
      } else {
        $sdelimlft = $sdelimrit = $delim;
      }
    }

    $table = ""; // return tbody
    
    while($row = mysql_fetch_assoc($result)) {
      // If $callback then do the callback function. If the callback function returns true (continue) skip row.

      $desc = $rowdesc;
      
      if($callback) {
        // Callback function can modify $row and/or $desc if the callback function has them passed by reference
        // NOTE that $desc does not have the keys replaced with the values yet!!
        if($callback($row, $desc)) {
          continue;
        }
      }

      // Replace the key in the $desc with the value.
      
      foreach($row as $k=>$v) {
        $desc = preg_replace("/{$sdelimlft}{$k}{$sdelimrit}/", "{$rdelimlft}{$v}{$rdelimrit}", $desc);
      }
      $table .= "$desc\n";
    }
    return $table; // on success return the tbody rows
  }