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

Go to the source code of this file.

Data Structures

struct  unicodeStyleRowFormat
 
struct  unicodeStyleColumnFormat
 
struct  unicodeStyleBorderFormat
 
struct  unicodeStyleFormat
 

Macros

#define LONGTABLE_WHITESPACE   " \t\n"
 

Typedefs

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

Functions

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

Variables

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

Macro Definition Documentation

◆ LONGTABLE_WHITESPACE

#define LONGTABLE_WHITESPACE   " \t\n"

Typedef Documentation

◆ unicodeStyleBorderFormat

◆ unicodeStyleColumnFormat

◆ unicodeStyleFormat

◆ unicodeStyleRowFormat

Function Documentation

◆ _print_horizontal_line()

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

Definition at line 593 of file print.c.

597 {
598  const printTextLineFormat *lformat = &format->lrule[pos];
599  unsigned int i,
600  j;
601 
602  if (border == 1)
603  fputs(lformat->hrule, fout);
604  else if (border == 2)
605  fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
606 
607  for (i = 0; i < ncolumns; i++)
608  {
609  for (j = 0; j < widths[i]; j++)
610  fputs(lformat->hrule, fout);
611 
612  if (i < ncolumns - 1)
613  {
614  if (border == 0)
615  fputc(' ', fout);
616  else
617  fprintf(fout, "%s%s%s", lformat->hrule,
618  lformat->midvrule, lformat->hrule);
619  }
620  }
621 
622  if (border == 2)
623  fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
624  else if (border == 1)
625  fputs(lformat->hrule, fout);
626 
627  fputc('\n', fout);
628 }
int j
Definition: isn.c:74
int i
Definition: isn.c:73
static char format
#define fprintf
Definition: port.h:242
const char * hrule
Definition: print.h:46
const char * rightvrule
Definition: print.h:49
const char * midvrule
Definition: print.h:48
const char * leftvrule
Definition: print.h:47

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

Referenced by print_aligned_text().

◆ additional_numeric_locale_len()

static int additional_numeric_locale_len ( const char *  my_str)
static

Definition at line 289 of file print.c.

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

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

Referenced by format_numeric_locale().

◆ asciidoc_escaped_print()

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

Definition at line 2168 of file print.c.

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

Referenced by print_asciidoc_text(), and print_asciidoc_vertical().

◆ ClosePager()

void ClosePager ( FILE *  pagerpipe)

Definition at line 3141 of file print.c.

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

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

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

◆ column_type_alignment()

char column_type_alignment ( Oid  ftype)

Definition at line 3614 of file print.c.

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

Referenced by printCrosstab(), and printQuery().

◆ csv_escaped_print()

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

Definition at line 1840 of file print.c.

1841 {
1842  const char *p;
1843 
1844  fputc('"', fout);
1845  for (p = str; *p; p++)
1846  {
1847  if (*p == '"')
1848  fputc('"', fout); /* double quotes are doubled */
1849  fputc(*p, fout);
1850  }
1851  fputc('"', fout);
1852 }
const char * str

References str.

Referenced by csv_print_field().

◆ csv_print_field()

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

Definition at line 1855 of file print.c.

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

References csv_escaped_print(), and str.

Referenced by print_csv_text(), and print_csv_vertical().

◆ disable_sigpipe_trap()

void disable_sigpipe_trap ( void  )

Definition at line 3039 of file print.c.

3040 {
3041 #ifndef WIN32
3043 #endif
3044 }
pqsigfunc pqsignal(int signo, pqsigfunc func)
#define SIGPIPE
Definition: win32_port.h:173
#define SIG_IGN
Definition: win32_port.h:165

References pqsignal(), SIG_IGN, and SIGPIPE.

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

◆ footers_with_default()

static printTableFooter* footers_with_default ( const printTableContent cont)
static

Definition at line 398 of file print.c.

399 {
400  if (cont->footers == NULL && cont->opt->default_footer)
401  {
402  unsigned long total_records;
403 
404  total_records = cont->opt->prior_records + cont->nrows;
406  ngettext("(%lu row)", "(%lu rows)", total_records),
407  total_records);
408 
409  return &default_footer_cell;
410  }
411  else
412  return cont->footers;
413 }
#define ngettext(s, p, n)
Definition: c.h:1181
static char default_footer[100]
Definition: print.c:52
static printTableFooter default_footer_cell
Definition: print.c:53
#define snprintf
Definition: port.h:238
const printTableOpt * opt
Definition: print.h:165
printTableFooter * footers
Definition: print.h:176
unsigned long prior_records
Definition: print.h:130
bool default_footer
Definition: print.h:129

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

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

◆ format_numeric_locale()

static char* format_numeric_locale ( const char *  my_str)
static

Definition at line 314 of file print.c.

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

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

Referenced by printQuery().

◆ get_line_style()

const printTextFormat* get_line_style ( const printTableOpt opt)

Definition at line 3677 of file print.c.

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

References printTableOpt::line_style, and pg_asciiformat.

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

◆ html_escaped_print()

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

Definition at line 1952 of file print.c.

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

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

◆ integer_digits()

static int integer_digits ( const char *  my_str)
static

Definition at line 278 of file print.c.

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

Referenced by additional_numeric_locale_len(), and format_numeric_locale().

◆ IsPagerNeeded()

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

Definition at line 3403 of file print.c.

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

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

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

◆ latex_escaped_print()

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

Definition at line 2392 of file print.c.

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

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

◆ PageOutput()

FILE* PageOutput ( int  lines,
const printTableOpt topt 
)

Definition at line 3089 of file print.c.

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

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

Referenced by exec_command_sf_sv(), ExecQueryAndProcessResults(), 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:682
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
void ClosePager(FILE *pagerpipe)
Definition: print.c:3141
const printTextFormat * get_line_style(const printTableOpt *opt)
Definition: print.c:3677
static int strlen_max_width(unsigned char *str, int *target_width, int encoding)
Definition: print.c:3746
static void IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded, FILE **fout, bool *is_pager)
Definition: print.c:3403
static 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:1324
static void _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths, unsigned short border, printTextRule pos, const printTextFormat *format, FILE *fout)
Definition: print.c:593
@ PRINT_RULE_MIDDLE
Definition: print.h:56
@ PRINT_RULE_BOTTOM
Definition: print.h:57
@ PRINT_RULE_DATA
Definition: print.h:58
@ PRINT_RULE_TOP
Definition: print.h:55
printTextLineWrap
Definition: print.h:62
@ PRINT_LINE_WRAP_WRAP
Definition: print.h:65
@ PRINT_LINE_WRAP_NEWLINE
Definition: print.h:66
@ PRINT_LINE_WRAP_NONE
Definition: print.h:64
@ PRINT_WRAPPED
Definition: print.h:39
#define free(a)
Definition: header.h:65
void pg_wcssize(const unsigned char *pwcs, size_t len, int encoding, int *result_width, int *result_height, int *result_format_size)
Definition: mbprint.c:211
void pg_wcsformat(const unsigned char *pwcs, size_t len, int encoding, struct lineptr *lines, int count)
Definition: mbprint.c:294
int32 encoding
Definition: pg_database.h:41
int width
Definition: mbprint.h:19
unsigned char * ptr
Definition: mbprint.h:18
char * aligns
Definition: print.h:178
const char ** headers
Definition: print.h:169
const char * title
Definition: print.h:166
const char ** cells
Definition: print.h:171
char * data
Definition: print.h:155
bool start_table
Definition: print.h:127
unsigned short int expanded
Definition: print.h:114
int columns
Definition: print.h:140
enum printFormat format
Definition: print.h:113
int encoding
Definition: print.h:138
unsigned short int border
Definition: print.h:120
int env_columns
Definition: print.h:139
bool stop_table
Definition: print.h:128

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

Referenced by printTable().

◆ print_aligned_vertical()

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

Definition at line 1324 of file print.c.

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

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

Referenced by print_aligned_text(), and printTable().

◆ print_aligned_vertical_line()

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

Definition at line 1225 of file print.c.

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

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

Referenced by print_aligned_vertical().

◆ print_asciidoc_text()

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

Definition at line 2186 of file print.c.

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

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

Referenced by printTable().

◆ print_asciidoc_vertical()

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

Definition at line 2296 of file print.c.

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

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

Referenced by printTable().

◆ print_csv_text()

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

Definition at line 1880 of file print.c.

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

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

Referenced by printTable().

◆ print_csv_vertical()

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

Definition at line 1920 of file print.c.

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

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

Referenced by printTable().

◆ print_html_text()

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

Definition at line 1993 of file print.c.

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

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

Referenced by printTable().

◆ print_html_vertical()

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

Definition at line 2082 of file print.c.

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

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

Referenced by printTable().

◆ print_latex_longtable_text()

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

Definition at line 2561 of file print.c.

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

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

Referenced by printTable().

◆ print_latex_text()

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

Definition at line 2454 of file print.c.

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

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

Referenced by printTable().

◆ print_latex_vertical()

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

Definition at line 2717 of file print.c.

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

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

Referenced by printTable().

◆ print_separator()

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

Definition at line 379 of file print.c.

380 {
381  if (sep.separator_zero)
382  fputc('\000', fout);
383  else if (sep.separator)
384  fputs(sep.separator, fout);
385 }
bool separator_zero
Definition: print.h:108
char * separator
Definition: print.h:107

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

Referenced by print_unaligned_text(), and print_unaligned_vertical().

◆ print_troff_ms_text()

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

Definition at line 2827 of file print.c.

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

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

Referenced by printTable().

◆ print_troff_ms_vertical()

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

Definition at line 2919 of file print.c.

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

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

Referenced by printTable().

◆ print_unaligned_text()

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

Definition at line 422 of file print.c.

423 {
424  bool opt_tuples_only = cont->opt->tuples_only;
425  unsigned int i;
426  const char *const *ptr;
427  bool need_recordsep = false;
428 
429  if (cancel_pressed)
430  return;
431 
432  if (cont->opt->start_table)
433  {
434  /* print title */
435  if (!opt_tuples_only && cont->title)
436  {
437  fputs(cont->title, fout);
438  print_separator(cont->opt->recordSep, fout);
439  }
440 
441  /* print headers */
442  if (!opt_tuples_only)
443  {
444  for (ptr = cont->headers; *ptr; ptr++)
445  {
446  if (ptr != cont->headers)
447  print_separator(cont->opt->fieldSep, fout);
448  fputs(*ptr, fout);
449  }
450  need_recordsep = true;
451  }
452  }
453  else
454  /* assume continuing printout */
455  need_recordsep = true;
456 
457  /* print cells */
458  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
459  {
460  if (need_recordsep)
461  {
462  print_separator(cont->opt->recordSep, fout);
463  need_recordsep = false;
464  if (cancel_pressed)
465  break;
466  }
467  fputs(*ptr, fout);
468 
469  if ((i + 1) % cont->ncolumns)
470  print_separator(cont->opt->fieldSep, fout);
471  else
472  need_recordsep = true;
473  }
474 
475  /* print footers */
476  if (cont->opt->stop_table)
477  {
478  printTableFooter *footers = footers_with_default(cont);
479 
480  if (!opt_tuples_only && footers != NULL && !cancel_pressed)
481  {
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:132
struct separator recordSep
Definition: print.h:133

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

Referenced by printTable().

◆ print_unaligned_vertical()

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

Definition at line 513 of file print.c.

514 {
515  bool opt_tuples_only = cont->opt->tuples_only;
516  unsigned int i;
517  const char *const *ptr;
518  bool need_recordsep = false;
519 
520  if (cancel_pressed)
521  return;
522 
523  if (cont->opt->start_table)
524  {
525  /* print title */
526  if (!opt_tuples_only && cont->title)
527  {
528  fputs(cont->title, fout);
529  need_recordsep = true;
530  }
531  }
532  else
533  /* assume continuing printout */
534  need_recordsep = true;
535 
536  /* print records */
537  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
538  {
539  if (need_recordsep)
540  {
541  /* record separator is 2 occurrences of recordsep in this mode */
542  print_separator(cont->opt->recordSep, fout);
543  print_separator(cont->opt->recordSep, fout);
544  need_recordsep = false;
545  if (cancel_pressed)
546  break;
547  }
548 
549  fputs(cont->headers[i % cont->ncolumns], fout);
550  print_separator(cont->opt->fieldSep, fout);
551  fputs(*ptr, fout);
552 
553  if ((i + 1) % cont->ncolumns)
554  print_separator(cont->opt->recordSep, fout);
555  else
556  need_recordsep = true;
557  }
558 
559  if (cont->opt->stop_table)
560  {
561  /* print footers */
562  if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
563  {
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 3549 of file print.c.

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

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

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

◆ printTable()

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

Definition at line 3443 of file print.c.

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

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

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

◆ printTableAddCell()

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

Definition at line 3260 of file print.c.

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

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

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

◆ printTableAddFooter()

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

Definition at line 3310 of file print.c.

3311 {
3312  printTableFooter *f;
3313 
3314  f = pg_malloc0(sizeof(*f));
3315  f->data = pg_strdup(footer);
3316 
3317  if (content->footers == NULL)
3318  content->footers = f;
3319  else
3320  content->footer->next = f;
3321 
3322  content->footer = f;
3323 }
printTableFooter * footer
Definition: print.h:177

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

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

◆ printTableAddHeader()

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

Definition at line 3220 of file print.c.

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

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

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

◆ printTableCleanup()

void printTableCleanup ( printTableContent *const  content)

Definition at line 3353 of file print.c.

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

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

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

◆ printTableInit()

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

Definition at line 3172 of file print.c.

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

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

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

◆ printTableSetFooter()

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

Definition at line 3335 of file print.c.

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

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

Referenced by add_tablespace_footer().

◆ refresh_utf8format()

void refresh_utf8format ( const printTableOpt opt)

Definition at line 3691 of file print.c.

3692 {
3693  printTextFormat *popt = &pg_utf8format;
3694 
3695  const unicodeStyleBorderFormat *border;
3696  const unicodeStyleRowFormat *header;
3697  const unicodeStyleColumnFormat *column;
3698 
3699  popt->name = "unicode";
3700 
3704 
3705  popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
3706  popt->lrule[PRINT_RULE_TOP].leftvrule = border->down_and_right;
3708  popt->lrule[PRINT_RULE_TOP].rightvrule = border->down_and_left;
3709 
3710  popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
3714 
3715  popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
3716  popt->lrule[PRINT_RULE_BOTTOM].leftvrule = border->up_and_right;
3719 
3720  /* N/A */
3721  popt->lrule[PRINT_RULE_DATA].hrule = "";
3722  popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
3723  popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
3724  popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
3725 
3726  popt->midvrule_nl = column->vertical;
3727  popt->midvrule_wrap = column->vertical;
3728  popt->midvrule_blank = column->vertical;
3729 
3730  /* Same for all unicode today */
3733  popt->nl_left = unicode_style.nl_left;
3738 }
static const unicodeStyleFormat unicode_style
Definition: print.c:140
printTextFormat pg_utf8format
Definition: print.c:99
unicode_linestyle unicode_border_linestyle
Definition: print.h:141
unicode_linestyle unicode_header_linestyle
Definition: print.h:143
unicode_linestyle unicode_column_linestyle
Definition: print.h:142
bool wrap_right_border
Definition: print.h:95
const char * nl_right
Definition: print.h:92
const char * wrap_left
Definition: print.h:93
const char * midvrule_blank
Definition: print.h:88
const char * header_nl_left
Definition: print.h:89
const char * nl_left
Definition: print.h:91
const char * midvrule_nl
Definition: print.h:86
const char * wrap_right
Definition: print.h:94
const char * midvrule_wrap
Definition: print.h:87
const char * name
Definition: print.h:84
const char * header_nl_right
Definition: print.h:90
const char * up_and_right
Definition: print.c:118
const char * left_and_right
Definition: print.c:123
const char * vertical
Definition: print.c:119
const char * down_and_left
Definition: print.c:122
const char * horizontal
Definition: print.c:121
const char * down_and_right
Definition: print.c:120
const char * vertical_and_horizontal[2]
Definition: print.c:111
const char * up_and_horizontal[2]
Definition: print.c:112
const char * vertical
Definition: print.c:110
const char * down_and_horizontal[2]
Definition: print.c:113
unicodeStyleRowFormat row_style[2]
Definition: print.c:128
unicodeStyleColumnFormat column_style[2]
Definition: print.c:129
const char * nl_right
Definition: print.c:134
const char * wrap_right
Definition: print.c:136
const char * header_nl_left
Definition: print.c:131
const char * header_nl_right
Definition: print.c:132
unicodeStyleBorderFormat border_style[2]
Definition: print.c:130
const char * nl_left
Definition: print.c:133
const char * wrap_left
Definition: print.c:135
bool wrap_right_border
Definition: print.c:137
const char * vertical_and_right[2]
Definition: print.c:104
const char * vertical_and_left[2]
Definition: print.c:105
const char * horizontal
Definition: print.c:103

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

Referenced by do_pset(), and main().

◆ restore_sigpipe_trap()

void restore_sigpipe_trap ( void  )

Definition at line 3062 of file print.c.

3063 {
3064 #ifndef WIN32
3066 #endif
3067 }
static bool always_ignore_sigpipe
Definition: print.c:45
#define SIG_DFL
Definition: win32_port.h:163

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

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

◆ set_sigpipe_trap_state()

void set_sigpipe_trap_state ( bool  ignore)

Definition at line 3075 of file print.c.

3076 {
3077  always_ignore_sigpipe = ignore;
3078 }

References always_ignore_sigpipe.

Referenced by setQFout().

◆ setDecimalLocale()

void setDecimalLocale ( void  )

Definition at line 3641 of file print.c.

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

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

Referenced by main().

◆ strlen_max_width()

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

Definition at line 3746 of file print.c.

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

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

Referenced by print_aligned_text(), and print_aligned_vertical().

◆ troff_ms_escaped_print()

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

Definition at line 2810 of file print.c.

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

Referenced by print_troff_ms_text(), and print_troff_ms_vertical().

Variable Documentation

◆ always_ignore_sigpipe

bool always_ignore_sigpipe = false
static

Definition at line 45 of file print.c.

Referenced by restore_sigpipe_trap(), and set_sigpipe_trap_state().

◆ cancel_pressed

◆ decimal_point

char* decimal_point
static

Definition at line 48 of file print.c.

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

◆ default_footer

char default_footer[100]
static

Definition at line 52 of file print.c.

Referenced by footers_with_default().

◆ default_footer_cell

printTableFooter default_footer_cell = {default_footer, NULL}
static

Definition at line 53 of file print.c.

Referenced by footers_with_default().

◆ groupdigits

int groupdigits
static

Definition at line 49 of file print.c.

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

◆ pg_asciiformat

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

Definition at line 56 of file print.c.

Referenced by do_pset(), and get_line_style().

◆ pg_asciiformat_old

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

Definition at line 77 of file print.c.

Referenced by do_pset(), and print_aligned_vertical().

◆ pg_utf8format

printTextFormat pg_utf8format

Definition at line 99 of file print.c.

Referenced by do_pset(), and refresh_utf8format().

◆ thousands_sep

char* thousands_sep
static

Definition at line 50 of file print.c.

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

◆ unicode_style

const unicodeStyleFormat unicode_style
static

Definition at line 140 of file print.c.

Referenced by refresh_utf8format().