the number the more borders and lines the tables will have,
but this depends on the particular format. In
<acronym>HTML</acronym> format, this will translate directly
- into the <literal>border=...</literal> attribute; in the
- other formats only values 0 (no border), 1 (internal dividing lines),
- and 2 (table frame) make sense.
+ into the <literal>border=...</literal> attribute; in
<literal>latex</literal> and <literal>latex-longtable</literal>
- also support a <literal>border</literal> value of 3 which adds
- a dividing line between each row.
+ formats, a value of 3 will add a dividing line between each row; in
+ the other formats only values 0 (no border), 1 (internal dividing
+ lines), and 2 (table frame) make sense and values above 2 will be
+ treated the same as <literal>border = 2</literal>.
</para>
</listitem>
</varlistentry>
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>unicode_border_style</literal></term>
+ <listitem>
+ <para>
+ Sets the border drawing style for the unicode linestyle to one
+ of <literal>single</literal> or <literal>double</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>unicode_column_style</literal></term>
+ <listitem>
+ <para>
+ Sets the column drawing style for the unicode linestyle to one
+ of <literal>single</literal> or <literal>double</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>unicode_header_style</literal></term>
+ <listitem>
+ <para>
+ Sets the header drawing style for the unicode linestyle to one
+ of <literal>single</literal> or <literal>double</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
"footer", "format", "linestyle", "null",
"numericlocale", "pager", "recordsep",
"tableattr", "title", "tuples_only",
+ "unicode_border_linestyle",
+ "unicode_column_linestyle",
+ "unicode_header_linestyle",
NULL
};
return "unknown";
}
+/*
+ * Parse entered unicode linestyle. Returns true, when entered string is
+ * known linestyle: single, double else returns false.
+ */
+static bool
+set_unicode_line_style(printQueryOpt *popt, const char *value, size_t vallen,
+ unicode_linestyle *linestyle)
+{
+ if (pg_strncasecmp("single", value, vallen) == 0)
+ *linestyle = UNICODE_LINESTYLE_SINGLE;
+ else if (pg_strncasecmp("double", value, vallen) == 0)
+ *linestyle = UNICODE_LINESTYLE_DOUBLE;
+ else
+ return false;
+
+ /* input is ok, generate new unicode style */
+ refresh_utf8format(&(popt->topt));
+
+ return true;
+}
+
+static const char *
+_unicode_linestyle2string(int linestyle)
+{
+ switch (linestyle)
+ {
+ case UNICODE_LINESTYLE_SINGLE:
+ return "single";
+ break;
+ case UNICODE_LINESTYLE_DOUBLE:
+ return "double";
+ break;
+ }
+ return "unknown";
+}
bool
do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
}
+ /* set unicode border line style */
+ else if (strcmp(param, "unicode_border_linestyle") == 0)
+ {
+ if (!value)
+ ;
+ else if (!set_unicode_line_style(popt, value, vallen,
+ &popt->topt.unicode_border_linestyle))
+ {
+ psql_error("\\pset: allowed unicode border linestyle are single, double\n");
+ return false;
+ }
+ }
+
+ /* set unicode column line style */
+ else if (strcmp(param, "unicode_column_linestyle") == 0)
+ {
+ if (!value)
+ ;
+ else if (!set_unicode_line_style(popt, value, vallen,
+ &popt->topt.unicode_column_linestyle))
+ {
+ psql_error("\\pset: allowed unicode column linestyle are single, double\n");
+ return false;
+ }
+ }
+
+ /* set unicode header line style */
+ else if (strcmp(param, "unicode_header_linestyle") == 0)
+ {
+ if (!value)
+ ;
+ else if (!set_unicode_line_style(popt, value, vallen,
+ &popt->topt.unicode_header_linestyle))
+ {
+ psql_error("\\pset: allowed unicode header linestyle are single, double\n");
+ return false;
+ }
+ }
+
/* set border style/width */
else if (strcmp(param, "border") == 0)
{
printf(_("Tuples only (%s) is off.\n"), param);
}
+ /* unicode style formatting */
+ else if (strcmp(param, "unicode_border_linestyle") == 0)
+ {
+ printf(_("Unicode border linestyle is \"%s\".\n"),
+ _unicode_linestyle2string(popt->topt.unicode_border_linestyle));
+ }
+
+ else if (strcmp(param, "unicode_column_linestyle") == 0)
+ {
+ printf(_("Unicode column linestyle is \"%s\".\n"),
+ _unicode_linestyle2string(popt->topt.unicode_column_linestyle));
+ }
+
+ else if (strcmp(param, "unicode_header_linestyle") == 0)
+ {
+ printf(_("Unicode border linestyle is \"%s\".\n"),
+ _unicode_linestyle2string(popt->topt.unicode_header_linestyle));
+ }
+
else
{
psql_error("\\pset: unknown option: %s\n", param);
ON(pset.popt.topt.format == PRINT_HTML));
fprintf(output, _(" \\pset [NAME [VALUE]] set table output option\n"
" (NAME := {format|border|expanded|fieldsep|fieldsep_zero|footer|null|\n"
- " numericlocale|recordsep|recordsep_zero|tuples_only|title|tableattr|pager})\n"));
+ " numericlocale|recordsep|recordsep_zero|tuples_only|title|tableattr|pager|\n"
+ " unicode_border_linestyle|unicode_column_linestyle|unicode_header_linestyle})\n"));
fprintf(output, _(" \\t [on|off] show only rows (currently %s)\n"),
ON(pset.popt.topt.tuples_only));
fprintf(output, _(" \\T [STRING] set HTML <table> tag attributes, or unset if none\n"));
false
};
-const printTextFormat pg_utf8format =
-{
- "unicode",
- {
- /* ─, ┌, ┬, ┐ */
- {"\342\224\200", "\342\224\214", "\342\224\254", "\342\224\220"},
- /* ─, ├, ┼, ┤ */
- {"\342\224\200", "\342\224\234", "\342\224\274", "\342\224\244"},
- /* ─, └, ┴, ┘ */
- {"\342\224\200", "\342\224\224", "\342\224\264", "\342\224\230"},
- /* N/A, │, │, │ */
- {"", "\342\224\202", "\342\224\202", "\342\224\202"}
+/* Default unicode linestyle format */
+const printTextFormat pg_utf8format;
+
+typedef struct unicodeStyleRowFormat {
+ const char *horizontal;
+ const char *vertical_and_right[2];
+ const char *vertical_and_left[2];
+} unicodeStyleRowFormat;
+
+typedef struct unicodeStyleColumnFormat {
+ const char *vertical;
+ const char *vertical_and_horizontal[2];
+ const char *up_and_horizontal[2];
+ const char *down_and_horizontal[2];
+} unicodeStyleColumnFormat;
+
+typedef struct unicodeStyleBorderFormat {
+ const char *up_and_right;
+ const char *vertical;
+ const char *down_and_right;
+ const char *horizontal;
+ const char *down_and_left;
+ const char *left_and_right;
+} unicodeStyleBorderFormat;
+
+typedef struct unicodeStyleFormat {
+ unicodeStyleRowFormat row_style[2];
+ unicodeStyleColumnFormat column_style[2];
+ unicodeStyleBorderFormat border_style[2];
+ const char *header_nl_left;
+ const char *header_nl_right;
+ const char *nl_left;
+ const char *nl_right;
+ const char *wrap_left;
+ const char *wrap_right;
+ bool wrap_right_border;
+} unicodeStyleFormat;
+
+const unicodeStyleFormat unicode_style = {
+ {
+ {
+ /* ─ */
+ "\342\224\200",
+ /* ├╟ */
+ {"\342\224\234", "\342\225\237"},
+ /* ┤╢ */
+ {"\342\224\244", "\342\225\242"},
+ },
+ {
+ /* ═ */
+ "\342\225\220",
+ /* ╞╠ */
+ {"\342\225\236", "\342\225\240"},
+ /* ╡╣ */
+ {"\342\225\241", "\342\225\243"},
+ },
+ },
+ {
+ {
+ /* │ */
+ "\342\224\202",
+ /* ┼╪ */
+ {"\342\224\274", "\342\225\252"},
+ /* ┴╧ */
+ {"\342\224\264", "\342\225\247"},
+ /* ┬╤ */
+ {"\342\224\254", "\342\225\244"},
+ },
+ {
+ /* ║ */
+ "\342\225\221",
+ /* ╫╬ */
+ {"\342\225\253", "\342\225\254"},
+ /* ╨╩ */
+ {"\342\225\250", "\342\225\251"},
+ /* ╥╦ */
+ {"\342\225\245", "\342\225\246"},
+ },
+ },
+ {
+ /* └│┌─┐┘ */
+ {"\342\224\224", "\342\224\202", "\342\224\214", "\342\224\200", "\342\224\220", "\342\224\230"},
+ /* ╚║╔═╗╝ */
+ {"\342\225\232", "\342\225\221", "\342\225\224", "\342\225\220", "\342\225\227", "\342\225\235"},
},
- /* │ */
- "\342\224\202",
- /* │ */
- "\342\224\202",
- /* │ */
- "\342\224\202",
" ",
- /* ↵ */
- "\342\206\265",
+ "\342\206\265", /* ↵ */
" ",
- /* ↵ */
- "\342\206\265",
- /* … */
- "\342\200\246",
- /* … */
- "\342\200\246",
+ "\342\206\265", /* ↵ */
+ "\342\200\246", /* … */
+ "\342\200\246", /* … */
true
};
}
else
/*
- * For border = 2, two more for the pipes (|) at the begging and
+ * For border = 2, two more for the pipes (|) at the beginning and
* at the end of the lines.
*/
swidth = 7;
return &pg_asciiformat;
}
+void
+refresh_utf8format(const printTableOpt *opt)
+{
+ printTextFormat *popt = (printTextFormat *) &pg_utf8format;
+
+ const unicodeStyleBorderFormat *border;
+ const unicodeStyleRowFormat *header;
+ const unicodeStyleColumnFormat *column;
+
+ popt->name = "unicode";
+
+ border = &unicode_style.border_style[opt->unicode_border_linestyle];
+ header = &unicode_style.row_style[opt->unicode_header_linestyle];
+ column = &unicode_style.column_style[opt->unicode_column_linestyle];
+
+ popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
+ popt->lrule[PRINT_RULE_TOP].leftvrule = border->down_and_right;
+ popt->lrule[PRINT_RULE_TOP].midvrule = column->down_and_horizontal[opt->unicode_border_linestyle];
+ popt->lrule[PRINT_RULE_TOP].rightvrule = border->down_and_left;
+
+ popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
+ popt->lrule[PRINT_RULE_MIDDLE].leftvrule = header->vertical_and_right[opt->unicode_border_linestyle];
+ popt->lrule[PRINT_RULE_MIDDLE].midvrule = column->vertical_and_horizontal[opt->unicode_header_linestyle];
+ popt->lrule[PRINT_RULE_MIDDLE].rightvrule = header->vertical_and_left[opt->unicode_border_linestyle];
+
+ popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
+ popt->lrule[PRINT_RULE_BOTTOM].leftvrule = border->up_and_right;
+ popt->lrule[PRINT_RULE_BOTTOM].midvrule = column->up_and_horizontal[opt->unicode_border_linestyle];
+ popt->lrule[PRINT_RULE_BOTTOM].rightvrule = border->left_and_right;
+
+ /* N/A */
+ popt->lrule[PRINT_RULE_DATA].hrule = "";
+ popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
+ popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
+ popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
+
+ popt->midvrule_nl = column->vertical;
+ popt->midvrule_wrap = column->vertical;
+ popt->midvrule_blank = column->vertical;
+
+ /* Same for all unicode today */
+ popt->header_nl_left = unicode_style.header_nl_left;
+ popt->header_nl_right = unicode_style.header_nl_right;
+ popt->nl_left = unicode_style.nl_left;
+ popt->nl_right = unicode_style.nl_right;
+ popt->wrap_left = unicode_style.wrap_left;
+ popt->wrap_right = unicode_style.wrap_right;
+ popt->wrap_right_border = unicode_style.wrap_right_border;
+
+ return;
+}
+
/*
* Compute the byte distance to the end of the string or *target_width
* display character positions, whichever comes first. Update *target_width
* marks when border=0? */
} printTextFormat;
+typedef enum unicode_linestyle
+{
+ UNICODE_LINESTYLE_SINGLE = 0,
+ UNICODE_LINESTYLE_DOUBLE
+} unicode_linestyle;
+
struct separator
{
char *separator;
int encoding; /* character encoding */
int env_columns; /* $COLUMNS on psql start, 0 is unset */
int columns; /* target width for wrapped format */
+ unicode_linestyle unicode_border_linestyle;
+ unicode_linestyle unicode_column_linestyle;
+ unicode_linestyle unicode_header_linestyle;
} printTableOpt;
/*
extern void setDecimalLocale(void);
extern const printTextFormat *get_line_style(const printTableOpt *opt);
+extern void refresh_utf8format(const printTableOpt *opt);
#ifndef __CYGWIN__
#define DEFAULT_PAGER "more"
#include "help.h"
#include "input.h"
#include "mainloop.h"
+#include "print.h"
#include "settings.h"
pset.popt.topt.start_table = true;
pset.popt.topt.stop_table = true;
pset.popt.topt.default_footer = true;
+
+ pset.popt.topt.unicode_border_linestyle = UNICODE_LINESTYLE_SINGLE;
+ pset.popt.topt.unicode_column_linestyle = UNICODE_LINESTYLE_SINGLE;
+ pset.popt.topt.unicode_header_linestyle = UNICODE_LINESTYLE_SINGLE;
+
+ refresh_utf8format(&(pset.popt.topt));
+
/* We must get COLUMNS here before readline() sets it */
pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
{"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
"footer", "format", "linestyle", "null", "numericlocale",
"pager", "recordsep", "recordsep_zero", "tableattr", "title",
- "tuples_only", NULL};
+ "tuples_only", "unicode_border_linestyle",
+ "unicode_column_linestyle", "unicode_header_linestyle", NULL};
COMPLETE_WITH_LIST_CS(my_list);
}
COMPLETE_WITH_LIST_CS(my_list);
}
+ else if (strcmp(prev_wd, "unicode_border_linestyle") == 0 ||
+ strcmp(prev_wd, "unicode_column_linestyle") == 0 ||
+ strcmp(prev_wd, "unicode_header_linestyle") == 0)
+ {
+ static const char *const my_list[] =
+ {"single", "double", NULL};
+
+ COMPLETE_WITH_LIST_CS(my_list);
+
+ }
}
else if (strcmp(prev_wd, "\\unset") == 0)
{
Table attributes (tableattr) unset.
Title (title) unset.
Tuples only (tuples_only) is off.
+Unicode border linestyle is "single".
+Unicode column linestyle is "single".
+Unicode border linestyle is "single".
-- test multi-line headers, wrapping, and newline indicators
prepare q as select array_to_string(array_agg(repeat('x',2*n)),E'\n') as "ab