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 void IsPagerNeeded (const printTableContent *cont, int extra_lines, bool expanded, 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 593 of file print.c.

597{
598 const printTextLineFormat *lformat = &format->lrule[pos];
599 unsigned int i,
600 j;
601
602 if (border == 1)
603 fputs(lformat->hrule, fout);
604 else if (border == 2)
605 fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
606
607 for (i = 0; i < ncolumns; i++)
608 {
609 for (j = 0; j < widths[i]; j++)
610 fputs(lformat->hrule, fout);
611
612 if (i < ncolumns - 1)
613 {
614 if (border == 0)
615 fputc(' ', fout);
616 else
617 fprintf(fout, "%s%s%s", lformat->hrule,
618 lformat->midvrule, lformat->hrule);
619 }
620 }
621
622 if (border == 2)
623 fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
624 else if (border == 1)
625 fputs(lformat->hrule, fout);
626
627 fputc('\n', fout);
628}
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
int j
Definition: isn.c:73
int i
Definition: isn.c:72
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 289 of file print.c.

290{
291 int int_len = integer_digits(my_str),
292 len = 0;
293
294 /* Account for added thousands_sep instances */
295 if (int_len > groupdigits)
296 len += ((int_len - 1) / groupdigits) * strlen(thousands_sep);
297
298 /* Account for possible additional length of decimal_point */
299 if (strchr(my_str, '.') != NULL)
300 len += strlen(decimal_point) - 1;
301
302 return len;
303}
static char * thousands_sep
Definition: print.c:50
static char * decimal_point
Definition: print.c:48
static int integer_digits(const char *my_str)
Definition: print.c:278
static int groupdigits
Definition: print.c:49
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 2168 of file print.c.

2169{
2170 const char *p;
2171
2172 for (p = in; *p; p++)
2173 {
2174 switch (*p)
2175 {
2176 case '|':
2177 fputs("\\|", fout);
2178 break;
2179 default:
2180 fputc(*p, fout);
2181 }
2182 }
2183}

Referenced by print_asciidoc_text(), and print_asciidoc_vertical().

◆ ClosePager()

void ClosePager ( FILE *  pagerpipe)

Definition at line 3141 of file print.c.

3142{
3143 if (pagerpipe && pagerpipe != stdout)
3144 {
3145 /*
3146 * If printing was canceled midstream, warn about it.
3147 *
3148 * Some pagers like less use Ctrl-C as part of their command set. Even
3149 * so, we abort our processing and warn the user what we did. If the
3150 * pager quit as a result of the SIGINT, this message won't go
3151 * anywhere ...
3152 */
3153 if (cancel_pressed)
3154 fprintf(pagerpipe, _("Interrupted\n"));
3155
3156 pclose(pagerpipe);
3158 }
3159}
#define _(x)
Definition: elog.c:90
void restore_sigpipe_trap(void)
Definition: print.c:3062
volatile sig_atomic_t cancel_pressed
Definition: print.c:43

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 3614 of file print.c.

3615{
3616 char align;
3617
3618 switch (ftype)
3619 {
3620 case INT2OID:
3621 case INT4OID:
3622 case INT8OID:
3623 case FLOAT4OID:
3624 case FLOAT8OID:
3625 case NUMERICOID:
3626 case OIDOID:
3627 case XIDOID:
3628 case XID8OID:
3629 case CIDOID:
3630 case MONEYOID:
3631 align = 'r';
3632 break;
3633 default:
3634 align = 'l';
3635 break;
3636 }
3637 return align;
3638}

Referenced by printCrosstab(), and printQuery().

◆ csv_escaped_print()

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

Definition at line 1840 of file print.c.

1841{
1842 const char *p;
1843
1844 fputc('"', fout);
1845 for (p = str; *p; p++)
1846 {
1847 if (*p == '"')
1848 fputc('"', fout); /* double quotes are doubled */
1849 fputc(*p, fout);
1850 }
1851 fputc('"', fout);
1852}
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 1855 of file print.c.

1856{
1857 /*----------------
1858 * Enclose and escape field contents when one of these conditions is met:
1859 * - the field separator is found in the contents.
1860 * - the field contains a CR or LF.
1861 * - the field contains a double quote.
1862 * - the field is exactly "\.".
1863 * - the field separator is either "\" or ".".
1864 * The last two cases prevent producing a line that the server's COPY
1865 * command would interpret as an end-of-data marker. We only really
1866 * need to ensure that the complete line isn't exactly "\.", but for
1867 * simplicity we apply stronger restrictions here.
1868 *----------------
1869 */
1870 if (strchr(str, sep) != NULL ||
1871 strcspn(str, "\r\n\"") != strlen(str) ||
1872 strcmp(str, "\\.") == 0 ||
1873 sep == '\\' || sep == '.')
1874 csv_escaped_print(str, fout);
1875 else
1876 fputs(str, fout);
1877}
static void csv_escaped_print(const char *str, FILE *fout)
Definition: print.c:1840

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 3039 of file print.c.

3040{
3041#ifndef WIN32
3042 pqsignal(SIGPIPE, SIG_IGN);
3043#endif
3044}
#define pqsignal
Definition: port.h:521
#define SIGPIPE
Definition: win32_port.h:163

References pqsignal, and SIGPIPE.

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

◆ footers_with_default()

static printTableFooter * footers_with_default ( const printTableContent cont)
static

Definition at line 398 of file print.c.

399{
400 if (cont->footers == NULL && cont->opt->default_footer)
401 {
402 unsigned long total_records;
403
404 total_records = cont->opt->prior_records + cont->nrows;
406 ngettext("(%lu row)", "(%lu rows)", total_records),
407 total_records);
408
409 return &default_footer_cell;
410 }
411 else
412 return cont->footers;
413}
#define ngettext(s, p, n)
Definition: c.h:1138
static char default_footer[100]
Definition: print.c:52
static printTableFooter default_footer_cell
Definition: print.c:53
#define snprintf
Definition: port.h:239
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 314 of file print.c.

315{
316 char *new_str;
317 int new_len,
318 int_len,
319 leading_digits,
320 i,
321 new_str_pos;
322
323 /*
324 * If the string doesn't look like a number, return it unchanged. This
325 * check is essential to avoid mangling already-localized "money" values.
326 */
327 if (strspn(my_str, "0123456789+-.eE") != strlen(my_str))
328 return pg_strdup(my_str);
329
330 new_len = strlen(my_str) + additional_numeric_locale_len(my_str);
331 new_str = pg_malloc(new_len + 1);
332 new_str_pos = 0;
333 int_len = integer_digits(my_str);
334
335 /* number of digits in first thousands group */
336 leading_digits = int_len % groupdigits;
337 if (leading_digits == 0)
338 leading_digits = groupdigits;
339
340 /* process sign */
341 if (my_str[0] == '-' || my_str[0] == '+')
342 {
343 new_str[new_str_pos++] = my_str[0];
344 my_str++;
345 }
346
347 /* process integer part of number */
348 for (i = 0; i < int_len; i++)
349 {
350 /* Time to insert separator? */
351 if (i > 0 && --leading_digits == 0)
352 {
353 strcpy(&new_str[new_str_pos], thousands_sep);
354 new_str_pos += strlen(thousands_sep);
355 leading_digits = groupdigits;
356 }
357 new_str[new_str_pos++] = my_str[i];
358 }
359
360 /* handle decimal point if any */
361 if (my_str[i] == '.')
362 {
363 strcpy(&new_str[new_str_pos], decimal_point);
364 new_str_pos += strlen(decimal_point);
365 i++;
366 }
367
368 /* copy the rest (fractional digits and/or exponent, and \0 terminator) */
369 strcpy(&new_str[new_str_pos], &my_str[i]);
370
371 /* assert we didn't underestimate new_len (an overestimate is OK) */
372 Assert(strlen(new_str) <= new_len);
373
374 return new_str;
375}
#define Assert(condition)
Definition: c.h:815
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:289

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 3677 of file print.c.

3678{
3679 /*
3680 * Note: this function mainly exists to preserve the convention that a
3681 * printTableOpt struct can be initialized to zeroes to get default
3682 * behavior.
3683 */
3684 if (opt->line_style != NULL)
3685 return opt->line_style;
3686 else
3687 return &pg_asciiformat;
3688}
const printTextFormat pg_asciiformat
Definition: print.c:56
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 1952 of file print.c.

1953{
1954 const char *p;
1955 bool leading_space = true;
1956
1957 for (p = in; *p; p++)
1958 {
1959 switch (*p)
1960 {
1961 case '&':
1962 fputs("&amp;", fout);
1963 break;
1964 case '<':
1965 fputs("&lt;", fout);
1966 break;
1967 case '>':
1968 fputs("&gt;", fout);
1969 break;
1970 case '\n':
1971 fputs("<br />\n", fout);
1972 break;
1973 case '"':
1974 fputs("&quot;", fout);
1975 break;
1976 case ' ':
1977 /* protect leading space, for EXPLAIN output */
1978 if (leading_space)
1979 fputs("&nbsp;", fout);
1980 else
1981 fputs(" ", fout);
1982 break;
1983 default:
1984 fputc(*p, fout);
1985 }
1986 if (*p != ' ')
1987 leading_space = false;
1988 }
1989}

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

◆ integer_digits()

static int integer_digits ( const char *  my_str)
static

Definition at line 278 of file print.c.

279{
280 /* ignoring any sign ... */
281 if (my_str[0] == '-' || my_str[0] == '+')
282 my_str++;
283 /* ... count initial integral digits */
284 return strspn(my_str, "0123456789");
285}

Referenced by additional_numeric_locale_len(), and format_numeric_locale().

◆ IsPagerNeeded()

static void IsPagerNeeded ( const printTableContent cont,
int  extra_lines,
bool  expanded,
FILE **  fout,
bool *  is_pager 
)
static

Definition at line 3403 of file print.c.

3405{
3406 if (*fout == stdout)
3407 {
3408 int lines;
3409
3410 if (expanded)
3411 lines = (cont->ncolumns + 1) * cont->nrows;
3412 else
3413 lines = cont->nrows + 1;
3414
3415 if (!cont->opt->tuples_only)
3416 {
3418
3419 /*
3420 * FIXME -- this is slightly bogus: it counts the number of
3421 * footers, not the number of lines in them.
3422 */
3423 for (f = cont->footers; f; f = f->next)
3424 lines++;
3425 }
3426
3427 *fout = PageOutput(lines + extra_lines, cont->opt);
3428 *is_pager = (*fout != stdout);
3429 }
3430 else
3431 *is_pager = false;
3432}
FILE * PageOutput(int lines, const printTableOpt *topt)
Definition: print.c:3089
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
struct printTableFooter * next
Definition: print.h:156
bool tuples_only
Definition: print.h:126

References printTableContent::footers, if(), printTableContent::ncolumns, printTableFooter::next, printTableContent::nrows, printTableContent::opt, PageOutput(), generate_unaccent_rules::stdout, and printTableOpt::tuples_only.

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 2392 of file print.c.

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

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

◆ PageOutput()

FILE * PageOutput ( int  lines,
const printTableOpt topt 
)

Definition at line 3089 of file print.c.

3090{
3091 /* check whether we need / can / are supposed to use pager */
3092 if (topt && topt->pager && isatty(fileno(stdin)) && isatty(fileno(stdout)))
3093 {
3094#ifdef TIOCGWINSZ
3095 unsigned short int pager = topt->pager;
3096 int min_lines = topt->pager_min_lines;
3097 int result;
3098 struct winsize screen_size;
3099
3100 result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
3101
3102 /* >= accounts for a one-line prompt */
3103 if (result == -1
3104 || (lines >= screen_size.ws_row && lines >= min_lines)
3105 || pager > 1)
3106#endif
3107 {
3108 const char *pagerprog;
3109 FILE *pagerpipe;
3110
3111 pagerprog = getenv("PSQL_PAGER");
3112 if (!pagerprog)
3113 pagerprog = getenv("PAGER");
3114 if (!pagerprog)
3115 pagerprog = DEFAULT_PAGER;
3116 else
3117 {
3118 /* if PAGER is empty or all-white-space, don't use pager */
3119 if (strspn(pagerprog, " \t\r\n") == strlen(pagerprog))
3120 return stdout;
3121 }
3122 fflush(NULL);
3124 pagerpipe = popen(pagerprog, "w");
3125 if (pagerpipe)
3126 return pagerpipe;
3127 /* if popen fails, silently proceed without pager */
3129 }
3130 }
3131
3132 return stdout;
3133}
void disable_sigpipe_trap(void)
Definition: print.c:3039
#define DEFAULT_PAGER
Definition: print.h:23
static void const char fflush(stdout)
int pager_min_lines
Definition: print.h:124
unsigned short int pager
Definition: print.h:122

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

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

◆ print_aligned_text()

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

Definition at line 635 of file print.c.

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

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

1232{
1233 const printTextLineFormat *lformat = &get_line_style(topt)->lrule[pos];
1234 const unsigned short opt_border = topt->border;
1235 unsigned int i;
1236 int reclen = 0;
1237
1238 if (opt_border == 2)
1239 fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
1240 else if (opt_border == 1)
1241 fputs(lformat->hrule, fout);
1242
1243 if (record)
1244 {
1245 if (opt_border == 0)
1246 reclen = fprintf(fout, "* Record %lu", record);
1247 else
1248 reclen = fprintf(fout, "[ RECORD %lu ]", record);
1249 }
1250 if (opt_border != 2)
1251 reclen++;
1252 if (reclen < 0)
1253 reclen = 0;
1254 for (i = reclen; i < hwidth; i++)
1255 fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1256 reclen -= hwidth;
1257
1258 if (opt_border > 0)
1259 {
1260 if (reclen-- <= 0)
1261 fputs(lformat->hrule, fout);
1262 if (reclen-- <= 0)
1263 {
1265 {
1266 fputs(lformat->rightvrule, fout);
1267 }
1268 else
1269 {
1270 fputs(lformat->midvrule, fout);
1271 }
1272 }
1273 if (reclen-- <= 0
1275 fputs(lformat->hrule, fout);
1276 }
1277 else
1278 {
1279 if (reclen-- <= 0)
1280 fputc(' ', fout);
1281 }
1282
1284 {
1287 {
1289 {
1290 output_columns = topt->expanded_header_exact_width;
1291 }
1292 if (output_columns > 0)
1293 {
1294 if (opt_border == 0)
1295 dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth)));
1296 if (opt_border == 1)
1297 dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth - 3)));
1298
1299 /*
1300 * Handling the xheader width for border=2 doesn't make much
1301 * sense because this format has an additional right border,
1302 * but keep this for consistency.
1303 */
1304 if (opt_border == 2)
1305 dwidth = Min(dwidth, Max(0, (int) (output_columns - hwidth - 7)));
1306 }
1307 }
1308
1309 if (reclen < 0)
1310 reclen = 0;
1311 if (dwidth < reclen)
1312 dwidth = reclen;
1313
1314 for (i = reclen; i < dwidth; i++)
1315 fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1316 if (opt_border == 2)
1317 fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
1318 }
1319
1320 fputc('\n', fout);
1321}
#define Min(x, y)
Definition: c.h:961
#define Max(x, y)
Definition: c.h:955
@ 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 2186 of file print.c.

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

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 2296 of file print.c.

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

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 1880 of file print.c.

1881{
1882 const char *const *ptr;
1883 int i;
1884
1885 if (cancel_pressed)
1886 return;
1887
1888 /*
1889 * The title and footer are never printed in csv format. The header is
1890 * printed if opt_tuples_only is false.
1891 *
1892 * Despite RFC 4180 saying that end of lines are CRLF, terminate lines
1893 * with '\n', which prints out as the system-dependent EOL string in text
1894 * mode (typically LF on Unix and CRLF on Windows).
1895 */
1896 if (cont->opt->start_table && !cont->opt->tuples_only)
1897 {
1898 /* print headers */
1899 for (ptr = cont->headers; *ptr; ptr++)
1900 {
1901 if (ptr != cont->headers)
1902 fputc(cont->opt->csvFieldSep[0], fout);
1903 csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1904 }
1905 fputc('\n', fout);
1906 }
1907
1908 /* print cells */
1909 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1910 {
1911 csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1912 if ((i + 1) % cont->ncolumns)
1913 fputc(cont->opt->csvFieldSep[0], fout);
1914 else
1915 fputc('\n', fout);
1916 }
1917}
static void csv_print_field(const char *str, FILE *fout, char sep)
Definition: print.c:1855
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 1920 of file print.c.

1921{
1922 const char *const *ptr;
1923 int i;
1924
1925 /* print records */
1926 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1927 {
1928 if (cancel_pressed)
1929 return;
1930
1931 /* print name of column */
1932 csv_print_field(cont->headers[i % cont->ncolumns], fout,
1933 cont->opt->csvFieldSep[0]);
1934
1935 /* print field separator */
1936 fputc(cont->opt->csvFieldSep[0], fout);
1937
1938 /* print field value */
1939 csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1940
1941 fputc('\n', fout);
1942 }
1943}

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 1993 of file print.c.

1994{
1995 bool opt_tuples_only = cont->opt->tuples_only;
1996 unsigned short opt_border = cont->opt->border;
1997 const char *opt_table_attr = cont->opt->tableAttr;
1998 unsigned int i;
1999 const char *const *ptr;
2000
2001 if (cancel_pressed)
2002 return;
2003
2004 if (cont->opt->start_table)
2005 {
2006 fprintf(fout, "<table border=\"%d\"", opt_border);
2007 if (opt_table_attr)
2008 fprintf(fout, " %s", opt_table_attr);
2009 fputs(">\n", fout);
2010
2011 /* print title */
2012 if (!opt_tuples_only && cont->title)
2013 {
2014 fputs(" <caption>", fout);
2015 html_escaped_print(cont->title, fout);
2016 fputs("</caption>\n", fout);
2017 }
2018
2019 /* print headers */
2020 if (!opt_tuples_only)
2021 {
2022 fputs(" <tr>\n", fout);
2023 for (ptr = cont->headers; *ptr; ptr++)
2024 {
2025 fputs(" <th align=\"center\">", fout);
2026 html_escaped_print(*ptr, fout);
2027 fputs("</th>\n", fout);
2028 }
2029 fputs(" </tr>\n", fout);
2030 }
2031 }
2032
2033 /* print cells */
2034 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2035 {
2036 if (i % cont->ncolumns == 0)
2037 {
2038 if (cancel_pressed)
2039 break;
2040 fputs(" <tr valign=\"top\">\n", fout);
2041 }
2042
2043 fprintf(fout, " <td align=\"%s\">", cont->aligns[(i) % cont->ncolumns] == 'r' ? "right" : "left");
2044 /* is string only whitespace? */
2045 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2046 fputs("&nbsp; ", fout);
2047 else
2048 html_escaped_print(*ptr, fout);
2049
2050 fputs("</td>\n", fout);
2051
2052 if ((i + 1) % cont->ncolumns == 0)
2053 fputs(" </tr>\n", fout);
2054 }
2055
2056 if (cont->opt->stop_table)
2057 {
2058 printTableFooter *footers = footers_with_default(cont);
2059
2060 fputs("</table>\n", fout);
2061
2062 /* print footers */
2063 if (!opt_tuples_only && footers != NULL && !cancel_pressed)
2064 {
2066
2067 fputs("<p>", fout);
2068 for (f = footers; f; f = f->next)
2069 {
2070 html_escaped_print(f->data, fout);
2071 fputs("<br />\n", fout);
2072 }
2073 fputs("</p>", fout);
2074 }
2075
2076 fputc('\n', fout);
2077 }
2078}
void html_escaped_print(const char *in, FILE *fout)
Definition: print.c:1952
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 2082 of file print.c.

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

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 2561 of file print.c.

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

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 2454 of file print.c.

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

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 2717 of file print.c.

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

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 379 of file print.c.

380{
381 if (sep.separator_zero)
382 fputc('\000', fout);
383 else if (sep.separator)
384 fputs(sep.separator, fout);
385}
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 2827 of file print.c.

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

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 2919 of file print.c.

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

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 422 of file print.c.

423{
424 bool opt_tuples_only = cont->opt->tuples_only;
425 unsigned int i;
426 const char *const *ptr;
427 bool need_recordsep = false;
428
429 if (cancel_pressed)
430 return;
431
432 if (cont->opt->start_table)
433 {
434 /* print title */
435 if (!opt_tuples_only && cont->title)
436 {
437 fputs(cont->title, fout);
438 print_separator(cont->opt->recordSep, fout);
439 }
440
441 /* print headers */
442 if (!opt_tuples_only)
443 {
444 for (ptr = cont->headers; *ptr; ptr++)
445 {
446 if (ptr != cont->headers)
447 print_separator(cont->opt->fieldSep, fout);
448 fputs(*ptr, fout);
449 }
450 need_recordsep = true;
451 }
452 }
453 else
454 /* assume continuing printout */
455 need_recordsep = true;
456
457 /* print cells */
458 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
459 {
460 if (need_recordsep)
461 {
462 print_separator(cont->opt->recordSep, fout);
463 need_recordsep = false;
464 if (cancel_pressed)
465 break;
466 }
467 fputs(*ptr, fout);
468
469 if ((i + 1) % cont->ncolumns)
470 print_separator(cont->opt->fieldSep, fout);
471 else
472 need_recordsep = true;
473 }
474
475 /* print footers */
476 if (cont->opt->stop_table)
477 {
478 printTableFooter *footers = footers_with_default(cont);
479
480 if (!opt_tuples_only && footers != NULL && !cancel_pressed)
481 {
483
484 for (f = footers; f; f = f->next)
485 {
486 if (need_recordsep)
487 {
488 print_separator(cont->opt->recordSep, fout);
489 need_recordsep = false;
490 }
491 fputs(f->data, fout);
492 need_recordsep = true;
493 }
494 }
495
496 /*
497 * The last record is terminated by a newline, independent of the set
498 * record separator. But when the record separator is a zero byte, we
499 * use that (compatible with find -print0 and xargs).
500 */
501 if (need_recordsep)
502 {
503 if (cont->opt->recordSep.separator_zero)
504 print_separator(cont->opt->recordSep, fout);
505 else
506 fputc('\n', fout);
507 }
508 }
509}
static void print_separator(struct separator sep, FILE *fout)
Definition: print.c:379
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 513 of file print.c.

514{
515 bool opt_tuples_only = cont->opt->tuples_only;
516 unsigned int i;
517 const char *const *ptr;
518 bool need_recordsep = false;
519
520 if (cancel_pressed)
521 return;
522
523 if (cont->opt->start_table)
524 {
525 /* print title */
526 if (!opt_tuples_only && cont->title)
527 {
528 fputs(cont->title, fout);
529 need_recordsep = true;
530 }
531 }
532 else
533 /* assume continuing printout */
534 need_recordsep = true;
535
536 /* print records */
537 for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
538 {
539 if (need_recordsep)
540 {
541 /* record separator is 2 occurrences of recordsep in this mode */
542 print_separator(cont->opt->recordSep, fout);
543 print_separator(cont->opt->recordSep, fout);
544 need_recordsep = false;
545 if (cancel_pressed)
546 break;
547 }
548
549 fputs(cont->headers[i % cont->ncolumns], fout);
550 print_separator(cont->opt->fieldSep, fout);
551 fputs(*ptr, fout);
552
553 if ((i + 1) % cont->ncolumns)
554 print_separator(cont->opt->recordSep, fout);
555 else
556 need_recordsep = true;
557 }
558
559 if (cont->opt->stop_table)
560 {
561 /* print footers */
562 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
563 {
565
566 print_separator(cont->opt->recordSep, fout);
567 for (f = cont->footers; f; f = f->next)
568 {
569 print_separator(cont->opt->recordSep, fout);
570 fputs(f->data, fout);
571 }
572 }
573
574 /* see above in print_unaligned_text() */
575 if (need_recordsep)
576 {
577 if (cont->opt->recordSep.separator_zero)
578 print_separator(cont->opt->recordSep, fout);
579 else
580 fputc('\n', fout);
581 }
582 }
583}

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 3549 of file print.c.

3551{
3552 printTableContent cont;
3553 int i,
3554 r,
3555 c;
3556
3557 if (cancel_pressed)
3558 return;
3559
3560 printTableInit(&cont, &opt->topt, opt->title,
3561 PQnfields(result), PQntuples(result));
3562
3563 /* Assert caller supplied enough translate_columns[] entries */
3564 Assert(opt->translate_columns == NULL ||
3565 opt->n_translate_columns >= cont.ncolumns);
3566
3567 for (i = 0; i < cont.ncolumns; i++)
3568 {
3569 printTableAddHeader(&cont, PQfname(result, i),
3570 opt->translate_header,
3571 column_type_alignment(PQftype(result, i)));
3572 }
3573
3574 /* set cells */
3575 for (r = 0; r < cont.nrows; r++)
3576 {
3577 for (c = 0; c < cont.ncolumns; c++)
3578 {
3579 char *cell;
3580 bool mustfree = false;
3581 bool translate;
3582
3583 if (PQgetisnull(result, r, c))
3584 cell = opt->nullPrint ? opt->nullPrint : "";
3585 else
3586 {
3587 cell = PQgetvalue(result, r, c);
3588 if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
3589 {
3590 cell = format_numeric_locale(cell);
3591 mustfree = true;
3592 }
3593 }
3594
3596 printTableAddCell(&cont, cell, translate, mustfree);
3597 }
3598 }
3599
3600 /* set footers */
3601 if (opt->footers)
3602 {
3603 char **footer;
3604
3605 for (footer = opt->footers; *footer; footer++)
3606 printTableAddFooter(&cont, *footer);
3607 }
3608
3609 printTable(&cont, fout, is_pager, flog);
3610 printTableCleanup(&cont);
3611}
Oid PQftype(const PGresult *res, int field_num)
Definition: fe-exec.c:3719
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
char * PQfname(const PGresult *res, int field_num)
Definition: fe-exec.c:3567
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3901
int PQnfields(const PGresult *res)
Definition: fe-exec.c:3489
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition: print.c:3172
void printTableCleanup(printTableContent *const content)
Definition: print.c:3353
char column_type_alignment(Oid ftype)
Definition: print.c:3614
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3260
static char * format_numeric_locale(const char *my_str)
Definition: print.c:314
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3443
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3310
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:3220
Datum translate(PG_FUNCTION_ARGS)
char * c
const bool * translate_columns
Definition: print.h:190
printTableOpt topt
Definition: print.h:185
char * nullPrint
Definition: print.h:186
char * title
Definition: print.h:187
char ** footers
Definition: print.h:188
bool translate_header
Definition: print.h:189
int n_translate_columns
Definition: print.h:192
bool numericLocale
Definition: print.h:135

References printTableContent::aligns, Assert, cancel_pressed, column_type_alignment(), 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, and printQueryOpt::translate_header.

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 3443 of file print.c.

3445{
3446 bool is_local_pager = false;
3447
3448 if (cancel_pressed)
3449 return;
3450
3451 if (cont->opt->format == PRINT_NOTHING)
3452 return;
3453
3454 /* print_aligned_*() handle the pager themselves */
3455 if (!is_pager &&
3456 cont->opt->format != PRINT_ALIGNED &&
3457 cont->opt->format != PRINT_WRAPPED)
3458 {
3459 IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager);
3460 is_local_pager = is_pager;
3461 }
3462
3463 /* clear any pre-existing error indication on the output stream */
3464 clearerr(fout);
3465
3466 /* print the stuff */
3467
3468 if (flog)
3469 print_aligned_text(cont, flog, false);
3470
3471 switch (cont->opt->format)
3472 {
3473 case PRINT_UNALIGNED:
3474 if (cont->opt->expanded == 1)
3475 print_unaligned_vertical(cont, fout);
3476 else
3477 print_unaligned_text(cont, fout);
3478 break;
3479 case PRINT_ALIGNED:
3480 case PRINT_WRAPPED:
3481
3482 /*
3483 * In expanded-auto mode, force vertical if a pager is passed in;
3484 * else we may make different decisions for different hunks of the
3485 * query result.
3486 */
3487 if (cont->opt->expanded == 1 ||
3488 (cont->opt->expanded == 2 && is_pager))
3489 print_aligned_vertical(cont, fout, is_pager);
3490 else
3491 print_aligned_text(cont, fout, is_pager);
3492 break;
3493 case PRINT_CSV:
3494 if (cont->opt->expanded == 1)
3495 print_csv_vertical(cont, fout);
3496 else
3497 print_csv_text(cont, fout);
3498 break;
3499 case PRINT_HTML:
3500 if (cont->opt->expanded == 1)
3501 print_html_vertical(cont, fout);
3502 else
3503 print_html_text(cont, fout);
3504 break;
3505 case PRINT_ASCIIDOC:
3506 if (cont->opt->expanded == 1)
3507 print_asciidoc_vertical(cont, fout);
3508 else
3509 print_asciidoc_text(cont, fout);
3510 break;
3511 case PRINT_LATEX:
3512 if (cont->opt->expanded == 1)
3513 print_latex_vertical(cont, fout);
3514 else
3515 print_latex_text(cont, fout);
3516 break;
3518 if (cont->opt->expanded == 1)
3519 print_latex_vertical(cont, fout);
3520 else
3521 print_latex_longtable_text(cont, fout);
3522 break;
3523 case PRINT_TROFF_MS:
3524 if (cont->opt->expanded == 1)
3525 print_troff_ms_vertical(cont, fout);
3526 else
3527 print_troff_ms_text(cont, fout);
3528 break;
3529 default:
3530 fprintf(stderr, _("invalid output format (internal error): %d"),
3531 cont->opt->format);
3533 }
3534
3535 if (is_local_pager)
3536 ClosePager(fout);
3537}
static void print_asciidoc_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2186
static void print_unaligned_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:513
static void print_latex_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2454
static void print_troff_ms_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2827
static void print_html_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1993
static void print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2919
static void print_csv_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1880
static void print_aligned_text(const printTableContent *cont, FILE *fout, bool is_pager)
Definition: print.c:635
static void print_csv_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:1920
static void print_html_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2082
static void print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2296
static void print_unaligned_text(const printTableContent *cont, FILE *fout)
Definition: print.c:422
static void print_latex_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2717
static void print_latex_longtable_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2561
@ 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
exit(1)
#define EXIT_FAILURE
Definition: settings.h:178

References _, cancel_pressed, ClosePager(), exit(), 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(), printCrosstab(), and printQuery().

◆ printTableAddCell()

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

Definition at line 3260 of file print.c.

3262{
3263 uint64 total_cells;
3264
3265#ifndef ENABLE_NLS
3266 (void) translate; /* unused parameter */
3267#endif
3268
3269 total_cells = (uint64) content->ncolumns * content->nrows;
3270 if (content->cellsadded >= total_cells)
3271 {
3272 fprintf(stderr, _("Cannot add cell to table content: total cell count of %lld exceeded.\n"),
3273 (long long int) total_cells);
3275 }
3276
3277 *content->cell = (char *) mbvalidate((unsigned char *) cell,
3278 content->opt->encoding);
3279
3280#ifdef ENABLE_NLS
3281 if (translate)
3282 *content->cell = _(*content->cell);
3283#endif
3284
3285 if (mustfree)
3286 {
3287 if (content->cellmustfree == NULL)
3288 content->cellmustfree =
3289 pg_malloc0((total_cells + 1) * sizeof(bool));
3290
3291 content->cellmustfree[content->cellsadded] = true;
3292 }
3293 content->cell++;
3294 content->cellsadded++;
3295}
uint64_t uint64
Definition: c.h:489
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(), EXIT_FAILURE, fprintf, if(), mbvalidate(), printTableContent::ncolumns, printTableContent::nrows, printTableContent::opt, pg_malloc0(), and translate().

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

◆ printTableAddFooter()

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

Definition at line 3310 of file print.c.

3311{
3313
3314 f = pg_malloc0(sizeof(*f));
3315 f->data = pg_strdup(footer);
3316
3317 if (content->footers == NULL)
3318 content->footers = f;
3319 else
3320 content->footer->next = f;
3321
3322 content->footer = f;
3323}
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 3220 of file print.c.

3222{
3223#ifndef ENABLE_NLS
3224 (void) translate; /* unused parameter */
3225#endif
3226
3227 if (content->header >= content->headers + content->ncolumns)
3228 {
3229 fprintf(stderr, _("Cannot add header to table content: "
3230 "column count of %d exceeded.\n"),
3231 content->ncolumns);
3233 }
3234
3235 *content->header = (char *) mbvalidate((unsigned char *) header,
3236 content->opt->encoding);
3237#ifdef ENABLE_NLS
3238 if (translate)
3239 *content->header = _(*content->header);
3240#endif
3241 content->header++;
3242
3243 *content->align = align;
3244 content->align++;
3245}
char * align
Definition: print.h:180
const char ** header
Definition: print.h:170

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

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

◆ printTableCleanup()

void printTableCleanup ( printTableContent *const  content)

Definition at line 3353 of file print.c.

3354{
3355 if (content->cellmustfree)
3356 {
3357 uint64 total_cells;
3358
3359 total_cells = (uint64) content->ncolumns * content->nrows;
3360 for (uint64 i = 0; i < total_cells; i++)
3361 {
3362 if (content->cellmustfree[i])
3363 free(unconstify(char *, content->cells[i]));
3364 }
3365 free(content->cellmustfree);
3366 content->cellmustfree = NULL;
3367 }
3368 free(content->headers);
3369 free(content->cells);
3370 free(content->aligns);
3371
3372 content->opt = NULL;
3373 content->title = NULL;
3374 content->headers = NULL;
3375 content->cells = NULL;
3376 content->aligns = NULL;
3377 content->header = NULL;
3378 content->cell = NULL;
3379 content->align = NULL;
3380
3381 if (content->footers)
3382 {
3383 for (content->footer = content->footers; content->footer;)
3384 {
3386
3387 f = content->footer;
3388 content->footer = f->next;
3389 free(f->data);
3390 free(f);
3391 }
3392 }
3393 content->footers = NULL;
3394 content->footer = NULL;
3395}
#define unconstify(underlying_type, expr)
Definition: c.h:1202
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(), printCrosstab(), and printQuery().

◆ printTableInit()

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

Definition at line 3172 of file print.c.

3174{
3175 uint64 total_cells;
3176
3177 content->opt = opt;
3178 content->title = title;
3179 content->ncolumns = ncolumns;
3180 content->nrows = nrows;
3181
3182 content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers));
3183
3184 total_cells = (uint64) ncolumns * nrows;
3185 /* Catch possible overflow. Using >= here allows adding 1 below */
3186 if (total_cells >= SIZE_MAX / sizeof(*content->cells))
3187 {
3188 fprintf(stderr, _("Cannot print table contents: number of cells %lld is equal to or exceeds maximum %lld.\n"),
3189 (long long int) total_cells,
3190 (long long int) (SIZE_MAX / sizeof(*content->cells)));
3192 }
3193 content->cells = pg_malloc0((total_cells + 1) * sizeof(*content->cells));
3194
3195 content->cellmustfree = NULL;
3196 content->footers = NULL;
3197
3198 content->aligns = pg_malloc0((ncolumns + 1) * sizeof(*content->align));
3199
3200 content->header = content->headers;
3201 content->cell = content->cells;
3202 content->footer = content->footers;
3203 content->align = content->aligns;
3204 content->cellsadded = 0;
3205}

References _, printTableContent::align, printTableContent::aligns, printTableContent::cell, printTableContent::cellmustfree, printTableContent::cells, printTableContent::cellsadded, exit(), 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(), printCrosstab(), and printQuery().

◆ printTableSetFooter()

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

Definition at line 3335 of file print.c.

3336{
3337 if (content->footers != NULL)
3338 {
3339 free(content->footer->data);
3340 content->footer->data = pg_strdup(footer);
3341 }
3342 else
3343 printTableAddFooter(content, footer);
3344}

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 3691 of file print.c.

3692{
3694
3695 const unicodeStyleBorderFormat *border;
3696 const unicodeStyleRowFormat *header;
3697 const unicodeStyleColumnFormat *column;
3698
3699 popt->name = "unicode";
3700
3704
3705 popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
3709
3710 popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
3714
3715 popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
3719
3720 /* N/A */
3721 popt->lrule[PRINT_RULE_DATA].hrule = "";
3722 popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
3723 popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
3724 popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
3725
3726 popt->midvrule_nl = column->vertical;
3727 popt->midvrule_wrap = column->vertical;
3728 popt->midvrule_blank = column->vertical;
3729
3730 /* Same for all unicode today */
3738}
static const unicodeStyleFormat unicode_style
Definition: print.c:140
printTextFormat pg_utf8format
Definition: print.c:99
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:118
const char * left_and_right
Definition: print.c:123
const char * vertical
Definition: print.c:119
const char * down_and_left
Definition: print.c:122
const char * horizontal
Definition: print.c:121
const char * down_and_right
Definition: print.c:120
const char * vertical_and_horizontal[2]
Definition: print.c:111
const char * up_and_horizontal[2]
Definition: print.c:112
const char * vertical
Definition: print.c:110
const char * down_and_horizontal[2]
Definition: print.c:113
unicodeStyleRowFormat row_style[2]
Definition: print.c:128
unicodeStyleColumnFormat column_style[2]
Definition: print.c:129
const char * nl_right
Definition: print.c:134
const char * wrap_right
Definition: print.c:136
const char * header_nl_left
Definition: print.c:131
const char * header_nl_right
Definition: print.c:132
unicodeStyleBorderFormat border_style[2]
Definition: print.c:130
const char * nl_left
Definition: print.c:133
const char * wrap_left
Definition: print.c:135
bool wrap_right_border
Definition: print.c:137
const char * vertical_and_right[2]
Definition: print.c:104
const char * vertical_and_left[2]
Definition: print.c:105
const char * horizontal
Definition: print.c:103

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 3062 of file print.c.

3063{
3064#ifndef WIN32
3065 pqsignal(SIGPIPE, always_ignore_sigpipe ? SIG_IGN : SIG_DFL);
3066#endif
3067}
static bool always_ignore_sigpipe
Definition: print.c:45

References always_ignore_sigpipe, pqsignal, and SIGPIPE.

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

◆ set_sigpipe_trap_state()

void set_sigpipe_trap_state ( bool  ignore)

Definition at line 3075 of file print.c.

3076{
3077 always_ignore_sigpipe = ignore;
3078}

References always_ignore_sigpipe.

Referenced by setQFout().

◆ setDecimalLocale()

void setDecimalLocale ( void  )

Definition at line 3641 of file print.c.

3642{
3643 struct lconv *extlconv;
3644
3645 extlconv = localeconv();
3646
3647 /* Don't accept an empty decimal_point string */
3648 if (*extlconv->decimal_point)
3649 decimal_point = pg_strdup(extlconv->decimal_point);
3650 else
3651 decimal_point = "."; /* SQL output standard */
3652
3653 /*
3654 * Although the Open Group standard allows locales to supply more than one
3655 * group width, we consider only the first one, and we ignore any attempt
3656 * to suppress grouping by specifying CHAR_MAX. As in the backend's
3657 * cash.c, we must apply a range check to avoid being fooled by variant
3658 * CHAR_MAX values.
3659 */
3660 groupdigits = *extlconv->grouping;
3661 if (groupdigits <= 0 || groupdigits > 6)
3662 groupdigits = 3; /* most common */
3663
3664 /* Don't accept an empty thousands_sep string, either */
3665 /* similar code exists in formatting.c */
3666 if (*extlconv->thousands_sep)
3667 thousands_sep = pg_strdup(extlconv->thousands_sep);
3668 /* Make sure thousands separator doesn't match decimal point symbol. */
3669 else if (strcmp(decimal_point, ",") != 0)
3670 thousands_sep = ",";
3671 else
3672 thousands_sep = ".";
3673}

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 3746 of file print.c.

3747{
3748 unsigned char *start = str;
3749 unsigned char *end = str + strlen((char *) str);
3750 int curr_width = 0;
3751
3752 while (str < end)
3753 {
3754 int char_width = PQdsplen((char *) str, encoding);
3755
3756 /*
3757 * If the display width of the new character causes the string to
3758 * exceed its target width, skip it and return. However, if this is
3759 * the first character of the string (curr_width == 0), we have to
3760 * accept it.
3761 */
3762 if (*target_width < curr_width + char_width && curr_width != 0)
3763 break;
3764
3765 curr_width += char_width;
3766
3767 str += PQmblen((char *) str, encoding);
3768
3769 if (str > end) /* Don't overrun invalid string */
3770 str = end;
3771 }
3772
3773 *target_width = curr_width;
3774
3775 return str - start;
3776}
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1233
int PQdsplen(const char *s, int encoding)
Definition: fe-misc.c:1253
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 2810 of file print.c.

2811{
2812 const char *p;
2813
2814 for (p = in; *p; p++)
2815 switch (*p)
2816 {
2817 case '\\':
2818 fputs("\\(rs", fout);
2819 break;
2820 default:
2821 fputc(*p, fout);
2822 }
2823}

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 45 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 48 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 52 of file print.c.

Referenced by footers_with_default().

◆ default_footer_cell

printTableFooter default_footer_cell = {default_footer, NULL}
static

Definition at line 53 of file print.c.

Referenced by footers_with_default().

◆ groupdigits

int groupdigits
static

Definition at line 49 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 56 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 77 of file print.c.

Referenced by do_pset(), and print_aligned_vertical().

◆ pg_utf8format

printTextFormat pg_utf8format

Definition at line 99 of file print.c.

Referenced by do_pset(), and refresh_utf8format().

◆ thousands_sep

char* thousands_sep
static

Definition at line 50 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 140 of file print.c.

Referenced by refresh_utf8format().