Bryce Nesbitt wrote:
> 
> 
> Bruce Momjian wrote:
> > 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.)
> Nice!  I'll merge with my current version.  As you note I changed to ":".

Good, I thought so.

> I also found that for hugely wide output it was better to give up (do 
> nothing), rather than mangle the output in a futile attempt to squash it 
> to the window width.  So there is one more clause in the wrapping if.

Was it because of performance?  I have a way to fix that by decrementing
by more than one to shrink a column?  I am attaching a new patch with my
improved loop.  It remembers the previous maximum ratio.

> I have tested on several unix flavors, but not on Windows or cygwin.

I don't think you need to do that to get it applied --- there is nothing
windows-specific in your code.

Is this ready to be applied?  Do you want to send a final update or are
you still testing?

-- 
  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 14:05:39 -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 14:05:39 -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 14:05:40 -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 14:05:40 -0000
***************
*** 43,48 ****
--- 43,52 ----
  static char *grouping;
  static char *thousands_sep;
  
+ #define COL_RATIO(col_num) \
+                       ((double) width_wrap[col_num] / width_average[col_num] 
+ \
+                       width_max[col_num] * 0.01)              /* Penalize 
wide columns */
+ 
  static void *
  pg_local_malloc(size_t size)
  {
***************
*** 396,401 ****
--- 400,408 ----
  }
  
  
+ /*
+  *    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;
--- 411,441 ----
  {
        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));
--- 449,458 ----
  
        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;
--- 461,470 ----
        }
        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];
                }
--- 472,564 ----
                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 */
--- 566,652 ----
        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          max_ratio = 0, prev_max_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])
+                                       {
+                                               if (COL_RATIO(i) > max_ratio)
+                                               {
+                                                       prev_max_ratio = 
max_ratio;
+                                                       max_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 */
+                               do
+                               {
+                                       width_wrap[worst_col]--;
+                                       width_total--;
+                               } while (width_total > tcolumns && COL_RATIO(i) 
>= prev_max_ratio);
+                       }
+               }
+       }
+ 
+       /* 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]);
--- 656,662 ----
                        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",
--- 679,685 ----
  
                                        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)
--- 692,698 ----
                                                }
                                        }
                                        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)
--- 710,857 ----
                                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);
--- 868,877 ----
        }
  
        /* 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,
--- 903,908 ----
***************
*** 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)
--- 927,939 ----
        /* 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)
--- 948,955 ----
        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)
--- 957,966 ----
                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 ****
--- 2029,2035 ----
                                                                         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 14:05:40 -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 (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches

Reply via email to