Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.119
diff -u -r1.119 psql-ref.sgml
--- doc/src/sgml/ref/psql-ref.sgml	15 Jul 2004 03:56:04 -0000	1.119
+++ doc/src/sgml/ref/psql-ref.sgml	1 Aug 2004 17:36:46 -0000
@@ -1372,9 +1372,10 @@
           <listitem>
           <para>
           Sets the output format to one of <literal>unaligned</literal>,
-          <literal>aligned</literal>, <literal>html</literal>, or
-          <literal>latex</literal>. Unique abbreviations are allowed.
-          (That would mean one letter is enough.)
+          <literal>aligned</literal>, <literal>html</literal>,
+          <literal>latex</literal>, or <literal>troff-ms</literal>.
+	  Unique abbreviations are allowed.  (That would mean one letter
+	  is enough.)
           </para>
 
           <para>
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/command.c,v
retrieving revision 1.122
diff -u -r1.122 command.c
--- src/bin/psql/command.c	15 Jul 2004 03:56:06 -0000	1.122
+++ src/bin/psql/command.c	1 Aug 2004 17:36:53 -0000
@@ -1307,6 +1307,9 @@
 		case PRINT_LATEX:
 			return "latex";
 			break;
+		case PRINT_TROFF_MS:
+			return "troff-ms";
+			break;
 	}
 	return "unknown";
 }
@@ -1335,9 +1338,11 @@
 			popt->topt.format = PRINT_HTML;
 		else if (pg_strncasecmp("latex", value, vallen) == 0)
 			popt->topt.format = PRINT_LATEX;
+		else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
+			popt->topt.format = PRINT_TROFF_MS;
 		else
 		{
-			psql_error("\\pset: allowed formats are unaligned, aligned, html, latex\n");
+			psql_error("\\pset: allowed formats are unaligned, aligned, html, latex, troff-ms\n");
 			return false;
 		}
 
Index: src/bin/psql/print.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.c,v
retrieving revision 1.48
diff -u -r1.48 print.c
--- src/bin/psql/print.c	23 May 2004 22:20:10 -0000	1.48
+++ src/bin/psql/print.c	1 Aug 2004 17:36:56 -0000
@@ -769,7 +769,7 @@
 
 
 /*************************/
-/* LaTeX				 */
+/* LaTeX		 */
 /*************************/
 
 
@@ -790,6 +790,9 @@
 			case '$':
 				fputs("\\$", fout);
 				break;
+			case '_':
+				fputs("\\_", fout);
+				break;
 			case '{':
 				fputs("\\{", fout);
 				break;
@@ -817,7 +820,6 @@
 {
 	unsigned int col_count = 0;
 	unsigned int i;
-	const char *cp;
 	const char *const * ptr;
 
 
@@ -829,42 +831,39 @@
 		fputs("\n\\end{center}\n\n", fout);
 	}
 
+	/* count columns */
+	for (ptr = headers; *ptr; ptr++)
+		col_count++;
+
 	/* begin environment and set alignments and borders */
 	fputs("\\begin{tabular}{", fout);
-	if (opt_border == 0)
-		fputs(opt_align, fout);
-	else if (opt_border == 1)
-	{
-		for (cp = opt_align; *cp; cp++)
-		{
-			if (cp != opt_align)
-				fputc('|', fout);
-			fputc(*cp, fout);
-		}
-	}
-	else if (opt_border == 2)
+
+	if (opt_border == 2)
+	  fputs("| ", fout);
+        for (i = 0; i < col_count; i++)
 	{
-		for (cp = opt_align; *cp; cp++)
-		{
-			fputc('|', fout);
-			fputc(*cp, fout);
-		}
-		fputc('|', fout);
+	  fputc(*(opt_align + i), fout);
+	  if (opt_border != 0 && i < col_count - 1)
+	    fputs (" | ", fout);
 	}
+	if (opt_border == 2)
+	  fputs(" |", fout);
+
 	fputs("}\n", fout);
 
 	if (!opt_barebones && opt_border == 2)
 		fputs("\\hline\n", fout);
 
 	/* print headers and count columns */
-	for (i = 0, ptr = headers; *ptr; i++, ptr++)
+	for (i = 0, ptr = headers; i < col_count; i++, ptr++)
 	{
-		col_count++;
 		if (!opt_barebones)
 		{
 			if (i != 0)
 				fputs(" & ", fout);
+                        fputs("\\textit{", fout);
 			latex_escaped_print(*ptr, fout);
+                        fputc('}', fout);
 		}
 	}
 
@@ -888,7 +887,7 @@
 	if (opt_border == 2)
 		fputs("\\hline\n", fout);
 
-	fputs("\\end{tabular}\n\n", fout);
+	fputs("\\end{tabular}\n\n\\noindent ", fout);
 
 
 	/* print footers */
@@ -951,8 +950,12 @@
 			if (!opt_barebones)
 			{
 				if (opt_border == 2)
+				{
 					fputs("\\hline\n", fout);
-				fprintf(fout, "\\multicolumn{2}{c}{Record %d} \\\\\n", record++);
+					fprintf(fout, "\\multicolumn{2}{|c|}{\\textit{Record %d}} \\\\\n", record++);
+				}
+				else
+					fprintf(fout, "\\multicolumn{2}{c}{\\textit{Record %d}} \\\\\n", record++);
 			}
 			if (opt_border >= 1)
 				fputs("\\hline\n", fout);
@@ -967,7 +970,7 @@
 	if (opt_border == 2)
 		fputs("\\hline\n", fout);
 
-	fputs("\\end{tabular}\n\n", fout);
+	fputs("\\end{tabular}\n\n\\noindent ", fout);
 
 
 	/* print footers */
@@ -984,6 +987,213 @@
 
 
 
+/*************************/
+/* Troff -ms		 */
+/*************************/
+
+
+static void
+troff_ms_escaped_print(const char *in, FILE *fout)
+{
+	const char *p;
+
+	for (p = in; *p; p++)
+		switch (*p)
+		{
+			case '\\':
+				fputs("\(rs", fout);
+				break;
+			default:
+				fputc(*p, fout);
+		}
+}
+
+
+
+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 */
+	if (!opt_barebones && title)
+	{
+		fputs(".LP\n.DS C\n", fout);
+		troff_ms_escaped_print(title, fout);
+		fputs("\n.DE\n", fout);
+	}
+
+	/* count columns */
+	for (ptr = headers; *ptr; ptr++)
+		col_count++;
+
+	/* begin environment and set alignments and borders */
+	fputs(".LP\n.TS\n", fout);
+	if (opt_border == 2)
+		fputs("center box;\n", fout);
+	else
+		fputs("center;\n", fout);
+
+	for (i = 0; i < col_count; i++)
+	{
+		fputc(*(opt_align + i), fout);
+		if (opt_border > 0 && i < col_count - 1)
+			fputs(" | ", fout);
+	}
+	fputs(".\n", fout);
+
+	/* print headers and count columns */
+	for (i = 0, ptr = headers; i < col_count; i++, ptr++)
+	{
+		if (!opt_barebones)
+		{
+			if (i != 0)
+				fputc('\t', fout);
+			fputs("\\fI", fout);
+			troff_ms_escaped_print(*ptr, fout);
+			fputs("\\fP", fout);
+		}
+	}
+
+	if (!opt_barebones)
+	{
+		fputs("\n_\n", fout);
+	}
+
+	/* print cells */
+	for (i = 0, ptr = cells; *ptr; i++, ptr++)
+	{
+		troff_ms_escaped_print(*ptr, fout);
+
+		if ((i + 1) % col_count == 0)
+			fputc('\n', fout);
+		else
+			fputc('\t', fout);
+	}
+
+	fputs(".TE\n.DS L\n", fout);
+
+
+	/* print footers */
+
+	if (footers && !opt_barebones)
+		for (ptr = footers; *ptr; ptr++)
+		{
+			troff_ms_escaped_print(*ptr, fout);
+			fputc('\n', fout);
+		}
+
+	fputs(".DE\n", fout);
+}
+
+
+
+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 */
+
+	(void) opt_align;			/* currently unused parameter */
+
+	/* print title */
+	if (!opt_barebones && title)
+	{
+		fputs(".LP\n.DS C\n", fout);
+		troff_ms_escaped_print(title, fout);
+		fputs("\n.DE\n", fout);
+	}
+
+	/* begin environment and set alignments and borders */
+	fputs(".LP\n.TS\n", fout);
+	if (opt_border == 2)
+		fputs("center box;\n", fout);
+	else
+		fputs("center;\n", fout);
+
+	/* basic format */
+        if (opt_barebones)
+ 		fputs("c l;\n", fout);
+
+
+	/* count columns */
+	for (ptr = headers; *ptr; ptr++)
+		col_count++;
+
+
+	/* print records */
+	for (i = 0, ptr = cells; *ptr; i++, ptr++)
+	{
+		/* new record */
+		if (i % col_count == 0)
+		{
+			if (!opt_barebones)
+			{
+
+				if (current_format != 1)
+				{
+					if (opt_border == 2 && i > 0)
+						fputs("_\n", fout);
+					if (current_format != 0)
+						fputs(".T&\n", fout);
+					fputs("c s.\n", fout);
+					current_format = 1;
+				}
+				fprintf(fout, "\\fIRecord %d\\fP\n", record++);
+			}
+			if (opt_border >= 1)
+				fputs("_\n", fout);
+		}
+
+		if (!opt_barebones)
+		{
+			if (current_format != 2)
+			{
+				if (current_format != 0)
+					fputs(".T&\n", fout);
+				if (opt_border != 1)
+					fputs("c l.\n", fout);
+				else
+					fputs("c | l.\n", fout);
+				current_format = 2;
+			}
+		}
+
+		troff_ms_escaped_print(headers[i % col_count], fout);
+		fputc('\t', fout);
+		troff_ms_escaped_print(*ptr, fout);
+		fputc('\n', fout);
+	}
+
+	fputs(".TE\n.DS L\n", fout);
+
+
+	/* print footers */
+
+	if (footers && !opt_barebones)
+		for (ptr = footers; *ptr; ptr++)
+		{
+			troff_ms_escaped_print(*ptr, fout);
+			fputc('\n', fout);
+		}
+
+	fputs(".DE\n", fout);
+}
+
+
+
 /********************************/
 /* Public functions		*/
 /********************************/
@@ -1113,6 +1323,12 @@
 			else
 				print_latex_text(title, headers, cells, footers, align, opt->tuples_only, border, output);
 			break;
+		case PRINT_TROFF_MS:
+			if (opt->expanded)
+				print_troff_ms_vertical(title, headers, cells, footers, align, opt->tuples_only, border, output);
+			else
+				print_troff_ms_text(title, headers, cells, footers, align, opt->tuples_only, border, output);
+			break;
 		default:
 			fprintf(stderr, "+ Oops, you shouldn't see this!\n");
 	}
Index: src/bin/psql/print.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/print.h,v
retrieving revision 1.20
diff -u -r1.20 print.h
--- src/bin/psql/print.h	29 Nov 2003 19:52:07 -0000	1.20
+++ src/bin/psql/print.h	1 Aug 2004 17:36:56 -0000
@@ -21,7 +21,8 @@
 	PRINT_UNALIGNED,
 	PRINT_ALIGNED,
 	PRINT_HTML,
-	PRINT_LATEX
+	PRINT_LATEX,
+	PRINT_TROFF_MS
 	/* add your favourite output format here ... */
 };
 
