Bryce Nesbitt wrote:
> I've attached a patch, against current 8.4 cvs, which optionally sets a
> maximum width for psql output:
>
> # \pset format aligned-wrapped
> # \pset border 2
> # select * from distributors order by did;
> +------+--------------------+---------------------+---------------+
> | did | name | descr | long_col_name |
> +------+--------------------+---------------------+---------------+
> | 1 | Food fish and wine | default | |
> | 2 | Cat Food Heaven 2 | abcdefghijklmnopqrs ! |
> | | | tuvwxyz | |
> | 3 | Cat Food Heaven 3 | default | |
> | 10 | Lah | default | |
> | 12 | name | line one | |
> | 2892 ! short name | short | |
> | 8732 | | | |
> +------+--------------------+---------------------+---------------+
> (8 rows)
>
> The interactive terminal column width comes from
> char * temp = getenv("COLUMNS");
> Which has the strong advantage of great simplicity and portability. But
> it may not be 1000% universal. If $COLUMNS is not defined, the code
> bails to assuming an infinitely wide terminal.
>
> I will also backport this to Postgres 8.1, for my own use. Though the
> code is almost totally different in structure.
I spent time reviewing your patch --- quite impressive. I have attached
and updated version with mostly stylistic changes.
In testing I found the regression tests were failing because of a divide
by zero error (fixed), and a missing case where the column delimiter has
to be ":". In fact I now see all your line continuation cases using ":"
rather than "!". It actually looks better --- "!" was too close to "|"
to be easily recognized. (Did you update your patch to use ":". I
didn't see "!" in your patch.)
I have added an XXX comment questioning whether the loop to find the
column to wrap is inefficient because it potentially loops over the
length of the longest column and for each character loops over the
number of columns. Not sure if that is a problem.
I checked the use of COLUMNS and it seems bash updates the environment
variable when a window is resized. I added ioctl(TIOCGWINSZ) if COLUMNS
isn't set. We already had a call in print.c for detecting the
number of rows on the screen to determine if the pager should
be used. Seems COLUMNS should take precedence over ioctl(), right?
I don't think Win32 supports that ioctl(), does it?
I added some comments and clarified some variable names. I also renamed
the option to a shorter "wrapped". I added documentation too.
For testers compare:
\df
with:
\pset format wrap
\df
Impressive!
--
Bruce Momjian <[EMAIL PROTECTED]> http://momjian.us
EnterpriseDB http://enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +
Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.199
diff -c -c -r1.199 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml 30 Mar 2008 18:10:20 -0000 1.199
--- doc/src/sgml/ref/psql-ref.sgml 17 Apr 2008 02:45:38 -0000
***************
*** 1513,1519 ****
<listitem>
<para>
Sets the output format to one of <literal>unaligned</literal>,
! <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.)
--- 1513,1520 ----
<listitem>
<para>
Sets the output format to one of <literal>unaligned</literal>,
! <literal>aligned</literal>, <literal>wrapped</literal>,
! <literal>html</literal>,
<literal>latex</literal>, or <literal>troff-ms</literal>.
Unique abbreviations are allowed. (That would mean one letter
is enough.)
***************
*** 1525,1531 ****
is intended to create output that might be intended to be read
in by other programs (tab-separated, comma-separated).
<quote>Aligned</quote> mode is the standard, human-readable,
! nicely formatted text output that is default. The
<quote><acronym>HTML</acronym></quote> and
<quote>LaTeX</quote> modes put out tables that are intended to
be included in documents using the respective mark-up
--- 1526,1535 ----
is intended to create output that might be intended to be read
in by other programs (tab-separated, comma-separated).
<quote>Aligned</quote> mode is the standard, human-readable,
! nicely formatted text output that is default.
! <quote>Wrapped</quote> is like <literal>aligned</> but wraps
! the output to fit the screen's width, based on the environment
! variable <envar>COLUMNS</> or the autodetected width. The
<quote><acronym>HTML</acronym></quote> and
<quote>LaTeX</quote> modes put out tables that are intended to
be included in documents using the respective mark-up
***************
*** 2708,2713 ****
--- 2712,2730 ----
<variablelist>
<varlistentry>
+ <term><envar>COLUMNS</envar></term>
+
+ <listitem>
+ <para>
+ The character width to wrap output in <literal>wrapped</> format
+ mode. Many shells automatically update <envar>COLUMNS</> when
+ a window is resized. If not set the screen width is automatically
+ detected, if possible.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><envar>PAGER</envar></term>
<listitem>
Index: src/bin/psql/command.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.186
diff -c -c -r1.186 command.c
*** src/bin/psql/command.c 1 Jan 2008 19:45:55 -0000 1.186
--- src/bin/psql/command.c 17 Apr 2008 02:45:38 -0000
***************
*** 1526,1531 ****
--- 1526,1534 ----
case PRINT_ALIGNED:
return "aligned";
break;
+ case PRINT_WRAP:
+ return "wrapped";
+ break;
case PRINT_HTML:
return "html";
break;
***************
*** 1559,1564 ****
--- 1562,1569 ----
popt->topt.format = PRINT_UNALIGNED;
else if (pg_strncasecmp("aligned", value, vallen) == 0)
popt->topt.format = PRINT_ALIGNED;
+ else if (pg_strncasecmp("wrapped", value, vallen) == 0)
+ popt->topt.format = PRINT_WRAP;
else if (pg_strncasecmp("html", value, vallen) == 0)
popt->topt.format = PRINT_HTML;
else if (pg_strncasecmp("latex", value, vallen) == 0)
***************
*** 1567,1573 ****
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned,
aligned, html, latex, troff-ms\n");
return false;
}
--- 1572,1578 ----
popt->topt.format = PRINT_TROFF_MS;
else
{
! psql_error("\\pset: allowed formats are unaligned,
aligned, wrapped, html, latex, troff-ms\n");
return false;
}
Index: src/bin/psql/mbprint.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/mbprint.c,v
retrieving revision 1.30
diff -c -c -r1.30 mbprint.c
*** src/bin/psql/mbprint.c 16 Apr 2008 18:18:00 -0000 1.30
--- src/bin/psql/mbprint.c 17 Apr 2008 02:45:38 -0000
***************
*** 279,284 ****
--- 279,288 ----
return width;
}
+ /*
+ * Filter out unprintable characters, companion to wcs_size.
+ * Break input into lines (based on \n or \r).
+ */
void
pg_wcsformat(unsigned char *pwcs, size_t len, int encoding,
struct lineptr * lines, int count)
***************
*** 353,364 ****
}
len -= chlen;
}
! *ptr++ = '\0';
lines->width = linewidth;
! lines++;
! count--;
! if (count > 0)
lines->ptr = NULL;
}
unsigned char *
--- 357,373 ----
}
len -= chlen;
}
! *ptr++ = '\0'; /* Terminate formatted string */
!
lines->width = linewidth;
!
! /* Fill remaining array slots with nulls */
! while (--count)
! {
! lines++;
lines->ptr = NULL;
+ lines->width = 0;
+ }
}
unsigned char *
Index: src/bin/psql/print.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/print.c,v
retrieving revision 1.97
diff -c -c -r1.97 print.c
*** src/bin/psql/print.c 27 Mar 2008 03:57:34 -0000 1.97
--- src/bin/psql/print.c 17 Apr 2008 02:45:38 -0000
***************
*** 396,401 ****
--- 396,404 ----
}
+ /*
+ * Prety pretty boxes around cells.
+ */
static void
print_aligned_text(const char *title, const char *const * headers,
const char *const * cells, const char *const
* footers,
***************
*** 404,429 ****
{
bool opt_tuples_only = opt->tuples_only;
bool opt_numeric_locale = opt->numericLocale;
- unsigned short int opt_border = opt->border;
int encoding = opt->encoding;
! unsigned int col_count = 0;
! unsigned int cell_count = 0;
! unsigned int i;
! int tmp;
! unsigned int *widths,
! total_w;
! unsigned int *heights;
! unsigned int *format_space;
unsigned char **format_buf;
const char *const * ptr;
! struct lineptr **col_lineptrs; /* pointers to line pointer for
each
!
* column */
struct lineptr *lineptr_list; /* complete list of
linepointers */
int *complete; /* Array remembering which
columns have
* completed
output */
if (cancel_pressed)
return;
--- 407,437 ----
{
bool opt_tuples_only = opt->tuples_only;
bool opt_numeric_locale = opt->numericLocale;
int encoding = opt->encoding;
! unsigned short int opt_border = opt->border;
!
! unsigned int col_count = 0, cell_count = 0;
!
! unsigned int i,
! j;
!
! unsigned int *width_header,
! *width_max,
! *width_wrap,
! *width_average;
! unsigned int *heights,
! *format_space;
unsigned char **format_buf;
+ unsigned int width_total;
const char *const * ptr;
! struct lineptr **col_lineptrs; /* pointers to line pointer per
column */
struct lineptr *lineptr_list; /* complete list of
linepointers */
int *complete; /* Array remembering which
columns have
* completed
output */
+ int tcolumns = 0; /* Width of interactive console
*/
if (cancel_pressed)
return;
***************
*** 437,443 ****
if (col_count > 0)
{
! widths = pg_local_calloc(col_count, sizeof(*widths));
heights = pg_local_calloc(col_count, sizeof(*heights));
col_lineptrs = pg_local_calloc(col_count,
sizeof(*col_lineptrs));
format_space = pg_local_calloc(col_count,
sizeof(*format_space));
--- 445,454 ----
if (col_count > 0)
{
! width_header = pg_local_calloc(col_count,
sizeof(*width_header));
! width_average = pg_local_calloc(col_count,
sizeof(*width_average));
! width_max = pg_local_calloc(col_count, sizeof(*width_max));
! width_wrap = pg_local_calloc(col_count, sizeof(*width_wrap));
heights = pg_local_calloc(col_count, sizeof(*heights));
col_lineptrs = pg_local_calloc(col_count,
sizeof(*col_lineptrs));
format_space = pg_local_calloc(col_count,
sizeof(*format_space));
***************
*** 446,452 ****
}
else
{
! widths = NULL;
heights = NULL;
col_lineptrs = NULL;
format_space = NULL;
--- 457,466 ----
}
else
{
! width_header = NULL;
! width_average = NULL;
! width_max = NULL;
! width_wrap = NULL;
heights = NULL;
col_lineptrs = NULL;
format_space = NULL;
***************
*** 454,533 ****
complete = NULL;
}
! /* count cells (rows * cols) */
! for (ptr = cells; *ptr; ptr++)
! cell_count++;
!
! /* calc column widths */
for (i = 0; i < col_count; i++)
{
/* Get width & height */
! int height,
space;
! pg_wcssize((unsigned char *) headers[i], strlen(headers[i]),
encoding, &tmp, &height, &space);
! if (tmp > widths[i])
! widths[i] = tmp;
if (height > heights[i])
heights[i] = height;
if (space > format_space[i])
format_space[i] = space;
}
! for (i = 0, ptr = cells; *ptr; ptr++, i++)
{
! int numeric_locale_len;
! int height,
space;
- if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
- numeric_locale_len =
additional_numeric_locale_len(*ptr);
- else
- numeric_locale_len = 0;
-
/* Get width, ignore height */
! pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
&tmp, &height, &space);
! tmp += numeric_locale_len;
! if (tmp > widths[i % col_count])
! widths[i % col_count] = tmp;
if (height > heights[i % col_count])
heights[i % col_count] = height;
if (space > format_space[i % col_count])
format_space[i % col_count] = space;
}
if (opt_border == 0)
! total_w = col_count - 1;
else if (opt_border == 1)
! total_w = col_count * 3 - 1;
else
! total_w = col_count * 3 + 1;
for (i = 0; i < col_count; i++)
! total_w += widths[i];
/*
! * At this point: widths contains the max width of each column heights
! * contains the max height of a cell of each column format_space
contains
! * maximum space required to store formatted string so we prepare the
! * formatting structures
*/
if (col_count > 0)
{
! int heights_total = 0;
struct lineptr *lineptr;
for (i = 0; i < col_count; i++)
! heights_total += heights[i];
! lineptr = lineptr_list = pg_local_calloc(heights_total,
sizeof(*lineptr_list));
for (i = 0; i < col_count; i++)
{
col_lineptrs[i] = lineptr;
lineptr += heights[i];
! format_buf[i] = pg_local_malloc(format_space[i]);
col_lineptrs[i]->ptr = format_buf[i];
}
--- 468,560 ----
complete = NULL;
}
! /* scan all column headers, find maximum width */
for (i = 0; i < col_count; i++)
{
/* Get width & height */
! int width,
! height,
space;
! pg_wcssize((unsigned char *) headers[i], strlen(headers[i]),
encoding, &width, &height, &space);
! if (width > width_max[i])
! width_max[i] = width;
if (height > heights[i])
heights[i] = height;
if (space > format_space[i])
format_space[i] = space;
+
+ width_header[i] = width;
}
! /* scan all rows, find maximum width, compute cell_count */
! for (i = 0, ptr = cells; *ptr; ptr++, i++, cell_count++)
{
! int width,
! height,
space;
/* Get width, ignore height */
! pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
&width, &height, &space);
! if (opt_numeric_locale && opt_align[i % col_count] == 'r')
! {
! width += additional_numeric_locale_len(*ptr);
! space += additional_numeric_locale_len(*ptr);
! }
!
! if (width > width_max[i % col_count])
! width_max[i % col_count] = width;
if (height > heights[i % col_count])
heights[i % col_count] = height;
if (space > format_space[i % col_count])
format_space[i % col_count] = space;
+
+ width_average[i % col_count] += width;
+ }
+
+ /* If we have rows, compute average */
+ if (col_count != 0 && cell_count != 0)
+ {
+ int rows = cell_count / col_count;
+
+ for (i = 0; i < col_count; i++)
+ width_average[i % col_count] /= rows;
}
+ /* adjust the total display width based on border style */
if (opt_border == 0)
! width_total = col_count - 1;
else if (opt_border == 1)
! width_total = col_count * 3 - 1;
else
! width_total = col_count * 3 + 1;
for (i = 0; i < col_count; i++)
! width_total += width_max[i];
/*
! * At this point: width_max[] contains the max width of each column,
! * heights[] contains the max number of lines in each column,
! * format_space[] contains the maximum storage space for formatting
! * strings, width_total contains the giant width sum. Now we allocate
! * some memory...
*/
if (col_count > 0)
{
! int height_total = 0;
struct lineptr *lineptr;
for (i = 0; i < col_count; i++)
! height_total += heights[i];
! lineptr = lineptr_list = pg_local_calloc(height_total,
sizeof(*lineptr_list));
for (i = 0; i < col_count; i++)
{
col_lineptrs[i] = lineptr;
lineptr += heights[i];
! format_buf[i] = pg_local_malloc(format_space[i] + 1);
col_lineptrs[i]->ptr = format_buf[i];
}
***************
*** 535,553 ****
else
lineptr_list = NULL;
if (opt->start_table)
{
/* print title */
if (title && !opt_tuples_only)
{
! /* Get width & height */
! int height;
! pg_wcssize((unsigned char *) title, strlen(title),
encoding, &tmp, &height, NULL);
! if (tmp >= total_w)
! fprintf(fout, "%s\n", title);
else
! fprintf(fout, "%-*s%s\n", (total_w - tmp) / 2,
"", title);
}
/* print headers */
--- 562,650 ----
else
lineptr_list = NULL;
+
+ /* Default word wrap to the full width, i.e. no word wrap */
+ for (i = 0; i < col_count; i++)
+ width_wrap[i] = width_max[i];
+
+ /*
+ * Optional optimized word wrap. Shrink columns with a high max/avg
ratio.
+ * Slighly bias against wider columns (increases chance a narrow column
+ * will fit in its cell)
+ */
+ if (opt->format == PRINT_WRAP)
+ {
+ /* If we can get the terminal width */
+ char *env = getenv("COLUMNS");
+
+ if (env != NULL)
+ tcolumns = atoi(env);
+ #ifdef TIOCGWINSZ
+ else
+ {
+ struct winsize screen_size;
+
+ if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) !=
-1)
+ tcolumns = screen_size.ws_col;
+ }
+ #endif
+
+ if (tcolumns > 0)
+ {
+ /* Shink high ratio columns */
+ while (width_total > tcolumns)
+ {
+ double ratio = 0;
+ double curr_ratio = 0;
+ int worst_col = -1;
+
+ /*
+ * Find column that has the highest ratio
of its maximum
+ * width compared to its average width.
This tells us which
+ * column will produce the fewest wrapped
values if shortened.
+ * width_wrap starts as equal to width_max.
+ */
+ for (i = 0; i < col_count; i++)
+ if (width_average[i] && width_wrap[i] >
width_header[i])
+ {
+ curr_ratio = (double)
width_wrap[i] / width_average[i];
+ curr_ratio += width_max[i] *
0.01; /* Penalize wide columns */
+ if (curr_ratio > ratio)
+ {
+ ratio = curr_ratio;
+ worst_col = i;
+ }
+ }
+
+ /* Exit loop if we can't squeeze any more. */
+ if (worst_col < 0)
+ break;
+
+ /* Squeeze the worst column. Lather, rinse,
repeat */
+ /*
+ * XXX This only reduces one character at
a time so might
+ * be inefficient for very long rows.
+ */
+ width_wrap[worst_col]--;
+ width_total--;
+ }
+ }
+ }
+
+ /* time to output */
if (opt->start_table)
{
/* print title */
if (title && !opt_tuples_only)
{
! int width,
! height;
! pg_wcssize((unsigned char *) title, strlen(title),
encoding, &width, &height, NULL);
! if (width >= width_total)
! fprintf(fout, "%s\n", title); /* Aligned */
else
! fprintf(fout, "%-*s%s\n", (width_total - width)
/ 2, "", title); /* Centered */
}
/* print headers */
***************
*** 557,563 ****
int line_count;
if (opt_border == 2)
! _print_horizontal_line(col_count, widths,
opt_border, fout);
for (i = 0; i < col_count; i++)
pg_wcsformat((unsigned char *) headers[i],
strlen(headers[i]), encoding, col_lineptrs[i], heights[i]);
--- 654,660 ----
int line_count;
if (opt_border == 2)
! _print_horizontal_line(col_count, width_wrap,
opt_border, fout);
for (i = 0; i < col_count; i++)
pg_wcsformat((unsigned char *) headers[i],
strlen(headers[i]), encoding, col_lineptrs[i], heights[i]);
***************
*** 580,586 ****
if (!complete[i])
{
! nbspace = widths[i] -
this_line->width;
/* centered */
fprintf(fout, "%-*s%s%-*s",
--- 677,683 ----
if (!complete[i])
{
! nbspace = width_wrap[i] -
this_line->width;
/* centered */
fprintf(fout, "%-*s%s%-*s",
***************
*** 593,599 ****
}
}
else
! fprintf(fout, "%*s", widths[i],
"");
if (i < col_count - 1)
{
if (opt_border == 0)
--- 690,696 ----
}
}
else
! fprintf(fout, "%*s",
width_wrap[i], "");
if (i < col_count - 1)
{
if (opt_border == 0)
***************
*** 611,711 ****
fputc('\n', fout);
}
! _print_horizontal_line(col_count, widths, opt_border,
fout);
}
}
/* print cells */
for (i = 0, ptr = cells; *ptr; i += col_count, ptr += col_count)
{
! int j;
! int cols_todo = col_count;
! int line_count; /* Number of lines output
so far in row */
if (cancel_pressed)
break;
for (j = 0; j < col_count; j++)
pg_wcsformat((unsigned char *) ptr[j], strlen(ptr[j]),
encoding, col_lineptrs[j], heights[j]);
! line_count = 0;
memset(complete, 0, col_count * sizeof(int));
! while (cols_todo)
{
! /* beginning of line */
! if (opt_border == 2)
! fputs("| ", fout);
! else if (opt_border == 1)
! fputc(' ', fout);
!
! for (j = 0; j < col_count; j++)
{
! struct lineptr *this_line = col_lineptrs[j] +
line_count;
! bool finalspaces = (opt_border == 2
|| j != col_count - 1);
! if (complete[j]) /* Just print spaces...
*/
! {
! if (finalspaces)
! fprintf(fout, "%*s", widths[j],
"");
! }
! else
{
! /* content */
! if (opt_align[j] == 'r')
{
! if (opt_numeric_locale)
{
! /*
! * Assumption: This
code used only on strings
! * without multibyte
characters, otherwise
! * this_line->width <
strlen(this_ptr) and we get
! * an overflow
! */
! char *my_cell =
format_numeric_locale((char *) this_line->ptr);
!
! fprintf(fout, "%*s%s",
! (int)
(widths[i % col_count] - strlen(my_cell)), "",
!
my_cell);
! free(my_cell);
}
else
! fprintf(fout, "%*s%s",
!
widths[j] - this_line->width, "",
!
this_line->ptr);
}
! else
! fprintf(fout, "%-s%*s",
this_line->ptr,
! finalspaces ? (widths[j] -
this_line->width) : 0, "");
! /* If at the right height, done this
col */
! if (line_count == heights[j] - 1 ||
!this_line[1].ptr)
{
! complete[j] = 1;
! cols_todo--;
}
}
! /* divider */
! if ((j + 1) % col_count)
{
! if (opt_border == 0)
! fputc(' ', fout);
! else if (line_count == 0)
! fputs(" | ", fout);
! else
! fprintf(fout, " %c ",
complete[j + 1] ? ' ' : ':');
}
}
- if (opt_border == 2)
- fputs(" |", fout);
- fputc('\n', fout);
- line_count++;
}
}
if (opt->stop_table)
{
if (opt_border == 2 && !cancel_pressed)
! _print_horizontal_line(col_count, widths, opt_border,
fout);
/* print footers */
if (footers && !opt_tuples_only && !cancel_pressed)
--- 708,855 ----
fputc('\n', fout);
}
! _print_horizontal_line(col_count, width_wrap,
opt_border, fout);
}
}
/* print cells */
for (i = 0, ptr = cells; *ptr; i += col_count, ptr += col_count)
{
! bool line_todo,
! cols_todo;
! int line_count;
if (cancel_pressed)
break;
+ /*
+ * Format each cell. Format again, it is a numeric formatting
locale
+ * (e.g. 123,456 vs. 123456)
+ */
for (j = 0; j < col_count; j++)
+ {
pg_wcsformat((unsigned char *) ptr[j], strlen(ptr[j]),
encoding, col_lineptrs[j], heights[j]);
+ if (opt_numeric_locale && opt_align[j % col_count] ==
'r')
+ {
+ char *my_cell;
! my_cell = format_numeric_locale((char *)
col_lineptrs[j]->ptr);
! strcpy((char *) col_lineptrs[j]->ptr, my_cell);
/* Buffer IS large
!
* enough... now */
! free(my_cell);
! }
! }
!
! /* Print rows to console */
memset(complete, 0, col_count * sizeof(int));
! line_count = 0;
! line_todo = true;
! while (line_todo)
{
! cols_todo = true;
! while (cols_todo)
{
! char border_cell = '*';
! cols_todo = false;
!
! /* left border */
! if (opt_border == 2)
! fputs("| ", fout);
! else if (opt_border == 1)
! fputc(' ', fout);
!
! /* for each column */
! for (j = 0; j < col_count; j++)
{
! struct lineptr *this_line =
&col_lineptrs[j][line_count];
!
! if (heights[j] <= line_count)
/* Blank column content */
! {
! fprintf(fout, "%*s",
width_wrap[j], "");
! border_cell = '|';
! }
! else if (opt_align[j] == 'r')
/* Right aligned cell */
{
! int
strlen_remaining = strlen((char *) this_line->ptr + complete[j]);
!
! if (strlen_remaining >
width_wrap[j])
{
! fprintf(fout, "%.*s",
(int) width_wrap[j], this_line->ptr + complete[j]);
! complete[j] +=
width_wrap[j]; /* We've done THIS much */
! cols_todo = true;
/* And there is more to do... */
! border_cell = ':';
}
else
! {
! fprintf(fout, "%*s",
width_wrap[j] - strlen_remaining, "");
! fprintf(fout, "%-s",
this_line->ptr + complete[j]);
! complete[j] +=
strlen_remaining;
! border_cell = '|';
! }
}
! else /* Left aligned cell */
{
! int
strlen_remaining = strlen((char *) this_line->ptr + complete[j]);
!
! if (strlen_remaining >
width_wrap[j])
! {
! fprintf(fout, "%.*s",
(int) width_wrap[j], this_line->ptr + complete[j]);
! complete[j] +=
width_wrap[j]; /* We've done THIS much */
! cols_todo = true;
/* And there is more to do... */
! border_cell = ':';
! }
! else
! {
! fprintf(fout, "%-s",
this_line->ptr + complete[j]);
! fprintf(fout, "%*s",
width_wrap[j] - strlen_remaining, "");
! complete[j] +=
strlen_remaining;
! border_cell = '|';
! }
! }
!
! /* print a divider, middle of columns
only */
! if ((j + 1) % col_count)
! {
! if (opt_border == 0)
! fputc(' ', fout);
! else if (line_count == 0)
! fprintf(fout, " %c ",
border_cell);
! else
! fprintf(fout, " %c ",
complete[j + 1] ? ' ' : ':');
}
}
! /* end of row border */
! if (opt_border == 2)
! fprintf(fout, " %c", border_cell);
! fputc('\n', fout);
! }
!
! /*
! * Check if any columns have line continuations due to
\n in the
! * cell.
! */
! line_count++;
! line_todo = false;
! for (j = 0; j < col_count; j++)
! {
! if (line_count < heights[j])
{
! if (col_lineptrs[j][line_count].ptr)
! {
! line_todo = true;
! complete[j] = 0;
! }
}
}
}
}
if (opt->stop_table)
{
if (opt_border == 2 && !cancel_pressed)
! _print_horizontal_line(col_count, width_wrap,
opt_border, fout);
/* print footers */
if (footers && !opt_tuples_only && !cancel_pressed)
***************
*** 722,728 ****
}
/* clean up */
! free(widths);
free(heights);
free(col_lineptrs);
free(format_space);
--- 866,875 ----
}
/* clean up */
! free(width_header);
! free(width_average);
! free(width_max);
! free(width_wrap);
free(heights);
free(col_lineptrs);
free(format_space);
***************
*** 754,760 ****
dheight = 1,
hformatsize = 0,
dformatsize = 0;
- int tmp = 0;
char *divider;
unsigned int cell_count = 0;
struct lineptr *hlineptr,
--- 901,906 ----
***************
*** 779,790 ****
/* Find the maximum dimensions for the headers */
for (i = 0; i < col_count; i++)
{
! int height,
fs;
! pg_wcssize((unsigned char *) headers[i], strlen(headers[i]),
encoding, &tmp, &height, &fs);
! if (tmp > hwidth)
! hwidth = tmp;
if (height > hheight)
hheight = height;
if (fs > hformatsize)
--- 925,937 ----
/* Find the maximum dimensions for the headers */
for (i = 0; i < col_count; i++)
{
! int width,
! height,
fs;
! pg_wcssize((unsigned char *) headers[i], strlen(headers[i]),
encoding, &width, &height, &fs);
! if (width > hwidth)
! hwidth = width;
if (height > hheight)
hheight = height;
if (fs > hformatsize)
***************
*** 799,805 ****
for (i = 0, ptr = cells; *ptr; ptr++, i++)
{
int numeric_locale_len;
! int height,
fs;
if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
--- 946,953 ----
for (i = 0, ptr = cells; *ptr; ptr++, i++)
{
int numeric_locale_len;
! int width,
! height,
fs;
if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
***************
*** 807,816 ****
else
numeric_locale_len = 0;
! pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
&tmp, &height, &fs);
! tmp += numeric_locale_len;
! if (tmp > dwidth)
! dwidth = tmp;
if (height > dheight)
dheight = height;
if (fs > dformatsize)
--- 955,964 ----
else
numeric_locale_len = 0;
! pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
&width, &height, &fs);
! width += numeric_locale_len;
! if (width > dwidth)
! dwidth = width;
if (height > dheight)
dheight = height;
if (fs > dformatsize)
***************
*** 1879,1884 ****
--- 2027,2033 ----
opt,
output);
break;
case PRINT_ALIGNED:
+ case PRINT_WRAP:
if (opt->expanded)
print_aligned_vertical(title, headers, cells,
footers, align,
opt,
output);
Index: src/bin/psql/print.h
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/print.h,v
retrieving revision 1.35
diff -c -c -r1.35 print.h
*** src/bin/psql/print.h 1 Jan 2008 19:45:56 -0000 1.35
--- src/bin/psql/print.h 17 Apr 2008 02:45:38 -0000
***************
*** 21,26 ****
--- 21,27 ----
PRINT_NOTHING = 0, /* to make sure someone
initializes this */
PRINT_UNALIGNED,
PRINT_ALIGNED,
+ PRINT_WRAP,
PRINT_HTML,
PRINT_LATEX,
PRINT_TROFF_MS
--
Sent via pgsql-patches mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches