On Mon, Oct 05, 2009 at 04:32:08PM -0400, Tom Lane wrote:
> Roger Leigh <rle...@codelibre.net> writes:
> > On Sun, Oct 04, 2009 at 11:22:27PM +0300, Peter Eisentraut wrote:
> >> Elsewhere in the psql code, notably in mbprint.c, we make the decision
> >> on whether to apply certain Unicode-aware processing based on whether
> >> the client encoding is UTF8.  The same should be done here.
> >> 
> >> There is a patch somewhere in the pipeline that would automatically set
> >> the psql client encoding to whatever the locale says, but until that is
> >> done, the client encoding should be the sole setting that rules what
> >> kind of character set processing is done on the client side.
> 
> > OK, that makes sense to a certain extent.  However, the characters
> > used to draw the table lines are not really that related to the
> > client encoding for data sent from the database (IMHO).
> 
> Huh?  The data *in* the table is going to be in the client_encoding, and
> psql contains no mechanisms that would translate it to something else.
> Surrounding it with decoration in a different encoding is just a recipe
> for breakage.

Ah, I was under the mistaken assumption that this was iconv()ed or
otherwise translated for correct display.  In that case, I'll leave
the patch as is (using the client encoding for table lines).

I've attached an updated copy of the patch (it just removes the
now unneeded langinfo.h header).


Regards,
Roger

-- 
  .''`.  Roger Leigh
 : :' :  Debian GNU/Linux             http://people.debian.org/~rleigh/
 `. `'   Printing on GNU/Linux?       http://gutenprint.sourceforge.net/
   `-    GPG Public Key: 0x25BFB848   Please GPG sign your mail.
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index 85e9375..cd1c137 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1690,6 +1690,54 @@ lo_import 152801
           </varlistentry>
 
           <varlistentry>
+          <term><literal>linestyle</literal></term>
+          <listitem>
+          <para>
+	  Sets the line drawing style of text table output to one
+          of <literal>ascii</literal>, or <literal>utf8</literal>.
+          Unique abbreviations are allowed.  (That would mean one
+          letter is enough.)  <literal>utf8</literal> will be selected
+          by default if supported by your locale,
+          otherwise <literal>ascii</literal> will be used.
+          </para>
+
+          <para>
+	  Query result tables are displayed as text for some output
+	  formats (<literal>unaligned</literal>,
+          <literal>aligned</literal>, and <literal>wrapped</literal>
+          formats).  The tables are drawn using characters of the
+          user's locale character set.  By
+          default, <acronym>ASCII</acronym> characters will be used,
+          which will display correctly in all locales.  However, if
+          the user is using a locale with a <acronym>UTF-8</acronym>
+          character set, the default will be to
+          use <acronym>UTF-8</acronym> box drawing characters in place
+          of ASCII punctuation to display more readable tables.
+          </para>
+
+          <para>
+	  This option is useful for overriding the default line
+	  style, for example to force the use of
+	  only <acronym>ASCII</acronym> characters when extended
+	  character sets such as <acronym>UTF-8</acronym> are
+	  inappropriate.  This might be the case if preserving output
+	  compatibility with older psql versions is important (prior
+	  to 8.5.0).
+          </para>
+
+          <para>
+          <quote>UTF8</quote> use Unicode <acronym>UTF-8</acronym> box
+          drawing characters.
+          </para>
+
+          <para>
+          <quote>ASCII</quote> use plain <acronym>ASCII</acronym> characters.
+          </para>
+
+          </listitem>
+          </varlistentry>
+
+          <varlistentry>
           <term><literal>columns</literal></term>
           <listitem>
           <para>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index da57eb4..be2b60b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -33,6 +33,11 @@
 #include <openssl/ssl.h>
 #endif
 
+#include <locale.h>
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
 #include "portability/instr_time.h"
 
 #include "libpq-fe.h"
@@ -46,6 +51,7 @@
 #include "input.h"
 #include "large_obj.h"
 #include "mainloop.h"
+#include "mbprint.h"
 #include "print.h"
 #include "psqlscan.h"
 #include "settings.h"
@@ -596,6 +602,14 @@ exec_command(const char *cmd,
 				/* save encoding info into psql internal data */
 				pset.encoding = PQclientEncoding(pset.db);
 				pset.popt.topt.encoding = pset.encoding;
+				if (!pset.popt.topt.line_style_set)
+				{
+					if (pset.encoding == get_utf8_id())
+						pset.popt.topt.line_style = &utf8format;
+					else
+						pset.popt.topt.line_style = &asciiformat;
+				}
+
 				SetVariable(pset.vars, "ENCODING",
 							pg_encoding_to_char(pset.encoding));
 			}
@@ -1430,8 +1444,19 @@ void
 SyncVariables(void)
 {
 	/* get stuff from connection */
+#if (defined(HAVE_LANGINFO_H) && defined(CODESET))
+	if (PQsetClientEncoding(pset.db, nl_langinfo(CODESET)) == -1)
+		psql_error("%s: invalid encoding name or conversion procedure not found for locale codeset\n", nl_langinfo(CODESET));
+#endif
 	pset.encoding = PQclientEncoding(pset.db);
 	pset.popt.topt.encoding = pset.encoding;
+	if (!pset.popt.topt.line_style_set)
+	{
+		if (pset.encoding == get_utf8_id())
+			pset.popt.topt.line_style = &utf8format;
+		else
+			pset.popt.topt.line_style = &asciiformat;
+	}
 	pset.sversion = PQserverVersion(pset.db);
 
 	SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
@@ -1772,6 +1797,27 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
 			printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
 	}
 
+	/* set table line style */
+	else if (strcmp(param, "linestyle") == 0)
+	{
+		if (!value)
+			;
+		else if (pg_strncasecmp("ascii", value, vallen) == 0)
+			popt->topt.line_style = &asciiformat;
+		else if (pg_strncasecmp("utf8", value, vallen) == 0)
+			popt->topt.line_style = &utf8format;
+		else
+		{
+			psql_error("\\pset: allowed table styles are ascii, utf8\n");
+			return false;
+		}
+
+		popt->topt.line_style_set = true;
+
+		if (!quiet)
+			printf(_("Table style is %s.\n"), popt->topt.line_style->name);
+	}
+
 	/* set border style/width */
 	else if (strcmp(param, "border") == 0)
 	{
diff --git a/src/bin/psql/mbprint.c b/src/bin/psql/mbprint.c
index 339ee0c..8cb1905 100644
--- a/src/bin/psql/mbprint.c
+++ b/src/bin/psql/mbprint.c
@@ -30,7 +30,7 @@
 
 typedef unsigned int pg_wchar;
 
-static int
+int
 get_utf8_id(void)
 {
 	static int	utf8_id = -1;
diff --git a/src/bin/psql/mbprint.h b/src/bin/psql/mbprint.h
index 83792e2..25e6018 100644
--- a/src/bin/psql/mbprint.h
+++ b/src/bin/psql/mbprint.h
@@ -9,6 +9,9 @@ struct lineptr
 	int			width;
 };
 
+extern int
+get_utf8_id(void);
+
 extern unsigned char *mbvalidate(unsigned char *pwcs, int encoding);
 
 extern int	pg_wcswidth(const unsigned char *pwcs, size_t len, int encoding);
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 7505cd4..7b108c4 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -356,38 +356,77 @@ print_unaligned_vertical(const printTableContent *cont, FILE *fout)
 /* Aligned text		*/
 /********************/
 
+const printTextFormat asciiformat =
+{
+	"ascii",
+	{
+		{ "-", "+", "+", "+" },
+		{ "-", "+", "+", "+" },
+		{ "-", "+", "+", "+" },
+		{ "",  "|", "|", "|" }
+	},
+	":",
+	";",
+	" "
+};
+
+const struct printTextFormat utf8format =
+{
+	"utf8",
+	{
+	  /* ─, ┌, ┬, ┐ */
+	  { "\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" }
+	},
+	  /* ╎ */
+	  "\342\225\216",
+	  /* ┊ */
+	  "\342\224\212",
+	  /* ╷ */
+	  "\342\225\267"
+};
 
 /* draw "line" */
 static void
 _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths,
-					   unsigned short border, FILE *fout)
+		       unsigned short border, printTextRule pos,
+		       const printTextFormat *format,
+		       FILE *fout)
 {
 	unsigned int i,
 				j;
 
+	const printTextLineFormat *lformat = &format->lrule[pos];
+
 	if (border == 1)
-		fputc('-', fout);
+		fputs(lformat->hrule, fout);
 	else if (border == 2)
-		fputs("+-", fout);
+		fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
 
 	for (i = 0; i < ncolumns; i++)
 	{
 		for (j = 0; j < widths[i]; j++)
-			fputc('-', fout);
+			fputs(lformat->hrule, fout);
 
 		if (i < ncolumns - 1)
 		{
 			if (border == 0)
 				fputc(' ', fout);
 			else
-				fputs("-+-", fout);
+				fprintf(fout, "%s%s%s", lformat->hrule,
+					lformat->midvrule, lformat->hrule);
 		}
 	}
 
 	if (border == 2)
-		fputs("-+", fout);
+		fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
 	else if (border == 1)
-		fputc('-', fout);
+		fputs(lformat->hrule, fout);
 
 	fputc('\n', fout);
 }
@@ -403,6 +442,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 	bool		opt_numeric_locale = cont->opt->numericLocale;
 	int			encoding = cont->opt->encoding;
 	unsigned short opt_border = cont->opt->border;
+	const printTextFormat *format = cont->opt->line_style;
 
 	unsigned int col_count = 0,
 				cell_count = 0;
@@ -431,6 +471,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 	int		   *bytes_output;	/* Bytes output for column value */
 	int			output_columns = 0;		/* Width of interactive console */
 	bool		is_pager = false;
+	const printTextLineFormat	*dformat = &format->lrule[PRINT_RULE_DATA];
 
 	if (cancel_pressed)
 		return;
@@ -709,7 +750,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 			int			curr_nl_line;
 
 			if (opt_border == 2)
-				_print_horizontal_line(col_count, width_wrap, opt_border, fout);
+				_print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_TOP, format, fout);
 
 			for (i = 0; i < col_count; i++)
 				pg_wcsformat((unsigned char *) cont->headers[i],
@@ -722,7 +763,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 			while (more_col_wrapping)
 			{
 				if (opt_border == 2)
-					fprintf(fout, "|%c", curr_nl_line ? '+' : ' ');
+					fprintf(fout, "%s%c", dformat->leftvrule, curr_nl_line ? '+' : ' ');
 				else if (opt_border == 1)
 					fputc(curr_nl_line ? '+' : ' ', fout);
 
@@ -753,19 +794,20 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 						if (opt_border == 0)
 							fputc(curr_nl_line ? '+' : ' ', fout);
 						else
-							fprintf(fout, " |%c", curr_nl_line ? '+' : ' ');
+							fprintf(fout, " %s%c", dformat->midvrule, curr_nl_line ? '+' : ' ');
 					}
 				}
 				curr_nl_line++;
 
 				if (opt_border == 2)
-					fputs(" |", fout);
+					fprintf(fout, " %s",
+						dformat->rightvrule);
 				else if (opt_border == 1)
 					fputc(' ', fout);
 				fputc('\n', fout);
 			}
 
-			_print_horizontal_line(col_count, width_wrap, opt_border, fout);
+			_print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_MIDDLE, format, fout);
 		}
 	}
 
@@ -811,7 +853,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 
 			/* left border */
 			if (opt_border == 2)
-				fputs("| ", fout);
+				fprintf(fout, "%s ", dformat->leftvrule);
 			else if (opt_border == 1)
 				fputc(' ', fout);
 
@@ -884,22 +926,26 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 						fputc(' ', fout);
 					/* Next value is beyond past newlines? */
 					else if (col_lineptrs[j + 1][curr_nl_line[j + 1]].ptr == NULL)
-						fputs("   ", fout);
+						fprintf(fout, " %s ",
+							format->midvrule_blank);
 					/* In wrapping of value? */
 					else if (bytes_output[j + 1] != 0)
-						fputs(" ; ", fout);
+						fprintf(fout, " %s ",
+							format->midvrule_wrap);
 					/* After first newline value */
 					else if (curr_nl_line[j + 1] != 0)
-						fputs(" : ", fout);
+						fprintf(fout, " %s ",
+							format->midvrule_cont);
+					/* Ordinary line */
 					else
-						/* Ordinary line */
-						fputs(" | ", fout);
+						fprintf(fout, " %s ",
+							dformat->midvrule);
 				}
 			}
 
 			/* end-of-row border */
 			if (opt_border == 2)
-				fputs(" |", fout);
+				fprintf(fout, " %s", dformat->rightvrule);
 			fputc('\n', fout);
 
 		} while (more_lines);
@@ -908,7 +954,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 	if (cont->opt->stop_table)
 	{
 		if (opt_border == 2 && !cancel_pressed)
-			_print_horizontal_line(col_count, width_wrap, opt_border, fout);
+			_print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_BOTTOM, format, fout);
 
 		/* print footers */
 		if (cont->footers && !opt_tuples_only && !cancel_pressed)
@@ -941,6 +987,62 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
 		ClosePager(fout);
 }
 
+static inline void
+print_aligned_vertical_line(const printTableContent *cont,
+			    unsigned long record,
+			    unsigned int hwidth,
+			    unsigned int dwidth,
+			    printTextRule pos,
+			    FILE *fout)
+{
+	unsigned short	opt_border = cont->opt->border;
+	unsigned int	i;
+	int		reclen = 0;
+	const printTextFormat *format = cont->opt->line_style;
+	const printTextLineFormat	*lformat = &format->lrule[pos];
+
+	if (opt_border == 2)
+		fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
+	else if (opt_border == 1)
+		fputs(lformat->hrule, fout);
+
+	if (record)
+	{
+		if (opt_border == 0)
+			reclen = fprintf(fout, "* Record %lu", record);
+		else
+			reclen = fprintf(fout, "[ RECORD %lu ]", record);
+	}
+	if (opt_border != 2)
+		reclen++;
+	if (reclen < 0)
+		reclen = 0;
+	for (i = reclen; i < hwidth; i++)
+		fputs(opt_border > 0 ? lformat->hrule : " ", fout);
+	reclen -= hwidth;
+
+	if (opt_border > 0)
+	{
+		if (reclen-- <= 0)
+			fputs(lformat->hrule, fout);
+		if (reclen-- <= 0)
+			fputs(lformat->midvrule, fout);
+		if (reclen-- <= 0)
+			fputs(lformat->hrule, fout);
+	}
+	else
+	{
+		if (reclen-- <= 0)
+			fputc(' ', fout);
+	}
+	if (reclen < 0)
+		reclen = 0;
+	for (i = reclen; i < dwidth; i++)
+		fputs(opt_border > 0 ? lformat->hrule : " ", fout);
+	if (opt_border == 2)
+		fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
+	fputc('\n', fout);
+}
 
 static void
 print_aligned_vertical(const printTableContent *cont, FILE *fout)
@@ -948,6 +1050,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 	bool		opt_tuples_only = cont->opt->tuples_only;
 	bool		opt_numeric_locale = cont->opt->numericLocale;
 	unsigned short opt_border = cont->opt->border;
+	const printTextFormat *format = cont->opt->line_style;
 	int			encoding = cont->opt->encoding;
 	unsigned long record = cont->opt->prior_records + 1;
 	const char *const * ptr;
@@ -958,9 +1061,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 				dheight = 1,
 				hformatsize = 0,
 				dformatsize = 0;
-	char	   *divider;
 	struct lineptr *hlineptr,
 			   *dlineptr;
+	const printTextLineFormat	*dformat = &format->lrule[PRINT_RULE_DATA];
 
 	if (cancel_pressed)
 		return;
@@ -1026,21 +1129,6 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 	dlineptr->ptr = pg_local_malloc(dformatsize);
 	hlineptr->ptr = pg_local_malloc(hformatsize);
 
-	/* make horizontal border */
-	divider = pg_local_malloc(hwidth + dwidth + 10);
-	divider[0] = '\0';
-	if (opt_border == 2)
-		strcat(divider, "+-");
-	for (i = 0; i < hwidth; i++)
-		strcat(divider, opt_border > 0 ? "-" : " ");
-	if (opt_border > 0)
-		strcat(divider, "-+-");
-	else
-		strcat(divider, " ");
-	for (i = 0; i < dwidth; i++)
-		strcat(divider, opt_border > 0 ? "-" : " ");
-	if (opt_border == 2)
-		strcat(divider, "-+");
 
 	if (cont->opt->start_table)
 	{
@@ -1052,40 +1140,25 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 	/* print records */
 	for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
 	{
-		int			line_count,
-					dcomplete,
-					hcomplete;
+		int		line_count,
+	    			dcomplete,
+				hcomplete;
+		printTextRule	pos = PRINT_RULE_MIDDLE;
+		if (i == 0)
+	  		pos = PRINT_RULE_TOP;
+		else if (!(*(ptr+1)))
+			pos = PRINT_RULE_BOTTOM;
+
+		if (cancel_pressed)
+			break;
 
 		if (i % cont->ncolumns == 0)
 		{
-			if (cancel_pressed)
-				break;
-			if (!opt_tuples_only)
-			{
-				char		record_str[64];
-				size_t		record_str_len;
-
-				if (opt_border == 0)
-					snprintf(record_str, 64, "* Record %lu", record++);
-				else
-					snprintf(record_str, 64, "[ RECORD %lu ]", record++);
-				record_str_len = strlen(record_str);
-
-				if (record_str_len + opt_border > strlen(divider))
-					fprintf(fout, "%.*s%s\n", opt_border, divider, record_str);
-				else
-				{
-					char	   *div_copy = pg_strdup(divider);
-
-					strncpy(div_copy + opt_border, record_str, record_str_len);
-					fprintf(fout, "%s\n", div_copy);
-					free(div_copy);
-				}
-			}
+	    		if (!opt_tuples_only)
+				print_aligned_vertical_line(cont, record++, hwidth, dwidth, pos, fout);
 			else if (i != 0 || !cont->opt->start_table || opt_border == 2)
-				fprintf(fout, "%s\n", divider);
+				print_aligned_vertical_line(cont, 0, hwidth, dwidth, pos, fout);
 		}
-
 		/* Format the header */
 		pg_wcsformat((unsigned char *) cont->headers[i % cont->ncolumns],
 					 strlen(cont->headers[i % cont->ncolumns]),
@@ -1099,7 +1172,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 		while (!dcomplete || !hcomplete)
 		{
 			if (opt_border == 2)
-				fputs("| ", fout);
+				fprintf(fout, "%s ", dformat->leftvrule);
 			if (!hcomplete)
 			{
 				fprintf(fout, "%-s%*s", hlineptr[line_count].ptr,
@@ -1112,9 +1185,13 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 				fprintf(fout, "%*s", hwidth, "");
 
 			if (opt_border > 0)
-				fprintf(fout, " %c ", (line_count == 0) ? '|' : ':');
+			{
+				fprintf(fout, " %s ",
+					(line_count == 0) ?
+					format->midvrule_cont : dformat->midvrule);
+			}
 			else
-				fputs(" ", fout);
+				fputc(' ', fout);
 
 			if (!dcomplete)
 			{
@@ -1125,8 +1202,8 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 					if (opt_border < 2)
 						fprintf(fout, "%s\n", my_cell);
 					else
-						fprintf(fout, "%-s%*s |\n", my_cell,
-								(int) (dwidth - strlen(my_cell)), "");
+						fprintf(fout, "%-s%*s %s\n", my_cell,
+								(int) (dwidth - strlen(my_cell)), "", dformat->rightvrule);
 					free(my_cell);
 				}
 				else
@@ -1134,8 +1211,8 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 					if (opt_border < 2)
 						fprintf(fout, "%s\n", dlineptr[line_count].ptr);
 					else
-						fprintf(fout, "%-s%*s |\n", dlineptr[line_count].ptr,
-								dwidth - dlineptr[line_count].width, "");
+						fprintf(fout, "%-s%*s %s\n", dlineptr[line_count].ptr,
+								dwidth - dlineptr[line_count].width, "", dformat->rightvrule);
 				}
 
 				if (!dlineptr[line_count + 1].ptr)
@@ -1146,7 +1223,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 				if (opt_border < 2)
 					fputc('\n', fout);
 				else
-					fprintf(fout, "%*s |\n", dwidth, "");
+					fprintf(fout, "%*s %s\n", dwidth, "", dformat->rightvrule);
 			}
 			line_count++;
 		}
@@ -1155,7 +1232,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 	if (cont->opt->stop_table)
 	{
 		if (opt_border == 2 && !cancel_pressed)
-			fprintf(fout, "%s\n", divider);
+			print_aligned_vertical_line(cont, 0, hwidth, dwidth, PRINT_RULE_BOTTOM, fout);
 
 		/* print footers */
 		if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
@@ -1171,7 +1248,6 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
 		fputc('\n', fout);
 	}
 
-	free(divider);
 	free(hlineptr->ptr);
 	free(dlineptr->ptr);
 	free(hlineptr);
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index 55122d7..dd38c5d 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -23,10 +23,36 @@ enum printFormat
 	/* add your favourite output format here ... */
 };
 
+typedef struct printTextLineFormat
+{
+	const char *hrule;
+	const char *leftvrule;
+	const char *midvrule;
+	const char *rightvrule;
+} printTextLineFormat;
+
+typedef struct printTextFormat
+{
+	const char *name;
+	printTextLineFormat	lrule[4];
+	const char		*midvrule_cont;
+	const char		*midvrule_wrap;
+	const char		*midvrule_blank;
+} printTextFormat;
+
+typedef enum printTextRule
+{
+	PRINT_RULE_TOP,
+	PRINT_RULE_MIDDLE,
+	PRINT_RULE_BOTTOM,
+	PRINT_RULE_DATA
+} printTextRule;
 
 typedef struct printTableOpt
 {
 	enum printFormat format;	/* one of the above */
+	const printTextFormat	*line_style;    /* table line formatting */
+	bool		line_style_set;    /* table line formatting set manually*/
 	bool		expanded;		/* expanded/vertical output (if supported by
 								 * output format) */
 	unsigned short int border;	/* Print a border around the table. 0=none,
@@ -95,6 +121,9 @@ typedef struct printQueryOpt
 										 * gettext on col i */
 } printQueryOpt;
 
+extern const printTextFormat asciiformat;
+extern const printTextFormat utf8format;
+
 
 extern FILE *PageOutput(int lines, unsigned short int pager);
 extern void ClosePager(FILE *pagerpipe);
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 429e5d9..eb855be 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -125,6 +125,10 @@ main(int argc, char *argv[])
 
 	/* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
 	pset.popt.topt.format = PRINT_ALIGNED;
+
+	/* Default table style to plain ASCII */
+	pset.popt.topt.line_style = &asciiformat;
+	pset.popt.topt.line_style_set = false;
 	pset.popt.topt.border = 1;
 	pset.popt.topt.pager = 1;
 	pset.popt.topt.start_table = true;
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 3e38b06..69a0fe5 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -2264,7 +2264,7 @@ psql_completion(char *text, int start, int end)
 	{
 		static const char *const my_list[] =
 		{"format", "border", "expanded",
-			"null", "fieldsep", "tuples_only", "title", "tableattr", "pager",
+			"null", "fieldsep", "tuples_only", "title", "tableattr", "linestyle", "pager",
 		"recordsep", NULL};
 
 		COMPLETE_WITH_LIST(my_list);
diff --git a/src/test/regress/pg_regress_main.c b/src/test/regress/pg_regress_main.c
index cb477a6..681a82e 100644
--- a/src/test/regress/pg_regress_main.c
+++ b/src/test/regress/pg_regress_main.c
@@ -59,7 +59,7 @@ psql_start_test(const char *testname,
 	add_stringlist_item(expectfiles, expectfile);
 
 	snprintf(psql_cmd, sizeof(psql_cmd),
-			 SYSTEMQUOTE "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
+			 SYSTEMQUOTE "\"%s%spsql\" -X -a -q -P linestyle=ascii -d \"%s\" < \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
 			 psqldir ? psqldir : "",
 			 psqldir ? "/" : "",
 			 dblist->str,
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to