On Tue, Oct 06, 2009 at 10:44:27AM +0100, Roger Leigh wrote:
> 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).

This patch included a bit of code not intended for inclusion
(setting of client encoding based on locale), which the attached
(and hopefully final!) revision of the patch excludes.


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..223f11c 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -46,6 +46,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 +597,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));
 			}
@@ -1432,6 +1441,13 @@ SyncVariables(void)
 	/* get stuff from connection */
 	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 +1788,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