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 **** Sets the output format to one of unaligned, ! aligned, html, latex, or troff-ms. Unique abbreviations are allowed. (That would mean one letter is enough.) --- 1513,1520 ---- Sets the output format to one of unaligned, ! aligned, wrapped, ! html, latex, or troff-ms. 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). Aligned mode is the standard, human-readable, ! nicely formatted text output that is default. The HTML and LaTeX 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). Aligned mode is the standard, human-readable, ! nicely formatted text output that is default. ! Wrapped is like aligned but wraps ! the output to fit the screen's width, based on the environment ! variable COLUMNS or the autodetected width. The HTML and LaTeX modes put out tables that are intended to be included in documents using the respective mark-up *************** *** 2708,2713 **** --- 2712,2730 ---- + COLUMNS + + + + The character width to wrap output in wrapped format + mode. Many shells automatically update COLUMNS when + a window is resized. If not set the screen width is automatically + detected, if possible. + + + + + PAGER 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