Hi,

Here is my patch to make psql handle multi-line output sanely. Instead
of embedded newlines splattering your output across the screen,
everything gets indented to the right column.

It basically works by extending the *_width functions to instead work
out the estimate width, height and formatting space of each cell. Then
the output goes through each cell formatting as it goes and outputting
lines at the right places.

I imagine it will be tweaked by others because everybody has different
ideas about how they want the output done. This just has the minimum
extra formatting to make the output unambiguous.

Also available at: http://svana.org/kleptog/pgsql/psql-format.patch

Have a nice day,
-- 
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.
? psql
? test_script
Index: mbprint.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/mbprint.c,v
retrieving revision 1.18
diff -c -r1.18 mbprint.c
*** mbprint.c   15 Oct 2005 02:49:40 -0000      1.18
--- mbprint.c   17 Nov 2005 13:06:57 -0000
***************
*** 211,216 ****
--- 211,360 ----
        return width;
  }
  
+ /* mb_utf_wcsize : calculate column display size for the utf8 string pwcs
+  */
+ static int
+ mb_utf_wcssize(unsigned char *pwcs, size_t len, int *width, int *height, int 
*format_size)
+ {
+       int                     w,
+                               l = 0,
+                               linewidth = 0;
+       *width = 0;
+       *height = 1;
+       *format_size = 0;
+ 
+       for (; *pwcs && len > 0; pwcs += l)
+       {
+               l = pg_utf_mblen(pwcs);
+               if ( len < (size_t) l)
+                       break;
+               w = ucs_wcwidth(utf2ucs(pwcs));
+ 
+               if( w == 0 )  /* NULL character */
+               {
+                       *format_size += 4;   /* \x00 */
+                       linewidth += 4;
+               }
+               else if( l == 1 )   /* ASCII char */
+               {
+                       if( *pwcs == '\n' ) /* Newline */
+                       {
+                               if( linewidth > *width )
+                                       *width = linewidth;
+                               linewidth = 0;
+                               *height+=1;
+                               *format_size += 1;  /* For NUL char */
+                       }
+                       else if( *pwcs == '\r' )   /* Linefeed */
+                       {
+                               linewidth+=2;
+                               *format_size+=2;
+                       }
+                       else if( *pwcs < 32 )  /* Control char */
+                       {
+                               linewidth+=4;
+                               *format_size+=4;
+                       }
+                       else  /* Output itself */
+                       {
+                               linewidth++;
+                               *format_size += 1;
+                       }
+               }
+               else if( w < 0 )  /* Non-ascii control char */
+               {
+                       linewidth+=6;   /* \u0000 */
+                       *format_size += 6;
+               }
+               else  /* All other chars */
+               {
+                       linewidth += w;
+                       *format_size += l;
+               }
+               len -= l;
+       }
+       if( linewidth > *width )
+               *width = linewidth;
+       *format_size += 1;
+       return *width;
+ }
+ 
+ static void
+ mb_utf_wcsformat( unsigned char *pwcs, int len, struct lineptr *lines, int 
count )
+ {
+       int                     w,
+                               l = 0;
+       int linewidth = 0;
+       
+       char *ptr = lines->ptr;   /* Pointer to data area */
+ 
+       for (; *pwcs && len > 0; pwcs += l)
+       {
+               l = pg_utf_mblen(pwcs);
+               if ( len < (size_t) l)
+                       break;
+               w = ucs_wcwidth(utf2ucs(pwcs));
+ 
+               if( w == 0 )  /* NULL character */
+               {
+                       strcpy( ptr, "\x00" );
+                       ptr+=4;
+                       linewidth += 4;
+               }
+               else if( l == 1 )   /* ASCII char */
+               {
+                       if( *pwcs == '\n' ) /* Newline */
+                       {
+                               *ptr++ = 0;   /* NULL char */
+                               lines->width = linewidth;
+                               linewidth = 0;
+                               lines++, count--;
+                               if( count == 0 )
+                                       exit(1);   /* Screwup */        
+                                       
+                               lines->ptr = ptr;
+                       }
+                       else if( *pwcs == '\r' )   /* Linefeed */
+                       {
+                               strcpy( ptr, "\\r" );
+                               linewidth += 2;
+                               ptr+=2;
+                       }
+                       else if( *pwcs < 32 )  /* Control char */
+                       {
+                               sprintf( ptr, "\\x%02X", *pwcs );
+                               linewidth += 4;
+                               ptr += 4;
+                       }
+                       else  /* Output itself */
+                       {
+                               linewidth++;
+                               *ptr++ = *pwcs;
+                       }
+               }
+               else if( w < 0 )  /* Non-ascii control char */
+               {
+                       sprintf( ptr, "\\u%04X", utf2ucs(pwcs) );
+                       ptr += 6;
+                       linewidth += 6;
+               }
+               else  /* All other chars */
+               {
+                       int i;
+                       for( i=0; i<l; i++ )
+                               *ptr++ = pwcs[i];
+                       linewidth += w;
+               }
+               len -= l;
+       }
+       *ptr++ = 0;
+       lines->width = linewidth;
+       lines++, count--;
+       if( count > 0 )
+               lines->ptr = NULL;
+       return;
+ }
+ 
  static int
  utf_charcheck(const unsigned char *c)
  {
***************
*** 309,315 ****
   */
  
  int
! pg_wcswidth(const char *pwcs, size_t len, int encoding)
  {
        if (encoding == PG_UTF8)
                return mb_utf_wcswidth((const unsigned char *) pwcs, len);
--- 453,459 ----
   */
  
  int
! pg_wcswidth(const unsigned char *pwcs, size_t len, int encoding)
  {
        if (encoding == PG_UTF8)
                return mb_utf_wcswidth((const unsigned char *) pwcs, len);
***************
*** 323,330 ****
        }
  }
  
! char *
! mbvalidate(char *pwcs, int encoding)
  {
        if (encoding == PG_UTF8)
                mb_utf_validate((unsigned char *) pwcs);
--- 467,623 ----
        }
  }
  
! int
! pg_wcssize( unsigned char *pwcs, size_t len, int encoding, int *width, int 
*height, int *format_size )
! {
!       int w, h, fs;
!       
!       switch( encoding )
!       {
!               case PG_UTF8:
!                       mb_utf_wcssize(pwcs, len, &w, &h, &fs);
!                       break;
!               case PG_SQL_ASCII:
!               case PG_LATIN1:                                      /* 
ISO-8859-1 Latin 1 */
!               case PG_LATIN2:                                      /* 
ISO-8859-2 Latin 2 */
!               case PG_LATIN3:                                      /* 
ISO-8859-3 Latin 3 */
!               case PG_LATIN4:                                      /* 
ISO-8859-4 Latin 4 */
!               case PG_LATIN5:                                      /* 
ISO-8859-9 Latin 5 */
!               case PG_LATIN6:                                      /* 
ISO-8859-10 Latin6 */
!               case PG_LATIN7:                                      /* 
ISO-8859-13 Latin7 */
!               case PG_LATIN8:                                      /* 
ISO-8859-14 Latin8 */
!               case PG_LATIN9:                                      /* 
ISO-8859-15 Latin9 */
!               case PG_LATIN10:                                     /* 
ISO-8859-16 Latin10 */
!               {   /* This should work for any single byte encoding */
!                       int i;
!                       int linewidth = 0;
!               
!                       w = 0;
!                       h = 1;
!                       fs = 0;
!               
!                       for( i=0; i<len; i++ )
!                       {
!                               if( pwcs[i] == '\n' )
!                               {
!                                       if( linewidth > w )
!                                               w = linewidth;
!                                       fs += linewidth+1;
!                                       linewidth = 0;
!                                       h++;
!                               }
!                               else if( pwcs[i] == '\r' )
!                               {
!                                       linewidth+=2;
!                               }
!                               else if( pwcs[i] < 32 )
!                               {
!                                       linewidth+=4;
!                               }
!                               else
!                               {
!                                       linewidth++;
!                               }
!                       }
!                       if( linewidth > w )
!                               w = linewidth;
!                       fs += linewidth+1;
!                       break;
!               }
!               default:
!                       w = len;
!                       h = 1;
!                       fs = len+1;
!                       break;
!       }
!       
!       if (width)
!               *width = w;
!       if (height)
!               *height = h;
!       if( format_size )
!               *format_size = fs;
!               
!       return w;
! }
! 
! void
! pg_wcsformat( unsigned char *pwcs, size_t len, int encoding, struct lineptr 
*lines, int count )
! {
!       switch( encoding )
!       {
!               case PG_UTF8:
!                       mb_utf_wcsformat(pwcs, len, lines, count);
!                       break;
!               case PG_SQL_ASCII:
!               case PG_LATIN1:                                      /* 
ISO-8859-1 Latin 1 */
!               case PG_LATIN2:                                      /* 
ISO-8859-2 Latin 2 */
!               case PG_LATIN3:                                      /* 
ISO-8859-3 Latin 3 */
!               case PG_LATIN4:                                      /* 
ISO-8859-4 Latin 4 */
!               case PG_LATIN5:                                      /* 
ISO-8859-9 Latin 5 */
!               case PG_LATIN6:                                      /* 
ISO-8859-10 Latin6 */
!               case PG_LATIN7:                                      /* 
ISO-8859-13 Latin7 */
!               case PG_LATIN8:                                      /* 
ISO-8859-14 Latin8 */
!               case PG_LATIN9:                                      /* 
ISO-8859-15 Latin9 */
!               case PG_LATIN10:                                     /* 
ISO-8859-16 Latin10 */
!               {       /* This should work for any single byte encoding */
!                       int i;
!                       
!                       int w = 0;
!                       unsigned char *ptr = lines->ptr;
!               
!                       for( i=0; i<len; i++ )
!                       {
!                               if( pwcs[i] == '\n' )
!                               {
!                                       *ptr++ = 0;
!                                       lines->width = w;
!                                       w = 0;
!                                       lines++, count--;
!                                       if( count == 0 )
!                                               exit(1);   /* Screwup */
!                                       lines->ptr = ptr;
!                               }
!                               else if( pwcs[i] == '\r' )
!                               {
!                                       strcpy( ptr, "\\r" );
!                                       w += 2;
!                                       ptr+=2;
!                               }
!                               else if( pwcs[i] < 32 )
!                               {
!                                       sprintf( ptr, "\\x%02X", pwcs[i] );
!                                       w += 4;
!                                       ptr+=4;
!                               }
!                               else
!                               {
!                                       *ptr++ = pwcs[i];
!                                       w++;
!                               }
!                       }
!                       *ptr++ = 0;
!                       lines->width = w;
!                       lines++, count--;
!                       if( count > 0 )
!                               lines->ptr = NULL;
!                       break;
!               }       
!               default:   /* Other encodings? */
!                       /* If we knew that the locale and the current
!                        * encoding were related, we could use the mblen()
!                        * function to acheive the same effect as what we've
!                        * hand-written for utf8... We don't so we just bail. */
! 
!                       memcpy( lines->ptr, pwcs, len );
!                       lines->width = len;
!                       break;
!       }
!       return;
! }
! 
! unsigned char *
! mbvalidate(unsigned char *pwcs, int encoding)
  {
        if (encoding == PG_UTF8)
                mb_utf_validate((unsigned char *) pwcs);
Index: mbprint.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/mbprint.h,v
retrieving revision 1.8
diff -c -r1.8 mbprint.h
*** mbprint.h   24 Sep 2005 17:53:27 -0000      1.8
--- mbprint.h   17 Nov 2005 13:06:57 -0000
***************
*** 4,11 ****
  
  #include "mb/pg_wchar.h"
  
! extern char *mbvalidate(char *pwcs, int encoding);
  
! extern int    pg_wcswidth(const char *pwcs, size_t len, int encoding);
  
  #endif   /* MBPRINT_H */
--- 4,18 ----
  
  #include "mb/pg_wchar.h"
  
! struct lineptr {
!       unsigned char *ptr;
!       int width;
! };
  
! extern unsigned char *mbvalidate(unsigned char *pwcs, int encoding);
! 
! extern int    pg_wcswidth(const unsigned char *pwcs, size_t len, int 
encoding);
! extern void   pg_wcsformat( unsigned char *pwcs, size_t len, int encoding, 
struct lineptr *lines, int count );
! extern int    pg_wcssize( unsigned char *pwcs, size_t len, int encoding, int 
*width, int *height, int *format_size );
  
  #endif   /* MBPRINT_H */
Index: print.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/print.c,v
retrieving revision 1.79
diff -c -r1.79 print.c
*** print.c     27 Oct 2005 13:34:47 -0000      1.79
--- print.c     17 Nov 2005 13:06:57 -0000
***************
*** 49,54 ****
--- 49,68 ----
        return tmp;
  }
  
+ static void *
+ pg_local_calloc(int count, size_t size)
+ {
+       void       *tmp;
+ 
+       tmp = calloc(count, size);
+       if (!tmp)
+       {
+               fprintf(stderr, _("out of memory\n"));
+               exit(EXIT_FAILURE);
+       }
+       return tmp;
+ }
+ 
  static int
  integer_digits(const char *my_str)
  {
***************
*** 87,92 ****
--- 101,107 ----
        return strlen(my_str) + additional_numeric_locale_len(my_str);
  }
  
+ /* Returns the appropriately formatted string in a new allocated block, 
caller must free */
  static char *
  format_numeric_locale(const char *my_str)
  {
***************
*** 138,144 ****
  
                new_str[j] = my_str[i];
        }
- 
        return new_str;
  }
  
--- 153,158 ----
***************
*** 342,354 ****
  {
        unsigned int col_count = 0;
        unsigned int cell_count = 0;
-       unsigned int *head_w,
-                          *cell_w;
        unsigned int i,
                                tmp;
        unsigned int *widths,
                                total_w;
!       const char *const * ptr;
  
        /* count columns */
        for (ptr = headers; *ptr; ptr++)
--- 356,375 ----
  {
        unsigned int col_count = 0;
        unsigned int cell_count = 0;
        unsigned int i,
                                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 */
  
        /* count columns */
        for (ptr = headers; *ptr; ptr++)
***************
*** 356,419 ****
  
        if (col_count > 0)
        {
!               widths = calloc(col_count, sizeof(*widths));
!               if (!widths)
!               {
!                       fprintf(stderr, _("out of memory\n"));
!                       exit(EXIT_FAILURE);
!               }
! 
!               head_w = calloc(col_count, sizeof(*head_w));
!               if (!head_w)
!               {
!                       fprintf(stderr, _("out of memory\n"));
!                       exit(EXIT_FAILURE);
!               }
        }
        else
        {
                widths = NULL;
!               head_w = NULL;
        }
! 
        /* count cells (rows * cols) */
        for (ptr = cells; *ptr; ptr++)
                cell_count++;
  
-       if (cell_count > 0)
-       {
-               cell_w = calloc(cell_count, sizeof(*cell_w));
-               if (!cell_w)
-               {
-                       fprintf(stderr, _("out of memory\n"));
-                       exit(EXIT_FAILURE);
-               }
-       }
-       else
-               cell_w = NULL;
- 
        /* calc column widths */
        for (i = 0; i < col_count; i++)
        {
!               tmp = pg_wcswidth(headers[i], strlen(headers[i]), encoding);
                if (tmp > widths[i])
                        widths[i] = tmp;
!               head_w[i] = tmp;
        }
  
        for (i = 0, ptr = cells; *ptr; ptr++, i++)
        {
!               int                     add_numeric_locale_len;
  
                if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
!                       add_numeric_locale_len = 
additional_numeric_locale_len(*ptr);
!               else
!                       add_numeric_locale_len = 0;
! 
!               tmp = pg_wcswidth(*ptr, strlen(*ptr), encoding) + 
add_numeric_locale_len;
                if (tmp > widths[i % col_count])
                        widths[i % col_count] = tmp;
!               cell_w[i] = tmp;
        }
  
        if (opt_border == 0)
--- 377,437 ----
  
        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) );
!               format_buf = pg_local_calloc( col_count, sizeof(*format_buf) );
!               complete = pg_local_calloc( col_count, sizeof(*complete) );
!       
        }
        else
        {
                widths = NULL;
!               heights = NULL;
!               col_lineptrs = NULL;
!               format_space = NULL;
!               format_buf = NULL;
!               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)
***************
*** 426,435 ****
        for (i = 0; i < col_count; i++)
                total_w += widths[i];
  
        /* print title */
        if (title && !opt_tuples_only)
        {
!               tmp = pg_wcswidth(title, strlen(title), encoding);
                if (tmp >= total_w)
                        fprintf(fout, "%s\n", title);
                else
--- 444,481 ----
        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
+        */
+       {
+               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];
+               }
+       }
+                       
        /* 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
***************
*** 439,528 ****
        /* print headers */
        if (!opt_tuples_only)
        {
                if (opt_border == 2)
                        _print_horizontal_line(col_count, widths, opt_border, 
fout);
  
-               if (opt_border == 2)
-                       fputs("| ", fout);
-               else if (opt_border == 1)
-                       fputc(' ', fout);
- 
                for (i = 0; i < col_count; i++)
                {
!                       unsigned int nbspace;
  
!                       nbspace = widths[i] - head_w[i];
  
!                       /* centered */
!                       fprintf(fout, "%-*s%s%-*s",
!                                       nbspace / 2, "", headers[i], (nbspace + 
1) / 2, "");
  
!                       if (i < col_count - 1)
!                       {
!                               if (opt_border == 0)
!                                       fputc(' ', fout);
                                else
!                                       fputs(" | ", fout);
                        }
                }
  
-               if (opt_border == 2)
-                       fputs(" |", fout);
-               else if (opt_border == 1)
-                       fputc(' ', fout);;
-               fputc('\n', fout);
  
                _print_horizontal_line(col_count, widths, opt_border, fout);
        }
  
        /* print cells */
!       for (i = 0, ptr = cells; *ptr; i++, ptr++)
        {
!               /* beginning of line */
!               if (i % col_count == 0)
                {
                        if (opt_border == 2)
                                fputs("| ", fout);
                        else if (opt_border == 1)
                                fputc(' ', fout);
-               }
  
!               /* content */
!               if (opt_align[i % col_count] == 'r')
!               {
!                       if (opt_numeric_locale)
                        {
!                               char       *my_cell = 
format_numeric_locale(*ptr);
  
!                               fprintf(fout, "%*s%s", widths[i % col_count] - 
cell_w[i], "", my_cell);
!                               free(my_cell);
                        }
-                       else
-                               fprintf(fout, "%*s%s", widths[i % col_count] - 
cell_w[i], "", *ptr);
-               }
-               else
-               {
-                       if ((i + 1) % col_count == 0 && opt_border != 2)
-                               fputs(cells[i], fout);
-                       else
-                               fprintf(fout, "%-s%*s", cells[i],
-                                               widths[i % col_count] - 
cell_w[i], "");
-               }
- 
-               /* divider */
-               if ((i + 1) % col_count)
-               {
-                       if (opt_border == 0)
-                               fputc(' ', fout);
-                       else
-                               fputs(" | ", fout);
-               }
-               /* end of line */
-               else
-               {
                        if (opt_border == 2)
                                fputs(" |", fout);
                        fputc('\n', fout);
                }
        }
  
--- 485,628 ----
        /* print headers */
        if (!opt_tuples_only)
        {
+               int cols_todo;
+               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] );
+       
+               cols_todo = col_count;
+               line_count = 0;
+               memset( complete, 0, col_count*sizeof(int) );
+               while( cols_todo )
                {
!                       if (opt_border == 2)
!                               fprintf(fout, "|%c", line_count ? '+' : ' ' );
!                       else if (opt_border == 1)
!                               fputc(line_count ? '+' : ' ', fout);
! 
!                       for (i = 0; i < col_count; i++)
!                       {
!                               unsigned int nbspace;
  
!                               struct lineptr *this_line = col_lineptrs[i] + 
line_count;
!                               if( !complete[i] )
!                               {
!                                       nbspace = widths[i] - this_line->width;
  
!                                       /* centered */
!                                       fprintf(fout, "%-*s%s%-*s",
!                                                       nbspace / 2, "", 
this_line->ptr, (nbspace + 1) / 2, "");
  
!                                       if( line_count == (heights[i]-1) || 
!(this_line+1)->ptr )
!                                       {
!                                               cols_todo--;
!                                               complete[i] = 1;
!                                       }
!                               }
                                else
!                               {
!                                       fprintf( fout, "%*s", widths[i], "" );
!                               }
!                               if (i < col_count - 1)
!                               {
!                                       if (opt_border == 0)
!                                               fputc(line_count ? '+' : ' ', 
fout);
!                                       else
!                                               fprintf( fout, " |%c", 
line_count ? '+' : ' ');
!                               }
                        }
+                       line_count++;
+ 
+                       if (opt_border == 2)
+                               fputs(" |", fout);
+                       else if (opt_border == 1)
+                               fputc(' ', fout);;
+                       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 */
!               
!               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;
!                               if( complete[j] )  /* Just print spaces... */
!                               {
!                                       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(this_line->ptr);
!                                                       fprintf(fout, "%*s%s", 
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,
!                                                               widths[j] - 
this_line->width, "");
!                                       }
!                                       /* 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++;
                }
        }
  
***************
*** 543,551 ****
  #endif
  
        /* clean up */
-       free(cell_w);
-       free(head_w);
        free(widths);
  }
  
  
--- 643,657 ----
  #endif
  
        /* clean up */
        free(widths);
+       free(heights);
+       free(col_lineptrs);
+       free(format_space);
+       free(complete);
+       free(lineptr_list);
+       for( i=0; i<col_count; i++ )
+               free(format_buf[i] );
+       free(format_buf);
  }
  
  
***************
*** 563,574 ****
        unsigned int i,
                                tmp = 0,
                                hwidth = 0,
!                               dwidth = 0;
        char       *divider;
        unsigned int cell_count = 0;
!       unsigned int *cell_w,
!                          *head_w;
! 
        if (cells[0] == NULL)
        {
                fprintf(fout, _("(No rows)\n"));
--- 669,683 ----
        unsigned int i,
                                tmp = 0,
                                hwidth = 0,
!                               dwidth = 0,
!                               hheight = 1,
!                               dheight = 1,
!                               hformatsize = 0,
!                               dformatsize = 0;
        char       *divider;
        unsigned int cell_count = 0;
!       struct lineptr *hlineptr, *dlineptr;
!       
        if (cells[0] == NULL)
        {
                fprintf(fout, _("(No rows)\n"));
***************
*** 578,635 ****
        /* count headers and find longest one */
        for (ptr = headers; *ptr; ptr++)
                col_count++;
-       if (col_count > 0)
-       {
-               head_w = calloc(col_count, sizeof(*head_w));
-               if (!head_w)
-               {
-                       fprintf(stderr, _("out of memory\n"));
-                       exit(EXIT_FAILURE);
-               }
-       }
-       else
-               head_w = NULL;
  
        for (i = 0; i < col_count; i++)
        {
!               tmp = pg_wcswidth(headers[i], strlen(headers[i]), encoding);
                if (tmp > hwidth)
                        hwidth = tmp;
!               head_w[i] = tmp;
        }
  
        /* Count cells, find their lengths */
        for (ptr = cells; *ptr; ptr++)
                cell_count++;
  
-       if (cell_count > 0)
-       {
-               cell_w = calloc(cell_count, sizeof(*cell_w));
-               if (!cell_w)
-               {
-                       fprintf(stderr, _("out of memory\n"));
-                       exit(EXIT_FAILURE);
-               }
-       }
-       else
-               cell_w = NULL;
- 
        /* find longest data cell */
        for (i = 0, ptr = cells; *ptr; ptr++, i++)
        {
!               int                     add_numeric_locale_len;
  
                if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
!                       add_numeric_locale_len = 
additional_numeric_locale_len(*ptr);
!               else
!                       add_numeric_locale_len = 0;
  
!               tmp = pg_wcswidth(*ptr, strlen(*ptr), encoding) + 
add_numeric_locale_len;
                if (tmp > dwidth)
                        dwidth = tmp;
!               cell_w[i] = tmp;
!       }
! 
        /* print title */
        if (!opt_tuples_only && title)
                fprintf(fout, "%s\n", title);
--- 687,738 ----
        /* count headers and find longest one */
        for (ptr = headers; *ptr; ptr++)
                col_count++;
  
+       /* 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)
!                       hformatsize = fs;
        }
  
        /* Count cells, find their lengths */
        for (ptr = cells; *ptr; ptr++)
                cell_count++;
  
        /* find longest data cell */
        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)
!                       numeric_locale_len = 
additional_numeric_locale_len(*ptr);
!               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)
!                       dformatsize = fs;
!       }
!       
!       /* We now have all the information we need to setup the formatting 
structures */
!       dlineptr = pg_local_malloc( sizeof(*dlineptr) * dheight );
!       hlineptr = pg_local_malloc( sizeof(*hlineptr) * hheight );
!       
!       dlineptr->ptr = pg_local_malloc( dformatsize );
!       hlineptr->ptr = pg_local_malloc( hformatsize );
!       
        /* print title */
        if (!opt_tuples_only && title)
                fprintf(fout, "%s\n", title);
***************
*** 653,658 ****
--- 756,763 ----
        /* print records */
        for (i = 0, ptr = cells; *ptr; i++, ptr++)
        {
+               int line_count, dcomplete, hcomplete;
+               
                if (i % col_count == 0)
                {
                        if (!opt_tuples_only)
***************
*** 688,720 ****
                                fprintf(fout, "%s\n", divider);
                }
  
!               if (opt_border == 2)
!                       fputs("| ", fout);
!               fprintf(fout, "%-s%*s", headers[i % col_count],
!                               hwidth - head_w[i % col_count], "");
! 
!               if (opt_border > 0)
!                       fputs(" | ", fout);
!               else
!                       fputs(" ", fout);
! 
!               if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
                {
!                       char       *my_cell = format_numeric_locale(*ptr);
! 
!                       if (opt_border < 2)
!                               fprintf(fout, "%s\n", my_cell);
                        else
!                               fprintf(fout, "%-s%*s |\n", my_cell, dwidth - 
cell_w[i], "");
!                       free(my_cell);
!               }
!               else
!               {
!                       if (opt_border < 2)
!                               fprintf(fout, "%s\n", *ptr);
                        else
!                               fprintf(fout, "%-s%*s |\n", *ptr, dwidth - 
cell_w[i], "");
!               }
        }
  
        if (opt_border == 2)
--- 793,858 ----
                                fprintf(fout, "%s\n", divider);
                }
  
!               /* Format the header */
!               pg_wcsformat( (unsigned char*)headers[i % col_count], 
strlen(headers[i % col_count]), encoding, hlineptr, hheight );
!               /* Format the data */
!               pg_wcsformat( (unsigned char*)*ptr, strlen(*ptr), encoding, 
dlineptr, dheight );
!               
!               line_count = 0;
!               dcomplete = hcomplete = 0;
!               while( !dcomplete || !hcomplete )
                {
!                       if (opt_border == 2)
!                               fputs("| ", fout);
!                       if( !hcomplete )
!                       {
!                               fprintf(fout, "%-s%*s", 
hlineptr[line_count].ptr,
!                                               hwidth - 
hlineptr[line_count].width, "");
!                                               
!                               if( line_count == (hheight-1) || 
!hlineptr[line_count+1].ptr )
!                                       hcomplete = 1;
!                       }
                        else
!                       {
!                               fprintf( fout, "%*s", hwidth, "" );
!                       }
!       
!                       if (opt_border > 0)
!                               fprintf(fout, " %c ", (line_count==0)?'|':':' );
                        else
!                               fputs(" ", fout);
! 
!                       if( !dcomplete )
!                       {
!                               if (opt_align[i % col_count] == 'r' && 
opt_numeric_locale)
!                               {
!                                       char *my_cell = 
format_numeric_locale(dlineptr[line_count].ptr);
!                                       if (opt_border < 2)
!                                               fprintf(fout, "%s\n", my_cell);
!                                       else
!                                               fprintf(fout, "%-s%*s |\n", 
my_cell, dwidth - strlen(my_cell), "");
!                                       free(my_cell);
!                               }
!                               else
!                               {
!                                       if (opt_border < 2)
!                                               fprintf(fout, "%s\n", 
dlineptr[line_count].ptr);
!                                       else
!                                               fprintf(fout, "%-s%*s |\n", 
dlineptr[line_count].ptr, dwidth - dlineptr[line_count].width, "");
!                               }
!                               
!                               if( line_count == (dheight-1) || 
!dlineptr[line_count+1].ptr )
!                                       dcomplete = 1;
!                       }
!                       else
!                       {
!                               if( opt_border < 2 )
!                                       fputc('\n', fout);
!                               else
!                                       fprintf( fout, "%*s |\n", dwidth, "" );
!                       }
!                       line_count++;
!               }
        }
  
        if (opt_border == 2)
***************
*** 732,740 ****
  
        fputc('\n', fout);
        free(divider);
! 
!       free(cell_w);
!       free(head_w);
  }
  
  
--- 870,879 ----
  
        fputc('\n', fout);
        free(divider);
!       free(hlineptr->ptr);
!       free(dlineptr->ptr);
!       free(hlineptr);
!       free(dlineptr);
  }
  
  
***************
*** 823,829 ****
                col_count++;
                if (!opt_tuples_only)
                {
!                       fputs("    <th align=\"center\">", fout);
                        html_escaped_print(*ptr, fout);
                        fputs("</th>\n", fout);
                }
--- 962,968 ----
                col_count++;
                if (!opt_tuples_only)
                {
!                       fputs(" <th align=\"center\">", fout);
                        html_escaped_print(*ptr, fout);
                        fputs("</th>\n", fout);
                }
***************
*** 837,843 ****
                if (i % col_count == 0)
                        fputs("  <tr valign=\"top\">\n", fout);
  
!               fprintf(fout, "    <td align=\"%s\">", opt_align[(i) % 
col_count] == 'r' ? "right" : "left");
                /* is string only whitespace? */
                if ((*ptr)[strspn(*ptr, " \t")] == '\0')
                        fputs("&nbsp; ", fout);
--- 976,982 ----
                if (i % col_count == 0)
                        fputs("  <tr valign=\"top\">\n", fout);
  
!               fprintf(fout, " <td align=\"%s\">", opt_align[(i) % col_count] 
== 'r' ? "right" : "left");
                /* is string only whitespace? */
                if ((*ptr)[strspn(*ptr, " \t")] == '\0')
                        fputs("&nbsp; ", fout);
***************
*** 916,926 ****
                                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");
                /* is string only whitespace? */
                if ((*ptr)[strspn(*ptr, " \t")] == '\0')
                        fputs("&nbsp; ", fout);
--- 1055,1065 ----
                                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");
                /* is string only whitespace? */
                if ((*ptr)[strspn(*ptr, " \t")] == '\0')
                        fputs("&nbsp; ", fout);
***************
*** 1613,1636 ****
        /* extract headers */
        nfields = PQnfields(result);
  
!       headers = calloc(nfields + 1, sizeof(*headers));
!       if (!headers)
!       {
!               fprintf(stderr, _("out of memory\n"));
!               exit(EXIT_FAILURE);
!       }
  
        for (i = 0; i < nfields; i++)
                headers[i] = mbvalidate(PQfname(result, i), opt->topt.encoding);
  
        /* set cells */
        ncells = PQntuples(result) * nfields;
!       cells = calloc(ncells + 1, sizeof(*cells));
!       if (!cells)
!       {
!               fprintf(stderr, _("out of memory\n"));
!               exit(EXIT_FAILURE);
!       }
  
        for (i = 0; i < ncells; i++)
        {
--- 1752,1765 ----
        /* extract headers */
        nfields = PQnfields(result);
  
!       headers = pg_local_calloc(nfields + 1, sizeof(*headers));
  
        for (i = 0; i < nfields; i++)
                headers[i] = mbvalidate(PQfname(result, i), opt->topt.encoding);
  
        /* set cells */
        ncells = PQntuples(result) * nfields;
!       cells = pg_local_calloc(ncells + 1, sizeof(*cells));
  
        for (i = 0; i < ncells; i++)
        {
***************
*** 1646,1657 ****
                footers = opt->footers;
        else if (!opt->topt.expanded && opt->default_footer)
        {
!               footers = calloc(2, sizeof(*footers));
!               if (!footers)
!               {
!                       fprintf(stderr, _("out of memory\n"));
!                       exit(EXIT_FAILURE);
!               }
  
                footers[0] = pg_local_malloc(100);
                if (PQntuples(result) == 1)
--- 1775,1781 ----
                footers = opt->footers;
        else if (!opt->topt.expanded && opt->default_footer)
        {
!               footers = pg_local_calloc(2, sizeof(*footers));
  
                footers[0] = pg_local_malloc(100);
                if (PQntuples(result) == 1)
***************
*** 1663,1674 ****
                footers = NULL;
  
        /* set alignment */
!       align = calloc(nfields + 1, sizeof(*align));
!       if (!align)
!       {
!               fprintf(stderr, _("out of memory\n"));
!               exit(EXIT_FAILURE);
!       }
  
        for (i = 0; i < nfields; i++)
        {
--- 1787,1793 ----
                footers = NULL;
  
        /* set alignment */
!       align = pg_local_calloc(nfields + 1, sizeof(*align));
  
        for (i = 0; i < nfields; i++)
        {

Attachment: pgpUvQPIXfEHZ.pgp
Description: PGP signature

Reply via email to