Valid HTML/XHTML output for psql

Started by Greg Sabino Mullaneabout 23 years ago5 messagespatches
Jump to latest
#1Greg Sabino Mullane
greg@turnstep.com

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Attached is a patch that enhances the output of psql's HTML mode.
The output now validates as HTML 4.01 Strict, XHTML 1.0 strict,
and XHTML 1.1 (assuming you wrap it in a valid html/body document).

It also wraps the output of PGRES_COMMAND_OK if the HTML tag is on,
for full compliance: this is why html_escaped_print has to be externalized.

--
Greg Sabino Mullane greg@turnstep.com
PGP Key: 0x14964AC8 200306011737

Index: common.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.62
diff -c -r1.62 common.c
*** common.c	25 Mar 2003 02:44:36 -0000	1.62
--- common.c	1 Jun 2003 20:34:41 -0000
***************
*** 525,531 ****
  					success = true;
  					sprintf(buf, "%u", (unsigned int) PQoidValue(results));
  					if (!QUIET())
! 						fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
  					SetVariable(pset.vars, "LASTOID", buf);
  					break;
  				}
--- 525,542 ----
  					success = true;
  					sprintf(buf, "%u", (unsigned int) PQoidValue(results));
  					if (!QUIET())
! 						{
! 							if (pset.popt.topt.format == PRINT_HTML)
! 							{
! 								fputs("<p>", pset.queryFout);
! 								html_escaped_print(PQcmdStatus(results), pset.queryFout);
! 								fputs("</p>\n", pset.queryFout);
! 							}
! 							else
! 							{
! 								fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
! 							}
! 						}
  					SetVariable(pset.vars, "LASTOID", buf);
  					break;
  				}
Index: print.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.c,v
retrieving revision 1.37
diff -c -r1.37 print.c
*** print.c	4 Apr 2003 15:48:38 -0000	1.37
--- print.c	1 Jun 2003 20:34:42 -0000
***************
*** 577,583 ****
  /**********************/
! static void
  html_escaped_print(const char *in, FILE *fout)
  {
  	const char *p;
--- 577,583 ----
  /**********************/
! void
  html_escaped_print(const char *in, FILE *fout)
  {
  	const char *p;
***************
*** 595,601 ****
  				fputs("&gt;", fout);
  				break;
  			case '\n':
! 				fputs("<br>", fout);
  				break;
  			default:
  				fputc(*p, fout);
--- 595,607 ----
  				fputs("&gt;", fout);
  				break;
  			case '\n':
! 				fputs("<br />\n", fout);
! 				break;
! 			case '"':
! 				fputs("&quot;", fout);
! 				break;
! 			case '\'':
! 				fputs("&apos;", fout);
  				break;
  			default:
  				fputc(*p, fout);
***************
*** 615,621 ****
  	unsigned int i;
  	const char *const * ptr;
! 	fprintf(fout, "<table border=%d", opt_border);
  	if (opt_table_attr)
  		fprintf(fout, " %s", opt_table_attr);
  	fputs(">\n", fout);
--- 621,627 ----
  	unsigned int i;
  	const char *const * ptr;
! 	fprintf(fout, "<table border=\"%d\"", opt_border);
  	if (opt_table_attr)
  		fprintf(fout, " %s", opt_table_attr);
  	fputs(">\n", fout);
***************
*** 636,642 ****
  		col_count++;
  		if (!opt_barebones)
  		{
! 			fputs("    <th align=center>", fout);
  			html_escaped_print(*ptr, fout);
  			fputs("</th>\n", fout);
  		}
--- 642,648 ----
  		col_count++;
  		if (!opt_barebones)
  		{
! 			fputs("    <th align=\"center\">", fout);
  			html_escaped_print(*ptr, fout);
  			fputs("</th>\n", fout);
  		}
***************
*** 648,659 ****
  	for (i = 0, ptr = cells; *ptr; i++, ptr++)
  	{
  		if (i % col_count == 0)
! 			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);
--- 654,664 ----
  	for (i = 0, ptr = cells; *ptr; i++, ptr++)
  	{
  		if (i % col_count == 0)
! 			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);
***************
*** 666,678 ****

/* print footers */

! if (footers && !opt_barebones)
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br>\n", fout);
}
!
fputc('\n', fout);
}

--- 671,686 ----

/* print footers */

! if (!opt_barebones && footers && *footers)
! {
! fputs("<p>", fout);
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br />\n", fout);
}
! fputs("</p>", fout);
! }
fputc('\n', fout);
}

***************
*** 690,696 ****
unsigned int record = 1;
const char *const * ptr;

! 	fprintf(fout, "<table border=%d", opt_border);
  	if (opt_table_attr)
  		fprintf(fout, " %s", opt_table_attr);
  	fputs(">\n", fout);
--- 698,704 ----
  	unsigned int record = 1;
  	const char *const * ptr;

! fprintf(fout, "<table border=\"%d\"", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
***************
*** 713,731 ****
if (i % col_count == 0)
{
if (!opt_barebones)
! fprintf(fout, "\n <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
else
! fputs("\n <tr><td colspan=2>&nbsp;</td></tr>\n", fout);
}
! fputs(" <tr valign=top>\n"
" <th>", fout);
html_escaped_print(headers[i % col_count], fout);
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);
--- 721,738 ----
  		if (i % col_count == 0)
  		{
  			if (!opt_barebones)
! 				fprintf(fout, "\n  <tr><td colspan=\"2\" align=\"center\">Record %d</td></tr>\n", record++);
  			else
! 				fputs("\n  <tr><td colspan=\"2\">&nbsp;</td></tr>\n", fout);
  		}
! 		fputs("  <tr valign=\"top\">\n"
  			  "    <th>", fout);
  		html_escaped_print(headers[i % col_count], fout);
  		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);
***************
*** 734,746 ****
fputs("</table>\n", fout);

/* print footers */
! if (footers && !opt_barebones)
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br>\n", fout);
}
!
fputc('\n', fout);
}

--- 741,756 ----
  	fputs("</table>\n", fout);

/* print footers */
! if (!opt_barebones && footers && *footers)
! {
! fputs("<p>", fout);
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br />\n", fout);
}
! fputs("</p>", fout);
! }
fputc('\n', fout);
}

***************
*** 1114,1119 ****
--- 1124,1130 ----
  	char	  **footers;
  	char	   *align;
  	int			i;
+ 

/* extract headers */

Index: print.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.h,v
retrieving revision 1.16
diff -c -r1.16 print.h
*** print.h	18 Mar 2003 22:15:44 -0000	1.16
--- print.h	1 Jun 2003 20:34:43 -0000
***************
*** 13,18 ****
--- 13,19 ----

extern FILE *PageOutput(int lines, unsigned short int pager);

+ extern void html_escaped_print(const char *in, FILE *fout);

enum printFormat
{

-----BEGIN PGP SIGNATURE-----
Comment: http://www.turnstep.com/pgp.html

iD8DBQE+2nNjvJuQZxSWSsgRAiuWAKCnpa1SzCe6A8i55EXBAIlS0KnspQCdGiWK
H3bbC9FnvDMWQxYOi+vMRGY=
=sLzN
-----END PGP SIGNATURE-----

#2Peter Eisentraut
peter_e@gmx.net
In reply to: Greg Sabino Mullane (#1)
Re: Valid HTML/XHTML output for psql

Greg Sabino Mullane writes:

It also wraps the output of PGRES_COMMAND_OK if the HTML tag is on,
for full compliance: this is why html_escaped_print has to be externalized.

I don't agree with this part. The formatting option is supposed to
control the format of tables, but the output of PGRES_COMMAND_OK isn't a
table.

--
Peter Eisentraut peter_e@gmx.net

#3Greg Sabino Mullane
greg@turnstep.com
In reply to: Peter Eisentraut (#2)
Re: Valid HTML/XHTML output for psql

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I don't agree with this part. The formatting option is supposed to
control the format of tables, but the output of PGRES_COMMAND_OK isn't a
table.

I can see that argument, but it also currently formats \d commands as
well as things like EXPLAIN ANALYZE. It just seems to me that if you
request HTML mode, you should get valid HTML on all output going to
your filehandle. Most people using HTML are not viewing it directly
anyway (nor should they), so there is a clear advantage is wrapping
everything we can (e.g. everything captured by \o)

- --
Greg Sabino Mullane greg@turnstep.com
PGP Key: 0x14964AC8 200306012126
-----BEGIN PGP SIGNATURE-----
Comment: http://www.turnstep.com/pgp.html

iD8DBQE+2qv1vJuQZxSWSsgRAubiAKCDRZgO/8Wa5YhSXpsJWveiOl5Z8ACg6Jgk
WnEoVCLfiX1tCwdMmOZawM8=
=lIKi
-----END PGP SIGNATURE-----

#4Bruce Momjian
bruce@momjian.us
In reply to: Greg Sabino Mullane (#1)
Re: Valid HTML/XHTML output for psql

Your patch has been added to the PostgreSQL unapplied patches list at:

http://momjian.postgresql.org/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------

Greg Sabino Mullane wrote:
[ There is text before PGP section. ]

[ PGP not available, raw data follows ]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Attached is a patch that enhances the output of psql's HTML mode.
The output now validates as HTML 4.01 Strict, XHTML 1.0 strict,
and XHTML 1.1 (assuming you wrap it in a valid html/body document).

It also wraps the output of PGRES_COMMAND_OK if the HTML tag is on,
for full compliance: this is why html_escaped_print has to be externalized.

--
Greg Sabino Mullane greg@turnstep.com
PGP Key: 0x14964AC8 200306011737

Index: common.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.62
diff -c -r1.62 common.c
*** common.c	25 Mar 2003 02:44:36 -0000	1.62
--- common.c	1 Jun 2003 20:34:41 -0000
***************
*** 525,531 ****
success = true;
sprintf(buf, "%u", (unsigned int) PQoidValue(results));
if (!QUIET())
! 						fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
SetVariable(pset.vars, "LASTOID", buf);
break;
}
--- 525,542 ----
success = true;
sprintf(buf, "%u", (unsigned int) PQoidValue(results));
if (!QUIET())
! 						{
! 							if (pset.popt.topt.format == PRINT_HTML)
! 							{
! 								fputs("<p>", pset.queryFout);
! 								html_escaped_print(PQcmdStatus(results), pset.queryFout);
! 								fputs("</p>\n", pset.queryFout);
! 							}
! 							else
! 							{
! 								fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
! 							}
! 						}
SetVariable(pset.vars, "LASTOID", buf);
break;
}
Index: print.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.c,v
retrieving revision 1.37
diff -c -r1.37 print.c
*** print.c	4 Apr 2003 15:48:38 -0000	1.37
--- print.c	1 Jun 2003 20:34:42 -0000
***************
*** 577,583 ****
/**********************/
! static void
html_escaped_print(const char *in, FILE *fout)
{
const char *p;
--- 577,583 ----
/**********************/
! void
html_escaped_print(const char *in, FILE *fout)
{
const char *p;
***************
*** 595,601 ****
fputs("&gt;", fout);
break;
case '\n':
! 				fputs("<br>", fout);
break;
default:
fputc(*p, fout);
--- 595,607 ----
fputs("&gt;", fout);
break;
case '\n':
! 				fputs("<br />\n", fout);
! 				break;
! 			case '"':
! 				fputs("&quot;", fout);
! 				break;
! 			case '\'':
! 				fputs("&apos;", fout);
break;
default:
fputc(*p, fout);
***************
*** 615,621 ****
unsigned int i;
const char *const * ptr;
! 	fprintf(fout, "<table border=%d", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
--- 621,627 ----
unsigned int i;
const char *const * ptr;
! 	fprintf(fout, "<table border=\"%d\"", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
***************
*** 636,642 ****
col_count++;
if (!opt_barebones)
{
! 			fputs("    <th align=center>", fout);
html_escaped_print(*ptr, fout);
fputs("</th>\n", fout);
}
--- 642,648 ----
col_count++;
if (!opt_barebones)
{
! 			fputs("    <th align=\"center\">", fout);
html_escaped_print(*ptr, fout);
fputs("</th>\n", fout);
}
***************
*** 648,659 ****
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
if (i % col_count == 0)
! 			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);
--- 654,664 ----
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
if (i % col_count == 0)
! 			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);
***************
*** 666,678 ****

/* print footers */

! if (footers && !opt_barebones)
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br>\n", fout);
}
!
fputc('\n', fout);
}

--- 671,686 ----

/* print footers */

! if (!opt_barebones && footers && *footers)
! {
! fputs("<p>", fout);
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br />\n", fout);
}
! fputs("</p>", fout);
! }
fputc('\n', fout);
}

***************
*** 690,696 ****
unsigned int record = 1;
const char *const * ptr;

! 	fprintf(fout, "<table border=%d", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
--- 698,704 ----
unsigned int record = 1;
const char *const * ptr;

! fprintf(fout, "<table border=\"%d\"", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
***************
*** 713,731 ****
if (i % col_count == 0)
{
if (!opt_barebones)
! fprintf(fout, "\n <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
else
! fputs("\n <tr><td colspan=2>&nbsp;</td></tr>\n", fout);
}
! fputs(" <tr valign=top>\n"
" <th>", fout);
html_escaped_print(headers[i % col_count], fout);
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);
--- 721,738 ----
if (i % col_count == 0)
{
if (!opt_barebones)
! 				fprintf(fout, "\n  <tr><td colspan=\"2\" align=\"center\">Record %d</td></tr>\n", record++);
else
! 				fputs("\n  <tr><td colspan=\"2\">&nbsp;</td></tr>\n", fout);
}
! 		fputs("  <tr valign=\"top\">\n"
"    <th>", fout);
html_escaped_print(headers[i % col_count], fout);
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);
***************
*** 734,746 ****
fputs("</table>\n", fout);

/* print footers */
! if (footers && !opt_barebones)
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br>\n", fout);
}
!
fputc('\n', fout);
}

--- 741,756 ----
fputs("</table>\n", fout);

/* print footers */
! if (!opt_barebones && footers && *footers)
! {
! fputs("<p>", fout);
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br />\n", fout);
}
! fputs("</p>", fout);
! }
fputc('\n', fout);
}

***************
*** 1114,1119 ****
--- 1124,1130 ----
char	  **footers;
char	   *align;
int			i;
+ 

/* extract headers */

Index: print.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.h,v
retrieving revision 1.16
diff -c -r1.16 print.h
*** print.h	18 Mar 2003 22:15:44 -0000	1.16
--- print.h	1 Jun 2003 20:34:43 -0000
***************
*** 13,18 ****
--- 13,19 ----

extern FILE *PageOutput(int lines, unsigned short int pager);

+ extern void html_escaped_print(const char *in, FILE *fout);

enum printFormat
{

-----BEGIN PGP SIGNATURE-----
Comment: http://www.turnstep.com/pgp.html

iD8DBQE+2nNjvJuQZxSWSsgRAiuWAKCnpa1SzCe6A8i55EXBAIlS0KnspQCdGiWK
H3bbC9FnvDMWQxYOi+vMRGY=
=sLzN
-----END PGP SIGNATURE-----

---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org

[ Decrypting message... End of raw data. ]

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
#5Bruce Momjian
bruce@momjian.us
In reply to: Greg Sabino Mullane (#1)
Re: Valid HTML/XHTML output for psql

Patch applied. Thanks.

---------------------------------------------------------------------------

Greg Sabino Mullane wrote:
[ There is text before PGP section. ]

[ PGP not available, raw data follows ]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
NotDashEscaped: You need GnuPG to verify this message

Attached is a patch that enhances the output of psql's HTML mode.
The output now validates as HTML 4.01 Strict, XHTML 1.0 strict,
and XHTML 1.1 (assuming you wrap it in a valid html/body document).

It also wraps the output of PGRES_COMMAND_OK if the HTML tag is on,
for full compliance: this is why html_escaped_print has to be externalized.

--
Greg Sabino Mullane greg@turnstep.com
PGP Key: 0x14964AC8 200306011737

Index: common.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.62
diff -c -r1.62 common.c
*** common.c	25 Mar 2003 02:44:36 -0000	1.62
--- common.c	1 Jun 2003 20:34:41 -0000
***************
*** 525,531 ****
success = true;
sprintf(buf, "%u", (unsigned int) PQoidValue(results));
if (!QUIET())
! 						fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
SetVariable(pset.vars, "LASTOID", buf);
break;
}
--- 525,542 ----
success = true;
sprintf(buf, "%u", (unsigned int) PQoidValue(results));
if (!QUIET())
! 						{
! 							if (pset.popt.topt.format == PRINT_HTML)
! 							{
! 								fputs("<p>", pset.queryFout);
! 								html_escaped_print(PQcmdStatus(results), pset.queryFout);
! 								fputs("</p>\n", pset.queryFout);
! 							}
! 							else
! 							{
! 								fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
! 							}
! 						}
SetVariable(pset.vars, "LASTOID", buf);
break;
}
Index: print.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.c,v
retrieving revision 1.37
diff -c -r1.37 print.c
*** print.c	4 Apr 2003 15:48:38 -0000	1.37
--- print.c	1 Jun 2003 20:34:42 -0000
***************
*** 577,583 ****
/**********************/
! static void
html_escaped_print(const char *in, FILE *fout)
{
const char *p;
--- 577,583 ----
/**********************/
! void
html_escaped_print(const char *in, FILE *fout)
{
const char *p;
***************
*** 595,601 ****
fputs("&gt;", fout);
break;
case '\n':
! 				fputs("<br>", fout);
break;
default:
fputc(*p, fout);
--- 595,607 ----
fputs("&gt;", fout);
break;
case '\n':
! 				fputs("<br />\n", fout);
! 				break;
! 			case '"':
! 				fputs("&quot;", fout);
! 				break;
! 			case '\'':
! 				fputs("&apos;", fout);
break;
default:
fputc(*p, fout);
***************
*** 615,621 ****
unsigned int i;
const char *const * ptr;
! 	fprintf(fout, "<table border=%d", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
--- 621,627 ----
unsigned int i;
const char *const * ptr;
! 	fprintf(fout, "<table border=\"%d\"", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
***************
*** 636,642 ****
col_count++;
if (!opt_barebones)
{
! 			fputs("    <th align=center>", fout);
html_escaped_print(*ptr, fout);
fputs("</th>\n", fout);
}
--- 642,648 ----
col_count++;
if (!opt_barebones)
{
! 			fputs("    <th align=\"center\">", fout);
html_escaped_print(*ptr, fout);
fputs("</th>\n", fout);
}
***************
*** 648,659 ****
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
if (i % col_count == 0)
! 			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);
--- 654,664 ----
for (i = 0, ptr = cells; *ptr; i++, ptr++)
{
if (i % col_count == 0)
! 			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);
***************
*** 666,678 ****

/* print footers */

! if (footers && !opt_barebones)
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br>\n", fout);
}
!
fputc('\n', fout);
}

--- 671,686 ----

/* print footers */

! if (!opt_barebones && footers && *footers)
! {
! fputs("<p>", fout);
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br />\n", fout);
}
! fputs("</p>", fout);
! }
fputc('\n', fout);
}

***************
*** 690,696 ****
unsigned int record = 1;
const char *const * ptr;

! 	fprintf(fout, "<table border=%d", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
--- 698,704 ----
unsigned int record = 1;
const char *const * ptr;

! fprintf(fout, "<table border=\"%d\"", opt_border);
if (opt_table_attr)
fprintf(fout, " %s", opt_table_attr);
fputs(">\n", fout);
***************
*** 713,731 ****
if (i % col_count == 0)
{
if (!opt_barebones)
! fprintf(fout, "\n <tr><td colspan=2 align=center>Record %d</td></tr>\n", record++);
else
! fputs("\n <tr><td colspan=2>&nbsp;</td></tr>\n", fout);
}
! fputs(" <tr valign=top>\n"
" <th>", fout);
html_escaped_print(headers[i % col_count], fout);
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);
--- 721,738 ----
if (i % col_count == 0)
{
if (!opt_barebones)
! 				fprintf(fout, "\n  <tr><td colspan=\"2\" align=\"center\">Record %d</td></tr>\n", record++);
else
! 				fputs("\n  <tr><td colspan=\"2\">&nbsp;</td></tr>\n", fout);
}
! 		fputs("  <tr valign=\"top\">\n"
"    <th>", fout);
html_escaped_print(headers[i % col_count], fout);
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);
***************
*** 734,746 ****
fputs("</table>\n", fout);

/* print footers */
! if (footers && !opt_barebones)
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br>\n", fout);
}
!
fputc('\n', fout);
}

--- 741,756 ----
fputs("</table>\n", fout);

/* print footers */
! if (!opt_barebones && footers && *footers)
! {
! fputs("<p>", fout);
for (ptr = footers; *ptr; ptr++)
{
html_escaped_print(*ptr, fout);
! fputs("<br />\n", fout);
}
! fputs("</p>", fout);
! }
fputc('\n', fout);
}

***************
*** 1114,1119 ****
--- 1124,1130 ----
char	  **footers;
char	   *align;
int			i;
+ 

/* extract headers */

Index: print.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.h,v
retrieving revision 1.16
diff -c -r1.16 print.h
*** print.h	18 Mar 2003 22:15:44 -0000	1.16
--- print.h	1 Jun 2003 20:34:43 -0000
***************
*** 13,18 ****
--- 13,19 ----

extern FILE *PageOutput(int lines, unsigned short int pager);

+ extern void html_escaped_print(const char *in, FILE *fout);

enum printFormat
{

-----BEGIN PGP SIGNATURE-----
Comment: http://www.turnstep.com/pgp.html

iD8DBQE+2nNjvJuQZxSWSsgRAiuWAKCnpa1SzCe6A8i55EXBAIlS0KnspQCdGiWK
H3bbC9FnvDMWQxYOi+vMRGY=
=sLzN
-----END PGP SIGNATURE-----

---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org

[ Decrypting message... End of raw data. ]

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073