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 fputnbytes (FILE *f, const char *str, size_t n)
 
static void print_separator (struct separator sep, FILE *fout)
 
static printTableFooterfooters_with_default (const printTableContent *cont)
 
static void print_unaligned_text (const printTableContent *cont, FILE *fout)
 
static void print_unaligned_vertical (const printTableContent *cont, FILE *fout)
 
static void _print_horizontal_line (const unsigned int ncolumns, const unsigned int *widths, unsigned short border, printTextRule pos, const printTextFormat *format, FILE *fout)
 
static void print_aligned_text (const printTableContent *cont, FILE *fout, bool is_pager)
 
static void print_aligned_vertical_line (const printTextFormat *format, const unsigned short opt_border, unsigned long record, unsigned int hwidth, unsigned int dwidth, printTextRule pos, FILE *fout)
 
static void csv_escaped_print (const char *str, FILE *fout)
 
static void csv_print_field (const char *str, FILE *fout, char sep)
 
static void print_csv_text (const printTableContent *cont, FILE *fout)
 
static void print_csv_vertical (const printTableContent *cont, FILE *fout)
 
void html_escaped_print (const char *in, FILE *fout)
 
static void print_html_text (const printTableContent *cont, FILE *fout)
 
static void print_html_vertical (const printTableContent *cont, FILE *fout)
 
static void asciidoc_escaped_print (const char *in, FILE *fout)
 
static void print_asciidoc_text (const printTableContent *cont, FILE *fout)
 
static void print_asciidoc_vertical (const printTableContent *cont, FILE *fout)
 
static void latex_escaped_print (const char *in, FILE *fout)
 
static void print_latex_text (const printTableContent *cont, FILE *fout)
 
static void print_latex_longtable_text (const printTableContent *cont, FILE *fout)
 
static void print_latex_vertical (const printTableContent *cont, FILE *fout)
 
static void troff_ms_escaped_print (const char *in, FILE *fout)
 
static void print_troff_ms_text (const printTableContent *cont, FILE *fout)
 
static void print_troff_ms_vertical (const printTableContent *cont, FILE *fout)
 
void disable_sigpipe_trap (void)
 
void restore_sigpipe_trap (void)
 
void set_sigpipe_trap_state (bool ignore)
 
FILE * PageOutput (int lines, const printTableOpt *topt)
 
void ClosePager (FILE *pagerpipe)
 
void printTableInit (printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
 
void printTableAddHeader (printTableContent *const content, char *header, const bool translate, const char align)
 
void printTableAddCell (printTableContent *const content, char *cell, const bool translate, const bool mustfree)
 
void printTableAddFooter (printTableContent *const content, const char *footer)
 
void printTableSetFooter (printTableContent *const content, const char *footer)
 
void printTableCleanup (printTableContent *const content)
 
void printTable (const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
 
void printQuery (const PGresult *result, const printQueryOpt *opt, FILE *fout, bool is_pager, FILE *flog)
 
char column_type_alignment (Oid ftype)
 
void setDecimalLocale (void)
 
const printTextFormatget_line_style (const printTableOpt *opt)
 
void refresh_utf8format (const printTableOpt *opt)
 

Variables

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

Macro Definition Documentation

◆ LONGTABLE_WHITESPACE

#define LONGTABLE_WHITESPACE   " \t\n"

Typedef Documentation

◆ unicodeStyleBorderFormat

◆ unicodeStyleColumnFormat

◆ unicodeStyleFormat

◆ unicodeStyleRowFormat

Function Documentation

◆ _print_horizontal_line()

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

Definition at line 537 of file print.c.

References fprintf, printTextLineFormat::hrule, i, printTextLineFormat::leftvrule, printTextFormat::lrule, printTextLineFormat::midvrule, and printTextLineFormat::rightvrule.

Referenced by print_aligned_text().

541 {
542  const printTextLineFormat *lformat = &format->lrule[pos];
543  unsigned int i,
544  j;
545 
546  if (border == 1)
547  fputs(lformat->hrule, fout);
548  else if (border == 2)
549  fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
550 
551  for (i = 0; i < ncolumns; i++)
552  {
553  for (j = 0; j < widths[i]; j++)
554  fputs(lformat->hrule, fout);
555 
556  if (i < ncolumns - 1)
557  {
558  if (border == 0)
559  fputc(' ', fout);
560  else
561  fprintf(fout, "%s%s%s", lformat->hrule,
562  lformat->midvrule, lformat->hrule);
563  }
564  }
565 
566  if (border == 2)
567  fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
568  else if (border == 1)
569  fputs(lformat->hrule, fout);
570 
571  fputc('\n', fout);
572 }
const char * midvrule
Definition: print.h:48
printTextLineFormat lrule[4]
Definition: print.h:73
#define fprintf
Definition: port.h:196
const char * hrule
Definition: print.h:46
const char * leftvrule
Definition: print.h:47
const char * rightvrule
Definition: print.h:49
int i

◆ additional_numeric_locale_len()

static int additional_numeric_locale_len ( const char *  my_str)
static

Definition at line 219 of file print.c.

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

Referenced by format_numeric_locale().

220 {
221  int int_len = integer_digits(my_str),
222  len = 0;
223 
224  /* Account for added thousands_sep instances */
225  if (int_len > groupdigits)
226  len += ((int_len - 1) / groupdigits) * strlen(thousands_sep);
227 
228  /* Account for possible additional length of decimal_point */
229  if (strchr(my_str, '.') != NULL)
230  len += strlen(decimal_point) - 1;
231 
232  return len;
233 }
static int integer_digits(const char *my_str)
Definition: print.c:208
static int groupdigits
Definition: print.c:49
static char * decimal_point
Definition: print.c:48
static char * thousands_sep
Definition: print.c:50

◆ asciidoc_escaped_print()

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

Definition at line 2070 of file print.c.

Referenced by print_asciidoc_text(), and print_asciidoc_vertical().

2071 {
2072  const char *p;
2073 
2074  for (p = in; *p; p++)
2075  {
2076  switch (*p)
2077  {
2078  case '|':
2079  fputs("\\|", fout);
2080  break;
2081  default:
2082  fputc(*p, fout);
2083  }
2084  }
2085 }

◆ ClosePager()

void ClosePager ( FILE *  pagerpipe)

Definition at line 3042 of file print.c.

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

3043 {
3044  if (pagerpipe && pagerpipe != stdout)
3045  {
3046  /*
3047  * If printing was canceled midstream, warn about it.
3048  *
3049  * Some pagers like less use Ctrl-C as part of their command set. Even
3050  * so, we abort our processing and warn the user what we did. If the
3051  * pager quit as a result of the SIGINT, this message won't go
3052  * anywhere ...
3053  */
3054  if (cancel_pressed)
3055  fprintf(pagerpipe, _("Interrupted\n"));
3056 
3057  pclose(pagerpipe);
3059  }
3060 }
#define fprintf
Definition: port.h:196
void restore_sigpipe_trap(void)
Definition: print.c:2964
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
#define _(x)
Definition: elog.c:87

◆ column_type_alignment()

char column_type_alignment ( Oid  ftype)

Definition at line 3498 of file print.c.

Referenced by printCrosstab(), and printQuery().

3499 {
3500  char align;
3501 
3502  switch (ftype)
3503  {
3504  case INT2OID:
3505  case INT4OID:
3506  case INT8OID:
3507  case FLOAT4OID:
3508  case FLOAT8OID:
3509  case NUMERICOID:
3510  case OIDOID:
3511  case XIDOID:
3512  case CIDOID:
3513  case CASHOID:
3514  align = 'r';
3515  break;
3516  default:
3517  align = 'l';
3518  break;
3519  }
3520  return align;
3521 }

◆ csv_escaped_print()

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

Definition at line 1742 of file print.c.

Referenced by csv_print_field().

1743 {
1744  const char *p;
1745 
1746  fputc('"', fout);
1747  for (p = str; *p; p++)
1748  {
1749  if (*p == '"')
1750  fputc('"', fout); /* double quotes are doubled */
1751  fputc(*p, fout);
1752  }
1753  fputc('"', fout);
1754 }

◆ csv_print_field()

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

Definition at line 1757 of file print.c.

References csv_escaped_print().

Referenced by print_csv_text(), and print_csv_vertical().

1758 {
1759  /*----------------
1760  * Enclose and escape field contents when one of these conditions is met:
1761  * - the field separator is found in the contents.
1762  * - the field contains a CR or LF.
1763  * - the field contains a double quote.
1764  * - the field is exactly "\.".
1765  * - the field separator is either "\" or ".".
1766  * The last two cases prevent producing a line that the server's COPY
1767  * command would interpret as an end-of-data marker. We only really
1768  * need to ensure that the complete line isn't exactly "\.", but for
1769  * simplicity we apply stronger restrictions here.
1770  *----------------
1771  */
1772  if (strchr(str, sep) != NULL ||
1773  strcspn(str, "\r\n\"") != strlen(str) ||
1774  strcmp(str, "\\.") == 0 ||
1775  sep == '\\' || sep == '.')
1776  csv_escaped_print(str, fout);
1777  else
1778  fputs(str, fout);
1779 }
static void csv_escaped_print(const char *str, FILE *fout)
Definition: print.c:1742

◆ disable_sigpipe_trap()

void disable_sigpipe_trap ( void  )

Definition at line 2941 of file print.c.

References pqsignal(), SIG_IGN, and SIGPIPE.

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

2942 {
2943 #ifndef WIN32
2945 #endif
2946 }
#define SIGPIPE
Definition: win32_port.h:159
#define SIG_IGN
Definition: win32_port.h:151
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170

◆ footers_with_default()

static printTableFooter* footers_with_default ( const printTableContent cont)
static

Definition at line 342 of file print.c.

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

343 {
344  if (cont->footers == NULL && cont->opt->default_footer)
345  {
346  unsigned long total_records;
347 
348  total_records = cont->opt->prior_records + cont->nrows;
350  ngettext("(%lu row)", "(%lu rows)", total_records),
351  total_records);
352 
353  return &default_footer_cell;
354  }
355  else
356  return cont->footers;
357 }
const printTableOpt * opt
Definition: print.h:149
unsigned long prior_records
Definition: print.h:114
#define ngettext(s, p, n)
Definition: c.h:1133
static printTableFooter default_footer_cell
Definition: print.c:53
bool default_footer
Definition: print.h:113
printTableFooter * footers
Definition: print.h:160
#define snprintf
Definition: port.h:192
static char default_footer[100]
Definition: print.c:52

◆ format_numeric_locale()

static char* format_numeric_locale ( const char *  my_str)
static

Definition at line 244 of file print.c.

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

Referenced by printQuery().

245 {
246  char *new_str;
247  int new_len,
248  int_len,
249  leading_digits,
250  i,
251  new_str_pos;
252 
253  /*
254  * If the string doesn't look like a number, return it unchanged. This
255  * check is essential to avoid mangling already-localized "money" values.
256  */
257  if (strspn(my_str, "0123456789+-.eE") != strlen(my_str))
258  return pg_strdup(my_str);
259 
260  new_len = strlen(my_str) + additional_numeric_locale_len(my_str);
261  new_str = pg_malloc(new_len + 1);
262  new_str_pos = 0;
263  int_len = integer_digits(my_str);
264 
265  /* number of digits in first thousands group */
266  leading_digits = int_len % groupdigits;
267  if (leading_digits == 0)
268  leading_digits = groupdigits;
269 
270  /* process sign */
271  if (my_str[0] == '-' || my_str[0] == '+')
272  {
273  new_str[new_str_pos++] = my_str[0];
274  my_str++;
275  }
276 
277  /* process integer part of number */
278  for (i = 0; i < int_len; i++)
279  {
280  /* Time to insert separator? */
281  if (i > 0 && --leading_digits == 0)
282  {
283  strcpy(&new_str[new_str_pos], thousands_sep);
284  new_str_pos += strlen(thousands_sep);
285  leading_digits = groupdigits;
286  }
287  new_str[new_str_pos++] = my_str[i];
288  }
289 
290  /* handle decimal point if any */
291  if (my_str[i] == '.')
292  {
293  strcpy(&new_str[new_str_pos], decimal_point);
294  new_str_pos += strlen(decimal_point);
295  i++;
296  }
297 
298  /* copy the rest (fractional digits and/or exponent, and \0 terminator) */
299  strcpy(&new_str[new_str_pos], &my_str[i]);
300 
301  /* assert we didn't underestimate new_len (an overestimate is OK) */
302  Assert(strlen(new_str) <= new_len);
303 
304  return new_str;
305 }
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
static int integer_digits(const char *my_str)
Definition: print.c:208
static int groupdigits
Definition: print.c:49
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
#define Assert(condition)
Definition: c.h:739
static char * decimal_point
Definition: print.c:48
int i
static char * thousands_sep
Definition: print.c:50
static int additional_numeric_locale_len(const char *my_str)
Definition: print.c:219

◆ fputnbytes()

static void fputnbytes ( FILE *  f,
const char *  str,
size_t  n 
)
static

Definition at line 315 of file print.c.

Referenced by print_aligned_text(), and print_aligned_vertical().

316 {
317  while (n-- > 0)
318  fputc(*str++, f);
319 }

◆ get_line_style()

const printTextFormat* get_line_style ( const printTableOpt opt)

Definition at line 3560 of file print.c.

References printTableOpt::line_style, and pg_asciiformat.

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

3561 {
3562  /*
3563  * Note: this function mainly exists to preserve the convention that a
3564  * printTableOpt struct can be initialized to zeroes to get default
3565  * behavior.
3566  */
3567  if (opt->line_style != NULL)
3568  return opt->line_style;
3569  else
3570  return &pg_asciiformat;
3571 }
const printTextFormat * line_style
Definition: print.h:115
const printTextFormat pg_asciiformat
Definition: print.c:56

◆ html_escaped_print()

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

Definition at line 1854 of file print.c.

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

1855 {
1856  const char *p;
1857  bool leading_space = true;
1858 
1859  for (p = in; *p; p++)
1860  {
1861  switch (*p)
1862  {
1863  case '&':
1864  fputs("&amp;", fout);
1865  break;
1866  case '<':
1867  fputs("&lt;", fout);
1868  break;
1869  case '>':
1870  fputs("&gt;", fout);
1871  break;
1872  case '\n':
1873  fputs("<br />\n", fout);
1874  break;
1875  case '"':
1876  fputs("&quot;", fout);
1877  break;
1878  case ' ':
1879  /* protect leading space, for EXPLAIN output */
1880  if (leading_space)
1881  fputs("&nbsp;", fout);
1882  else
1883  fputs(" ", fout);
1884  break;
1885  default:
1886  fputc(*p, fout);
1887  }
1888  if (*p != ' ')
1889  leading_space = false;
1890  }
1891 }

◆ integer_digits()

static int integer_digits ( const char *  my_str)
static

Definition at line 208 of file print.c.

Referenced by additional_numeric_locale_len(), and format_numeric_locale().

209 {
210  /* ignoring any sign ... */
211  if (my_str[0] == '-' || my_str[0] == '+')
212  my_str++;
213  /* ... count initial integral digits */
214  return strspn(my_str, "0123456789");
215 }

◆ IsPagerNeeded()

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

Definition at line 3290 of file print.c.

References printTableContent::footers, 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().

3292 {
3293  if (*fout == stdout)
3294  {
3295  int lines;
3296 
3297  if (expanded)
3298  lines = (cont->ncolumns + 1) * cont->nrows;
3299  else
3300  lines = cont->nrows + 1;
3301 
3302  if (!cont->opt->tuples_only)
3303  {
3304  printTableFooter *f;
3305 
3306  /*
3307  * FIXME -- this is slightly bogus: it counts the number of
3308  * footers, not the number of lines in them.
3309  */
3310  for (f = cont->footers; f; f = f->next)
3311  lines++;
3312  }
3313 
3314  *fout = PageOutput(lines + extra_lines, cont->opt);
3315  *is_pager = (*fout != stdout);
3316  }
3317  else
3318  *is_pager = false;
3319 }
const printTableOpt * opt
Definition: print.h:149
struct printTableFooter * next
Definition: print.h:140
FILE * PageOutput(int lines, const printTableOpt *topt)
Definition: print.c:2991
bool tuples_only
Definition: print.h:110
printTableFooter * footers
Definition: print.h:160

◆ latex_escaped_print()

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

Definition at line 2294 of file print.c.

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

2295 {
2296  const char *p;
2297 
2298  for (p = in; *p; p++)
2299  switch (*p)
2300  {
2301  /*
2302  * We convert ASCII characters per the recommendations in
2303  * Scott Pakin's "The Comprehensive LATEX Symbol List",
2304  * available from CTAN. For non-ASCII, you're on your own.
2305  */
2306  case '#':
2307  fputs("\\#", fout);
2308  break;
2309  case '$':
2310  fputs("\\$", fout);
2311  break;
2312  case '%':
2313  fputs("\\%", fout);
2314  break;
2315  case '&':
2316  fputs("\\&", fout);
2317  break;
2318  case '<':
2319  fputs("\\textless{}", fout);
2320  break;
2321  case '>':
2322  fputs("\\textgreater{}", fout);
2323  break;
2324  case '\\':
2325  fputs("\\textbackslash{}", fout);
2326  break;
2327  case '^':
2328  fputs("\\^{}", fout);
2329  break;
2330  case '_':
2331  fputs("\\_", fout);
2332  break;
2333  case '{':
2334  fputs("\\{", fout);
2335  break;
2336  case '|':
2337  fputs("\\textbar{}", fout);
2338  break;
2339  case '}':
2340  fputs("\\}", fout);
2341  break;
2342  case '~':
2343  fputs("\\~{}", fout);
2344  break;
2345  case '\n':
2346  /* This is not right, but doing it right seems too hard */
2347  fputs("\\\\", fout);
2348  break;
2349  default:
2350  fputc(*p, fout);
2351  }
2352 }

◆ PageOutput()

FILE* PageOutput ( int  lines,
const printTableOpt topt 
)

Definition at line 2991 of file print.c.

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

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

2992 {
2993  /* check whether we need / can / are supposed to use pager */
2994  if (topt && topt->pager && isatty(fileno(stdin)) && isatty(fileno(stdout)))
2995  {
2996 #ifdef TIOCGWINSZ
2997  unsigned short int pager = topt->pager;
2998  int min_lines = topt->pager_min_lines;
2999  int result;
3000  struct winsize screen_size;
3001 
3002  result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
3003 
3004  /* >= accounts for a one-line prompt */
3005  if (result == -1
3006  || (lines >= screen_size.ws_row && lines >= min_lines)
3007  || pager > 1)
3008 #endif
3009  {
3010  const char *pagerprog;
3011  FILE *pagerpipe;
3012 
3013  pagerprog = getenv("PSQL_PAGER");
3014  if (!pagerprog)
3015  pagerprog = getenv("PAGER");
3016  if (!pagerprog)
3017  pagerprog = DEFAULT_PAGER;
3018  else
3019  {
3020  /* if PAGER is empty or all-white-space, don't use pager */
3021  if (strspn(pagerprog, " \t\r\n") == strlen(pagerprog))
3022  return stdout;
3023  }
3025  pagerpipe = popen(pagerprog, "w");
3026  if (pagerpipe)
3027  return pagerpipe;
3028  /* if popen fails, silently proceed without pager */
3030  }
3031  }
3032 
3033  return stdout;
3034 }
void disable_sigpipe_trap(void)
Definition: print.c:2941
void restore_sigpipe_trap(void)
Definition: print.c:2964
unsigned short int pager
Definition: print.h:106
int pager_min_lines
Definition: print.h:108
#define DEFAULT_PAGER
Definition: print.h:23

◆ print_aligned_text()

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

Definition at line 579 of file print.c.

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(), printTableOpt::format, format, fprintf, fputnbytes(), free, get_line_style(), printTextFormat::header_nl_left, printTextFormat::header_nl_right, printTableContent::headers, i, IsPagerNeeded(), printTextLineFormat::leftvrule, printTextFormat::lrule, printTextLineFormat::midvrule, printTextFormat::midvrule_blank, printTextFormat::midvrule_nl, printTextFormat::midvrule_wrap, printTableContent::ncolumns, printTableFooter::next, printTextFormat::nl_left, printTextFormat::nl_right, 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, lineptr::width, printTextFormat::wrap_left, printTextFormat::wrap_right, and printTextFormat::wrap_right_border.

Referenced by printTable().

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

◆ print_aligned_vertical()

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

Definition at line 1227 of file print.c.

References printTableOpt::border, cancel_pressed, printTableContent::cells, ClosePager(), printTableOpt::columns, printTableFooter::data, encoding, printTableOpt::encoding, printTableOpt::env_columns, printTableContent::footers, footers_with_default(), printTableOpt::format, format, fprintf, fputnbytes(), free, get_line_style(), printTextFormat::header_nl_left, printTextFormat::header_nl_right, printTableContent::headers, i, IsPagerNeeded(), printTextLineFormat::leftvrule, printTextFormat::lrule, printTextLineFormat::midvrule, printTextFormat::midvrule_nl, printTextFormat::midvrule_wrap, printTableContent::ncolumns, printTableFooter::next, printTextFormat::nl_right, printTableContent::nrows, printTableContent::opt, 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, lineptr::width, printTextFormat::wrap_left, and printTextFormat::wrap_right.

Referenced by print_aligned_text(), and printTable().

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

◆ print_aligned_vertical_line()

static void print_aligned_vertical_line ( const printTextFormat format,
const unsigned short  opt_border,
unsigned long  record,
unsigned int  hwidth,
unsigned int  dwidth,
printTextRule  pos,
FILE *  fout 
)
static

Definition at line 1171 of file print.c.

References fprintf, printTextLineFormat::hrule, i, printTextLineFormat::leftvrule, printTextFormat::lrule, printTextLineFormat::midvrule, and printTextLineFormat::rightvrule.

Referenced by print_aligned_vertical().

1178 {
1179  const printTextLineFormat *lformat = &format->lrule[pos];
1180  unsigned int i;
1181  int reclen = 0;
1182 
1183  if (opt_border == 2)
1184  fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
1185  else if (opt_border == 1)
1186  fputs(lformat->hrule, fout);
1187 
1188  if (record)
1189  {
1190  if (opt_border == 0)
1191  reclen = fprintf(fout, "* Record %lu", record);
1192  else
1193  reclen = fprintf(fout, "[ RECORD %lu ]", record);
1194  }
1195  if (opt_border != 2)
1196  reclen++;
1197  if (reclen < 0)
1198  reclen = 0;
1199  for (i = reclen; i < hwidth; i++)
1200  fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1201  reclen -= hwidth;
1202 
1203  if (opt_border > 0)
1204  {
1205  if (reclen-- <= 0)
1206  fputs(lformat->hrule, fout);
1207  if (reclen-- <= 0)
1208  fputs(lformat->midvrule, fout);
1209  if (reclen-- <= 0)
1210  fputs(lformat->hrule, fout);
1211  }
1212  else
1213  {
1214  if (reclen-- <= 0)
1215  fputc(' ', fout);
1216  }
1217  if (reclen < 0)
1218  reclen = 0;
1219  for (i = reclen; i < dwidth; i++)
1220  fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1221  if (opt_border == 2)
1222  fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
1223  fputc('\n', fout);
1224 }
const char * midvrule
Definition: print.h:48
printTextLineFormat lrule[4]
Definition: print.h:73
#define fprintf
Definition: port.h:196
const char * hrule
Definition: print.h:46
const char * leftvrule
Definition: print.h:47
const char * rightvrule
Definition: print.h:49
int i

◆ print_asciidoc_text()

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

Definition at line 2088 of file print.c.

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

2089 {
2090  bool opt_tuples_only = cont->opt->tuples_only;
2091  unsigned short opt_border = cont->opt->border;
2092  unsigned int i;
2093  const char *const *ptr;
2094 
2095  if (cancel_pressed)
2096  return;
2097 
2098  if (cont->opt->start_table)
2099  {
2100  /* print table in new paragraph - enforce preliminary new line */
2101  fputs("\n", fout);
2102 
2103  /* print title */
2104  if (!opt_tuples_only && cont->title)
2105  {
2106  fputs(".", fout);
2107  fputs(cont->title, fout);
2108  fputs("\n", fout);
2109  }
2110 
2111  /* print table [] header definition */
2112  fprintf(fout, "[%scols=\"", !opt_tuples_only ? "options=\"header\"," : "");
2113  for (i = 0; i < cont->ncolumns; i++)
2114  {
2115  if (i != 0)
2116  fputs(",", fout);
2117  fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
2118  }
2119  fputs("\"", fout);
2120  switch (opt_border)
2121  {
2122  case 0:
2123  fputs(",frame=\"none\",grid=\"none\"", fout);
2124  break;
2125  case 1:
2126  fputs(",frame=\"none\"", fout);
2127  break;
2128  case 2:
2129  fputs(",frame=\"all\",grid=\"all\"", fout);
2130  break;
2131  }
2132  fputs("]\n", fout);
2133  fputs("|====\n", fout);
2134 
2135  /* print headers */
2136  if (!opt_tuples_only)
2137  {
2138  for (ptr = cont->headers; *ptr; ptr++)
2139  {
2140  if (ptr != cont->headers)
2141  fputs(" ", fout);
2142  fputs("^l|", fout);
2143  asciidoc_escaped_print(*ptr, fout);
2144  }
2145  fputs("\n", fout);
2146  }
2147  }
2148 
2149  /* print cells */
2150  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2151  {
2152  if (i % cont->ncolumns == 0)
2153  {
2154  if (cancel_pressed)
2155  break;
2156  }
2157 
2158  if (i % cont->ncolumns != 0)
2159  fputs(" ", fout);
2160  fputs("|", fout);
2161 
2162  /* protect against needless spaces */
2163  if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2164  {
2165  if ((i + 1) % cont->ncolumns != 0)
2166  fputs(" ", fout);
2167  }
2168  else
2169  asciidoc_escaped_print(*ptr, fout);
2170 
2171  if ((i + 1) % cont->ncolumns == 0)
2172  fputs("\n", fout);
2173  }
2174 
2175  fputs("|====\n", fout);
2176 
2177  if (cont->opt->stop_table)
2178  {
2179  printTableFooter *footers = footers_with_default(cont);
2180 
2181  /* print footers */
2182  if (!opt_tuples_only && footers != NULL && !cancel_pressed)
2183  {
2184  printTableFooter *f;
2185 
2186  fputs("\n....\n", fout);
2187  for (f = footers; f; f = f->next)
2188  {
2189  fputs(f->data, fout);
2190  fputs("\n", fout);
2191  }
2192  fputs("....\n", fout);
2193  }
2194  }
2195 }
const char * title
Definition: print.h:150
static void asciidoc_escaped_print(const char *in, FILE *fout)
Definition: print.c:2070
static printTableFooter * footers_with_default(const printTableContent *cont)
Definition: print.c:342
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
struct printTableFooter * next
Definition: print.h:140
unsigned short int border
Definition: print.h:104
char * aligns
Definition: print.h:162
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
int i
char * data
Definition: print.h:139
const char ** headers
Definition: print.h:153

◆ print_asciidoc_vertical()

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

Definition at line 2198 of file print.c.

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

2199 {
2200  bool opt_tuples_only = cont->opt->tuples_only;
2201  unsigned short opt_border = cont->opt->border;
2202  unsigned long record = cont->opt->prior_records + 1;
2203  unsigned int i;
2204  const char *const *ptr;
2205 
2206  if (cancel_pressed)
2207  return;
2208 
2209  if (cont->opt->start_table)
2210  {
2211  /* print table in new paragraph - enforce preliminary new line */
2212  fputs("\n", fout);
2213 
2214  /* print title */
2215  if (!opt_tuples_only && cont->title)
2216  {
2217  fputs(".", fout);
2218  fputs(cont->title, fout);
2219  fputs("\n", fout);
2220  }
2221 
2222  /* print table [] header definition */
2223  fputs("[cols=\"h,l\"", fout);
2224  switch (opt_border)
2225  {
2226  case 0:
2227  fputs(",frame=\"none\",grid=\"none\"", fout);
2228  break;
2229  case 1:
2230  fputs(",frame=\"none\"", fout);
2231  break;
2232  case 2:
2233  fputs(",frame=\"all\",grid=\"all\"", fout);
2234  break;
2235  }
2236  fputs("]\n", fout);
2237  fputs("|====\n", fout);
2238  }
2239 
2240  /* print records */
2241  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2242  {
2243  if (i % cont->ncolumns == 0)
2244  {
2245  if (cancel_pressed)
2246  break;
2247  if (!opt_tuples_only)
2248  fprintf(fout,
2249  "2+^|Record %lu\n",
2250  record++);
2251  else
2252  fputs("2+|\n", fout);
2253  }
2254 
2255  fputs("<l|", fout);
2256  asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
2257 
2258  fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">l" : "<l");
2259  /* is string only whitespace? */
2260  if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2261  fputs(" ", fout);
2262  else
2263  asciidoc_escaped_print(*ptr, fout);
2264  fputs("\n", fout);
2265  }
2266 
2267  fputs("|====\n", fout);
2268 
2269  if (cont->opt->stop_table)
2270  {
2271  /* print footers */
2272  if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
2273  {
2274  printTableFooter *f;
2275 
2276  fputs("\n....\n", fout);
2277  for (f = cont->footers; f; f = f->next)
2278  {
2279  fputs(f->data, fout);
2280  fputs("\n", fout);
2281  }
2282  fputs("....\n", fout);
2283  }
2284  }
2285 }
const char * title
Definition: print.h:150
static void asciidoc_escaped_print(const char *in, FILE *fout)
Definition: print.c:2070
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
unsigned long prior_records
Definition: print.h:114
struct printTableFooter * next
Definition: print.h:140
unsigned short int border
Definition: print.h:104
char * aligns
Definition: print.h:162
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
printTableFooter * footers
Definition: print.h:160
int i
char * data
Definition: print.h:139
const char ** headers
Definition: print.h:153

◆ print_csv_text()

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

Definition at line 1782 of file print.c.

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

1783 {
1784  const char *const *ptr;
1785  int i;
1786 
1787  if (cancel_pressed)
1788  return;
1789 
1790  /*
1791  * The title and footer are never printed in csv format. The header is
1792  * printed if opt_tuples_only is false.
1793  *
1794  * Despite RFC 4180 saying that end of lines are CRLF, terminate lines
1795  * with '\n', which prints out as the system-dependent EOL string in text
1796  * mode (typically LF on Unix and CRLF on Windows).
1797  */
1798  if (cont->opt->start_table && !cont->opt->tuples_only)
1799  {
1800  /* print headers */
1801  for (ptr = cont->headers; *ptr; ptr++)
1802  {
1803  if (ptr != cont->headers)
1804  fputc(cont->opt->csvFieldSep[0], fout);
1805  csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1806  }
1807  fputc('\n', fout);
1808  }
1809 
1810  /* print cells */
1811  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1812  {
1813  csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1814  if ((i + 1) % cont->ncolumns)
1815  fputc(cont->opt->csvFieldSep[0], fout);
1816  else
1817  fputc('\n', fout);
1818  }
1819 }
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
bool tuples_only
Definition: print.h:110
static void csv_print_field(const char *str, FILE *fout, char sep)
Definition: print.c:1757
const char ** cells
Definition: print.h:155
char csvFieldSep[2]
Definition: print.h:118
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
int i
const char ** headers
Definition: print.h:153

◆ print_csv_vertical()

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

Definition at line 1822 of file print.c.

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

Referenced by printTable().

1823 {
1824  const char *const *ptr;
1825  int i;
1826 
1827  /* print records */
1828  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1829  {
1830  if (cancel_pressed)
1831  return;
1832 
1833  /* print name of column */
1834  csv_print_field(cont->headers[i % cont->ncolumns], fout,
1835  cont->opt->csvFieldSep[0]);
1836 
1837  /* print field separator */
1838  fputc(cont->opt->csvFieldSep[0], fout);
1839 
1840  /* print field value */
1841  csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1842 
1843  fputc('\n', fout);
1844  }
1845 }
const printTableOpt * opt
Definition: print.h:149
static void csv_print_field(const char *str, FILE *fout, char sep)
Definition: print.c:1757
const char ** cells
Definition: print.h:155
char csvFieldSep[2]
Definition: print.h:118
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
int i
const char ** headers
Definition: print.h:153

◆ print_html_text()

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

Definition at line 1895 of file print.c.

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

1896 {
1897  bool opt_tuples_only = cont->opt->tuples_only;
1898  unsigned short opt_border = cont->opt->border;
1899  const char *opt_table_attr = cont->opt->tableAttr;
1900  unsigned int i;
1901  const char *const *ptr;
1902 
1903  if (cancel_pressed)
1904  return;
1905 
1906  if (cont->opt->start_table)
1907  {
1908  fprintf(fout, "<table border=\"%d\"", opt_border);
1909  if (opt_table_attr)
1910  fprintf(fout, " %s", opt_table_attr);
1911  fputs(">\n", fout);
1912 
1913  /* print title */
1914  if (!opt_tuples_only && cont->title)
1915  {
1916  fputs(" <caption>", fout);
1917  html_escaped_print(cont->title, fout);
1918  fputs("</caption>\n", fout);
1919  }
1920 
1921  /* print headers */
1922  if (!opt_tuples_only)
1923  {
1924  fputs(" <tr>\n", fout);
1925  for (ptr = cont->headers; *ptr; ptr++)
1926  {
1927  fputs(" <th align=\"center\">", fout);
1928  html_escaped_print(*ptr, fout);
1929  fputs("</th>\n", fout);
1930  }
1931  fputs(" </tr>\n", fout);
1932  }
1933  }
1934 
1935  /* print cells */
1936  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1937  {
1938  if (i % cont->ncolumns == 0)
1939  {
1940  if (cancel_pressed)
1941  break;
1942  fputs(" <tr valign=\"top\">\n", fout);
1943  }
1944 
1945  fprintf(fout, " <td align=\"%s\">", cont->aligns[(i) % cont->ncolumns] == 'r' ? "right" : "left");
1946  /* is string only whitespace? */
1947  if ((*ptr)[strspn(*ptr, " \t")] == '\0')
1948  fputs("&nbsp; ", fout);
1949  else
1950  html_escaped_print(*ptr, fout);
1951 
1952  fputs("</td>\n", fout);
1953 
1954  if ((i + 1) % cont->ncolumns == 0)
1955  fputs(" </tr>\n", fout);
1956  }
1957 
1958  if (cont->opt->stop_table)
1959  {
1960  printTableFooter *footers = footers_with_default(cont);
1961 
1962  fputs("</table>\n", fout);
1963 
1964  /* print footers */
1965  if (!opt_tuples_only && footers != NULL && !cancel_pressed)
1966  {
1967  printTableFooter *f;
1968 
1969  fputs("<p>", fout);
1970  for (f = footers; f; f = f->next)
1971  {
1972  html_escaped_print(f->data, fout);
1973  fputs("<br />\n", fout);
1974  }
1975  fputs("</p>", fout);
1976  }
1977 
1978  fputc('\n', fout);
1979  }
1980 }
const char * title
Definition: print.h:150
static printTableFooter * footers_with_default(const printTableContent *cont)
Definition: print.c:342
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
struct printTableFooter * next
Definition: print.h:140
unsigned short int border
Definition: print.h:104
char * aligns
Definition: print.h:162
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
char * tableAttr
Definition: print.h:121
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
int i
char * data
Definition: print.h:139
void html_escaped_print(const char *in, FILE *fout)
Definition: print.c:1854
const char ** headers
Definition: print.h:153

◆ print_html_vertical()

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

Definition at line 1984 of file print.c.

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

1985 {
1986  bool opt_tuples_only = cont->opt->tuples_only;
1987  unsigned short opt_border = cont->opt->border;
1988  const char *opt_table_attr = cont->opt->tableAttr;
1989  unsigned long record = cont->opt->prior_records + 1;
1990  unsigned int i;
1991  const char *const *ptr;
1992 
1993  if (cancel_pressed)
1994  return;
1995 
1996  if (cont->opt->start_table)
1997  {
1998  fprintf(fout, "<table border=\"%d\"", opt_border);
1999  if (opt_table_attr)
2000  fprintf(fout, " %s", opt_table_attr);
2001  fputs(">\n", fout);
2002 
2003  /* print title */
2004  if (!opt_tuples_only && cont->title)
2005  {
2006  fputs(" <caption>", fout);
2007  html_escaped_print(cont->title, fout);
2008  fputs("</caption>\n", fout);
2009  }
2010  }
2011 
2012  /* print records */
2013  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2014  {
2015  if (i % cont->ncolumns == 0)
2016  {
2017  if (cancel_pressed)
2018  break;
2019  if (!opt_tuples_only)
2020  fprintf(fout,
2021  "\n <tr><td colspan=\"2\" align=\"center\">Record %lu</td></tr>\n",
2022  record++);
2023  else
2024  fputs("\n <tr><td colspan=\"2\">&nbsp;</td></tr>\n", fout);
2025  }
2026  fputs(" <tr valign=\"top\">\n"
2027  " <th>", fout);
2028  html_escaped_print(cont->headers[i % cont->ncolumns], fout);
2029  fputs("</th>\n", fout);
2030 
2031  fprintf(fout, " <td align=\"%s\">", cont->aligns[i % cont->ncolumns] == 'r' ? "right" : "left");
2032  /* is string only whitespace? */
2033  if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2034  fputs("&nbsp; ", fout);
2035  else
2036  html_escaped_print(*ptr, fout);
2037 
2038  fputs("</td>\n </tr>\n", fout);
2039  }
2040 
2041  if (cont->opt->stop_table)
2042  {
2043  fputs("</table>\n", fout);
2044 
2045  /* print footers */
2046  if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
2047  {
2048  printTableFooter *f;
2049 
2050  fputs("<p>", fout);
2051  for (f = cont->footers; f; f = f->next)
2052  {
2053  html_escaped_print(f->data, fout);
2054  fputs("<br />\n", fout);
2055  }
2056  fputs("</p>", fout);
2057  }
2058 
2059  fputc('\n', fout);
2060  }
2061 }
const char * title
Definition: print.h:150
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
unsigned long prior_records
Definition: print.h:114
struct printTableFooter * next
Definition: print.h:140
unsigned short int border
Definition: print.h:104
char * aligns
Definition: print.h:162
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
char * tableAttr
Definition: print.h:121
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
printTableFooter * footers
Definition: print.h:160
int i
char * data
Definition: print.h:139
void html_escaped_print(const char *in, FILE *fout)
Definition: print.c:1854
const char ** headers
Definition: print.h:153

◆ print_latex_longtable_text()

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

Definition at line 2463 of file print.c.

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

2464 {
2465  bool opt_tuples_only = cont->opt->tuples_only;
2466  unsigned short opt_border = cont->opt->border;
2467  unsigned int i;
2468  const char *opt_table_attr = cont->opt->tableAttr;
2469  const char *next_opt_table_attr_char = opt_table_attr;
2470  const char *last_opt_table_attr_char = NULL;
2471  const char *const *ptr;
2472 
2473  if (cancel_pressed)
2474  return;
2475 
2476  if (opt_border > 3)
2477  opt_border = 3;
2478 
2479  if (cont->opt->start_table)
2480  {
2481  /* begin environment and set alignments and borders */
2482  fputs("\\begin{longtable}{", fout);
2483 
2484  if (opt_border >= 2)
2485  fputs("| ", fout);
2486 
2487  for (i = 0; i < cont->ncolumns; i++)
2488  {
2489  /* longtable supports either a width (p) or an alignment (l/r) */
2490  /* Are we left-justified and was a proportional width specified? */
2491  if (*(cont->aligns + i) == 'l' && opt_table_attr)
2492  {
2493 #define LONGTABLE_WHITESPACE " \t\n"
2494 
2495  /* advance over whitespace */
2496  next_opt_table_attr_char += strspn(next_opt_table_attr_char,
2498  /* We have a value? */
2499  if (next_opt_table_attr_char[0] != '\0')
2500  {
2501  fputs("p{", fout);
2502  fwrite(next_opt_table_attr_char, strcspn(next_opt_table_attr_char,
2503  LONGTABLE_WHITESPACE), 1, fout);
2504  last_opt_table_attr_char = next_opt_table_attr_char;
2505  next_opt_table_attr_char += strcspn(next_opt_table_attr_char,
2507  fputs("\\textwidth}", fout);
2508  }
2509  /* use previous value */
2510  else if (last_opt_table_attr_char != NULL)
2511  {
2512  fputs("p{", fout);
2513  fwrite(last_opt_table_attr_char, strcspn(last_opt_table_attr_char,
2514  LONGTABLE_WHITESPACE), 1, fout);
2515  fputs("\\textwidth}", fout);
2516  }
2517  else
2518  fputc('l', fout);
2519  }
2520  else
2521  fputc(*(cont->aligns + i), fout);
2522 
2523  if (opt_border != 0 && i < cont->ncolumns - 1)
2524  fputs(" | ", fout);
2525  }
2526 
2527  if (opt_border >= 2)
2528  fputs(" |", fout);
2529 
2530  fputs("}\n", fout);
2531 
2532  /* print headers */
2533  if (!opt_tuples_only)
2534  {
2535  /* firsthead */
2536  if (opt_border >= 2)
2537  fputs("\\toprule\n", fout);
2538  for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2539  {
2540  if (i != 0)
2541  fputs(" & ", fout);
2542  fputs("\\small\\textbf{\\textit{", fout);
2543  latex_escaped_print(*ptr, fout);
2544  fputs("}}", fout);
2545  }
2546  fputs(" \\\\\n", fout);
2547  fputs("\\midrule\n\\endfirsthead\n", fout);
2548 
2549  /* secondary heads */
2550  if (opt_border >= 2)
2551  fputs("\\toprule\n", fout);
2552  for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2553  {
2554  if (i != 0)
2555  fputs(" & ", fout);
2556  fputs("\\small\\textbf{\\textit{", fout);
2557  latex_escaped_print(*ptr, fout);
2558  fputs("}}", fout);
2559  }
2560  fputs(" \\\\\n", fout);
2561  /* If the line under the row already appeared, don't do another */
2562  if (opt_border != 3)
2563  fputs("\\midrule\n", fout);
2564  fputs("\\endhead\n", fout);
2565 
2566  /* table name, caption? */
2567  if (!opt_tuples_only && cont->title)
2568  {
2569  /* Don't output if we are printing a line under each row */
2570  if (opt_border == 2)
2571  fputs("\\bottomrule\n", fout);
2572  fputs("\\caption[", fout);
2573  latex_escaped_print(cont->title, fout);
2574  fputs(" (Continued)]{", fout);
2575  latex_escaped_print(cont->title, fout);
2576  fputs("}\n\\endfoot\n", fout);
2577  if (opt_border == 2)
2578  fputs("\\bottomrule\n", fout);
2579  fputs("\\caption[", fout);
2580  latex_escaped_print(cont->title, fout);
2581  fputs("]{", fout);
2582  latex_escaped_print(cont->title, fout);
2583  fputs("}\n\\endlastfoot\n", fout);
2584  }
2585  /* output bottom table line? */
2586  else if (opt_border >= 2)
2587  {
2588  fputs("\\bottomrule\n\\endfoot\n", fout);
2589  fputs("\\bottomrule\n\\endlastfoot\n", fout);
2590  }
2591  }
2592  }
2593 
2594  /* print cells */
2595  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2596  {
2597  /* Add a line under each row? */
2598  if (i != 0 && i % cont->ncolumns != 0)
2599  fputs("\n&\n", fout);
2600  fputs("\\raggedright{", fout);
2601  latex_escaped_print(*ptr, fout);
2602  fputc('}', fout);
2603  if ((i + 1) % cont->ncolumns == 0)
2604  {
2605  fputs(" \\tabularnewline\n", fout);
2606  if (opt_border == 3)
2607  fputs(" \\hline\n", fout);
2608  }
2609  if (cancel_pressed)
2610  break;
2611  }
2612 
2613  if (cont->opt->stop_table)
2614  fputs("\\end{longtable}\n", fout);
2615 }
const char * title
Definition: print.h:150
static void latex_escaped_print(const char *in, FILE *fout)
Definition: print.c:2294
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
unsigned short int border
Definition: print.h:104
char * aligns
Definition: print.h:162
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
#define LONGTABLE_WHITESPACE
char * tableAttr
Definition: print.h:121
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
int i
const char ** headers
Definition: print.h:153

◆ print_latex_text()

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

Definition at line 2356 of file print.c.

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

2357 {
2358  bool opt_tuples_only = cont->opt->tuples_only;
2359  unsigned short opt_border = cont->opt->border;
2360  unsigned int i;
2361  const char *const *ptr;
2362 
2363  if (cancel_pressed)
2364  return;
2365 
2366  if (opt_border > 3)
2367  opt_border = 3;
2368 
2369  if (cont->opt->start_table)
2370  {
2371  /* print title */
2372  if (!opt_tuples_only && cont->title)
2373  {
2374  fputs("\\begin{center}\n", fout);
2375  latex_escaped_print(cont->title, fout);
2376  fputs("\n\\end{center}\n\n", fout);
2377  }
2378 
2379  /* begin environment and set alignments and borders */
2380  fputs("\\begin{tabular}{", fout);
2381 
2382  if (opt_border >= 2)
2383  fputs("| ", fout);
2384  for (i = 0; i < cont->ncolumns; i++)
2385  {
2386  fputc(*(cont->aligns + i), fout);
2387  if (opt_border != 0 && i < cont->ncolumns - 1)
2388  fputs(" | ", fout);
2389  }
2390  if (opt_border >= 2)
2391  fputs(" |", fout);
2392 
2393  fputs("}\n", fout);
2394 
2395  if (!opt_tuples_only && opt_border >= 2)
2396  fputs("\\hline\n", fout);
2397 
2398  /* print headers */
2399  if (!opt_tuples_only)
2400  {
2401  for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2402  {
2403  if (i != 0)
2404  fputs(" & ", fout);
2405  fputs("\\textit{", fout);
2406  latex_escaped_print(*ptr, fout);
2407  fputc('}', fout);
2408  }
2409  fputs(" \\\\\n", fout);
2410  fputs("\\hline\n", fout);
2411  }
2412  }
2413 
2414  /* print cells */
2415  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2416  {
2417  latex_escaped_print(*ptr, fout);
2418 
2419  if ((i + 1) % cont->ncolumns == 0)
2420  {
2421  fputs(" \\\\\n", fout);
2422  if (opt_border == 3)
2423  fputs("\\hline\n", fout);
2424  if (cancel_pressed)
2425  break;
2426  }
2427  else
2428  fputs(" & ", fout);
2429  }
2430 
2431  if (cont->opt->stop_table)
2432  {
2433  printTableFooter *footers = footers_with_default(cont);
2434 
2435  if (opt_border == 2)
2436  fputs("\\hline\n", fout);
2437 
2438  fputs("\\end{tabular}\n\n\\noindent ", fout);
2439 
2440  /* print footers */
2441  if (footers && !opt_tuples_only && !cancel_pressed)
2442  {
2443  printTableFooter *f;
2444 
2445  for (f = footers; f; f = f->next)
2446  {
2447  latex_escaped_print(f->data, fout);
2448  fputs(" \\\\\n", fout);
2449  }
2450  }
2451 
2452  fputc('\n', fout);
2453  }
2454 }
const char * title
Definition: print.h:150
static void latex_escaped_print(const char *in, FILE *fout)
Definition: print.c:2294
static printTableFooter * footers_with_default(const printTableContent *cont)
Definition: print.c:342
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
struct printTableFooter * next
Definition: print.h:140
unsigned short int border
Definition: print.h:104
char * aligns
Definition: print.h:162
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
int i
char * data
Definition: print.h:139
const char ** headers
Definition: print.h:153

◆ print_latex_vertical()

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

Definition at line 2619 of file print.c.

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

2620 {
2621  bool opt_tuples_only = cont->opt->tuples_only;
2622  unsigned short opt_border = cont->opt->border;
2623  unsigned long record = cont->opt->prior_records + 1;
2624  unsigned int i;
2625  const char *const *ptr;
2626 
2627  if (cancel_pressed)
2628  return;
2629 
2630  if (opt_border > 2)
2631  opt_border = 2;
2632 
2633  if (cont->opt->start_table)
2634  {
2635  /* print title */
2636  if (!opt_tuples_only && cont->title)
2637  {
2638  fputs("\\begin{center}\n", fout);
2639  latex_escaped_print(cont->title, fout);
2640  fputs("\n\\end{center}\n\n", fout);
2641  }
2642 
2643  /* begin environment and set alignments and borders */
2644  fputs("\\begin{tabular}{", fout);
2645  if (opt_border == 0)
2646  fputs("cl", fout);
2647  else if (opt_border == 1)
2648  fputs("c|l", fout);
2649  else if (opt_border == 2)
2650  fputs("|c|l|", fout);
2651  fputs("}\n", fout);
2652  }
2653 
2654  /* print records */
2655  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2656  {
2657  /* new record */
2658  if (i % cont->ncolumns == 0)
2659  {
2660  if (cancel_pressed)
2661  break;
2662  if (!opt_tuples_only)
2663  {
2664  if (opt_border == 2)
2665  {
2666  fputs("\\hline\n", fout);
2667  fprintf(fout, "\\multicolumn{2}{|c|}{\\textit{Record %lu}} \\\\\n", record++);
2668  }
2669  else
2670  fprintf(fout, "\\multicolumn{2}{c}{\\textit{Record %lu}} \\\\\n", record++);
2671  }
2672  if (opt_border >= 1)
2673  fputs("\\hline\n", fout);
2674  }
2675 
2676  latex_escaped_print(cont->headers[i % cont->ncolumns], fout);
2677  fputs(" & ", fout);
2678  latex_escaped_print(*ptr, fout);
2679  fputs(" \\\\\n", fout);
2680  }
2681 
2682  if (cont->opt->stop_table)
2683  {
2684  if (opt_border == 2)
2685  fputs("\\hline\n", fout);
2686 
2687  fputs("\\end{tabular}\n\n\\noindent ", fout);
2688 
2689  /* print footers */
2690  if (cont->footers && !opt_tuples_only && !cancel_pressed)
2691  {
2692  printTableFooter *f;
2693 
2694  for (f = cont->footers; f; f = f->next)
2695  {
2696  latex_escaped_print(f->data, fout);
2697  fputs(" \\\\\n", fout);
2698  }
2699  }
2700 
2701  fputc('\n', fout);
2702  }
2703 }
const char * title
Definition: print.h:150
static void latex_escaped_print(const char *in, FILE *fout)
Definition: print.c:2294
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
unsigned long prior_records
Definition: print.h:114
struct printTableFooter * next
Definition: print.h:140
unsigned short int border
Definition: print.h:104
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
printTableFooter * footers
Definition: print.h:160
int i
char * data
Definition: print.h:139
const char ** headers
Definition: print.h:153

◆ print_separator()

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

Definition at line 323 of file print.c.

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

Referenced by print_unaligned_text(), and print_unaligned_vertical().

324 {
325  if (sep.separator_zero)
326  fputc('\000', fout);
327  else if (sep.separator)
328  fputs(sep.separator, fout);
329 }
bool separator_zero
Definition: print.h:96
char * separator
Definition: print.h:95

◆ print_troff_ms_text()

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

Definition at line 2729 of file print.c.

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

2730 {
2731  bool opt_tuples_only = cont->opt->tuples_only;
2732  unsigned short opt_border = cont->opt->border;
2733  unsigned int i;
2734  const char *const *ptr;
2735 
2736  if (cancel_pressed)
2737  return;
2738 
2739  if (opt_border > 2)
2740  opt_border = 2;
2741 
2742  if (cont->opt->start_table)
2743  {
2744  /* print title */
2745  if (!opt_tuples_only && cont->title)
2746  {
2747  fputs(".LP\n.DS C\n", fout);
2748  troff_ms_escaped_print(cont->title, fout);
2749  fputs("\n.DE\n", fout);
2750  }
2751 
2752  /* begin environment and set alignments and borders */
2753  fputs(".LP\n.TS\n", fout);
2754  if (opt_border == 2)
2755  fputs("center box;\n", fout);
2756  else
2757  fputs("center;\n", fout);
2758 
2759  for (i = 0; i < cont->ncolumns; i++)
2760  {
2761  fputc(*(cont->aligns + i), fout);
2762  if (opt_border > 0 && i < cont->ncolumns - 1)
2763  fputs(" | ", fout);
2764  }
2765  fputs(".\n", fout);
2766 
2767  /* print headers */
2768  if (!opt_tuples_only)
2769  {
2770  for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2771  {
2772  if (i != 0)
2773  fputc('\t', fout);
2774  fputs("\\fI", fout);
2775  troff_ms_escaped_print(*ptr, fout);
2776  fputs("\\fP", fout);
2777  }
2778  fputs("\n_\n", fout);
2779  }
2780  }
2781 
2782  /* print cells */
2783  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2784  {
2785  troff_ms_escaped_print(*ptr, fout);
2786 
2787  if ((i + 1) % cont->ncolumns == 0)
2788  {
2789  fputc('\n', fout);
2790  if (cancel_pressed)
2791  break;
2792  }
2793  else
2794  fputc('\t', fout);
2795  }
2796 
2797  if (cont->opt->stop_table)
2798  {
2799  printTableFooter *footers = footers_with_default(cont);
2800 
2801  fputs(".TE\n.DS L\n", fout);
2802 
2803  /* print footers */
2804  if (footers && !opt_tuples_only && !cancel_pressed)
2805  {
2806  printTableFooter *f;
2807 
2808  for (f = footers; f; f = f->next)
2809  {
2810  troff_ms_escaped_print(f->data, fout);
2811  fputc('\n', fout);
2812  }
2813  }
2814 
2815  fputs(".DE\n", fout);
2816  }
2817 }
const char * title
Definition: print.h:150
static printTableFooter * footers_with_default(const printTableContent *cont)
Definition: print.c:342
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
struct printTableFooter * next
Definition: print.h:140
unsigned short int border
Definition: print.h:104
char * aligns
Definition: print.h:162
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
static void troff_ms_escaped_print(const char *in, FILE *fout)
Definition: print.c:2712
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
int i
char * data
Definition: print.h:139
const char ** headers
Definition: print.h:153

◆ print_troff_ms_vertical()

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

Definition at line 2821 of file print.c.

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

2822 {
2823  bool opt_tuples_only = cont->opt->tuples_only;
2824  unsigned short opt_border = cont->opt->border;
2825  unsigned long record = cont->opt->prior_records + 1;
2826  unsigned int i;
2827  const char *const *ptr;
2828  unsigned short current_format = 0; /* 0=none, 1=header, 2=body */
2829 
2830  if (cancel_pressed)
2831  return;
2832 
2833  if (opt_border > 2)
2834  opt_border = 2;
2835 
2836  if (cont->opt->start_table)
2837  {
2838  /* print title */
2839  if (!opt_tuples_only && cont->title)
2840  {
2841  fputs(".LP\n.DS C\n", fout);
2842  troff_ms_escaped_print(cont->title, fout);
2843  fputs("\n.DE\n", fout);
2844  }
2845 
2846  /* begin environment and set alignments and borders */
2847  fputs(".LP\n.TS\n", fout);
2848  if (opt_border == 2)
2849  fputs("center box;\n", fout);
2850  else
2851  fputs("center;\n", fout);
2852 
2853  /* basic format */
2854  if (opt_tuples_only)
2855  fputs("c l;\n", fout);
2856  }
2857  else
2858  current_format = 2; /* assume tuples printed already */
2859 
2860  /* print records */
2861  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2862  {
2863  /* new record */
2864  if (i % cont->ncolumns == 0)
2865  {
2866  if (cancel_pressed)
2867  break;
2868  if (!opt_tuples_only)
2869  {
2870  if (current_format != 1)
2871  {
2872  if (opt_border == 2 && record > 1)
2873  fputs("_\n", fout);
2874  if (current_format != 0)
2875  fputs(".T&\n", fout);
2876  fputs("c s.\n", fout);
2877  current_format = 1;
2878  }
2879  fprintf(fout, "\\fIRecord %lu\\fP\n", record++);
2880  }
2881  if (opt_border >= 1)
2882  fputs("_\n", fout);
2883  }
2884 
2885  if (!opt_tuples_only)
2886  {
2887  if (current_format != 2)
2888  {
2889  if (current_format != 0)
2890  fputs(".T&\n", fout);
2891  if (opt_border != 1)
2892  fputs("c l.\n", fout);
2893  else
2894  fputs("c | l.\n", fout);
2895  current_format = 2;
2896  }
2897  }
2898 
2899  troff_ms_escaped_print(cont->headers[i % cont->ncolumns], fout);
2900  fputc('\t', fout);
2901  troff_ms_escaped_print(*ptr, fout);
2902 
2903  fputc('\n', fout);
2904  }
2905 
2906  if (cont->opt->stop_table)
2907  {
2908  fputs(".TE\n.DS L\n", fout);
2909 
2910  /* print footers */
2911  if (cont->footers && !opt_tuples_only && !cancel_pressed)
2912  {
2913  printTableFooter *f;
2914 
2915  for (f = cont->footers; f; f = f->next)
2916  {
2917  troff_ms_escaped_print(f->data, fout);
2918  fputc('\n', fout);
2919  }
2920  }
2921 
2922  fputs(".DE\n", fout);
2923  }
2924 }
const char * title
Definition: print.h:150
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
unsigned long prior_records
Definition: print.h:114
struct printTableFooter * next
Definition: print.h:140
unsigned short int border
Definition: print.h:104
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
static void troff_ms_escaped_print(const char *in, FILE *fout)
Definition: print.c:2712
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
printTableFooter * footers
Definition: print.h:160
int i
char * data
Definition: print.h:139
const char ** headers
Definition: print.h:153

◆ print_unaligned_text()

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

Definition at line 366 of file print.c.

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

367 {
368  bool opt_tuples_only = cont->opt->tuples_only;
369  unsigned int i;
370  const char *const *ptr;
371  bool need_recordsep = false;
372 
373  if (cancel_pressed)
374  return;
375 
376  if (cont->opt->start_table)
377  {
378  /* print title */
379  if (!opt_tuples_only && cont->title)
380  {
381  fputs(cont->title, fout);
382  print_separator(cont->opt->recordSep, fout);
383  }
384 
385  /* print headers */
386  if (!opt_tuples_only)
387  {
388  for (ptr = cont->headers; *ptr; ptr++)
389  {
390  if (ptr != cont->headers)
391  print_separator(cont->opt->fieldSep, fout);
392  fputs(*ptr, fout);
393  }
394  need_recordsep = true;
395  }
396  }
397  else
398  /* assume continuing printout */
399  need_recordsep = true;
400 
401  /* print cells */
402  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
403  {
404  if (need_recordsep)
405  {
406  print_separator(cont->opt->recordSep, fout);
407  need_recordsep = false;
408  if (cancel_pressed)
409  break;
410  }
411  fputs(*ptr, fout);
412 
413  if ((i + 1) % cont->ncolumns)
414  print_separator(cont->opt->fieldSep, fout);
415  else
416  need_recordsep = true;
417  }
418 
419  /* print footers */
420  if (cont->opt->stop_table)
421  {
422  printTableFooter *footers = footers_with_default(cont);
423 
424  if (!opt_tuples_only && footers != NULL && !cancel_pressed)
425  {
426  printTableFooter *f;
427 
428  for (f = footers; f; f = f->next)
429  {
430  if (need_recordsep)
431  {
432  print_separator(cont->opt->recordSep, fout);
433  need_recordsep = false;
434  }
435  fputs(f->data, fout);
436  need_recordsep = true;
437  }
438  }
439 
440  /*
441  * The last record is terminated by a newline, independent of the set
442  * record separator. But when the record separator is a zero byte, we
443  * use that (compatible with find -print0 and xargs).
444  */
445  if (need_recordsep)
446  {
447  if (cont->opt->recordSep.separator_zero)
448  print_separator(cont->opt->recordSep, fout);
449  else
450  fputc('\n', fout);
451  }
452  }
453 }
const char * title
Definition: print.h:150
static void print_separator(struct separator sep, FILE *fout)
Definition: print.c:323
static printTableFooter * footers_with_default(const printTableContent *cont)
Definition: print.c:342
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
bool separator_zero
Definition: print.h:96
struct printTableFooter * next
Definition: print.h:140
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
struct separator fieldSep
Definition: print.h:116
int i
char * data
Definition: print.h:139
const char ** headers
Definition: print.h:153
struct separator recordSep
Definition: print.h:117

◆ print_unaligned_vertical()

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

Definition at line 457 of file print.c.

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

458 {
459  bool opt_tuples_only = cont->opt->tuples_only;
460  unsigned int i;
461  const char *const *ptr;
462  bool need_recordsep = false;
463 
464  if (cancel_pressed)
465  return;
466 
467  if (cont->opt->start_table)
468  {
469  /* print title */
470  if (!opt_tuples_only && cont->title)
471  {
472  fputs(cont->title, fout);
473  need_recordsep = true;
474  }
475  }
476  else
477  /* assume continuing printout */
478  need_recordsep = true;
479 
480  /* print records */
481  for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
482  {
483  if (need_recordsep)
484  {
485  /* record separator is 2 occurrences of recordsep in this mode */
486  print_separator(cont->opt->recordSep, fout);
487  print_separator(cont->opt->recordSep, fout);
488  need_recordsep = false;
489  if (cancel_pressed)
490  break;
491  }
492 
493  fputs(cont->headers[i % cont->ncolumns], fout);
494  print_separator(cont->opt->fieldSep, fout);
495  fputs(*ptr, fout);
496 
497  if ((i + 1) % cont->ncolumns)
498  print_separator(cont->opt->recordSep, fout);
499  else
500  need_recordsep = true;
501  }
502 
503  if (cont->opt->stop_table)
504  {
505  /* print footers */
506  if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
507  {
508  printTableFooter *f;
509 
510  print_separator(cont->opt->recordSep, fout);
511  for (f = cont->footers; f; f = f->next)
512  {
513  print_separator(cont->opt->recordSep, fout);
514  fputs(f->data, fout);
515  }
516  }
517 
518  /* see above in print_unaligned_text() */
519  if (need_recordsep)
520  {
521  if (cont->opt->recordSep.separator_zero)
522  print_separator(cont->opt->recordSep, fout);
523  else
524  fputc('\n', fout);
525  }
526  }
527 }
const char * title
Definition: print.h:150
static void print_separator(struct separator sep, FILE *fout)
Definition: print.c:323
bool start_table
Definition: print.h:111
const printTableOpt * opt
Definition: print.h:149
bool separator_zero
Definition: print.h:96
struct printTableFooter * next
Definition: print.h:140
bool tuples_only
Definition: print.h:110
const char ** cells
Definition: print.h:155
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
bool stop_table
Definition: print.h:112
struct separator fieldSep
Definition: print.h:116
printTableFooter * footers
Definition: print.h:160
int i
char * data
Definition: print.h:139
const char ** headers
Definition: print.h:153
struct separator recordSep
Definition: print.h:117

◆ printQuery()

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

Definition at line 3433 of file print.c.

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(), describeFunctions(), describeOneTableDetails(), describeOneTSConfig(), describeOneTSParser(), describeOperators(), describeSubscriptions(), describeTablespaces(), describeTypes(), do_lo_list(), ExecQueryUsingCursor(), listAllDbs(), listCasts(), listCollations(), listConversions(), listDbRoleSettings(), listDefaultACLs(), listDomains(), listEventTriggers(), listExtensions(), listForeignDataWrappers(), listForeignServers(), listForeignTables(), listLanguages(), listOneExtensionContents(), listPartitionedTables(), listPublications(), listSchemas(), listTables(), listTSConfigs(), listTSDictionaries(), listTSParsers(), listTSTemplates(), listUserMappings(), objectDescription(), permissionsList(), PrintQueryTuples(), and PSQLexecWatch().

3435 {
3436  printTableContent cont;
3437  int i,
3438  r,
3439  c;
3440 
3441  if (cancel_pressed)
3442  return;
3443 
3444  printTableInit(&cont, &opt->topt, opt->title,
3445  PQnfields(result), PQntuples(result));
3446 
3447  /* Assert caller supplied enough translate_columns[] entries */
3448  Assert(opt->translate_columns == NULL ||
3449  opt->n_translate_columns >= cont.ncolumns);
3450 
3451  for (i = 0; i < cont.ncolumns; i++)
3452  {
3453  printTableAddHeader(&cont, PQfname(result, i),
3454  opt->translate_header,
3455  column_type_alignment(PQftype(result, i)));
3456  }
3457 
3458  /* set cells */
3459  for (r = 0; r < cont.nrows; r++)
3460  {
3461  for (c = 0; c < cont.ncolumns; c++)
3462  {
3463  char *cell;
3464  bool mustfree = false;
3465  bool translate;
3466 
3467  if (PQgetisnull(result, r, c))
3468  cell = opt->nullPrint ? opt->nullPrint : "";
3469  else
3470  {
3471  cell = PQgetvalue(result, r, c);
3472  if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
3473  {
3474  cell = format_numeric_locale(cell);
3475  mustfree = true;
3476  }
3477  }
3478 
3479  translate = (opt->translate_columns && opt->translate_columns[c]);
3480  printTableAddCell(&cont, cell, translate, mustfree);
3481  }
3482  }
3483 
3484  /* set footers */
3485  if (opt->footers)
3486  {
3487  char **footer;
3488 
3489  for (footer = opt->footers; *footer; footer++)
3490  printTableAddFooter(&cont, *footer);
3491  }
3492 
3493  printTable(&cont, fout, is_pager, flog);
3494  printTableCleanup(&cont);
3495 }
int PQnfields(const PGresult *res)
Definition: fe-exec.c:2777
char * nullPrint
Definition: print.h:170
void printTableCleanup(printTableContent *const content)
Definition: print.c:3241
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3163
char * PQfname(const PGresult *res, int field_num)
Definition: fe-exec.c:2855
printTableOpt topt
Definition: print.h:169
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2769
Datum translate(PG_FUNCTION_ARGS)
void printTableAddHeader(printTableContent *const content, char *header, const bool translate, const char align)
Definition: print.c:3110
char * aligns
Definition: print.h:162
void printTableAddCell(printTableContent *const content, char *cell, const bool translate, const bool mustfree)
Definition: print.c:3150
Oid PQftype(const PGresult *res, int field_num)
Definition: fe-exec.c:3007
char * c
bool translate_header
Definition: print.h:173
void printTable(const printTableContent *cont, FILE *fout, bool is_pager, FILE *flog)
Definition: print.c:3330
char column_type_alignment(Oid ftype)
Definition: print.c:3498
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3198
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
char * title
Definition: print.h:171
char ** footers
Definition: print.h:172
static char * format_numeric_locale(const char *my_str)
Definition: print.c:244
#define Assert(condition)
Definition: c.h:739
int n_translate_columns
Definition: print.h:176
void printTableInit(printTableContent *const content, const printTableOpt *opt, const char *title, const int ncolumns, const int nrows)
Definition: print.c:3073
bool numericLocale
Definition: print.h:119
int i
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3188
const bool * translate_columns
Definition: print.h:174

◆ printTable()

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

Definition at line 3330 of file print.c.

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

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

3332 {
3333  bool is_local_pager = false;
3334 
3335  if (cancel_pressed)
3336  return;
3337 
3338  if (cont->opt->format == PRINT_NOTHING)
3339  return;
3340 
3341  /* print_aligned_*() handle the pager themselves */
3342  if (!is_pager &&
3343  cont->opt->format != PRINT_ALIGNED &&
3344  cont->opt->format != PRINT_WRAPPED)
3345  {
3346  IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager);
3347  is_local_pager = is_pager;
3348  }
3349 
3350  /* print the stuff */
3351 
3352  if (flog)
3353  print_aligned_text(cont, flog, false);
3354 
3355  switch (cont->opt->format)
3356  {
3357  case PRINT_UNALIGNED:
3358  if (cont->opt->expanded == 1)
3359  print_unaligned_vertical(cont, fout);
3360  else
3361  print_unaligned_text(cont, fout);
3362  break;
3363  case PRINT_ALIGNED:
3364  case PRINT_WRAPPED:
3365 
3366  /*
3367  * In expanded-auto mode, force vertical if a pager is passed in;
3368  * else we may make different decisions for different hunks of the
3369  * query result.
3370  */
3371  if (cont->opt->expanded == 1 ||
3372  (cont->opt->expanded == 2 && is_pager))
3373  print_aligned_vertical(cont, fout, is_pager);
3374  else
3375  print_aligned_text(cont, fout, is_pager);
3376  break;
3377  case PRINT_CSV:
3378  if (cont->opt->expanded == 1)
3379  print_csv_vertical(cont, fout);
3380  else
3381  print_csv_text(cont, fout);
3382  break;
3383  case PRINT_HTML:
3384  if (cont->opt->expanded == 1)
3385  print_html_vertical(cont, fout);
3386  else
3387  print_html_text(cont, fout);
3388  break;
3389  case PRINT_ASCIIDOC:
3390  if (cont->opt->expanded == 1)
3391  print_asciidoc_vertical(cont, fout);
3392  else
3393  print_asciidoc_text(cont, fout);
3394  break;
3395  case PRINT_LATEX:
3396  if (cont->opt->expanded == 1)
3397  print_latex_vertical(cont, fout);
3398  else
3399  print_latex_text(cont, fout);
3400  break;
3401  case PRINT_LATEX_LONGTABLE:
3402  if (cont->opt->expanded == 1)
3403  print_latex_vertical(cont, fout);
3404  else
3405  print_latex_longtable_text(cont, fout);
3406  break;
3407  case PRINT_TROFF_MS:
3408  if (cont->opt->expanded == 1)
3409  print_troff_ms_vertical(cont, fout);
3410  else
3411  print_troff_ms_text(cont, fout);
3412  break;
3413  default:
3414  fprintf(stderr, _("invalid output format (internal error): %d"),
3415  cont->opt->format);
3416  exit(EXIT_FAILURE);
3417  }
3418 
3419  if (is_local_pager)
3420  ClosePager(fout);
3421 }
static void print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2821
static void print_unaligned_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:457
static void print_csv_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:1822
void ClosePager(FILE *pagerpipe)
Definition: print.c:3042
static void print_aligned_text(const printTableContent *cont, FILE *fout, bool is_pager)
Definition: print.c:579
enum printFormat format
Definition: print.h:101
static void print_aligned_vertical(const printTableContent *cont, FILE *fout, bool is_pager)
Definition: print.c:1227
static void print_troff_ms_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2729
static void print_csv_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1782
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
static void IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded, FILE **fout, bool *is_pager)
Definition: print.c:3290
unsigned short int expanded
Definition: print.h:102
static void print_html_text(const printTableContent *cont, FILE *fout)
Definition: print.c:1895
static void print_latex_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2356
static void print_unaligned_text(const printTableContent *cont, FILE *fout)
Definition: print.c:366
static void print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2198
static void print_html_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:1984
static void print_latex_longtable_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2463
static void print_asciidoc_text(const printTableContent *cont, FILE *fout)
Definition: print.c:2088
volatile sig_atomic_t cancel_pressed
Definition: print.c:43
static void print_latex_vertical(const printTableContent *cont, FILE *fout)
Definition: print.c:2619
#define EXIT_FAILURE
Definition: settings.h:153
#define _(x)
Definition: elog.c:87

◆ printTableAddCell()

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

Definition at line 3150 of file print.c.

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

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

3152 {
3153 #ifndef ENABLE_NLS
3154  (void) translate; /* unused parameter */
3155 #endif
3156 
3157  if (content->cellsadded >= content->ncolumns * content->nrows)
3158  {
3159  fprintf(stderr, _("Cannot add cell to table content: "
3160  "total cell count of %d exceeded.\n"),
3161  content->ncolumns * content->nrows);
3162  exit(EXIT_FAILURE);
3163  }
3164 
3165  *content->cell = (char *) mbvalidate((unsigned char *) cell,
3166  content->opt->encoding);
3167 
3168 #ifdef ENABLE_NLS
3169  if (translate)
3170  *content->cell = _(*content->cell);
3171 #endif
3172 
3173  if (mustfree)
3174  {
3175  if (content->cellmustfree == NULL)
3176  content->cellmustfree =
3177  pg_malloc0((content->ncolumns * content->nrows + 1) * sizeof(bool));
3178 
3179  content->cellmustfree[content->cellsadded] = true;
3180  }
3181  content->cell++;
3182  content->cellsadded++;
3183 }
int encoding
Definition: print.h:122
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
Datum translate(PG_FUNCTION_ARGS)
const char ** cell
Definition: print.h:157
bool * cellmustfree
Definition: print.h:159
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
unsigned char * mbvalidate(unsigned char *pwcs, int encoding)
Definition: mbprint.c:392
long cellsadded
Definition: print.h:158
#define EXIT_FAILURE
Definition: settings.h:153
#define _(x)
Definition: elog.c:87

◆ printTableAddFooter()

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

Definition at line 3198 of file print.c.

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

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

3199 {
3200  printTableFooter *f;
3201 
3202  f = pg_malloc0(sizeof(*f));
3203  f->data = pg_strdup(footer);
3204 
3205  if (content->footers == NULL)
3206  content->footers = f;
3207  else
3208  content->footer->next = f;
3209 
3210  content->footer = f;
3211 }
struct printTableFooter * next
Definition: print.h:140
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
printTableFooter * footer
Definition: print.h:161
printTableFooter * footers
Definition: print.h:160
char * data
Definition: print.h:139

◆ printTableAddHeader()

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

Definition at line 3110 of file print.c.

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

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

3112 {
3113 #ifndef ENABLE_NLS
3114  (void) translate; /* unused parameter */
3115 #endif
3116 
3117  if (content->header >= content->headers + content->ncolumns)
3118  {
3119  fprintf(stderr, _("Cannot add header to table content: "
3120  "column count of %d exceeded.\n"),
3121  content->ncolumns);
3122  exit(EXIT_FAILURE);
3123  }
3124 
3125  *content->header = (char *) mbvalidate((unsigned char *) header,
3126  content->opt->encoding);
3127 #ifdef ENABLE_NLS
3128  if (translate)
3129  *content->header = _(*content->header);
3130 #endif
3131  content->header++;
3132 
3133  *content->align = align;
3134  content->align++;
3135 }
int encoding
Definition: print.h:122
const printTableOpt * opt
Definition: print.h:149
#define fprintf
Definition: port.h:196
Datum translate(PG_FUNCTION_ARGS)
unsigned char * mbvalidate(unsigned char *pwcs, int encoding)
Definition: mbprint.c:392
const char ** header
Definition: print.h:154
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:209
#define EXIT_FAILURE
Definition: settings.h:153
char * align
Definition: print.h:164
const char ** headers
Definition: print.h:153
#define _(x)
Definition: elog.c:87

◆ printTableCleanup()

void printTableCleanup ( printTableContent *const  content)

Definition at line 3241 of file print.c.

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

3242 {
3243  if (content->cellmustfree)
3244  {
3245  int i;
3246 
3247  for (i = 0; i < content->nrows * content->ncolumns; i++)
3248  {
3249  if (content->cellmustfree[i])
3250  free(unconstify(char *, content->cells[i]));
3251  }
3252  free(content->cellmustfree);
3253  content->cellmustfree = NULL;
3254  }
3255  free(content->headers);
3256  free(content->cells);
3257  free(content->aligns);
3258 
3259  content->opt = NULL;
3260  content->title = NULL;
3261  content->headers = NULL;
3262  content->cells = NULL;
3263  content->aligns = NULL;
3264  content->header = NULL;
3265  content->cell = NULL;
3266  content->align = NULL;
3267 
3268  if (content->footers)
3269  {
3270  for (content->footer = content->footers; content->footer;)
3271  {
3272  printTableFooter *f;
3273 
3274  f = content->footer;
3275  content->footer = f->next;
3276  free(f->data);
3277  free(f);
3278  }
3279  }
3280  content->footers = NULL;
3281  content->footer = NULL;
3282 }
const char * title
Definition: print.h:150
const printTableOpt * opt
Definition: print.h:149
struct printTableFooter * next
Definition: print.h:140
const char ** cell
Definition: print.h:157
bool * cellmustfree
Definition: print.h:159
char * aligns
Definition: print.h:162
const char ** cells
Definition: print.h:155
const char ** header
Definition: print.h:154
#define unconstify(underlying_type, expr)
Definition: c.h:1193
printTableFooter * footer
Definition: print.h:161
#define free(a)
Definition: header.h:65
printTableFooter * footers
Definition: print.h:160
int i
char * data
Definition: print.h:139
char * align
Definition: print.h:164
const char ** headers
Definition: print.h:153

◆ printTableInit()

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

Definition at line 3073 of file print.c.

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

3075 {
3076  content->opt = opt;
3077  content->title = title;
3078  content->ncolumns = ncolumns;
3079  content->nrows = nrows;
3080 
3081  content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers));
3082 
3083  content->cells = pg_malloc0((ncolumns * nrows + 1) * sizeof(*content->cells));
3084 
3085  content->cellmustfree = NULL;
3086  content->footers = NULL;
3087 
3088  content->aligns = pg_malloc0((ncolumns + 1) * sizeof(*content->align));
3089 
3090  content->header = content->headers;
3091  content->cell = content->cells;
3092  content->footer = content->footers;
3093  content->align = content->aligns;
3094  content->cellsadded = 0;
3095 }
const char * title
Definition: print.h:150
const printTableOpt * opt
Definition: print.h:149
const char ** cell
Definition: print.h:157
bool * cellmustfree
Definition: print.h:159
char * aligns
Definition: print.h:162
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
const char ** cells
Definition: print.h:155
long cellsadded
Definition: print.h:158
const char ** header
Definition: print.h:154
printTableFooter * footer
Definition: print.h:161
printTableFooter * footers
Definition: print.h:160
char * align
Definition: print.h:164
const char ** headers
Definition: print.h:153

◆ printTableSetFooter()

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

Definition at line 3223 of file print.c.

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

Referenced by add_tablespace_footer().

3224 {
3225  if (content->footers != NULL)
3226  {
3227  free(content->footer->data);
3228  content->footer->data = pg_strdup(footer);
3229  }
3230  else
3231  printTableAddFooter(content, footer);
3232 }
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void printTableAddFooter(printTableContent *const content, const char *footer)
Definition: print.c:3198
printTableFooter * footer
Definition: print.h:161
#define free(a)
Definition: header.h:65
printTableFooter * footers
Definition: print.h:160
char * data
Definition: print.h:139

◆ refresh_utf8format()

void refresh_utf8format ( const printTableOpt opt)

Definition at line 3574 of file print.c.

References unicodeStyleFormat::border_style, unicodeStyleFormat::column_style, unicodeStyleColumnFormat::down_and_horizontal, unicodeStyleBorderFormat::down_and_left, unicodeStyleBorderFormat::down_and_right, header(), printTextFormat::header_nl_left, unicodeStyleFormat::header_nl_left, printTextFormat::header_nl_right, unicodeStyleFormat::header_nl_right, unicodeStyleRowFormat::horizontal, unicodeStyleBorderFormat::horizontal, printTextLineFormat::hrule, unicodeStyleBorderFormat::left_and_right, printTextLineFormat::leftvrule, printTextFormat::lrule, printTextLineFormat::midvrule, printTextFormat::midvrule_blank, printTextFormat::midvrule_nl, printTextFormat::midvrule_wrap, printTextFormat::name, printTextFormat::nl_left, unicodeStyleFormat::nl_left, printTextFormat::nl_right, unicodeStyleFormat::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, unicodeStyleColumnFormat::up_and_horizontal, unicodeStyleBorderFormat::up_and_right, unicodeStyleColumnFormat::vertical, unicodeStyleBorderFormat::vertical, unicodeStyleColumnFormat::vertical_and_horizontal, unicodeStyleRowFormat::vertical_and_left, unicodeStyleRowFormat::vertical_and_right, printTextFormat::wrap_left, unicodeStyleFormat::wrap_left, printTextFormat::wrap_right, unicodeStyleFormat::wrap_right, printTextFormat::wrap_right_border, and unicodeStyleFormat::wrap_right_border.

Referenced by do_pset(), and main().

3575 {
3576  printTextFormat *popt = &pg_utf8format;
3577 
3578  const unicodeStyleBorderFormat *border;
3580  const unicodeStyleColumnFormat *column;
3581 
3582  popt->name = "unicode";
3583 
3587 
3588  popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
3589  popt->lrule[PRINT_RULE_TOP].leftvrule = border->down_and_right;
3591  popt->lrule[PRINT_RULE_TOP].rightvrule = border->down_and_left;
3592 
3593  popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
3597 
3598  popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
3599  popt->lrule[PRINT_RULE_BOTTOM].leftvrule = border->up_and_right;
3602 
3603  /* N/A */
3604  popt->lrule[PRINT_RULE_DATA].hrule = "";
3605  popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
3606  popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
3607  popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
3608 
3609  popt->midvrule_nl = column->vertical;
3610  popt->midvrule_wrap = column->vertical;
3611  popt->midvrule_blank = column->vertical;
3612 
3613  /* Same for all unicode today */
3616  popt->nl_left = unicode_style.nl_left;
3621 }
const char * midvrule
Definition: print.h:48
const char * vertical
Definition: print.c:110
unicodeStyleColumnFormat column_style[2]
Definition: print.c:129
const char * midvrule_wrap
Definition: print.h:75
static const unicodeStyleFormat unicode_style
Definition: print.c:140
const char * header_nl_left
Definition: print.c:131
const char * header_nl_left
Definition: print.h:77
printTextFormat pg_utf8format
Definition: print.c:99
bool wrap_right_border
Definition: print.h:83
const char * wrap_left
Definition: print.c:135
unicode_linestyle unicode_header_linestyle
Definition: print.h:127
printTextLineFormat lrule[4]
Definition: print.h:73
const char * horizontal
Definition: print.c:121
const char * down_and_left
Definition: print.c:122
const char * name
Definition: print.h:72
const char * up_and_right
Definition: print.c:118
const char * midvrule_blank
Definition: print.h:76
unicode_linestyle unicode_border_linestyle
Definition: print.h:125
const char * header_nl_right
Definition: print.c:132
const char * vertical_and_left[2]
Definition: print.c:105
const char * header_nl_right
Definition: print.h:78
unicodeStyleBorderFormat border_style[2]
Definition: print.c:130
const char * down_and_horizontal[2]
Definition: print.c:113
const char * horizontal
Definition: print.c:103
const char * hrule
Definition: print.h:46
const char * vertical_and_horizontal[2]
Definition: print.c:111
unicode_linestyle unicode_column_linestyle
Definition: print.h:126
const char * midvrule_nl
Definition: print.h:74
const char * left_and_right
Definition: print.c:123
const char * wrap_right
Definition: print.c:136
bool wrap_right_border
Definition: print.c:137
const char * nl_left
Definition: print.c:133
const char * leftvrule
Definition: print.h:47
const char * nl_right
Definition: print.c:134
const char * up_and_horizontal[2]
Definition: print.c:112
const char * down_and_right
Definition: print.c:120
const char * nl_right
Definition: print.h:80
const char * vertical
Definition: print.c:119
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:209
const char * vertical_and_right[2]
Definition: print.c:104
const char * nl_left
Definition: print.h:79
const char * rightvrule
Definition: print.h:49
const char * wrap_left
Definition: print.h:81
const char * wrap_right
Definition: print.h:82
unicodeStyleRowFormat row_style[2]
Definition: print.c:128

◆ restore_sigpipe_trap()

void restore_sigpipe_trap ( void  )

Definition at line 2964 of file print.c.

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

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

2965 {
2966 #ifndef WIN32
2968 #endif
2969 }
#define SIGPIPE
Definition: win32_port.h:159
#define SIG_IGN
Definition: win32_port.h:151
static bool always_ignore_sigpipe
Definition: print.c:45
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
#define SIG_DFL
Definition: win32_port.h:149

◆ set_sigpipe_trap_state()

void set_sigpipe_trap_state ( bool  ignore)

Definition at line 2977 of file print.c.

References always_ignore_sigpipe.

Referenced by setQFout().

2978 {
2979  always_ignore_sigpipe = ignore;
2980 }
static bool always_ignore_sigpipe
Definition: print.c:45

◆ setDecimalLocale()

void setDecimalLocale ( void  )

Definition at line 3524 of file print.c.

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

Referenced by main().

3525 {
3526  struct lconv *extlconv;
3527 
3528  extlconv = localeconv();
3529 
3530  /* Don't accept an empty decimal_point string */
3531  if (*extlconv->decimal_point)
3532  decimal_point = pg_strdup(extlconv->decimal_point);
3533  else
3534  decimal_point = "."; /* SQL output standard */
3535 
3536  /*
3537  * Although the Open Group standard allows locales to supply more than one
3538  * group width, we consider only the first one, and we ignore any attempt
3539  * to suppress grouping by specifying CHAR_MAX. As in the backend's
3540  * cash.c, we must apply a range check to avoid being fooled by variant
3541  * CHAR_MAX values.
3542  */
3543  groupdigits = *extlconv->grouping;
3544  if (groupdigits <= 0 || groupdigits > 6)
3545  groupdigits = 3; /* most common */
3546 
3547  /* Don't accept an empty thousands_sep string, either */
3548  /* similar code exists in formatting.c */
3549  if (*extlconv->thousands_sep)
3550  thousands_sep = pg_strdup(extlconv->thousands_sep);
3551  /* Make sure thousands separator doesn't match decimal point symbol. */
3552  else if (strcmp(decimal_point, ",") != 0)
3553  thousands_sep = ",";
3554  else
3555  thousands_sep = ".";
3556 }
static int groupdigits
Definition: print.c:49
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static char * decimal_point
Definition: print.c:48
static char * thousands_sep
Definition: print.c:50

◆ strlen_max_width()

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

Definition at line 3629 of file print.c.

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

Referenced by print_aligned_text(), and print_aligned_vertical().

3630 {
3631  unsigned char *start = str;
3632  unsigned char *end = str + strlen((char *) str);
3633  int curr_width = 0;
3634 
3635  while (str < end)
3636  {
3637  int char_width = PQdsplen((char *) str, encoding);
3638 
3639  /*
3640  * If the display width of the new character causes the string to
3641  * exceed its target width, skip it and return. However, if this is
3642  * the first character of the string (curr_width == 0), we have to
3643  * accept it.
3644  */
3645  if (*target_width < curr_width + char_width && curr_width != 0)
3646  break;
3647 
3648  curr_width += char_width;
3649 
3650  str += PQmblen((char *) str, encoding);
3651  }
3652 
3653  *target_width = curr_width;
3654 
3655  return str - start;
3656 }
int PQdsplen(const char *s, int encoding)
Definition: fe-misc.c:1226
int32 encoding
Definition: pg_database.h:41
int PQmblen(const char *s, int encoding)
Definition: fe-misc.c:1216

◆ troff_ms_escaped_print()

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

Definition at line 2712 of file print.c.

Referenced by print_troff_ms_text(), and print_troff_ms_vertical().

2713 {
2714  const char *p;
2715 
2716  for (p = in; *p; p++)
2717  switch (*p)
2718  {
2719  case '\\':
2720  fputs("\\(rs", fout);
2721  break;
2722  default:
2723  fputc(*p, fout);
2724  }
2725 }

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

◆ 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.