PostgreSQL Source Code git master
print.c File Reference
#include "postgres_fe.h"
#include <limits.h>
#include <math.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "catalog/pg_type_d.h"
#include "fe_utils/mbprint.h"
#include "fe_utils/print.h"
Include dependency graph for print.c:

Go to the source code of this file.

Data Structures

struct  unicodeStyleRowFormat
 
struct  unicodeStyleColumnFormat
 
struct  unicodeStyleBorderFormat
 
struct  unicodeStyleFormat
 

Macros

#define LONGTABLE_WHITESPACE   " \t\n"
 

Typedefs

typedef struct unicodeStyleRowFormat unicodeStyleRowFormat
 
typedef struct unicodeStyleColumnFormat unicodeStyleColumnFormat
 
typedef struct unicodeStyleBorderFormat unicodeStyleBorderFormat
 
typedef struct unicodeStyleFormat unicodeStyleFormat
 

Functions

static int strlen_max_width (unsigned char *str, int *target_width, int encoding)
 
static FILE * PageOutputInternal (int lines, const printTableOpt *topt, const printTableContent *cont, const unsigned int *width_wrap, bool vertical)
 
static void IsPagerNeeded (const printTableContent *cont, const unsigned int *width_wrap, bool vertical, FILE **fout, bool *is_pager)
 
static void print_aligned_vertical (const printTableContent *cont, FILE *fout, bool is_pager)
 
static int integer_digits (const char *my_str)
 
static int additional_numeric_locale_len (const char *my_str)
 
static char * format_numeric_locale (const char *my_str)
 
static void print_separator (struct separator sep, FILE *fout)
 
static printTableFooterfooters_with_default (const printTableContent *cont)
 
static void print_unaligned_text (const printTableContent *cont, FILE *fout)
 
static void print_unaligned_vertical (const printTableContent *cont, FILE *fout)
 
static void _print_horizontal_line (const unsigned int ncolumns, const unsigned int *widths, unsigned short border, printTextRule pos, const printTextFormat *format, FILE *fout)
 
static void print_aligned_text (const printTableContent *cont, FILE *fout, bool is_pager)
 
static void print_aligned_vertical_line (const printTableOpt *topt, unsigned long record, unsigned int hwidth, unsigned int dwidth, int output_columns, printTextRule pos, FILE *fout)
 
static void csv_escaped_print (const char *str, FILE *fout)
 
static void csv_print_field (const char *str, FILE *fout, char sep)
 
static void print_csv_text (const printTableContent *cont, FILE *fout)
 
static void print_csv_vertical (const printTableContent *cont, FILE *fout)
 
void html_escaped_print (const char *in, FILE *fout)
 
static void print_html_text (const printTableContent *cont, FILE *fout)
 
static void print_html_vertical (const printTableContent *cont, FILE *fout)
 
static void asciidoc_escaped_print (const char *in, FILE *fout)
 
static void print_asciidoc_text (const printTableContent *cont, FILE *fout)
 
static void print_asciidoc_vertical (const printTableContent *cont, FILE *fout)
 
static void latex_escaped_print (const char *in, FILE *fout)
 
static void print_latex_text (const printTableContent *cont, FILE *fout)
 
static void print_latex_longtable_text (const printTableContent *cont, FILE *fout)
 
static void print_latex_vertical (const printTableContent *cont, FILE *fout)
 
static void troff_ms_escaped_print (const char *in, FILE *fout)
 
static void print_troff_ms_text (const printTableContent *cont, FILE *fout)
 
static void print_troff_ms_vertical (const printTableContent *cont, FILE *fout)
 
void disable_sigpipe_trap (void)
 
void restore_sigpipe_trap (void)
 
void set_sigpipe_trap_state (bool ignore)
 
FILE * PageOutput (int lines, const printTableOpt *topt)
 
void ClosePager (FILE *pagerpipe)
 
void printTableInit (printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
 
void printTableAddHeader (printTableContent *const content, char *header, const bool translate, const char align)
 
void printTableAddCell (printTableContent *const content, char *cell, const bool translate, const bool mustfree)
 
void printTableAddFooter (printTableContent *const content, const char *footer)
 
void printTableSetFooter (printTableContent *const content, const char *footer)
 
void printTableCleanup (printTableContent *const content)
 
void printTable (const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
 
void printQuery (const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
 
char column_type_alignment (Oid ftype)
 
void setDecimalLocale (void)
 
const printTextFormatget_line_style (const printTableOpt *opt)
 
void refresh_utf8format (const printTableOpt *opt)
 

Variables

volatile sig_atomic_t cancel_pressed = false
 
static bool always_ignore_sigpipe = false
 
static char * decimal_point
 
static int groupdigits
 
static char * thousands_sep
 
static char default_footer [100]
 
static printTableFooter default_footer_cell = {default_footer, NULL}
 
const printTextFormat pg_asciiformat
 
const printTextFormat pg_asciiformat_old
 
printTextFormat pg_utf8format
 
static const unicodeStyleFormat unicode_style
 

Macro Definition Documentation

◆ LONGTABLE_WHITESPACE

#define LONGTABLE_WHITESPACE   " \t\n"

Typedef Documentation

◆ unicodeStyleBorderFormat

◆ unicodeStyleColumnFormat

◆ unicodeStyleFormat

◆ unicodeStyleRowFormat

Function Documentation

◆ _print_horizontal_line()

static void _print_horizontal_line ( const unsigned int  ncolumns,
const unsigned int *  widths,
unsigned short  border,
printTextRule  pos,
const printTextFormat format,
FILE *  fout 
)
static

Definition at line 609 of file print.c.

613{
614 const printTextLineFormat *lformat = &format->lrule[pos];
615 unsigned int i,
616 j;
617
618 if (border == 1)
619 fputs(lformat->hrule, fout);
620 else if (border == 2)
621 fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
622
623 for (i = 0; i < ncolumns; i++)
624 {
625 for (j = 0; j < widths[i]; j++)
626 fputs(lformat->hrule, fout);
627
628 if (i < ncolumns - 1)
629 {
630 if (border == 0)
631 fputc(' ', fout);
632 else
633 fprintf(fout, "%s%s%s", lformat->hrule,
634 lformat->midvrule, lformat->hrule);
635 }
636 }
637
638 if (border == 2)
639 fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
640 else if (border == 1)
641 fputs(lformat->hrule, fout);
642
643 fputc('\n', fout);
644}
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
int j
Definition: isn.c:78
int i
Definition: isn.c:77
static char format
const char * hrule
Definition: print.h:46
const char * rightvrule
Definition: print.h:49
const char * midvrule
Definition: print.h:48
const char * leftvrule
Definition: print.h:47

References format, fprintf, printTextLineFormat::hrule, i, j, printTextLineFormat::leftvrule, printTextLineFormat::midvrule, and printTextLineFormat::rightvrule.

Referenced by print_aligned_text().

◆ additional_numeric_locale_len()

static int additional_numeric_locale_len ( const char *  my_str)
static

Definition at line 305 of file print.c.

306{
307 int int_len = integer_digits(my_str),
308 len = 0;
309
310 /* Account for added thousands_sep instances */
311 if (int_len > groupdigits)
312 len += ((int_len - 1) / groupdigits) * strlen(thousands_sep);
313
314 /* Account for possible additional length of decimal_point */
315 if (strchr(my_str, '.') != NULL)
316 len += strlen(decimal_point) - 1;
317
318 return len;
319}
static char * thousands_sep
Definition: print.c:55
static char * decimal_point
Definition: print.c:53
static int integer_digits(const char *my_str)
Definition: print.c:294
static int groupdigits
Definition: print.c:54
const void size_t len

References decimal_point, groupdigits, integer_digits(), len, and thousands_sep.

Referenced by format_numeric_locale().

◆ asciidoc_escaped_print()

static void asciidoc_escaped_print ( const char *  in,
FILE *  fout 
)
static

Definition at line 2153 of file print.c.

2154{
2155 const char *p;
2156
2157 for (p = in; *p; p++)
2158 {
2159 switch (*p)
2160 {
2161 case '|':
2162 fputs("\\|", fout);
2163 break;
2164 default:
2165 fputc(*p, fout);
2166 }
2167 }
2168}

Referenced by print_asciidoc_text(), and print_asciidoc_vertical().

◆ ClosePager()

void ClosePager ( FILE *  pagerpipe)

Definition at line 3160 of file print.c.

3161{
3162 if (pagerpipe && pagerpipe != stdout)
3163 {
3164 /*
3165 * If printing was canceled midstream, warn about it.
3166 *
3167 * Some pagers like less use Ctrl-C as part of their command set. Even
3168 * so, we abort our processing and warn the user what we did. If the
3169 * pager quit as a result of the SIGINT, this message won't go
3170 * anywhere ...
3171 */
3172 if (cancel_pressed)
3173 fprintf(pagerpipe, _("Interrupted\n"));
3174
3175 pclose(pagerpipe);
3177 }
3178}
#define _(x)
Definition: elog.c:91
void restore_sigpipe_trap(void)
Definition: print.c:3047
volatile sig_atomic_t cancel_pressed
Definition: print.c:48

References _, cancel_pressed, fprintf, restore_sigpipe_trap(), and generate_unaccent_rules::stdout.

Referenced by exec_command_sf_sv(), ExecQueryAndProcessResults(), helpSQL(), helpVariables(), print_aligned_text(), print_aligned_vertical(), printHistory(), printTable(), slashUsage(), and usage().

◆ column_type_alignment()

char column_type_alignment ( Oid  ftype)

Definition at line 3811 of file print.c.

3812{
3813 char align;
3814
3815 switch (ftype)
3816 {
3817 case INT2OID:
3818 case INT4OID:
3819 case INT8OID:
3820 case FLOAT4OID:
3821 case FLOAT8OID:
3822 case NUMERICOID:
3823 case OIDOID:
3824 case XIDOID:
3825 case XID8OID:
3826 case CIDOID:
3827 case MONEYOID:
3828 align = 'r';
3829 break;
3830 default:
3831 align = 'l';
3832 break;
3833 }
3834 return align;
3835}

Referenced by printCrosstab(), and printQuery().

◆ csv_escaped_print()

static void csv_escaped_print ( const char *  str,
FILE *  fout 
)
static

Definition at line 1825 of file print.c.

1826{
1827 const char *p;
1828
1829 fputc('"', fout);
1830 for (p = str; *p; p++)
1831 {
1832 if (*p == '"')
1833 fputc('"', fout); /* double quotes are doubled */
1834 fputc(*p, fout);
1835 }
1836 fputc('"', fout);
1837}
const char * str

References str.

Referenced by csv_print_field().

◆ csv_print_field()

static void csv_print_field ( const char *  str,
FILE *  fout,
char  sep 
)
static

Definition at line 1840 of file print.c.

1841{
1842 /*----------------
1843 * Enclose and escape field contents when one of these conditions is met:
1844 * - the field separator is found in the contents.
1845 * - the field contains a CR or LF.
1846 * - the field contains a double quote.
1847 * - the field is exactly "\.".
1848 * - the field separator is either "\" or ".".
1849 * The last two cases prevent producing a line that the server's COPY
1850 * command would interpret as an end-of-data marker. We only really
1851 * need to ensure that the complete line isn't exactly "\.", but for
1852 * simplicity we apply stronger restrictions here.
1853 *----------------
1854 */
1855 if (strchr(str, sep) != NULL ||
1856 strcspn(str, "\r\n\"") != strlen(str) ||
1857 strcmp(str, "\\.") == 0 ||
1858 sep == '\\' || sep == '.')
1859 csv_escaped_print(str, fout);
1860 else
1861 fputs(str, fout);
1862}
static void csv_escaped_print(const char *str, FILE *fout)
Definition: print.c:1825

References csv_escaped_print(), and str.

Referenced by print_csv_text(), and print_csv_vertical().

◆ disable_sigpipe_trap()

void disable_sigpipe_trap ( void  )

Definition at line 3024 of file print.c.

3025{
3026#ifndef WIN32
3027 pqsignal(SIGPIPE, SIG_IGN);
3028#endif
3029}
#define pqsignal
Definition: port.h:552
#define SIGPIPE
Definition: win32_port.h:163

References pqsignal, and SIGPIPE.

Referenced by do_copy(), do_watch(), exec_command_write(), PageOutputInternal(), and SetupGOutput().

◆ footers_with_default()

static printTableFooter * footers_with_default ( const printTableContent cont)
static

Definition at line 414 of file print.c.

415{
416 if (cont->footers == NULL && cont->opt->default_footer)
417 {
418 unsigned long total_records;
419
420 total_records = cont->opt->prior_records + cont->nrows;
422 ngettext("(%lu row)", "(%lu rows)", total_records),
423 total_records);
424
425 return &default_footer_cell;
426 }
427 else
428 return cont->footers;
429}
#define ngettext(s, p, n)
Definition: c.h:1169
static char default_footer[100]
Definition: print.c:57
static printTableFooter default_footer_cell
Definition: print.c:58
#define snprintf
Definition: port.h:260
const printTableOpt * opt
Definition: print.h:165
printTableFooter * footers
Definition: print.h:176
unsigned long prior_records
Definition: print.h:130
bool default_footer
Definition: print.h:129

References default_footer, printTableOpt::default_footer, default_footer_cell, printTableContent::footers, ngettext, printTableContent::nrows, printTableContent::opt, printTableOpt::prior_records, and snprintf.

Referenced by print_aligned_text(), print_aligned_vertical(), print_asciidoc_text(), print_html_text(), print_latex_text(), print_troff_ms_text(), and print_unaligned_text().

◆ format_numeric_locale()

static char * format_numeric_locale ( const char *  my_str)
static

Definition at line 330 of file print.c.

331{
332 char *new_str;
333 int new_len,
334 int_len,
335 leading_digits,
336 i,
337 new_str_pos;
338
339 /*
340 * If the string doesn't look like a number, return it unchanged. This
341 * check is essential to avoid mangling already-localized "money" values.
342 */
343 if (strspn(my_str, "0123456789+-.eE") != strlen(my_str))
344 return pg_strdup(my_str);
345
346 new_len = strlen(my_str) + additional_numeric_locale_len(my_str);
347 new_str = pg_malloc(new_len + 1);
348 new_str_pos = 0;
349 int_len = integer_digits(my_str);
350
351 /* number of digits in first thousands group */
352 leading_digits = int_len % groupdigits;
353 if (leading_digits == 0)
354 leading_digits = groupdigits;
355
356 /* process sign */
357 if (my_str[0] == '-' || my_str[0] == '+')
358 {
359 new_str[new_str_pos++] = my_str[0];
360 my_str++;
361 }
362
363 /* process integer part of number */
364 for (i = 0; i < int_len; i++)
365 {
366 /* Time to insert separator? */
367 if (i > 0 && --leading_digits == 0)
368 {
369 strcpy(&new_str[new_str_pos], thousands_sep);
370 new_str_pos += strlen(thousands_sep);
371 leading_digits = groupdigits;
372 }
373 new_str[new_str_pos++] = my_str[i];
374 }
375
376 /* handle decimal point if any */
377 if (my_str[i] == '.')
378 {
379 strcpy(&new_str[new_str_pos], decimal_point);
380 new_str_pos += strlen(decimal_point);
381 i++;
382 }
383
384 /* copy the rest (fractional digits and/or exponent, and \0 terminator) */
385 strcpy(&new_str[new_str_pos], &my_str[i]);
386
387 /* assert we didn't underestimate new_len (an overestimate is OK) */
388 Assert(strlen(new_str) <= new_len);
389
390 return new_str;
391}
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static int additional_numeric_locale_len(const char *my_str)
Definition: print.c:305
Assert(PointerIsAligned(start, uint64))

References additional_numeric_locale_len(), Assert(), decimal_point, groupdigits, i, integer_digits(), pg_malloc(), pg_strdup(), and thousands_sep.

Referenced by printQuery().

◆ get_line_style()

const printTextFormat * get_line_style ( const printTableOpt opt)

Definition at line 3874 of file print.c.

3875{
3876 /*
3877 * Note: this function mainly exists to preserve the convention that a
3878 * printTableOpt struct can be initialized to zeroes to get default
3879 * behavior.
3880 */
3881 if (opt->line_style != NULL)
3882 return opt->line_style;
3883 else
3884 return &pg_asciiformat;
3885}
const printTextFormat pg_asciiformat
Definition: print.c:61
const printTextFormat * line_style
Definition: print.h:131

References printTableOpt::line_style, and pg_asciiformat.

Referenced by print_aligned_text(), print_aligned_vertical(), print_aligned_vertical_line(), printPsetInfo(), and pset_value_string().

◆ html_escaped_print()

void html_escaped_print ( const char *  in,
FILE *  fout 
)

Definition at line 1937 of file print.c.

1938{
1939 const char *p;
1940 bool leading_space = true;
1941
1942 for (p = in; *p; p++)
1943 {
1944 switch (*p)
1945 {
1946 case '&':
1947 fputs("&amp;", fout);
1948 break;
1949 case '<':
1950 fputs("&lt;", fout);
1951 break;
1952 case '>':
1953 fputs("&gt;", fout);
1954 break;
1955 case '\n':
1956 fputs("<br />\n", fout);
1957 break;
1958 case '"':
1959 fputs("&quot;", fout);
1960 break;
1961 case ' ':
1962 /* protect leading space, for EXPLAIN output */
1963 if (leading_space)
1964 fputs("&nbsp;", fout);
1965 else
1966 fputs(" ", fout);
1967 break;
1968 default:
1969 fputc(*p, fout);
1970 }
1971 if (*p != ' ')
1972 leading_space = false;
1973 }
1974}

Referenced by print_html_text(), print_html_vertical(), and PrintQueryStatus().

◆ integer_digits()

static int integer_digits ( const char *  my_str)
static

Definition at line 294 of file print.c.

295{
296 /* ignoring any sign ... */
297 if (my_str[0] == '-' || my_str[0] == '+')
298 my_str++;
299 /* ... count initial integral digits */
300 return strspn(my_str, "0123456789");
301}

Referenced by additional_numeric_locale_len(), and format_numeric_locale().

◆ IsPagerNeeded()

static void IsPagerNeeded ( const printTableContent cont,
const unsigned int *  width_wrap,
bool  vertical,
FILE **  fout,
bool *  is_pager 
)
static

Definition at line 3430 of file print.c.

3433{
3434 if (*fout == stdout)
3435 {
3436 *fout = PageOutputInternal(0, cont->opt, cont, width_wrap, vertical);
3437 *is_pager = (*fout != stdout);
3438 }
3439 else
3440 *is_pager = false;
3441}
static FILE * PageOutputInternal(int lines, const printTableOpt *topt, const printTableContent *cont, const unsigned int *width_wrap, bool vertical)
Definition: print.c:3090

References printTableContent::opt, PageOutputInternal(), and generate_unaccent_rules::stdout.

Referenced by print_aligned_text(), print_aligned_vertical(), and printTable().

◆ latex_escaped_print()

static void latex_escaped_print ( const char *  in,
FILE *  fout 
)
static

Definition at line 2377 of file print.c.

2378{
2379 const char *p;
2380
2381 for (p = in; *p; p++)
2382 switch (*p)
2383 {
2384 /*
2385 * We convert ASCII characters per the recommendations in
2386 * Scott Pakin's "The Comprehensive LATEX Symbol List",
2387 * available from CTAN. For non-ASCII, you're on your own.
2388 */
2389 case '#':
2390 fputs("\\#", fout);
2391 break;
2392 case '$':
2393 fputs("\\$", fout);
2394 break;
2395 case '%':
2396 fputs("\\%", fout);
2397 break;
2398 case '&':
2399 fputs("\\&", fout);
2400 break;
2401 case '<':
2402 fputs("\\textless{}", fout);
2403 break;
2404 case '>':
2405 fputs("\\textgreater{}", fout);
2406 break;
2407 case '\\':
2408 fputs("\\textbackslash{}", fout);
2409 break;
2410 case '^':
2411 fputs("\\^{}", fout);
2412 break;
2413 case '_':
2414 fputs("\\_", fout);
2415 break;
2416 case '{':
2417 fputs("\\{", fout);
2418 break;
2419 case '|':
2420 fputs("\\textbar{}", fout);
2421 break;
2422 case '}':
2423 fputs("\\}", fout);
2424 break;
2425 case '~':
2426 fputs("\\~{}", fout);
2427 break;
2428 case '\n':
2429 /* This is not right, but doing it right seems too hard */
2430 fputs("\\\\", fout);
2431 break;
2432 default:
2433 fputc(*p, fout);
2434 }
2435}

Referenced by print_latex_longtable_text(), print_latex_text(), and print_latex_vertical().

◆ PageOutput()

FILE * PageOutput ( int  lines,
const printTableOpt topt 
)

Definition at line 3078 of file print.c.

3079{
3080 return PageOutputInternal(lines, topt, NULL, NULL, false);
3081}

References PageOutputInternal().

Referenced by exec_command_sf_sv(), ExecQueryAndProcessResults(), helpSQL(), helpVariables(), print_aligned_text(), printHistory(), slashUsage(), and usage().

◆ PageOutputInternal()

static FILE * PageOutputInternal ( int  lines,
const printTableOpt topt,
const printTableContent cont,
const unsigned int *  width_wrap,
bool  vertical 
)
static

Definition at line 3090 of file print.c.

3094{
3095 /* check whether we need / can / are supposed to use pager */
3096 if (topt && topt->pager && isatty(fileno(stdin)) && isatty(fileno(stdout)))
3097 {
3098 /* without TIOCGWINSZ, pager == 1 acts the same as pager > 1 */
3099#ifdef TIOCGWINSZ
3100 unsigned short int pager = topt->pager;
3101 int min_lines = topt->pager_min_lines;
3102
3103 if (pager == 1)
3104 {
3105 int result;
3106 struct winsize screen_size;
3107
3108 result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
3109 if (result < 0)
3110 pager = 2; /* force use of pager */
3111 else
3112 {
3113 int threshold = Max(screen_size.ws_row, min_lines);
3114
3115 if (cont) /* caller wants us to calculate lines */
3116 lines = count_table_lines(cont, width_wrap, vertical,
3117 threshold);
3118 /* >= accounts for a one-line prompt */
3119 if (lines >= threshold)
3120 pager = 2;
3121 }
3122 }
3123
3124 if (pager > 1)
3125#endif
3126 {
3127 const char *pagerprog;
3128 FILE *pagerpipe;
3129
3130 pagerprog = getenv("PSQL_PAGER");
3131 if (!pagerprog)
3132 pagerprog = getenv("PAGER");
3133 if (!pagerprog)
3134 pagerprog = DEFAULT_PAGER;
3135 else
3136 {
3137 /* if PAGER is empty or all-white-space, don't use pager */
3138 if (strspn(pagerprog, " \t\r\n") == strlen(pagerprog))
3139 return stdout;
3140 }
3141 fflush(NULL);
3143 pagerpipe = popen(pagerprog, "w");
3144 if (pagerpipe)
3145 return pagerpipe;
3146 /* if popen fails, silently proceed without pager */
3148 }
3149 }
3150
3151 return stdout;
3152}
#define Max(x, y)
Definition: c.h:1000
void disable_sigpipe_trap(void)
Definition: print.c:3024
#define DEFAULT_PAGER
Definition: print.h:23
int pager_min_lines
Definition: print.h:124
unsigned short int pager
Definition: print.h:122

References DEFAULT_PAGER, disable_sigpipe_trap(), Max, printTableOpt::pager, printTableOpt::pager_min_lines, restore_sigpipe_trap(), and generate_unaccent_rules::stdout.

Referenced by IsPagerNeeded(), and PageOutput().

◆ print_aligned_text()

static void print_aligned_text ( const printTableContent cont,
FILE *  fout,
bool  is_pager 
)
static

Definition at line 651 of file print.c.

652{
653 bool opt_tuples_only = cont->opt->tuples_only;
654 int encoding = cont->opt->encoding;
655 unsigned short opt_border = cont->opt->border;
657 const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA];
658
659 unsigned int col_count = 0,
660 cell_count = 0;
661
662 unsigned int i,
663 j;
664
665 unsigned int *width_header,
666 *max_width,
667 *width_wrap,
668 *width_average;
669 unsigned int *max_nl_lines, /* value split by newlines */
670 *curr_nl_line,
671 *max_bytes;
672 unsigned char **format_buf;
673 unsigned int width_total;
674 unsigned int total_header_width;
675
676 const char *const *ptr;
677
678 struct lineptr **col_lineptrs; /* pointers to line pointer per column */
679
680 bool *header_done; /* Have all header lines been output? */
681 int *bytes_output; /* Bytes output for column value */
682 printTextLineWrap *wrap; /* Wrap status for each column */
683 int output_columns = 0; /* Width of interactive console */
684 bool is_local_pager = false;
685
686 if (cancel_pressed)
687 return;
688
689 if (opt_border > 2)
690 opt_border = 2;
691
692 if (cont->ncolumns > 0)
693 {
694 col_count = cont->ncolumns;
695 width_header = pg_malloc0(col_count * sizeof(*width_header));
696 width_average = pg_malloc0(col_count * sizeof(*width_average));
697 max_width = pg_malloc0(col_count * sizeof(*max_width));
698 width_wrap = pg_malloc0(col_count * sizeof(*width_wrap));
699 max_nl_lines = pg_malloc0(col_count * sizeof(*max_nl_lines));
700 curr_nl_line = pg_malloc0(col_count * sizeof(*curr_nl_line));
701 col_lineptrs = pg_malloc0(col_count * sizeof(*col_lineptrs));
702 max_bytes = pg_malloc0(col_count * sizeof(*max_bytes));
703 format_buf = pg_malloc0(col_count * sizeof(*format_buf));
704 header_done = pg_malloc0(col_count * sizeof(*header_done));
705 bytes_output = pg_malloc0(col_count * sizeof(*bytes_output));
706 wrap = pg_malloc0(col_count * sizeof(*wrap));
707 }
708 else
709 {
710 width_header = NULL;
711 width_average = NULL;
712 max_width = NULL;
713 width_wrap = NULL;
714 max_nl_lines = NULL;
715 curr_nl_line = NULL;
716 col_lineptrs = NULL;
717 max_bytes = NULL;
718 format_buf = NULL;
719 header_done = NULL;
720 bytes_output = NULL;
721 wrap = NULL;
722 }
723
724 /* scan all column headers, find maximum width and max max_nl_lines */
725 for (i = 0; i < col_count; i++)
726 {
727 int width,
728 nl_lines,
729 bytes_required;
730
731 pg_wcssize((const unsigned char *) cont->headers[i], strlen(cont->headers[i]),
732 encoding, &width, &nl_lines, &bytes_required);
733 if (width > max_width[i])
734 max_width[i] = width;
735 if (nl_lines > max_nl_lines[i])
736 max_nl_lines[i] = nl_lines;
737 if (bytes_required > max_bytes[i])
738 max_bytes[i] = bytes_required;
739
740 width_header[i] = width;
741 }
742
743 /* scan all cells, find maximum width, compute cell_count */
744 for (i = 0, ptr = cont->cells; *ptr; ptr++, cell_count++)
745 {
746 int width,
747 nl_lines,
748 bytes_required;
749
750 pg_wcssize((const unsigned char *) *ptr, strlen(*ptr), encoding,
751 &width, &nl_lines, &bytes_required);
752
753 if (width > max_width[i])
754 max_width[i] = width;
755 if (nl_lines > max_nl_lines[i])
756 max_nl_lines[i] = nl_lines;
757 if (bytes_required > max_bytes[i])
758 max_bytes[i] = bytes_required;
759
760 width_average[i] += width;
761
762 /* i is the current column number: increment with wrap */
763 if (++i >= col_count)
764 i = 0;
765 }
766
767 /* If we have rows, compute average */
768 if (col_count != 0 && cell_count != 0)
769 {
770 int rows = cell_count / col_count;
771
772 for (i = 0; i < col_count; i++)
773 width_average[i] /= rows;
774 }
775
776 /* adjust the total display width based on border style */
777 if (opt_border == 0)
778 width_total = col_count;
779 else if (opt_border == 1)
780 width_total = col_count * 3 - ((col_count > 0) ? 1 : 0);
781 else
782 width_total = col_count * 3 + 1;
783 total_header_width = width_total;
784
785 for (i = 0; i < col_count; i++)
786 {
787 width_total += max_width[i];
788 total_header_width += width_header[i];
789 }
790
791 /*
792 * At this point: max_width[] contains the max width of each column,
793 * max_nl_lines[] contains the max number of lines in each column,
794 * max_bytes[] contains the maximum storage space for formatting strings,
795 * width_total contains the giant width sum. Now we allocate some memory
796 * for line pointers.
797 */
798 for (i = 0; i < col_count; i++)
799 {
800 /* Add entry for ptr == NULL array termination */
801 col_lineptrs[i] = pg_malloc0((max_nl_lines[i] + 1) *
802 sizeof(**col_lineptrs));
803
804 format_buf[i] = pg_malloc(max_bytes[i] + 1);
805
806 col_lineptrs[i]->ptr = format_buf[i];
807 }
808
809 /* Default word wrap to the full width, i.e. no word wrap */
810 for (i = 0; i < col_count; i++)
811 width_wrap[i] = max_width[i];
812
813 /*
814 * Choose target output width: \pset columns, or $COLUMNS, or ioctl
815 */
816 if (cont->opt->columns > 0)
817 output_columns = cont->opt->columns;
818 else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
819 {
820 if (cont->opt->env_columns > 0)
821 output_columns = cont->opt->env_columns;
822#ifdef TIOCGWINSZ
823 else
824 {
825 struct winsize screen_size;
826
827 if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
828 output_columns = screen_size.ws_col;
829 }
830#endif
831 }
832
833 if (cont->opt->format == PRINT_WRAPPED)
834 {
835 /*
836 * Optional optimized word wrap. Shrink columns with a high max/avg
837 * ratio. Slightly bias against wider columns. (Increases chance a
838 * narrow column will fit in its cell.) If available columns is
839 * positive... and greater than the width of the unshrinkable column
840 * headers
841 */
842 if (output_columns > 0 && output_columns >= total_header_width)
843 {
844 /* While there is still excess width... */
845 while (width_total > output_columns)
846 {
847 double max_ratio = 0;
848 int worst_col = -1;
849
850 /*
851 * Find column that has the highest ratio of its maximum width
852 * compared to its average width. This tells us which column
853 * will produce the fewest wrapped values if shortened.
854 * width_wrap starts as equal to max_width.
855 */
856 for (i = 0; i < col_count; i++)
857 {
858 if (width_average[i] && width_wrap[i] > width_header[i])
859 {
860 /* Penalize wide columns by 1% of their width */
861 double ratio;
862
863 ratio = (double) width_wrap[i] / width_average[i] +
864 max_width[i] * 0.01;
865 if (ratio > max_ratio)
866 {
867 max_ratio = ratio;
868 worst_col = i;
869 }
870 }
871 }
872
873 /* Exit loop if we can't squeeze any more. */
874 if (worst_col == -1)
875 break;
876
877 /* Decrease width of target column by one. */
878 width_wrap[worst_col]--;
879 width_total--;
880 }
881 }
882 }
883
884 /*
885 * If in expanded auto mode, we have now calculated the expected width, so
886 * we can now escape to vertical mode if necessary. If the output has
887 * only one column, the expanded format would be wider than the regular
888 * format, so don't use it in that case.
889 */
890 if (cont->opt->expanded == 2 && output_columns > 0 && cont->ncolumns > 1 &&
891 (output_columns < total_header_width || output_columns < width_total))
892 {
893 print_aligned_vertical(cont, fout, is_pager);
894 goto cleanup;
895 }
896
897 /* If we wrapped beyond the display width, use the pager */
898 if (!is_pager && fout == stdout && output_columns > 0 &&
899 (output_columns < total_header_width || output_columns < width_total))
900 {
901 fout = PageOutput(INT_MAX, cont->opt); /* force pager */
902 is_pager = is_local_pager = true;
903 }
904
905 /* Check if there are enough lines to require the pager */
906 if (!is_pager)
907 {
908 IsPagerNeeded(cont, width_wrap, false, &fout, &is_pager);
909 is_local_pager = is_pager;
910 }
911
912 /* time to output */
913 if (cont->opt->start_table)
914 {
915 /* print title */
916 if (cont->title && !opt_tuples_only)
917 {
918 int width,
919 height;
920
921 pg_wcssize((const unsigned char *) cont->title, strlen(cont->title),
922 encoding, &width, &height, NULL);
923 if (width >= width_total)
924 /* Aligned */
925 fprintf(fout, "%s\n", cont->title);
926 else
927 /* Centered */
928 fprintf(fout, "%-*s%s\n", (width_total - width) / 2, "",
929 cont->title);
930 }
931
932 /* print headers */
933 if (!opt_tuples_only)
934 {
935 int more_col_wrapping;
936 int curr_nl_line;
937
938 if (opt_border == 2)
939 _print_horizontal_line(col_count, width_wrap, opt_border,
940 PRINT_RULE_TOP, format, fout);
941
942 for (i = 0; i < col_count; i++)
943 pg_wcsformat((const unsigned char *) cont->headers[i],
944 strlen(cont->headers[i]), encoding,
945 col_lineptrs[i], max_nl_lines[i]);
946
947 more_col_wrapping = col_count;
948 curr_nl_line = 0;
949 if (col_count > 0)
950 memset(header_done, false, col_count * sizeof(bool));
951 while (more_col_wrapping)
952 {
953 if (opt_border == 2)
954 fputs(dformat->leftvrule, fout);
955
956 for (i = 0; i < cont->ncolumns; i++)
957 {
958 struct lineptr *this_line = col_lineptrs[i] + curr_nl_line;
959 unsigned int nbspace;
960
961 if (opt_border != 0 ||
962 (!format->wrap_right_border && i > 0))
963 fputs(curr_nl_line ? format->header_nl_left : " ",
964 fout);
965
966 if (!header_done[i])
967 {
968 nbspace = width_wrap[i] - this_line->width;
969
970 /* centered */
971 fprintf(fout, "%-*s%s%-*s",
972 nbspace / 2, "", this_line->ptr, (nbspace + 1) / 2, "");
973
974 if (!(this_line + 1)->ptr)
975 {
976 more_col_wrapping--;
977 header_done[i] = 1;
978 }
979 }
980 else
981 fprintf(fout, "%*s", width_wrap[i], "");
982
983 if (opt_border != 0 || format->wrap_right_border)
984 fputs(!header_done[i] ? format->header_nl_right : " ",
985 fout);
986
987 if (opt_border != 0 && col_count > 0 && i < col_count - 1)
988 fputs(dformat->midvrule, fout);
989 }
990 curr_nl_line++;
991
992 if (opt_border == 2)
993 fputs(dformat->rightvrule, fout);
994 fputc('\n', fout);
995 }
996
997 _print_horizontal_line(col_count, width_wrap, opt_border,
999 }
1000 }
1001
1002 /* print cells, one loop per row */
1003 for (i = 0, ptr = cont->cells; *ptr; i += col_count, ptr += col_count)
1004 {
1005 bool more_lines;
1006
1007 if (cancel_pressed)
1008 break;
1009
1010 /*
1011 * Format each cell.
1012 */
1013 for (j = 0; j < col_count; j++)
1014 {
1015 pg_wcsformat((const unsigned char *) ptr[j], strlen(ptr[j]), encoding,
1016 col_lineptrs[j], max_nl_lines[j]);
1017 curr_nl_line[j] = 0;
1018 }
1019
1020 memset(bytes_output, 0, col_count * sizeof(int));
1021
1022 /*
1023 * Each time through this loop, one display line is output. It can
1024 * either be a full value or a partial value if embedded newlines
1025 * exist or if 'format=wrapping' mode is enabled.
1026 */
1027 do
1028 {
1029 more_lines = false;
1030
1031 /* left border */
1032 if (opt_border == 2)
1033 fputs(dformat->leftvrule, fout);
1034
1035 /* for each column */
1036 for (j = 0; j < col_count; j++)
1037 {
1038 /* We have a valid array element, so index it */
1039 struct lineptr *this_line = &col_lineptrs[j][curr_nl_line[j]];
1040 int bytes_to_output;
1041 int chars_to_output = width_wrap[j];
1042 bool finalspaces = (opt_border == 2 ||
1043 (col_count > 0 && j < col_count - 1));
1044
1045 /* Print left-hand wrap or newline mark */
1046 if (opt_border != 0)
1047 {
1048 if (wrap[j] == PRINT_LINE_WRAP_WRAP)
1049 fputs(format->wrap_left, fout);
1050 else if (wrap[j] == PRINT_LINE_WRAP_NEWLINE)
1051 fputs(format->nl_left, fout);
1052 else
1053 fputc(' ', fout);
1054 }
1055
1056 if (!this_line->ptr)
1057 {
1058 /* Past newline lines so just pad for other columns */
1059 if (finalspaces)
1060 fprintf(fout, "%*s", chars_to_output, "");
1061 }
1062 else
1063 {
1064 /* Get strlen() of the characters up to width_wrap */
1065 bytes_to_output =
1066 strlen_max_width(this_line->ptr + bytes_output[j],
1067 &chars_to_output, encoding);
1068
1069 /*
1070 * If we exceeded width_wrap, it means the display width
1071 * of a single character was wider than our target width.
1072 * In that case, we have to pretend we are only printing
1073 * the target display width and make the best of it.
1074 */
1075 if (chars_to_output > width_wrap[j])
1076 chars_to_output = width_wrap[j];
1077
1078 if (cont->aligns[j] == 'r') /* Right aligned cell */
1079 {
1080 /* spaces first */
1081 fprintf(fout, "%*s", width_wrap[j] - chars_to_output, "");
1082 fwrite((char *) (this_line->ptr + bytes_output[j]),
1083 1, bytes_to_output, fout);
1084 }
1085 else /* Left aligned cell */
1086 {
1087 /* spaces second */
1088 fwrite((char *) (this_line->ptr + bytes_output[j]),
1089 1, bytes_to_output, fout);
1090 }
1091
1092 bytes_output[j] += bytes_to_output;
1093
1094 /* Do we have more text to wrap? */
1095 if (*(this_line->ptr + bytes_output[j]) != '\0')
1096 more_lines = true;
1097 else
1098 {
1099 /* Advance to next newline line */
1100 curr_nl_line[j]++;
1101 if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL)
1102 more_lines = true;
1103 bytes_output[j] = 0;
1104 }
1105 }
1106
1107 /* Determine next line's wrap status for this column */
1108 wrap[j] = PRINT_LINE_WRAP_NONE;
1109 if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL)
1110 {
1111 if (bytes_output[j] != 0)
1112 wrap[j] = PRINT_LINE_WRAP_WRAP;
1113 else if (curr_nl_line[j] != 0)
1114 wrap[j] = PRINT_LINE_WRAP_NEWLINE;
1115 }
1116
1117 /*
1118 * If left-aligned, pad out remaining space if needed (not
1119 * last column, and/or wrap marks required).
1120 */
1121 if (cont->aligns[j] != 'r') /* Left aligned cell */
1122 {
1123 if (finalspaces ||
1124 wrap[j] == PRINT_LINE_WRAP_WRAP ||
1125 wrap[j] == PRINT_LINE_WRAP_NEWLINE)
1126 fprintf(fout, "%*s",
1127 width_wrap[j] - chars_to_output, "");
1128 }
1129
1130 /* Print right-hand wrap or newline mark */
1131 if (wrap[j] == PRINT_LINE_WRAP_WRAP)
1132 fputs(format->wrap_right, fout);
1133 else if (wrap[j] == PRINT_LINE_WRAP_NEWLINE)
1134 fputs(format->nl_right, fout);
1135 else if (opt_border == 2 || (col_count > 0 && j < col_count - 1))
1136 fputc(' ', fout);
1137
1138 /* Print column divider, if not the last column */
1139 if (opt_border != 0 && (col_count > 0 && j < col_count - 1))
1140 {
1141 if (wrap[j + 1] == PRINT_LINE_WRAP_WRAP)
1142 fputs(format->midvrule_wrap, fout);
1143 else if (wrap[j + 1] == PRINT_LINE_WRAP_NEWLINE)
1144 fputs(format->midvrule_nl, fout);
1145 else if (col_lineptrs[j + 1][curr_nl_line[j + 1]].ptr == NULL)
1146 fputs(format->midvrule_blank, fout);
1147 else
1148 fputs(dformat->midvrule, fout);
1149 }
1150 }
1151
1152 /* end-of-row border */
1153 if (opt_border == 2)
1154 fputs(dformat->rightvrule, fout);
1155 fputc('\n', fout);
1156 } while (more_lines);
1157 }
1158
1159 if (cont->opt->stop_table)
1160 {
1161 printTableFooter *footers = footers_with_default(cont);
1162
1163 if (opt_border == 2 && !cancel_pressed)
1164 _print_horizontal_line(col_count, width_wrap, opt_border,
1165 PRINT_RULE_BOTTOM, format, fout);
1166
1167 /* print footers */
1168 if (footers && !opt_tuples_only && !cancel_pressed)
1169 {
1171
1172 for (f = footers; f; f = f->next)
1173 fprintf(fout, "%s\n", f->data);
1174 }
1175
1176 fputc('\n', fout);
1177 }
1178
1179cleanup:
1180 /* clean up */
1181 for (i = 0; i < col_count; i++)
1182 {
1183 free(col_lineptrs[i]);
1184 free(format_buf[i]);
1185 }
1186 free(width_header);
1187 free(width_average);
1188 free(max_width);
1189 free(width_wrap);
1190 free(max_nl_lines);
1191 free(curr_nl_line);
1192 free(col_lineptrs);
1193 free(max_bytes);
1194 free(format_buf);
1195 free(header_done);
1196 free(bytes_output);
1197 free(wrap);
1198
1199 if (is_local_pager)
1200 ClosePager(fout);
1201}
static void cleanup(void)
Definition: bootstrap.c:715
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
const printTextFormat * get_line_style(const printTableOpt *opt)
Definition: print.c:3874
static printTableFooter * footers_with_default(const printTableContent *cont)
Definition: print.c:414
FILE * PageOutput(int lines, const printTableOpt *topt)
Definition: print.c:3078
static void IsPagerNeeded(const printTableContent *cont, const unsigned int *width_wrap, bool vertical, FILE **fout, bool *is_pager)
Definition: print.c:3430
void ClosePager(FILE *pagerpipe)
Definition: print.c:3160
static int strlen_max_width(unsigned char *str, int *target_width, int encoding)
Definition: print.c:3943
static void print_aligned_vertical(const printTableContent *cont, FILE *fout, bool is_pager)
Definition: print.c:1304
static void _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths, unsigned short border, printTextRule pos, const printTextFormat *format, FILE *fout)
Definition: print.c:609
@ PRINT_RULE_MIDDLE
Definition: print.h:56
@ PRINT_RULE_BOTTOM
Definition: print.h:57
@ PRINT_RULE_DATA
Definition: print.h:58
@ PRINT_RULE_TOP
Definition: print.h:55
printTextLineWrap
Definition: print.h:62
@ PRINT_LINE_WRAP_WRAP
Definition: print.h:65
@ PRINT_LINE_WRAP_NEWLINE
Definition: print.h:66
@ PRINT_LINE_WRAP_NONE
Definition: print.h:64
@ PRINT_WRAPPED
Definition: print.h:39
#define free(a)
Definition: header.h:65
void pg_wcssize(const unsigned char *pwcs, size_t len, int encoding, int *result_width, int *result_height, int *result_format_size)
Definition: mbprint.c:211
void pg_wcsformat(const unsigned char *pwcs, size_t len, int encoding, struct lineptr *lines, int count)
Definition: mbprint.c:294
int32 encoding
Definition: pg_database.h:41
int width
Definition: mbprint.h:19
unsigned char * ptr
Definition: mbprint.h:18
char * aligns
Definition: print.h:178
const char ** headers
Definition: print.h:169
const char * title
Definition: print.h:166
const char ** cells
Definition: print.h:171
char * data
Definition: print.h:155
struct printTableFooter * next
Definition: print.h:156
bool start_table
Definition: print.h:127
unsigned short int expanded
Definition: print.h:114
bool tuples_only
Definition: print.h:126
int columns
Definition: print.h:140
enum printFormat format
Definition: print.h:113
int encoding
Definition: print.h:138
unsigned short int border
Definition: print.h:120
int env_columns
Definition: print.h:139
bool stop_table
Definition: print.h:128

References _print_horizontal_line(), printTableContent::aligns, printTableOpt::border, cancel_pressed, printTableContent::cells, cleanup(), ClosePager(), printTableOpt::columns, printTableFooter::data, encoding, printTableOpt::encoding, printTableOpt::env_columns, printTableOpt::expanded, footers_with_default(), format, printTableOpt::format, fprintf, free, get_line_style(), printTableContent::headers, i, IsPagerNeeded(), j, printTextLineFormat::leftvrule, printTextLineFormat::midvrule, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, PageOutput(), pg_malloc(), pg_malloc0(), pg_wcsformat(), pg_wcssize(), print_aligned_vertical(), PRINT_LINE_WRAP_NEWLINE, PRINT_LINE_WRAP_NONE, PRINT_LINE_WRAP_WRAP, PRINT_RULE_BOTTOM, PRINT_RULE_DATA, PRINT_RULE_MIDDLE, PRINT_RULE_TOP, PRINT_WRAPPED, lineptr::ptr, printTextLineFormat::rightvrule, printTableOpt::start_table, generate_unaccent_rules::stdout, printTableOpt::stop_table, strlen_max_width(), printTableContent::title, printTableOpt::tuples_only, and lineptr::width.

Referenced by printTable().

◆ print_aligned_vertical()

static void print_aligned_vertical ( const printTableContent cont,
FILE *  fout,
bool  is_pager 
)
static

Definition at line 1304 of file print.c.

1306{
1307 bool opt_tuples_only = cont->opt->tuples_only;
1308 unsigned short opt_border = cont->opt->border;
1309 const printTextFormat *format = get_line_style(cont->opt);
1310 const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA];
1311 int encoding = cont->opt->encoding;
1312 unsigned long record = cont->opt->prior_records + 1;
1313 const char *const *ptr;
1314 unsigned int i,
1315 hwidth = 0,
1316 dwidth = 0,
1317 hheight = 1,
1318 dheight = 1,
1319 hformatsize = 0,
1320 dformatsize = 0;
1321 struct lineptr *hlineptr,
1322 *dlineptr;
1323 bool is_local_pager = false,
1324 hmultiline = false,
1325 dmultiline = false;
1326 int output_columns = 0; /* Width of interactive console */
1327
1328 if (cancel_pressed)
1329 return;
1330
1331 if (opt_border > 2)
1332 opt_border = 2;
1333
1334 /*
1335 * Kluge for totally empty table: use the default footer even though
1336 * vertical modes normally don't. Otherwise we'd print nothing at all,
1337 * which isn't terribly friendly. Assume pager will not be needed.
1338 */
1339 if (cont->cells[0] == NULL && cont->opt->start_table &&
1340 cont->opt->stop_table)
1341 {
1342 printTableFooter *footers = footers_with_default(cont);
1343
1344 if (!opt_tuples_only && !cancel_pressed && footers)
1345 {
1347
1348 for (f = footers; f; f = f->next)
1349 fprintf(fout, "%s\n", f->data);
1350 }
1351
1352 fputc('\n', fout);
1353
1354 return;
1355 }
1356
1357 /*
1358 * Deal with the pager here instead of in printTable(), because we could
1359 * get here via print_aligned_text() in expanded auto mode, and so we have
1360 * to recalculate the pager requirement based on vertical output.
1361 */
1362 if (!is_pager)
1363 {
1364 IsPagerNeeded(cont, NULL, true, &fout, &is_pager);
1365 is_local_pager = is_pager;
1366 }
1367
1368 /* Find the maximum dimensions for the headers */
1369 for (i = 0; i < cont->ncolumns; i++)
1370 {
1371 int width,
1372 height,
1373 fs;
1374
1375 pg_wcssize((const unsigned char *) cont->headers[i], strlen(cont->headers[i]),
1376 encoding, &width, &height, &fs);
1377 if (width > hwidth)
1378 hwidth = width;
1379 if (height > hheight)
1380 {
1381 hheight = height;
1382 hmultiline = true;
1383 }
1384 if (fs > hformatsize)
1385 hformatsize = fs;
1386 }
1387
1388 /* find longest data cell */
1389 for (ptr = cont->cells; *ptr; ptr++)
1390 {
1391 int width,
1392 height,
1393 fs;
1394
1395 pg_wcssize((const unsigned char *) *ptr, strlen(*ptr), encoding,
1396 &width, &height, &fs);
1397 if (width > dwidth)
1398 dwidth = width;
1399 if (height > dheight)
1400 {
1401 dheight = height;
1402 dmultiline = true;
1403 }
1404 if (fs > dformatsize)
1405 dformatsize = fs;
1406 }
1407
1408 /*
1409 * We now have all the information we need to setup the formatting
1410 * structures
1411 */
1412 dlineptr = pg_malloc((sizeof(*dlineptr)) * (dheight + 1));
1413 hlineptr = pg_malloc((sizeof(*hlineptr)) * (hheight + 1));
1414
1415 dlineptr->ptr = pg_malloc(dformatsize);
1416 hlineptr->ptr = pg_malloc(hformatsize);
1417
1418 if (cont->opt->start_table)
1419 {
1420 /* print title */
1421 if (!opt_tuples_only && cont->title)
1422 fprintf(fout, "%s\n", cont->title);
1423 }
1424
1425 /*
1426 * Choose target output width: \pset columns, or $COLUMNS, or ioctl
1427 */
1428 if (cont->opt->columns > 0)
1429 output_columns = cont->opt->columns;
1430 else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
1431 {
1432 if (cont->opt->env_columns > 0)
1433 output_columns = cont->opt->env_columns;
1434#ifdef TIOCGWINSZ
1435 else
1436 {
1437 struct winsize screen_size;
1438
1439 if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
1440 output_columns = screen_size.ws_col;
1441 }
1442#endif
1443 }
1444
1445 /*
1446 * Calculate available width for data in wrapped mode
1447 */
1448 if (cont->opt->format == PRINT_WRAPPED)
1449 {
1450 unsigned int swidth,
1451 rwidth = 0,
1452 newdwidth;
1453
1454 if (opt_border == 0)
1455 {
1456 /*
1457 * For border = 0, one space in the middle. (If we discover we
1458 * need to wrap, the spacer column will be replaced by a wrap
1459 * marker, and we'll make room below for another wrap marker at
1460 * the end of the line. But for now, assume no wrap is needed.)
1461 */
1462 swidth = 1;
1463
1464 /* We might need a column for header newline markers, too */
1465 if (hmultiline)
1466 swidth++;
1467 }
1468 else if (opt_border == 1)
1469 {
1470 /*
1471 * For border = 1, two spaces and a vrule in the middle. (As
1472 * above, we might need one more column for a wrap marker.)
1473 */
1474 swidth = 3;
1475
1476 /* We might need a column for left header newline markers, too */
1477 if (hmultiline && (format == &pg_asciiformat_old))
1478 swidth++;
1479 }
1480 else
1481 {
1482 /*
1483 * For border = 2, two more for the vrules at the beginning and
1484 * end of the lines, plus spacer columns adjacent to these. (We
1485 * won't need extra columns for wrap/newline markers, we'll just
1486 * repurpose the spacers.)
1487 */
1488 swidth = 7;
1489 }
1490
1491 /* Reserve a column for data newline indicators, too, if needed */
1492 if (dmultiline &&
1493 opt_border < 2 && format != &pg_asciiformat_old)
1494 swidth++;
1495
1496 /* Determine width required for record header lines */
1497 if (!opt_tuples_only)
1498 {
1499 if (cont->nrows > 0)
1500 rwidth = 1 + (int) log10(cont->nrows);
1501 if (opt_border == 0)
1502 rwidth += 9; /* "* RECORD " */
1503 else if (opt_border == 1)
1504 rwidth += 12; /* "-[ RECORD ]" */
1505 else
1506 rwidth += 15; /* "+-[ RECORD ]-+" */
1507 }
1508
1509 /* We might need to do the rest of the calculation twice */
1510 for (;;)
1511 {
1512 unsigned int width;
1513
1514 /* Total width required to not wrap data */
1515 width = hwidth + swidth + dwidth;
1516 /* ... and not the header lines, either */
1517 if (width < rwidth)
1518 width = rwidth;
1519
1520 if (output_columns > 0)
1521 {
1522 unsigned int min_width;
1523
1524 /* Minimum acceptable width: room for just 3 columns of data */
1525 min_width = hwidth + swidth + 3;
1526 /* ... but not less than what the record header lines need */
1527 if (min_width < rwidth)
1528 min_width = rwidth;
1529
1530 if (output_columns >= width)
1531 {
1532 /* Plenty of room, use native data width */
1533 /* (but at least enough for the record header lines) */
1534 newdwidth = width - hwidth - swidth;
1535 }
1536 else if (output_columns < min_width)
1537 {
1538 /* Set data width to match min_width */
1539 newdwidth = min_width - hwidth - swidth;
1540 }
1541 else
1542 {
1543 /* Set data width to match output_columns */
1544 newdwidth = output_columns - hwidth - swidth;
1545 }
1546 }
1547 else
1548 {
1549 /* Don't know the wrap limit, so use native data width */
1550 /* (but at least enough for the record header lines) */
1551 newdwidth = width - hwidth - swidth;
1552 }
1553
1554 /*
1555 * If we will need to wrap data and didn't already allocate a data
1556 * newline/wrap marker column, do so and recompute.
1557 */
1558 if (newdwidth < dwidth && !dmultiline &&
1559 opt_border < 2 && format != &pg_asciiformat_old)
1560 {
1561 dmultiline = true;
1562 swidth++;
1563 }
1564 else
1565 break;
1566 }
1567
1568 dwidth = newdwidth;
1569 }
1570
1571 /* print records */
1572 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1573 {
1574 printTextRule pos;
1575 int dline,
1576 hline,
1577 dcomplete,
1578 hcomplete,
1579 offset,
1580 chars_to_output;
1581
1582 if (cancel_pressed)
1583 break;
1584
1585 if (i == 0)
1586 pos = PRINT_RULE_TOP;
1587 else
1588 pos = PRINT_RULE_MIDDLE;
1589
1590 /* Print record header (e.g. "[ RECORD N ]") above each record */
1591 if (i % cont->ncolumns == 0)
1592 {
1593 unsigned int lhwidth = hwidth;
1594
1595 if ((opt_border < 2) &&
1596 (hmultiline) &&
1598 lhwidth++; /* for newline indicators */
1599
1600 if (!opt_tuples_only)
1601 print_aligned_vertical_line(cont->opt, record++,
1602 lhwidth, dwidth, output_columns,
1603 pos, fout);
1604 else if (i != 0 || !cont->opt->start_table || opt_border == 2)
1605 print_aligned_vertical_line(cont->opt, 0, lhwidth,
1606 dwidth, output_columns, pos, fout);
1607 }
1608
1609 /* Format the header */
1610 pg_wcsformat((const unsigned char *) cont->headers[i % cont->ncolumns],
1611 strlen(cont->headers[i % cont->ncolumns]),
1612 encoding, hlineptr, hheight);
1613 /* Format the data */
1614 pg_wcsformat((const unsigned char *) *ptr, strlen(*ptr), encoding,
1615 dlineptr, dheight);
1616
1617 /*
1618 * Loop through header and data in parallel dealing with newlines and
1619 * wrapped lines until they're both exhausted
1620 */
1621 dline = hline = 0;
1622 dcomplete = hcomplete = 0;
1623 offset = 0;
1624 chars_to_output = dlineptr[dline].width;
1625 while (!dcomplete || !hcomplete)
1626 {
1627 /* Left border */
1628 if (opt_border == 2)
1629 fprintf(fout, "%s", dformat->leftvrule);
1630
1631 /* Header (never wrapped so just need to deal with newlines) */
1632 if (!hcomplete)
1633 {
1634 int swidth = hwidth,
1635 target_width = hwidth;
1636
1637 /*
1638 * Left spacer or new line indicator
1639 */
1640 if ((opt_border == 2) ||
1641 (hmultiline && (format == &pg_asciiformat_old)))
1642 fputs(hline ? format->header_nl_left : " ", fout);
1643
1644 /*
1645 * Header text
1646 */
1647 strlen_max_width(hlineptr[hline].ptr, &target_width,
1648 encoding);
1649 fprintf(fout, "%-s", hlineptr[hline].ptr);
1650
1651 /*
1652 * Spacer
1653 */
1654 swidth -= target_width;
1655 if (swidth > 0)
1656 fprintf(fout, "%*s", swidth, " ");
1657
1658 /*
1659 * New line indicator or separator's space
1660 */
1661 if (hlineptr[hline + 1].ptr)
1662 {
1663 /* More lines after this one due to a newline */
1664 if ((opt_border > 0) ||
1665 (hmultiline && (format != &pg_asciiformat_old)))
1666 fputs(format->header_nl_right, fout);
1667 hline++;
1668 }
1669 else
1670 {
1671 /* This was the last line of the header */
1672 if ((opt_border > 0) ||
1673 (hmultiline && (format != &pg_asciiformat_old)))
1674 fputs(" ", fout);
1675 hcomplete = 1;
1676 }
1677 }
1678 else
1679 {
1680 unsigned int swidth = hwidth + opt_border;
1681
1682 if ((opt_border < 2) &&
1683 (hmultiline) &&
1685 swidth++;
1686
1687 if ((opt_border == 0) &&
1688 (format != &pg_asciiformat_old) &&
1689 (hmultiline))
1690 swidth++;
1691
1692 fprintf(fout, "%*s", swidth, " ");
1693 }
1694
1695 /* Separator */
1696 if (opt_border > 0)
1697 {
1698 if (offset)
1699 fputs(format->midvrule_wrap, fout);
1700 else if (dline == 0)
1701 fputs(dformat->midvrule, fout);
1702 else
1703 fputs(format->midvrule_nl, fout);
1704 }
1705
1706 /* Data */
1707 if (!dcomplete)
1708 {
1709 int target_width = dwidth,
1710 bytes_to_output,
1711 swidth = dwidth;
1712
1713 /*
1714 * Left spacer or wrap indicator
1715 */
1716 fputs(offset == 0 ? " " : format->wrap_left, fout);
1717
1718 /*
1719 * Data text
1720 */
1721 bytes_to_output = strlen_max_width(dlineptr[dline].ptr + offset,
1722 &target_width, encoding);
1723 fwrite((char *) (dlineptr[dline].ptr + offset),
1724 1, bytes_to_output, fout);
1725
1726 chars_to_output -= target_width;
1727 offset += bytes_to_output;
1728
1729 /* Spacer */
1730 swidth -= target_width;
1731
1732 if (chars_to_output)
1733 {
1734 /* continuing a wrapped column */
1735 if ((opt_border > 1) ||
1736 (dmultiline && (format != &pg_asciiformat_old)))
1737 {
1738 if (swidth > 0)
1739 fprintf(fout, "%*s", swidth, " ");
1740 fputs(format->wrap_right, fout);
1741 }
1742 }
1743 else if (dlineptr[dline + 1].ptr)
1744 {
1745 /* reached a newline in the column */
1746 if ((opt_border > 1) ||
1747 (dmultiline && (format != &pg_asciiformat_old)))
1748 {
1749 if (swidth > 0)
1750 fprintf(fout, "%*s", swidth, " ");
1751 fputs(format->nl_right, fout);
1752 }
1753 dline++;
1754 offset = 0;
1755 chars_to_output = dlineptr[dline].width;
1756 }
1757 else
1758 {
1759 /* reached the end of the cell */
1760 if (opt_border > 1)
1761 {
1762 if (swidth > 0)
1763 fprintf(fout, "%*s", swidth, " ");
1764 fputs(" ", fout);
1765 }
1766 dcomplete = 1;
1767 }
1768
1769 /* Right border */
1770 if (opt_border == 2)
1771 fputs(dformat->rightvrule, fout);
1772
1773 fputs("\n", fout);
1774 }
1775 else
1776 {
1777 /*
1778 * data exhausted (this can occur if header is longer than the
1779 * data due to newlines in the header)
1780 */
1781 if (opt_border < 2)
1782 fputs("\n", fout);
1783 else
1784 fprintf(fout, "%*s %s\n", dwidth, "", dformat->rightvrule);
1785 }
1786 }
1787 }
1788
1789 if (cont->opt->stop_table)
1790 {
1791 if (opt_border == 2 && !cancel_pressed)
1792 print_aligned_vertical_line(cont->opt, 0, hwidth, dwidth,
1793 output_columns, PRINT_RULE_BOTTOM, fout);
1794
1795 /* print footers */
1796 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
1797 {
1799
1800 if (opt_border < 2)
1801 fputc('\n', fout);
1802 for (f = cont->footers; f; f = f->next)
1803 fprintf(fout, "%s\n", f->data);
1804 }
1805
1806 fputc('\n', fout);
1807 }
1808
1809 free(hlineptr->ptr);
1810 free(dlineptr->ptr);
1811 free(hlineptr);
1812 free(dlineptr);
1813
1814 if (is_local_pager)
1815 ClosePager(fout);
1816}
static void print_aligned_vertical_line(const printTableOpt *topt, unsigned long record, unsigned int hwidth, unsigned int dwidth, int output_columns, printTextRule pos, FILE *fout)
Definition: print.c:1205
const printTextFormat pg_asciiformat_old
Definition: print.c:82
printTextRule
Definition: print.h:53

References printTableOpt::border, cancel_pressed, printTableContent::cells, ClosePager(), printTableOpt::columns, printTableFooter::data, encoding, printTableOpt::encoding, printTableOpt::env_columns, printTableContent::footers, footers_with_default(), format, printTableOpt::format, fprintf, free, get_line_style(), printTableContent::headers, i, IsPagerNeeded(), printTextLineFormat::leftvrule, printTextLineFormat::midvrule, printTableContent::ncolumns, printTableFooter::next, printTableContent::nrows, printTableContent::opt, pg_asciiformat_old, pg_malloc(), pg_wcsformat(), pg_wcssize(), print_aligned_vertical_line(), PRINT_RULE_BOTTOM, PRINT_RULE_DATA, PRINT_RULE_MIDDLE, PRINT_RULE_TOP, PRINT_WRAPPED, printTableOpt::prior_records, lineptr::ptr, printTextLineFormat::rightvrule, printTableOpt::start_table, generate_unaccent_rules::stdout, printTableOpt::stop_table, strlen_max_width(), printTableContent::title, printTableOpt::tuples_only, and lineptr::width.

Referenced by print_aligned_text(), and printTable().

◆ print_aligned_vertical_line()

static void print_aligned_vertical_line ( const printTableOpt topt,
unsigned long  record,
unsigned int  hwidth,
unsigned int  dwidth,
int  output_columns,
printTextRule  pos,
FILE *  fout 
)
static

Definition at line 1205 of file print.c.

1212{
1213 const printTextLineFormat *lformat = &get_line_style(topt)->lrule[pos];
1214 const unsigned short opt_border = topt->border;
1215 unsigned int i;
1216 int reclen = 0;
1217
1218 if (opt_border == 2)
1219 fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
1220 else if (opt_border == 1)
1221 fputs(lformat->hrule, fout);
1222
1223 if (record)
1224 {
1225 if (opt_border == 0)
1226 reclen = fprintf(fout, "* Record %lu", record);
1227 else
1228 reclen = fprintf(fout, "[ RECORD %lu ]", record);
1229 }
1230 if (opt_border != 2)
1231 reclen++;
1232 if (reclen < 0)
1233 reclen = 0;
1234 for (i = reclen; i < hwidth; i++)
1235 fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1236 reclen -= hwidth;
1237
1238 if (opt_border > 0)
1239 {
1240 if (reclen-- <= 0)
1241 fputs(lformat->hrule, fout);
1242 if (reclen-- <= 0)
1243 {
1245 {
1246 fputs(lformat->rightvrule, fout);
1247 }
1248 else
1249 {
1250 fputs(lformat->midvrule, fout);
1251 }
1252 }
1253 if (reclen-- <= 0
1255 fputs(lformat->hrule, fout);
1256 }
1257 else
1258 {
1259 if (reclen-- <= 0)
1260 fputc(' ', fout);
1261 }
1262
1264 {
1267 {
1269 {
1270 output_columns = topt->expanded_header_exact_width;
1271 }
1272 if (output_columns > 0)
1273 {
1274 if (opt_border == 0)
1275 dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth)));
1276 if (opt_border == 1)
1277 dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth - 3)));
1278
1279 /*
1280 * Handling the xheader width for border=2 doesn't make much
1281 * sense because this format has an additional right border,
1282 * but keep this for consistency.
1283 */
1284 if (opt_border == 2)
1285 dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth - 7)));
1286 }
1287 }
1288
1289 if (reclen < 0)
1290 reclen = 0;
1291 if (dwidth < reclen)
1292 dwidth = reclen;
1293
1294 for (i = reclen; i < dwidth; i++)
1295 fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1296 if (opt_border == 2)
1297 fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
1298 }
1299
1300 fputc('\n', fout);
1301}
#define Min(x, y)
Definition: c.h:1006
@ PRINT_XHEADER_EXACT_WIDTH
Definition: print.h:78
@ PRINT_XHEADER_PAGE
Definition: print.h:76
@ PRINT_XHEADER_COLUMN
Definition: print.h:74
int expanded_header_exact_width
Definition: print.h:118
printXheaderWidthType expanded_header_width_type
Definition: print.h:116
printTextLineFormat lrule[4]
Definition: print.h:85

References printTableOpt::border, printTableOpt::expanded_header_exact_width, printTableOpt::expanded_header_width_type, fprintf, get_line_style(), printTextLineFormat::hrule, i, printTextLineFormat::leftvrule, printTextFormat::lrule, Max, printTextLineFormat::midvrule, Min, PRINT_XHEADER_COLUMN, PRINT_XHEADER_EXACT_WIDTH, PRINT_XHEADER_PAGE, and printTextLineFormat::rightvrule.

Referenced by print_aligned_vertical().

◆ print_asciidoc_text()

static void print_asciidoc_text ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 2171 of file print.c.

2172{
2173 bool opt_tuples_only = cont->opt->tuples_only;
2174 unsigned short opt_border = cont->opt->border;
2175 unsigned int i;
2176 const char *const *ptr;
2177
2178 if (cancel_pressed)
2179 return;
2180
2181 if (cont->opt->start_table)
2182 {
2183 /* print table in new paragraph - enforce preliminary new line */
2184 fputs("\n", fout);
2185
2186 /* print title */
2187 if (!opt_tuples_only && cont->title)
2188 {
2189 fputs(".", fout);
2190 fputs(cont->title, fout);
2191 fputs("\n", fout);
2192 }
2193
2194 /* print table [] header definition */
2195 fprintf(fout, "[%scols=\"", !opt_tuples_only ? "options=\"header\"," : "");
2196 for (i = 0; i < cont->ncolumns; i++)
2197 {
2198 if (i != 0)
2199 fputs(",", fout);
2200 fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
2201 }
2202 fputs("\"", fout);
2203 switch (opt_border)
2204 {
2205 case 0:
2206 fputs(",frame=\"none\",grid=\"none\"", fout);
2207 break;
2208 case 1:
2209 fputs(",frame=\"none\"", fout);
2210 break;
2211 case 2:
2212 fputs(",frame=\"all\",grid=\"all\"", fout);
2213 break;
2214 }
2215 fputs("]\n", fout);
2216 fputs("|====\n", fout);
2217
2218 /* print headers */
2219 if (!opt_tuples_only)
2220 {
2221 for (ptr = cont->headers; *ptr; ptr++)
2222 {
2223 if (ptr != cont->headers)
2224 fputs(" ", fout);
2225 fputs("^l|", fout);
2226 asciidoc_escaped_print(*ptr, fout);
2227 }
2228 fputs("\n", fout);
2229 }
2230 }
2231
2232 /* print cells */
2233 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2234 {
2235 if (i % cont->ncolumns == 0)
2236 {
2237 if (cancel_pressed)
2238 break;
2239 }
2240
2241 if (i % cont->ncolumns != 0)
2242 fputs(" ", fout);
2243 fputs("|", fout);
2244
2245 /* protect against needless spaces */
2246 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2247 {
2248 if ((i + 1) % cont->ncolumns != 0)
2249 fputs(" ", fout);
2250 }
2251 else
2252 asciidoc_escaped_print(*ptr, fout);
2253
2254 if ((i + 1) % cont->ncolumns == 0)
2255 fputs("\n", fout);
2256 }
2257
2258 fputs("|====\n", fout);
2259
2260 if (cont->opt->stop_table)
2261 {
2262 printTableFooter *footers = footers_with_default(cont);
2263
2264 /* print footers */
2265 if (!opt_tuples_only && footers != NULL && !cancel_pressed)
2266 {
2268
2269 fputs("\n....\n", fout);
2270 for (f = footers; f; f = f->next)
2271 {
2272 fputs(f->data, fout);
2273 fputs("\n", fout);
2274 }
2275 fputs("....\n", fout);
2276 }
2277 }
2278}
static void asciidoc_escaped_print(const char *in, FILE *fout)
Definition: print.c:2153

References printTableContent::aligns, asciidoc_escaped_print(), printTableOpt::border, cancel_pressed, printTableContent::cells, printTableFooter::data, footers_with_default(), fprintf, printTableContent::headers, i, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, printTableOpt::start_table, printTableOpt::stop_table, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_asciidoc_vertical()

static void print_asciidoc_vertical ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 2281 of file print.c.

2282{
2283 bool opt_tuples_only = cont->opt->tuples_only;
2284 unsigned short opt_border = cont->opt->border;
2285 unsigned long record = cont->opt->prior_records + 1;
2286 unsigned int i;
2287 const char *const *ptr;
2288
2289 if (cancel_pressed)
2290 return;
2291
2292 if (cont->opt->start_table)
2293 {
2294 /* print table in new paragraph - enforce preliminary new line */
2295 fputs("\n", fout);
2296
2297 /* print title */
2298 if (!opt_tuples_only && cont->title)
2299 {
2300 fputs(".", fout);
2301 fputs(cont->title, fout);
2302 fputs("\n", fout);
2303 }
2304
2305 /* print table [] header definition */
2306 fputs("[cols=\"h,l\"", fout);
2307 switch (opt_border)
2308 {
2309 case 0:
2310 fputs(",frame=\"none\",grid=\"none\"", fout);
2311 break;
2312 case 1:
2313 fputs(",frame=\"none\"", fout);
2314 break;
2315 case 2:
2316 fputs(",frame=\"all\",grid=\"all\"", fout);
2317 break;
2318 }
2319 fputs("]\n", fout);
2320 fputs("|====\n", fout);
2321 }
2322
2323 /* print records */
2324 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2325 {
2326 if (i % cont->ncolumns == 0)
2327 {
2328 if (cancel_pressed)
2329 break;
2330 if (!opt_tuples_only)
2331 fprintf(fout,
2332 "2+^|Record %lu\n",
2333 record++);
2334 else
2335 fputs("2+|\n", fout);
2336 }
2337
2338 fputs("<l|", fout);
2339 asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
2340
2341 fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">l" : "<l");
2342 /* is string only whitespace? */
2343 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2344 fputs(" ", fout);
2345 else
2346 asciidoc_escaped_print(*ptr, fout);
2347 fputs("\n", fout);
2348 }
2349
2350 fputs("|====\n", fout);
2351
2352 if (cont->opt->stop_table)
2353 {
2354 /* print footers */
2355 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
2356 {
2358
2359 fputs("\n....\n", fout);
2360 for (f = cont->footers; f; f = f->next)
2361 {
2362 fputs(f->data, fout);
2363 fputs("\n", fout);
2364 }
2365 fputs("....\n", fout);
2366 }
2367 }
2368}

References printTableContent::aligns, asciidoc_escaped_print(), printTableOpt::border, cancel_pressed, printTableContent::cells, printTableFooter::data, printTableContent::footers, fprintf, printTableContent::headers, i, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, printTableOpt::prior_records, printTableOpt::start_table, printTableOpt::stop_table, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_csv_text()

static void print_csv_text ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 1865 of file print.c.

1866{
1867 const char *const *ptr;
1868 int i;
1869
1870 if (cancel_pressed)
1871 return;
1872
1873 /*
1874 * The title and footer are never printed in csv format. The header is
1875 * printed if opt_tuples_only is false.
1876 *
1877 * Despite RFC 4180 saying that end of lines are CRLF, terminate lines
1878 * with '\n', which prints out as the system-dependent EOL string in text
1879 * mode (typically LF on Unix and CRLF on Windows).
1880 */
1881 if (cont->opt->start_table && !cont->opt->tuples_only)
1882 {
1883 /* print headers */
1884 for (ptr = cont->headers; *ptr; ptr++)
1885 {
1886 if (ptr != cont->headers)
1887 fputc(cont->opt->csvFieldSep[0], fout);
1888 csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1889 }
1890 fputc('\n', fout);
1891 }
1892
1893 /* print cells */
1894 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1895 {
1896 csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1897 if ((i + 1) % cont->ncolumns)
1898 fputc(cont->opt->csvFieldSep[0], fout);
1899 else
1900 fputc('\n', fout);
1901 }
1902}
static void csv_print_field(const char *str, FILE *fout, char sep)
Definition: print.c:1840
char csvFieldSep[2]
Definition: print.h:134

References cancel_pressed, printTableContent::cells, csv_print_field(), printTableOpt::csvFieldSep, printTableContent::headers, i, printTableContent::ncolumns, printTableContent::opt, printTableOpt::start_table, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_csv_vertical()

static void print_csv_vertical ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 1905 of file print.c.

1906{
1907 const char *const *ptr;
1908 int i;
1909
1910 /* print records */
1911 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1912 {
1913 if (cancel_pressed)
1914 return;
1915
1916 /* print name of column */
1917 csv_print_field(cont->headers[i % cont->ncolumns], fout,
1918 cont->opt->csvFieldSep[0]);
1919
1920 /* print field separator */
1921 fputc(cont->opt->csvFieldSep[0], fout);
1922
1923 /* print field value */
1924 csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1925
1926 fputc('\n', fout);
1927 }
1928}

References cancel_pressed, printTableContent::cells, csv_print_field(), printTableOpt::csvFieldSep, printTableContent::headers, i, printTableContent::ncolumns, and printTableContent::opt.

Referenced by printTable().

◆ print_html_text()

static void print_html_text ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 1978 of file print.c.

1979{
1980 bool opt_tuples_only = cont->opt->tuples_only;
1981 unsigned short opt_border = cont->opt->border;
1982 const char *opt_table_attr = cont->opt->tableAttr;
1983 unsigned int i;
1984 const char *const *ptr;
1985
1986 if (cancel_pressed)
1987 return;
1988
1989 if (cont->opt->start_table)
1990 {
1991 fprintf(fout, "<table border=\"%d\"", opt_border);
1992 if (opt_table_attr)
1993 fprintf(fout, " %s", opt_table_attr);
1994 fputs(">\n", fout);
1995
1996 /* print title */
1997 if (!opt_tuples_only && cont->title)
1998 {
1999 fputs(" <caption>", fout);
2000 html_escaped_print(cont->title, fout);
2001 fputs("</caption>\n", fout);
2002 }
2003
2004 /* print headers */
2005 if (!opt_tuples_only)
2006 {
2007 fputs(" <tr>\n", fout);
2008 for (ptr = cont->headers; *ptr; ptr++)
2009 {
2010 fputs(" <th align=\"center\">", fout);
2011 html_escaped_print(*ptr, fout);
2012 fputs("</th>\n", fout);
2013 }
2014 fputs(" </tr>\n", fout);
2015 }
2016 }
2017
2018 /* print cells */
2019 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2020 {
2021 if (i % cont->ncolumns == 0)
2022 {
2023 if (cancel_pressed)
2024 break;
2025 fputs(" <tr valign=\"top\">\n", fout);
2026 }
2027
2028 fprintf(fout, " <td align=\"%s\">", cont->aligns[(i) % cont->ncolumns] == 'r' ? "right" : "left");
2029 /* is string only whitespace? */
2030 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2031 fputs("&nbsp; ", fout);
2032 else
2033 html_escaped_print(*ptr, fout);
2034
2035 fputs("</td>\n", fout);
2036
2037 if ((i + 1) % cont->ncolumns == 0)
2038 fputs(" </tr>\n", fout);
2039 }
2040
2041 if (cont->opt->stop_table)
2042 {
2043 printTableFooter *footers = footers_with_default(cont);
2044
2045 fputs("</table>\n", fout);
2046
2047 /* print footers */
2048 if (!opt_tuples_only && footers != NULL && !cancel_pressed)
2049 {
2051
2052 fputs("<p>", fout);
2053 for (f = footers; f; f = f->next)
2054 {
2055 html_escaped_print(f->data, fout);
2056 fputs("<br />\n", fout);
2057 }
2058 fputs("</p>", fout);
2059 }
2060
2061 fputc('\n', fout);
2062 }
2063}
void html_escaped_print(const char *in, FILE *fout)
Definition: print.c:1937
char * tableAttr
Definition: print.h:137

References printTableContent::aligns, printTableOpt::border, cancel_pressed, printTableContent::cells, printTableFooter::data, footers_with_default(), fprintf, printTableContent::headers, html_escaped_print(), i, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, printTableOpt::start_table, printTableOpt::stop_table, printTableOpt::tableAttr, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_html_vertical()

static void print_html_vertical ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 2067 of file print.c.

2068{
2069 bool opt_tuples_only = cont->opt->tuples_only;
2070 unsigned short opt_border = cont->opt->border;
2071 const char *opt_table_attr = cont->opt->tableAttr;
2072 unsigned long record = cont->opt->prior_records + 1;
2073 unsigned int i;
2074 const char *const *ptr;
2075
2076 if (cancel_pressed)
2077 return;
2078
2079 if (cont->opt->start_table)
2080 {
2081 fprintf(fout, "<table border=\"%d\"", opt_border);
2082 if (opt_table_attr)
2083 fprintf(fout, " %s", opt_table_attr);
2084 fputs(">\n", fout);
2085
2086 /* print title */
2087 if (!opt_tuples_only && cont->title)
2088 {
2089 fputs(" <caption>", fout);
2090 html_escaped_print(cont->title, fout);
2091 fputs("</caption>\n", fout);
2092 }
2093 }
2094
2095 /* print records */
2096 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2097 {
2098 if (i % cont->ncolumns == 0)
2099 {
2100 if (cancel_pressed)
2101 break;
2102 if (!opt_tuples_only)
2103 fprintf(fout,
2104 "\n <tr><td colspan=\"2\" align=\"center\">Record %lu</td></tr>\n",
2105 record++);
2106 else
2107 fputs("\n <tr><td colspan=\"2\">&nbsp;</td></tr>\n", fout);
2108 }
2109 fputs(" <tr valign=\"top\">\n"
2110 " <th>", fout);
2111 html_escaped_print(cont->headers[i % cont->ncolumns], fout);
2112 fputs("</th>\n", fout);
2113
2114 fprintf(fout, " <td align=\"%s\">", cont->aligns[i % cont->ncolumns] == 'r' ? "right" : "left");
2115 /* is string only whitespace? */
2116 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2117 fputs("&nbsp; ", fout);
2118 else
2119 html_escaped_print(*ptr, fout);
2120
2121 fputs("</td>\n </tr>\n", fout);
2122 }
2123
2124 if (cont->opt->stop_table)
2125 {
2126 fputs("</table>\n", fout);
2127
2128 /* print footers */
2129 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
2130 {
2132
2133 fputs("<p>", fout);
2134 for (f = cont->footers; f; f = f->next)
2135 {
2136 html_escaped_print(f->data, fout);
2137 fputs("<br />\n", fout);
2138 }
2139 fputs("</p>", fout);
2140 }
2141
2142 fputc('\n', fout);
2143 }
2144}

References printTableContent::aligns, printTableOpt::border, cancel_pressed, printTableContent::cells, printTableFooter::data, printTableContent::footers, fprintf, printTableContent::headers, html_escaped_print(), i, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, printTableOpt::prior_records, printTableOpt::start_table, printTableOpt::stop_table, printTableOpt::tableAttr, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_latex_longtable_text()

static void print_latex_longtable_text ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 2546 of file print.c.

2547{
2548 bool opt_tuples_only = cont->opt->tuples_only;
2549 unsigned short opt_border = cont->opt->border;
2550 unsigned int i;
2551 const char *opt_table_attr = cont->opt->tableAttr;
2552 const char *next_opt_table_attr_char = opt_table_attr;
2553 const char *last_opt_table_attr_char = NULL;
2554 const char *const *ptr;
2555
2556 if (cancel_pressed)
2557 return;
2558
2559 if (opt_border > 3)
2560 opt_border = 3;
2561
2562 if (cont->opt->start_table)
2563 {
2564 /* begin environment and set alignments and borders */
2565 fputs("\\begin{longtable}{", fout);
2566
2567 if (opt_border >= 2)
2568 fputs("| ", fout);
2569
2570 for (i = 0; i < cont->ncolumns; i++)
2571 {
2572 /* longtable supports either a width (p) or an alignment (l/r) */
2573 /* Are we left-justified and was a proportional width specified? */
2574 if (*(cont->aligns + i) == 'l' && opt_table_attr)
2575 {
2576#define LONGTABLE_WHITESPACE " \t\n"
2577
2578 /* advance over whitespace */
2579 next_opt_table_attr_char += strspn(next_opt_table_attr_char,
2581 /* We have a value? */
2582 if (next_opt_table_attr_char[0] != '\0')
2583 {
2584 fputs("p{", fout);
2585 fwrite(next_opt_table_attr_char, strcspn(next_opt_table_attr_char,
2586 LONGTABLE_WHITESPACE), 1, fout);
2587 last_opt_table_attr_char = next_opt_table_attr_char;
2588 next_opt_table_attr_char += strcspn(next_opt_table_attr_char,
2590 fputs("\\textwidth}", fout);
2591 }
2592 /* use previous value */
2593 else if (last_opt_table_attr_char != NULL)
2594 {
2595 fputs("p{", fout);
2596 fwrite(last_opt_table_attr_char, strcspn(last_opt_table_attr_char,
2597 LONGTABLE_WHITESPACE), 1, fout);
2598 fputs("\\textwidth}", fout);
2599 }
2600 else
2601 fputc('l', fout);
2602 }
2603 else
2604 fputc(*(cont->aligns + i), fout);
2605
2606 if (opt_border != 0 && i < cont->ncolumns - 1)
2607 fputs(" | ", fout);
2608 }
2609
2610 if (opt_border >= 2)
2611 fputs(" |", fout);
2612
2613 fputs("}\n", fout);
2614
2615 /* print headers */
2616 if (!opt_tuples_only)
2617 {
2618 /* firsthead */
2619 if (opt_border >= 2)
2620 fputs("\\toprule\n", fout);
2621 for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2622 {
2623 if (i != 0)
2624 fputs(" & ", fout);
2625 fputs("\\small\\textbf{\\textit{", fout);
2626 latex_escaped_print(*ptr, fout);
2627 fputs("}}", fout);
2628 }
2629 fputs(" \\\\\n", fout);
2630 fputs("\\midrule\n\\endfirsthead\n", fout);
2631
2632 /* secondary heads */
2633 if (opt_border >= 2)
2634 fputs("\\toprule\n", fout);
2635 for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2636 {
2637 if (i != 0)
2638 fputs(" & ", fout);
2639 fputs("\\small\\textbf{\\textit{", fout);
2640 latex_escaped_print(*ptr, fout);
2641 fputs("}}", fout);
2642 }
2643 fputs(" \\\\\n", fout);
2644 /* If the line under the row already appeared, don't do another */
2645 if (opt_border != 3)
2646 fputs("\\midrule\n", fout);
2647 fputs("\\endhead\n", fout);
2648
2649 /* table name, caption? */
2650 if (!opt_tuples_only && cont->title)
2651 {
2652 /* Don't output if we are printing a line under each row */
2653 if (opt_border == 2)
2654 fputs("\\bottomrule\n", fout);
2655 fputs("\\caption[", fout);
2656 latex_escaped_print(cont->title, fout);
2657 fputs(" (Continued)]{", fout);
2658 latex_escaped_print(cont->title, fout);
2659 fputs("}\n\\endfoot\n", fout);
2660 if (opt_border == 2)
2661 fputs("\\bottomrule\n", fout);
2662 fputs("\\caption[", fout);
2663 latex_escaped_print(cont->title, fout);
2664 fputs("]{", fout);
2665 latex_escaped_print(cont->title, fout);
2666 fputs("}\n\\endlastfoot\n", fout);
2667 }
2668 /* output bottom table line? */
2669 else if (opt_border >= 2)
2670 {
2671 fputs("\\bottomrule\n\\endfoot\n", fout);
2672 fputs("\\bottomrule\n\\endlastfoot\n", fout);
2673 }
2674 }
2675 }
2676
2677 /* print cells */
2678 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2679 {
2680 /* Add a line under each row? */
2681 if (i != 0 && i % cont->ncolumns != 0)
2682 fputs("\n&\n", fout);
2683 fputs("\\raggedright{", fout);
2684 latex_escaped_print(*ptr, fout);
2685 fputc('}', fout);
2686 if ((i + 1) % cont->ncolumns == 0)
2687 {
2688 fputs(" \\tabularnewline\n", fout);
2689 if (opt_border == 3)
2690 fputs(" \\hline\n", fout);
2691 }
2692 if (cancel_pressed)
2693 break;
2694 }
2695
2696 if (cont->opt->stop_table)
2697 fputs("\\end{longtable}\n", fout);
2698}
#define LONGTABLE_WHITESPACE
static void latex_escaped_print(const char *in, FILE *fout)
Definition: print.c:2377

References printTableContent::aligns, printTableOpt::border, cancel_pressed, printTableContent::cells, printTableContent::headers, i, latex_escaped_print(), LONGTABLE_WHITESPACE, printTableContent::ncolumns, printTableContent::opt, printTableOpt::start_table, printTableOpt::stop_table, printTableOpt::tableAttr, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_latex_text()

static void print_latex_text ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 2439 of file print.c.

2440{
2441 bool opt_tuples_only = cont->opt->tuples_only;
2442 unsigned short opt_border = cont->opt->border;
2443 unsigned int i;
2444 const char *const *ptr;
2445
2446 if (cancel_pressed)
2447 return;
2448
2449 if (opt_border > 3)
2450 opt_border = 3;
2451
2452 if (cont->opt->start_table)
2453 {
2454 /* print title */
2455 if (!opt_tuples_only && cont->title)
2456 {
2457 fputs("\\begin{center}\n", fout);
2458 latex_escaped_print(cont->title, fout);
2459 fputs("\n\\end{center}\n\n", fout);
2460 }
2461
2462 /* begin environment and set alignments and borders */
2463 fputs("\\begin{tabular}{", fout);
2464
2465 if (opt_border >= 2)
2466 fputs("| ", fout);
2467 for (i = 0; i < cont->ncolumns; i++)
2468 {
2469 fputc(*(cont->aligns + i), fout);
2470 if (opt_border != 0 && i < cont->ncolumns - 1)
2471 fputs(" | ", fout);
2472 }
2473 if (opt_border >= 2)
2474 fputs(" |", fout);
2475
2476 fputs("}\n", fout);
2477
2478 if (!opt_tuples_only && opt_border >= 2)
2479 fputs("\\hline\n", fout);
2480
2481 /* print headers */
2482 if (!opt_tuples_only)
2483 {
2484 for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2485 {
2486 if (i != 0)
2487 fputs(" & ", fout);
2488 fputs("\\textit{", fout);
2489 latex_escaped_print(*ptr, fout);
2490 fputc('}', fout);
2491 }
2492 fputs(" \\\\\n", fout);
2493 fputs("\\hline\n", fout);
2494 }
2495 }
2496
2497 /* print cells */
2498 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2499 {
2500 latex_escaped_print(*ptr, fout);
2501
2502 if ((i + 1) % cont->ncolumns == 0)
2503 {
2504 fputs(" \\\\\n", fout);
2505 if (opt_border == 3)
2506 fputs("\\hline\n", fout);
2507 if (cancel_pressed)
2508 break;
2509 }
2510 else
2511 fputs(" & ", fout);
2512 }
2513
2514 if (cont->opt->stop_table)
2515 {
2516 printTableFooter *footers = footers_with_default(cont);
2517
2518 if (opt_border == 2)
2519 fputs("\\hline\n", fout);
2520
2521 fputs("\\end{tabular}\n\n\\noindent ", fout);
2522
2523 /* print footers */
2524 if (footers && !opt_tuples_only && !cancel_pressed)
2525 {
2527
2528 for (f = footers; f; f = f->next)
2529 {
2530 latex_escaped_print(f->data, fout);
2531 fputs(" \\\\\n", fout);
2532 }
2533 }
2534
2535 fputc('\n', fout);
2536 }
2537}

References printTableContent::aligns, printTableOpt::border, cancel_pressed, printTableContent::cells, printTableFooter::data, footers_with_default(), printTableContent::headers, i, latex_escaped_print(), printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, printTableOpt::start_table, printTableOpt::stop_table, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_latex_vertical()

static void print_latex_vertical ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 2702 of file print.c.

2703{
2704 bool opt_tuples_only = cont->opt->tuples_only;
2705 unsigned short opt_border = cont->opt->border;
2706 unsigned long record = cont->opt->prior_records + 1;
2707 unsigned int i;
2708 const char *const *ptr;
2709
2710 if (cancel_pressed)
2711 return;
2712
2713 if (opt_border > 2)
2714 opt_border = 2;
2715
2716 if (cont->opt->start_table)
2717 {
2718 /* print title */
2719 if (!opt_tuples_only && cont->title)
2720 {
2721 fputs("\\begin{center}\n", fout);
2722 latex_escaped_print(cont->title, fout);
2723 fputs("\n\\end{center}\n\n", fout);
2724 }
2725
2726 /* begin environment and set alignments and borders */
2727 fputs("\\begin{tabular}{", fout);
2728 if (opt_border == 0)
2729 fputs("cl", fout);
2730 else if (opt_border == 1)
2731 fputs("c|l", fout);
2732 else if (opt_border == 2)
2733 fputs("|c|l|", fout);
2734 fputs("}\n", fout);
2735 }
2736
2737 /* print records */
2738 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2739 {
2740 /* new record */
2741 if (i % cont->ncolumns == 0)
2742 {
2743 if (cancel_pressed)
2744 break;
2745 if (!opt_tuples_only)
2746 {
2747 if (opt_border == 2)
2748 {
2749 fputs("\\hline\n", fout);
2750 fprintf(fout, "\\multicolumn{2}{|c|}{\\textit{Record %lu}} \\\\\n", record++);
2751 }
2752 else
2753 fprintf(fout, "\\multicolumn{2}{c}{\\textit{Record %lu}} \\\\\n", record++);
2754 }
2755 if (opt_border >= 1)
2756 fputs("\\hline\n", fout);
2757 }
2758
2759 latex_escaped_print(cont->headers[i % cont->ncolumns], fout);
2760 fputs(" & ", fout);
2761 latex_escaped_print(*ptr, fout);
2762 fputs(" \\\\\n", fout);
2763 }
2764
2765 if (cont->opt->stop_table)
2766 {
2767 if (opt_border == 2)
2768 fputs("\\hline\n", fout);
2769
2770 fputs("\\end{tabular}\n\n\\noindent ", fout);
2771
2772 /* print footers */
2773 if (cont->footers && !opt_tuples_only && !cancel_pressed)
2774 {
2776
2777 for (f = cont->footers; f; f = f->next)
2778 {
2779 latex_escaped_print(f->data, fout);
2780 fputs(" \\\\\n", fout);
2781 }
2782 }
2783
2784 fputc('\n', fout);
2785 }
2786}

References printTableOpt::border, cancel_pressed, printTableContent::cells, printTableFooter::data, printTableContent::footers, fprintf, printTableContent::headers, i, latex_escaped_print(), printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, printTableOpt::prior_records, printTableOpt::start_table, printTableOpt::stop_table, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_separator()

static void print_separator ( struct separator  sep,
FILE *  fout 
)
static

Definition at line 395 of file print.c.

396{
397 if (sep.separator_zero)
398 fputc('\000', fout);
399 else if (sep.separator)
400 fputs(sep.separator, fout);
401}
bool separator_zero
Definition: print.h:108
char * separator
Definition: print.h:107

References separator::separator, and separator::separator_zero.

Referenced by print_unaligned_text(), and print_unaligned_vertical().

◆ print_troff_ms_text()

static void print_troff_ms_text ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 2812 of file print.c.

2813{
2814 bool opt_tuples_only = cont->opt->tuples_only;
2815 unsigned short opt_border = cont->opt->border;
2816 unsigned int i;
2817 const char *const *ptr;
2818
2819 if (cancel_pressed)
2820 return;
2821
2822 if (opt_border > 2)
2823 opt_border = 2;
2824
2825 if (cont->opt->start_table)
2826 {
2827 /* print title */
2828 if (!opt_tuples_only && cont->title)
2829 {
2830 fputs(".LP\n.DS C\n", fout);
2831 troff_ms_escaped_print(cont->title, fout);
2832 fputs("\n.DE\n", fout);
2833 }
2834
2835 /* begin environment and set alignments and borders */
2836 fputs(".LP\n.TS\n", fout);
2837 if (opt_border == 2)
2838 fputs("center box;\n", fout);
2839 else
2840 fputs("center;\n", fout);
2841
2842 for (i = 0; i < cont->ncolumns; i++)
2843 {
2844 fputc(*(cont->aligns + i), fout);
2845 if (opt_border > 0 && i < cont->ncolumns - 1)
2846 fputs(" | ", fout);
2847 }
2848 fputs(".\n", fout);
2849
2850 /* print headers */
2851 if (!opt_tuples_only)
2852 {
2853 for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2854 {
2855 if (i != 0)
2856 fputc('\t', fout);
2857 fputs("\\fI", fout);
2858 troff_ms_escaped_print(*ptr, fout);
2859 fputs("\\fP", fout);
2860 }
2861 fputs("\n_\n", fout);
2862 }
2863 }
2864
2865 /* print cells */
2866 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2867 {
2868 troff_ms_escaped_print(*ptr, fout);
2869
2870 if ((i + 1) % cont->ncolumns == 0)
2871 {
2872 fputc('\n', fout);
2873 if (cancel_pressed)
2874 break;
2875 }
2876 else
2877 fputc('\t', fout);
2878 }
2879
2880 if (cont->opt->stop_table)
2881 {
2882 printTableFooter *footers = footers_with_default(cont);
2883
2884 fputs(".TE\n.DS L\n", fout);
2885
2886 /* print footers */
2887 if (footers && !opt_tuples_only && !cancel_pressed)
2888 {
2890
2891 for (f = footers; f; f = f->next)
2892 {
2893 troff_ms_escaped_print(f->data, fout);
2894 fputc('\n', fout);
2895 }
2896 }
2897
2898 fputs(".DE\n", fout);
2899 }
2900}
static void troff_ms_escaped_print(const char *in, FILE *fout)
Definition: print.c:2795

References printTableContent::aligns, printTableOpt::border, cancel_pressed, printTableContent::cells, printTableFooter::data, footers_with_default(), printTableContent::headers, i, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, printTableOpt::start_table, printTableOpt::stop_table, printTableContent::title, troff_ms_escaped_print(), and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_troff_ms_vertical()

static void print_troff_ms_vertical ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 2904 of file print.c.

2905{
2906 bool opt_tuples_only = cont->opt->tuples_only;
2907 unsigned short opt_border = cont->opt->border;
2908 unsigned long record = cont->opt->prior_records + 1;
2909 unsigned int i;
2910 const char *const *ptr;
2911 unsigned short current_format = 0; /* 0=none, 1=header, 2=body */
2912
2913 if (cancel_pressed)
2914 return;
2915
2916 if (opt_border > 2)
2917 opt_border = 2;
2918
2919 if (cont->opt->start_table)
2920 {
2921 /* print title */
2922 if (!opt_tuples_only && cont->title)
2923 {
2924 fputs(".LP\n.DS C\n", fout);
2925 troff_ms_escaped_print(cont->title, fout);
2926 fputs("\n.DE\n", fout);
2927 }
2928
2929 /* begin environment and set alignments and borders */
2930 fputs(".LP\n.TS\n", fout);
2931 if (opt_border == 2)
2932 fputs("center box;\n", fout);
2933 else
2934 fputs("center;\n", fout);
2935
2936 /* basic format */
2937 if (opt_tuples_only)
2938 fputs("c l;\n", fout);
2939 }
2940 else
2941 current_format = 2; /* assume tuples printed already */
2942
2943 /* print records */
2944 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2945 {
2946 /* new record */
2947 if (i % cont->ncolumns == 0)
2948 {
2949 if (cancel_pressed)
2950 break;
2951 if (!opt_tuples_only)
2952 {
2953 if (current_format != 1)
2954 {
2955 if (opt_border == 2 && record > 1)
2956 fputs("_\n", fout);
2957 if (current_format != 0)
2958 fputs(".T&\n", fout);
2959 fputs("c s.\n", fout);
2960 current_format = 1;
2961 }
2962 fprintf(fout, "\\fIRecord %lu\\fP\n", record++);
2963 }
2964 if (opt_border >= 1)
2965 fputs("_\n", fout);
2966 }
2967
2968 if (!opt_tuples_only)
2969 {
2970 if (current_format != 2)
2971 {
2972 if (current_format != 0)
2973 fputs(".T&\n", fout);
2974 if (opt_border != 1)
2975 fputs("c l.\n", fout);
2976 else
2977 fputs("c | l.\n", fout);
2978 current_format = 2;
2979 }
2980 }
2981
2982 troff_ms_escaped_print(cont->headers[i % cont->ncolumns], fout);
2983 fputc('\t', fout);
2984 troff_ms_escaped_print(*ptr, fout);
2985
2986 fputc('\n', fout);
2987 }
2988
2989 if (cont->opt->stop_table)
2990 {
2991 fputs(".TE\n.DS L\n", fout);
2992
2993 /* print footers */
2994 if (cont->footers && !opt_tuples_only && !cancel_pressed)
2995 {
2997
2998 for (f = cont->footers; f; f = f->next)
2999 {
3000 troff_ms_escaped_print(f->data, fout);
3001 fputc('\n', fout);
3002 }
3003 }
3004
3005 fputs(".DE\n", fout);
3006 }
3007}

References printTableOpt::border, cancel_pressed, printTableContent::cells, printTableFooter::data, printTableContent::footers, fprintf, printTableContent::headers, i, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, printTableOpt::prior_records, printTableOpt::start_table, printTableOpt::stop_table, printTableContent::title, troff_ms_escaped_print(), and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_unaligned_text()

static void print_unaligned_text ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 438 of file print.c.

439{
440 bool opt_tuples_only = cont->opt->tuples_only;
441 unsigned int i;
442 const char *const *ptr;
443 bool need_recordsep = false;
444
445 if (cancel_pressed)
446 return;
447
448 if (cont->opt->start_table)
449 {
450 /* print title */
451 if (!opt_tuples_only && cont->title)
452 {
453 fputs(cont->title, fout);
454 print_separator(cont->opt->recordSep, fout);
455 }
456
457 /* print headers */
458 if (!opt_tuples_only)
459 {
460 for (ptr = cont->headers; *ptr; ptr++)
461 {
462 if (ptr != cont->headers)
463 print_separator(cont->opt->fieldSep, fout);
464 fputs(*ptr, fout);
465 }
466 need_recordsep = true;
467 }
468 }
469 else
470 /* assume continuing printout */
471 need_recordsep = true;
472
473 /* print cells */
474 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
475 {
476 if (need_recordsep)
477 {
478 print_separator(cont->opt->recordSep, fout);
479 need_recordsep = false;
480 if (cancel_pressed)
481 break;
482 }
483 fputs(*ptr, fout);
484
485 if ((i + 1) % cont->ncolumns)
486 print_separator(cont->opt->fieldSep, fout);
487 else
488 need_recordsep = true;
489 }
490
491 /* print footers */
492 if (cont->opt->stop_table)
493 {
494 printTableFooter *footers = footers_with_default(cont);
495
496 if (!opt_tuples_only && footers != NULL && !cancel_pressed)
497 {
499
500 for (f = footers; f; f = f->next)
501 {
502 if (need_recordsep)
503 {
504 print_separator(cont->opt->recordSep, fout);
505 need_recordsep = false;
506 }
507 fputs(f->data, fout);
508 need_recordsep = true;
509 }
510 }
511
512 /*
513 * The last record is terminated by a newline, independent of the set
514 * record separator. But when the record separator is a zero byte, we
515 * use that (compatible with find -print0 and xargs).
516 */
517 if (need_recordsep)
518 {
519 if (cont->opt->recordSep.separator_zero)
520 print_separator(cont->opt->recordSep, fout);
521 else
522 fputc('\n', fout);
523 }
524 }
525}
static void print_separator(struct separator sep, FILE *fout)
Definition: print.c:395
struct separator fieldSep
Definition: print.h:132
struct separator recordSep
Definition: print.h:133

References cancel_pressed, printTableContent::cells, printTableFooter::data, printTableOpt::fieldSep, footers_with_default(), printTableContent::headers, i, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, print_separator(), printTableOpt::recordSep, separator::separator_zero, printTableOpt::start_table, printTableOpt::stop_table, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ print_unaligned_vertical()

static void print_unaligned_vertical ( const printTableContent cont,
FILE *  fout 
)
static

Definition at line 529 of file print.c.

530{
531 bool opt_tuples_only = cont->opt->tuples_only;
532 unsigned int i;
533 const char *const *ptr;
534 bool need_recordsep = false;
535
536 if (cancel_pressed)
537 return;
538
539 if (cont->opt->start_table)
540 {
541 /* print title */
542 if (!opt_tuples_only && cont->title)
543 {
544 fputs(cont->title, fout);
545 need_recordsep = true;
546 }
547 }
548 else
549 /* assume continuing printout */
550 need_recordsep = true;
551
552 /* print records */
553 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
554 {
555 if (need_recordsep)
556 {
557 /* record separator is 2 occurrences of recordsep in this mode */
558 print_separator(cont->opt->recordSep, fout);
559 print_separator(cont->opt->recordSep, fout);
560 need_recordsep = false;
561 if (cancel_pressed)
562 break;
563 }
564
565 fputs(cont->headers[i % cont->ncolumns], fout);
566 print_separator(cont->opt->fieldSep, fout);
567 fputs(*ptr, fout);
568
569 if ((i + 1) % cont->ncolumns)
570 print_separator(cont->opt->recordSep, fout);
571 else
572 need_recordsep = true;
573 }
574
575 if (cont->opt->stop_table)
576 {
577 /* print footers */
578 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
579 {
581
582 print_separator(cont->opt->recordSep, fout);
583 for (f = cont->footers; f; f = f->next)
584 {
585 print_separator(cont->opt->recordSep, fout);
586 fputs(f->data, fout);
587 }
588 }
589
590 /* see above in print_unaligned_text() */
591 if (need_recordsep)
592 {
593 if (cont->opt->recordSep.separator_zero)
594 print_separator(cont->opt->recordSep, fout);
595 else
596 fputc('\n', fout);
597 }
598 }
599}

References cancel_pressed, printTableContent::cells, printTableFooter::data, printTableOpt::fieldSep, printTableContent::footers, printTableContent::headers, i, printTableContent::ncolumns, printTableFooter::next, printTableContent::opt, print_separator(), printTableOpt::recordSep, separator::separator_zero, printTableOpt::start_table, printTableOpt::stop_table, printTableContent::title, and printTableOpt::tuples_only.

Referenced by printTable().

◆ printQuery()

void printQuery ( const PGresult result,
const printQueryOpt opt,
FILE *  fout,
bool  is_pager,
FILE *  flog 
)

Definition at line 3742 of file print.c.

3744{
3745 printTableContent cont;
3746 int i,
3747 r,
3748 c;
3749
3750 if (cancel_pressed)
3751 return;
3752
3753 printTableInit(&cont, &opt->topt, opt->title,
3754 PQnfields(result), PQntuples(result));
3755
3756 /* Assert caller supplied enough translate_columns[] entries */
3757 Assert(opt->translate_columns == NULL ||
3758 opt->n_translate_columns >= cont.ncolumns);
3759
3760 for (i = 0; i < cont.ncolumns; i++)
3761 {
3762 printTableAddHeader(&cont, PQfname(result, i),
3763 opt->translate_header,
3764 column_type_alignment(PQftype(result, i)));
3765 }
3766
3767 /* set cells */
3768 for (r = 0; r < cont.nrows; r++)
3769 {
3770 for (c = 0; c < cont.ncolumns; c++)
3771 {
3772 char *cell;
3773 bool mustfree = false;
3774 bool translate;
3775
3776 if (PQgetisnull(result, r, c))
3777 cell = opt->nullPrint ? opt->nullPrint : "";
3778 else if (PQftype(result, c) == BOOLOID)
3779 cell = (PQgetvalue(result, r, c)[0] == 't' ?
3780 (opt->truePrint ? opt->truePrint : "t") :
3781 (opt->falsePrint ? opt->falsePrint : "f"));
3782 else
3783 {
3784 cell = PQgetvalue(result, r, c);
3785 if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
3786 {
3787 cell = format_numeric_locale(cell);
3788 mustfree = true;
3789 }
3790 }
3791
3793 printTableAddCell(&cont, cell, translate, mustfree);
3794 }
3795 }
3796
3797 /* set footers */
3798 if (opt->footers)
3799 {
3800 char **footer;
3801
3802 for (footer = opt->footers; *footer; footer++)
3803 printTableAddFooter(&cont, *footer);
3804 }
3805
3806 printTable(&cont, fout, is_pager, flog);
3807 printTableCleanup(&cont);
3808}
Oid PQftype(const PGresult *res, int field_num)
Definition: fe-exec.c:3736
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition: print.c:3191
void printTableCleanup(printTableContent *const content)
Definition: print.c:3372
char column_type_alignment(Oid ftype)
Definition: print.c:3811
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3279
static char * format_numeric_locale(const char *my_str)
Definition: print.c:330
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3636
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3329
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:3239
#define PQgetvalue
Definition: libpq-be-fe.h:253
#define PQnfields
Definition: libpq-be-fe.h:252
#define PQgetisnull
Definition: libpq-be-fe.h:255
#define PQfname
Definition: libpq-be-fe.h:256
#define PQntuples
Definition: libpq-be-fe.h:251
Datum translate(PG_FUNCTION_ARGS)
char * c
const bool * translate_columns
Definition: print.h:192
printTableOpt topt
Definition: print.h:185
char * nullPrint
Definition: print.h:186
char * falsePrint
Definition: print.h:188
char * title
Definition: print.h:189
char ** footers
Definition: print.h:190
bool translate_header
Definition: print.h:191
int n_translate_columns
Definition: print.h:194
char * truePrint
Definition: print.h:187
bool numericLocale
Definition: print.h:135

References printTableContent::aligns, Assert(), cancel_pressed, column_type_alignment(), printQueryOpt::falsePrint, printQueryOpt::footers, format_numeric_locale(), i, printQueryOpt::n_translate_columns, printTableContent::ncolumns, printTableContent::nrows, printQueryOpt::nullPrint, printTableOpt::numericLocale, PQfname, PQftype(), PQgetisnull, PQgetvalue, PQnfields, PQntuples, printTable(), printTableAddCell(), printTableAddFooter(), printTableAddHeader(), printTableCleanup(), printTableInit(), printQueryOpt::title, printQueryOpt::topt, translate(), printQueryOpt::translate_columns, printQueryOpt::translate_header, and printQueryOpt::truePrint.

Referenced by describeAccessMethods(), describeAggregates(), describeConfigurationParameters(), describeFunctions(), describeOneTableDetails(), describeOneTSConfig(), describeOneTSParser(), describeOperators(), describeRoleGrants(), describeSubscriptions(), describeTablespaces(), describeTypes(), ExecQueryAndProcessResults(), listAllDbs(), listCasts(), listCollations(), listConversions(), listDbRoleSettings(), listDefaultACLs(), listDomains(), listEventTriggers(), listExtendedStats(), listExtensions(), listForeignDataWrappers(), listForeignServers(), listForeignTables(), listLanguages(), listLargeObjects(), listOneExtensionContents(), listOperatorClasses(), listOperatorFamilies(), listOpFamilyFunctions(), listOpFamilyOperators(), listPartitionedTables(), listPublications(), listSchemas(), listTables(), listTSConfigs(), listTSDictionaries(), listTSParsers(), listTSTemplates(), listUserMappings(), objectDescription(), permissionsList(), and PrintQueryTuples().

◆ printTable()

void printTable ( const printTableContent cont,
FILE *  fout,
bool  is_pager,
FILE *  flog 
)

Definition at line 3636 of file print.c.

3638{
3639 bool is_local_pager = false;
3640
3641 if (cancel_pressed)
3642 return;
3643
3644 if (cont->opt->format == PRINT_NOTHING)
3645 return;
3646
3647 /* print_aligned_*() handle the pager themselves */
3648 if (!is_pager &&
3649 cont->opt->format != PRINT_ALIGNED &&
3650 cont->opt->format != PRINT_WRAPPED)
3651 {
3652 IsPagerNeeded(cont, NULL, (cont->opt->expanded == 1), &fout, &is_pager);
3653 is_local_pager = is_pager;
3654 }
3655
3656 /* clear any pre-existing error indication on the output stream */
3657 clearerr(fout);
3658
3659 /* print the stuff */
3660 switch (cont->opt->format)
3661 {
3662 case PRINT_UNALIGNED:
3663 if (cont->opt->expanded == 1)
3664 print_unaligned_vertical(cont, fout);
3665 else
3666 print_unaligned_text(cont, fout);
3667 break;
3668 case PRINT_ALIGNED:
3669 case PRINT_WRAPPED:
3670
3671 /*
3672 * In expanded-auto mode, force vertical if a pager is passed in;
3673 * else we may make different decisions for different hunks of the
3674 * query result.
3675 */
3676 if (cont->opt->expanded == 1 ||
3677 (cont->opt->expanded == 2 && is_pager))
3678 print_aligned_vertical(cont, fout, is_pager);
3679 else
3680 print_aligned_text(cont, fout, is_pager);
3681 break;
3682 case PRINT_CSV:
3683 if (cont->opt->expanded == 1)
3684 print_csv_vertical(cont, fout);
3685 else
3686 print_csv_text(cont, fout);
3687 break;
3688 case PRINT_HTML:
3689 if (cont->opt->expanded == 1)
3690 print_html_vertical(cont, fout);
3691 else
3692 print_html_text(cont, fout);
3693 break;
3694 case PRINT_ASCIIDOC:
3695 if (cont->opt->expanded == 1)
3696 print_asciidoc_vertical(cont, fout);
3697 else
3698 print_asciidoc_text(cont, fout);
3699 break;
3700 case PRINT_LATEX:
3701 if (cont->opt->expanded == 1)
3702 print_latex_vertical(cont, fout);
3703 else
3704 print_latex_text(cont, fout);
3705 break;
3707 if (cont->opt->expanded == 1)
3708 print_latex_vertical(cont, fout);
3709 else
3710 print_latex_longtable_text(cont, fout);
3711 break;
3712 case PRINT_TROFF_MS:
3713 if (cont->opt->expanded == 1)
3714 print_troff_ms_vertical(cont, fout);
3715 else
3716 print_troff_ms_text(cont, fout);
3717 break;
3718 default:
3719 fprintf(stderr, _("invalid output format (internal error): %d"),
3720 cont->opt->format);
3721 exit(EXIT_FAILURE);
3722 }
3723
3724 if (is_local_pager)
3725 ClosePager(fout);
3726
3727 /* also produce log output if wanted */
3728 if (flog)
3729 print_aligned_text(cont, flog, false);
3730}
static void print_asciidoc_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2171
static void print_unaligned_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:529
static void print_latex_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2439
static void print_troff_ms_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2812
static void print_html_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1978
static void print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2904
static void print_csv_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1865
static void print_aligned_text(const printTableContent *cont, FILE *fout, bool is_pager)
Definition: print.c:651
static void print_csv_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:1905
static void print_html_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2067
static void print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2281
static void print_unaligned_text(const printTableContent *cont, FILE *fout)
Definition: print.c:438
static void print_latex_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2702
static void print_latex_longtable_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2546
@ PRINT_LATEX_LONGTABLE
Definition: print.h:36
@ PRINT_CSV
Definition: print.h:33
@ PRINT_UNALIGNED
Definition: print.h:38
@ PRINT_ALIGNED
Definition: print.h:31
@ PRINT_TROFF_MS
Definition: print.h:37
@ PRINT_ASCIIDOC
Definition: print.h:32
@ PRINT_NOTHING
Definition: print.h:30
@ PRINT_LATEX
Definition: print.h:35
@ PRINT_HTML
Definition: print.h:34
#define EXIT_FAILURE
Definition: settings.h:197

References _, cancel_pressed, ClosePager(), EXIT_FAILURE, printTableOpt::expanded, printTableOpt::format, fprintf, IsPagerNeeded(), printTableContent::opt, PRINT_ALIGNED, print_aligned_text(), print_aligned_vertical(), PRINT_ASCIIDOC, print_asciidoc_text(), print_asciidoc_vertical(), PRINT_CSV, print_csv_text(), print_csv_vertical(), PRINT_HTML, print_html_text(), print_html_vertical(), PRINT_LATEX, PRINT_LATEX_LONGTABLE, print_latex_longtable_text(), print_latex_text(), print_latex_vertical(), PRINT_NOTHING, PRINT_TROFF_MS, print_troff_ms_text(), print_troff_ms_vertical(), PRINT_UNALIGNED, print_unaligned_text(), print_unaligned_vertical(), and PRINT_WRAPPED.

Referenced by describeOneTableDetails(), describePublications(), describeRoles(), exec_command_conninfo(), printCrosstab(), and printQuery().

◆ printTableAddCell()

void printTableAddCell ( printTableContent *const  content,
char *  cell,
const bool  translate,
const bool  mustfree 
)

Definition at line 3279 of file print.c.

3281{
3282 uint64 total_cells;
3283
3284#ifndef ENABLE_NLS
3285 (void) translate; /* unused parameter */
3286#endif
3287
3288 total_cells = (uint64) content->ncolumns * content->nrows;
3289 if (content->cellsadded >= total_cells)
3290 {
3291 fprintf(stderr, _("Cannot add cell to table content: total cell count of %" PRIu64 " exceeded.\n"),
3292 total_cells);
3293 exit(EXIT_FAILURE);
3294 }
3295
3296 *content->cell = (char *) mbvalidate((unsigned char *) cell,
3297 content->opt->encoding);
3298
3299#ifdef ENABLE_NLS
3300 if (translate)
3301 *content->cell = _(*content->cell);
3302#endif
3303
3304 if (mustfree)
3305 {
3306 if (content->cellmustfree == NULL)
3307 content->cellmustfree =
3308 pg_malloc0((total_cells + 1) * sizeof(bool));
3309
3310 content->cellmustfree[content->cellsadded] = true;
3311 }
3312 content->cell++;
3313 content->cellsadded++;
3314}
uint64_t uint64
Definition: c.h:542
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
unsigned char * mbvalidate(unsigned char *pwcs, int encoding)
Definition: mbprint.c:392
uint64 cellsadded
Definition: print.h:174
bool * cellmustfree
Definition: print.h:175
const char ** cell
Definition: print.h:173

References _, printTableContent::cell, printTableContent::cellmustfree, printTableContent::cellsadded, printTableOpt::encoding, EXIT_FAILURE, fprintf, if(), mbvalidate(), printTableContent::ncolumns, printTableContent::nrows, printTableContent::opt, pg_malloc0(), and translate().

Referenced by describeOneTableDetails(), describePublications(), describeRoles(), exec_command_conninfo(), and printQuery().

◆ printTableAddFooter()

void printTableAddFooter ( printTableContent *const  content,
const char *  footer 
)

Definition at line 3329 of file print.c.

3330{
3332
3333 f = pg_malloc0(sizeof(*f));
3334 f->data = pg_strdup(footer);
3335
3336 if (content->footers == NULL)
3337 content->footers = f;
3338 else
3339 content->footer->next = f;
3340
3341 content->footer = f;
3342}
printTableFooter * footer
Definition: print.h:177

References printTableFooter::data, printTableContent::footer, printTableContent::footers, printTableFooter::next, pg_malloc0(), and pg_strdup().

Referenced by add_tablespace_footer(), addFooterToPublicationDesc(), describeOneTableDetails(), printQuery(), and printTableSetFooter().

◆ printTableAddHeader()

void printTableAddHeader ( printTableContent *const  content,
char *  header,
const bool  translate,
const char  align 
)

Definition at line 3239 of file print.c.

3241{
3242#ifndef ENABLE_NLS
3243 (void) translate; /* unused parameter */
3244#endif
3245
3246 if (content->header >= content->headers + content->ncolumns)
3247 {
3248 fprintf(stderr, _("Cannot add header to table content: "
3249 "column count of %d exceeded.\n"),
3250 content->ncolumns);
3251 exit(EXIT_FAILURE);
3252 }
3253
3254 *content->header = (char *) mbvalidate((unsigned char *) header,
3255 content->opt->encoding);
3256#ifdef ENABLE_NLS
3257 if (translate)
3258 *content->header = _(*content->header);
3259#endif
3260 content->header++;
3261
3262 *content->align = align;
3263 content->align++;
3264}
char * align
Definition: print.h:180
const char ** header
Definition: print.h:170

References _, printTableContent::align, printTableOpt::encoding, EXIT_FAILURE, fprintf, printTableContent::header, printTableContent::headers, mbvalidate(), printTableContent::ncolumns, printTableContent::opt, and translate().

Referenced by describeOneTableDetails(), describePublications(), describeRoles(), exec_command_conninfo(), printCrosstab(), and printQuery().

◆ printTableCleanup()

void printTableCleanup ( printTableContent *const  content)

Definition at line 3372 of file print.c.

3373{
3374 if (content->cellmustfree)
3375 {
3376 uint64 total_cells;
3377
3378 total_cells = (uint64) content->ncolumns * content->nrows;
3379 for (uint64 i = 0; i < total_cells; i++)
3380 {
3381 if (content->cellmustfree[i])
3382 free(unconstify(char *, content->cells[i]));
3383 }
3384 free(content->cellmustfree);
3385 content->cellmustfree = NULL;
3386 }
3387 free(content->headers);
3388 free(content->cells);
3389 free(content->aligns);
3390
3391 content->opt = NULL;
3392 content->title = NULL;
3393 content->headers = NULL;
3394 content->cells = NULL;
3395 content->aligns = NULL;
3396 content->header = NULL;
3397 content->cell = NULL;
3398 content->align = NULL;
3399
3400 if (content->footers)
3401 {
3402 for (content->footer = content->footers; content->footer;)
3403 {
3405
3406 f = content->footer;
3407 content->footer = f->next;
3408 free(f->data);
3409 free(f);
3410 }
3411 }
3412 content->footers = NULL;
3413 content->footer = NULL;
3414}
#define unconstify(underlying_type, expr)
Definition: c.h:1233
for(;;)

References printTableContent::align, printTableContent::aligns, printTableContent::cell, printTableContent::cellmustfree, printTableContent::cells, printTableFooter::data, printTableContent::footer, printTableContent::footers, for(), free, printTableContent::header, printTableContent::headers, i, printTableContent::ncolumns, printTableFooter::next, printTableContent::nrows, printTableContent::opt, printTableContent::title, and unconstify.

Referenced by describeOneTableDetails(), describePublications(), describeRoles(), exec_command_conninfo(), printCrosstab(), and printQuery().

◆ printTableInit()

void printTableInit ( printTableContent *const  content,
const printTableOpt opt,
const char *  title,
const int  ncolumns,
const int  nrows 
)

Definition at line 3191 of file print.c.

3193{
3194 uint64 total_cells;
3195
3196 content->opt = opt;
3197 content->title = title;
3198 content->ncolumns = ncolumns;
3199 content->nrows = nrows;
3200
3201 content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers));
3202
3203 total_cells = (uint64) ncolumns * nrows;
3204 /* Catch possible overflow. Using >= here allows adding 1 below */
3205 if (total_cells >= SIZE_MAX / sizeof(*content->cells))
3206 {
3207 fprintf(stderr, _("Cannot print table contents: number of cells %" PRIu64 " is equal to or exceeds maximum %zu.\n"),
3208 total_cells,
3209 SIZE_MAX / sizeof(*content->cells));
3210 exit(EXIT_FAILURE);
3211 }
3212 content->cells = pg_malloc0((total_cells + 1) * sizeof(*content->cells));
3213
3214 content->cellmustfree = NULL;
3215 content->footers = NULL;
3216
3217 content->aligns = pg_malloc0((ncolumns + 1) * sizeof(*content->align));
3218
3219 content->header = content->headers;
3220 content->cell = content->cells;
3221 content->footer = content->footers;
3222 content->align = content->aligns;
3223 content->cellsadded = 0;
3224}

References _, printTableContent::align, printTableContent::aligns, printTableContent::cell, printTableContent::cellmustfree, printTableContent::cells, printTableContent::cellsadded, EXIT_FAILURE, printTableContent::footer, printTableContent::footers, fprintf, printTableContent::header, printTableContent::headers, printTableContent::ncolumns, printTableContent::nrows, printTableContent::opt, pg_malloc0(), and printTableContent::title.

Referenced by describeOneTableDetails(), describePublications(), describeRoles(), exec_command_conninfo(), printCrosstab(), and printQuery().

◆ printTableSetFooter()

void printTableSetFooter ( printTableContent *const  content,
const char *  footer 
)

Definition at line 3354 of file print.c.

3355{
3356 if (content->footers != NULL)
3357 {
3358 free(content->footer->data);
3359 content->footer->data = pg_strdup(footer);
3360 }
3361 else
3362 printTableAddFooter(content, footer);
3363}

References printTableFooter::data, printTableContent::footer, printTableContent::footers, free, pg_strdup(), and printTableAddFooter().

Referenced by add_tablespace_footer().

◆ refresh_utf8format()

void refresh_utf8format ( const printTableOpt opt)

Definition at line 3888 of file print.c.

3889{
3891
3892 const unicodeStyleBorderFormat *border;
3893 const unicodeStyleRowFormat *header;
3894 const unicodeStyleColumnFormat *column;
3895
3896 popt->name = "unicode";
3897
3901
3902 popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
3906
3907 popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
3911
3912 popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
3916
3917 /* N/A */
3918 popt->lrule[PRINT_RULE_DATA].hrule = "";
3919 popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
3920 popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
3921 popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
3922
3923 popt->midvrule_nl = column->vertical;
3924 popt->midvrule_wrap = column->vertical;
3925 popt->midvrule_blank = column->vertical;
3926
3927 /* Same for all unicode today */
3935}
static const unicodeStyleFormat unicode_style
Definition: print.c:145
printTextFormat pg_utf8format
Definition: print.c:104
unicode_linestyle unicode_border_linestyle
Definition: print.h:141
unicode_linestyle unicode_header_linestyle
Definition: print.h:143
unicode_linestyle unicode_column_linestyle
Definition: print.h:142
bool wrap_right_border
Definition: print.h:95
const char * nl_right
Definition: print.h:92
const char * wrap_left
Definition: print.h:93
const char * midvrule_blank
Definition: print.h:88
const char * header_nl_left
Definition: print.h:89
const char * nl_left
Definition: print.h:91
const char * midvrule_nl
Definition: print.h:86
const char * wrap_right
Definition: print.h:94
const char * midvrule_wrap
Definition: print.h:87
const char * name
Definition: print.h:84
const char * header_nl_right
Definition: print.h:90
const char * up_and_right
Definition: print.c:123
const char * left_and_right
Definition: print.c:128
const char * vertical
Definition: print.c:124
const char * down_and_left
Definition: print.c:127
const char * horizontal
Definition: print.c:126
const char * down_and_right
Definition: print.c:125
const char * vertical_and_horizontal[2]
Definition: print.c:116
const char * up_and_horizontal[2]
Definition: print.c:117
const char * vertical
Definition: print.c:115
const char * down_and_horizontal[2]
Definition: print.c:118
unicodeStyleRowFormat row_style[2]
Definition: print.c:133
unicodeStyleColumnFormat column_style[2]
Definition: print.c:134
const char * nl_right
Definition: print.c:139
const char * wrap_right
Definition: print.c:141
const char * header_nl_left
Definition: print.c:136
const char * header_nl_right
Definition: print.c:137
unicodeStyleBorderFormat border_style[2]
Definition: print.c:135
const char * nl_left
Definition: print.c:138
const char * wrap_left
Definition: print.c:140
bool wrap_right_border
Definition: print.c:142
const char * vertical_and_right[2]
Definition: print.c:109
const char * vertical_and_left[2]
Definition: print.c:110
const char * horizontal
Definition: print.c:108

References unicodeStyleFormat::border_style, unicodeStyleFormat::column_style, unicodeStyleColumnFormat::down_and_horizontal, unicodeStyleBorderFormat::down_and_left, unicodeStyleBorderFormat::down_and_right, unicodeStyleFormat::header_nl_left, printTextFormat::header_nl_left, unicodeStyleFormat::header_nl_right, printTextFormat::header_nl_right, unicodeStyleRowFormat::horizontal, unicodeStyleBorderFormat::horizontal, printTextLineFormat::hrule, unicodeStyleBorderFormat::left_and_right, printTextLineFormat::leftvrule, printTextFormat::lrule, printTextLineFormat::midvrule, printTextFormat::midvrule_blank, printTextFormat::midvrule_nl, printTextFormat::midvrule_wrap, printTextFormat::name, unicodeStyleFormat::nl_left, printTextFormat::nl_left, unicodeStyleFormat::nl_right, printTextFormat::nl_right, pg_utf8format, PRINT_RULE_BOTTOM, PRINT_RULE_DATA, PRINT_RULE_MIDDLE, PRINT_RULE_TOP, printTextLineFormat::rightvrule, unicodeStyleFormat::row_style, printTableOpt::unicode_border_linestyle, printTableOpt::unicode_column_linestyle, printTableOpt::unicode_header_linestyle, unicode_style, unicodeStyleColumnFormat::up_and_horizontal, unicodeStyleBorderFormat::up_and_right, unicodeStyleColumnFormat::vertical, unicodeStyleBorderFormat::vertical, unicodeStyleColumnFormat::vertical_and_horizontal, unicodeStyleRowFormat::vertical_and_left, unicodeStyleRowFormat::vertical_and_right, unicodeStyleFormat::wrap_left, printTextFormat::wrap_left, unicodeStyleFormat::wrap_right, printTextFormat::wrap_right, unicodeStyleFormat::wrap_right_border, and printTextFormat::wrap_right_border.

Referenced by do_pset(), and main().

◆ restore_sigpipe_trap()

void restore_sigpipe_trap ( void  )

Definition at line 3047 of file print.c.

3048{
3049#ifndef WIN32
3050 pqsignal(SIGPIPE, always_ignore_sigpipe ? SIG_IGN : SIG_DFL);
3051#endif
3052}
static bool always_ignore_sigpipe
Definition: print.c:50

References always_ignore_sigpipe, pqsignal, and SIGPIPE.

Referenced by CloseGOutput(), ClosePager(), do_copy(), do_watch(), exec_command_write(), PageOutputInternal(), and setQFout().

◆ set_sigpipe_trap_state()

void set_sigpipe_trap_state ( bool  ignore)

Definition at line 3060 of file print.c.

3061{
3062 always_ignore_sigpipe = ignore;
3063}

References always_ignore_sigpipe.

Referenced by setQFout().

◆ setDecimalLocale()

void setDecimalLocale ( void  )

Definition at line 3838 of file print.c.

3839{
3840 struct lconv *extlconv;
3841
3842 extlconv = localeconv();
3843
3844 /* Don't accept an empty decimal_point string */
3845 if (*extlconv->decimal_point)
3846 decimal_point = pg_strdup(extlconv->decimal_point);
3847 else
3848 decimal_point = "."; /* SQL output standard */
3849
3850 /*
3851 * Although the Open Group standard allows locales to supply more than one
3852 * group width, we consider only the first one, and we ignore any attempt
3853 * to suppress grouping by specifying CHAR_MAX. As in the backend's
3854 * cash.c, we must apply a range check to avoid being fooled by variant
3855 * CHAR_MAX values.
3856 */
3857 groupdigits = *extlconv->grouping;
3858 if (groupdigits <= 0 || groupdigits > 6)
3859 groupdigits = 3; /* most common */
3860
3861 /* Don't accept an empty thousands_sep string, either */
3862 /* similar code exists in formatting.c */
3863 if (*extlconv->thousands_sep)
3864 thousands_sep = pg_strdup(extlconv->thousands_sep);
3865 /* Make sure thousands separator doesn't match decimal point symbol. */
3866 else if (strcmp(decimal_point, ",") != 0)
3867 thousands_sep = ",";
3868 else
3869 thousands_sep = ".";
3870}

References decimal_point, groupdigits, pg_strdup(), and thousands_sep.

Referenced by main().

◆ strlen_max_width()

static int strlen_max_width ( unsigned char *  str,
int *  target_width,
int  encoding 
)
static

Definition at line 3943 of file print.c.

3944{
3945 unsigned char *start = str;
3946 unsigned char *end = str + strlen((char *) str);
3947 int curr_width = 0;
3948
3949 while (str < end)
3950 {
3951 int char_width = PQdsplen((char *) str, encoding);
3952
3953 /*
3954 * If the display width of the new character causes the string to
3955 * exceed its target width, skip it and return. However, if this is
3956 * the first character of the string (curr_width == 0), we have to
3957 * accept it.
3958 */
3959 if (*target_width < curr_width + char_width && curr_width != 0)
3960 break;
3961
3962 curr_width += char_width;
3963
3964 str += PQmblen((char *) str, encoding);
3965
3966 if (str > end) /* Don't overrun invalid string */
3967 str = end;
3968 }
3969
3970 *target_width = curr_width;
3971
3972 return str - start;
3973}
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1255
int PQdsplen(const char *s, int encoding)
Definition: fe-misc.c:1276
return str start

References encoding, PQdsplen(), PQmblen(), start, and str.

Referenced by print_aligned_text(), and print_aligned_vertical().

◆ troff_ms_escaped_print()

static void troff_ms_escaped_print ( const char *  in,
FILE *  fout 
)
static

Definition at line 2795 of file print.c.

2796{
2797 const char *p;
2798
2799 for (p = in; *p; p++)
2800 switch (*p)
2801 {
2802 case '\\':
2803 fputs("\\(rs", fout);
2804 break;
2805 default:
2806 fputc(*p, fout);
2807 }
2808}

Referenced by print_troff_ms_text(), and print_troff_ms_vertical().

Variable Documentation

◆ always_ignore_sigpipe

bool always_ignore_sigpipe = false
static

Definition at line 50 of file print.c.

Referenced by restore_sigpipe_trap(), and set_sigpipe_trap_state().

◆ cancel_pressed

◆ decimal_point

char* decimal_point
static

Definition at line 53 of file print.c.

Referenced by additional_numeric_locale_len(), format_numeric_locale(), and setDecimalLocale().

◆ default_footer

char default_footer[100]
static

Definition at line 57 of file print.c.

Referenced by footers_with_default().

◆ default_footer_cell

printTableFooter default_footer_cell = {default_footer, NULL}
static

Definition at line 58 of file print.c.

Referenced by footers_with_default().

◆ groupdigits

int groupdigits
static

Definition at line 54 of file print.c.

Referenced by additional_numeric_locale_len(), format_numeric_locale(), and setDecimalLocale().

◆ pg_asciiformat

const printTextFormat pg_asciiformat
Initial value:
=
{
"ascii",
{
{"-", "+", "+", "+"},
{"-", "+", "+", "+"},
{"-", "+", "+", "+"},
{"", "|", "|", "|"}
},
"|",
"|",
"|",
" ",
"+",
" ",
"+",
".",
".",
true
}

Definition at line 61 of file print.c.

Referenced by do_pset(), and get_line_style().

◆ pg_asciiformat_old

const printTextFormat pg_asciiformat_old
Initial value:
=
{
"old-ascii",
{
{"-", "+", "+", "+"},
{"-", "+", "+", "+"},
{"-", "+", "+", "+"},
{"", "|", "|", "|"}
},
":",
";",
" ",
"+",
" ",
" ",
" ",
" ",
" ",
false
}

Definition at line 82 of file print.c.

Referenced by do_pset(), and print_aligned_vertical().

◆ pg_utf8format

printTextFormat pg_utf8format

Definition at line 104 of file print.c.

Referenced by do_pset(), and refresh_utf8format().

◆ thousands_sep

char* thousands_sep
static

Definition at line 55 of file print.c.

Referenced by additional_numeric_locale_len(), format_numeric_locale(), and setDecimalLocale().

◆ unicode_style

const unicodeStyleFormat unicode_style
static

Definition at line 145 of file print.c.

Referenced by refresh_utf8format().