public function table_output($attrib, $table_data, $show_cols, $id_col)
    {
        $table = new html_table($attrib);

        // add table header
        if (!$attrib['noheader']) {
            foreach ($show_cols as $col) {
                $table->add_header($col, $this->Q($this->gettext($col)));
            }
        }

        if (!is_array($table_data)) {
            $db = $this->get_dbh();
            while ($table_data && ($sql_arr = $db->fetch_assoc($table_data))) {
                $table->add_row(array('id' => 'rcmrow' . rcube_utils::html_identifier($sql_arr[$id_col])));

                // format each col
                foreach ($show_cols as $col) {
                    $table->add($col, $this->Q($sql_arr[$col]));
                }
            }
        }
        else {
            foreach ($table_data as $row_data) {
                $class = !empty($row_data['class']) ? $row_data['class'] : null;
                if (!empty($attrib['rowclass']))
                    $class = trim($class . ' ' . $attrib['rowclass']);
                $rowid = 'rcmrow' . rcube_utils::html_identifier($row_data[$id_col]);

                $table->add_row(array('id' => $rowid, 'class' => $class));

                // format each col
                foreach ($show_cols as $col) {
                    $val = is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col];
                    $table->add($col, empty($attrib['ishtml']) ? $this->Q($val) : $val);
                }
            }
        }

        return $table->show($attrib);
    }