📄 print.c
字号:
/* * psql - the PostgreSQL interactive terminal * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.79 2005/10/27 13:34:47 momjian Exp $ */#include "postgres_fe.h"#include "common.h"#include "print.h"#include <math.h>#include <signal.h>#ifndef WIN32_CLIENT_ONLY#include <unistd.h>#endif#ifndef WIN32#include <sys/ioctl.h> /* for ioctl() */#endif#ifdef HAVE_TERMIOS_H#include <termios.h>#endif#include <locale.h>#include "pqsignal.h"#include "libpq-fe.h"#include "mbprint.h"static char *decimal_point;static char *grouping;static char *thousands_sep;static void *pg_local_malloc(size_t size){ void *tmp; tmp = malloc(size); if (!tmp) { fprintf(stderr, _("out of memory\n")); exit(EXIT_FAILURE); } return tmp;}static intinteger_digits(const char *my_str){ int frac_len; if (my_str[0] == '-') my_str++; frac_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0; return strlen(my_str) - frac_len;}/* Return additional length required for locale-aware numeric output */static intadditional_numeric_locale_len(const char *my_str){ int int_len = integer_digits(my_str), len = 0; int groupdigits = atoi(grouping); if (int_len > 0) /* Don't count a leading separator */ len = (int_len / groupdigits - (int_len % groupdigits == 0)) * strlen(thousands_sep); if (strchr(my_str, '.') != NULL) len += strlen(decimal_point) - strlen("."); return len;}static intstrlen_with_numeric_locale(const char *my_str){ return strlen(my_str) + additional_numeric_locale_len(my_str);}static char *format_numeric_locale(const char *my_str){ int i, j, int_len = integer_digits(my_str), leading_digits; int groupdigits = atoi(grouping); int new_str_start = 0; char *new_str = new_str = pg_local_malloc( strlen_with_numeric_locale(my_str) + 1); leading_digits = (int_len % groupdigits != 0) ? int_len % groupdigits : groupdigits; if (my_str[0] == '-') /* skip over sign, affects grouping * calculations */ { new_str[0] = my_str[0]; my_str++; new_str_start = 1; } for (i = 0, j = new_str_start;; i++, j++) { /* Hit decimal point? */ if (my_str[i] == '.') { strcpy(&new_str[j], decimal_point); j += strlen(decimal_point); /* add fractional part */ strcpy(&new_str[j], &my_str[i] + 1); break; } /* End of string? */ if (my_str[i] == '\0') { new_str[j] = '\0'; break; } /* Add separator? */ if (i != 0 && (i - leading_digits) % groupdigits == 0) { strcpy(&new_str[j], thousands_sep); j += strlen(thousands_sep); } new_str[j] = my_str[i]; } return new_str;}/*************************//* Unaligned text *//*************************/static voidprint_unaligned_text(const char *title, const char *const * headers, const char *const * cells, const char *const * footers, const char *opt_align, const char *opt_fieldsep, const char *opt_recordsep, bool opt_tuples_only, bool opt_numeric_locale, FILE *fout){ unsigned int col_count = 0; unsigned int i; const char *const * ptr; bool need_recordsep = false; if (!opt_fieldsep) opt_fieldsep = ""; if (!opt_recordsep) opt_recordsep = ""; /* print title */ if (!opt_tuples_only && title) fprintf(fout, "%s%s", title, opt_recordsep); /* print headers and count columns */ for (ptr = headers; *ptr; ptr++) { col_count++; if (!opt_tuples_only) { if (col_count > 1) fputs(opt_fieldsep, fout); fputs(*ptr, fout); } } if (!opt_tuples_only) need_recordsep = true; /* print cells */ i = 0; for (ptr = cells; *ptr; ptr++) { if (need_recordsep) { fputs(opt_recordsep, fout); need_recordsep = false; } if (opt_align[i % col_count] == 'r' && opt_numeric_locale) { char *my_cell = format_numeric_locale(*ptr); fputs(my_cell, fout); free(my_cell); } else fputs(*ptr, fout); if ((i + 1) % col_count) fputs(opt_fieldsep, fout); else need_recordsep = true; i++; } /* print footers */ if (!opt_tuples_only && footers) for (ptr = footers; *ptr; ptr++) { if (need_recordsep) { fputs(opt_recordsep, fout); need_recordsep = false; } fputs(*ptr, fout); need_recordsep = true; } /* the last record needs to be concluded with a newline */ if (need_recordsep) fputc('\n', fout);}static voidprint_unaligned_vertical(const char *title, const char *const * headers, const char *const * cells, const char *const * footers, const char *opt_align, const char *opt_fieldsep, const char *opt_recordsep, bool opt_tuples_only, bool opt_numeric_locale, FILE *fout){ unsigned int col_count = 0; unsigned int i; const char *const * ptr; if (!opt_fieldsep) opt_fieldsep = ""; if (!opt_recordsep) opt_recordsep = ""; /* print title */ if (!opt_tuples_only && title) fputs(title, fout); /* count columns */ for (ptr = headers; *ptr; ptr++) col_count++; /* print records */ for (i = 0, ptr = cells; *ptr; i++, ptr++) { if (i != 0 || (!opt_tuples_only && title)) { fputs(opt_recordsep, fout); if (i % col_count == 0) fputs(opt_recordsep, fout); /* another one */ } fputs(headers[i % col_count], fout); fputs(opt_fieldsep, fout); if (opt_align[i % col_count] == 'r' && opt_numeric_locale) { char *my_cell = format_numeric_locale(*ptr); fputs(my_cell, fout); free(my_cell); } else fputs(*ptr, fout); } /* print footers */ if (!opt_tuples_only && footers && *footers) { fputs(opt_recordsep, fout); for (ptr = footers; *ptr; ptr++) { fputs(opt_recordsep, fout); fputs(*ptr, fout); } } fputc('\n', fout);}/********************//* Aligned text *//********************//* draw "line" */static void_print_horizontal_line(const unsigned int col_count, const unsigned int *widths, unsigned short border, FILE *fout){ unsigned int i, j; if (border == 1) fputc('-', fout); else if (border == 2) fputs("+-", fout); for (i = 0; i < col_count; i++) { for (j = 0; j < widths[i]; j++) fputc('-', fout); if (i < col_count - 1) { if (border == 0) fputc(' ', fout); else fputs("-+-", fout); } } if (border == 2) fputs("-+", fout); else if (border == 1) fputc('-', fout); fputc('\n', fout);}static voidprint_aligned_text(const char *title, const char *const * headers, const char *const * cells, const char *const * footers, const char *opt_align, bool opt_tuples_only, bool opt_numeric_locale, unsigned short int opt_border, int encoding, FILE *fout){ 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++) col_count++; 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) 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]; /* print title */ if (title && !opt_tuples_only) { tmp = pg_wcswidth(title, strlen(title), encoding); if (tmp >= total_w) fprintf(fout, "%s\n", title); else fprintf(fout, "%-*s%s\n", (total_w - tmp) / 2, "", title); } /* 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); } } if (opt_border == 2) _print_horizontal_line(col_count, widths, opt_border, fout); /* print footers */ if (footers && !opt_tuples_only) for (ptr = footers; *ptr; ptr++) fprintf(fout, "%s\n", *ptr);#ifndef __MINGW32__ /* * for some reason MinGW outputs an extra newline, so this supresses it */ fputc('\n', fout);#endif /* clean up */ free(cell_w); free(head_w); free(widths);}static voidprint_aligned_vertical(const char *title, const char *const * headers, const char *const * cells, const char *const * footers, const char *opt_align, bool opt_tuples_only, bool opt_numeric_locale, unsigned short int opt_border, int encoding, FILE *fout){ unsigned int col_count = 0; unsigned int record = 1; const char *const * ptr; 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")); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -