On Sun, Aug 23, 2009 at 06:33:49PM -0400, Alvaro Herrera wrote: > Roger Leigh escribió: > > > +#if (defined(HAVE_LANGINFO_H) && defined(CODESET)) > > + if (!strcmp(nl_langinfo(CODESET), "UTF-8")) > > + text_format = &utf8format; > > +#endif > > I think you should also try to match to "UTF8", and do it in > case-insensitive manner (pg_strcasecmp), just like chklocale.c.
An updated copy of the patch is attached. This has the following changes: - matches UTF-8, utf8 and CP65001 case insensitively as for chklocale.c - uses fprintf in place of repeated fputs/fputc calls - moved hrule from table to line formatting - moved vrule from table to separate line format The latter two allow complete specification of all the characters used to draw. You can now have different horizonal rule types for the different line types (demonstrated by making PRINT_RULE_MIDDLE thick rather than thin). The same applies to the vertical rules, but since these are drawn intermixed with data these are a separate line format in their own right (PRINT_RULE_DATA). You can if you like make incredibly ugly tables consisting of all sorts of thin, thick and double ruled lines running horizontally and vertically at all edges and positions. The patch as it is keeps this subtle! But, a potential future extension to this could be a \pset command to customise the table style in addition to border printing, since the code is now there to do this. Regards, Roger -- .''`. Roger Leigh : :' : Debian GNU/Linux http://people.debian.org/~rleigh/ `. `' Printing on GNU/Linux? http://gutenprint.sourceforge.net/ `- GPG Public Key: 0x25BFB848 Please GPG sign your mail.
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c index 7505cd4..1740109 100644 --- a/src/bin/psql/print.c +++ b/src/bin/psql/print.c @@ -21,6 +21,9 @@ #endif #include <locale.h> +#ifdef HAVE_LANGINFO_H +#include <langinfo.h> +#endif #include "catalog/pg_type.h" #include "pqsignal.h" @@ -356,38 +359,66 @@ print_unaligned_vertical(const printTableContent *cont, FILE *fout) /* Aligned text */ /********************/ +static const printTextFormat asciiformat = +{ + { + { "-", "+", "+", "+" }, + { "-", "+", "+", "+" }, + { "-", "+", "+", "+" }, + { "", "|", "|", "|" } + } +}; + +static const struct printTextFormat utf8format = +{ + { + /* ─, ┌, ┬, ┐ */ + { "\342\224\200", "\342\224\214", "\342\224\254", "\342\224\220" }, + /* ━, ┝, ┿, ┥ */ + { "\342\224\201", "\342\224\235", "\342\224\277", "\342\224\245" }, + /* ─, └, ┴, ┘ */ + { "\342\224\200", "\342\224\224", "\342\224\264", "\342\224\230" }, + /* N/A, │, │, │ */ + { "", "\342\224\202", "\342\224\202", "\342\224\202" } + }, +}; /* draw "line" */ static void _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths, - unsigned short border, FILE *fout) + unsigned short border, printTextRule pos, + const printTextFormat *format, + FILE *fout) { unsigned int i, j; + const printTextLineFormat *lformat = &format->lrule[pos]; + if (border == 1) - fputc('-', fout); + fputs(lformat->hrule, fout); else if (border == 2) - fputs("+-", fout); + fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule); for (i = 0; i < ncolumns; i++) { for (j = 0; j < widths[i]; j++) - fputc('-', fout); + fputs(lformat->hrule, fout); if (i < ncolumns - 1) { if (border == 0) fputc(' ', fout); else - fputs("-+-", fout); + fprintf(fout, "%s%s%s", lformat->hrule, + lformat->midvrule, lformat->hrule); } } if (border == 2) - fputs("-+", fout); + fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule); else if (border == 1) - fputc('-', fout); + fputs(lformat->hrule, fout); fputc('\n', fout); } @@ -397,7 +428,8 @@ _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths, * Print pretty boxes around cells. */ static void -print_aligned_text(const printTableContent *cont, FILE *fout) +print_aligned_text(const printTableContent *cont, const printTextFormat *format, + FILE *fout) { bool opt_tuples_only = cont->opt->tuples_only; bool opt_numeric_locale = cont->opt->numericLocale; @@ -431,6 +463,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) int *bytes_output; /* Bytes output for column value */ int output_columns = 0; /* Width of interactive console */ bool is_pager = false; + const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA]; if (cancel_pressed) return; @@ -709,7 +742,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) int curr_nl_line; if (opt_border == 2) - _print_horizontal_line(col_count, width_wrap, opt_border, fout); + _print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_TOP, format, fout); for (i = 0; i < col_count; i++) pg_wcsformat((unsigned char *) cont->headers[i], @@ -722,7 +755,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) while (more_col_wrapping) { if (opt_border == 2) - fprintf(fout, "|%c", curr_nl_line ? '+' : ' '); + fprintf(fout, "%s%c", dformat->leftvrule, curr_nl_line ? '+' : ' '); else if (opt_border == 1) fputc(curr_nl_line ? '+' : ' ', fout); @@ -753,19 +786,20 @@ print_aligned_text(const printTableContent *cont, FILE *fout) if (opt_border == 0) fputc(curr_nl_line ? '+' : ' ', fout); else - fprintf(fout, " |%c", curr_nl_line ? '+' : ' '); + fprintf(fout, " %s%c", dformat->midvrule, curr_nl_line ? '+' : ' '); } } curr_nl_line++; if (opt_border == 2) - fputs(" |", fout); + fprintf(fout, " %s", + dformat->rightvrule); else if (opt_border == 1) fputc(' ', fout); fputc('\n', fout); } - _print_horizontal_line(col_count, width_wrap, opt_border, fout); + _print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_MIDDLE, format, fout); } } @@ -811,7 +845,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) /* left border */ if (opt_border == 2) - fputs("| ", fout); + fprintf(fout, "%s ", dformat->leftvrule); else if (opt_border == 1) fputc(' ', fout); @@ -891,15 +925,16 @@ print_aligned_text(const printTableContent *cont, FILE *fout) /* After first newline value */ else if (curr_nl_line[j + 1] != 0) fputs(" : ", fout); + /* Ordinary line */ else - /* Ordinary line */ - fputs(" | ", fout); + fprintf(fout, " %s ", + dformat->midvrule); } } /* end-of-row border */ if (opt_border == 2) - fputs(" |", fout); + fprintf(fout, " %s", dformat->rightvrule); fputc('\n', fout); } while (more_lines); @@ -908,7 +943,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout) if (cont->opt->stop_table) { if (opt_border == 2 && !cancel_pressed) - _print_horizontal_line(col_count, width_wrap, opt_border, fout); + _print_horizontal_line(col_count, width_wrap, opt_border, PRINT_RULE_BOTTOM, format, fout); /* print footers */ if (cont->footers && !opt_tuples_only && !cancel_pressed) @@ -941,9 +976,67 @@ print_aligned_text(const printTableContent *cont, FILE *fout) ClosePager(fout); } +static inline void +print_aligned_vertical_line(const printTableContent *cont, + unsigned long record, + unsigned int hwidth, + unsigned int dwidth, + printTextRule pos, + const printTextFormat *format, + FILE *fout) +{ + unsigned short opt_border = cont->opt->border; + unsigned int i; + int reclen = 0; + const printTextLineFormat *lformat = &format->lrule[pos]; + + if (opt_border == 2) + fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule); + else if (opt_border == 1) + fputs(lformat->hrule, fout); + + if (record) + { + if (opt_border == 0) + reclen = fprintf(fout, "* Record %lu", record); + else + reclen = fprintf(fout, "[ RECORD %lu ]", record); + } + if (opt_border != 2) + reclen++; + if (reclen < 0) + reclen = 0; + for (i = reclen; i < hwidth; i++) + fputs(opt_border > 0 ? lformat->hrule : " ", fout); + reclen -= hwidth; + + if (opt_border > 0) + { + if (reclen-- <= 0) + fputs(lformat->hrule, fout); + if (reclen-- <= 0) + fputs(lformat->midvrule, fout); + if (reclen-- <= 0) + fputs(lformat->hrule, fout); + } + else + { + if (reclen-- <= 0) + fputc(' ', fout); + } + if (reclen < 0) + reclen = 0; + for (i = reclen; i < dwidth; i++) + fputs(opt_border > 0 ? lformat->hrule : " ", fout); + if (opt_border == 2) + fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule); + fputc('\n', fout); +} static void -print_aligned_vertical(const printTableContent *cont, FILE *fout) +print_aligned_vertical(const printTableContent *cont, + const printTextFormat *format, + FILE *fout) { bool opt_tuples_only = cont->opt->tuples_only; bool opt_numeric_locale = cont->opt->numericLocale; @@ -958,9 +1051,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) dheight = 1, hformatsize = 0, dformatsize = 0; - char *divider; struct lineptr *hlineptr, *dlineptr; + const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA]; if (cancel_pressed) return; @@ -1026,21 +1119,6 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) dlineptr->ptr = pg_local_malloc(dformatsize); hlineptr->ptr = pg_local_malloc(hformatsize); - /* make horizontal border */ - divider = pg_local_malloc(hwidth + dwidth + 10); - divider[0] = '\0'; - if (opt_border == 2) - strcat(divider, "+-"); - for (i = 0; i < hwidth; i++) - strcat(divider, opt_border > 0 ? "-" : " "); - if (opt_border > 0) - strcat(divider, "-+-"); - else - strcat(divider, " "); - for (i = 0; i < dwidth; i++) - strcat(divider, opt_border > 0 ? "-" : " "); - if (opt_border == 2) - strcat(divider, "-+"); if (cont->opt->start_table) { @@ -1052,40 +1130,25 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) /* print records */ for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) { - int line_count, - dcomplete, - hcomplete; + int line_count, + dcomplete, + hcomplete; + printTextRule pos = PRINT_RULE_MIDDLE; + if (i == 0) + pos = PRINT_RULE_TOP; + else if (!(*(ptr+1))) + pos = PRINT_RULE_BOTTOM; + + if (cancel_pressed) + break; if (i % cont->ncolumns == 0) { - if (cancel_pressed) - break; - if (!opt_tuples_only) - { - char record_str[64]; - size_t record_str_len; - - if (opt_border == 0) - snprintf(record_str, 64, "* Record %lu", record++); - else - snprintf(record_str, 64, "[ RECORD %lu ]", record++); - record_str_len = strlen(record_str); - - if (record_str_len + opt_border > strlen(divider)) - fprintf(fout, "%.*s%s\n", opt_border, divider, record_str); - else - { - char *div_copy = pg_strdup(divider); - - strncpy(div_copy + opt_border, record_str, record_str_len); - fprintf(fout, "%s\n", div_copy); - free(div_copy); - } - } + if (!opt_tuples_only) + print_aligned_vertical_line(cont, record++, hwidth, dwidth, pos, format, fout); else if (i != 0 || !cont->opt->start_table || opt_border == 2) - fprintf(fout, "%s\n", divider); + print_aligned_vertical_line(cont, 0, hwidth, dwidth, pos, format, fout); } - /* Format the header */ pg_wcsformat((unsigned char *) cont->headers[i % cont->ncolumns], strlen(cont->headers[i % cont->ncolumns]), @@ -1099,7 +1162,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) while (!dcomplete || !hcomplete) { if (opt_border == 2) - fputs("| ", fout); + fprintf(fout, "%s ", dformat->leftvrule); if (!hcomplete) { fprintf(fout, "%-s%*s", hlineptr[line_count].ptr, @@ -1112,9 +1175,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) fprintf(fout, "%*s", hwidth, ""); if (opt_border > 0) - fprintf(fout, " %c ", (line_count == 0) ? '|' : ':'); + fprintf(fout, " %s ", (line_count == 0) ? dformat->midvrule : ":"); else - fputs(" ", fout); + fputc(' ', fout); if (!dcomplete) { @@ -1125,8 +1188,8 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) if (opt_border < 2) fprintf(fout, "%s\n", my_cell); else - fprintf(fout, "%-s%*s |\n", my_cell, - (int) (dwidth - strlen(my_cell)), ""); + fprintf(fout, "%-s%*s %s\n", my_cell, + (int) (dwidth - strlen(my_cell)), "", dformat->rightvrule); free(my_cell); } else @@ -1134,8 +1197,8 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) 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, ""); + fprintf(fout, "%-s%*s %s\n", dlineptr[line_count].ptr, + dwidth - dlineptr[line_count].width, "", dformat->rightvrule); } if (!dlineptr[line_count + 1].ptr) @@ -1146,7 +1209,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) if (opt_border < 2) fputc('\n', fout); else - fprintf(fout, "%*s |\n", dwidth, ""); + fprintf(fout, "%*s %s\n", dwidth, "", dformat->rightvrule); } line_count++; } @@ -1155,7 +1218,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) if (cont->opt->stop_table) { if (opt_border == 2 && !cancel_pressed) - fprintf(fout, "%s\n", divider); + print_aligned_vertical_line(cont, 0, hwidth, dwidth, PRINT_RULE_BOTTOM, format, fout); /* print footers */ if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed) @@ -1171,7 +1234,6 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout) fputc('\n', fout); } - free(divider); free(hlineptr->ptr); free(dlineptr->ptr); free(hlineptr); @@ -2208,7 +2270,15 @@ IsPagerNeeded(const printTableContent *cont, const int extra_lines, FILE **fout, void printTable(const printTableContent *cont, FILE *fout, FILE *flog) { - bool is_pager = false; + bool is_pager = false; + const printTextFormat *text_format = &asciiformat; + +#if (defined(HAVE_LANGINFO_H) && defined(CODESET)) + if (pg_strcasecmp(nl_langinfo(CODESET), "UTF-8") == 0 || + pg_strcasecmp(nl_langinfo(CODESET), "utf8") == 0 || + pg_strcasecmp(nl_langinfo(CODESET), "CP65001") == 0) + text_format = &utf8format; +#endif if (cancel_pressed) return; @@ -2225,7 +2295,7 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog) /* print the stuff */ if (flog) - print_aligned_text(cont, flog); + print_aligned_text(cont, text_format, flog); switch (cont->opt->format) { @@ -2238,9 +2308,9 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog) case PRINT_ALIGNED: case PRINT_WRAPPED: if (cont->opt->expanded) - print_aligned_vertical(cont, fout); + print_aligned_vertical(cont, text_format, fout); else - print_aligned_text(cont, fout); + print_aligned_text(cont, text_format, fout); break; case PRINT_HTML: if (cont->opt->expanded) diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h index 55122d7..7b53fae 100644 --- a/src/bin/psql/print.h +++ b/src/bin/psql/print.h @@ -95,6 +95,27 @@ typedef struct printQueryOpt * gettext on col i */ } printQueryOpt; +typedef struct printTextLineFormat +{ + const char *hrule; + const char *leftvrule; + const char *midvrule; + const char *rightvrule; +} printTextLineFormat; + +typedef struct printTextFormat +{ + printTextLineFormat lrule[4]; +} printTextFormat; + +typedef enum printTextRule +{ + PRINT_RULE_TOP, + PRINT_RULE_MIDDLE, + PRINT_RULE_BOTTOM, + PRINT_RULE_DATA +} printTextRule; + extern FILE *PageOutput(int lines, unsigned short int pager); extern void ClosePager(FILE *pagerpipe);
signature.asc
Description: Digital signature