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

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

Referenced by print_asciidoc_text(), and print_asciidoc_vertical().

◆ ClosePager()

void ClosePager ( FILE *  pagerpipe)

Definition at line 3140 of file print.c.

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

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

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

◆ column_type_alignment()

char column_type_alignment ( Oid  ftype)

Definition at line 3599 of file print.c.

3600 {
3601  char align;
3602 
3603  switch (ftype)
3604  {
3605  case INT2OID:
3606  case INT4OID:
3607  case INT8OID:
3608  case FLOAT4OID:
3609  case FLOAT8OID:
3610  case NUMERICOID:
3611  case OIDOID:
3612  case XIDOID:
3613  case XID8OID:
3614  case CIDOID:
3615  case MONEYOID:
3616  align = 'r';
3617  break;
3618  default:
3619  align = 'l';
3620  break;
3621  }
3622  return align;
3623 }

Referenced by printCrosstab(), and printQuery().

◆ csv_escaped_print()

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

Definition at line 1839 of file print.c.

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

References generate_unaccent_rules::str.

Referenced by csv_print_field().

◆ csv_print_field()

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

Definition at line 1854 of file print.c.

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

References csv_escaped_print(), and generate_unaccent_rules::str.

Referenced by print_csv_text(), and print_csv_vertical().

◆ disable_sigpipe_trap()

void disable_sigpipe_trap ( void  )

Definition at line 3038 of file print.c.

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

References pqsignal(), SIG_IGN, and SIGPIPE.

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

◆ 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:1171
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:160
printTableFooter * footers
Definition: print.h:171
unsigned long prior_records
Definition: print.h:125
bool default_footer
Definition: print.h:124

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

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

◆ format_numeric_locale()

static char* format_numeric_locale ( const char *  my_str)
static

Definition at line 314 of file print.c.

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

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

Referenced by printQuery().

◆ get_line_style()

const printTextFormat* get_line_style ( const printTableOpt opt)

Definition at line 3662 of file print.c.

3663 {
3664  /*
3665  * Note: this function mainly exists to preserve the convention that a
3666  * printTableOpt struct can be initialized to zeroes to get default
3667  * behavior.
3668  */
3669  if (opt->line_style != NULL)
3670  return opt->line_style;
3671  else
3672  return &pg_asciiformat;
3673 }
const printTextFormat pg_asciiformat
Definition: print.c:56
const printTextFormat * line_style
Definition: print.h:126

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

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

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

3390 {
3391  if (*fout == stdout)
3392  {
3393  int lines;
3394 
3395  if (expanded)
3396  lines = (cont->ncolumns + 1) * cont->nrows;
3397  else
3398  lines = cont->nrows + 1;
3399 
3400  if (!cont->opt->tuples_only)
3401  {
3402  printTableFooter *f;
3403 
3404  /*
3405  * FIXME -- this is slightly bogus: it counts the number of
3406  * footers, not the number of lines in them.
3407  */
3408  for (f = cont->footers; f; f = f->next)
3409  lines++;
3410  }
3411 
3412  *fout = PageOutput(lines + extra_lines, cont->opt);
3413  *is_pager = (*fout != stdout);
3414  }
3415  else
3416  *is_pager = false;
3417 }
FILE * PageOutput(int lines, const printTableOpt *topt)
Definition: print.c:3088
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
struct printTableFooter * next
Definition: print.h:151
bool tuples_only
Definition: print.h:121

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

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

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

◆ PageOutput()

FILE* PageOutput ( int  lines,
const printTableOpt topt 
)

Definition at line 3088 of file print.c.

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

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(), ExecQueryUsingCursor(), helpSQL(), helpVariables(), IsPagerNeeded(), print_aligned_text(), printHistory(), slashUsage(), and usage().

◆ print_aligned_text()

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

Definition at line 635 of file print.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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:127
struct separator recordSep
Definition: print.h:128

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

3536 {
3537  printTableContent cont;
3538  int i,
3539  r,
3540  c;
3541 
3542  if (cancel_pressed)
3543  return;
3544 
3545  printTableInit(&cont, &opt->topt, opt->title,
3546  PQnfields(result), PQntuples(result));
3547 
3548  /* Assert caller supplied enough translate_columns[] entries */
3549  Assert(opt->translate_columns == NULL ||
3550  opt->n_translate_columns >= cont.ncolumns);
3551 
3552  for (i = 0; i < cont.ncolumns; i++)
3553  {
3554  printTableAddHeader(&cont, PQfname(result, i),
3555  opt->translate_header,
3556  column_type_alignment(PQftype(result, i)));
3557  }
3558 
3559  /* set cells */
3560  for (r = 0; r < cont.nrows; r++)
3561  {
3562  for (c = 0; c < cont.ncolumns; c++)
3563  {
3564  char *cell;
3565  bool mustfree = false;
3566  bool translate;
3567 
3568  if (PQgetisnull(result, r, c))
3569  cell = opt->nullPrint ? opt->nullPrint : "";
3570  else
3571  {
3572  cell = PQgetvalue(result, r, c);
3573  if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
3574  {
3575  cell = format_numeric_locale(cell);
3576  mustfree = true;
3577  }
3578  }
3579 
3580  translate = (opt->translate_columns && opt->translate_columns[c]);
3581  printTableAddCell(&cont, cell, translate, mustfree);
3582  }
3583  }
3584 
3585  /* set footers */
3586  if (opt->footers)
3587  {
3588  char **footer;
3589 
3590  for (footer = opt->footers; *footer; footer++)
3591  printTableAddFooter(&cont, *footer);
3592  }
3593 
3594  printTable(&cont, fout, is_pager, flog);
3595  printTableCleanup(&cont);
3596 }
Oid PQftype(const PGresult *res, int field_num)
Definition: fe-exec.c:3548
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3310
char * PQfname(const PGresult *res, int field_num)
Definition: fe-exec.c:3396
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3705
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3730
int PQnfields(const PGresult *res)
Definition: fe-exec.c:3318
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition: print.c:3171
void printTableCleanup(printTableContent *const content)
Definition: print.c:3339
char column_type_alignment(Oid ftype)
Definition: print.c:3599
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3248
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3428
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3296
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:3208
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:185
printTableOpt topt
Definition: print.h:180
char * nullPrint
Definition: print.h:181
char * title
Definition: print.h:182
char ** footers
Definition: print.h:183
bool translate_header
Definition: print.h:184
int n_translate_columns
Definition: print.h:187
bool numericLocale
Definition: print.h:130

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

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

◆ printTable()

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

Definition at line 3428 of file print.c.

3430 {
3431  bool is_local_pager = false;
3432 
3433  if (cancel_pressed)
3434  return;
3435 
3436  if (cont->opt->format == PRINT_NOTHING)
3437  return;
3438 
3439  /* print_aligned_*() handle the pager themselves */
3440  if (!is_pager &&
3441  cont->opt->format != PRINT_ALIGNED &&
3442  cont->opt->format != PRINT_WRAPPED)
3443  {
3444  IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager);
3445  is_local_pager = is_pager;
3446  }
3447 
3448  /* clear any pre-existing error indication on the output stream */
3449  clearerr(fout);
3450 
3451  /* print the stuff */
3452 
3453  if (flog)
3454  print_aligned_text(cont, flog, false);
3455 
3456  switch (cont->opt->format)
3457  {
3458  case PRINT_UNALIGNED:
3459  if (cont->opt->expanded == 1)
3460  print_unaligned_vertical(cont, fout);
3461  else
3462  print_unaligned_text(cont, fout);
3463  break;
3464  case PRINT_ALIGNED:
3465  case PRINT_WRAPPED:
3466 
3467  /*
3468  * In expanded-auto mode, force vertical if a pager is passed in;
3469  * else we may make different decisions for different hunks of the
3470  * query result.
3471  */
3472  if (cont->opt->expanded == 1 ||
3473  (cont->opt->expanded == 2 && is_pager))
3474  print_aligned_vertical(cont, fout, is_pager);
3475  else
3476  print_aligned_text(cont, fout, is_pager);
3477  break;
3478  case PRINT_CSV:
3479  if (cont->opt->expanded == 1)
3480  print_csv_vertical(cont, fout);
3481  else
3482  print_csv_text(cont, fout);
3483  break;
3484  case PRINT_HTML:
3485  if (cont->opt->expanded == 1)
3486  print_html_vertical(cont, fout);
3487  else
3488  print_html_text(cont, fout);
3489  break;
3490  case PRINT_ASCIIDOC:
3491  if (cont->opt->expanded == 1)
3492  print_asciidoc_vertical(cont, fout);
3493  else
3494  print_asciidoc_text(cont, fout);
3495  break;
3496  case PRINT_LATEX:
3497  if (cont->opt->expanded == 1)
3498  print_latex_vertical(cont, fout);
3499  else
3500  print_latex_text(cont, fout);
3501  break;
3502  case PRINT_LATEX_LONGTABLE:
3503  if (cont->opt->expanded == 1)
3504  print_latex_vertical(cont, fout);
3505  else
3506  print_latex_longtable_text(cont, fout);
3507  break;
3508  case PRINT_TROFF_MS:
3509  if (cont->opt->expanded == 1)
3510  print_troff_ms_vertical(cont, fout);
3511  else
3512  print_troff_ms_text(cont, fout);
3513  break;
3514  default:
3515  fprintf(stderr, _("invalid output format (internal error): %d"),
3516  cont->opt->format);
3517  exit(EXIT_FAILURE);
3518  }
3519 
3520  if (is_local_pager)
3521  ClosePager(fout);
3522 }
static void print_asciidoc_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2185
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:2453
static void print_troff_ms_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2826
static void print_html_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1992
static void print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2918
static void print_csv_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1879
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:1919
static void print_html_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2081
static void print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2295
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:2716
static void print_latex_longtable_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2560
@ 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:166

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

3250 {
3251 #ifndef ENABLE_NLS
3252  (void) translate; /* unused parameter */
3253 #endif
3254 
3255  if (content->cellsadded >= content->ncolumns * content->nrows)
3256  {
3257  fprintf(stderr, _("Cannot add cell to table content: "
3258  "total cell count of %d exceeded.\n"),
3259  content->ncolumns * content->nrows);
3260  exit(EXIT_FAILURE);
3261  }
3262 
3263  *content->cell = (char *) mbvalidate((unsigned char *) cell,
3264  content->opt->encoding);
3265 
3266 #ifdef ENABLE_NLS
3267  if (translate)
3268  *content->cell = _(*content->cell);
3269 #endif
3270 
3271  if (mustfree)
3272  {
3273  if (content->cellmustfree == NULL)
3274  content->cellmustfree =
3275  pg_malloc0((content->ncolumns * content->nrows + 1) * sizeof(bool));
3276 
3277  content->cellmustfree[content->cellsadded] = true;
3278  }
3279  content->cell++;
3280  content->cellsadded++;
3281 }
unsigned char * mbvalidate(unsigned char *pwcs, int encoding)
Definition: mbprint.c:392
bool * cellmustfree
Definition: print.h:170
const char ** cell
Definition: print.h:168
long cellsadded
Definition: print.h:169

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

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

◆ printTableAddFooter()

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

Definition at line 3296 of file print.c.

3297 {
3298  printTableFooter *f;
3299 
3300  f = pg_malloc0(sizeof(*f));
3301  f->data = pg_strdup(footer);
3302 
3303  if (content->footers == NULL)
3304  content->footers = f;
3305  else
3306  content->footer->next = f;
3307 
3308  content->footer = f;
3309 }
printTableFooter * footer
Definition: print.h:172

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

3210 {
3211 #ifndef ENABLE_NLS
3212  (void) translate; /* unused parameter */
3213 #endif
3214 
3215  if (content->header >= content->headers + content->ncolumns)
3216  {
3217  fprintf(stderr, _("Cannot add header to table content: "
3218  "column count of %d exceeded.\n"),
3219  content->ncolumns);
3220  exit(EXIT_FAILURE);
3221  }
3222 
3223  *content->header = (char *) mbvalidate((unsigned char *) header,
3224  content->opt->encoding);
3225 #ifdef ENABLE_NLS
3226  if (translate)
3227  *content->header = _(*content->header);
3228 #endif
3229  content->header++;
3230 
3231  *content->align = align;
3232  content->align++;
3233 }
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:207
char * align
Definition: print.h:175
const char ** header
Definition: print.h:165

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

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

◆ printTableCleanup()

void printTableCleanup ( printTableContent *const  content)

Definition at line 3339 of file print.c.

3340 {
3341  if (content->cellmustfree)
3342  {
3343  int i;
3344 
3345  for (i = 0; i < content->nrows * content->ncolumns; i++)
3346  {
3347  if (content->cellmustfree[i])
3348  free(unconstify(char *, content->cells[i]));
3349  }
3350  free(content->cellmustfree);
3351  content->cellmustfree = NULL;
3352  }
3353  free(content->headers);
3354  free(content->cells);
3355  free(content->aligns);
3356 
3357  content->opt = NULL;
3358  content->title = NULL;
3359  content->headers = NULL;
3360  content->cells = NULL;
3361  content->aligns = NULL;
3362  content->header = NULL;
3363  content->cell = NULL;
3364  content->align = NULL;
3365 
3366  if (content->footers)
3367  {
3368  for (content->footer = content->footers; content->footer;)
3369  {
3370  printTableFooter *f;
3371 
3372  f = content->footer;
3373  content->footer = f->next;
3374  free(f->data);
3375  free(f);
3376  }
3377  }
3378  content->footers = NULL;
3379  content->footer = NULL;
3380 }
#define unconstify(underlying_type, expr)
Definition: c.h:1232

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

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

◆ printTableInit()

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

Definition at line 3171 of file print.c.

3173 {
3174  content->opt = opt;
3175  content->title = title;
3176  content->ncolumns = ncolumns;
3177  content->nrows = nrows;
3178 
3179  content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers));
3180 
3181  content->cells = pg_malloc0((ncolumns * nrows + 1) * sizeof(*content->cells));
3182 
3183  content->cellmustfree = NULL;
3184  content->footers = NULL;
3185 
3186  content->aligns = pg_malloc0((ncolumns + 1) * sizeof(*content->align));
3187 
3188  content->header = content->headers;
3189  content->cell = content->cells;
3190  content->footer = content->footers;
3191  content->align = content->aligns;
3192  content->cellsadded = 0;
3193 }

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

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

◆ printTableSetFooter()

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

Definition at line 3321 of file print.c.

3322 {
3323  if (content->footers != NULL)
3324  {
3325  free(content->footer->data);
3326  content->footer->data = pg_strdup(footer);
3327  }
3328  else
3329  printTableAddFooter(content, footer);
3330 }

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

3677 {
3678  printTextFormat *popt = &pg_utf8format;
3679 
3680  const unicodeStyleBorderFormat *border;
3682  const unicodeStyleColumnFormat *column;
3683 
3684  popt->name = "unicode";
3685 
3689 
3690  popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
3691  popt->lrule[PRINT_RULE_TOP].leftvrule = border->down_and_right;
3693  popt->lrule[PRINT_RULE_TOP].rightvrule = border->down_and_left;
3694 
3695  popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
3696  popt->lrule[PRINT_RULE_MIDDLE].leftvrule = header->vertical_and_right[opt->unicode_border_linestyle];
3698  popt->lrule[PRINT_RULE_MIDDLE].rightvrule = header->vertical_and_left[opt->unicode_border_linestyle];
3699 
3700  popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
3701  popt->lrule[PRINT_RULE_BOTTOM].leftvrule = border->up_and_right;
3704 
3705  /* N/A */
3706  popt->lrule[PRINT_RULE_DATA].hrule = "";
3707  popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
3708  popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
3709  popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
3710 
3711  popt->midvrule_nl = column->vertical;
3712  popt->midvrule_wrap = column->vertical;
3713  popt->midvrule_blank = column->vertical;
3714 
3715  /* Same for all unicode today */
3718  popt->nl_left = unicode_style.nl_left;
3723 }
static const unicodeStyleFormat unicode_style
Definition: print.c:140
printTextFormat pg_utf8format
Definition: print.c:99
unicode_linestyle unicode_border_linestyle
Definition: print.h:136
unicode_linestyle unicode_header_linestyle
Definition: print.h:138
unicode_linestyle unicode_column_linestyle
Definition: print.h:137
bool wrap_right_border
Definition: print.h:92
const char * nl_right
Definition: print.h:89
const char * wrap_left
Definition: print.h:90
const char * midvrule_blank
Definition: print.h:85
const char * header_nl_left
Definition: print.h:86
const char * nl_left
Definition: print.h:88
const char * midvrule_nl
Definition: print.h:83
const char * wrap_right
Definition: print.h:91
const char * midvrule_wrap
Definition: print.h:84
const char * name
Definition: print.h:81
const char * header_nl_right
Definition: print.h:87
const char * up_and_right
Definition: print.c:118
const char * left_and_right
Definition: print.c:123
const char * vertical
Definition: print.c:119
const char * down_and_left
Definition: print.c:122
const char * horizontal
Definition: print.c:121
const char * down_and_right
Definition: print.c:120
const char * vertical_and_horizontal[2]
Definition: print.c:111
const char * up_and_horizontal[2]
Definition: print.c:112
const char * vertical
Definition: print.c:110
const char * down_and_horizontal[2]
Definition: print.c:113
unicodeStyleRowFormat row_style[2]
Definition: print.c:128
unicodeStyleColumnFormat column_style[2]
Definition: print.c:129
const char * nl_right
Definition: print.c:134
const char * wrap_right
Definition: print.c:136
const char * header_nl_left
Definition: print.c:131
const char * header_nl_right
Definition: print.c:132
unicodeStyleBorderFormat border_style[2]
Definition: print.c:130
const char * nl_left
Definition: print.c:133
const char * wrap_left
Definition: print.c:135
bool wrap_right_border
Definition: print.c:137

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

Referenced by do_pset(), and main().

◆ restore_sigpipe_trap()

void restore_sigpipe_trap ( void  )

Definition at line 3061 of file print.c.

3062 {
3063 #ifndef WIN32
3065 #endif
3066 }
static bool always_ignore_sigpipe
Definition: print.c:45
#define SIG_DFL
Definition: win32_port.h:171

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

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

◆ set_sigpipe_trap_state()

void set_sigpipe_trap_state ( bool  ignore)

Definition at line 3074 of file print.c.

3075 {
3076  always_ignore_sigpipe = ignore;
3077 }

References always_ignore_sigpipe.

Referenced by setQFout().

◆ setDecimalLocale()

void setDecimalLocale ( void  )

Definition at line 3626 of file print.c.

3627 {
3628  struct lconv *extlconv;
3629 
3630  extlconv = localeconv();
3631 
3632  /* Don't accept an empty decimal_point string */
3633  if (*extlconv->decimal_point)
3634  decimal_point = pg_strdup(extlconv->decimal_point);
3635  else
3636  decimal_point = "."; /* SQL output standard */
3637 
3638  /*
3639  * Although the Open Group standard allows locales to supply more than one
3640  * group width, we consider only the first one, and we ignore any attempt
3641  * to suppress grouping by specifying CHAR_MAX. As in the backend's
3642  * cash.c, we must apply a range check to avoid being fooled by variant
3643  * CHAR_MAX values.
3644  */
3645  groupdigits = *extlconv->grouping;
3646  if (groupdigits <= 0 || groupdigits > 6)
3647  groupdigits = 3; /* most common */
3648 
3649  /* Don't accept an empty thousands_sep string, either */
3650  /* similar code exists in formatting.c */
3651  if (*extlconv->thousands_sep)
3652  thousands_sep = pg_strdup(extlconv->thousands_sep);
3653  /* Make sure thousands separator doesn't match decimal point symbol. */
3654  else if (strcmp(decimal_point, ",") != 0)
3655  thousands_sep = ",";
3656  else
3657  thousands_sep = ".";
3658 }

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

3732 {
3733  unsigned char *start = str;
3734  unsigned char *end = str + strlen((char *) str);
3735  int curr_width = 0;
3736 
3737  while (str < end)
3738  {
3739  int char_width = PQdsplen((char *) str, encoding);
3740 
3741  /*
3742  * If the display width of the new character causes the string to
3743  * exceed its target width, skip it and return. However, if this is
3744  * the first character of the string (curr_width == 0), we have to
3745  * accept it.
3746  */
3747  if (*target_width < curr_width + char_width && curr_width != 0)
3748  break;
3749 
3750  curr_width += char_width;
3751 
3752  str += PQmblen((char *) str, encoding);
3753 
3754  if (str > end) /* Don't overrun invalid string */
3755  str = end;
3756  }
3757 
3758  *target_width = curr_width;
3759 
3760  return str - start;
3761 }
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1177
int PQdsplen(const char *s, int encoding)
Definition: fe-misc.c:1197

References encoding, PQdsplen(), PQmblen(), and generate_unaccent_rules::str.

Referenced by print_aligned_text(), and print_aligned_vertical().

◆ troff_ms_escaped_print()

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

Definition at line 2809 of file print.c.

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

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