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 printTextFormat *format, const unsigned short opt_border, unsigned long record, unsigned int hwidth, unsigned int dwidth, 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 }
int j
Definition: isn.c:74
int i
Definition: isn.c:73
static char format
#define fprintf
Definition: port.h:229
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 2124 of file print.c.

2125 {
2126  const char *p;
2127 
2128  for (p = in; *p; p++)
2129  {
2130  switch (*p)
2131  {
2132  case '|':
2133  fputs("\\|", fout);
2134  break;
2135  default:
2136  fputc(*p, fout);
2137  }
2138  }
2139 }

Referenced by print_asciidoc_text(), and print_asciidoc_vertical().

◆ ClosePager()

void ClosePager ( FILE *  pagerpipe)

Definition at line 3096 of file print.c.

3097 {
3098  if (pagerpipe && pagerpipe != stdout)
3099  {
3100  /*
3101  * If printing was canceled midstream, warn about it.
3102  *
3103  * Some pagers like less use Ctrl-C as part of their command set. Even
3104  * so, we abort our processing and warn the user what we did. If the
3105  * pager quit as a result of the SIGINT, this message won't go
3106  * anywhere ...
3107  */
3108  if (cancel_pressed)
3109  fprintf(pagerpipe, _("Interrupted\n"));
3110 
3111  pclose(pagerpipe);
3113  }
3114 }
#define _(x)
Definition: elog.c:89
void restore_sigpipe_trap(void)
Definition: print.c:3018
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(), ExecQueryUsingCursor(), 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 3555 of file print.c.

3556 {
3557  char align;
3558 
3559  switch (ftype)
3560  {
3561  case INT2OID:
3562  case INT4OID:
3563  case INT8OID:
3564  case FLOAT4OID:
3565  case FLOAT8OID:
3566  case NUMERICOID:
3567  case OIDOID:
3568  case XIDOID:
3569  case XID8OID:
3570  case CIDOID:
3571  case MONEYOID:
3572  align = 'r';
3573  break;
3574  default:
3575  align = 'l';
3576  break;
3577  }
3578  return align;
3579 }

Referenced by printCrosstab(), and printQuery().

◆ csv_escaped_print()

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

Definition at line 1796 of file print.c.

1797 {
1798  const char *p;
1799 
1800  fputc('"', fout);
1801  for (p = str; *p; p++)
1802  {
1803  if (*p == '"')
1804  fputc('"', fout); /* double quotes are doubled */
1805  fputc(*p, fout);
1806  }
1807  fputc('"', fout);
1808 }

References generate_unaccent_rules::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 1811 of file print.c.

1812 {
1813  /*----------------
1814  * Enclose and escape field contents when one of these conditions is met:
1815  * - the field separator is found in the contents.
1816  * - the field contains a CR or LF.
1817  * - the field contains a double quote.
1818  * - the field is exactly "\.".
1819  * - the field separator is either "\" or ".".
1820  * The last two cases prevent producing a line that the server's COPY
1821  * command would interpret as an end-of-data marker. We only really
1822  * need to ensure that the complete line isn't exactly "\.", but for
1823  * simplicity we apply stronger restrictions here.
1824  *----------------
1825  */
1826  if (strchr(str, sep) != NULL ||
1827  strcspn(str, "\r\n\"") != strlen(str) ||
1828  strcmp(str, "\\.") == 0 ||
1829  sep == '\\' || sep == '.')
1830  csv_escaped_print(str, fout);
1831  else
1832  fputs(str, fout);
1833 }
static void csv_escaped_print(const char *str, FILE *fout)
Definition: print.c:1796

References csv_escaped_print(), and generate_unaccent_rules::str.

Referenced by print_csv_text(), and print_csv_vertical().

◆ disable_sigpipe_trap()

void disable_sigpipe_trap ( void  )

Definition at line 2995 of file print.c.

2996 {
2997 #ifndef WIN32
2999 #endif
3000 }
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:180
#define SIGPIPE
Definition: win32_port.h:172
#define SIG_IGN
Definition: win32_port.h:164

References pqsignal(), SIG_IGN, and SIGPIPE.

Referenced by do_copy(), do_watch(), exec_command_write(), ExecQueryUsingCursor(), HandleCopyResult(), PageOutput(), and PrintQueryTuples().

◆ 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:1179
static char default_footer[100]
Definition: print.c:52
static printTableFooter default_footer_cell
Definition: print.c:53
#define snprintf
Definition: port.h:225
const printTableOpt * opt
Definition: print.h:149
printTableFooter * footers
Definition: print.h:160
unsigned long prior_records
Definition: print.h:114
bool default_footer
Definition: print.h:113

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 }
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static int additional_numeric_locale_len(const char *my_str)
Definition: print.c:289
Assert(fmt[strlen(fmt) - 1] !='\n')

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

3619 {
3620  /*
3621  * Note: this function mainly exists to preserve the convention that a
3622  * printTableOpt struct can be initialized to zeroes to get default
3623  * behavior.
3624  */
3625  if (opt->line_style != NULL)
3626  return opt->line_style;
3627  else
3628  return &pg_asciiformat;
3629 }
const printTextFormat pg_asciiformat
Definition: print.c:56
const printTextFormat * line_style
Definition: print.h:115

References printTableOpt::line_style, and pg_asciiformat.

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

◆ html_escaped_print()

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

Definition at line 1908 of file print.c.

1909 {
1910  const char *p;
1911  bool leading_space = true;
1912 
1913  for (p = in; *p; p++)
1914  {
1915  switch (*p)
1916  {
1917  case '&':
1918  fputs("&amp;", fout);
1919  break;
1920  case '<':
1921  fputs("&lt;", fout);
1922  break;
1923  case '>':
1924  fputs("&gt;", fout);
1925  break;
1926  case '\n':
1927  fputs("<br />\n", fout);
1928  break;
1929  case '"':
1930  fputs("&quot;", fout);
1931  break;
1932  case ' ':
1933  /* protect leading space, for EXPLAIN output */
1934  if (leading_space)
1935  fputs("&nbsp;", fout);
1936  else
1937  fputs(" ", fout);
1938  break;
1939  default:
1940  fputc(*p, fout);
1941  }
1942  if (*p != ' ')
1943  leading_space = false;
1944  }
1945 }

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

3346 {
3347  if (*fout == stdout)
3348  {
3349  int lines;
3350 
3351  if (expanded)
3352  lines = (cont->ncolumns + 1) * cont->nrows;
3353  else
3354  lines = cont->nrows + 1;
3355 
3356  if (!cont->opt->tuples_only)
3357  {
3358  printTableFooter *f;
3359 
3360  /*
3361  * FIXME -- this is slightly bogus: it counts the number of
3362  * footers, not the number of lines in them.
3363  */
3364  for (f = cont->footers; f; f = f->next)
3365  lines++;
3366  }
3367 
3368  *fout = PageOutput(lines + extra_lines, cont->opt);
3369  *is_pager = (*fout != stdout);
3370  }
3371  else
3372  *is_pager = false;
3373 }
FILE * PageOutput(int lines, const printTableOpt *topt)
Definition: print.c:3045
struct printTableFooter * next
Definition: print.h:140
bool tuples_only
Definition: print.h:110

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

2349 {
2350  const char *p;
2351 
2352  for (p = in; *p; p++)
2353  switch (*p)
2354  {
2355  /*
2356  * We convert ASCII characters per the recommendations in
2357  * Scott Pakin's "The Comprehensive LATEX Symbol List",
2358  * available from CTAN. For non-ASCII, you're on your own.
2359  */
2360  case '#':
2361  fputs("\\#", fout);
2362  break;
2363  case '$':
2364  fputs("\\$", fout);
2365  break;
2366  case '%':
2367  fputs("\\%", fout);
2368  break;
2369  case '&':
2370  fputs("\\&", fout);
2371  break;
2372  case '<':
2373  fputs("\\textless{}", fout);
2374  break;
2375  case '>':
2376  fputs("\\textgreater{}", fout);
2377  break;
2378  case '\\':
2379  fputs("\\textbackslash{}", fout);
2380  break;
2381  case '^':
2382  fputs("\\^{}", fout);
2383  break;
2384  case '_':
2385  fputs("\\_", fout);
2386  break;
2387  case '{':
2388  fputs("\\{", fout);
2389  break;
2390  case '|':
2391  fputs("\\textbar{}", fout);
2392  break;
2393  case '}':
2394  fputs("\\}", fout);
2395  break;
2396  case '~':
2397  fputs("\\~{}", fout);
2398  break;
2399  case '\n':
2400  /* This is not right, but doing it right seems too hard */
2401  fputs("\\\\", fout);
2402  break;
2403  default:
2404  fputc(*p, fout);
2405  }
2406 }

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

◆ PageOutput()

FILE* PageOutput ( int  lines,
const printTableOpt topt 
)

Definition at line 3045 of file print.c.

3046 {
3047  /* check whether we need / can / are supposed to use pager */
3048  if (topt && topt->pager && isatty(fileno(stdin)) && isatty(fileno(stdout)))
3049  {
3050 #ifdef TIOCGWINSZ
3051  unsigned short int pager = topt->pager;
3052  int min_lines = topt->pager_min_lines;
3053  int result;
3054  struct winsize screen_size;
3055 
3056  result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
3057 
3058  /* >= accounts for a one-line prompt */
3059  if (result == -1
3060  || (lines >= screen_size.ws_row && lines >= min_lines)
3061  || pager > 1)
3062 #endif
3063  {
3064  const char *pagerprog;
3065  FILE *pagerpipe;
3066 
3067  pagerprog = getenv("PSQL_PAGER");
3068  if (!pagerprog)
3069  pagerprog = getenv("PAGER");
3070  if (!pagerprog)
3071  pagerprog = DEFAULT_PAGER;
3072  else
3073  {
3074  /* if PAGER is empty or all-white-space, don't use pager */
3075  if (strspn(pagerprog, " \t\r\n") == strlen(pagerprog))
3076  return stdout;
3077  }
3079  pagerpipe = popen(pagerprog, "w");
3080  if (pagerpipe)
3081  return pagerpipe;
3082  /* if popen fails, silently proceed without pager */
3084  }
3085  }
3086 
3087  return stdout;
3088 }
void disable_sigpipe_trap(void)
Definition: print.c:2995
#define DEFAULT_PAGER
Definition: print.h:23
int pager_min_lines
Definition: print.h:108
unsigned short int pager
Definition: print.h:106

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

Referenced by exec_command_sf_sv(), ExecQueryUsingCursor(), 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;
640  const printTextFormat *format = get_line_style(cont->opt);
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  {
1190  printTableFooter *f;
1191 
1192  for (f = footers; f; f = f->next)
1193  fprintf(fout, "%s\n", f->data);
1194  }
1195 
1196  fputc('\n', fout);
1197  }
1198 
1199 cleanup:
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:697
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
void ClosePager(FILE *pagerpipe)
Definition: print.c:3096
const printTextFormat * get_line_style(const printTableOpt *opt)
Definition: print.c:3618
static int strlen_max_width(unsigned char *str, int *target_width, int encoding)
Definition: print.c:3687
static void IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded, FILE **fout, bool *is_pager)
Definition: print.c:3344
static printTableFooter * footers_with_default(const printTableContent *cont)
Definition: print.c:398
static void print_aligned_vertical(const printTableContent *cont, FILE *fout, bool is_pager)
Definition: print.c:1281
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:162
const char ** headers
Definition: print.h:153
const char * title
Definition: print.h:150
const char ** cells
Definition: print.h:155
char * data
Definition: print.h:139
bool start_table
Definition: print.h:111
unsigned short int expanded
Definition: print.h:102
int columns
Definition: print.h:124
enum printFormat format
Definition: print.h:101
int encoding
Definition: print.h:122
unsigned short int border
Definition: print.h:104
int env_columns
Definition: print.h:123
bool stop_table
Definition: print.h:112

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

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

Definition at line 1225 of file print.c.

1232 {
1233  const printTextLineFormat *lformat = &format->lrule[pos];
1234  unsigned int i;
1235  int reclen = 0;
1236 
1237  if (opt_border == 2)
1238  fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
1239  else if (opt_border == 1)
1240  fputs(lformat->hrule, fout);
1241 
1242  if (record)
1243  {
1244  if (opt_border == 0)
1245  reclen = fprintf(fout, "* Record %lu", record);
1246  else
1247  reclen = fprintf(fout, "[ RECORD %lu ]", record);
1248  }
1249  if (opt_border != 2)
1250  reclen++;
1251  if (reclen < 0)
1252  reclen = 0;
1253  for (i = reclen; i < hwidth; i++)
1254  fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1255  reclen -= hwidth;
1256 
1257  if (opt_border > 0)
1258  {
1259  if (reclen-- <= 0)
1260  fputs(lformat->hrule, fout);
1261  if (reclen-- <= 0)
1262  fputs(lformat->midvrule, fout);
1263  if (reclen-- <= 0)
1264  fputs(lformat->hrule, fout);
1265  }
1266  else
1267  {
1268  if (reclen-- <= 0)
1269  fputc(' ', fout);
1270  }
1271  if (reclen < 0)
1272  reclen = 0;
1273  for (i = reclen; i < dwidth; i++)
1274  fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1275  if (opt_border == 2)
1276  fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
1277  fputc('\n', fout);
1278 }

References format, fprintf, printTextLineFormat::hrule, i, printTextLineFormat::leftvrule, printTextLineFormat::midvrule, 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 2142 of file print.c.

2143 {
2144  bool opt_tuples_only = cont->opt->tuples_only;
2145  unsigned short opt_border = cont->opt->border;
2146  unsigned int i;
2147  const char *const *ptr;
2148 
2149  if (cancel_pressed)
2150  return;
2151 
2152  if (cont->opt->start_table)
2153  {
2154  /* print table in new paragraph - enforce preliminary new line */
2155  fputs("\n", fout);
2156 
2157  /* print title */
2158  if (!opt_tuples_only && cont->title)
2159  {
2160  fputs(".", fout);
2161  fputs(cont->title, fout);
2162  fputs("\n", fout);
2163  }
2164 
2165  /* print table [] header definition */
2166  fprintf(fout, "[%scols=\"", !opt_tuples_only ? "options=\"header\"," : "");
2167  for (i = 0; i < cont->ncolumns; i++)
2168  {
2169  if (i != 0)
2170  fputs(",", fout);
2171  fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
2172  }
2173  fputs("\"", fout);
2174  switch (opt_border)
2175  {
2176  case 0:
2177  fputs(",frame=\"none\",grid=\"none\"", fout);
2178  break;
2179  case 1:
2180  fputs(",frame=\"none\"", fout);
2181  break;
2182  case 2:
2183  fputs(",frame=\"all\",grid=\"all\"", fout);
2184  break;
2185  }
2186  fputs("]\n", fout);
2187  fputs("|====\n", fout);
2188 
2189  /* print headers */
2190  if (!opt_tuples_only)
2191  {
2192  for (ptr = cont->headers; *ptr; ptr++)
2193  {
2194  if (ptr != cont->headers)
2195  fputs(" ", fout);
2196  fputs("^l|", fout);
2197  asciidoc_escaped_print(*ptr, fout);
2198  }
2199  fputs("\n", fout);
2200  }
2201  }
2202 
2203  /* print cells */
2204  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2205  {
2206  if (i % cont->ncolumns == 0)
2207  {
2208  if (cancel_pressed)
2209  break;
2210  }
2211 
2212  if (i % cont->ncolumns != 0)
2213  fputs(" ", fout);
2214  fputs("|", fout);
2215 
2216  /* protect against needless spaces */
2217  if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2218  {
2219  if ((i + 1) % cont->ncolumns != 0)
2220  fputs(" ", fout);
2221  }
2222  else
2223  asciidoc_escaped_print(*ptr, fout);
2224 
2225  if ((i + 1) % cont->ncolumns == 0)
2226  fputs("\n", fout);
2227  }
2228 
2229  fputs("|====\n", fout);
2230 
2231  if (cont->opt->stop_table)
2232  {
2233  printTableFooter *footers = footers_with_default(cont);
2234 
2235  /* print footers */
2236  if (!opt_tuples_only && footers != NULL && !cancel_pressed)
2237  {
2238  printTableFooter *f;
2239 
2240  fputs("\n....\n", fout);
2241  for (f = footers; f; f = f->next)
2242  {
2243  fputs(f->data, fout);
2244  fputs("\n", fout);
2245  }
2246  fputs("....\n", fout);
2247  }
2248  }
2249 }
static void asciidoc_escaped_print(const char *in, FILE *fout)
Definition: print.c:2124

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

2253 {
2254  bool opt_tuples_only = cont->opt->tuples_only;
2255  unsigned short opt_border = cont->opt->border;
2256  unsigned long record = cont->opt->prior_records + 1;
2257  unsigned int i;
2258  const char *const *ptr;
2259 
2260  if (cancel_pressed)
2261  return;
2262 
2263  if (cont->opt->start_table)
2264  {
2265  /* print table in new paragraph - enforce preliminary new line */
2266  fputs("\n", fout);
2267 
2268  /* print title */
2269  if (!opt_tuples_only && cont->title)
2270  {
2271  fputs(".", fout);
2272  fputs(cont->title, fout);
2273  fputs("\n", fout);
2274  }
2275 
2276  /* print table [] header definition */
2277  fputs("[cols=\"h,l\"", fout);
2278  switch (opt_border)
2279  {
2280  case 0:
2281  fputs(",frame=\"none\",grid=\"none\"", fout);
2282  break;
2283  case 1:
2284  fputs(",frame=\"none\"", fout);
2285  break;
2286  case 2:
2287  fputs(",frame=\"all\",grid=\"all\"", fout);
2288  break;
2289  }
2290  fputs("]\n", fout);
2291  fputs("|====\n", fout);
2292  }
2293 
2294  /* print records */
2295  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2296  {
2297  if (i % cont->ncolumns == 0)
2298  {
2299  if (cancel_pressed)
2300  break;
2301  if (!opt_tuples_only)
2302  fprintf(fout,
2303  "2+^|Record %lu\n",
2304  record++);
2305  else
2306  fputs("2+|\n", fout);
2307  }
2308 
2309  fputs("<l|", fout);
2310  asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
2311 
2312  fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">l" : "<l");
2313  /* is string only whitespace? */
2314  if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2315  fputs(" ", fout);
2316  else
2317  asciidoc_escaped_print(*ptr, fout);
2318  fputs("\n", fout);
2319  }
2320 
2321  fputs("|====\n", fout);
2322 
2323  if (cont->opt->stop_table)
2324  {
2325  /* print footers */
2326  if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
2327  {
2328  printTableFooter *f;
2329 
2330  fputs("\n....\n", fout);
2331  for (f = cont->footers; f; f = f->next)
2332  {
2333  fputs(f->data, fout);
2334  fputs("\n", fout);
2335  }
2336  fputs("....\n", fout);
2337  }
2338  }
2339 }

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

1837 {
1838  const char *const *ptr;
1839  int i;
1840 
1841  if (cancel_pressed)
1842  return;
1843 
1844  /*
1845  * The title and footer are never printed in csv format. The header is
1846  * printed if opt_tuples_only is false.
1847  *
1848  * Despite RFC 4180 saying that end of lines are CRLF, terminate lines
1849  * with '\n', which prints out as the system-dependent EOL string in text
1850  * mode (typically LF on Unix and CRLF on Windows).
1851  */
1852  if (cont->opt->start_table && !cont->opt->tuples_only)
1853  {
1854  /* print headers */
1855  for (ptr = cont->headers; *ptr; ptr++)
1856  {
1857  if (ptr != cont->headers)
1858  fputc(cont->opt->csvFieldSep[0], fout);
1859  csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1860  }
1861  fputc('\n', fout);
1862  }
1863 
1864  /* print cells */
1865  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1866  {
1867  csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1868  if ((i + 1) % cont->ncolumns)
1869  fputc(cont->opt->csvFieldSep[0], fout);
1870  else
1871  fputc('\n', fout);
1872  }
1873 }
static void csv_print_field(const char *str, FILE *fout, char sep)
Definition: print.c:1811
char csvFieldSep[2]
Definition: print.h:118

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

1877 {
1878  const char *const *ptr;
1879  int i;
1880 
1881  /* print records */
1882  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1883  {
1884  if (cancel_pressed)
1885  return;
1886 
1887  /* print name of column */
1888  csv_print_field(cont->headers[i % cont->ncolumns], fout,
1889  cont->opt->csvFieldSep[0]);
1890 
1891  /* print field separator */
1892  fputc(cont->opt->csvFieldSep[0], fout);
1893 
1894  /* print field value */
1895  csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1896 
1897  fputc('\n', fout);
1898  }
1899 }

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

1950 {
1951  bool opt_tuples_only = cont->opt->tuples_only;
1952  unsigned short opt_border = cont->opt->border;
1953  const char *opt_table_attr = cont->opt->tableAttr;
1954  unsigned int i;
1955  const char *const *ptr;
1956 
1957  if (cancel_pressed)
1958  return;
1959 
1960  if (cont->opt->start_table)
1961  {
1962  fprintf(fout, "<table border=\"%d\"", opt_border);
1963  if (opt_table_attr)
1964  fprintf(fout, " %s", opt_table_attr);
1965  fputs(">\n", fout);
1966 
1967  /* print title */
1968  if (!opt_tuples_only && cont->title)
1969  {
1970  fputs(" <caption>", fout);
1971  html_escaped_print(cont->title, fout);
1972  fputs("</caption>\n", fout);
1973  }
1974 
1975  /* print headers */
1976  if (!opt_tuples_only)
1977  {
1978  fputs(" <tr>\n", fout);
1979  for (ptr = cont->headers; *ptr; ptr++)
1980  {
1981  fputs(" <th align=\"center\">", fout);
1982  html_escaped_print(*ptr, fout);
1983  fputs("</th>\n", fout);
1984  }
1985  fputs(" </tr>\n", fout);
1986  }
1987  }
1988 
1989  /* print cells */
1990  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1991  {
1992  if (i % cont->ncolumns == 0)
1993  {
1994  if (cancel_pressed)
1995  break;
1996  fputs(" <tr valign=\"top\">\n", fout);
1997  }
1998 
1999  fprintf(fout, " <td align=\"%s\">", cont->aligns[(i) % cont->ncolumns] == 'r' ? "right" : "left");
2000  /* is string only whitespace? */
2001  if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2002  fputs("&nbsp; ", fout);
2003  else
2004  html_escaped_print(*ptr, fout);
2005 
2006  fputs("</td>\n", fout);
2007 
2008  if ((i + 1) % cont->ncolumns == 0)
2009  fputs(" </tr>\n", fout);
2010  }
2011 
2012  if (cont->opt->stop_table)
2013  {
2014  printTableFooter *footers = footers_with_default(cont);
2015 
2016  fputs("</table>\n", fout);
2017 
2018  /* print footers */
2019  if (!opt_tuples_only && footers != NULL && !cancel_pressed)
2020  {
2021  printTableFooter *f;
2022 
2023  fputs("<p>", fout);
2024  for (f = footers; f; f = f->next)
2025  {
2026  html_escaped_print(f->data, fout);
2027  fputs("<br />\n", fout);
2028  }
2029  fputs("</p>", fout);
2030  }
2031 
2032  fputc('\n', fout);
2033  }
2034 }
void html_escaped_print(const char *in, FILE *fout)
Definition: print.c:1908
char * tableAttr
Definition: print.h:121

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

2039 {
2040  bool opt_tuples_only = cont->opt->tuples_only;
2041  unsigned short opt_border = cont->opt->border;
2042  const char *opt_table_attr = cont->opt->tableAttr;
2043  unsigned long record = cont->opt->prior_records + 1;
2044  unsigned int i;
2045  const char *const *ptr;
2046 
2047  if (cancel_pressed)
2048  return;
2049 
2050  if (cont->opt->start_table)
2051  {
2052  fprintf(fout, "<table border=\"%d\"", opt_border);
2053  if (opt_table_attr)
2054  fprintf(fout, " %s", opt_table_attr);
2055  fputs(">\n", fout);
2056 
2057  /* print title */
2058  if (!opt_tuples_only && cont->title)
2059  {
2060  fputs(" <caption>", fout);
2061  html_escaped_print(cont->title, fout);
2062  fputs("</caption>\n", fout);
2063  }
2064  }
2065 
2066  /* print records */
2067  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2068  {
2069  if (i % cont->ncolumns == 0)
2070  {
2071  if (cancel_pressed)
2072  break;
2073  if (!opt_tuples_only)
2074  fprintf(fout,
2075  "\n <tr><td colspan=\"2\" align=\"center\">Record %lu</td></tr>\n",
2076  record++);
2077  else
2078  fputs("\n <tr><td colspan=\"2\">&nbsp;</td></tr>\n", fout);
2079  }
2080  fputs(" <tr valign=\"top\">\n"
2081  " <th>", fout);
2082  html_escaped_print(cont->headers[i % cont->ncolumns], fout);
2083  fputs("</th>\n", fout);
2084 
2085  fprintf(fout, " <td align=\"%s\">", cont->aligns[i % cont->ncolumns] == 'r' ? "right" : "left");
2086  /* is string only whitespace? */
2087  if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2088  fputs("&nbsp; ", fout);
2089  else
2090  html_escaped_print(*ptr, fout);
2091 
2092  fputs("</td>\n </tr>\n", fout);
2093  }
2094 
2095  if (cont->opt->stop_table)
2096  {
2097  fputs("</table>\n", fout);
2098 
2099  /* print footers */
2100  if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
2101  {
2102  printTableFooter *f;
2103 
2104  fputs("<p>", fout);
2105  for (f = cont->footers; f; f = f->next)
2106  {
2107  html_escaped_print(f->data, fout);
2108  fputs("<br />\n", fout);
2109  }
2110  fputs("</p>", fout);
2111  }
2112 
2113  fputc('\n', fout);
2114  }
2115 }

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

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

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

2411 {
2412  bool opt_tuples_only = cont->opt->tuples_only;
2413  unsigned short opt_border = cont->opt->border;
2414  unsigned int i;
2415  const char *const *ptr;
2416 
2417  if (cancel_pressed)
2418  return;
2419 
2420  if (opt_border > 3)
2421  opt_border = 3;
2422 
2423  if (cont->opt->start_table)
2424  {
2425  /* print title */
2426  if (!opt_tuples_only && cont->title)
2427  {
2428  fputs("\\begin{center}\n", fout);
2429  latex_escaped_print(cont->title, fout);
2430  fputs("\n\\end{center}\n\n", fout);
2431  }
2432 
2433  /* begin environment and set alignments and borders */
2434  fputs("\\begin{tabular}{", fout);
2435 
2436  if (opt_border >= 2)
2437  fputs("| ", fout);
2438  for (i = 0; i < cont->ncolumns; i++)
2439  {
2440  fputc(*(cont->aligns + i), fout);
2441  if (opt_border != 0 && i < cont->ncolumns - 1)
2442  fputs(" | ", fout);
2443  }
2444  if (opt_border >= 2)
2445  fputs(" |", fout);
2446 
2447  fputs("}\n", fout);
2448 
2449  if (!opt_tuples_only && opt_border >= 2)
2450  fputs("\\hline\n", fout);
2451 
2452  /* print headers */
2453  if (!opt_tuples_only)
2454  {
2455  for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2456  {
2457  if (i != 0)
2458  fputs(" & ", fout);
2459  fputs("\\textit{", fout);
2460  latex_escaped_print(*ptr, fout);
2461  fputc('}', fout);
2462  }
2463  fputs(" \\\\\n", fout);
2464  fputs("\\hline\n", fout);
2465  }
2466  }
2467 
2468  /* print cells */
2469  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2470  {
2471  latex_escaped_print(*ptr, fout);
2472 
2473  if ((i + 1) % cont->ncolumns == 0)
2474  {
2475  fputs(" \\\\\n", fout);
2476  if (opt_border == 3)
2477  fputs("\\hline\n", fout);
2478  if (cancel_pressed)
2479  break;
2480  }
2481  else
2482  fputs(" & ", fout);
2483  }
2484 
2485  if (cont->opt->stop_table)
2486  {
2487  printTableFooter *footers = footers_with_default(cont);
2488 
2489  if (opt_border == 2)
2490  fputs("\\hline\n", fout);
2491 
2492  fputs("\\end{tabular}\n\n\\noindent ", fout);
2493 
2494  /* print footers */
2495  if (footers && !opt_tuples_only && !cancel_pressed)
2496  {
2497  printTableFooter *f;
2498 
2499  for (f = footers; f; f = f->next)
2500  {
2501  latex_escaped_print(f->data, fout);
2502  fputs(" \\\\\n", fout);
2503  }
2504  }
2505 
2506  fputc('\n', fout);
2507  }
2508 }

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

2674 {
2675  bool opt_tuples_only = cont->opt->tuples_only;
2676  unsigned short opt_border = cont->opt->border;
2677  unsigned long record = cont->opt->prior_records + 1;
2678  unsigned int i;
2679  const char *const *ptr;
2680 
2681  if (cancel_pressed)
2682  return;
2683 
2684  if (opt_border > 2)
2685  opt_border = 2;
2686 
2687  if (cont->opt->start_table)
2688  {
2689  /* print title */
2690  if (!opt_tuples_only && cont->title)
2691  {
2692  fputs("\\begin{center}\n", fout);
2693  latex_escaped_print(cont->title, fout);
2694  fputs("\n\\end{center}\n\n", fout);
2695  }
2696 
2697  /* begin environment and set alignments and borders */
2698  fputs("\\begin{tabular}{", fout);
2699  if (opt_border == 0)
2700  fputs("cl", fout);
2701  else if (opt_border == 1)
2702  fputs("c|l", fout);
2703  else if (opt_border == 2)
2704  fputs("|c|l|", fout);
2705  fputs("}\n", fout);
2706  }
2707 
2708  /* print records */
2709  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2710  {
2711  /* new record */
2712  if (i % cont->ncolumns == 0)
2713  {
2714  if (cancel_pressed)
2715  break;
2716  if (!opt_tuples_only)
2717  {
2718  if (opt_border == 2)
2719  {
2720  fputs("\\hline\n", fout);
2721  fprintf(fout, "\\multicolumn{2}{|c|}{\\textit{Record %lu}} \\\\\n", record++);
2722  }
2723  else
2724  fprintf(fout, "\\multicolumn{2}{c}{\\textit{Record %lu}} \\\\\n", record++);
2725  }
2726  if (opt_border >= 1)
2727  fputs("\\hline\n", fout);
2728  }
2729 
2730  latex_escaped_print(cont->headers[i % cont->ncolumns], fout);
2731  fputs(" & ", fout);
2732  latex_escaped_print(*ptr, fout);
2733  fputs(" \\\\\n", fout);
2734  }
2735 
2736  if (cont->opt->stop_table)
2737  {
2738  if (opt_border == 2)
2739  fputs("\\hline\n", fout);
2740 
2741  fputs("\\end{tabular}\n\n\\noindent ", fout);
2742 
2743  /* print footers */
2744  if (cont->footers && !opt_tuples_only && !cancel_pressed)
2745  {
2746  printTableFooter *f;
2747 
2748  for (f = cont->footers; f; f = f->next)
2749  {
2750  latex_escaped_print(f->data, fout);
2751  fputs(" \\\\\n", fout);
2752  }
2753  }
2754 
2755  fputc('\n', fout);
2756  }
2757 }

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:96
char * separator
Definition: print.h:95

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

2784 {
2785  bool opt_tuples_only = cont->opt->tuples_only;
2786  unsigned short opt_border = cont->opt->border;
2787  unsigned int i;
2788  const char *const *ptr;
2789 
2790  if (cancel_pressed)
2791  return;
2792 
2793  if (opt_border > 2)
2794  opt_border = 2;
2795 
2796  if (cont->opt->start_table)
2797  {
2798  /* print title */
2799  if (!opt_tuples_only && cont->title)
2800  {
2801  fputs(".LP\n.DS C\n", fout);
2802  troff_ms_escaped_print(cont->title, fout);
2803  fputs("\n.DE\n", fout);
2804  }
2805 
2806  /* begin environment and set alignments and borders */
2807  fputs(".LP\n.TS\n", fout);
2808  if (opt_border == 2)
2809  fputs("center box;\n", fout);
2810  else
2811  fputs("center;\n", fout);
2812 
2813  for (i = 0; i < cont->ncolumns; i++)
2814  {
2815  fputc(*(cont->aligns + i), fout);
2816  if (opt_border > 0 && i < cont->ncolumns - 1)
2817  fputs(" | ", fout);
2818  }
2819  fputs(".\n", fout);
2820 
2821  /* print headers */
2822  if (!opt_tuples_only)
2823  {
2824  for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2825  {
2826  if (i != 0)
2827  fputc('\t', fout);
2828  fputs("\\fI", fout);
2829  troff_ms_escaped_print(*ptr, fout);
2830  fputs("\\fP", fout);
2831  }
2832  fputs("\n_\n", fout);
2833  }
2834  }
2835 
2836  /* print cells */
2837  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2838  {
2839  troff_ms_escaped_print(*ptr, fout);
2840 
2841  if ((i + 1) % cont->ncolumns == 0)
2842  {
2843  fputc('\n', fout);
2844  if (cancel_pressed)
2845  break;
2846  }
2847  else
2848  fputc('\t', fout);
2849  }
2850 
2851  if (cont->opt->stop_table)
2852  {
2853  printTableFooter *footers = footers_with_default(cont);
2854 
2855  fputs(".TE\n.DS L\n", fout);
2856 
2857  /* print footers */
2858  if (footers && !opt_tuples_only && !cancel_pressed)
2859  {
2860  printTableFooter *f;
2861 
2862  for (f = footers; f; f = f->next)
2863  {
2864  troff_ms_escaped_print(f->data, fout);
2865  fputc('\n', fout);
2866  }
2867  }
2868 
2869  fputs(".DE\n", fout);
2870  }
2871 }
static void troff_ms_escaped_print(const char *in, FILE *fout)
Definition: print.c:2766

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

2876 {
2877  bool opt_tuples_only = cont->opt->tuples_only;
2878  unsigned short opt_border = cont->opt->border;
2879  unsigned long record = cont->opt->prior_records + 1;
2880  unsigned int i;
2881  const char *const *ptr;
2882  unsigned short current_format = 0; /* 0=none, 1=header, 2=body */
2883 
2884  if (cancel_pressed)
2885  return;
2886 
2887  if (opt_border > 2)
2888  opt_border = 2;
2889 
2890  if (cont->opt->start_table)
2891  {
2892  /* print title */
2893  if (!opt_tuples_only && cont->title)
2894  {
2895  fputs(".LP\n.DS C\n", fout);
2896  troff_ms_escaped_print(cont->title, fout);
2897  fputs("\n.DE\n", fout);
2898  }
2899 
2900  /* begin environment and set alignments and borders */
2901  fputs(".LP\n.TS\n", fout);
2902  if (opt_border == 2)
2903  fputs("center box;\n", fout);
2904  else
2905  fputs("center;\n", fout);
2906 
2907  /* basic format */
2908  if (opt_tuples_only)
2909  fputs("c l;\n", fout);
2910  }
2911  else
2912  current_format = 2; /* assume tuples printed already */
2913 
2914  /* print records */
2915  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2916  {
2917  /* new record */
2918  if (i % cont->ncolumns == 0)
2919  {
2920  if (cancel_pressed)
2921  break;
2922  if (!opt_tuples_only)
2923  {
2924  if (current_format != 1)
2925  {
2926  if (opt_border == 2 && record > 1)
2927  fputs("_\n", fout);
2928  if (current_format != 0)
2929  fputs(".T&\n", fout);
2930  fputs("c s.\n", fout);
2931  current_format = 1;
2932  }
2933  fprintf(fout, "\\fIRecord %lu\\fP\n", record++);
2934  }
2935  if (opt_border >= 1)
2936  fputs("_\n", fout);
2937  }
2938 
2939  if (!opt_tuples_only)
2940  {
2941  if (current_format != 2)
2942  {
2943  if (current_format != 0)
2944  fputs(".T&\n", fout);
2945  if (opt_border != 1)
2946  fputs("c l.\n", fout);
2947  else
2948  fputs("c | l.\n", fout);
2949  current_format = 2;
2950  }
2951  }
2952 
2953  troff_ms_escaped_print(cont->headers[i % cont->ncolumns], fout);
2954  fputc('\t', fout);
2955  troff_ms_escaped_print(*ptr, fout);
2956 
2957  fputc('\n', fout);
2958  }
2959 
2960  if (cont->opt->stop_table)
2961  {
2962  fputs(".TE\n.DS L\n", fout);
2963 
2964  /* print footers */
2965  if (cont->footers && !opt_tuples_only && !cancel_pressed)
2966  {
2967  printTableFooter *f;
2968 
2969  for (f = cont->footers; f; f = f->next)
2970  {
2971  troff_ms_escaped_print(f->data, fout);
2972  fputc('\n', fout);
2973  }
2974  }
2975 
2976  fputs(".DE\n", fout);
2977  }
2978 }

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  {
482  printTableFooter *f;
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:116
struct separator recordSep
Definition: print.h:117

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  {
564  printTableFooter *f;
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 3490 of file print.c.

3492 {
3493  printTableContent cont;
3494  int i,
3495  r,
3496  c;
3497 
3498  if (cancel_pressed)
3499  return;
3500 
3501  printTableInit(&cont, &opt->topt, opt->title,
3502  PQnfields(result), PQntuples(result));
3503 
3504  /* Assert caller supplied enough translate_columns[] entries */
3505  Assert(opt->translate_columns == NULL ||
3506  opt->n_translate_columns >= cont.ncolumns);
3507 
3508  for (i = 0; i < cont.ncolumns; i++)
3509  {
3510  printTableAddHeader(&cont, PQfname(result, i),
3511  opt->translate_header,
3512  column_type_alignment(PQftype(result, i)));
3513  }
3514 
3515  /* set cells */
3516  for (r = 0; r < cont.nrows; r++)
3517  {
3518  for (c = 0; c < cont.ncolumns; c++)
3519  {
3520  char *cell;
3521  bool mustfree = false;
3522  bool translate;
3523 
3524  if (PQgetisnull(result, r, c))
3525  cell = opt->nullPrint ? opt->nullPrint : "";
3526  else
3527  {
3528  cell = PQgetvalue(result, r, c);
3529  if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
3530  {
3531  cell = format_numeric_locale(cell);
3532  mustfree = true;
3533  }
3534  }
3535 
3536  translate = (opt->translate_columns && opt->translate_columns[c]);
3537  printTableAddCell(&cont, cell, translate, mustfree);
3538  }
3539  }
3540 
3541  /* set footers */
3542  if (opt->footers)
3543  {
3544  char **footer;
3545 
3546  for (footer = opt->footers; *footer; footer++)
3547  printTableAddFooter(&cont, *footer);
3548  }
3549 
3550  printTable(&cont, fout, is_pager, flog);
3551  printTableCleanup(&cont);
3552 }
Oid PQftype(const PGresult *res, int field_num)
Definition: fe-exec.c:3578
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3340
char * PQfname(const PGresult *res, int field_num)
Definition: fe-exec.c:3426
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3735
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3760
int PQnfields(const PGresult *res)
Definition: fe-exec.c:3348
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition: print.c:3127
void printTableCleanup(printTableContent *const content)
Definition: print.c:3295
char column_type_alignment(Oid ftype)
Definition: print.c:3555
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3204
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3384
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3252
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:3164
static char * format_numeric_locale(const char *my_str)
Definition: print.c:314
Datum translate(PG_FUNCTION_ARGS)
char * c
const bool * translate_columns
Definition: print.h:174
printTableOpt topt
Definition: print.h:169
char * nullPrint
Definition: print.h:170
char * title
Definition: print.h:171
char ** footers
Definition: print.h:172
bool translate_header
Definition: print.h:173
int n_translate_columns
Definition: print.h:176
bool numericLocale
Definition: print.h:119

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(), describeSubscriptions(), describeTablespaces(), describeTypes(), ExecQueryUsingCursor(), 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 3384 of file print.c.

3386 {
3387  bool is_local_pager = false;
3388 
3389  if (cancel_pressed)
3390  return;
3391 
3392  if (cont->opt->format == PRINT_NOTHING)
3393  return;
3394 
3395  /* print_aligned_*() handle the pager themselves */
3396  if (!is_pager &&
3397  cont->opt->format != PRINT_ALIGNED &&
3398  cont->opt->format != PRINT_WRAPPED)
3399  {
3400  IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager);
3401  is_local_pager = is_pager;
3402  }
3403 
3404  /* clear any pre-existing error indication on the output stream */
3405  clearerr(fout);
3406 
3407  /* print the stuff */
3408 
3409  if (flog)
3410  print_aligned_text(cont, flog, false);
3411 
3412  switch (cont->opt->format)
3413  {
3414  case PRINT_UNALIGNED:
3415  if (cont->opt->expanded == 1)
3416  print_unaligned_vertical(cont, fout);
3417  else
3418  print_unaligned_text(cont, fout);
3419  break;
3420  case PRINT_ALIGNED:
3421  case PRINT_WRAPPED:
3422 
3423  /*
3424  * In expanded-auto mode, force vertical if a pager is passed in;
3425  * else we may make different decisions for different hunks of the
3426  * query result.
3427  */
3428  if (cont->opt->expanded == 1 ||
3429  (cont->opt->expanded == 2 && is_pager))
3430  print_aligned_vertical(cont, fout, is_pager);
3431  else
3432  print_aligned_text(cont, fout, is_pager);
3433  break;
3434  case PRINT_CSV:
3435  if (cont->opt->expanded == 1)
3436  print_csv_vertical(cont, fout);
3437  else
3438  print_csv_text(cont, fout);
3439  break;
3440  case PRINT_HTML:
3441  if (cont->opt->expanded == 1)
3442  print_html_vertical(cont, fout);
3443  else
3444  print_html_text(cont, fout);
3445  break;
3446  case PRINT_ASCIIDOC:
3447  if (cont->opt->expanded == 1)
3448  print_asciidoc_vertical(cont, fout);
3449  else
3450  print_asciidoc_text(cont, fout);
3451  break;
3452  case PRINT_LATEX:
3453  if (cont->opt->expanded == 1)
3454  print_latex_vertical(cont, fout);
3455  else
3456  print_latex_text(cont, fout);
3457  break;
3458  case PRINT_LATEX_LONGTABLE:
3459  if (cont->opt->expanded == 1)
3460  print_latex_vertical(cont, fout);
3461  else
3462  print_latex_longtable_text(cont, fout);
3463  break;
3464  case PRINT_TROFF_MS:
3465  if (cont->opt->expanded == 1)
3466  print_troff_ms_vertical(cont, fout);
3467  else
3468  print_troff_ms_text(cont, fout);
3469  break;
3470  default:
3471  fprintf(stderr, _("invalid output format (internal error): %d"),
3472  cont->opt->format);
3473  exit(EXIT_FAILURE);
3474  }
3475 
3476  if (is_local_pager)
3477  ClosePager(fout);
3478 }
static void print_asciidoc_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2142
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:2410
static void print_troff_ms_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2783
static void print_html_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1949
static void print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2875
static void print_csv_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1836
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:1876
static void print_html_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2038
static void print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2252
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:2673
static void print_latex_longtable_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2517
@ 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:163

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

3206 {
3207 #ifndef ENABLE_NLS
3208  (void) translate; /* unused parameter */
3209 #endif
3210 
3211  if (content->cellsadded >= content->ncolumns * content->nrows)
3212  {
3213  fprintf(stderr, _("Cannot add cell to table content: "
3214  "total cell count of %d exceeded.\n"),
3215  content->ncolumns * content->nrows);
3216  exit(EXIT_FAILURE);
3217  }
3218 
3219  *content->cell = (char *) mbvalidate((unsigned char *) cell,
3220  content->opt->encoding);
3221 
3222 #ifdef ENABLE_NLS
3223  if (translate)
3224  *content->cell = _(*content->cell);
3225 #endif
3226 
3227  if (mustfree)
3228  {
3229  if (content->cellmustfree == NULL)
3230  content->cellmustfree =
3231  pg_malloc0((content->ncolumns * content->nrows + 1) * sizeof(bool));
3232 
3233  content->cellmustfree[content->cellsadded] = true;
3234  }
3235  content->cell++;
3236  content->cellsadded++;
3237 }
unsigned char * mbvalidate(unsigned char *pwcs, int encoding)
Definition: mbprint.c:392
bool * cellmustfree
Definition: print.h:159
const char ** cell
Definition: print.h:157
long cellsadded
Definition: print.h:158

References _, printTableContent::cell, printTableContent::cellmustfree, printTableContent::cellsadded, printTableOpt::encoding, exit(), EXIT_FAILURE, fprintf, 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 3252 of file print.c.

3253 {
3254  printTableFooter *f;
3255 
3256  f = pg_malloc0(sizeof(*f));
3257  f->data = pg_strdup(footer);
3258 
3259  if (content->footers == NULL)
3260  content->footers = f;
3261  else
3262  content->footer->next = f;
3263 
3264  content->footer = f;
3265 }
printTableFooter * footer
Definition: print.h:161

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

3166 {
3167 #ifndef ENABLE_NLS
3168  (void) translate; /* unused parameter */
3169 #endif
3170 
3171  if (content->header >= content->headers + content->ncolumns)
3172  {
3173  fprintf(stderr, _("Cannot add header to table content: "
3174  "column count of %d exceeded.\n"),
3175  content->ncolumns);
3176  exit(EXIT_FAILURE);
3177  }
3178 
3179  *content->header = (char *) mbvalidate((unsigned char *) header,
3180  content->opt->encoding);
3181 #ifdef ENABLE_NLS
3182  if (translate)
3183  *content->header = _(*content->header);
3184 #endif
3185  content->header++;
3186 
3187  *content->align = align;
3188  content->align++;
3189 }
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:212
char * align
Definition: print.h:164
const char ** header
Definition: print.h:154

References _, printTableContent::align, printTableOpt::encoding, exit(), EXIT_FAILURE, fprintf, printTableContent::header, 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 3295 of file print.c.

3296 {
3297  if (content->cellmustfree)
3298  {
3299  int i;
3300 
3301  for (i = 0; i < content->nrows * content->ncolumns; i++)
3302  {
3303  if (content->cellmustfree[i])
3304  free(unconstify(char *, content->cells[i]));
3305  }
3306  free(content->cellmustfree);
3307  content->cellmustfree = NULL;
3308  }
3309  free(content->headers);
3310  free(content->cells);
3311  free(content->aligns);
3312 
3313  content->opt = NULL;
3314  content->title = NULL;
3315  content->headers = NULL;
3316  content->cells = NULL;
3317  content->aligns = NULL;
3318  content->header = NULL;
3319  content->cell = NULL;
3320  content->align = NULL;
3321 
3322  if (content->footers)
3323  {
3324  for (content->footer = content->footers; content->footer;)
3325  {
3326  printTableFooter *f;
3327 
3328  f = content->footer;
3329  content->footer = f->next;
3330  free(f->data);
3331  free(f);
3332  }
3333  }
3334  content->footers = NULL;
3335  content->footer = NULL;
3336 }
#define unconstify(underlying_type, expr)
Definition: c.h:1240

References printTableContent::align, printTableContent::aligns, printTableContent::cell, printTableContent::cellmustfree, printTableContent::cells, printTableFooter::data, printTableContent::footer, printTableContent::footers, 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 3127 of file print.c.

3129 {
3130  content->opt = opt;
3131  content->title = title;
3132  content->ncolumns = ncolumns;
3133  content->nrows = nrows;
3134 
3135  content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers));
3136 
3137  content->cells = pg_malloc0((ncolumns * nrows + 1) * sizeof(*content->cells));
3138 
3139  content->cellmustfree = NULL;
3140  content->footers = NULL;
3141 
3142  content->aligns = pg_malloc0((ncolumns + 1) * sizeof(*content->align));
3143 
3144  content->header = content->headers;
3145  content->cell = content->cells;
3146  content->footer = content->footers;
3147  content->align = content->aligns;
3148  content->cellsadded = 0;
3149 }

References printTableContent::align, printTableContent::aligns, printTableContent::cell, printTableContent::cellmustfree, printTableContent::cells, printTableContent::cellsadded, printTableContent::footer, printTableContent::footers, 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 3277 of file print.c.

3278 {
3279  if (content->footers != NULL)
3280  {
3281  free(content->footer->data);
3282  content->footer->data = pg_strdup(footer);
3283  }
3284  else
3285  printTableAddFooter(content, footer);
3286 }

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

3633 {
3634  printTextFormat *popt = &pg_utf8format;
3635 
3636  const unicodeStyleBorderFormat *border;
3638  const unicodeStyleColumnFormat *column;
3639 
3640  popt->name = "unicode";
3641 
3645 
3646  popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
3647  popt->lrule[PRINT_RULE_TOP].leftvrule = border->down_and_right;
3649  popt->lrule[PRINT_RULE_TOP].rightvrule = border->down_and_left;
3650 
3651  popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
3652  popt->lrule[PRINT_RULE_MIDDLE].leftvrule = header->vertical_and_right[opt->unicode_border_linestyle];
3654  popt->lrule[PRINT_RULE_MIDDLE].rightvrule = header->vertical_and_left[opt->unicode_border_linestyle];
3655 
3656  popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
3657  popt->lrule[PRINT_RULE_BOTTOM].leftvrule = border->up_and_right;
3660 
3661  /* N/A */
3662  popt->lrule[PRINT_RULE_DATA].hrule = "";
3663  popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
3664  popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
3665  popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
3666 
3667  popt->midvrule_nl = column->vertical;
3668  popt->midvrule_wrap = column->vertical;
3669  popt->midvrule_blank = column->vertical;
3670 
3671  /* Same for all unicode today */
3674  popt->nl_left = unicode_style.nl_left;
3679 }
static const unicodeStyleFormat unicode_style
Definition: print.c:140
printTextFormat pg_utf8format
Definition: print.c:99
unicode_linestyle unicode_border_linestyle
Definition: print.h:125
unicode_linestyle unicode_header_linestyle
Definition: print.h:127
unicode_linestyle unicode_column_linestyle
Definition: print.h:126
bool wrap_right_border
Definition: print.h:83
const char * nl_right
Definition: print.h:80
const char * wrap_left
Definition: print.h:81
const char * midvrule_blank
Definition: print.h:76
const char * header_nl_left
Definition: print.h:77
const char * nl_left
Definition: print.h:79
const char * midvrule_nl
Definition: print.h:74
printTextLineFormat lrule[4]
Definition: print.h:73
const char * wrap_right
Definition: print.h:82
const char * midvrule_wrap
Definition: print.h:75
const char * name
Definition: print.h:72
const char * header_nl_right
Definition: print.h:78
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

References unicodeStyleFormat::border_style, unicodeStyleFormat::column_style, unicodeStyleColumnFormat::down_and_horizontal, unicodeStyleBorderFormat::down_and_left, unicodeStyleBorderFormat::down_and_right, header(), unicodeStyleFormat::header_nl_left, printTextFormat::header_nl_left, unicodeStyleFormat::header_nl_right, printTextFormat::header_nl_right, 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, 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 3018 of file print.c.

3019 {
3020 #ifndef WIN32
3022 #endif
3023 }
static bool always_ignore_sigpipe
Definition: print.c:45
#define SIG_DFL
Definition: win32_port.h:162

References always_ignore_sigpipe, pqsignal(), SIG_DFL, SIG_IGN, and SIGPIPE.

Referenced by ClosePager(), do_copy(), do_watch(), exec_command_write(), ExecQueryUsingCursor(), HandleCopyResult(), PageOutput(), PrintQueryTuples(), and setQFout().

◆ set_sigpipe_trap_state()

void set_sigpipe_trap_state ( bool  ignore)

Definition at line 3031 of file print.c.

3032 {
3033  always_ignore_sigpipe = ignore;
3034 }

References always_ignore_sigpipe.

Referenced by setQFout().

◆ setDecimalLocale()

void setDecimalLocale ( void  )

Definition at line 3582 of file print.c.

3583 {
3584  struct lconv *extlconv;
3585 
3586  extlconv = localeconv();
3587 
3588  /* Don't accept an empty decimal_point string */
3589  if (*extlconv->decimal_point)
3590  decimal_point = pg_strdup(extlconv->decimal_point);
3591  else
3592  decimal_point = "."; /* SQL output standard */
3593 
3594  /*
3595  * Although the Open Group standard allows locales to supply more than one
3596  * group width, we consider only the first one, and we ignore any attempt
3597  * to suppress grouping by specifying CHAR_MAX. As in the backend's
3598  * cash.c, we must apply a range check to avoid being fooled by variant
3599  * CHAR_MAX values.
3600  */
3601  groupdigits = *extlconv->grouping;
3602  if (groupdigits <= 0 || groupdigits > 6)
3603  groupdigits = 3; /* most common */
3604 
3605  /* Don't accept an empty thousands_sep string, either */
3606  /* similar code exists in formatting.c */
3607  if (*extlconv->thousands_sep)
3608  thousands_sep = pg_strdup(extlconv->thousands_sep);
3609  /* Make sure thousands separator doesn't match decimal point symbol. */
3610  else if (strcmp(decimal_point, ",") != 0)
3611  thousands_sep = ",";
3612  else
3613  thousands_sep = ".";
3614 }

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

3688 {
3689  unsigned char *start = str;
3690  unsigned char *end = str + strlen((char *) str);
3691  int curr_width = 0;
3692 
3693  while (str < end)
3694  {
3695  int char_width = PQdsplen((char *) str, encoding);
3696 
3697  /*
3698  * If the display width of the new character causes the string to
3699  * exceed its target width, skip it and return. However, if this is
3700  * the first character of the string (curr_width == 0), we have to
3701  * accept it.
3702  */
3703  if (*target_width < curr_width + char_width && curr_width != 0)
3704  break;
3705 
3706  curr_width += char_width;
3707 
3708  str += PQmblen((char *) str, encoding);
3709 
3710  if (str > end) /* Don't overrun invalid string */
3711  str = end;
3712  }
3713 
3714  *target_width = curr_width;
3715 
3716  return str - start;
3717 }
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1185
int PQdsplen(const char *s, int encoding)
Definition: fe-misc.c:1205

References encoding, PQdsplen(), PQmblen(), and generate_unaccent_rules::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 2766 of file print.c.

2767 {
2768  const char *p;
2769 
2770  for (p = in; *p; p++)
2771  switch (*p)
2772  {
2773  case '\\':
2774  fputs("\\(rs", fout);
2775  break;
2776  default:
2777  fputc(*p, fout);
2778  }
2779 }

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().