Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.145
diff -c -c -r1.145 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml	14 Jun 2005 02:57:38 -0000	1.145
--- doc/src/sgml/ref/psql-ref.sgml	10 Jul 2005 03:24:16 -0000
***************
*** 1493,1498 ****
--- 1493,1510 ----
            </varlistentry>
  
            <varlistentry>
+           <term><literal>numericsep</literal></term>
+           <listitem>
+           <para>
+           Specifies the character separator between groups of three digits
+           to the left of the decimal marker.  The default is <literal>''</>
+           (none).  Setting this to a period also changes the decimal marker 
+           to a comma.
+           </para>
+           </listitem>
+           </varlistentry>
+ 
+           <varlistentry>
            <term><literal>recordsep</literal></term>
            <listitem>
            <para>
Index: src/bin/psql/command.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.146
diff -c -c -r1.146 command.c
*** src/bin/psql/command.c	13 Jun 2005 06:36:22 -0000	1.146
--- src/bin/psql/command.c	10 Jul 2005 03:24:17 -0000
***************
*** 838,844 ****
  	else if (strcmp(cmd, "x") == 0)
  		success = do_pset("expanded", NULL, &pset.popt, quiet);
  
- 
  	/* \z -- list table rights (equivalent to \dp) */
  	else if (strcmp(cmd, "z") == 0)
  	{
--- 838,843 ----
***************
*** 1421,1426 ****
--- 1420,1436 ----
  				   : _("Expanded display is off.\n"));
  	}
  
+ 	else if (strcmp(param, "numericsep") == 0)
+ 	{
+ 		if (value)
+ 		{
+ 			free(popt->topt.numericSep);
+ 			popt->topt.numericSep = pg_strdup(value);
+ 		}
+ 		if (!quiet)
+ 			printf(_("Numeric separator is \"%s\".\n"), popt->topt.numericSep);
+ 	}
+ 
  	/* null display */
  	else if (strcmp(param, "null") == 0)
  	{
Index: src/bin/psql/help.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/help.c,v
retrieving revision 1.103
diff -c -c -r1.103 help.c
*** src/bin/psql/help.c	6 Jul 2005 03:14:48 -0000	1.103
--- src/bin/psql/help.c	10 Jul 2005 03:24:18 -0000
***************
*** 239,245 ****
  	fprintf(output, _("  \\pset NAME [VALUE]\n"
  					  "                 set table output option\n"
  					  "                 (NAME := {format|border|expanded|fieldsep|footer|null|\n"
! 	"                 recordsep|tuples_only|title|tableattr|pager})\n"));
  	fprintf(output, _("  \\t             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"));
--- 239,245 ----
  	fprintf(output, _("  \\pset NAME [VALUE]\n"
  					  "                 set table output option\n"
  					  "                 (NAME := {format|border|expanded|fieldsep|footer|null|\n"
! 	"                 numericsep|recordsep|tuples_only|title|tableattr|pager})\n"));
  	fprintf(output, _("  \\t             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"));
Index: src/bin/psql/print.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/print.c,v
retrieving revision 1.60
diff -c -c -r1.60 print.c
*** src/bin/psql/print.c	14 Jun 2005 22:15:57 -0000	1.60
--- src/bin/psql/print.c	10 Jul 2005 03:24:24 -0000
***************
*** 29,48 ****
  
  #include "mbprint.h"
  
  /*************************/
  /* Unaligned text		 */
  /*************************/
  
  
  static void
! print_unaligned_text(const char *title, const char *const * headers,
! 				  const char *const * cells, const char *const * footers,
!  const char *opt_fieldsep, const char *opt_recordsep, bool opt_barebones,
! 					 FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const * ptr;
  	bool		need_recordsep = false;
  
  	if (!opt_fieldsep)
--- 29,135 ----
  
  #include "mbprint.h"
  
+ static int
+ num_numericseps(const char *my_str)
+ {
+ 	int old_len, dec_len, int_len;
+ 
+ 	if (my_str[0] == '-')
+ 		my_str++;
+     
+ 	old_len = strlen(my_str);
+ 	dec_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
+ 
+ 	int_len = old_len - dec_len;
+ 	if (int_len % 3 != 0)
+ 		return int_len / 3;
+ 	else
+ 		return int_len / 3 - 1;	/* no leading separator */
+ }
+ static int
+ len_with_numericsep(const char *my_str)
+ {
+ 	return strlen(my_str) + num_numericseps(my_str);
+ }
+ 
+ static void 
+ format_numericsep(char *my_str, char *numericsep)
+ {
+ 	int i, j, digits_before_sep, old_len, new_len, dec_len, int_len;
+ 	char *dec_point;
+ 	char *new_str;
+ 	char *dec_value;
+     
+ 	if (strcmp(numericsep, ".") != 0)
+ 		dec_point = ".";
+ 	else
+ 		dec_point = ",";
+     
+ 	if (my_str[0] == '-')
+ 		my_str++;
+     
+ 	old_len = strlen(my_str);
+ 	dec_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
+ 	int_len = old_len - dec_len;
+ 	digits_before_sep = int_len % 3;
+ 
+ 	new_len = int_len + int_len / 3 + dec_len;
+ 	if (digits_before_sep == 0)
+ 		new_len--;	/* no leading separator */
+ 
+ 	new_str = malloc(new_len);
+ 	if (!new_str)
+ 	{
+ 		fprintf(stderr, _("out of memory\n"));
+ 		exit(EXIT_FAILURE);
+ 	}
+ 
+ 	for (i=0, j=0; ; i++, j++)
+ 	{
+ 		/* hit decimal point */
+ 		if (my_str[i] == '.')
+ 		{
+ 			new_str[j] = *dec_point;
+ 			new_str[j+1] = '\0';
+ 			dec_value = strchr(my_str, '.');
+ 			strcat(new_str, ++dec_value);
+ 			break;
+ 		}
+ 
+ 		/* end of string */
+ 		if (my_str[i] == '\0')
+ 		{
+ 			new_str[j] = '\0';
+ 			break;
+ 		}
+     
+ 		/* add separator? */
+ 		if (i != 0 &&
+ 			(i - (digits_before_sep ? digits_before_sep : 3)) % 3 == 0)
+ 			new_str[j++] = *numericsep;
+ 
+ 		new_str[j] = my_str[i];
+ 	}
+ 	    
+ 	strcpy(my_str, new_str);
+ 	free(new_str);
+ }
+ 
  /*************************/
  /* Unaligned text		 */
  /*************************/
  
  
  static void
! print_unaligned_text(const char *title, const char *const *headers,
! 					 const char *const *cells, const char *const *footers,
! 					 const char *opt_align, const char *opt_fieldsep,
! 					 const char *opt_recordsep, bool opt_barebones,
! 					 char *opt_numericsep, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const *ptr;
  	bool		need_recordsep = false;
  
  	if (!opt_fieldsep)
***************
*** 77,83 ****
  			fputs(opt_recordsep, fout);
  			need_recordsep = false;
  		}
! 		fputs(*ptr, fout);
  		if ((i + 1) % col_count)
  			fputs(opt_fieldsep, fout);
  		else
--- 164,187 ----
  			fputs(opt_recordsep, fout);
  			need_recordsep = false;
  		}
! 		if ((opt_align[i % col_count] == 'r') && strlen(*ptr) > 0 &&
! 			opt_numericsep != NULL && strlen(opt_numericsep) > 0)
! 		{
! 			char *my_cell = malloc(len_with_numericsep(*ptr));
! 		
! 			if (!my_cell)
! 			{
! 				fprintf(stderr, _("out of memory\n"));
! 				exit(EXIT_FAILURE);
! 			}
! 			strcpy(my_cell, *ptr);
! 			format_numericsep(my_cell, opt_numericsep);
! 			fputs(my_cell, fout);
! 			free(my_cell);
! 		}
! 		else
! 			fputs(*ptr, fout);
! 		
  		if ((i + 1) % col_count)
  			fputs(opt_fieldsep, fout);
  		else
***************
*** 107,120 ****
  
  
  static void
! print_unaligned_vertical(const char *title, const char *const * headers,
! 				  const char *const * cells, const char *const * footers,
!  const char *opt_fieldsep, const char *opt_recordsep, bool opt_barebones,
! 						 FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const * ptr;
  
  	if (!opt_fieldsep)
  		opt_fieldsep = "";
--- 211,225 ----
  
  
  static void
! print_unaligned_vertical(const char *title, const char *const *headers,
! 						 const char *const *cells,
! 						 const char *const *footers, const char *opt_align,
! 						 const char *opt_fieldsep, const char *opt_recordsep,
! 						 bool opt_barebones, char *opt_numericsep, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const *ptr;
  
  	if (!opt_fieldsep)
  		opt_fieldsep = "";
***************
*** 141,147 ****
  
  		fputs(headers[i % col_count], fout);
  		fputs(opt_fieldsep, fout);
! 		fputs(*ptr, fout);
  	}
  
  	/* print footers */
--- 246,268 ----
  
  		fputs(headers[i % col_count], fout);
  		fputs(opt_fieldsep, fout);
! 		if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
! 			opt_numericsep != NULL && strlen(opt_numericsep) > 0)
! 		{
! 			char *my_cell = malloc(len_with_numericsep(*ptr));
! 		
! 			if (!my_cell)
! 			{
! 				fprintf(stderr, _("out of memory\n"));
! 				exit(EXIT_FAILURE);
! 			}
! 			strcpy(my_cell, *ptr);
! 			format_numericsep(my_cell, opt_numericsep);
! 			fputs(my_cell, fout);
! 			free(my_cell);
! 		}
! 		else
! 			fputs(*ptr, fout);
  	}
  
  	/* print footers */
***************
*** 202,210 ****
  
  
  static void
! print_aligned_text(const char *title, const char *const * headers,
! 				   const char *const * cells, const char *const * footers,
! 				   const char *opt_align, bool opt_barebones,
  				   unsigned short int opt_border, int encoding,
  				   FILE *fout)
  {
--- 323,331 ----
  
  
  static void
! print_aligned_text(const char *title, const char *const *headers,
! 				   const char *const *cells, const char *const *footers,
! 				   const char *opt_align, bool opt_barebones, char *opt_numericsep,
  				   unsigned short int opt_border, int encoding,
  				   FILE *fout)
  {
***************
*** 216,222 ****
  				tmp;
  	unsigned int *widths,
  				total_w;
! 	const char *const * ptr;
  
  	/* count columns */
  	for (ptr = headers; *ptr; ptr++)
--- 337,343 ----
  				tmp;
  	unsigned int *widths,
  				total_w;
! 	const char *const *ptr;
  
  	/* count columns */
  	for (ptr = headers; *ptr; ptr++)
***************
*** 271,277 ****
  
  	for (i = 0, ptr = cells; *ptr; ptr++, i++)
  	{
! 		tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr), encoding);
  		if (tmp > widths[i % col_count])
  			widths[i % col_count] = tmp;
  		cell_w[i] = tmp;
--- 392,406 ----
  
  	for (i = 0, ptr = cells; *ptr; ptr++, i++)
  	{
! 		int numericseps;
! 
! 		if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
! 			opt_numericsep != NULL && strlen(opt_numericsep) > 0)
! 		    numericseps = num_numericseps(*ptr);
! 		else 
! 		    numericseps = 0;
! 		
! 		tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr), encoding) + numericseps;
  		if (tmp > widths[i % col_count])
  			widths[i % col_count] = tmp;
  		cell_w[i] = tmp;
***************
*** 351,358 ****
  		/* content */
  		if (opt_align[i % col_count] == 'r')
  		{
! 			fprintf(fout, "%*s%s",
! 					widths[i % col_count] - cell_w[i], "", cells[i]);
  		}
  		else
  		{
--- 480,501 ----
  		/* content */
  		if (opt_align[i % col_count] == 'r')
  		{
! 		    if (strlen(*ptr) > 0 && opt_numericsep != NULL && strlen(opt_numericsep) > 0)
! 		    {
! 				char *my_cell = malloc(cell_w[i]);
! 
! 				if (!my_cell)
! 				{
! 					fprintf(stderr, _("out of memory\n"));
! 					exit(EXIT_FAILURE);
! 				}
! 				strcpy(my_cell, *ptr);
! 				format_numericsep(my_cell, opt_numericsep);
! 				fprintf(fout, "%*s%s", widths[i % col_count] - cell_w[i], "", my_cell);
! 				free(my_cell);
! 		    }
! 			else
! 				fprintf(fout, "%*s%s", widths[i % col_count] - cell_w[i], "", *ptr);
  		}
  		else
  		{
***************
*** 406,419 ****
  
  
  static void
! print_aligned_vertical(const char *title, const char *const * headers,
! 				  const char *const * cells, const char *const * footers,
! 					   bool opt_barebones, unsigned short int opt_border,
  					   int encoding, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int record = 1;
! 	const char *const * ptr;
  	unsigned int i,
  				tmp = 0,
  				hwidth = 0,
--- 549,563 ----
  
  
  static void
! print_aligned_vertical(const char *title, const char *const *headers,
! 					   const char *const *cells, const char *const *footers,
! 					   const char *opt_align, bool opt_barebones,
! 					   char *opt_numericsep, unsigned short int opt_border,
  					   int encoding, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int record = 1;
! 	const char *const *ptr;
  	unsigned int i,
  				tmp = 0,
  				hwidth = 0,
***************
*** 471,477 ****
  	/* find longest data cell */
  	for (i = 0, ptr = cells; *ptr; ptr++, i++)
  	{
! 		tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr), encoding);
  		if (tmp > dwidth)
  			dwidth = tmp;
  		cell_w[i] = tmp;
--- 615,629 ----
  	/* find longest data cell */
  	for (i = 0, ptr = cells; *ptr; ptr++, i++)
  	{
! 		int numericseps;
! 
! 		if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
! 			opt_numericsep != NULL && strlen(opt_numericsep) > 0)
! 		    numericseps = num_numericseps(*ptr);
! 		else 
! 		    numericseps = 0;
! 
! 		tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr), encoding) + numericseps;
  		if (tmp > dwidth)
  			dwidth = tmp;
  		cell_w[i] = tmp;
***************
*** 556,565 ****
  		else
  			fputs(" ", fout);
  
! 		if (opt_border < 2)
! 			fprintf(fout, "%s\n", *ptr);
! 		else
! 			fprintf(fout, "%-s%*s |\n", *ptr, dwidth - cell_w[i], "");
  	}
  
  	if (opt_border == 2)
--- 708,731 ----
  		else
  			fputs(" ", fout);
  
! 		{
! 			char *my_cell = malloc(cell_w[i]);
! 
! 			if (!my_cell)
! 			{
! 				fprintf(stderr, _("out of memory\n"));
! 				exit(EXIT_FAILURE);
! 			}
! 			strcpy(my_cell, *ptr);
! 			if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
! 				opt_numericsep != NULL && strlen(opt_numericsep) > 0)
! 			    format_numericsep(my_cell, opt_numericsep);
! 			if (opt_border < 2)
! 				puts(my_cell);
! 			else
! 				fprintf(fout, "%-s%*s |\n", my_cell, dwidth - cell_w[i], "");
! 			free(my_cell);
! 		}
  	}
  
  	if (opt_border == 2)
***************
*** 637,651 ****
  
  
  static void
! print_html_text(const char *title, const char *const * headers,
! 				const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
! 				const char *opt_table_attr,
! 				FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const * ptr;
  
  	fprintf(fout, "<table border=\"%d\"", opt_border);
  	if (opt_table_attr)
--- 803,817 ----
  
  
  static void
! print_html_text(const char *title, const char *const *headers,
! 				const char *const *cells, const char *const *footers,
! 				const char *opt_align, bool opt_barebones,
! 				char *opt_numericsep, unsigned short int opt_border,
! 				const char *opt_table_attr, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const *ptr;
  
  	fprintf(fout, "<table border=\"%d\"", opt_border);
  	if (opt_table_attr)
***************
*** 683,693 ****
  			fputs("  <tr valign=\"top\">\n", fout);
  
  		fprintf(fout, "    <td align=\"%s\">", opt_align[(i) % col_count] == 'r' ? "right" : "left");
! 		if ((*ptr)[strspn(*ptr, " \t")] == '\0')		/* is string only
! 														 * whitespace? */
  			fputs("&nbsp; ", fout);
  		else
  			html_escaped_print(*ptr, fout);
  		fputs("</td>\n", fout);
  
  		if ((i + 1) % col_count == 0)
--- 849,875 ----
  			fputs("  <tr valign=\"top\">\n", fout);
  
  		fprintf(fout, "    <td align=\"%s\">", opt_align[(i) % col_count] == 'r' ? "right" : "left");
! 		/* is string only whitespace? */
! 		if ((*ptr)[strspn(*ptr, " \t")] == '\0')		
  			fputs("&nbsp; ", fout);
+ 		else if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
+ 				 opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ 		{
+ 			char *my_cell = malloc(len_with_numericsep(*ptr));
+ 
+ 			if (!my_cell)
+ 			{
+ 				fprintf(stderr, _("out of memory\n"));
+ 				exit(EXIT_FAILURE);
+ 			}
+ 		    strcpy(my_cell, *ptr);
+ 		    format_numericsep(my_cell, opt_numericsep);
+ 		    html_escaped_print(my_cell, fout);
+ 		    free(my_cell);
+ 		}
  		else
  			html_escaped_print(*ptr, fout);
+ 
  		fputs("</td>\n", fout);
  
  		if ((i + 1) % col_count == 0)
***************
*** 714,729 ****
  
  
  static void
! print_html_vertical(const char *title, const char *const * headers,
! 				  const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
! 					const char *opt_table_attr,
! 					FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
  	unsigned int record = 1;
! 	const char *const * ptr;
  
  	fprintf(fout, "<table border=\"%d\"", opt_border);
  	if (opt_table_attr)
--- 896,911 ----
  
  
  static void
! print_html_vertical(const char *title, const char *const *headers,
! 				  const char *const *cells, const char *const *footers,
! 				  const char *opt_align, bool opt_barebones,
! 				  char *opt_numericsep, unsigned short int opt_border,
! 				  const char *opt_table_attr, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
  	unsigned int record = 1;
! 	const char *const *ptr;
  
  	fprintf(fout, "<table border=\"%d\"", opt_border);
  	if (opt_table_attr)
***************
*** 758,768 ****
  		fputs("</th>\n", fout);
  
  		fprintf(fout, "    <td align=\"%s\">", opt_align[i % col_count] == 'r' ? "right" : "left");
! 		if ((*ptr)[strspn(*ptr, " \t")] == '\0')		/* is string only
! 														 * whitespace? */
  			fputs("&nbsp; ", fout);
  		else
  			html_escaped_print(*ptr, fout);
  		fputs("</td>\n  </tr>\n", fout);
  	}
  
--- 940,966 ----
  		fputs("</th>\n", fout);
  
  		fprintf(fout, "    <td align=\"%s\">", opt_align[i % col_count] == 'r' ? "right" : "left");
! 		/* is string only whitespace? */
! 		if ((*ptr)[strspn(*ptr, " \t")] == '\0')		
  			fputs("&nbsp; ", fout);
+ 		else if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
+ 			opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+ 		{
+ 			char *my_cell = malloc(len_with_numericsep(*ptr));
+ 		    
+ 			if (!my_cell)
+ 			{
+ 				fprintf(stderr, _("out of memory\n"));
+ 				exit(EXIT_FAILURE);
+ 			}
+ 		    strcpy(my_cell, *ptr);
+ 		    format_numericsep(my_cell, opt_numericsep);
+ 		    html_escaped_print(my_cell, fout);
+ 		    free(my_cell);
+ 		}
  		else
  			html_escaped_print(*ptr, fout);
+ 
  		fputs("</td>\n  </tr>\n", fout);
  	}
  
***************
*** 829,842 ****
  
  
  static void
! print_latex_text(const char *title, const char *const * headers,
! 				 const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
! 				 FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const * ptr;
  
  
  	/* print title */
--- 1027,1040 ----
  
  
  static void
! print_latex_text(const char *title, const char *const *headers,
! 				 const char *const *cells, const char *const *footers,
! 				 const char *opt_align, bool opt_barebones,
! 				 unsigned short int opt_border, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const *ptr;
  
  
  	/* print title */
***************
*** 921,934 ****
  
  
  static void
! print_latex_vertical(const char *title, const char *const * headers,
! 				  const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
! 					 FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const * ptr;
  	unsigned int record = 1;
  
  	(void) opt_align;			/* currently unused parameter */
--- 1119,1132 ----
  
  
  static void
! print_latex_vertical(const char *title, const char *const *headers,
! 				  const char *const *cells, const char *const *footers,
! 				  const char *opt_align, bool opt_barebones,
! 				  unsigned short int opt_border, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const *ptr;
  	unsigned int record = 1;
  
  	(void) opt_align;			/* currently unused parameter */
***************
*** 1027,1040 ****
  
  
  static void
! print_troff_ms_text(const char *title, const char *const * headers,
! 				 const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
! 				 FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const * ptr;
  
  
  	/* print title */
--- 1225,1238 ----
  
  
  static void
! print_troff_ms_text(const char *title, const char *const *headers,
! 				 const char *const *cells, const char *const *footers,
! 				 const char *opt_align, bool opt_barebones,
! 				 unsigned short int opt_border, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const *ptr;
  
  
  	/* print title */
***************
*** 1111,1124 ****
  
  
  static void
! print_troff_ms_vertical(const char *title, const char *const * headers,
! 				  const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
! 					 FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const * ptr;
  	unsigned int record = 1;
          unsigned short current_format = 0; /* 0=none, 1=header, 2=body */
  
--- 1309,1322 ----
  
  
  static void
! print_troff_ms_vertical(const char *title, const char *const *headers,
! 				  const char *const *cells, const char *const *footers,
! 				  const char *opt_align, bool opt_barebones,
! 				  unsigned short int opt_border, FILE *fout)
  {
  	unsigned int col_count = 0;
  	unsigned int i;
! 	const char *const *ptr;
  	unsigned int record = 1;
          unsigned short current_format = 0; /* 0=none, 1=header, 2=body */
  
***************
*** 1263,1271 ****
  
  void
  printTable(const char *title,
! 		   const char *const * headers,
! 		   const char *const * cells,
! 		   const char *const * footers,
  		   const char *align,
  		   const printTableOpt *opt, FILE *fout, FILE *flog)
  {
--- 1461,1469 ----
  
  void
  printTable(const char *title,
! 		   const char *const *headers,
! 		   const char *const *cells,
! 		   const char *const *footers,
  		   const char *align,
  		   const printTableOpt *opt, FILE *fout, FILE *flog)
  {
***************
*** 1298,1304 ****
  		int			col_count = 0,
  					row_count = 0,
  					lines;
! 		const char *const * ptr;
  
  		/* rough estimate of columns and rows */
  		if (headers)
--- 1496,1502 ----
  		int			col_count = 0,
  					row_count = 0,
  					lines;
! 		const char *const *ptr;
  
  		/* rough estimate of columns and rows */
  		if (headers)
***************
*** 1325,1362 ****
  	/* print the stuff */
  
  	if (flog)
! 		print_aligned_text(title, headers, cells, footers, align, opt->tuples_only, border, opt->encoding, flog);
  
  	switch (opt->format)
  	{
  		case PRINT_UNALIGNED:
  			if (use_expanded)
! 				print_unaligned_vertical(title, headers, cells, footers,
  										 opt->fieldSep, opt->recordSep,
! 										 opt->tuples_only, output);
  			else
! 				print_unaligned_text(title, headers, cells, footers,
  									 opt->fieldSep, opt->recordSep,
! 									 opt->tuples_only, output);
  			break;
  		case PRINT_ALIGNED:
  			if (use_expanded)
! 				print_aligned_vertical(title, headers, cells, footers,
! 									   opt->tuples_only, border,
  									   opt->encoding, output);
  			else
! 				print_aligned_text(title, headers, cells, footers,
! 								   align, opt->tuples_only,
  								   border, opt->encoding, output);
  			break;
  		case PRINT_HTML:
  			if (use_expanded)
! 				print_html_vertical(title, headers, cells, footers,
! 									align, opt->tuples_only,
  									border, opt->tableAttr, output);
  			else
  				print_html_text(title, headers, cells, footers,
! 								align, opt->tuples_only, border,
  								opt->tableAttr, output);
  			break;
  		case PRINT_LATEX:
--- 1523,1560 ----
  	/* print the stuff */
  
  	if (flog)
! 		print_aligned_text(title, headers, cells, footers, align, opt->tuples_only, opt->numericSep, border, opt->encoding, flog);
  
  	switch (opt->format)
  	{
  		case PRINT_UNALIGNED:
  			if (use_expanded)
! 				print_unaligned_vertical(title, headers, cells, footers, align,
  										 opt->fieldSep, opt->recordSep,
! 										 opt->tuples_only, opt->numericSep, output);
  			else
! 				print_unaligned_text(title, headers, cells, footers, align,
  									 opt->fieldSep, opt->recordSep,
! 									 opt->tuples_only, opt->numericSep, output);
  			break;
  		case PRINT_ALIGNED:
  			if (use_expanded)
! 				print_aligned_vertical(title, headers, cells, footers, align,
! 									   opt->tuples_only, opt->numericSep, border,
  									   opt->encoding, output);
  			else
! 				print_aligned_text(title, headers, cells, footers, align,
! 								   opt->tuples_only, opt->numericSep,
  								   border, opt->encoding, output);
  			break;
  		case PRINT_HTML:
  			if (use_expanded)
! 				print_html_vertical(title, headers, cells, footers, align,
! 									opt->tuples_only, opt->numericSep,
  									border, opt->tableAttr, output);
  			else
  				print_html_text(title, headers, cells, footers,
! 								align, opt->tuples_only, opt->numericSep, border,
  								opt->tableAttr, output);
  			break;
  		case PRINT_LATEX:
Index: src/bin/psql/print.h
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/print.h,v
retrieving revision 1.25
diff -c -c -r1.25 print.h
*** src/bin/psql/print.h	14 Jun 2005 02:57:41 -0000	1.25
--- src/bin/psql/print.h	10 Jul 2005 03:24:24 -0000
***************
*** 40,45 ****
--- 40,46 ----
  	char	   *fieldSep;		/* field separator for unaligned text mode */
  	char	   *recordSep;		/* record separator for unaligned text
  								 * mode */
+ 	char	   *numericSep;		/* numeric units separator */
  	char	   *tableAttr;		/* attributes for HTML <table ...> */
  	int			encoding;		/* character encoding */
  	bool		normal_query;	/* are we presenting the results of a
