? 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; iwidth = 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 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; iwidth = 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 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(" ", fout); html_escaped_print(*ptr, fout); fputs("\n", fout); } --- 962,968 ---- col_count++; if (!opt_tuples_only) { ! fputs(" ", fout); html_escaped_print(*ptr, fout); fputs("\n", fout); } *************** *** 837,843 **** if (i % col_count == 0) fputs(" \n", fout); ! fprintf(fout, " ", opt_align[(i) % col_count] == 'r' ? "right" : "left"); /* is string only whitespace? */ if ((*ptr)[strspn(*ptr, " \t")] == '\0') fputs("  ", fout); --- 976,982 ---- if (i % col_count == 0) fputs(" \n", fout); ! fprintf(fout, " ", opt_align[(i) % col_count] == 'r' ? "right" : "left"); /* is string only whitespace? */ if ((*ptr)[strspn(*ptr, " \t")] == '\0') fputs("  ", fout); *************** *** 916,926 **** fputs("\n  \n", fout); } fputs(" \n" ! " ", fout); html_escaped_print(headers[i % col_count], fout); fputs("\n", fout); ! fprintf(fout, " ", opt_align[i % col_count] == 'r' ? "right" : "left"); /* is string only whitespace? */ if ((*ptr)[strspn(*ptr, " \t")] == '\0') fputs("  ", fout); --- 1055,1065 ---- fputs("\n  \n", fout); } fputs(" \n" ! " ", fout); html_escaped_print(headers[i % col_count], fout); fputs("\n", fout); ! fprintf(fout, " ", opt_align[i % col_count] == 'r' ? "right" : "left"); /* is string only whitespace? */ if ((*ptr)[strspn(*ptr, " \t")] == '\0') fputs("  ", 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++) {