<?php
/*******************************************************************************
 *
 * LEIDEN OPEN VARIATION DATABASE (LOVD)
 *
 * Created     : 2007-02-19
 * Modified    : 2012-03-15
 * For LOVD    : 2.0-34
 *
 * Access      : Administrator and managers.
 * Purpose     : Create and manage LOVD custom columns (system wide default
 *               settings).
 *
 * Copyright   : 2004-2012 Leiden University Medical Center; http://www.LUMC.nl/
 * Programmers : Ing. Ivo F.A.C. Fokkema <I.F.A.C.Fokkema@LUMC.nl>
 *               Ir. Gerard C.P. Schaafsma <G.C.P.Schaafsma@LUMC.nl>
 * Last edited : Ing. Ivo F.A.C. Fokkema <I.F.A.C.Fokkema@LUMC.nl>
 *
 *
 * This file is part of LOVD.
 *
 * LOVD is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * LOVD is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LOVD; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *************/

define('ROOT_PATH', './');
require ROOT_PATH . 'inc-init.php';

if (HAS_AUTH) {
    // If authorized, check for updates.
    require ROOT_PATH . 'inc-upgrade.php';
}

// Require manager clearance.
lovd_requireAUTH(LEVEL_MANAGER);





if ($_GET['action'] == 'view_all') {
    // View all cols.

    require ROOT_PATH . 'inc-lib-list.php';
    require ROOT_PATH . 'inc-lib-columns.php';
    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_columns_view_defaults', 'LOVD Setup - View custom column defaults');

    list($nTotal) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_COLS));
    if (!$nTotal) {
        lovd_showInfoTable('There are no custom columns configured in this system.', 'information');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    lovd_showInfoTable('Please note that these are all columns available in this LOVD installation. This is not the list of columns actually added to the system. Also, modifications made to the columns added to the system are not shown.', 'information', 950);

    // Standard query, will be extended later on.
    $sQ = 'SELECT *, (created_by = 0) AS created FROM ' . TABLE_COLS . ' WHERE 1=1';

    // 2008-11-14; 2.0-14; Added by Gerard for searching through the columns list.
    // Here starts the actual building of the query.
    // Implement XSS check on search terms.
    foreach ($_GET as $key => $val) {
        if (!is_array($val) && $val != strip_tags($val)) {
            $_GET[$key] = '';
        }
    }

    // SEARCH: Advanced text search.
    $aSearchText =
         array(
               'search_colid' => 'colid',
               'search_head_column' => 'head_column',
              );

    foreach ($aSearchText as $key => $val) {
        if (isset($_GET[$key]) && trim($_GET[$key])) {
            // 2010; 2.0-28; Allow for searches where the order of words is forced by enclosing the values with double quotes; ["Fokkema et al 2005"] will only
            // return hits with these words in exactly this order while [Fokkema et al 2005] will return hits with all of these words, in whatever order.
            $sSearch = preg_replace_callback('/\\\"([^"]+)\\\"/', create_function('$aRegs', 'return str_replace(\' \', \'{{SPACE}}\', $aRegs[1]);'), trim($_GET[$key]));
            $a = explode(' ', $sSearch);
            foreach ($a as $sTerm) {
                if ($sTerm) {
                    if (substr_count($sTerm, '|') && preg_match('/^[^|]+(\|[^|]+)+$/', $sTerm)) {
                        // OR.
                        $aOR = explode('|', $sTerm);
                        $sQ .= ' AND (';
                        foreach ($aOR as $nTerm => $sTerm) {
                            // 2009-03-03; 2.0-17; Advanced searching did not allow to combine NOT and OR searches.
                            if (substr($sTerm, 0, 1) == '!') {
                                // NOT.
                                $sQ .= ($nTerm? ' OR ' : '') . $val . ' NOT LIKE "%' . lovd_escapeSearchTerm(substr($sTerm, 1)) . '%"';
                            } else {
                                // Common search term.
                                $sQ .= ($nTerm? ' OR ' : '') . $val . ' LIKE "%' . lovd_escapeSearchTerm($sTerm) . '%"';
                            }
                        }
                        $sQ .= ')';
                    } elseif (substr($sTerm, 0, 1) == '!') {
                        // NOT.
                        $sQ .= ' AND ' . $val . ' NOT LIKE "%' . lovd_escapeSearchTerm(substr($sTerm, 1)) . '%"';
                    } else {
                        // Common search term.
                        $sQ .= ' AND ' . $val . ' LIKE "%' . lovd_escapeSearchTerm($sTerm) . '%"';
                    }
                }
            }
        }
    }

    $nResults = mysql_num_rows(mysql_query($sQ));

    // SORT: Current settings.
    if (!empty($_GET['order'])) {
        $aOrder = explode(',', $_GET['order']);
    } else {
        $aOrder = array('', '');
    }

    // SORT: Column data.
    $aOrderList = array('colid' => array('colid', 'ASC'), 'hgvs' => array('hgvs', 'DESC'), 'standard' => array('standard', 'DESC'), 'head_column' => array('head_column', 'ASC'), 'public' => array('public', 'DESC'), 'created' => array('created', 'DESC'));
    if (!array_key_exists($aOrder[0], $aOrderList)) {
        $aOrder[0] = 'colid';
    }
    if ($aOrder[1] != 'ASC' && $aOrder[1] != 'DESC') {
        $aOrder[1] = $aOrderList[$aOrder[0]][1];
    }

    $sQueryLimit = lovd_pagesplitInit(($nResults > 0? $nResults : $nTotal), 25);
    $sQ .= ' ORDER BY ' . $aOrderList[$aOrder[0]][0] . ' ' . $aOrder[1] . ', colid ' . $sQueryLimit;



    // Show form; required for sorting and searching.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '" method="get" style="margin : 0px;">' . "\n" .
          '        <INPUT type="hidden" name="action" value="' . $_GET['action'] . '">' . "\n" .
          '        <INPUT type="hidden" name="order" value="' . implode(',', $aOrder) . '">');

    // 2008-11-14; 2.0-14; Added by Gerard for searching through the columns list.
    if (!$nResults) {
        // Searched, but no results.
        print('      No results have been found that match your criteria.<BR><BR>' . "\n\n");
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    $q = mysql_query($sQ);
    if (!$q) {
        lovd_dbFout('Cols' . ucfirst($_GET['action']), $sQ, mysql_error());
    }

    $n = (isset($nResults)? $nResults : $nTotal);
    print('      <SPAN class="S11">' . $n . ' entr' . ($n == 1? 'y' : 'ies') . '</SPAN><BR>' . "\n");

    // Array which will make up the table (header and data).
    $aTable =
             array(
                    'colid' => array('ID', '*'),
                    'hgvs' => array('HGVS', '60', 'align="center"'),
                    'standard' => array('Standard', '80', 'align="center"'),
                    'head_column' => array('Column heading', '*'),
                    'form_type' => array('Form type', '*'),
                    'public' => array('Public', '60', 'align="center"'),
                    'created' => array('Created by', '90'),
                  );

    // Table.
    print('      <TABLE border="0" cellpadding="0" cellspacing="1" width="950" class="data">' . "\n" .
          '        <TR>');

    // 2008-11-17; 2.0-14; Foreach loop changed by Gerard to add text boxes.
    foreach ($aTable as $sField => $aCol) {
        // Location onclick changed because of the search fields within the same <TH>. Clicking on the field triggers a sort.
        print("\n" . '          <TH valign="top"' . (!empty($aCol[2])? ' ' . $aCol[2] : '') . (is_numeric($aCol[1])? ' width="' . $aCol[1] . '"' : '') . (array_key_exists($sField, $aOrderList)? ' class="order' . ($aOrder[0] == $sField? 'ed' : '') . '"' : '') . '>' .
              (array_key_exists($sField, $aOrderList)? "\n" .
                                                           '            <TABLE border="0" cellpadding="0" cellspacing="0" width="100%" class="S11">' . "\n" .
                                                           '              <TR' . (array_key_exists($sField, $aOrderList)? ' onclick="document.forms[0].order.value=\'' . $sField . ',' . ($aOrder[0] == $sField? ($aOrder[1] == 'ASC'? 'DESC' : 'ASC') : $aOrderList[$sField][1]) . '\';document.forms[0].submit();"' : '') . '>' . "\n" .
                                                           '                <TH>' . str_replace(' ', '&nbsp;', $aCol[0]) . '</TH>' . "\n" .
                                                           '                <TD align="right" width="13"><IMG src="' . ROOT_PATH . 'gfx/order_arrow_desc' . ($aOrder[0] == $sField && $aOrder[1] == 'DESC'? '_sel' : '') . '.png" alt="Descending" title="Descending" width="13" height="6"><BR><IMG src="' . ROOT_PATH . 'gfx/order_arrow_asc' . ($aOrder[0] == $sField && $aOrder[1] == 'ASC'? '_sel' : '') . '.png" alt="Ascending" title="Ascending" width="13" height="6"></TD></TR>' .
                                                           (array_key_exists('search_' . $sField, $aSearchText)? "\n" .
                                                                                         '              <TR>' . "\n" .
                                                                                         '                <TD colspan="3"><INPUT type="text" name="search_' . $sField . '" value="' . (isset($_GET['search_' . $sField])? htmlspecialchars(stripslashes($_GET['search_' . $sField])) : '') . '" title="' . $aCol[0] . ' field should contain..." style="width : ' . ($aCol[1] - 8) . 'px; font-weight : normal;" onchange="document.forms[0].submit();"></TD></TR>' : '') .
                                                           '</TABLE>' : $aCol[0]) . '</TH>');
    }
    print('</TR>');

    while ($zData = mysql_fetch_assoc($q)) {
        print("\n" .
              '        <TR style="cursor : pointer; cursor : hand;" onmouseover="this.className = \'hover\';" onmouseout="this.className = \'\';" onclick="window.location.href = \'' . $_SERVER['PHP_SELF'] . '?action=view&amp;view=' . rawurlencode($zData['colid']) . lovd_showSID(true, true) . '\';">');

        // Put first part of colid in bold.
        $zData['colid']     = '<A href="' . $_SERVER['PHP_SELF'] . '?action=view&amp;view=' . rawurlencode($zData['colid']) . '" class="data">' . preg_replace('/^([[:alnum:]]+)\/(.*)$/', '<B>$1</B>/$2', $zData['colid']) . '</A>';
        $zData['hgvs']      = '<IMG src="' . ROOT_PATH . 'gfx/mark_' . $zData['hgvs'] . '.png" alt="" title="This column is ' . ($zData['hgvs']? '' : 'not ') . 'required by the HGVS standards for sequence variant databases" width="11" height="11">';
        $zData['standard']  = '<IMG src="' . ROOT_PATH . 'gfx/mark_' . $zData['standard'] . '.png" alt="" title="This column is ' . ($zData['standard']? '' : 'not ') . 'enabled by default" width="11" height="11">';
        $zData['form_type'] = lovd_describeFormType($zData);
        $zData['public']    = '<IMG src="' . ROOT_PATH . 'gfx/mark_' . $zData['public'] . '.png" alt="" width="11" height="11">';
        $zData['created']   = ($zData['created']? 'LOVD' : 'LOVD user');

        foreach ($aTable as $sField => $aCol) {
            print("\n" . '          <TD' . (!empty($aCol[2])? ' ' . $aCol[2] : '') . (is_numeric($aCol[1])? ' width="' . $aCol[1] . '"' : '') . ($aOrder[0] == $sField? ' class="ordered"' : '') . '>' . (!$zData[$sField]? '-' : $zData[$sField]) . '</TD>');
        }
        print('</TR>');
    }
    print('</TABLE>' . "\n" .
          '</FORM>' . "\n\n");

    // URL pagelink.
    $sPageLink = 'order=' . rawurlencode(implode(',', $aOrder));

    // 2008-11-17; 2.0-14; added by Gerard; SEARCH: Simple text search.
    foreach ($aSearchText as $key => $val) {
        if (isset($_GET[$key]) && $_GET[$key]) {
            // 2009-04-23; 2.0-18; Added stripslashes to allow search terms to include quotes.
            $sPageLink .= ($sPageLink? '&amp;' : '') . $key . '=' . rawurlencode(stripslashes($_GET[$key]));
        }
    }

    lovd_pagesplitShowNav($sPageLink);

    // 2009-07-10; 2.0-20; Change the default order of the Variant columns for new genes.
    print('      <BUTTON onclick="javascript:lovd_openWindow(\'' . $_SERVER['PHP_SELF'] . '?action=order' . lovd_showSID(true, true) . '\', \'ColOrderDefault\', 550, 375);"' . ($nTotal > 1? '' : ' style="color : #999999;" disabled') . '>Change default column order (for new genes)</BUTTON><BR>' . "\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'view' && !empty($_GET['view'])) {
    // View specific column.

    require ROOT_PATH . 'inc-lib-columns.php';
    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_columns_view_defaults', 'LOVD Setup - View custom column defaults');

    $zData = @mysql_fetch_assoc(mysql_query('SELECT c.*, u_c.name AS created_by_, u_e.name AS edited_by_ FROM ' . TABLE_COLS . ' AS c LEFT OUTER JOIN ' . TABLE_USERS . ' AS u_c ON (c.created_by = u_c.userid) LEFT OUTER JOIN ' . TABLE_USERS . ' AS u_e ON (c.edited_by = u_e.userid) WHERE c.colid = "' . $_GET['view'] . '"'));
    if (!$zData) {
        // Wrong ID, apparently.
        lovd_showInfoTable('No such ID!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Array which will make up the data table.
    $aTable =
             array(
                    'colid' => 'Column ID',
                    'hgvs_' => 'HGVS required column',
                    'standard' => 'Standard',
                    'mandatory' => 'Mandatory',
                    'head_column' => 'Column heading',
                    'description_form' => 'Description on form',
                    'description_legend_short' => 'Description on short legend',
                    'description_legend_full' => 'Description on full legend',
                    'mysql_type' => 'Database type',
                    'form_type' => 'Form type',
                    'select_options' => 'Select options',
                    'preg_pattern' => 'Regular expression pattern',
                    'public' => 'Show to public',
                    'public_form' => 'Show on public form',
                    'allow_count_all' => 'Include in search form',
                    'created_by_' => 'Created by',
                    'created_date' => 'Date created',
                    'edited_by_' => 'Last edited by',
                    'edited_date' => 'Date last edited',
                  );

    // Prepare information for created by column.
    if (!$zData['created_by']) {
        // LOVD custom column.
        $zData['created_by_'] = 'LOVD';
    }

    // Remove unnecessary columns.
    if ($zData['edited_by'] == NULL) {
        // Never been edited.
        unset($aTable['edited_by_'], $aTable['edited_date']);
    }

    // Remove columns based on form type?
    $aFormType = explode('|', $zData['form_type']);
    if ($aFormType[1] != 'select') {
        unset($aTable['select_options']);
    } else {
        unset($aTable['preg_pattern']);
    }

    // Table.
    print('      <TABLE border="0" cellpadding="0" cellspacing="1" width="600" class="data">');

    $zData['hgvs_']           = '<IMG src="' . ROOT_PATH . 'gfx/mark_' . $zData['hgvs'] . '.png" alt="" width="11" height="11">';
    $zData['standard']        = '<IMG src="gfx/mark_' . $zData['standard'] . '.png" alt="" width="11" height="11">';
    $zData['mandatory']       = '<IMG src="gfx/mark_' . $zData['mandatory'] . '.png" alt="" width="11" height="11">';
    $zData['form_type']       = lovd_describeFormType($zData) . '<BR>' . $zData['form_type'];
    $zData['select_options']  = str_replace(array("\r\n", "\r", "\n"), '<BR>', htmlspecialchars($zData['select_options']));
    $zData['public']          = '<IMG src="gfx/mark_' . $zData['public'] . '.png" alt="" width="11" height="11">';
    $zData['public_form']     = '<IMG src="gfx/mark_' . $zData['public_form'] . '.png" alt="" width="11" height="11">';
    $zData['allow_count_all'] = '<IMG src="gfx/mark_' . $zData['allow_count_all'] . '.png" alt="" width="11" height="11">';

    foreach ($aTable as $sField => $sHeader) {
        print("\n" .
              '        <TR>' . "\n" .
              '          <TH valign="top">' . str_replace(' ', '&nbsp;', $sHeader) . '</TH>' . "\n" .
              '          <TD>' . (!$zData[$sField]? '-' : $zData[$sField]) . '</TD></TR>');
    }
    print('</TABLE>' . "\n\n");

    $sNavigation = '';
    // Authorized user (admin or manager) is logged in. Provide tools.
    $sNavigation = '<A href="' . $_SERVER['PHP_SELF'] . '?action=edit&amp;edit=' . rawurlencode($zData['colid']) . '">Edit column default settings</A>';

    // 2008-11-27; 2.0-15; Drop global column. Added by Gerard
    $bSelected = true;
    if (substr($zData['colid'], 0, 7) == 'Variant') {
        // Check genes to find if column is active.
        $aGenes = lovd_getGeneList();
        foreach ($aGenes as $sSymbol) {
            list($bSelected) = mysql_fetch_row(mysql_query('SELECT colid FROM ' . TABLEPREFIX . '_' . $sSymbol . '_columns WHERE colid = "' . $zData['colid'] . '"'));
            if ($bSelected) {
                // Column present in this gene.
                break;
            }
        }
    } elseif (substr($zData['colid'], 0, 7) == 'Patient') {
        // Patient column.
        list($bSelected) = mysql_fetch_row(mysql_query('SELECT colid FROM ' . TABLE_PATIENTS_COLS . ' WHERE colid = "' . $zData['colid'] . '"'));
    }

    if ($zData['created_by'] && !$bSelected) {
        $sNavigation .= ' | <A href="' . $_SERVER['PHP_SELF'] . '?action=edit_colid&amp;edit_colid=' . rawurlencode($zData['colid']) . '">Edit column ID</A>';
        $sNavigation .= ' | <A href="' . $_SERVER['PHP_SELF'] . '?action=drop&amp;drop=' . rawurlencode($zData['colid']) . '">Delete column</A>';
    } else {
        $sNavigation .= ' | <A style="color : #999999;">Edit column ID</A>';
        $sNavigation .= ' | <A style="color : #999999;">Delete column</A>';
    }
    if ($sNavigation) {
        print('      <IMG src="gfx/trans.png" alt="" width="1" height="5"><BR>' . "\n");
        lovd_viewNavigation($sNavigation);
    }

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'order') {
    // 2009-07-10; 2.0-20; Change the default order of the Variant columns for new genes.
    // Change column order.

    $qData = mysql_query('SELECT colid, CONCAT(colid, " (", head_column, ")") AS name FROM ' . TABLE_COLS . ' WHERE LEFT(colid, 8) = "Variant/" AND (hgvs = 1 OR standard = 1) ORDER BY col_order');
    $nData = mysql_num_rows($qData);

    if (!$nData) {
        // Can this actually happen?
        require ROOT_PATH . 'inc-top-clean.php';
        lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
        lovd_showInfoTable('There are no custom columns!', 'information');
        require ROOT_PATH . 'inc-bot-clean.php';
        exit;
    }

    if (isset($_GET['sent']) && count($_POST['columns']) == $nData) {
        foreach ($_POST['columns'] as $nOrderID => $sColID) {
            // Query text.
            $sQ = 'UPDATE ' . TABLE_COLS . ' SET col_order = ' . $nOrderID . ' WHERE colid = "' . $sColID . '"';

            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top-clean.php';
                lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
                lovd_dbFout('ColOrderDefault' . str_pad($nOrderID + 1, 2, '0', STR_PAD_LEFT), $sQ, $sError);
                require 'inc-bot-clean.php';
                exit;
            }
        }

        // Thank the user...
        require ROOT_PATH . 'inc-top-clean.php';
        lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
        print('      Default column order has successfully been set!<BR><BR>' . "\n\n");
        print('      <SCRIPT type="text/javascript">' . "\n" .
              '        <!--' . "\n" .
              '        setTimeout("self.close()", 1000);' . "\n" .
              '        // --> ' . "\n" .
              '      </SCRIPT>' . "\n");

        require ROOT_PATH . 'inc-bot-clean.php';
        exit;
    }



    require ROOT_PATH . 'inc-top-clean.php';
    lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
    lovd_showInfoTable('These are all default Variant columns, which will be added to new genes. You can control this by setting or unsetting the "Standard for new genes" checkbox on the "Edit column default settings" form.', 'information');

    $nData = ($nData > 15? 15 : ($nData < 6? 6 : $nData));

    print('      <SCRIPT type="text/javascript" src="inc-js-columnsort.js"></SCRIPT>' . "\n\n");
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;sent=true" method="post" onsubmit="javascript:lovd_orderSubmit()">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="0">' . "\n" .
          '          <TR>' . "\n" .
          '            <TD valign="top" rowspan="2">' . "\n" .
          '              <SELECT name="columns[]" multiple size="' . $nData . '" id="select_order">' . "\n");

    while ($zData = mysql_fetch_array($qData)) {
        print('            <OPTION value="' . $zData['colid'] . '">' . $zData['name'] . '</OPTION>' . "\n");
    }

    print('              </SELECT></TD>' . "\n" .
          '            <TD valign="top"><A href="#" onclick="lovd_orderHome(); return false;"><IMG src="gfx/order_button_home.png" alt="Top" width="24" height="24" id="butHome" border="0" onmouseover="lovd_imageSwitch(\'butHome\', \'H\');" onmouseout="lovd_imageSwitch(\'butHome\', \'B\');"></A><BR><A href="#" onclick="lovd_orderUp(); return false;"><IMG src="gfx/order_button_up.png" alt="Up" width="24" height="24" id="butUp" border="0" onmouseover="lovd_imageSwitch(\'butUp\', \'H\');" onmouseout="lovd_imageSwitch(\'butUp\', \'B\');"></A></TD></TR>' . "\n" .
          '          <TR>' . "\n" .
          '            <TD valign="bottom"><A href="#" onclick="lovd_orderDown(); return false;"><IMG src="gfx/order_button_down.png" alt="Down" width="24" height="24" id="butDown" border="0" onmouseover="lovd_imageSwitch(\'butDown\', \'H\');" onmouseout="lovd_imageSwitch(\'butDown\', \'B\');"></A><BR><A href="#" onclick="lovd_orderEnd(); return false;"><IMG src="gfx/order_button_end.png" alt="Bottom" width="24" height="24" id="butEnd" border="0" onmouseover="lovd_imageSwitch(\'butEnd\', \'H\');" onmouseout="lovd_imageSwitch(\'butEnd\', \'B\');"></A></TD></TR></TABLE>' . "\n" .
          '        <INPUT type="submit" value="Change column order"><BR>' . "\n" .
          '      </FORM>' . "\n");

    require ROOT_PATH . 'inc-bot-clean.php';
    exit;





} elseif ($_GET['action'] == 'form_type_define') {
    // Show form type forms and send info back.

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';

    // Step 1: Choose column form type.
    if (empty($_POST['form_type'])) {
        // Choose from the form types, and continue.

        require ROOT_PATH . 'inc-top-clean.php';
        lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');

        if (isset($_GET['from_action']) && $_GET['from_action'] == 'edit') {
            // Got action from form, specifically for this!
            lovd_showInfoTable('Please note that changing the data type of an existing column causes a risk of loosing data!', 'warning');
        }

        // Table.
        print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '" method="post">' . "\n" .
              '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

        // If we've been here before, select last used option.
        if (!empty($_SESSION['form_type']['form_type'])) {
            $_POST['form_type'] = $_SESSION['form_type']['form_type'];
        }

        // Form types.
        // 2009-06-11; 2.0-19; Added decimal and date input fields.
        $aTypes =
                 array(
                        'text' => 'Text/numeric input field',
                        'int' => 'Integer input field',
                        'dec' => 'Decimal input field',
                        'textarea' => 'Large multi-row textual input field',
                        'select' => 'Drop down list (one option selected)',
                        'select_multiple' => 'Selection list (multiple options selected)',
                        'date' => 'Date input field',
                        'checkbox' => 'On/off checkbox',
                      );

        // Array which will make up the form table.
        $aForm = array(
                        array('POST', '', '', '30%', '70%'),
                        array('', 'print', '<B>Select custom column\'s form style</B>'),
                        array('Basic form style', 'select', 'form_type', 1, $aTypes, false, false, false),
                        array('', 'print', '<SPAN class="form_note">This is the type of field your custom column will appear on the input forms, such as the submission form.</SPAN>'),
                        'skip',
                        array('', 'submit', 'Next &raquo;'),
                      );
        $_MODULES->processForm('SetupColumnsGlobalFormTypeStyle', $aForm);
        lovd_viewForm($aForm);

        print('</TABLE></FORM>' . "\n\n");

        require ROOT_PATH . 'inc-bot-clean.php';
        exit;
    }

    // Store in SESSION.
    $_SESSION['form_type']['form_type'] = $_POST['form_type'];



    // Step 2: Gather options.
    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // Mandatory fields.
        $aCheckM =
                 array(
                        'name' => 'Column name on form',
                      );

        // Numeric fields.
        $aCheckN = array();

        // Mandatory and Numeric fields depend on column type.
        // 2009-06-11; 2.0-19; Added decimal and date input field.
        switch ($_POST['form_type']) {
            case 'text':
                $aCheckM['size'] = 'Width on form (characters)';
                $aCheckM['maxlength'] = 'Maximum input length (characters)';
                $aCheckN['size'] = 'Width on form (characters)';
                $aCheckN['maxlength'] = 'Maximum input length (characters)';
                break;
            case 'int':
                $aCheckM['size'] = 'Width on form (characters)';
                $aCheckM['maxlength'] = 'Maximum input length (characters)';
                $aCheckN['size'] = 'Width on form (characters)';
                $aCheckN['maxlength'] = 'Maximum input length (characters)';
                $aCheckN['default_val'] = 'Default value (optional)';
                break;
            case 'dec':
                $aCheckM['size'] = 'Width on form (characters)';
                $aCheckM['maxlength'] = 'Number of digits before the decimal point';
                $aCheckM['scale'] = 'Number of digits following the decimal point';
                $aCheckN['size'] = 'Width on form (characters)';
                $aCheckN['maxlength'] = 'Number of digits before the decimal point';
                $aCheckN['scale'] = 'Number of digits following the decimal point';
                $aCheckN['default_val'] = 'Default value (optional)';
                break;
            case 'date':
                $aCheckM['size'] = 'Width on form (characters)';
                $aCheckN['size'] = 'Width on form (characters)';
                break;
            case 'textarea':
                $aCheckM['cols'] = 'Width on form (characters)';
                $aCheckM['rows'] = 'Height on form (lines)';
                $aCheckN['cols'] = 'Width on form (characters)';
                $aCheckN['rows'] = 'Height on form (lines)';
                break;
            case 'select':
                $aCheckM['select_options'] = 'List of possible options';
                break;
            case 'select_multiple':
                $aCheckM['rows'] = 'Height on form (lines)';
                $aCheckM['select_options'] = 'List of possible options';
                $aCheckN['rows'] = 'Height on form (lines)';
                break;
        }

        // Mandatory fields...
        foreach ($aCheckM as $key => $val) {
            if (empty($_POST[$key])) {
                lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
            }
        }

        // Numeric fields...
        // 2009-06-17; 2.0-19; Default values are allowed to contain negative numbers!
        foreach ($aCheckN as $key => $val) {
            if ($_POST[$key]) {
                if ($_POST[$key] < 0 && ($key != 'default_val' || $_POST['unsigned'])) {
                    lovd_errorAdd('The \'' . $val . '\' field has to contain a positive numeric value.');
                } elseif (!is_numeric($_POST[$key])){
                    lovd_errorAdd('The \'' . $val . '\' field has to contain a numeric value.');
                }
            }
        }

        // FIXME; add proper check on proper PHP Perl-compatible regexp syntax.
        // Check regexp syntax.
        // 2009-01-30; 2.0-15; Wrong field name was printed here.
        if (!empty($_POST['preg_pattern']) && !preg_match('/^\/.+\/[imsxeADSUXu]*$/', $_POST['preg_pattern'])) {
            lovd_errorAdd('The \'Regular expression pattern\' field does not seem to contain valid PHP Perl compatible regexp syntax.');
        }

        // Select_options.
        if (!empty($_POST['select_options'])) {
            $aOptions = explode("\r\n", $_POST['select_options']);
            foreach ($aOptions as $n => $sOption) {
                if (!preg_match('/^([^=]+|[A-Z0-9 \/\()?._+-]+ *= *[^=]+)$/i', $sOption)) {
                    // 2009-02-16; 2.0-16; Added stripslashes().
                    lovd_errorAdd('Select option #' . ($n + 1) . ' &quot;' . htmlspecialchars(stripslashes($sOption)) . '&quot; not understood.');
                }
            }
        }

        // 2009-02-24; 2.0-16; Introducing default values.
        if ($_POST['form_type'] == 'text' && $_POST['default_val'] && !preg_match('/^[^"]*$/', $_POST['default_val'])) {
            lovd_errorAdd('The \'Default value\' field can not contain a quote.');
        }

        // 2009-06-18; 2.0-19; Check the format of the default value for the DATE/DATETIME column types.
        if ($_POST['form_type'] == 'date') {
            if (!lovd_matchDate($_POST['default_val'], $_POST['time'])) {
                lovd_errorAdd('The \'Default value\' for the date field should be like YYYY-MM-DD' . ($_POST['time'] ? ' HH:MM:SS.' : '.'));
            }
        }

        if (!lovd_error()) {
            // Build proper values and send them through.
            $sMySQLType = '';
            $sFormType = '';
            $sPregPattern = '';

            // Store vars in $_SESSION...
            $aStore = array('name', 'size', 'maxlength', 'scale', 'preg_pattern', 'unsigned', 'default_val', 'cols', 'rows', 'select', 'select_options', 'select_all');
            foreach ($aStore as $val) {
                if (!isset($_POST[$val])) {
                    $_POST[$val] = '';
                }
                // 2009-02-16; 2.0-16; Fix added slashes when running the data type wizard consecutively.
                $_SESSION['form_type'][$val] = stripslashes($_POST[$val]);
            }

            // Thank the user...
            require ROOT_PATH . 'inc-top-clean.php';
            lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
            print('      Done! Gathering info and sending you through to the form...<BR><BR>' . "\n\n");

            // MySQL and Form type.
            switch ($_POST['form_type']) {
                case 'text':
                    if ($_POST['maxlength'] > 255) {
                        $sMySQLType = 'TEXT';
                    } else {
                        $sMySQLType = 'VARCHAR(' . $_POST['maxlength'] . ')';
                    }
                    $sFormType = $_POST['name'] . '|text|' . $_POST['size'];
                    $sPregPattern = $_POST['preg_pattern'];
                    break;
                case 'int':
                    if ($_POST['maxlength'] < 3) {
                        $sMySQLType = 'TINY';
                    } elseif ($_POST['maxlength'] < 5) {
                        $sMySQLType = 'SMALL';
                    } elseif ($_POST['maxlength'] < ($_POST['unsigned']? 8 : 7)) {
                        $sMySQLType = 'MEDIUM';
                    } elseif ($_POST['maxlength'] < 10) {
                        $sMySQLType = '';
                    } else {
                        $sMySQLType = 'BIG';
                    }
                    if ($_POST['unsigned']) {
                        $sMySQLType .= 'INT(' . ($_POST['maxlength'] > 19? 19 : $_POST['maxlength']) . ') UNSIGNED';
                    } else {
                        $sMySQLType .= 'INT(' . ($_POST['maxlength'] > 18? 18 : $_POST['maxlength']) . ')';
                    }
                    $sFormType = $_POST['name'] . '|text|' . $_POST['size'];
                    break;
                case 'dec':
                    // 2009-06-11; 2.0-19; Added DEC, DATE and DATETIME types.
                    $_POST['maxlength'] += $_POST['scale']; // Maxlength was number of digits before the decimal point.
                    $sMySQLType = 'DEC(' . ($_POST['maxlength'] > 65? 65 : $_POST['maxlength']) . ',' . $_POST['scale'] . ')' . ($_POST['unsigned']? ' UNSIGNED' : '');
                    $sFormType = $_POST['name'] . '|text|' . $_POST['size'];
                    break;
                case 'date':
                    $sMySQLType = 'DATE' . ($_POST['time']? 'TIME' : '');
                    $sFormType = $_POST['name'] . '|text|' . $_POST['size'];
                    break;
                case 'textarea':
                    $sMySQLType = 'TEXT';
                    $sFormType = $_POST['name'] . '|textarea|' . $_POST['cols'] . '|' . $_POST['rows'];
                    break;
                case 'select':
                    // Don't bother to check the maximum value length.
                    // By the way, one could change the select_options without
                    // changing the MySQL type (Variant columns).
                    $sMySQLType = 'VARCHAR(75)';
                    $sFormType = $_POST['name'] . '|select|1|' . ($_POST['select']? 'true' : 'false') . '|false|false';
                    break;
                case 'select_multiple':
                    $sMySQLType = 'TEXT';
                    $sFormType = $_POST['name'] . '|select|' . $_POST['rows'] . '|false|true|' . ($_POST['select_all']? 'true' : 'false');
                    break;
                case 'checkbox':
                    $sMySQLType = 'TINYINT(1) UNSIGNED';
                    // FIXME; allow option to choose from V or X?
                    $sFormType = $_POST['name'] . '|checkbox|1';
                    break;
            }

            // 2009-02-16; 2.0-16; Introducing default values.
            if (in_array($_POST['form_type'], array('text', 'int', 'dec', 'date')) && $_POST['default_val']) {
                $sMySQLType .= ' DEFAULT "' . $_POST['default_val'] . '"';
            }

            // Pass it on to the opener...
            // 2008-02-14; 2.0-04; Do not quote this data, it's from $_POST and has already been magicQuoted.
            print('      <SCRIPT type="text/javascript">' . "\n" .
                  '        <!--' . "\n" .
                  '        opener.document.forms[0][\'mysql_type\'].value = \'' . $sMySQLType . '\';' . "\n" .
                  '        opener.document.forms[0][\'form_type\'].value = \'' . $sFormType . '\';' . "\n" .
                  '        opener.document.forms[0][\'preg_pattern\'].value = \'' . $sPregPattern . '\';' . "\n" .
                  '        opener.document.forms[0][\'select_options\'].value = \'' . (!empty($_POST['select_options'])? str_replace(array("\r\n", "\r", "\n"), array('\r\n', '\r', '\n'), $_POST['select_options']) : '') . '\';' . "\n" .
                  '        self.close();' . "\n" .
                  '        // -->' . "\n" .
                  '      </SCRIPT>' . "\n\n");

            // Script up there should suffice actually...
            print('      <BUTTON onclick="javascript:self.close();">Close window</BUTTON><BR>' . "\n\n");

            require ROOT_PATH . 'inc-bot-clean.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password']);
        }

    } else {
        // Default values.
        $_POST['name'] = $_SESSION['form_type']['name'];

        switch ($_POST['form_type']) {
            case 'text':
                $_POST['size'] = ($_SESSION['form_type']['size']? $_SESSION['form_type']['size'] : '30');
                $_POST['maxlength'] = ($_SESSION['form_type']['maxlength']? $_SESSION['form_type']['maxlength'] : '255');
                $_POST['preg_pattern'] = ($_SESSION['form_type']['preg_pattern']? $_SESSION['form_type']['preg_pattern'] : '');
                $_POST['default_val'] = ($_SESSION['form_type']['default_val']? $_SESSION['form_type']['default_val'] : '');
                break;
            case 'int':
                $_POST['size'] = ($_SESSION['form_type']['size']? $_SESSION['form_type']['size'] : '10');
                $_POST['maxlength'] = ($_SESSION['form_type']['maxlength']? $_SESSION['form_type']['maxlength'] : '8');
                $_POST['unsigned'] = ($_SESSION['form_type']['unsigned']? $_SESSION['form_type']['unsigned'] : '0');
                $_POST['default_val'] = ($_SESSION['form_type']['default_val']? $_SESSION['form_type']['default_val'] : '');
                break;
            case 'dec':
                // 2009-06-11; 2.0-19; Added dec and date datatypes.
                $_POST['size'] = ($_SESSION['form_type']['size']? $_SESSION['form_type']['size'] : '10');
                $_POST['maxlength'] = ($_SESSION['form_type']['maxlength']? $_SESSION['form_type']['maxlength'] : '5');
                $_POST['scale'] = ($_SESSION['form_type']['scale']? $_SESSION['form_type']['scale'] : '2');
                $_POST['unsigned'] = ($_SESSION['form_type']['unsigned']? $_SESSION['form_type']['unsigned'] : '0');
                $_POST['default_val'] = ($_SESSION['form_type']['default_val']? $_SESSION['form_type']['default_val'] : '');
                break;
            case 'date':
                $_POST['size'] = ($_SESSION['form_type']['size']? $_SESSION['form_type']['size'] : '20');
                $_POST['default_val'] = ($_SESSION['form_type']['default_val']? $_SESSION['form_type']['default_val'] : '');
                break;
            case 'textarea':
                $_POST['cols'] = ($_SESSION['form_type']['cols']? $_SESSION['form_type']['cols'] : '40');
                $_POST['rows'] = ($_SESSION['form_type']['rows']? $_SESSION['form_type']['rows'] : '4');
                break;
            case 'select':
                $_POST['select'] = ($_SESSION['form_type']['select']? $_SESSION['form_type']['select'] : '1');
                $_POST['select_options'] = ($_SESSION['form_type']['select_options']? $_SESSION['form_type']['select_options'] : '');
                break;
            case 'select_multiple':
                $_POST['rows'] = ($_SESSION['form_type']['rows']? $_SESSION['form_type']['rows'] : '4');
                $_POST['select_all'] = ($_SESSION['form_type']['select_all']? $_SESSION['form_type']['select_all'] : '0');
                $_POST['select_options'] = ($_SESSION['form_type']['select_options']? $_SESSION['form_type']['select_options'] : '');
                break;
        }
    }



    require ROOT_PATH . 'inc-top-clean.php';
    lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;sent=true" method="post">' . "\n" .
          '        <INPUT type="hidden" name="form_type" value="' . $_POST['form_type'] . '">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '40%', '60%'),
                    array('', 'print', '<B>Column options</B>'),
                    array('Column name on form', 'text', 'name', 30),
                  );

    // Form depends on chosen form type.
    switch ($_POST['form_type']) {
        case 'text':
            $aForm[] = array('Width on form (characters)', 'text', 'size', 5);
            $aForm[] = array('Maximum input length (characters)', 'text', 'maxlength', 5);
            $aForm[] = array('Regular expression pattern (optional)', 'text', 'preg_pattern', 50);
            $aForm[] = array('', 'print', '<SPAN class="form_note">Note: for advanced users only. Type in a full regular expression pattern (PHP\'s Perl-compatible regexp syntax), including \'/\' delimiters and possible modifiers. Make sure it\'s valid, otherwise you risk getting all input rejected.</SPAN>');
            $aForm[] = array('Default value (optional)', 'text', 'default_val', 20);
            break;
        case 'int':
            $aForm[] = array('Width on form (characters)', 'text', 'size', 5);
            $aForm[] = array('Maximum input length (characters)', 'text', 'maxlength', 5);
            $aForm[] = array('Allow only positive values', 'checkbox', 'unsigned', 1);
            $aForm[] = array('Default value (optional)', 'text', 'default_val', 5);
            break;
        case 'dec':
            // 2009-06-15; 2.0-19; Added dec and date datatypes.
            $aForm[] = array('Width on form (characters)', 'text', 'size', 5);
            $aForm[] = array('Number of digits before the decimal point', 'text', 'maxlength', 5);
            $aForm[] = array('Number of digits following the decimal point', 'text', 'scale', 5);
            $aForm[] = array('Allow only positive values', 'checkbox', 'unsigned', 1);
            $aForm[] = array('Default value (optional)', 'text', 'default_val', 5);
            break;
        case 'date':
            $aForm[] = array('Width on form (characters)', 'text', 'size', 5);
            $aForm[] = array('Also store time?', 'checkbox', 'time', 1);
            $aForm[] = array('Default value (optional)', 'text', 'default_val', 20);
            $aForm[] = array('', 'print', '<SPAN class="form_note">YYYY-MM-DD or YYYY-MM-DD HH:MM:SS.</SPAN>');
            break;
        case 'textarea':
            $aForm[] = array('Width on form (characters)', 'text', 'cols', 5);
            $aForm[] = array('Height on form (lines)', 'text', 'rows', 5);
            break;
        case 'select':
            $aForm[] = array('Provide "-- select --" option', 'checkbox', 'select', 1);
            $aForm[] = array('', 'print', '<SPAN class="form_note">This will add an option called "-- select --" that will be regarded as an empty value.</SPAN>');
            $aForm[] = array('List of possible options', 'print', '<TEXTAREA name="select_options" cols="70" rows="5" class="S11">' . $_POST['select_options'] . '</TEXTAREA>');
            $aForm[] = array('', 'print', '<SPAN class="form_note">This is used to build the available options for the selection list.<BR>One option per line.<BR>If you want to use abbreviations, use: Abbreviation = Long name<BR>Example: &quot;DMD = Duchenne Muscular Dystrophy&quot;</SPAN>');
            break;
        case 'select_multiple':
            $aForm[] = array('Height on form (lines)', 'text', 'rows', 5);
            $aForm[] = array('Provide "select all" link', 'checkbox', 'select_all', 1);
            $aForm[] = array('', 'print', '<SPAN class="form_note">This will add a link next to the selection list that allows the user to instantly select all available options.</SPAN>');
            $aForm[] = array('List of possible options', 'print', '<TEXTAREA name="select_options" cols="70" rows="5" class="S11">' . $_POST['select_options'] . '</TEXTAREA>');
            $aForm[] = array('', 'print', '<SPAN class="form_note">This is used to build the available options for the selection list.<BR>One option per line.<BR>If you want to use abbreviations, use: Abbreviation = Long name<BR>Example: &quot;DMD = Duchenne Muscular Dystrophy&quot;</SPAN>');
            break;
    }

    $aForm[] = 'skip';
    $aForm[] = array('', 'submit', 'Finish');
    $_MODULES->processForm('SetupColumnsGlobalFinish', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot-clean.php';
    exit;





} elseif ($_GET['action'] == 'create') {
    // Create brand new custom column.

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';

    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // Mandatory fields.
        $aCheck =
                 array(
                        'col_cat' => 'Category',
                        'colid' => 'Column ID',
                        'head_column' => 'Column heading',
                        'description_legend_short' => 'Description on short legend',
                        'description_legend_full' => 'Description on full legend',
                        'mysql_type' => 'MySQL data type',
                        'form_type' => 'Form type',
                        'password' => 'Enter your password for authorization',
                      );

        foreach ($aCheck as $key => $val) {
            if (empty($_POST[$key])) {
                lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
            }
        }

        // ColID format.
        if ($_POST['colid'] && !preg_match('/^[A-Za-z0-9_]+(\/[A-Za-z0-9_]+)*$/', $_POST['colid'])) {
            lovd_errorAdd('The column ID is not of the correct format. It can contain only letters, numbers and underscores. Subcategories must be devided by a slash (/).');
        }

        // ColID must not exist in the database.
        if ($_POST['col_cat'] && $_POST['colid']) {
            list($n) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_COLS . ' WHERE colid = "' . $_POST['col_cat'] . '/' . $_POST['colid'] . '"'));
            if ($n) {
                lovd_errorAdd('There is already a ' . $_POST['col_cat'] . ' column with this column ID. Please choose another one.');
            }
        }

        // FIXME; are we just assuming that select_options, preg_pattern and form_format are OK?

        // MySQL type format.
        // 2009-02-16; 2.0-16; Allow for input of default values using "DEFAULT ..."
        // 2009-06-11; 2.0-19; Added DEC, DATE and DATETIME types.
        if ($_POST['mysql_type'] && !preg_match('/^(TEXT|VARCHAR\([0-9]{1,3}\)|DATE(TIME)?|((TINY|SMALL|MEDIUM|BIG)?INT\([0-9]{1,2}\)|DEC\([0-9]{1,2}\,[0-9]{1,2}\))( UNSIGNED)?)( DEFAULT ([0-9]+|"[^"]+"))?$/i', stripslashes($_POST['mysql_type']))) {
            lovd_errorAdd('The MySQL data type is not recognized. Please use the data type wizard to generate a proper MySQL data type.');
        }

        // User had to enter his/her password for authorization.
        if ($_POST['password'] && md5($_POST['password']) != $_AUTH['password']) {
            lovd_errorAdd('Please enter your correct password for authorization.');
        }

        if (!lovd_error()) {
            // Query text.
            $sQ = 'INSERT INTO ' . TABLE_COLS . ' VALUES (';

            $_POST['colid'] = $_POST['col_cat'] . '/' . $_POST['colid'];
            $_POST['col_order'] = 0;
            $_POST['hgvs'] = '0';

            // Standard fields to be used.
            $aQ = array('colid', 'col_order', 'hgvs', 'standard', 'mandatory', 'head_column', 'description_form', 'description_legend_short', 'description_legend_full', 'mysql_type', 'form_type', 'select_options', 'preg_pattern', 'public', 'public_form', 'allow_count_all');

            foreach ($aQ as $key => $val) {
                $sQ .= ($key? ', ' : '') . '"' . $_POST[$val] . '"';
            }

            $sQ .= ', ' . $_AUTH['userid'] . ', NOW(), NULL, NULL)';

            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('setup_columns_create', 'LOVD Setup - Create new custom column');
                lovd_dbFout('ColCreate', $sQ, $sError);
            }

            // 2008-12-01; 2.0-15; Add links. added by Gerard
            // To prevent errors to show up on screen.
            if (!isset($_POST['active_links'])) {
                $_POST['active_links'] = array();
            }

            $aLinks = array();
            foreach ($_POST['active_links'] as $nLinkID) {
                list($sLinkName) = @mysql_fetch_row(mysql_query('SELECT linkname FROM ' . TABLE_LINKS . ' WHERE linkid = "' . $nLinkID . '"'));
                $aLinks[$nLinkID] = $sLinkName;
            }

            foreach ($aLinks AS $nLinkID => $sLinkName) {
                $q = mysql_query('INSERT INTO ' . TABLE_COLS2LINKS . ' VALUES ("' . $_POST['colid'] . '", "' . $nLinkID . '")');
                if (!$q) {
                    // Silent error.
                    lovd_writeLog('MySQL:Error', 'ColCreate', 'Custom link ' . $nLinkID . ' (' . $sLinkName . ') could not be added to ' . $_POST['colid']);
                } else {
                    lovd_writeLog('MySQL:Event', 'ColCreate', 'Custom link ' . $nLinkID . ' (' . $sLinkName . ') successfully added to ' . $_POST['colid']);
                }
            }

            // Clean up...
            $_SESSION['form_type'] = array();

            // Write to log...
            lovd_writeLog('MySQL:Event', 'ColCreate', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully created column ' . $_POST['colid'] . ' (' . $_POST['head_column'] . ')');

            // Thank the user...
            header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view&view=' . rawurlencode($_POST['colid']) . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('setup_columns_create', 'LOVD Setup - Create new custom column');
            print('      Column "' . $_POST['head_column'] . '" has successfully been created!<BR><BR>' . "\n\n");

            require ROOT_PATH . 'inc-bot.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password']);
        }

    } else {
        // Default values.
        $_POST['public'] = 1;
        $_POST['public_form'] = 1;
        $_POST['allow_count_all'] = 1;
        $_POST['select_options'] = '';
        $_POST['preg_pattern'] = '';

        // Default data type information, loaded in SESSION.
        $_SESSION['form_type'] =
                 array(
                        'form_type' => '',
                        'name' => '',
                        'size' => '',
                        'maxlength' => '',
                        'scale' => '',
                        'preg_pattern' => '',
                        'unsigned' => '',
                        'default_val' => '',
                        'cols' => '',
                        'rows' => '',
                        'select' => '',
                        'select_options' => '',
                        'select_all' => '',
                      );
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_columns_create', 'LOVD Setup - Create new custom column');

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;sent=true" method="post">' . "\n" .
          '        <INPUT type="hidden" name="select_options" value="' . $_POST['select_options'] . '">' . "\n" .
          '        <INPUT type="hidden" name="preg_pattern" value="' . $_POST['preg_pattern'] . '">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Get links list, to connect column to link.
    $aLinks = array();
    $qLinks = mysql_query('SELECT linkid, linkname FROM ' . TABLE_LINKS . ' ORDER BY linkname');
    $nLinks = mysql_num_rows($qLinks);
    $nLinkSize = ($nLinks < 10? $nLinks : 10);
    while ($r = mysql_fetch_row($qLinks)) {
        $aLinks[$r[0]] = $r[1];
    }

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '50%', '50%'),
                    array('', 'print', '<B>Column name and descriptions</B>'),
                    array('Category', 'select', 'col_cat', 1, array('Patient' => 'Patient', 'Variant' => 'Variant'), true, false, false),
                    array('Column ID', 'text', 'colid', 30),
                    array('', 'print', '<SPAN class="form_note">This ID must be unique and may contain only letters, numbers and underscores. Subcategories must be divided by a slash (/), such as \'Phenotype/Disease\'.<BR>Do NOT add \'Patient/\' or \'Variant/\' here.</SPAN>'),
                    array('Column heading', 'text', 'head_column', 30),
                    array('', 'print', '<SPAN class="form_note">This will appear above the column on data listings and the legend.</SPAN>'),
                    array('Description on form', 'textarea', 'description_form', 40, 2),
                    array('Description on short legend', 'textarea', 'description_legend_short', 40, 2),
                    array('Description on full legend', 'textarea', 'description_legend_full', 40, 2),
                    'skip',
                    array('', 'print', '<B>Data settings</B> (Use data type wizard to change values)'),
                    array('', 'print', '<BUTTON type="button" onclick="javascript:lovd_openWindow(\'' . $_SERVER['PHP_SELF'] . '?action=form_type_define&amp;from_action=' . $_GET['action'] . lovd_showSID(true, true) . '\', \'FormTypeDefine\', 800, 400); return false;">Start data type wizard</BUTTON>'),
                    array('MySQL data type', 'text', 'mysql_type', 30),
                    array('Form type', 'text', 'form_type', 30),
                    'skip',
                    array('', 'print', '<B>Column settings</B>'),
                    array('Standard for new genes (Variant columns only)', 'checkbox', 'standard', 1),
                    array('Mandatory field', 'checkbox', 'mandatory', 1),
                    array('Show contents to public', 'checkbox', 'public', 1),
                    array('Show field on public forms', 'checkbox', 'public_form', 1),
                    array('Include in search form', 'checkbox', 'allow_count_all', 1),
                    array('', 'print', '<SPAN class="form_note">Selecting this checkbox allows the public to find the number of entries in the database (including hidden entries) matching one or more search terms on this column.</SPAN>'),
                    'skip',
                    array('', 'print', '<B>Link settings</B>'),
                    array('Active custom links', 'select', 'active_links', $nLinkSize, $aLinks, false, true, false),
                    'skip',
                    array('Enter your password for authorization', 'password', 'password', 20),
                    array('', 'submit', 'Create column'),
                  );
    $_MODULES->processForm('SetupColumnsGlobalCreate', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'edit' && !empty($_GET['edit'])) {
    // Edit specific custom column.

    $zData = @mysql_fetch_assoc(mysql_query('SELECT * FROM ' . TABLE_COLS . ' WHERE colid = "' . $_GET['edit'] . '"'));
    if (!$zData) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
        lovd_showInfoTable('No such ID!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';

    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // Mandatory fields.
        $aCheck =
                 array(
                        'head_column' => 'Column heading',
                        'description_legend_short' => 'Description on short legend',
                        'description_legend_full' => 'Description on full legend',
                        'mysql_type' => 'MySQL data type',
                        'form_type' => 'Form type',
                        'password' => 'Enter your password for authorization',
                      );

        foreach ($aCheck as $key => $val) {
            if (empty($_POST[$key])) {
                lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
            }
        }

        // FIXME; are we just assuming that select_options, preg_pattern and form_format are OK?

        // MySQL type format.
        // 2009-02-16; 2.0-16; Allow for input of default values using "DEFAULT ..."
        // 2009-06-16; 2.0-19; Added DEC, DATE and DATETIME types.
        if ($_POST['mysql_type'] && !preg_match('/^(TEXT|VARCHAR\([0-9]{1,3}\)|DATE(TIME)?|((TINY|SMALL|MEDIUM|BIG)?INT\([0-9]{1,2}\)|DEC\([0-9]{1,2}\,[0-9]{1,2}\))( UNSIGNED)?)( DEFAULT ([0-9]+|"[^"]+"))?$/i', stripslashes($_POST['mysql_type']))) {
            lovd_errorAdd('The MySQL data type is not recognized. Please use the data type wizard to generate a proper MySQL data type.');
        }

        // User had to enter his/her password for authorization.
        if ($_POST['password'] && md5($_POST['password']) != $_AUTH['password']) {
            lovd_errorAdd('Please enter your correct password for authorization.');
        }

        if (!lovd_error()) {
            // FIXME; Warning if MySQL type has been changed... possibly loss of data will occur.

            // First, alter all tables who have this column. Less problematic if things go wrong.
            if ($zData['mysql_type'] != stripslashes($_POST['mysql_type'])) {
                // Type changed... take action!
                $aSQL = array();
                if (substr($zData['colid'], 0, 7) == 'Variant') {
                    // Check genes to find if column is active.
                    $aGenes = lovd_getGeneList();
                    foreach ($aGenes as $sSymbol) {
                        list($b) = mysql_fetch_row(mysql_query('SELECT colid FROM ' . TABLEPREFIX . '_' . $sSymbol . '_columns WHERE colid = "' . $zData['colid'] . '"'));
                        if ($b) {
                            // Column present in this gene.
                            // 2009-02-16; 2.0-16; Added stripslashes to allow receiving quotes. This variable has been checked using regexps, so can be considered safe.
                            $aSQL[TABLEPREFIX . '_' . $sSymbol . '_variants'] = 'ALTER TABLE ' . TABLEPREFIX . '_' . $sSymbol . '_variants MODIFY COLUMN `' . $zData['colid'] . '` ' . stripslashes($_POST['mysql_type']) . ' NOT NULL';
                        }
                    }

                } else {
                    // Patient column.
                    list($b) = mysql_fetch_row(mysql_query('SELECT colid FROM ' . TABLE_PATIENTS_COLS . ' WHERE colid = "' . $zData['colid'] . '"'));
                    if ($b) {
                        // Column present in patient table.
                        // 2009-02-16; 2.0-16; Added stripslashes to allow receiving quotes. This variable has been checked using regexps, so can be considered safe.
                        $aSQL[TABLE_PATIENTS] = 'ALTER TABLE ' . TABLE_PATIENTS . ' MODIFY COLUMN `' . $zData['colid'] . '` ' . stripslashes($_POST['mysql_type']) . ' NOT NULL';
                    }
                }

                // If we've got any entries in $aSQL, go ahead...
                $nSQL = count($aSQL);
                if ($nSQL) {
                    // Loop needed queries...
                    foreach ($aSQL as $sTable => $sQ) {
                        $q = mysql_query($sQ);
                        if (!$q) {
                            $sError = mysql_error(); // Save the mysql_error before it disappears.
                            require ROOT_PATH . 'inc-top.php';
                            lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
                            lovd_dbFout('ColEditError', $sQ, $sError, false);
                            lovd_showInfoTable('Error while modifying ' . $sTable . ' table!<BR>This may indicate an error in the MySQL data definition. For more information, see the error log.', 'warning');
                            lovd_showInfoTable('Unfortunately, due to an error I cannot continue to edit the column. Your changes are lost.', 'stop');
                            require ROOT_PATH . 'inc-bot.php';
                            exit;
                        }
                    }
                }
            }



            // Query text.
            $sQ = 'UPDATE ' . TABLE_COLS . ' SET ';

            // Standard fields to be used.
            $aQ = array('standard', 'mandatory', 'head_column', 'description_form', 'description_legend_short', 'description_legend_full', 'mysql_type', 'form_type', 'select_options', 'preg_pattern', 'public', 'public_form', 'allow_count_all');

            // 2012-03-15; 2.0-34; Variant/DNA can not be made non-public because it generates query errors (Variant/DNA is a fallback for order).
            if ($_GET['edit'] == 'Variant/DNA') {
                $_POST['public'] = 1;
            }

            foreach ($aQ as $key => $val) {
                $sQ .= ($key? ', ' : '') . $val . ' = "' . $_POST[$val] . '"';
            }

            $sQ .= ', edited_by = "' . $_AUTH['userid'] . '", edited_date = NOW() WHERE colid = "' . $zData['colid'] . '"';

            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
                lovd_dbFout('ColEdit', $sQ, $sError);
            }

            // Write to log...
            lovd_writeLog('MySQL:Event', 'ColEdit', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully edited column ' . $zData['colid'] . ' (' . $_POST['head_column'] . ')');



            // 2009-04-15; 2.0-18; Allow to update all active columns as well.
            // Fields to be used.
            $aColsToCopy = array('mandatory', 'description_form', 'description_legend_short', 'description_legend_full', 'select_options', 'public', 'public_form');

            if ($_POST['apply_to_all']) {
                if (substr($zData['colid'], 0, 7) == 'Variant') {
                    // Variant column.
                    // Check all genes; update will just fail if column is not active for a particular gene.
                    $aGenes = lovd_getGeneList();
                    foreach ($aGenes as $sSymbol) {
                        $sQ = 'UPDATE ' . TABLEPREFIX . '_' . $sSymbol . '_columns SET ';
                        foreach ($aColsToCopy as $key => $val) {
                            $sQ .= ($key? ', ' : '') . $val . ' = "' . $_POST[$val] . '"';
                        }
                        $sQ .= ', edited_by = "' . $_AUTH['userid'] . '", edited_date = NOW() WHERE colid = "' . $zData['colid'] . '"';

                        $q = mysql_query($sQ);
                        if (mysql_affected_rows()) {
                            // Write to log...
                            lovd_writeLog('MySQL:Event', 'ColEdit', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully edited variant column ' . $zData['colid'] . ' (' . mysql_real_escape_string($zData['head_column']) . ') in ' . $sSymbol . ' gene');
                        }
                    }

                } else {
                    // Patient column.
                    $sQ = 'UPDATE '. TABLE_PATIENTS_COLS . ' SET ';
                    foreach ($aColsToCopy as $key => $val) {
                        $sQ .= ($key? ', ' : '') . $val . ' = "' . $_POST[$val] . '"';
                    }
                    $sQ .= ', edited_by = "' . $_AUTH['userid'] . '", edited_date = NOW() WHERE colid = "' . $zData['colid'] . '"';

                    $q = mysql_query($sQ);
                    if (mysql_affected_rows()) {
                        // Write to log...
                        lovd_writeLog('MySQL:Event', 'ColEdit', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully edited patient column ' . $zData['colid'] . ' (' . mysql_real_escape_string($zData['head_column']) . ')');
                    }
                }
            }



            // 2008-12-02; 2.0-15; Change active columns. added by Gerard
            // Fetch columns link is currently active for.
            $aLinksActive = array();
            $q = mysql_query('SELECT l.linkid, l.linkname FROM ' . TABLE_COLS2LINKS . ' AS c2l LEFT JOIN ' . TABLE_LINKS . ' AS l USING (linkid) WHERE c2l.colid = "' . $zData['colid'] . '"');
            while (list($nLinkID, $sLinkName) = mysql_fetch_row($q)) {
                $aLinksActive[$nLinkID] = $sLinkName;
            }

            // To prevent errors to show up on screen.
            if (!isset($_POST['active_links'])) {
                $_POST['active_links'] = array();
            }

            // Remove link.
            foreach ($aLinksActive AS $nLinkID => $sLinkName) {
                if (!in_array($nLinkID, $_POST['active_links'])) {
                    // User has requested removal...
                    $q = mysql_query('DELETE FROM ' . TABLE_COLS2LINKS . ' WHERE linkid = "' . $nLinkID . '" AND colid = "' . $zData['colid'] . '"');
                    if (!$q) {
                        // Silent error.
                        lovd_writeLog('MySQL:Error', 'ColEdit', 'Custom link ' . $nLinkID . ' (' . $sLinkName . ') could not be removed from ' . $zData['colid']);
                    } else {
                        lovd_writeLog('MySQL:Event', 'ColEdit', 'Custom link ' . $nLinkID . ' (' . $sLinkName . ') successfully removed from ' . $zData['colid']);
                    }
                }
            }

            // Fetch requested custom link names.
            $aLinksRequested = array();
            if (count($_POST['active_links'])) {
                $q = mysql_query('SELECT linkid, linkname FROM ' . TABLE_LINKS . ' WHERE linkid IN (' . implode(', ', $_POST['active_links']) . ')');
                while (list($nLinkID, $sLinkName) = mysql_fetch_row($q)) {
                    $aLinksRequested[$nLinkID] = $sLinkName;
                }
            }

            // Add link.
            foreach ($_POST['active_links'] AS $nLinkID) {
                if (!array_key_exists($nLinkID, $aLinksActive)) {
                    // User has requested addition...
                    $q = mysql_query('INSERT INTO ' . TABLE_COLS2LINKS . ' VALUES ("' . $zData['colid'] . '", "' . $nLinkID . '")');
                    if (!$q) {
                        // Silent error
                        lovd_writeLog('MySQL:Error', 'ColEdit', 'Custom link ' . $nLinkID . ' (' . $aLinksRequested[$nLinkID] . ') could not be added to ' . $zData['colid']);
                    } else {
                        lovd_writeLog('MySQL:Event', 'ColEdit', 'Custom link ' . $nLinkID . ' (' . $aLinksRequested[$nLinkID] . ') successfully added to ' . $zData['colid']);
                    }
                }
            }

            // Clean up...
            $_SESSION['form_type'] = array();

            // Thank the user...
            header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view&view=' . rawurlencode($_GET['edit']) . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
            print('      Successfully edited column \'' . $zData['colid'] . '\'!<BR>' .
                  ($zData['mysql_type'] != stripslashes($_POST['mysql_type']) && $nSQL? 'Modified ' . $nSQL . ' data table' . ($nSQL == 1? '.' : 's.') : '') .
                  '<BR>' . "\n\n");

            require ROOT_PATH . 'inc-bot.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password']);
        }

    } else {
        foreach ($zData as $key => $val) {
            if (!isset($_POST[$key]) || !$_POST[$key]) {
                $_POST[$key] = $val;
            }
        }
        $_POST['password'] = '';

        // 2008-12-02; 2.0-15; Load connected links.
        $_POST['active_links'] = array();
        $q = mysql_query('SELECT linkid FROM ' . TABLE_COLS2LINKS . ' WHERE colid = "' . $zData['colid'] . '"');
        while (list($nLinkID) = @mysql_fetch_row($q)) {
            $_POST['active_links'][] = $nLinkID;
        }

        // Default data type information, loaded in SESSION.
        $aFormType = explode('|', $zData['form_type']);
        $_SESSION['form_type'] =
                 array(
                        'form_type' => '',
                        'name' => $aFormType[0],
                        'size' => '',
                        'maxlength' => '',
                        'scale' => '',
                        'preg_pattern' => $zData['preg_pattern'],
                        'unsigned' => '',
                        'default_val' => '',
                        'cols' => '',
                        'rows' => '',
                        'select' => '',
                        'select_options' => $zData['select_options'],
                        'select_all' => '',
                      );

        // Load $_SESSION['form_type'] with current data from form_type and mysql_type.
        switch ($aFormType[1]) {
            case 'text':
                // VARCHAR, TEXT or INT columns.
                $_SESSION['form_type']['size'] = $aFormType[2];
                if (preg_match('/^VARCHAR\(([0-9]+)\)/', $zData['mysql_type'], $aRegs)) {
                    $_SESSION['form_type']['form_type'] = 'text';
                    $_SESSION['form_type']['maxlength'] = $aRegs[1];
                } elseif (substr($zData['mysql_type'], 0, 4) == 'TEXT') {
                    $_SESSION['form_type']['form_type'] = 'text';
                    $_SESSION['form_type']['maxlength'] = 65535;
                } elseif (preg_match('/^(TINY|SMALL|MEDIUM|BIG)?INT\(([0-9]+)\) *(UNSIGNED)?/', $zData['mysql_type'], $aRegs)) {
                    $_SESSION['form_type']['form_type'] = 'int';
                    // 2009-02-16; 2.0-16; Should be $aRegs[2], not [1] of course.
                    $_SESSION['form_type']['maxlength'] = $aRegs[2];
                    // 2009-02-16; 2.0-16; Should be $aRegs[3], not [2] of course.
                    $_SESSION['form_type']['unsigned']  = (!empty($aRegs[3])? 1 : 0);
                } elseif (preg_match('/^DEC\(([0-9]+),([0-9]+)\) *(UNSIGNED)?/', $zData['mysql_type'], $aRegs)) {
                    // 2009-06-11; 2.0-19; Added DEC, DATE and DATETIME types.
                    $_SESSION['form_type']['form_type'] = 'dec';
                    $_SESSION['form_type']['maxlength'] = $aRegs[1] - $aRegs[2];
                    $_SESSION['form_type']['scale'] = $aRegs[2];
                    $_SESSION['form_type']['unsigned']  = (!empty($aRegs[3])? 1 : 0);
                } elseif (preg_match('/^DATE(TIME)?/', $zData['mysql_type'], $aRegs)) {//need $aRegs for the default value
                    $_SESSION['form_type']['form_type'] = 'date';
                    $_SESSION['form_type']['time'] = (!empty($aRegs[1])? 1 : 0);
                } else {
                    // Should not happen.
                    $_SESSION['form_type']['form_type'] = 'text';
                }

                // 2009-02-16; 2.0-16; Introducing default values.
                if (preg_match('/ DEFAULT ([0-9]+|"[^"]+")/', $zData['mysql_type'], $aRegs)) {
                    // Process default values.
                    $_SESSION['form_type']['default_val'] = trim($aRegs[1], '"');
                }
                break;
            case 'textarea':
                // TEXT column.
                $_SESSION['form_type']['form_type'] = 'textarea';
                $_SESSION['form_type']['cols']      = $aFormType[2];
                $_SESSION['form_type']['rows']      = $aFormType[3];
                break;
            case 'select':
                // VARCHAR or TEXT columns.
                if ($aFormType[4] == 'false') {
                    $_SESSION['form_type']['form_type'] = 'select';
                    $_SESSION['form_type']['select']    = ($aFormType[3] == 'false'? 0 : 1);
                } else {
                    $_SESSION['form_type']['form_type']  = 'select_multiple';
                    $_SESSION['form_type']['rows']       = $aFormType[2];
                    $_SESSION['form_type']['select']     = ($aFormType[3] == 'false'? 0 : 1);
                    $_SESSION['form_type']['select_all'] = ($aFormType[5] == 'false'? 0 : 1);
                }
                break;
            case 'checkbox':
                // TINYINT(1) UNSIGNED column.
                $_SESSION['form_type']['form_type']  = 'checkbox';
                break;
        }
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;edit=' . rawurlencode($zData['colid']) . '&amp;sent=true" method="post">' . "\n" .
          '        <INPUT type="hidden" name="select_options" value="' . $_POST['select_options'] . '">' . "\n" .
          '        <INPUT type="hidden" name="preg_pattern" value="' . $_POST['preg_pattern'] . '">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Get links list, to connect column to link.
    $aLinks = array();
    $qLinks = mysql_query('SELECT linkid, linkname FROM ' . TABLE_LINKS);
    $nLinks = mysql_num_rows($qLinks);
    $nLinkSize = ($nLinks < 10? $nLinks : 10);
    while ($r = mysql_fetch_row($qLinks)) {
        $aLinks[$r[0]] = $r[1];
    }

    // 2009-04-15; 2.0-18; Allow to update all active columns as well.
    if (substr($zData['colid'], 0, 7) == 'Variant') {
        // Check genes to find if column is active.
        $aGenes = lovd_getGeneList();
        foreach ($aGenes as $sSymbol) {
            list($bInUse) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLEPREFIX . '_' . $sSymbol . '_columns WHERE colid = "' . $zData['colid'] . '"'));
            if ($bInUse) {
                break;
            }
        }
    } else {
        // Patient column.
        list($bInUse) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_PATIENTS_COLS . ' WHERE colid = "' . $zData['colid'] . '"'));
    }

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '50%', '50%'),
                    array('', 'print', '<B>Column name and descriptions</B>'),
                    array('Column heading', 'text', 'head_column', 30),
                    array('', 'print', '<SPAN class="form_note">This will appear above the column on data listings and the legend.</SPAN>'),
                    array('Description on form', 'textarea', 'description_form', 40, 2),
                    array('Description on short legend', 'textarea', 'description_legend_short', 40, 2),
                    array('Description on full legend', 'textarea', 'description_legend_full', 40, 2),
                    'skip',
                    array('', 'print', '<B>Data settings</B> (Use data type wizard to change values)'),
                    array('', 'print', '<BUTTON type="button" onclick="javascript:lovd_openWindow(\'' . $_SERVER['PHP_SELF'] . '?action=form_type_define&amp;from_action=' . $_GET['action'] . lovd_showSID(true, true) . '\', \'FormTypeDefine\', 800, 400); return false;">Start data type wizard</BUTTON>'),
                    array('MySQL data type', 'text', 'mysql_type', 30),
                    array('Form type', 'text', 'form_type', 30),
                    'skip',
                    array('', 'print', '<B>Column settings</B>'),
                    array('Standard for new genes (Variant columns only)', 'checkbox', 'standard', 1),
                    array('Mandatory field', 'checkbox', 'mandatory', 1),
                    array('Show contents to public', 'checkbox', 'public', 1),
                    array('Show field on public forms', 'checkbox', 'public_form', 1),
                    array('Include in search form', 'checkbox', 'allow_count_all', 1),
                    array('', 'print', '<SPAN class="form_note">Selecting this checkbox allows the public to find the number of entries in the database (including hidden entries) matching one or more search terms on this column.</SPAN>'),
                    'skip',
                    array('', 'print', '<B>Link settings</B>'),
                    array('Active custom links', 'select', 'active_links', $nLinkSize, $aLinks, false, true, false),
                    'skip',
                  );
    // 2009-04-15; 2.0-18; Allow to update all active columns as well.
    if ($bInUse) {
        if (substr($zData['colid'], 0, 7) == 'Variant') {
            $aForm[] = array('Apply changes to all genes where this column is active', 'checkbox', 'apply_to_all', 1);
        } else {
            $aForm[] = array('Apply changes to patient table where this column is active', 'checkbox', 'apply_to_all', 1);
        }
    }
    $aForm[] = array('Enter your password for authorization', 'password', 'password', 20);
    $aForm[] = array('', 'submit', 'Edit column default settings');
    $_MODULES->processForm('SetupColumnsGlobalEdit', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'drop' && !empty($_GET['drop'])) {
    // 2008-11-24; 2.0-15 added by Gerard.
    // Deleting self-created columns.
    $zData = @mysql_fetch_assoc(mysql_query('SELECT * FROM ' . TABLE_COLS . ' WHERE created_by != 0 AND colid = "' . $_GET['drop'] . '"'));
    if (!$zData) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
        lovd_showInfoTable('No such ID!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    $bSelected = true;
    if (substr($zData['colid'], 0, 7) == 'Variant') {
        // Check genes to find if column is active.
        $aGenes = lovd_getGeneList();
        foreach ($aGenes as $sSymbol) {
            list($bSelected) = mysql_fetch_row(mysql_query('SELECT colid FROM ' . TABLEPREFIX . '_' . $sSymbol . '_columns WHERE colid = "' . $zData['colid'] . '"'));
            if ($bSelected) {
                // Column present in this gene.
                break;
            }
        }
    } elseif (substr($zData['colid'], 0, 7) == 'Patient') {
        // Patient column.
        list($bSelected) = mysql_fetch_row(mysql_query('SELECT colid FROM ' . TABLE_PATIENTS_COLS . ' WHERE colid = "' . $zData['colid'] . '"'));
    }

    if (!$zData['created_by'] || $bSelected) {
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
        lovd_showInfoTable('Column has been selected, cannot be removed!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    require ROOT_PATH . 'inc-lib-form.php';

    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // Mandatory fields.
        $aCheck =
                 array(
                        'password' => 'Enter your password for authorization',
                      );

        foreach ($aCheck as $key => $val) {
            if (empty($_POST[$key])) {
                lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
            }
        }

        // User had to enter his/her password for authorization.
        if ($_POST['password'] && md5($_POST['password']) != $_AUTH['password']) {
            lovd_errorAdd('Please enter your correct password for authorization.');
        }

        if (!lovd_error()) {
            // Delete the row in the general_columns table.
            $sQ = 'DELETE FROM ' . TABLE_COLS . ' WHERE colid = "' . $_GET['drop'] . '"';
            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
                lovd_dbFout('ColDrop', $sQ, $sError);
            }

            // Delete the links in the general_columns2links table.
            $sQ = 'DELETE FROM ' . TABLE_COLS2LINKS . ' WHERE colid = "' . $_GET['drop'] . '"';
            $q = mysql_query($sQ);
            if (!$q) {
                // Silent error.
                lovd_writeLog('MySQL:Error', 'ColDrop', 'Custom links could not be removed from ' . $zData['colid']);
            } else {
                lovd_writeLog('MySQL:Event', 'ColDrop', 'Custom links successfully removed from ' . $zData['colid']);
            }

            // Write to log...
            lovd_writeLog('MySQL:Event', 'ColDrop', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully deleted column ' . $zData['colid'] . ' (' . mysql_real_escape_string($zData['head_column']) . ')');

            // Thank the user...
            header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view_all' . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
            print('      Successfully deleted column "' . $zData['colid'] . '"!<BR><BR>' . "\n\n");

            require ROOT_PATH . 'inc-bot.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password']);
        }
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;drop=' . rawurlencode($zData['colid']) . '&amp;sent=true" method="post">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '50%', '50%'),
                    array('Permanently deleting column', 'print', $zData['colid'] . ' (' . $zData['head_column'] . ')'),
                    'skip',
                    array('Enter your password for authorization', 'password', 'password', 20),
                    array('', 'submit', 'Delete column permanently'),
                  );
    $_MODULES->processForm('SetupColumnsDelete', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} elseif ($_GET['action'] == 'edit_colid' && !empty($_GET['edit_colid'])) {
    // 2008-12-02; 2.0-15; Edit specific custom colid. by Gerard
    $zData = @mysql_fetch_assoc(mysql_query('SELECT * FROM ' . TABLE_COLS . ' WHERE created_by != 0 AND colid = "' . $_GET['edit_colid'] . '"'));
    if (!$zData) {
        // Wrong ID, apparently.
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
        lovd_showInfoTable('No such ID!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    $bSelected = true;
    if (substr($zData['colid'], 0, 7) == 'Variant') {
        // Check genes to find if column is active.
        $aGenes = lovd_getGeneList();
        foreach ($aGenes as $sSymbol) {
            list($bSelected) = mysql_fetch_row(mysql_query('SELECT colid FROM ' . TABLEPREFIX . '_' . $sSymbol . '_columns WHERE colid = "' . $zData['colid'] . '"'));
            if ($bSelected) {
                // Column present in this gene.
                break;
            }
        }
    } elseif (substr($zData['colid'], 0, 7) == 'Patient') {
        // Patient column.
        list($bSelected) = mysql_fetch_row(mysql_query('SELECT colid FROM ' . TABLE_PATIENTS_COLS . ' WHERE colid = "' . $zData['colid'] . '"'));
    }

    if (!$zData['created_by'] || $bSelected) {
        require ROOT_PATH . 'inc-top.php';
        lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
        lovd_showInfoTable('Column has been selected, cannot be renamed!', 'stop');
        require ROOT_PATH . 'inc-bot.php';
        exit;
    }

    // Require form functions.
    require ROOT_PATH . 'inc-lib-form.php';

    if (isset($_GET['sent'])) {
        lovd_errorClean();

        // Mandatory fields.
        $aCheck =
                 array(
                        'col_cat' => 'Category',
                        'colid' => 'Column ID',
                        'password' => 'Enter your password for authorization',
                      );

        foreach ($aCheck as $key => $val) {
            if (empty($_POST[$key])) {
                lovd_errorAdd('Please fill in the \'' . $val . '\' field.');
            }
        }

        // ColID format.
        if ($_POST['colid'] && !preg_match('/^[A-Za-z0-9_]+(\/[A-Za-z0-9_]+)*$/', $_POST['colid'])) {
            lovd_errorAdd('The column ID is not of the correct format. It can contain only letters, numbers and underscores. Subcategories must be devided by a slash (/).');
        }

        // ColID must not exist in the database.
        if ($_POST['col_cat'] && $_POST['colid'] && $_POST['col_cat'] . '/' . $_POST['colid'] != $zData['colid']) {
            list($n) = mysql_fetch_row(mysql_query('SELECT COUNT(*) FROM ' . TABLE_COLS . ' WHERE colid = "' . $_POST['col_cat'] . '/' . $_POST['colid'] . '"'));
            if ($n) {
                lovd_errorAdd('There is already a ' . $_POST['col_cat'] . ' column with this column ID. Please choose another one.');
            }
        }

        // User had to enter his/her password for authorization.
        if ($_POST['password'] && md5($_POST['password']) != $_AUTH['password']) {
            lovd_errorAdd('Please enter your correct password for authorization.');
        }

        if (!lovd_error()) {
            // Query text.
            $_POST['colid'] = $_POST['col_cat'] . '/' . $_POST['colid'];
            $sQ = 'UPDATE ' . TABLE_COLS . ' SET colid = "' . $_POST['colid'] . '", edited_by = "' . $_AUTH['userid'] . '", edited_date = NOW() WHERE colid = "' . $zData['colid'] . '"';
            $q = mysql_query($sQ);
            if (!$q) {
                $sError = mysql_error(); // Save the mysql_error before it disappears.
                require ROOT_PATH . 'inc-top.php';
                lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
                lovd_dbFout('ColEditColID', $sQ, $sError);
            }

            // Write to log...
            lovd_writeLog('MySQL:Event', 'ColEditColID', $_AUTH['username'] . ' (' . mysql_real_escape_string($_AUTH['name']) . ') successfully changed column ID ' . $zData['colid'] . ' to ' . $_POST['colid']);

            // 2008-12-03; 2.0-15; Update links (whether they exist or not)
            $sQ = 'UPDATE ' . TABLE_COLS2LINKS . ' SET colid="' . $_POST['colid'] . '" WHERE colid="' . $zData['colid'] . '"';
            $q = mysql_query($sQ);
            if (!$q) {
                // Silent error.
                lovd_writeLog('MySQL:Error', 'ColEdit', 'Custom links could not be updated for ' . $_POST['colid']);
            } else {
                lovd_writeLog('MySQL:Event', 'ColEdit', 'Custom links successfully updated for ' . $_POST['colid']);
            }

            // Thank the user...
            header('Refresh: 3; url=' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view&view=' . rawurlencode($_POST['colid']) . lovd_showSID(true));

            require ROOT_PATH . 'inc-top.php';
            lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');
            print('      Successfully changed column ID \'' . $zData['colid'] . '\' to \'' . $_POST['colid'] . '\'!<BR><BR>' . "\n\n");

            require ROOT_PATH . 'inc-bot.php';
            exit;

        } else {
            // Errors, so the whole lot returns to the form.
            lovd_magicUnquoteAll();

            // Because we're sending the data back to the form, I need to unset the password fields!
            unset($_POST['password']);
        }

    } else {
        foreach ($zData as $key => $val) {
            if (!isset($_POST[$key]) || !$_POST[$key]) {
                $_POST[$key] = $val;
            }
        }
        list($_POST['col_cat'], $_POST['colid']) = explode('/', $_POST['colid'], 2);
        $_POST['password'] = '';
    }



    require ROOT_PATH . 'inc-top.php';
    lovd_printHeader('setup_columns_manage_defaults', 'LOVD Setup - Manage custom column defaults');

    lovd_errorPrint();

    // Table.
    print('      <FORM action="' . $_SERVER['PHP_SELF'] . '?action=' . $_GET['action'] . '&amp;edit_colid=' . rawurlencode($zData['colid']) . '&amp;sent=true" method="post">' . "\n" .
          '        <TABLE border="0" cellpadding="0" cellspacing="1" width="760">');

    // Array which will make up the form table.
    $aForm = array(
                    array('POST', '', '', '50%', '50%'),
                    array('Category', 'select', 'col_cat', 1, array('Patient' => 'Patient', 'Variant' => 'Variant'), true, false, false),
                    array('Column ID', 'text', 'colid', 30),
                    array('', 'print', '<SPAN class="form_note">This ID must be unique and may contain only letters, numbers and underscores. Subcategories must be divided by a slash (/), such as \'Phenotype/Disease\'.<BR>Do NOT add \'Patient/\' or \'Variant/\' here.</SPAN>'),
                    'skip',
                    array('Enter your password for authorization', 'password', 'password', 20),
                    array('', 'submit', 'Edit column ID'),
                  );
    $_MODULES->processForm('SetupColumnsGlobalEdit', $aForm);
    lovd_viewForm($aForm);

    print('</TABLE></FORM>' . "\n\n");

    require ROOT_PATH . 'inc-bot.php';
    exit;





} else {
    // Default action:
    header('Location: ' . PROTOCOL . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . '?action=view_all' . lovd_showSID(true));
    exit;
}
?>
