]> granicus.if.org Git - postgresql/blob - src/fe_utils/print.c
Make the order of the header file includes consistent in non-backend modules.
[postgresql] / src / fe_utils / print.c
1 /*-------------------------------------------------------------------------
2  *
3  * Query-result printing support for frontend code
4  *
5  * This file used to be part of psql, but now it's separated out to allow
6  * other frontend programs to use it.  Because the printing code needs
7  * access to the cancel_pressed flag as well as SIGPIPE trapping and
8  * pager open/close functions, all that stuff came with it.
9  *
10  *
11  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
12  * Portions Copyright (c) 1994, Regents of the University of California
13  *
14  * src/fe_utils/print.c
15  *
16  *-------------------------------------------------------------------------
17  */
18 #include "postgres_fe.h"
19
20 #include <limits.h>
21 #include <math.h>
22 #include <signal.h>
23 #include <unistd.h>
24
25 #ifndef WIN32
26 #include <sys/ioctl.h>                  /* for ioctl() */
27 #endif
28
29 #ifdef HAVE_TERMIOS_H
30 #include <termios.h>
31 #endif
32
33 #include "catalog/pg_type_d.h"
34 #include "fe_utils/mbprint.h"
35 #include "fe_utils/print.h"
36
37 /*
38  * If the calling program doesn't have any mechanism for setting
39  * cancel_pressed, it will have no effect.
40  *
41  * Note: print.c's general strategy for when to check cancel_pressed is to do
42  * so at completion of each row of output.
43  */
44 volatile bool cancel_pressed = false;
45
46 static bool always_ignore_sigpipe = false;
47
48 /* info for locale-aware numeric formatting; set up by setDecimalLocale() */
49 static char *decimal_point;
50 static int      groupdigits;
51 static char *thousands_sep;
52
53 static char default_footer[100];
54 static printTableFooter default_footer_cell = {default_footer, NULL};
55
56 /* Line style control structures */
57 const printTextFormat pg_asciiformat =
58 {
59         "ascii",
60         {
61                 {"-", "+", "+", "+"},
62                 {"-", "+", "+", "+"},
63                 {"-", "+", "+", "+"},
64                 {"", "|", "|", "|"}
65         },
66         "|",
67         "|",
68         "|",
69         " ",
70         "+",
71         " ",
72         "+",
73         ".",
74         ".",
75         true
76 };
77
78 const printTextFormat pg_asciiformat_old =
79 {
80         "old-ascii",
81         {
82                 {"-", "+", "+", "+"},
83                 {"-", "+", "+", "+"},
84                 {"-", "+", "+", "+"},
85                 {"", "|", "|", "|"}
86         },
87         ":",
88         ";",
89         " ",
90         "+",
91         " ",
92         " ",
93         " ",
94         " ",
95         " ",
96         false
97 };
98
99 /* Default unicode linestyle format */
100 printTextFormat pg_utf8format;
101
102 typedef struct unicodeStyleRowFormat
103 {
104         const char *horizontal;
105         const char *vertical_and_right[2];
106         const char *vertical_and_left[2];
107 } unicodeStyleRowFormat;
108
109 typedef struct unicodeStyleColumnFormat
110 {
111         const char *vertical;
112         const char *vertical_and_horizontal[2];
113         const char *up_and_horizontal[2];
114         const char *down_and_horizontal[2];
115 } unicodeStyleColumnFormat;
116
117 typedef struct unicodeStyleBorderFormat
118 {
119         const char *up_and_right;
120         const char *vertical;
121         const char *down_and_right;
122         const char *horizontal;
123         const char *down_and_left;
124         const char *left_and_right;
125 } unicodeStyleBorderFormat;
126
127 typedef struct unicodeStyleFormat
128 {
129         unicodeStyleRowFormat row_style[2];
130         unicodeStyleColumnFormat column_style[2];
131         unicodeStyleBorderFormat border_style[2];
132         const char *header_nl_left;
133         const char *header_nl_right;
134         const char *nl_left;
135         const char *nl_right;
136         const char *wrap_left;
137         const char *wrap_right;
138         bool            wrap_right_border;
139 } unicodeStyleFormat;
140
141 static const unicodeStyleFormat unicode_style = {
142         {
143                 {
144                         /* ─ */
145                         "\342\224\200",
146                         /* ├╟ */
147                         {"\342\224\234", "\342\225\237"},
148                         /* ┤╢ */
149                         {"\342\224\244", "\342\225\242"},
150                 },
151                 {
152                         /* ═ */
153                         "\342\225\220",
154                         /* ╞╠ */
155                         {"\342\225\236", "\342\225\240"},
156                         /* ╡╣ */
157                         {"\342\225\241", "\342\225\243"},
158                 },
159         },
160         {
161                 {
162                         /* │ */
163                         "\342\224\202",
164                         /* ┼╪ */
165                         {"\342\224\274", "\342\225\252"},
166                         /* ┴╧ */
167                         {"\342\224\264", "\342\225\247"},
168                         /* ┬╤ */
169                         {"\342\224\254", "\342\225\244"},
170                 },
171                 {
172                         /* ║ */
173                         "\342\225\221",
174                         /* ╫╬ */
175                         {"\342\225\253", "\342\225\254"},
176                         /* ╨╩ */
177                         {"\342\225\250", "\342\225\251"},
178                         /* ╥╦ */
179                         {"\342\225\245", "\342\225\246"},
180                 },
181         },
182         {
183                 /* └│┌─┐┘ */
184                 {"\342\224\224", "\342\224\202", "\342\224\214", "\342\224\200", "\342\224\220", "\342\224\230"},
185                 /* ╚║╔═╗╝ */
186                 {"\342\225\232", "\342\225\221", "\342\225\224", "\342\225\220", "\342\225\227", "\342\225\235"},
187         },
188         " ",
189         "\342\206\265",                         /* ↵ */
190         " ",
191         "\342\206\265",                         /* ↵ */
192         "\342\200\246",                         /* … */
193         "\342\200\246",                         /* … */
194         true
195 };
196
197
198 /* Local functions */
199 static int      strlen_max_width(unsigned char *str, int *target_width, int encoding);
200 static void IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded,
201                                                   FILE **fout, bool *is_pager);
202
203 static void print_aligned_vertical(const printTableContent *cont,
204                                                                    FILE *fout, bool is_pager);
205
206
207 /* Count number of digits in integral part of number */
208 static int
209 integer_digits(const char *my_str)
210 {
211         /* ignoring any sign ... */
212         if (my_str[0] == '-' || my_str[0] == '+')
213                 my_str++;
214         /* ... count initial integral digits */
215         return strspn(my_str, "0123456789");
216 }
217
218 /* Compute additional length required for locale-aware numeric output */
219 static int
220 additional_numeric_locale_len(const char *my_str)
221 {
222         int                     int_len = integer_digits(my_str),
223                                 len = 0;
224
225         /* Account for added thousands_sep instances */
226         if (int_len > groupdigits)
227                 len += ((int_len - 1) / groupdigits) * strlen(thousands_sep);
228
229         /* Account for possible additional length of decimal_point */
230         if (strchr(my_str, '.') != NULL)
231                 len += strlen(decimal_point) - 1;
232
233         return len;
234 }
235
236 /*
237  * Format a numeric value per current LC_NUMERIC locale setting
238  *
239  * Returns the appropriately formatted string in a new allocated block,
240  * caller must free.
241  *
242  * setDecimalLocale() must have been called earlier.
243  */
244 static char *
245 format_numeric_locale(const char *my_str)
246 {
247         char       *new_str;
248         int                     new_len,
249                                 int_len,
250                                 leading_digits,
251                                 i,
252                                 new_str_pos;
253
254         /*
255          * If the string doesn't look like a number, return it unchanged.  This
256          * check is essential to avoid mangling already-localized "money" values.
257          */
258         if (strspn(my_str, "0123456789+-.eE") != strlen(my_str))
259                 return pg_strdup(my_str);
260
261         new_len = strlen(my_str) + additional_numeric_locale_len(my_str);
262         new_str = pg_malloc(new_len + 1);
263         new_str_pos = 0;
264         int_len = integer_digits(my_str);
265
266         /* number of digits in first thousands group */
267         leading_digits = int_len % groupdigits;
268         if (leading_digits == 0)
269                 leading_digits = groupdigits;
270
271         /* process sign */
272         if (my_str[0] == '-' || my_str[0] == '+')
273         {
274                 new_str[new_str_pos++] = my_str[0];
275                 my_str++;
276         }
277
278         /* process integer part of number */
279         for (i = 0; i < int_len; i++)
280         {
281                 /* Time to insert separator? */
282                 if (i > 0 && --leading_digits == 0)
283                 {
284                         strcpy(&new_str[new_str_pos], thousands_sep);
285                         new_str_pos += strlen(thousands_sep);
286                         leading_digits = groupdigits;
287                 }
288                 new_str[new_str_pos++] = my_str[i];
289         }
290
291         /* handle decimal point if any */
292         if (my_str[i] == '.')
293         {
294                 strcpy(&new_str[new_str_pos], decimal_point);
295                 new_str_pos += strlen(decimal_point);
296                 i++;
297         }
298
299         /* copy the rest (fractional digits and/or exponent, and \0 terminator) */
300         strcpy(&new_str[new_str_pos], &my_str[i]);
301
302         /* assert we didn't underestimate new_len (an overestimate is OK) */
303         Assert(strlen(new_str) <= new_len);
304
305         return new_str;
306 }
307
308
309 /*
310  * fputnbytes: print exactly N bytes to a file
311  *
312  * We avoid using %.*s here because it can misbehave if the data
313  * is not valid in what libc thinks is the prevailing encoding.
314  */
315 static void
316 fputnbytes(FILE *f, const char *str, size_t n)
317 {
318         while (n-- > 0)
319                 fputc(*str++, f);
320 }
321
322
323 static void
324 print_separator(struct separator sep, FILE *fout)
325 {
326         if (sep.separator_zero)
327                 fputc('\000', fout);
328         else if (sep.separator)
329                 fputs(sep.separator, fout);
330 }
331
332
333 /*
334  * Return the list of explicitly-requested footers or, when applicable, the
335  * default "(xx rows)" footer.  Always omit the default footer when given
336  * non-default footers, "\pset footer off", or a specific instruction to that
337  * effect from a calling backslash command.  Vertical formats number each row,
338  * making the default footer redundant; they do not call this function.
339  *
340  * The return value may point to static storage; do not keep it across calls.
341  */
342 static printTableFooter *
343 footers_with_default(const printTableContent *cont)
344 {
345         if (cont->footers == NULL && cont->opt->default_footer)
346         {
347                 unsigned long total_records;
348
349                 total_records = cont->opt->prior_records + cont->nrows;
350                 snprintf(default_footer, sizeof(default_footer),
351                                  ngettext("(%lu row)", "(%lu rows)", total_records),
352                                  total_records);
353
354                 return &default_footer_cell;
355         }
356         else
357                 return cont->footers;
358 }
359
360
361 /*************************/
362 /* Unaligned text                */
363 /*************************/
364
365
366 static void
367 print_unaligned_text(const printTableContent *cont, FILE *fout)
368 {
369         bool            opt_tuples_only = cont->opt->tuples_only;
370         unsigned int i;
371         const char *const *ptr;
372         bool            need_recordsep = false;
373
374         if (cancel_pressed)
375                 return;
376
377         if (cont->opt->start_table)
378         {
379                 /* print title */
380                 if (!opt_tuples_only && cont->title)
381                 {
382                         fputs(cont->title, fout);
383                         print_separator(cont->opt->recordSep, fout);
384                 }
385
386                 /* print headers */
387                 if (!opt_tuples_only)
388                 {
389                         for (ptr = cont->headers; *ptr; ptr++)
390                         {
391                                 if (ptr != cont->headers)
392                                         print_separator(cont->opt->fieldSep, fout);
393                                 fputs(*ptr, fout);
394                         }
395                         need_recordsep = true;
396                 }
397         }
398         else
399                 /* assume continuing printout */
400                 need_recordsep = true;
401
402         /* print cells */
403         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
404         {
405                 if (need_recordsep)
406                 {
407                         print_separator(cont->opt->recordSep, fout);
408                         need_recordsep = false;
409                         if (cancel_pressed)
410                                 break;
411                 }
412                 fputs(*ptr, fout);
413
414                 if ((i + 1) % cont->ncolumns)
415                         print_separator(cont->opt->fieldSep, fout);
416                 else
417                         need_recordsep = true;
418         }
419
420         /* print footers */
421         if (cont->opt->stop_table)
422         {
423                 printTableFooter *footers = footers_with_default(cont);
424
425                 if (!opt_tuples_only && footers != NULL && !cancel_pressed)
426                 {
427                         printTableFooter *f;
428
429                         for (f = footers; f; f = f->next)
430                         {
431                                 if (need_recordsep)
432                                 {
433                                         print_separator(cont->opt->recordSep, fout);
434                                         need_recordsep = false;
435                                 }
436                                 fputs(f->data, fout);
437                                 need_recordsep = true;
438                         }
439                 }
440
441                 /*
442                  * The last record is terminated by a newline, independent of the set
443                  * record separator.  But when the record separator is a zero byte, we
444                  * use that (compatible with find -print0 and xargs).
445                  */
446                 if (need_recordsep)
447                 {
448                         if (cont->opt->recordSep.separator_zero)
449                                 print_separator(cont->opt->recordSep, fout);
450                         else
451                                 fputc('\n', fout);
452                 }
453         }
454 }
455
456
457 static void
458 print_unaligned_vertical(const printTableContent *cont, FILE *fout)
459 {
460         bool            opt_tuples_only = cont->opt->tuples_only;
461         unsigned int i;
462         const char *const *ptr;
463         bool            need_recordsep = false;
464
465         if (cancel_pressed)
466                 return;
467
468         if (cont->opt->start_table)
469         {
470                 /* print title */
471                 if (!opt_tuples_only && cont->title)
472                 {
473                         fputs(cont->title, fout);
474                         need_recordsep = true;
475                 }
476         }
477         else
478                 /* assume continuing printout */
479                 need_recordsep = true;
480
481         /* print records */
482         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
483         {
484                 if (need_recordsep)
485                 {
486                         /* record separator is 2 occurrences of recordsep in this mode */
487                         print_separator(cont->opt->recordSep, fout);
488                         print_separator(cont->opt->recordSep, fout);
489                         need_recordsep = false;
490                         if (cancel_pressed)
491                                 break;
492                 }
493
494                 fputs(cont->headers[i % cont->ncolumns], fout);
495                 print_separator(cont->opt->fieldSep, fout);
496                 fputs(*ptr, fout);
497
498                 if ((i + 1) % cont->ncolumns)
499                         print_separator(cont->opt->recordSep, fout);
500                 else
501                         need_recordsep = true;
502         }
503
504         if (cont->opt->stop_table)
505         {
506                 /* print footers */
507                 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
508                 {
509                         printTableFooter *f;
510
511                         print_separator(cont->opt->recordSep, fout);
512                         for (f = cont->footers; f; f = f->next)
513                         {
514                                 print_separator(cont->opt->recordSep, fout);
515                                 fputs(f->data, fout);
516                         }
517                 }
518
519                 /* see above in print_unaligned_text() */
520                 if (need_recordsep)
521                 {
522                         if (cont->opt->recordSep.separator_zero)
523                                 print_separator(cont->opt->recordSep, fout);
524                         else
525                                 fputc('\n', fout);
526                 }
527         }
528 }
529
530
531 /********************/
532 /* Aligned text         */
533 /********************/
534
535
536 /* draw "line" */
537 static void
538 _print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths,
539                                            unsigned short border, printTextRule pos,
540                                            const printTextFormat *format,
541                                            FILE *fout)
542 {
543         const printTextLineFormat *lformat = &format->lrule[pos];
544         unsigned int i,
545                                 j;
546
547         if (border == 1)
548                 fputs(lformat->hrule, fout);
549         else if (border == 2)
550                 fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
551
552         for (i = 0; i < ncolumns; i++)
553         {
554                 for (j = 0; j < widths[i]; j++)
555                         fputs(lformat->hrule, fout);
556
557                 if (i < ncolumns - 1)
558                 {
559                         if (border == 0)
560                                 fputc(' ', fout);
561                         else
562                                 fprintf(fout, "%s%s%s", lformat->hrule,
563                                                 lformat->midvrule, lformat->hrule);
564                 }
565         }
566
567         if (border == 2)
568                 fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
569         else if (border == 1)
570                 fputs(lformat->hrule, fout);
571
572         fputc('\n', fout);
573 }
574
575
576 /*
577  *      Print pretty boxes around cells.
578  */
579 static void
580 print_aligned_text(const printTableContent *cont, FILE *fout, bool is_pager)
581 {
582         bool            opt_tuples_only = cont->opt->tuples_only;
583         int                     encoding = cont->opt->encoding;
584         unsigned short opt_border = cont->opt->border;
585         const printTextFormat *format = get_line_style(cont->opt);
586         const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA];
587
588         unsigned int col_count = 0,
589                                 cell_count = 0;
590
591         unsigned int i,
592                                 j;
593
594         unsigned int *width_header,
595                            *max_width,
596                            *width_wrap,
597                            *width_average;
598         unsigned int *max_nl_lines, /* value split by newlines */
599                            *curr_nl_line,
600                            *max_bytes;
601         unsigned char **format_buf;
602         unsigned int width_total;
603         unsigned int total_header_width;
604         unsigned int extra_row_output_lines = 0;
605         unsigned int extra_output_lines = 0;
606
607         const char *const *ptr;
608
609         struct lineptr **col_lineptrs;  /* pointers to line pointer per column */
610
611         bool       *header_done;        /* Have all header lines been output? */
612         int                *bytes_output;       /* Bytes output for column value */
613         printTextLineWrap *wrap;        /* Wrap status for each column */
614         int                     output_columns = 0; /* Width of interactive console */
615         bool            is_local_pager = false;
616
617         if (cancel_pressed)
618                 return;
619
620         if (opt_border > 2)
621                 opt_border = 2;
622
623         if (cont->ncolumns > 0)
624         {
625                 col_count = cont->ncolumns;
626                 width_header = pg_malloc0(col_count * sizeof(*width_header));
627                 width_average = pg_malloc0(col_count * sizeof(*width_average));
628                 max_width = pg_malloc0(col_count * sizeof(*max_width));
629                 width_wrap = pg_malloc0(col_count * sizeof(*width_wrap));
630                 max_nl_lines = pg_malloc0(col_count * sizeof(*max_nl_lines));
631                 curr_nl_line = pg_malloc0(col_count * sizeof(*curr_nl_line));
632                 col_lineptrs = pg_malloc0(col_count * sizeof(*col_lineptrs));
633                 max_bytes = pg_malloc0(col_count * sizeof(*max_bytes));
634                 format_buf = pg_malloc0(col_count * sizeof(*format_buf));
635                 header_done = pg_malloc0(col_count * sizeof(*header_done));
636                 bytes_output = pg_malloc0(col_count * sizeof(*bytes_output));
637                 wrap = pg_malloc0(col_count * sizeof(*wrap));
638         }
639         else
640         {
641                 width_header = NULL;
642                 width_average = NULL;
643                 max_width = NULL;
644                 width_wrap = NULL;
645                 max_nl_lines = NULL;
646                 curr_nl_line = NULL;
647                 col_lineptrs = NULL;
648                 max_bytes = NULL;
649                 format_buf = NULL;
650                 header_done = NULL;
651                 bytes_output = NULL;
652                 wrap = NULL;
653         }
654
655         /* scan all column headers, find maximum width and max max_nl_lines */
656         for (i = 0; i < col_count; i++)
657         {
658                 int                     width,
659                                         nl_lines,
660                                         bytes_required;
661
662                 pg_wcssize((const unsigned char *) cont->headers[i], strlen(cont->headers[i]),
663                                    encoding, &width, &nl_lines, &bytes_required);
664                 if (width > max_width[i])
665                         max_width[i] = width;
666                 if (nl_lines > max_nl_lines[i])
667                         max_nl_lines[i] = nl_lines;
668                 if (bytes_required > max_bytes[i])
669                         max_bytes[i] = bytes_required;
670                 if (nl_lines > extra_row_output_lines)
671                         extra_row_output_lines = nl_lines;
672
673                 width_header[i] = width;
674         }
675         /* Add height of tallest header column */
676         extra_output_lines += extra_row_output_lines;
677         extra_row_output_lines = 0;
678
679         /* scan all cells, find maximum width, compute cell_count */
680         for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++)
681         {
682                 int                     width,
683                                         nl_lines,
684                                         bytes_required;
685
686                 pg_wcssize((const unsigned char *) *ptr, strlen(*ptr), encoding,
687                                    &width, &nl_lines, &bytes_required);
688
689                 if (width > max_width[i % col_count])
690                         max_width[i % col_count] = width;
691                 if (nl_lines > max_nl_lines[i % col_count])
692                         max_nl_lines[i % col_count] = nl_lines;
693                 if (bytes_required > max_bytes[i % col_count])
694                         max_bytes[i % col_count] = bytes_required;
695
696                 width_average[i % col_count] += width;
697         }
698
699         /* If we have rows, compute average */
700         if (col_count != 0 && cell_count != 0)
701         {
702                 int                     rows = cell_count / col_count;
703
704                 for (i = 0; i < col_count; i++)
705                         width_average[i] /= rows;
706         }
707
708         /* adjust the total display width based on border style */
709         if (opt_border == 0)
710                 width_total = col_count;
711         else if (opt_border == 1)
712                 width_total = col_count * 3 - ((col_count > 0) ? 1 : 0);
713         else
714                 width_total = col_count * 3 + 1;
715         total_header_width = width_total;
716
717         for (i = 0; i < col_count; i++)
718         {
719                 width_total += max_width[i];
720                 total_header_width += width_header[i];
721         }
722
723         /*
724          * At this point: max_width[] contains the max width of each column,
725          * max_nl_lines[] contains the max number of lines in each column,
726          * max_bytes[] contains the maximum storage space for formatting strings,
727          * width_total contains the giant width sum.  Now we allocate some memory
728          * for line pointers.
729          */
730         for (i = 0; i < col_count; i++)
731         {
732                 /* Add entry for ptr == NULL array termination */
733                 col_lineptrs[i] = pg_malloc0((max_nl_lines[i] + 1) *
734                                                                          sizeof(**col_lineptrs));
735
736                 format_buf[i] = pg_malloc(max_bytes[i] + 1);
737
738                 col_lineptrs[i]->ptr = format_buf[i];
739         }
740
741         /* Default word wrap to the full width, i.e. no word wrap */
742         for (i = 0; i < col_count; i++)
743                 width_wrap[i] = max_width[i];
744
745         /*
746          * Choose target output width: \pset columns, or $COLUMNS, or ioctl
747          */
748         if (cont->opt->columns > 0)
749                 output_columns = cont->opt->columns;
750         else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
751         {
752                 if (cont->opt->env_columns > 0)
753                         output_columns = cont->opt->env_columns;
754 #ifdef TIOCGWINSZ
755                 else
756                 {
757                         struct winsize screen_size;
758
759                         if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
760                                 output_columns = screen_size.ws_col;
761                 }
762 #endif
763         }
764
765         if (cont->opt->format == PRINT_WRAPPED)
766         {
767                 /*
768                  * Optional optimized word wrap. Shrink columns with a high max/avg
769                  * ratio.  Slightly bias against wider columns. (Increases chance a
770                  * narrow column will fit in its cell.)  If available columns is
771                  * positive...  and greater than the width of the unshrinkable column
772                  * headers
773                  */
774                 if (output_columns > 0 && output_columns >= total_header_width)
775                 {
776                         /* While there is still excess width... */
777                         while (width_total > output_columns)
778                         {
779                                 double          max_ratio = 0;
780                                 int                     worst_col = -1;
781
782                                 /*
783                                  * Find column that has the highest ratio of its maximum width
784                                  * compared to its average width.  This tells us which column
785                                  * will produce the fewest wrapped values if shortened.
786                                  * width_wrap starts as equal to max_width.
787                                  */
788                                 for (i = 0; i < col_count; i++)
789                                 {
790                                         if (width_average[i] && width_wrap[i] > width_header[i])
791                                         {
792                                                 /* Penalize wide columns by 1% of their width */
793                                                 double          ratio;
794
795                                                 ratio = (double) width_wrap[i] / width_average[i] +
796                                                         max_width[i] * 0.01;
797                                                 if (ratio > max_ratio)
798                                                 {
799                                                         max_ratio = ratio;
800                                                         worst_col = i;
801                                                 }
802                                         }
803                                 }
804
805                                 /* Exit loop if we can't squeeze any more. */
806                                 if (worst_col == -1)
807                                         break;
808
809                                 /* Decrease width of target column by one. */
810                                 width_wrap[worst_col]--;
811                                 width_total--;
812                         }
813                 }
814         }
815
816         /*
817          * If in expanded auto mode, we have now calculated the expected width, so
818          * we can now escape to vertical mode if necessary.  If the output has
819          * only one column, the expanded format would be wider than the regular
820          * format, so don't use it in that case.
821          */
822         if (cont->opt->expanded == 2 && output_columns > 0 && cont->ncolumns > 1 &&
823                 (output_columns < total_header_width || output_columns < width_total))
824         {
825                 print_aligned_vertical(cont, fout, is_pager);
826                 goto cleanup;
827         }
828
829         /* If we wrapped beyond the display width, use the pager */
830         if (!is_pager && fout == stdout && output_columns > 0 &&
831                 (output_columns < total_header_width || output_columns < width_total))
832         {
833                 fout = PageOutput(INT_MAX, cont->opt);  /* force pager */
834                 is_pager = is_local_pager = true;
835         }
836
837         /* Check if newlines or our wrapping now need the pager */
838         if (!is_pager && fout == stdout)
839         {
840                 /* scan all cells, find maximum width, compute cell_count */
841                 for (i = 0, ptr = cont->cells; *ptr; ptr++, cell_count++)
842                 {
843                         int                     width,
844                                                 nl_lines,
845                                                 bytes_required;
846
847                         pg_wcssize((const unsigned char *) *ptr, strlen(*ptr), encoding,
848                                            &width, &nl_lines, &bytes_required);
849
850                         /*
851                          * A row can have both wrapping and newlines that cause it to
852                          * display across multiple lines.  We check for both cases below.
853                          */
854                         if (width > 0 && width_wrap[i])
855                         {
856                                 unsigned int extra_lines;
857
858                                 /* don't count the first line of nl_lines - it's not "extra" */
859                                 extra_lines = ((width - 1) / width_wrap[i]) + nl_lines - 1;
860                                 if (extra_lines > extra_row_output_lines)
861                                         extra_row_output_lines = extra_lines;
862                         }
863
864                         /* i is the current column number: increment with wrap */
865                         if (++i >= col_count)
866                         {
867                                 i = 0;
868                                 /* At last column of each row, add tallest column height */
869                                 extra_output_lines += extra_row_output_lines;
870                                 extra_row_output_lines = 0;
871                         }
872                 }
873                 IsPagerNeeded(cont, extra_output_lines, false, &fout, &is_pager);
874                 is_local_pager = is_pager;
875         }
876
877         /* time to output */
878         if (cont->opt->start_table)
879         {
880                 /* print title */
881                 if (cont->title && !opt_tuples_only)
882                 {
883                         int                     width,
884                                                 height;
885
886                         pg_wcssize((const unsigned char *) cont->title, strlen(cont->title),
887                                            encoding, &width, &height, NULL);
888                         if (width >= width_total)
889                                 /* Aligned */
890                                 fprintf(fout, "%s\n", cont->title);
891                         else
892                                 /* Centered */
893                                 fprintf(fout, "%-*s%s\n", (width_total - width) / 2, "",
894                                                 cont->title);
895                 }
896
897                 /* print headers */
898                 if (!opt_tuples_only)
899                 {
900                         int                     more_col_wrapping;
901                         int                     curr_nl_line;
902
903                         if (opt_border == 2)
904                                 _print_horizontal_line(col_count, width_wrap, opt_border,
905                                                                            PRINT_RULE_TOP, format, fout);
906
907                         for (i = 0; i < col_count; i++)
908                                 pg_wcsformat((const unsigned char *) cont->headers[i],
909                                                          strlen(cont->headers[i]), encoding,
910                                                          col_lineptrs[i], max_nl_lines[i]);
911
912                         more_col_wrapping = col_count;
913                         curr_nl_line = 0;
914                         memset(header_done, false, col_count * sizeof(bool));
915                         while (more_col_wrapping)
916                         {
917                                 if (opt_border == 2)
918                                         fputs(dformat->leftvrule, fout);
919
920                                 for (i = 0; i < cont->ncolumns; i++)
921                                 {
922                                         struct lineptr *this_line = col_lineptrs[i] + curr_nl_line;
923                                         unsigned int nbspace;
924
925                                         if (opt_border != 0 ||
926                                                 (!format->wrap_right_border && i > 0))
927                                                 fputs(curr_nl_line ? format->header_nl_left : " ",
928                                                           fout);
929
930                                         if (!header_done[i])
931                                         {
932                                                 nbspace = width_wrap[i] - this_line->width;
933
934                                                 /* centered */
935                                                 fprintf(fout, "%-*s%s%-*s",
936                                                                 nbspace / 2, "", this_line->ptr, (nbspace + 1) / 2, "");
937
938                                                 if (!(this_line + 1)->ptr)
939                                                 {
940                                                         more_col_wrapping--;
941                                                         header_done[i] = 1;
942                                                 }
943                                         }
944                                         else
945                                                 fprintf(fout, "%*s", width_wrap[i], "");
946
947                                         if (opt_border != 0 || format->wrap_right_border)
948                                                 fputs(!header_done[i] ? format->header_nl_right : " ",
949                                                           fout);
950
951                                         if (opt_border != 0 && col_count > 0 && i < col_count - 1)
952                                                 fputs(dformat->midvrule, fout);
953                                 }
954                                 curr_nl_line++;
955
956                                 if (opt_border == 2)
957                                         fputs(dformat->rightvrule, fout);
958                                 fputc('\n', fout);
959                         }
960
961                         _print_horizontal_line(col_count, width_wrap, opt_border,
962                                                                    PRINT_RULE_MIDDLE, format, fout);
963                 }
964         }
965
966         /* print cells, one loop per row */
967         for (i = 0, ptr = cont->cells; *ptr; i += col_count, ptr += col_count)
968         {
969                 bool            more_lines;
970
971                 if (cancel_pressed)
972                         break;
973
974                 /*
975                  * Format each cell.
976                  */
977                 for (j = 0; j < col_count; j++)
978                 {
979                         pg_wcsformat((const unsigned char *) ptr[j], strlen(ptr[j]), encoding,
980                                                  col_lineptrs[j], max_nl_lines[j]);
981                         curr_nl_line[j] = 0;
982                 }
983
984                 memset(bytes_output, 0, col_count * sizeof(int));
985
986                 /*
987                  * Each time through this loop, one display line is output. It can
988                  * either be a full value or a partial value if embedded newlines
989                  * exist or if 'format=wrapping' mode is enabled.
990                  */
991                 do
992                 {
993                         more_lines = false;
994
995                         /* left border */
996                         if (opt_border == 2)
997                                 fputs(dformat->leftvrule, fout);
998
999                         /* for each column */
1000                         for (j = 0; j < col_count; j++)
1001                         {
1002                                 /* We have a valid array element, so index it */
1003                                 struct lineptr *this_line = &col_lineptrs[j][curr_nl_line[j]];
1004                                 int                     bytes_to_output;
1005                                 int                     chars_to_output = width_wrap[j];
1006                                 bool            finalspaces = (opt_border == 2 ||
1007                                                                                    (col_count > 0 && j < col_count - 1));
1008
1009                                 /* Print left-hand wrap or newline mark */
1010                                 if (opt_border != 0)
1011                                 {
1012                                         if (wrap[j] == PRINT_LINE_WRAP_WRAP)
1013                                                 fputs(format->wrap_left, fout);
1014                                         else if (wrap[j] == PRINT_LINE_WRAP_NEWLINE)
1015                                                 fputs(format->nl_left, fout);
1016                                         else
1017                                                 fputc(' ', fout);
1018                                 }
1019
1020                                 if (!this_line->ptr)
1021                                 {
1022                                         /* Past newline lines so just pad for other columns */
1023                                         if (finalspaces)
1024                                                 fprintf(fout, "%*s", chars_to_output, "");
1025                                 }
1026                                 else
1027                                 {
1028                                         /* Get strlen() of the characters up to width_wrap */
1029                                         bytes_to_output =
1030                                                 strlen_max_width(this_line->ptr + bytes_output[j],
1031                                                                                  &chars_to_output, encoding);
1032
1033                                         /*
1034                                          * If we exceeded width_wrap, it means the display width
1035                                          * of a single character was wider than our target width.
1036                                          * In that case, we have to pretend we are only printing
1037                                          * the target display width and make the best of it.
1038                                          */
1039                                         if (chars_to_output > width_wrap[j])
1040                                                 chars_to_output = width_wrap[j];
1041
1042                                         if (cont->aligns[j] == 'r') /* Right aligned cell */
1043                                         {
1044                                                 /* spaces first */
1045                                                 fprintf(fout, "%*s", width_wrap[j] - chars_to_output, "");
1046                                                 fputnbytes(fout,
1047                                                                    (char *) (this_line->ptr + bytes_output[j]),
1048                                                                    bytes_to_output);
1049                                         }
1050                                         else            /* Left aligned cell */
1051                                         {
1052                                                 /* spaces second */
1053                                                 fputnbytes(fout,
1054                                                                    (char *) (this_line->ptr + bytes_output[j]),
1055                                                                    bytes_to_output);
1056                                         }
1057
1058                                         bytes_output[j] += bytes_to_output;
1059
1060                                         /* Do we have more text to wrap? */
1061                                         if (*(this_line->ptr + bytes_output[j]) != '\0')
1062                                                 more_lines = true;
1063                                         else
1064                                         {
1065                                                 /* Advance to next newline line */
1066                                                 curr_nl_line[j]++;
1067                                                 if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL)
1068                                                         more_lines = true;
1069                                                 bytes_output[j] = 0;
1070                                         }
1071                                 }
1072
1073                                 /* Determine next line's wrap status for this column */
1074                                 wrap[j] = PRINT_LINE_WRAP_NONE;
1075                                 if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL)
1076                                 {
1077                                         if (bytes_output[j] != 0)
1078                                                 wrap[j] = PRINT_LINE_WRAP_WRAP;
1079                                         else if (curr_nl_line[j] != 0)
1080                                                 wrap[j] = PRINT_LINE_WRAP_NEWLINE;
1081                                 }
1082
1083                                 /*
1084                                  * If left-aligned, pad out remaining space if needed (not
1085                                  * last column, and/or wrap marks required).
1086                                  */
1087                                 if (cont->aligns[j] != 'r') /* Left aligned cell */
1088                                 {
1089                                         if (finalspaces ||
1090                                                 wrap[j] == PRINT_LINE_WRAP_WRAP ||
1091                                                 wrap[j] == PRINT_LINE_WRAP_NEWLINE)
1092                                                 fprintf(fout, "%*s",
1093                                                                 width_wrap[j] - chars_to_output, "");
1094                                 }
1095
1096                                 /* Print right-hand wrap or newline mark */
1097                                 if (wrap[j] == PRINT_LINE_WRAP_WRAP)
1098                                         fputs(format->wrap_right, fout);
1099                                 else if (wrap[j] == PRINT_LINE_WRAP_NEWLINE)
1100                                         fputs(format->nl_right, fout);
1101                                 else if (opt_border == 2 || (col_count > 0 && j < col_count - 1))
1102                                         fputc(' ', fout);
1103
1104                                 /* Print column divider, if not the last column */
1105                                 if (opt_border != 0 && (col_count > 0 && j < col_count - 1))
1106                                 {
1107                                         if (wrap[j + 1] == PRINT_LINE_WRAP_WRAP)
1108                                                 fputs(format->midvrule_wrap, fout);
1109                                         else if (wrap[j + 1] == PRINT_LINE_WRAP_NEWLINE)
1110                                                 fputs(format->midvrule_nl, fout);
1111                                         else if (col_lineptrs[j + 1][curr_nl_line[j + 1]].ptr == NULL)
1112                                                 fputs(format->midvrule_blank, fout);
1113                                         else
1114                                                 fputs(dformat->midvrule, fout);
1115                                 }
1116                         }
1117
1118                         /* end-of-row border */
1119                         if (opt_border == 2)
1120                                 fputs(dformat->rightvrule, fout);
1121                         fputc('\n', fout);
1122
1123                 } while (more_lines);
1124         }
1125
1126         if (cont->opt->stop_table)
1127         {
1128                 printTableFooter *footers = footers_with_default(cont);
1129
1130                 if (opt_border == 2 && !cancel_pressed)
1131                         _print_horizontal_line(col_count, width_wrap, opt_border,
1132                                                                    PRINT_RULE_BOTTOM, format, fout);
1133
1134                 /* print footers */
1135                 if (footers && !opt_tuples_only && !cancel_pressed)
1136                 {
1137                         printTableFooter *f;
1138
1139                         for (f = footers; f; f = f->next)
1140                                 fprintf(fout, "%s\n", f->data);
1141                 }
1142
1143                 fputc('\n', fout);
1144         }
1145
1146 cleanup:
1147         /* clean up */
1148         for (i = 0; i < col_count; i++)
1149         {
1150                 free(col_lineptrs[i]);
1151                 free(format_buf[i]);
1152         }
1153         free(width_header);
1154         free(width_average);
1155         free(max_width);
1156         free(width_wrap);
1157         free(max_nl_lines);
1158         free(curr_nl_line);
1159         free(col_lineptrs);
1160         free(max_bytes);
1161         free(format_buf);
1162         free(header_done);
1163         free(bytes_output);
1164         free(wrap);
1165
1166         if (is_local_pager)
1167                 ClosePager(fout);
1168 }
1169
1170
1171 static void
1172 print_aligned_vertical_line(const printTextFormat *format,
1173                                                         const unsigned short opt_border,
1174                                                         unsigned long record,
1175                                                         unsigned int hwidth,
1176                                                         unsigned int dwidth,
1177                                                         printTextRule pos,
1178                                                         FILE *fout)
1179 {
1180         const printTextLineFormat *lformat = &format->lrule[pos];
1181         unsigned int i;
1182         int                     reclen = 0;
1183
1184         if (opt_border == 2)
1185                 fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule);
1186         else if (opt_border == 1)
1187                 fputs(lformat->hrule, fout);
1188
1189         if (record)
1190         {
1191                 if (opt_border == 0)
1192                         reclen = fprintf(fout, "* Record %lu", record);
1193                 else
1194                         reclen = fprintf(fout, "[ RECORD %lu ]", record);
1195         }
1196         if (opt_border != 2)
1197                 reclen++;
1198         if (reclen < 0)
1199                 reclen = 0;
1200         for (i = reclen; i < hwidth; i++)
1201                 fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1202         reclen -= hwidth;
1203
1204         if (opt_border > 0)
1205         {
1206                 if (reclen-- <= 0)
1207                         fputs(lformat->hrule, fout);
1208                 if (reclen-- <= 0)
1209                         fputs(lformat->midvrule, fout);
1210                 if (reclen-- <= 0)
1211                         fputs(lformat->hrule, fout);
1212         }
1213         else
1214         {
1215                 if (reclen-- <= 0)
1216                         fputc(' ', fout);
1217         }
1218         if (reclen < 0)
1219                 reclen = 0;
1220         for (i = reclen; i < dwidth; i++)
1221                 fputs(opt_border > 0 ? lformat->hrule : " ", fout);
1222         if (opt_border == 2)
1223                 fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule);
1224         fputc('\n', fout);
1225 }
1226
1227 static void
1228 print_aligned_vertical(const printTableContent *cont,
1229                                            FILE *fout, bool is_pager)
1230 {
1231         bool            opt_tuples_only = cont->opt->tuples_only;
1232         unsigned short opt_border = cont->opt->border;
1233         const printTextFormat *format = get_line_style(cont->opt);
1234         const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA];
1235         int                     encoding = cont->opt->encoding;
1236         unsigned long record = cont->opt->prior_records + 1;
1237         const char *const *ptr;
1238         unsigned int i,
1239                                 hwidth = 0,
1240                                 dwidth = 0,
1241                                 hheight = 1,
1242                                 dheight = 1,
1243                                 hformatsize = 0,
1244                                 dformatsize = 0;
1245         struct lineptr *hlineptr,
1246                            *dlineptr;
1247         bool            is_local_pager = false,
1248                                 hmultiline = false,
1249                                 dmultiline = false;
1250         int                     output_columns = 0; /* Width of interactive console */
1251
1252         if (cancel_pressed)
1253                 return;
1254
1255         if (opt_border > 2)
1256                 opt_border = 2;
1257
1258         if (cont->cells[0] == NULL && cont->opt->start_table &&
1259                 cont->opt->stop_table)
1260         {
1261                 printTableFooter *footers = footers_with_default(cont);
1262
1263                 if (!opt_tuples_only && !cancel_pressed && footers)
1264                 {
1265                         printTableFooter *f;
1266
1267                         for (f = footers; f; f = f->next)
1268                                 fprintf(fout, "%s\n", f->data);
1269                 }
1270
1271                 fputc('\n', fout);
1272
1273                 return;
1274         }
1275
1276         /*
1277          * Deal with the pager here instead of in printTable(), because we could
1278          * get here via print_aligned_text() in expanded auto mode, and so we have
1279          * to recalculate the pager requirement based on vertical output.
1280          */
1281         if (!is_pager)
1282         {
1283                 IsPagerNeeded(cont, 0, true, &fout, &is_pager);
1284                 is_local_pager = is_pager;
1285         }
1286
1287         /* Find the maximum dimensions for the headers */
1288         for (i = 0; i < cont->ncolumns; i++)
1289         {
1290                 int                     width,
1291                                         height,
1292                                         fs;
1293
1294                 pg_wcssize((const unsigned char *) cont->headers[i], strlen(cont->headers[i]),
1295                                    encoding, &width, &height, &fs);
1296                 if (width > hwidth)
1297                         hwidth = width;
1298                 if (height > hheight)
1299                 {
1300                         hheight = height;
1301                         hmultiline = true;
1302                 }
1303                 if (fs > hformatsize)
1304                         hformatsize = fs;
1305         }
1306
1307         /* find longest data cell */
1308         for (i = 0, ptr = cont->cells; *ptr; ptr++, i++)
1309         {
1310                 int                     width,
1311                                         height,
1312                                         fs;
1313
1314                 pg_wcssize((const unsigned char *) *ptr, strlen(*ptr), encoding,
1315                                    &width, &height, &fs);
1316                 if (width > dwidth)
1317                         dwidth = width;
1318                 if (height > dheight)
1319                 {
1320                         dheight = height;
1321                         dmultiline = true;
1322                 }
1323                 if (fs > dformatsize)
1324                         dformatsize = fs;
1325         }
1326
1327         /*
1328          * We now have all the information we need to setup the formatting
1329          * structures
1330          */
1331         dlineptr = pg_malloc((sizeof(*dlineptr)) * (dheight + 1));
1332         hlineptr = pg_malloc((sizeof(*hlineptr)) * (hheight + 1));
1333
1334         dlineptr->ptr = pg_malloc(dformatsize);
1335         hlineptr->ptr = pg_malloc(hformatsize);
1336
1337         if (cont->opt->start_table)
1338         {
1339                 /* print title */
1340                 if (!opt_tuples_only && cont->title)
1341                         fprintf(fout, "%s\n", cont->title);
1342         }
1343
1344         /*
1345          * Choose target output width: \pset columns, or $COLUMNS, or ioctl
1346          */
1347         if (cont->opt->columns > 0)
1348                 output_columns = cont->opt->columns;
1349         else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
1350         {
1351                 if (cont->opt->env_columns > 0)
1352                         output_columns = cont->opt->env_columns;
1353 #ifdef TIOCGWINSZ
1354                 else
1355                 {
1356                         struct winsize screen_size;
1357
1358                         if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
1359                                 output_columns = screen_size.ws_col;
1360                 }
1361 #endif
1362         }
1363
1364         /*
1365          * Calculate available width for data in wrapped mode
1366          */
1367         if (cont->opt->format == PRINT_WRAPPED)
1368         {
1369                 unsigned int swidth,
1370                                         rwidth = 0,
1371                                         newdwidth;
1372
1373                 if (opt_border == 0)
1374                 {
1375                         /*
1376                          * For border = 0, one space in the middle.  (If we discover we
1377                          * need to wrap, the spacer column will be replaced by a wrap
1378                          * marker, and we'll make room below for another wrap marker at
1379                          * the end of the line.  But for now, assume no wrap is needed.)
1380                          */
1381                         swidth = 1;
1382
1383                         /* We might need a column for header newline markers, too */
1384                         if (hmultiline)
1385                                 swidth++;
1386                 }
1387                 else if (opt_border == 1)
1388                 {
1389                         /*
1390                          * For border = 1, two spaces and a vrule in the middle.  (As
1391                          * above, we might need one more column for a wrap marker.)
1392                          */
1393                         swidth = 3;
1394
1395                         /* We might need a column for left header newline markers, too */
1396                         if (hmultiline && (format == &pg_asciiformat_old))
1397                                 swidth++;
1398                 }
1399                 else
1400                 {
1401                         /*
1402                          * For border = 2, two more for the vrules at the beginning and
1403                          * end of the lines, plus spacer columns adjacent to these.  (We
1404                          * won't need extra columns for wrap/newline markers, we'll just
1405                          * repurpose the spacers.)
1406                          */
1407                         swidth = 7;
1408                 }
1409
1410                 /* Reserve a column for data newline indicators, too, if needed */
1411                 if (dmultiline &&
1412                         opt_border < 2 && format != &pg_asciiformat_old)
1413                         swidth++;
1414
1415                 /* Determine width required for record header lines */
1416                 if (!opt_tuples_only)
1417                 {
1418                         if (cont->nrows > 0)
1419                                 rwidth = 1 + (int) log10(cont->nrows);
1420                         if (opt_border == 0)
1421                                 rwidth += 9;    /* "* RECORD " */
1422                         else if (opt_border == 1)
1423                                 rwidth += 12;   /* "-[ RECORD  ]" */
1424                         else
1425                                 rwidth += 15;   /* "+-[ RECORD  ]-+" */
1426                 }
1427
1428                 /* We might need to do the rest of the calculation twice */
1429                 for (;;)
1430                 {
1431                         unsigned int width;
1432
1433                         /* Total width required to not wrap data */
1434                         width = hwidth + swidth + dwidth;
1435                         /* ... and not the header lines, either */
1436                         if (width < rwidth)
1437                                 width = rwidth;
1438
1439                         if (output_columns > 0)
1440                         {
1441                                 unsigned int min_width;
1442
1443                                 /* Minimum acceptable width: room for just 3 columns of data */
1444                                 min_width = hwidth + swidth + 3;
1445                                 /* ... but not less than what the record header lines need */
1446                                 if (min_width < rwidth)
1447                                         min_width = rwidth;
1448
1449                                 if (output_columns >= width)
1450                                 {
1451                                         /* Plenty of room, use native data width */
1452                                         /* (but at least enough for the record header lines) */
1453                                         newdwidth = width - hwidth - swidth;
1454                                 }
1455                                 else if (output_columns < min_width)
1456                                 {
1457                                         /* Set data width to match min_width */
1458                                         newdwidth = min_width - hwidth - swidth;
1459                                 }
1460                                 else
1461                                 {
1462                                         /* Set data width to match output_columns */
1463                                         newdwidth = output_columns - hwidth - swidth;
1464                                 }
1465                         }
1466                         else
1467                         {
1468                                 /* Don't know the wrap limit, so use native data width */
1469                                 /* (but at least enough for the record header lines) */
1470                                 newdwidth = width - hwidth - swidth;
1471                         }
1472
1473                         /*
1474                          * If we will need to wrap data and didn't already allocate a data
1475                          * newline/wrap marker column, do so and recompute.
1476                          */
1477                         if (newdwidth < dwidth && !dmultiline &&
1478                                 opt_border < 2 && format != &pg_asciiformat_old)
1479                         {
1480                                 dmultiline = true;
1481                                 swidth++;
1482                         }
1483                         else
1484                                 break;
1485                 }
1486
1487                 dwidth = newdwidth;
1488         }
1489
1490         /* print records */
1491         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1492         {
1493                 printTextRule pos;
1494                 int                     dline,
1495                                         hline,
1496                                         dcomplete,
1497                                         hcomplete,
1498                                         offset,
1499                                         chars_to_output;
1500
1501                 if (cancel_pressed)
1502                         break;
1503
1504                 if (i == 0)
1505                         pos = PRINT_RULE_TOP;
1506                 else
1507                         pos = PRINT_RULE_MIDDLE;
1508
1509                 /* Print record header (e.g. "[ RECORD N ]") above each record */
1510                 if (i % cont->ncolumns == 0)
1511                 {
1512                         unsigned int lhwidth = hwidth;
1513
1514                         if ((opt_border < 2) &&
1515                                 (hmultiline) &&
1516                                 (format == &pg_asciiformat_old))
1517                                 lhwidth++;              /* for newline indicators */
1518
1519                         if (!opt_tuples_only)
1520                                 print_aligned_vertical_line(format, opt_border, record++,
1521                                                                                         lhwidth, dwidth, pos, fout);
1522                         else if (i != 0 || !cont->opt->start_table || opt_border == 2)
1523                                 print_aligned_vertical_line(format, opt_border, 0, lhwidth,
1524                                                                                         dwidth, pos, fout);
1525                 }
1526
1527                 /* Format the header */
1528                 pg_wcsformat((const unsigned char *) cont->headers[i % cont->ncolumns],
1529                                          strlen(cont->headers[i % cont->ncolumns]),
1530                                          encoding, hlineptr, hheight);
1531                 /* Format the data */
1532                 pg_wcsformat((const unsigned char *) *ptr, strlen(*ptr), encoding,
1533                                          dlineptr, dheight);
1534
1535                 /*
1536                  * Loop through header and data in parallel dealing with newlines and
1537                  * wrapped lines until they're both exhausted
1538                  */
1539                 dline = hline = 0;
1540                 dcomplete = hcomplete = 0;
1541                 offset = 0;
1542                 chars_to_output = dlineptr[dline].width;
1543                 while (!dcomplete || !hcomplete)
1544                 {
1545                         /* Left border */
1546                         if (opt_border == 2)
1547                                 fprintf(fout, "%s", dformat->leftvrule);
1548
1549                         /* Header (never wrapped so just need to deal with newlines) */
1550                         if (!hcomplete)
1551                         {
1552                                 int                     swidth = hwidth,
1553                                                         target_width = hwidth;
1554
1555                                 /*
1556                                  * Left spacer or new line indicator
1557                                  */
1558                                 if ((opt_border == 2) ||
1559                                         (hmultiline && (format == &pg_asciiformat_old)))
1560                                         fputs(hline ? format->header_nl_left : " ", fout);
1561
1562                                 /*
1563                                  * Header text
1564                                  */
1565                                 strlen_max_width(hlineptr[hline].ptr, &target_width,
1566                                                                  encoding);
1567                                 fprintf(fout, "%-s", hlineptr[hline].ptr);
1568
1569                                 /*
1570                                  * Spacer
1571                                  */
1572                                 swidth -= target_width;
1573                                 if (swidth > 0)
1574                                         fprintf(fout, "%*s", swidth, " ");
1575
1576                                 /*
1577                                  * New line indicator or separator's space
1578                                  */
1579                                 if (hlineptr[hline + 1].ptr)
1580                                 {
1581                                         /* More lines after this one due to a newline */
1582                                         if ((opt_border > 0) ||
1583                                                 (hmultiline && (format != &pg_asciiformat_old)))
1584                                                 fputs(format->header_nl_right, fout);
1585                                         hline++;
1586                                 }
1587                                 else
1588                                 {
1589                                         /* This was the last line of the header */
1590                                         if ((opt_border > 0) ||
1591                                                 (hmultiline && (format != &pg_asciiformat_old)))
1592                                                 fputs(" ", fout);
1593                                         hcomplete = 1;
1594                                 }
1595                         }
1596                         else
1597                         {
1598                                 unsigned int swidth = hwidth + opt_border;
1599
1600                                 if ((opt_border < 2) &&
1601                                         (hmultiline) &&
1602                                         (format == &pg_asciiformat_old))
1603                                         swidth++;
1604
1605                                 if ((opt_border == 0) &&
1606                                         (format != &pg_asciiformat_old) &&
1607                                         (hmultiline))
1608                                         swidth++;
1609
1610                                 fprintf(fout, "%*s", swidth, " ");
1611                         }
1612
1613                         /* Separator */
1614                         if (opt_border > 0)
1615                         {
1616                                 if (offset)
1617                                         fputs(format->midvrule_wrap, fout);
1618                                 else if (dline == 0)
1619                                         fputs(dformat->midvrule, fout);
1620                                 else
1621                                         fputs(format->midvrule_nl, fout);
1622                         }
1623
1624                         /* Data */
1625                         if (!dcomplete)
1626                         {
1627                                 int                     target_width = dwidth,
1628                                                         bytes_to_output,
1629                                                         swidth = dwidth;
1630
1631                                 /*
1632                                  * Left spacer or wrap indicator
1633                                  */
1634                                 fputs(offset == 0 ? " " : format->wrap_left, fout);
1635
1636                                 /*
1637                                  * Data text
1638                                  */
1639                                 bytes_to_output = strlen_max_width(dlineptr[dline].ptr + offset,
1640                                                                                                    &target_width, encoding);
1641                                 fputnbytes(fout, (char *) (dlineptr[dline].ptr + offset),
1642                                                    bytes_to_output);
1643
1644                                 chars_to_output -= target_width;
1645                                 offset += bytes_to_output;
1646
1647                                 /* Spacer */
1648                                 swidth -= target_width;
1649
1650                                 if (chars_to_output)
1651                                 {
1652                                         /* continuing a wrapped column */
1653                                         if ((opt_border > 1) ||
1654                                                 (dmultiline && (format != &pg_asciiformat_old)))
1655                                         {
1656                                                 if (swidth > 0)
1657                                                         fprintf(fout, "%*s", swidth, " ");
1658                                                 fputs(format->wrap_right, fout);
1659                                         }
1660                                 }
1661                                 else if (dlineptr[dline + 1].ptr)
1662                                 {
1663                                         /* reached a newline in the column */
1664                                         if ((opt_border > 1) ||
1665                                                 (dmultiline && (format != &pg_asciiformat_old)))
1666                                         {
1667                                                 if (swidth > 0)
1668                                                         fprintf(fout, "%*s", swidth, " ");
1669                                                 fputs(format->nl_right, fout);
1670                                         }
1671                                         dline++;
1672                                         offset = 0;
1673                                         chars_to_output = dlineptr[dline].width;
1674                                 }
1675                                 else
1676                                 {
1677                                         /* reached the end of the cell */
1678                                         if (opt_border > 1)
1679                                         {
1680                                                 if (swidth > 0)
1681                                                         fprintf(fout, "%*s", swidth, " ");
1682                                                 fputs(" ", fout);
1683                                         }
1684                                         dcomplete = 1;
1685                                 }
1686
1687                                 /* Right border */
1688                                 if (opt_border == 2)
1689                                         fputs(dformat->rightvrule, fout);
1690
1691                                 fputs("\n", fout);
1692                         }
1693                         else
1694                         {
1695                                 /*
1696                                  * data exhausted (this can occur if header is longer than the
1697                                  * data due to newlines in the header)
1698                                  */
1699                                 if (opt_border < 2)
1700                                         fputs("\n", fout);
1701                                 else
1702                                         fprintf(fout, "%*s  %s\n", dwidth, "", dformat->rightvrule);
1703                         }
1704                 }
1705         }
1706
1707         if (cont->opt->stop_table)
1708         {
1709                 if (opt_border == 2 && !cancel_pressed)
1710                         print_aligned_vertical_line(format, opt_border, 0, hwidth, dwidth,
1711                                                                                 PRINT_RULE_BOTTOM, fout);
1712
1713                 /* print footers */
1714                 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
1715                 {
1716                         printTableFooter *f;
1717
1718                         if (opt_border < 2)
1719                                 fputc('\n', fout);
1720                         for (f = cont->footers; f; f = f->next)
1721                                 fprintf(fout, "%s\n", f->data);
1722                 }
1723
1724                 fputc('\n', fout);
1725         }
1726
1727         free(hlineptr->ptr);
1728         free(dlineptr->ptr);
1729         free(hlineptr);
1730         free(dlineptr);
1731
1732         if (is_local_pager)
1733                 ClosePager(fout);
1734 }
1735
1736
1737 /**********************/
1738 /* CSV format             */
1739 /**********************/
1740
1741
1742 static void
1743 csv_escaped_print(const char *str, FILE *fout)
1744 {
1745         const char *p;
1746
1747         fputc('"', fout);
1748         for (p = str; *p; p++)
1749         {
1750                 if (*p == '"')
1751                         fputc('"', fout);       /* double quotes are doubled */
1752                 fputc(*p, fout);
1753         }
1754         fputc('"', fout);
1755 }
1756
1757 static void
1758 csv_print_field(const char *str, FILE *fout, char sep)
1759 {
1760         /*----------------
1761          * Enclose and escape field contents when one of these conditions is met:
1762          * - the field separator is found in the contents.
1763          * - the field contains a CR or LF.
1764          * - the field contains a double quote.
1765          * - the field is exactly "\.".
1766          * - the field separator is either "\" or ".".
1767          * The last two cases prevent producing a line that the server's COPY
1768          * command would interpret as an end-of-data marker.  We only really
1769          * need to ensure that the complete line isn't exactly "\.", but for
1770          * simplicity we apply stronger restrictions here.
1771          *----------------
1772          */
1773         if (strchr(str, sep) != NULL ||
1774                 strcspn(str, "\r\n\"") != strlen(str) ||
1775                 strcmp(str, "\\.") == 0 ||
1776                 sep == '\\' || sep == '.')
1777                 csv_escaped_print(str, fout);
1778         else
1779                 fputs(str, fout);
1780 }
1781
1782 static void
1783 print_csv_text(const printTableContent *cont, FILE *fout)
1784 {
1785         const char *const *ptr;
1786         int                     i;
1787
1788         if (cancel_pressed)
1789                 return;
1790
1791         /*
1792          * The title and footer are never printed in csv format. The header is
1793          * printed if opt_tuples_only is false.
1794          *
1795          * Despite RFC 4180 saying that end of lines are CRLF, terminate lines
1796          * with '\n', which prints out as the system-dependent EOL string in text
1797          * mode (typically LF on Unix and CRLF on Windows).
1798          */
1799         if (cont->opt->start_table && !cont->opt->tuples_only)
1800         {
1801                 /* print headers */
1802                 for (ptr = cont->headers; *ptr; ptr++)
1803                 {
1804                         if (ptr != cont->headers)
1805                                 fputc(cont->opt->csvFieldSep[0], fout);
1806                         csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1807                 }
1808                 fputc('\n', fout);
1809         }
1810
1811         /* print cells */
1812         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1813         {
1814                 csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1815                 if ((i + 1) % cont->ncolumns)
1816                         fputc(cont->opt->csvFieldSep[0], fout);
1817                 else
1818                         fputc('\n', fout);
1819         }
1820 }
1821
1822 static void
1823 print_csv_vertical(const printTableContent *cont, FILE *fout)
1824 {
1825         const char *const *ptr;
1826         int                     i;
1827
1828         /* print records */
1829         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1830         {
1831                 if (cancel_pressed)
1832                         return;
1833
1834                 /* print name of column */
1835                 csv_print_field(cont->headers[i % cont->ncolumns], fout,
1836                                                 cont->opt->csvFieldSep[0]);
1837
1838                 /* print field separator */
1839                 fputc(cont->opt->csvFieldSep[0], fout);
1840
1841                 /* print field value */
1842                 csv_print_field(*ptr, fout, cont->opt->csvFieldSep[0]);
1843
1844                 fputc('\n', fout);
1845         }
1846 }
1847
1848
1849 /**********************/
1850 /* HTML                           */
1851 /**********************/
1852
1853
1854 void
1855 html_escaped_print(const char *in, FILE *fout)
1856 {
1857         const char *p;
1858         bool            leading_space = true;
1859
1860         for (p = in; *p; p++)
1861         {
1862                 switch (*p)
1863                 {
1864                         case '&':
1865                                 fputs("&amp;", fout);
1866                                 break;
1867                         case '<':
1868                                 fputs("&lt;", fout);
1869                                 break;
1870                         case '>':
1871                                 fputs("&gt;", fout);
1872                                 break;
1873                         case '\n':
1874                                 fputs("<br />\n", fout);
1875                                 break;
1876                         case '"':
1877                                 fputs("&quot;", fout);
1878                                 break;
1879                         case ' ':
1880                                 /* protect leading space, for EXPLAIN output */
1881                                 if (leading_space)
1882                                         fputs("&nbsp;", fout);
1883                                 else
1884                                         fputs(" ", fout);
1885                                 break;
1886                         default:
1887                                 fputc(*p, fout);
1888                 }
1889                 if (*p != ' ')
1890                         leading_space = false;
1891         }
1892 }
1893
1894
1895 static void
1896 print_html_text(const printTableContent *cont, FILE *fout)
1897 {
1898         bool            opt_tuples_only = cont->opt->tuples_only;
1899         unsigned short opt_border = cont->opt->border;
1900         const char *opt_table_attr = cont->opt->tableAttr;
1901         unsigned int i;
1902         const char *const *ptr;
1903
1904         if (cancel_pressed)
1905                 return;
1906
1907         if (cont->opt->start_table)
1908         {
1909                 fprintf(fout, "<table border=\"%d\"", opt_border);
1910                 if (opt_table_attr)
1911                         fprintf(fout, " %s", opt_table_attr);
1912                 fputs(">\n", fout);
1913
1914                 /* print title */
1915                 if (!opt_tuples_only && cont->title)
1916                 {
1917                         fputs("  <caption>", fout);
1918                         html_escaped_print(cont->title, fout);
1919                         fputs("</caption>\n", fout);
1920                 }
1921
1922                 /* print headers */
1923                 if (!opt_tuples_only)
1924                 {
1925                         fputs("  <tr>\n", fout);
1926                         for (ptr = cont->headers; *ptr; ptr++)
1927                         {
1928                                 fputs("    <th align=\"center\">", fout);
1929                                 html_escaped_print(*ptr, fout);
1930                                 fputs("</th>\n", fout);
1931                         }
1932                         fputs("  </tr>\n", fout);
1933                 }
1934         }
1935
1936         /* print cells */
1937         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
1938         {
1939                 if (i % cont->ncolumns == 0)
1940                 {
1941                         if (cancel_pressed)
1942                                 break;
1943                         fputs("  <tr valign=\"top\">\n", fout);
1944                 }
1945
1946                 fprintf(fout, "    <td align=\"%s\">", cont->aligns[(i) % cont->ncolumns] == 'r' ? "right" : "left");
1947                 /* is string only whitespace? */
1948                 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
1949                         fputs("&nbsp; ", fout);
1950                 else
1951                         html_escaped_print(*ptr, fout);
1952
1953                 fputs("</td>\n", fout);
1954
1955                 if ((i + 1) % cont->ncolumns == 0)
1956                         fputs("  </tr>\n", fout);
1957         }
1958
1959         if (cont->opt->stop_table)
1960         {
1961                 printTableFooter *footers = footers_with_default(cont);
1962
1963                 fputs("</table>\n", fout);
1964
1965                 /* print footers */
1966                 if (!opt_tuples_only && footers != NULL && !cancel_pressed)
1967                 {
1968                         printTableFooter *f;
1969
1970                         fputs("<p>", fout);
1971                         for (f = footers; f; f = f->next)
1972                         {
1973                                 html_escaped_print(f->data, fout);
1974                                 fputs("<br />\n", fout);
1975                         }
1976                         fputs("</p>", fout);
1977                 }
1978
1979                 fputc('\n', fout);
1980         }
1981 }
1982
1983
1984 static void
1985 print_html_vertical(const printTableContent *cont, FILE *fout)
1986 {
1987         bool            opt_tuples_only = cont->opt->tuples_only;
1988         unsigned short opt_border = cont->opt->border;
1989         const char *opt_table_attr = cont->opt->tableAttr;
1990         unsigned long record = cont->opt->prior_records + 1;
1991         unsigned int i;
1992         const char *const *ptr;
1993
1994         if (cancel_pressed)
1995                 return;
1996
1997         if (cont->opt->start_table)
1998         {
1999                 fprintf(fout, "<table border=\"%d\"", opt_border);
2000                 if (opt_table_attr)
2001                         fprintf(fout, " %s", opt_table_attr);
2002                 fputs(">\n", fout);
2003
2004                 /* print title */
2005                 if (!opt_tuples_only && cont->title)
2006                 {
2007                         fputs("  <caption>", fout);
2008                         html_escaped_print(cont->title, fout);
2009                         fputs("</caption>\n", fout);
2010                 }
2011         }
2012
2013         /* print records */
2014         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2015         {
2016                 if (i % cont->ncolumns == 0)
2017                 {
2018                         if (cancel_pressed)
2019                                 break;
2020                         if (!opt_tuples_only)
2021                                 fprintf(fout,
2022                                                 "\n  <tr><td colspan=\"2\" align=\"center\">Record %lu</td></tr>\n",
2023                                                 record++);
2024                         else
2025                                 fputs("\n  <tr><td colspan=\"2\">&nbsp;</td></tr>\n", fout);
2026                 }
2027                 fputs("  <tr valign=\"top\">\n"
2028                           "    <th>", fout);
2029                 html_escaped_print(cont->headers[i % cont->ncolumns], fout);
2030                 fputs("</th>\n", fout);
2031
2032                 fprintf(fout, "    <td align=\"%s\">", cont->aligns[i % cont->ncolumns] == 'r' ? "right" : "left");
2033                 /* is string only whitespace? */
2034                 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2035                         fputs("&nbsp; ", fout);
2036                 else
2037                         html_escaped_print(*ptr, fout);
2038
2039                 fputs("</td>\n  </tr>\n", fout);
2040         }
2041
2042         if (cont->opt->stop_table)
2043         {
2044                 fputs("</table>\n", fout);
2045
2046                 /* print footers */
2047                 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
2048                 {
2049                         printTableFooter *f;
2050
2051                         fputs("<p>", fout);
2052                         for (f = cont->footers; f; f = f->next)
2053                         {
2054                                 html_escaped_print(f->data, fout);
2055                                 fputs("<br />\n", fout);
2056                         }
2057                         fputs("</p>", fout);
2058                 }
2059
2060                 fputc('\n', fout);
2061         }
2062 }
2063
2064
2065 /*************************/
2066 /* ASCIIDOC                              */
2067 /*************************/
2068
2069
2070 static void
2071 asciidoc_escaped_print(const char *in, FILE *fout)
2072 {
2073         const char *p;
2074
2075         for (p = in; *p; p++)
2076         {
2077                 switch (*p)
2078                 {
2079                         case '|':
2080                                 fputs("\\|", fout);
2081                                 break;
2082                         default:
2083                                 fputc(*p, fout);
2084                 }
2085         }
2086 }
2087
2088 static void
2089 print_asciidoc_text(const printTableContent *cont, FILE *fout)
2090 {
2091         bool            opt_tuples_only = cont->opt->tuples_only;
2092         unsigned short opt_border = cont->opt->border;
2093         unsigned int i;
2094         const char *const *ptr;
2095
2096         if (cancel_pressed)
2097                 return;
2098
2099         if (cont->opt->start_table)
2100         {
2101                 /* print table in new paragraph - enforce preliminary new line */
2102                 fputs("\n", fout);
2103
2104                 /* print title */
2105                 if (!opt_tuples_only && cont->title)
2106                 {
2107                         fputs(".", fout);
2108                         fputs(cont->title, fout);
2109                         fputs("\n", fout);
2110                 }
2111
2112                 /* print table [] header definition */
2113                 fprintf(fout, "[%scols=\"", !opt_tuples_only ? "options=\"header\"," : "");
2114                 for (i = 0; i < cont->ncolumns; i++)
2115                 {
2116                         if (i != 0)
2117                                 fputs(",", fout);
2118                         fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "<l");
2119                 }
2120                 fputs("\"", fout);
2121                 switch (opt_border)
2122                 {
2123                         case 0:
2124                                 fputs(",frame=\"none\",grid=\"none\"", fout);
2125                                 break;
2126                         case 1:
2127                                 fputs(",frame=\"none\"", fout);
2128                                 break;
2129                         case 2:
2130                                 fputs(",frame=\"all\",grid=\"all\"", fout);
2131                                 break;
2132                 }
2133                 fputs("]\n", fout);
2134                 fputs("|====\n", fout);
2135
2136                 /* print headers */
2137                 if (!opt_tuples_only)
2138                 {
2139                         for (ptr = cont->headers; *ptr; ptr++)
2140                         {
2141                                 if (ptr != cont->headers)
2142                                         fputs(" ", fout);
2143                                 fputs("^l|", fout);
2144                                 asciidoc_escaped_print(*ptr, fout);
2145                         }
2146                         fputs("\n", fout);
2147                 }
2148         }
2149
2150         /* print cells */
2151         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2152         {
2153                 if (i % cont->ncolumns == 0)
2154                 {
2155                         if (cancel_pressed)
2156                                 break;
2157                 }
2158
2159                 if (i % cont->ncolumns != 0)
2160                         fputs(" ", fout);
2161                 fputs("|", fout);
2162
2163                 /* protect against needless spaces */
2164                 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2165                 {
2166                         if ((i + 1) % cont->ncolumns != 0)
2167                                 fputs(" ", fout);
2168                 }
2169                 else
2170                         asciidoc_escaped_print(*ptr, fout);
2171
2172                 if ((i + 1) % cont->ncolumns == 0)
2173                         fputs("\n", fout);
2174         }
2175
2176         fputs("|====\n", fout);
2177
2178         if (cont->opt->stop_table)
2179         {
2180                 printTableFooter *footers = footers_with_default(cont);
2181
2182                 /* print footers */
2183                 if (!opt_tuples_only && footers != NULL && !cancel_pressed)
2184                 {
2185                         printTableFooter *f;
2186
2187                         fputs("\n....\n", fout);
2188                         for (f = footers; f; f = f->next)
2189                         {
2190                                 fputs(f->data, fout);
2191                                 fputs("\n", fout);
2192                         }
2193                         fputs("....\n", fout);
2194                 }
2195         }
2196 }
2197
2198 static void
2199 print_asciidoc_vertical(const printTableContent *cont, FILE *fout)
2200 {
2201         bool            opt_tuples_only = cont->opt->tuples_only;
2202         unsigned short opt_border = cont->opt->border;
2203         unsigned long record = cont->opt->prior_records + 1;
2204         unsigned int i;
2205         const char *const *ptr;
2206
2207         if (cancel_pressed)
2208                 return;
2209
2210         if (cont->opt->start_table)
2211         {
2212                 /* print table in new paragraph - enforce preliminary new line */
2213                 fputs("\n", fout);
2214
2215                 /* print title */
2216                 if (!opt_tuples_only && cont->title)
2217                 {
2218                         fputs(".", fout);
2219                         fputs(cont->title, fout);
2220                         fputs("\n", fout);
2221                 }
2222
2223                 /* print table [] header definition */
2224                 fputs("[cols=\"h,l\"", fout);
2225                 switch (opt_border)
2226                 {
2227                         case 0:
2228                                 fputs(",frame=\"none\",grid=\"none\"", fout);
2229                                 break;
2230                         case 1:
2231                                 fputs(",frame=\"none\"", fout);
2232                                 break;
2233                         case 2:
2234                                 fputs(",frame=\"all\",grid=\"all\"", fout);
2235                                 break;
2236                 }
2237                 fputs("]\n", fout);
2238                 fputs("|====\n", fout);
2239         }
2240
2241         /* print records */
2242         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2243         {
2244                 if (i % cont->ncolumns == 0)
2245                 {
2246                         if (cancel_pressed)
2247                                 break;
2248                         if (!opt_tuples_only)
2249                                 fprintf(fout,
2250                                                 "2+^|Record %lu\n",
2251                                                 record++);
2252                         else
2253                                 fputs("2+|\n", fout);
2254                 }
2255
2256                 fputs("<l|", fout);
2257                 asciidoc_escaped_print(cont->headers[i % cont->ncolumns], fout);
2258
2259                 fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">l" : "<l");
2260                 /* is string only whitespace? */
2261                 if ((*ptr)[strspn(*ptr, " \t")] == '\0')
2262                         fputs(" ", fout);
2263                 else
2264                         asciidoc_escaped_print(*ptr, fout);
2265                 fputs("\n", fout);
2266         }
2267
2268         fputs("|====\n", fout);
2269
2270         if (cont->opt->stop_table)
2271         {
2272                 /* print footers */
2273                 if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
2274                 {
2275                         printTableFooter *f;
2276
2277                         fputs("\n....\n", fout);
2278                         for (f = cont->footers; f; f = f->next)
2279                         {
2280                                 fputs(f->data, fout);
2281                                 fputs("\n", fout);
2282                         }
2283                         fputs("....\n", fout);
2284                 }
2285         }
2286 }
2287
2288
2289 /*************************/
2290 /* LaTeX                                 */
2291 /*************************/
2292
2293
2294 static void
2295 latex_escaped_print(const char *in, FILE *fout)
2296 {
2297         const char *p;
2298
2299         for (p = in; *p; p++)
2300                 switch (*p)
2301                 {
2302                                 /*
2303                                  * We convert ASCII characters per the recommendations in
2304                                  * Scott Pakin's "The Comprehensive LATEX Symbol List",
2305                                  * available from CTAN.  For non-ASCII, you're on your own.
2306                                  */
2307                         case '#':
2308                                 fputs("\\#", fout);
2309                                 break;
2310                         case '$':
2311                                 fputs("\\$", fout);
2312                                 break;
2313                         case '%':
2314                                 fputs("\\%", fout);
2315                                 break;
2316                         case '&':
2317                                 fputs("\\&", fout);
2318                                 break;
2319                         case '<':
2320                                 fputs("\\textless{}", fout);
2321                                 break;
2322                         case '>':
2323                                 fputs("\\textgreater{}", fout);
2324                                 break;
2325                         case '\\':
2326                                 fputs("\\textbackslash{}", fout);
2327                                 break;
2328                         case '^':
2329                                 fputs("\\^{}", fout);
2330                                 break;
2331                         case '_':
2332                                 fputs("\\_", fout);
2333                                 break;
2334                         case '{':
2335                                 fputs("\\{", fout);
2336                                 break;
2337                         case '|':
2338                                 fputs("\\textbar{}", fout);
2339                                 break;
2340                         case '}':
2341                                 fputs("\\}", fout);
2342                                 break;
2343                         case '~':
2344                                 fputs("\\~{}", fout);
2345                                 break;
2346                         case '\n':
2347                                 /* This is not right, but doing it right seems too hard */
2348                                 fputs("\\\\", fout);
2349                                 break;
2350                         default:
2351                                 fputc(*p, fout);
2352                 }
2353 }
2354
2355
2356 static void
2357 print_latex_text(const printTableContent *cont, FILE *fout)
2358 {
2359         bool            opt_tuples_only = cont->opt->tuples_only;
2360         unsigned short opt_border = cont->opt->border;
2361         unsigned int i;
2362         const char *const *ptr;
2363
2364         if (cancel_pressed)
2365                 return;
2366
2367         if (opt_border > 3)
2368                 opt_border = 3;
2369
2370         if (cont->opt->start_table)
2371         {
2372                 /* print title */
2373                 if (!opt_tuples_only && cont->title)
2374                 {
2375                         fputs("\\begin{center}\n", fout);
2376                         latex_escaped_print(cont->title, fout);
2377                         fputs("\n\\end{center}\n\n", fout);
2378                 }
2379
2380                 /* begin environment and set alignments and borders */
2381                 fputs("\\begin{tabular}{", fout);
2382
2383                 if (opt_border >= 2)
2384                         fputs("| ", fout);
2385                 for (i = 0; i < cont->ncolumns; i++)
2386                 {
2387                         fputc(*(cont->aligns + i), fout);
2388                         if (opt_border != 0 && i < cont->ncolumns - 1)
2389                                 fputs(" | ", fout);
2390                 }
2391                 if (opt_border >= 2)
2392                         fputs(" |", fout);
2393
2394                 fputs("}\n", fout);
2395
2396                 if (!opt_tuples_only && opt_border >= 2)
2397                         fputs("\\hline\n", fout);
2398
2399                 /* print headers */
2400                 if (!opt_tuples_only)
2401                 {
2402                         for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2403                         {
2404                                 if (i != 0)
2405                                         fputs(" & ", fout);
2406                                 fputs("\\textit{", fout);
2407                                 latex_escaped_print(*ptr, fout);
2408                                 fputc('}', fout);
2409                         }
2410                         fputs(" \\\\\n", fout);
2411                         fputs("\\hline\n", fout);
2412                 }
2413         }
2414
2415         /* print cells */
2416         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2417         {
2418                 latex_escaped_print(*ptr, fout);
2419
2420                 if ((i + 1) % cont->ncolumns == 0)
2421                 {
2422                         fputs(" \\\\\n", fout);
2423                         if (opt_border == 3)
2424                                 fputs("\\hline\n", fout);
2425                         if (cancel_pressed)
2426                                 break;
2427                 }
2428                 else
2429                         fputs(" & ", fout);
2430         }
2431
2432         if (cont->opt->stop_table)
2433         {
2434                 printTableFooter *footers = footers_with_default(cont);
2435
2436                 if (opt_border == 2)
2437                         fputs("\\hline\n", fout);
2438
2439                 fputs("\\end{tabular}\n\n\\noindent ", fout);
2440
2441                 /* print footers */
2442                 if (footers && !opt_tuples_only && !cancel_pressed)
2443                 {
2444                         printTableFooter *f;
2445
2446                         for (f = footers; f; f = f->next)
2447                         {
2448                                 latex_escaped_print(f->data, fout);
2449                                 fputs(" \\\\\n", fout);
2450                         }
2451                 }
2452
2453                 fputc('\n', fout);
2454         }
2455 }
2456
2457
2458 /*************************/
2459 /* LaTeX longtable               */
2460 /*************************/
2461
2462
2463 static void
2464 print_latex_longtable_text(const printTableContent *cont, FILE *fout)
2465 {
2466         bool            opt_tuples_only = cont->opt->tuples_only;
2467         unsigned short opt_border = cont->opt->border;
2468         unsigned int i;
2469         const char *opt_table_attr = cont->opt->tableAttr;
2470         const char *next_opt_table_attr_char = opt_table_attr;
2471         const char *last_opt_table_attr_char = NULL;
2472         const char *const *ptr;
2473
2474         if (cancel_pressed)
2475                 return;
2476
2477         if (opt_border > 3)
2478                 opt_border = 3;
2479
2480         if (cont->opt->start_table)
2481         {
2482                 /* begin environment and set alignments and borders */
2483                 fputs("\\begin{longtable}{", fout);
2484
2485                 if (opt_border >= 2)
2486                         fputs("| ", fout);
2487
2488                 for (i = 0; i < cont->ncolumns; i++)
2489                 {
2490                         /* longtable supports either a width (p) or an alignment (l/r) */
2491                         /* Are we left-justified and was a proportional width specified? */
2492                         if (*(cont->aligns + i) == 'l' && opt_table_attr)
2493                         {
2494 #define LONGTABLE_WHITESPACE    " \t\n"
2495
2496                                 /* advance over whitespace */
2497                                 next_opt_table_attr_char += strspn(next_opt_table_attr_char,
2498                                                                                                    LONGTABLE_WHITESPACE);
2499                                 /* We have a value? */
2500                                 if (next_opt_table_attr_char[0] != '\0')
2501                                 {
2502                                         fputs("p{", fout);
2503                                         fwrite(next_opt_table_attr_char, strcspn(next_opt_table_attr_char,
2504                                                                                                                          LONGTABLE_WHITESPACE), 1, fout);
2505                                         last_opt_table_attr_char = next_opt_table_attr_char;
2506                                         next_opt_table_attr_char += strcspn(next_opt_table_attr_char,
2507                                                                                                                 LONGTABLE_WHITESPACE);
2508                                         fputs("\\textwidth}", fout);
2509                                 }
2510                                 /* use previous value */
2511                                 else if (last_opt_table_attr_char != NULL)
2512                                 {
2513                                         fputs("p{", fout);
2514                                         fwrite(last_opt_table_attr_char, strcspn(last_opt_table_attr_char,
2515                                                                                                                          LONGTABLE_WHITESPACE), 1, fout);
2516                                         fputs("\\textwidth}", fout);
2517                                 }
2518                                 else
2519                                         fputc('l', fout);
2520                         }
2521                         else
2522                                 fputc(*(cont->aligns + i), fout);
2523
2524                         if (opt_border != 0 && i < cont->ncolumns - 1)
2525                                 fputs(" | ", fout);
2526                 }
2527
2528                 if (opt_border >= 2)
2529                         fputs(" |", fout);
2530
2531                 fputs("}\n", fout);
2532
2533                 /* print headers */
2534                 if (!opt_tuples_only)
2535                 {
2536                         /* firsthead */
2537                         if (opt_border >= 2)
2538                                 fputs("\\toprule\n", fout);
2539                         for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2540                         {
2541                                 if (i != 0)
2542                                         fputs(" & ", fout);
2543                                 fputs("\\small\\textbf{\\textit{", fout);
2544                                 latex_escaped_print(*ptr, fout);
2545                                 fputs("}}", fout);
2546                         }
2547                         fputs(" \\\\\n", fout);
2548                         fputs("\\midrule\n\\endfirsthead\n", fout);
2549
2550                         /* secondary heads */
2551                         if (opt_border >= 2)
2552                                 fputs("\\toprule\n", fout);
2553                         for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2554                         {
2555                                 if (i != 0)
2556                                         fputs(" & ", fout);
2557                                 fputs("\\small\\textbf{\\textit{", fout);
2558                                 latex_escaped_print(*ptr, fout);
2559                                 fputs("}}", fout);
2560                         }
2561                         fputs(" \\\\\n", fout);
2562                         /* If the line under the row already appeared, don't do another */
2563                         if (opt_border != 3)
2564                                 fputs("\\midrule\n", fout);
2565                         fputs("\\endhead\n", fout);
2566
2567                         /* table name, caption? */
2568                         if (!opt_tuples_only && cont->title)
2569                         {
2570                                 /* Don't output if we are printing a line under each row */
2571                                 if (opt_border == 2)
2572                                         fputs("\\bottomrule\n", fout);
2573                                 fputs("\\caption[", fout);
2574                                 latex_escaped_print(cont->title, fout);
2575                                 fputs(" (Continued)]{", fout);
2576                                 latex_escaped_print(cont->title, fout);
2577                                 fputs("}\n\\endfoot\n", fout);
2578                                 if (opt_border == 2)
2579                                         fputs("\\bottomrule\n", fout);
2580                                 fputs("\\caption[", fout);
2581                                 latex_escaped_print(cont->title, fout);
2582                                 fputs("]{", fout);
2583                                 latex_escaped_print(cont->title, fout);
2584                                 fputs("}\n\\endlastfoot\n", fout);
2585                         }
2586                         /* output bottom table line? */
2587                         else if (opt_border >= 2)
2588                         {
2589                                 fputs("\\bottomrule\n\\endfoot\n", fout);
2590                                 fputs("\\bottomrule\n\\endlastfoot\n", fout);
2591                         }
2592                 }
2593         }
2594
2595         /* print cells */
2596         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2597         {
2598                 /* Add a line under each row? */
2599                 if (i != 0 && i % cont->ncolumns != 0)
2600                         fputs("\n&\n", fout);
2601                 fputs("\\raggedright{", fout);
2602                 latex_escaped_print(*ptr, fout);
2603                 fputc('}', fout);
2604                 if ((i + 1) % cont->ncolumns == 0)
2605                 {
2606                         fputs(" \\tabularnewline\n", fout);
2607                         if (opt_border == 3)
2608                                 fputs(" \\hline\n", fout);
2609                 }
2610                 if (cancel_pressed)
2611                         break;
2612         }
2613
2614         if (cont->opt->stop_table)
2615                 fputs("\\end{longtable}\n", fout);
2616 }
2617
2618
2619 static void
2620 print_latex_vertical(const printTableContent *cont, FILE *fout)
2621 {
2622         bool            opt_tuples_only = cont->opt->tuples_only;
2623         unsigned short opt_border = cont->opt->border;
2624         unsigned long record = cont->opt->prior_records + 1;
2625         unsigned int i;
2626         const char *const *ptr;
2627
2628         if (cancel_pressed)
2629                 return;
2630
2631         if (opt_border > 2)
2632                 opt_border = 2;
2633
2634         if (cont->opt->start_table)
2635         {
2636                 /* print title */
2637                 if (!opt_tuples_only && cont->title)
2638                 {
2639                         fputs("\\begin{center}\n", fout);
2640                         latex_escaped_print(cont->title, fout);
2641                         fputs("\n\\end{center}\n\n", fout);
2642                 }
2643
2644                 /* begin environment and set alignments and borders */
2645                 fputs("\\begin{tabular}{", fout);
2646                 if (opt_border == 0)
2647                         fputs("cl", fout);
2648                 else if (opt_border == 1)
2649                         fputs("c|l", fout);
2650                 else if (opt_border == 2)
2651                         fputs("|c|l|", fout);
2652                 fputs("}\n", fout);
2653         }
2654
2655         /* print records */
2656         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2657         {
2658                 /* new record */
2659                 if (i % cont->ncolumns == 0)
2660                 {
2661                         if (cancel_pressed)
2662                                 break;
2663                         if (!opt_tuples_only)
2664                         {
2665                                 if (opt_border == 2)
2666                                 {
2667                                         fputs("\\hline\n", fout);
2668                                         fprintf(fout, "\\multicolumn{2}{|c|}{\\textit{Record %lu}} \\\\\n", record++);
2669                                 }
2670                                 else
2671                                         fprintf(fout, "\\multicolumn{2}{c}{\\textit{Record %lu}} \\\\\n", record++);
2672                         }
2673                         if (opt_border >= 1)
2674                                 fputs("\\hline\n", fout);
2675                 }
2676
2677                 latex_escaped_print(cont->headers[i % cont->ncolumns], fout);
2678                 fputs(" & ", fout);
2679                 latex_escaped_print(*ptr, fout);
2680                 fputs(" \\\\\n", fout);
2681         }
2682
2683         if (cont->opt->stop_table)
2684         {
2685                 if (opt_border == 2)
2686                         fputs("\\hline\n", fout);
2687
2688                 fputs("\\end{tabular}\n\n\\noindent ", fout);
2689
2690                 /* print footers */
2691                 if (cont->footers && !opt_tuples_only && !cancel_pressed)
2692                 {
2693                         printTableFooter *f;
2694
2695                         for (f = cont->footers; f; f = f->next)
2696                         {
2697                                 latex_escaped_print(f->data, fout);
2698                                 fputs(" \\\\\n", fout);
2699                         }
2700                 }
2701
2702                 fputc('\n', fout);
2703         }
2704 }
2705
2706
2707 /*************************/
2708 /* Troff -ms                     */
2709 /*************************/
2710
2711
2712 static void
2713 troff_ms_escaped_print(const char *in, FILE *fout)
2714 {
2715         const char *p;
2716
2717         for (p = in; *p; p++)
2718                 switch (*p)
2719                 {
2720                         case '\\':
2721                                 fputs("\\(rs", fout);
2722                                 break;
2723                         default:
2724                                 fputc(*p, fout);
2725                 }
2726 }
2727
2728
2729 static void
2730 print_troff_ms_text(const printTableContent *cont, FILE *fout)
2731 {
2732         bool            opt_tuples_only = cont->opt->tuples_only;
2733         unsigned short opt_border = cont->opt->border;
2734         unsigned int i;
2735         const char *const *ptr;
2736
2737         if (cancel_pressed)
2738                 return;
2739
2740         if (opt_border > 2)
2741                 opt_border = 2;
2742
2743         if (cont->opt->start_table)
2744         {
2745                 /* print title */
2746                 if (!opt_tuples_only && cont->title)
2747                 {
2748                         fputs(".LP\n.DS C\n", fout);
2749                         troff_ms_escaped_print(cont->title, fout);
2750                         fputs("\n.DE\n", fout);
2751                 }
2752
2753                 /* begin environment and set alignments and borders */
2754                 fputs(".LP\n.TS\n", fout);
2755                 if (opt_border == 2)
2756                         fputs("center box;\n", fout);
2757                 else
2758                         fputs("center;\n", fout);
2759
2760                 for (i = 0; i < cont->ncolumns; i++)
2761                 {
2762                         fputc(*(cont->aligns + i), fout);
2763                         if (opt_border > 0 && i < cont->ncolumns - 1)
2764                                 fputs(" | ", fout);
2765                 }
2766                 fputs(".\n", fout);
2767
2768                 /* print headers */
2769                 if (!opt_tuples_only)
2770                 {
2771                         for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++)
2772                         {
2773                                 if (i != 0)
2774                                         fputc('\t', fout);
2775                                 fputs("\\fI", fout);
2776                                 troff_ms_escaped_print(*ptr, fout);
2777                                 fputs("\\fP", fout);
2778                         }
2779                         fputs("\n_\n", fout);
2780                 }
2781         }
2782
2783         /* print cells */
2784         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2785         {
2786                 troff_ms_escaped_print(*ptr, fout);
2787
2788                 if ((i + 1) % cont->ncolumns == 0)
2789                 {
2790                         fputc('\n', fout);
2791                         if (cancel_pressed)
2792                                 break;
2793                 }
2794                 else
2795                         fputc('\t', fout);
2796         }
2797
2798         if (cont->opt->stop_table)
2799         {
2800                 printTableFooter *footers = footers_with_default(cont);
2801
2802                 fputs(".TE\n.DS L\n", fout);
2803
2804                 /* print footers */
2805                 if (footers && !opt_tuples_only && !cancel_pressed)
2806                 {
2807                         printTableFooter *f;
2808
2809                         for (f = footers; f; f = f->next)
2810                         {
2811                                 troff_ms_escaped_print(f->data, fout);
2812                                 fputc('\n', fout);
2813                         }
2814                 }
2815
2816                 fputs(".DE\n", fout);
2817         }
2818 }
2819
2820
2821 static void
2822 print_troff_ms_vertical(const printTableContent *cont, FILE *fout)
2823 {
2824         bool            opt_tuples_only = cont->opt->tuples_only;
2825         unsigned short opt_border = cont->opt->border;
2826         unsigned long record = cont->opt->prior_records + 1;
2827         unsigned int i;
2828         const char *const *ptr;
2829         unsigned short current_format = 0;      /* 0=none, 1=header, 2=body */
2830
2831         if (cancel_pressed)
2832                 return;
2833
2834         if (opt_border > 2)
2835                 opt_border = 2;
2836
2837         if (cont->opt->start_table)
2838         {
2839                 /* print title */
2840                 if (!opt_tuples_only && cont->title)
2841                 {
2842                         fputs(".LP\n.DS C\n", fout);
2843                         troff_ms_escaped_print(cont->title, fout);
2844                         fputs("\n.DE\n", fout);
2845                 }
2846
2847                 /* begin environment and set alignments and borders */
2848                 fputs(".LP\n.TS\n", fout);
2849                 if (opt_border == 2)
2850                         fputs("center box;\n", fout);
2851                 else
2852                         fputs("center;\n", fout);
2853
2854                 /* basic format */
2855                 if (opt_tuples_only)
2856                         fputs("c l;\n", fout);
2857         }
2858         else
2859                 current_format = 2;             /* assume tuples printed already */
2860
2861         /* print records */
2862         for (i = 0, ptr = cont->cells; *ptr; i++, ptr++)
2863         {
2864                 /* new record */
2865                 if (i % cont->ncolumns == 0)
2866                 {
2867                         if (cancel_pressed)
2868                                 break;
2869                         if (!opt_tuples_only)
2870                         {
2871                                 if (current_format != 1)
2872                                 {
2873                                         if (opt_border == 2 && record > 1)
2874                                                 fputs("_\n", fout);
2875                                         if (current_format != 0)
2876                                                 fputs(".T&\n", fout);
2877                                         fputs("c s.\n", fout);
2878                                         current_format = 1;
2879                                 }
2880                                 fprintf(fout, "\\fIRecord %lu\\fP\n", record++);
2881                         }
2882                         if (opt_border >= 1)
2883                                 fputs("_\n", fout);
2884                 }
2885
2886                 if (!opt_tuples_only)
2887                 {
2888                         if (current_format != 2)
2889                         {
2890                                 if (current_format != 0)
2891                                         fputs(".T&\n", fout);
2892                                 if (opt_border != 1)
2893                                         fputs("c l.\n", fout);
2894                                 else
2895                                         fputs("c | l.\n", fout);
2896                                 current_format = 2;
2897                         }
2898                 }
2899
2900                 troff_ms_escaped_print(cont->headers[i % cont->ncolumns], fout);
2901                 fputc('\t', fout);
2902                 troff_ms_escaped_print(*ptr, fout);
2903
2904                 fputc('\n', fout);
2905         }
2906
2907         if (cont->opt->stop_table)
2908         {
2909                 fputs(".TE\n.DS L\n", fout);
2910
2911                 /* print footers */
2912                 if (cont->footers && !opt_tuples_only && !cancel_pressed)
2913                 {
2914                         printTableFooter *f;
2915
2916                         for (f = cont->footers; f; f = f->next)
2917                         {
2918                                 troff_ms_escaped_print(f->data, fout);
2919                                 fputc('\n', fout);
2920                         }
2921                 }
2922
2923                 fputs(".DE\n", fout);
2924         }
2925 }
2926
2927
2928 /********************************/
2929 /* Public functions                             */
2930 /********************************/
2931
2932
2933 /*
2934  * disable_sigpipe_trap
2935  *
2936  * Turn off SIGPIPE interrupt --- call this before writing to a temporary
2937  * query output file that is a pipe.
2938  *
2939  * No-op on Windows, where there's no SIGPIPE interrupts.
2940  */
2941 void
2942 disable_sigpipe_trap(void)
2943 {
2944 #ifndef WIN32
2945         pqsignal(SIGPIPE, SIG_IGN);
2946 #endif
2947 }
2948
2949 /*
2950  * restore_sigpipe_trap
2951  *
2952  * Restore normal SIGPIPE interrupt --- call this when done writing to a
2953  * temporary query output file that was (or might have been) a pipe.
2954  *
2955  * Note: within psql, we enable SIGPIPE interrupts unless the permanent query
2956  * output file is a pipe, in which case they should be kept off.  This
2957  * approach works only because psql is not currently complicated enough to
2958  * have nested usages of short-lived output files.  Otherwise we'd probably
2959  * need a genuine save-and-restore-state approach; but for now, that would be
2960  * useless complication.  In non-psql programs, this always enables SIGPIPE.
2961  *
2962  * No-op on Windows, where there's no SIGPIPE interrupts.
2963  */
2964 void
2965 restore_sigpipe_trap(void)
2966 {
2967 #ifndef WIN32
2968         pqsignal(SIGPIPE, always_ignore_sigpipe ? SIG_IGN : SIG_DFL);
2969 #endif
2970 }
2971
2972 /*
2973  * set_sigpipe_trap_state
2974  *
2975  * Set the trap state that restore_sigpipe_trap should restore to.
2976  */
2977 void
2978 set_sigpipe_trap_state(bool ignore)
2979 {
2980         always_ignore_sigpipe = ignore;
2981 }
2982
2983
2984 /*
2985  * PageOutput
2986  *
2987  * Tests if pager is needed and returns appropriate FILE pointer.
2988  *
2989  * If the topt argument is NULL no pager is used.
2990  */
2991 FILE *
2992 PageOutput(int lines, const printTableOpt *topt)
2993 {
2994         /* check whether we need / can / are supposed to use pager */
2995         if (topt && topt->pager && isatty(fileno(stdin)) && isatty(fileno(stdout)))
2996         {
2997 #ifdef TIOCGWINSZ
2998                 unsigned short int pager = topt->pager;
2999                 int                     min_lines = topt->pager_min_lines;
3000                 int                     result;
3001                 struct winsize screen_size;
3002
3003                 result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size);
3004
3005                 /* >= accounts for a one-line prompt */
3006                 if (result == -1
3007                         || (lines >= screen_size.ws_row && lines >= min_lines)
3008                         || pager > 1)
3009 #endif
3010                 {
3011                         const char *pagerprog;
3012                         FILE       *pagerpipe;
3013
3014                         pagerprog = getenv("PSQL_PAGER");
3015                         if (!pagerprog)
3016                                 pagerprog = getenv("PAGER");
3017                         if (!pagerprog)
3018                                 pagerprog = DEFAULT_PAGER;
3019                         else
3020                         {
3021                                 /* if PAGER is empty or all-white-space, don't use pager */
3022                                 if (strspn(pagerprog, " \t\r\n") == strlen(pagerprog))
3023                                         return stdout;
3024                         }
3025                         disable_sigpipe_trap();
3026                         pagerpipe = popen(pagerprog, "w");
3027                         if (pagerpipe)
3028                                 return pagerpipe;
3029                         /* if popen fails, silently proceed without pager */
3030                         restore_sigpipe_trap();
3031                 }
3032         }
3033
3034         return stdout;
3035 }
3036
3037 /*
3038  * ClosePager
3039  *
3040  * Close previously opened pager pipe, if any
3041  */
3042 void
3043 ClosePager(FILE *pagerpipe)
3044 {
3045         if (pagerpipe && pagerpipe != stdout)
3046         {
3047                 /*
3048                  * If printing was canceled midstream, warn about it.
3049                  *
3050                  * Some pagers like less use Ctrl-C as part of their command set. Even
3051                  * so, we abort our processing and warn the user what we did.  If the
3052                  * pager quit as a result of the SIGINT, this message won't go
3053                  * anywhere ...
3054                  */
3055                 if (cancel_pressed)
3056                         fprintf(pagerpipe, _("Interrupted\n"));
3057
3058                 pclose(pagerpipe);
3059                 restore_sigpipe_trap();
3060         }
3061 }
3062
3063 /*
3064  * Initialise a table contents struct.
3065  *              Must be called before any other printTable method is used.
3066  *
3067  * The title is not duplicated; the caller must ensure that the buffer
3068  * is available for the lifetime of the printTableContent struct.
3069  *
3070  * If you call this, you must call printTableCleanup once you're done with the
3071  * table.
3072  */
3073 void
3074 printTableInit(printTableContent *const content, const printTableOpt *opt,
3075                            const char *title, const int ncolumns, const int nrows)
3076 {
3077         content->opt = opt;
3078         content->title = title;
3079         content->ncolumns = ncolumns;
3080         content->nrows = nrows;
3081
3082         content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers));
3083
3084         content->cells = pg_malloc0((ncolumns * nrows + 1) * sizeof(*content->cells));
3085
3086         content->cellmustfree = NULL;
3087         content->footers = NULL;
3088
3089         content->aligns = pg_malloc0((ncolumns + 1) * sizeof(*content->align));
3090
3091         content->header = content->headers;
3092         content->cell = content->cells;
3093         content->footer = content->footers;
3094         content->align = content->aligns;
3095         content->cellsadded = 0;
3096 }
3097
3098 /*
3099  * Add a header to the table.
3100  *
3101  * Headers are not duplicated; you must ensure that the header string is
3102  * available for the lifetime of the printTableContent struct.
3103  *
3104  * If translate is true, the function will pass the header through gettext.
3105  * Otherwise, the header will not be translated.
3106  *
3107  * align is either 'l' or 'r', and specifies the alignment for cells in this
3108  * column.
3109  */
3110 void
3111 printTableAddHeader(printTableContent *const content, char *header,
3112                                         const bool translate, const char align)
3113 {
3114 #ifndef ENABLE_NLS
3115         (void) translate;                       /* unused parameter */
3116 #endif
3117
3118         if (content->header >= content->headers + content->ncolumns)
3119         {
3120                 fprintf(stderr, _("Cannot add header to table content: "
3121                                                   "column count of %d exceeded.\n"),
3122                                 content->ncolumns);
3123                 exit(EXIT_FAILURE);
3124         }
3125
3126         *content->header = (char *) mbvalidate((unsigned char *) header,
3127                                                                                    content->opt->encoding);
3128 #ifdef ENABLE_NLS
3129         if (translate)
3130                 *content->header = _(*content->header);
3131 #endif
3132         content->header++;
3133
3134         *content->align = align;
3135         content->align++;
3136 }
3137
3138 /*
3139  * Add a cell to the table.
3140  *
3141  * Cells are not duplicated; you must ensure that the cell string is available
3142  * for the lifetime of the printTableContent struct.
3143  *
3144  * If translate is true, the function will pass the cell through gettext.
3145  * Otherwise, the cell will not be translated.
3146  *
3147  * If mustfree is true, the cell string is freed by printTableCleanup().
3148  * Note: Automatic freeing of translatable strings is not supported.
3149  */
3150 void
3151 printTableAddCell(printTableContent *const content, char *cell,
3152                                   const bool translate, const bool mustfree)
3153 {
3154 #ifndef ENABLE_NLS
3155         (void) translate;                       /* unused parameter */
3156 #endif
3157
3158         if (content->cellsadded >= content->ncolumns * content->nrows)
3159         {
3160                 fprintf(stderr, _("Cannot add cell to table content: "
3161                                                   "total cell count of %d exceeded.\n"),
3162                                 content->ncolumns * content->nrows);
3163                 exit(EXIT_FAILURE);
3164         }
3165
3166         *content->cell = (char *) mbvalidate((unsigned char *) cell,
3167                                                                                  content->opt->encoding);
3168
3169 #ifdef ENABLE_NLS
3170         if (translate)
3171                 *content->cell = _(*content->cell);
3172 #endif
3173
3174         if (mustfree)
3175         {
3176                 if (content->cellmustfree == NULL)
3177                         content->cellmustfree =
3178                                 pg_malloc0((content->ncolumns * content->nrows + 1) * sizeof(bool));
3179
3180                 content->cellmustfree[content->cellsadded] = true;
3181         }
3182         content->cell++;
3183         content->cellsadded++;
3184 }
3185
3186 /*
3187  * Add a footer to the table.
3188  *
3189  * Footers are added as elements of a singly-linked list, and the content is
3190  * strdup'd, so there is no need to keep the original footer string around.
3191  *
3192  * Footers are never translated by the function.  If you want the footer
3193  * translated you must do so yourself, before calling printTableAddFooter.  The
3194  * reason this works differently to headers and cells is that footers tend to
3195  * be made of up individually translated components, rather than being
3196  * translated as a whole.
3197  */
3198 void
3199 printTableAddFooter(printTableContent *const content, const char *footer)
3200 {
3201         printTableFooter *f;
3202
3203         f = pg_malloc0(sizeof(*f));
3204         f->data = pg_strdup(footer);
3205
3206         if (content->footers == NULL)
3207                 content->footers = f;
3208         else
3209                 content->footer->next = f;
3210
3211         content->footer = f;
3212 }
3213
3214 /*
3215  * Change the content of the last-added footer.
3216  *
3217  * The current contents of the last-added footer are freed, and replaced by the
3218  * content given in *footer.  If there was no previous footer, add a new one.
3219  *
3220  * The content is strdup'd, so there is no need to keep the original string
3221  * around.
3222  */
3223 void
3224 printTableSetFooter(printTableContent *const content, const char *footer)
3225 {
3226         if (content->footers != NULL)
3227         {
3228                 free(content->footer->data);
3229                 content->footer->data = pg_strdup(footer);
3230         }
3231         else
3232                 printTableAddFooter(content, footer);
3233 }
3234
3235 /*
3236  * Free all memory allocated to this struct.
3237  *
3238  * Once this has been called, the struct is unusable unless you pass it to
3239  * printTableInit() again.
3240  */
3241 void
3242 printTableCleanup(printTableContent *const content)
3243 {
3244         if (content->cellmustfree)
3245         {
3246                 int                     i;
3247
3248                 for (i = 0; i < content->nrows * content->ncolumns; i++)
3249                 {
3250                         if (content->cellmustfree[i])
3251                                 free(unconstify(char *, content->cells[i]));
3252                 }
3253                 free(content->cellmustfree);
3254                 content->cellmustfree = NULL;
3255         }
3256         free(content->headers);
3257         free(content->cells);
3258         free(content->aligns);
3259
3260         content->opt = NULL;
3261         content->title = NULL;
3262         content->headers = NULL;
3263         content->cells = NULL;
3264         content->aligns = NULL;
3265         content->header = NULL;
3266         content->cell = NULL;
3267         content->align = NULL;
3268
3269         if (content->footers)
3270         {
3271                 for (content->footer = content->footers; content->footer;)
3272                 {
3273                         printTableFooter *f;
3274
3275                         f = content->footer;
3276                         content->footer = f->next;
3277                         free(f->data);
3278                         free(f);
3279                 }
3280         }
3281         content->footers = NULL;
3282         content->footer = NULL;
3283 }
3284
3285 /*
3286  * IsPagerNeeded
3287  *
3288  * Setup pager if required
3289  */
3290 static void
3291 IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded,
3292                           FILE **fout, bool *is_pager)
3293 {
3294         if (*fout == stdout)
3295         {
3296                 int                     lines;
3297
3298                 if (expanded)
3299                         lines = (cont->ncolumns + 1) * cont->nrows;
3300                 else
3301                         lines = cont->nrows + 1;
3302
3303                 if (!cont->opt->tuples_only)
3304                 {
3305                         printTableFooter *f;
3306
3307                         /*
3308                          * FIXME -- this is slightly bogus: it counts the number of
3309                          * footers, not the number of lines in them.
3310                          */
3311                         for (f = cont->footers; f; f = f->next)
3312                                 lines++;
3313                 }
3314
3315                 *fout = PageOutput(lines + extra_lines, cont->opt);
3316                 *is_pager = (*fout != stdout);
3317         }
3318         else
3319                 *is_pager = false;
3320 }
3321
3322 /*
3323  * Use this to print any table in the supported formats.
3324  *
3325  * cont: table data and formatting options
3326  * fout: where to print to
3327  * is_pager: true if caller has already redirected fout to be a pager pipe
3328  * flog: if not null, also print the table there (for --log-file option)
3329  */
3330 void
3331 printTable(const printTableContent *cont,
3332                    FILE *fout, bool is_pager, FILE *flog)
3333 {
3334         bool            is_local_pager = false;
3335
3336         if (cancel_pressed)
3337                 return;
3338
3339         if (cont->opt->format == PRINT_NOTHING)
3340                 return;
3341
3342         /* print_aligned_*() handle the pager themselves */
3343         if (!is_pager &&
3344                 cont->opt->format != PRINT_ALIGNED &&
3345                 cont->opt->format != PRINT_WRAPPED)
3346         {
3347                 IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager);
3348                 is_local_pager = is_pager;
3349         }
3350
3351         /* print the stuff */
3352
3353         if (flog)
3354                 print_aligned_text(cont, flog, false);
3355
3356         switch (cont->opt->format)
3357         {
3358                 case PRINT_UNALIGNED:
3359                         if (cont->opt->expanded == 1)
3360                                 print_unaligned_vertical(cont, fout);
3361                         else
3362                                 print_unaligned_text(cont, fout);
3363                         break;
3364                 case PRINT_ALIGNED:
3365                 case PRINT_WRAPPED:
3366
3367                         /*
3368                          * In expanded-auto mode, force vertical if a pager is passed in;
3369                          * else we may make different decisions for different hunks of the
3370                          * query result.
3371                          */
3372                         if (cont->opt->expanded == 1 ||
3373                                 (cont->opt->expanded == 2 && is_pager))
3374                                 print_aligned_vertical(cont, fout, is_pager);
3375                         else
3376                                 print_aligned_text(cont, fout, is_pager);
3377                         break;
3378                 case PRINT_CSV:
3379                         if (cont->opt->expanded == 1)
3380                                 print_csv_vertical(cont, fout);
3381                         else
3382                                 print_csv_text(cont, fout);
3383                         break;
3384                 case PRINT_HTML:
3385                         if (cont->opt->expanded == 1)
3386                                 print_html_vertical(cont, fout);
3387                         else
3388                                 print_html_text(cont, fout);
3389                         break;
3390                 case PRINT_ASCIIDOC:
3391                         if (cont->opt->expanded == 1)
3392                                 print_asciidoc_vertical(cont, fout);
3393                         else
3394                                 print_asciidoc_text(cont, fout);
3395                         break;
3396                 case PRINT_LATEX:
3397                         if (cont->opt->expanded == 1)
3398                                 print_latex_vertical(cont, fout);
3399                         else
3400                                 print_latex_text(cont, fout);
3401                         break;
3402                 case PRINT_LATEX_LONGTABLE:
3403                         if (cont->opt->expanded == 1)
3404                                 print_latex_vertical(cont, fout);
3405                         else
3406                                 print_latex_longtable_text(cont, fout);
3407                         break;
3408                 case PRINT_TROFF_MS:
3409                         if (cont->opt->expanded == 1)
3410                                 print_troff_ms_vertical(cont, fout);
3411                         else
3412                                 print_troff_ms_text(cont, fout);
3413                         break;
3414                 default:
3415                         fprintf(stderr, _("invalid output format (internal error): %d"),
3416                                         cont->opt->format);
3417                         exit(EXIT_FAILURE);
3418         }
3419
3420         if (is_local_pager)
3421                 ClosePager(fout);
3422 }
3423
3424 /*
3425  * Use this to print query results
3426  *
3427  * result: result of a successful query
3428  * opt: formatting options
3429  * fout: where to print to
3430  * is_pager: true if caller has already redirected fout to be a pager pipe
3431  * flog: if not null, also print the data there (for --log-file option)
3432  */
3433 void
3434 printQuery(const PGresult *result, const printQueryOpt *opt,
3435                    FILE *fout, bool is_pager, FILE *flog)
3436 {
3437         printTableContent cont;
3438         int                     i,
3439                                 r,
3440                                 c;
3441
3442         if (cancel_pressed)
3443                 return;
3444
3445         printTableInit(&cont, &opt->topt, opt->title,
3446                                    PQnfields(result), PQntuples(result));
3447
3448         /* Assert caller supplied enough translate_columns[] entries */
3449         Assert(opt->translate_columns == NULL ||
3450                    opt->n_translate_columns >= cont.ncolumns);
3451
3452         for (i = 0; i < cont.ncolumns; i++)
3453         {
3454                 printTableAddHeader(&cont, PQfname(result, i),
3455                                                         opt->translate_header,
3456                                                         column_type_alignment(PQftype(result, i)));
3457         }
3458
3459         /* set cells */
3460         for (r = 0; r < cont.nrows; r++)
3461         {
3462                 for (c = 0; c < cont.ncolumns; c++)
3463                 {
3464                         char       *cell;
3465                         bool            mustfree = false;
3466                         bool            translate;
3467
3468                         if (PQgetisnull(result, r, c))
3469                                 cell = opt->nullPrint ? opt->nullPrint : "";
3470                         else
3471                         {
3472                                 cell = PQgetvalue(result, r, c);
3473                                 if (cont.aligns[c] == 'r' && opt->topt.numericLocale)
3474                                 {
3475                                         cell = format_numeric_locale(cell);
3476                                         mustfree = true;
3477                                 }
3478                         }
3479
3480                         translate = (opt->translate_columns && opt->translate_columns[c]);
3481                         printTableAddCell(&cont, cell, translate, mustfree);
3482                 }
3483         }
3484
3485         /* set footers */
3486         if (opt->footers)
3487         {
3488                 char      **footer;
3489
3490                 for (footer = opt->footers; *footer; footer++)
3491                         printTableAddFooter(&cont, *footer);
3492         }
3493
3494         printTable(&cont, fout, is_pager, flog);
3495         printTableCleanup(&cont);
3496 }
3497
3498 char
3499 column_type_alignment(Oid ftype)
3500 {
3501         char            align;
3502
3503         switch (ftype)
3504         {
3505                 case INT2OID:
3506                 case INT4OID:
3507                 case INT8OID:
3508                 case FLOAT4OID:
3509                 case FLOAT8OID:
3510                 case NUMERICOID:
3511                 case OIDOID:
3512                 case XIDOID:
3513                 case CIDOID:
3514                 case CASHOID:
3515                         align = 'r';
3516                         break;
3517                 default:
3518                         align = 'l';
3519                         break;
3520         }
3521         return align;
3522 }
3523
3524 void
3525 setDecimalLocale(void)
3526 {
3527         struct lconv *extlconv;
3528
3529         extlconv = localeconv();
3530
3531         /* Don't accept an empty decimal_point string */
3532         if (*extlconv->decimal_point)
3533                 decimal_point = pg_strdup(extlconv->decimal_point);
3534         else
3535                 decimal_point = ".";    /* SQL output standard */
3536
3537         /*
3538          * Although the Open Group standard allows locales to supply more than one
3539          * group width, we consider only the first one, and we ignore any attempt
3540          * to suppress grouping by specifying CHAR_MAX.  As in the backend's
3541          * cash.c, we must apply a range check to avoid being fooled by variant
3542          * CHAR_MAX values.
3543          */
3544         groupdigits = *extlconv->grouping;
3545         if (groupdigits <= 0 || groupdigits > 6)
3546                 groupdigits = 3;                /* most common */
3547
3548         /* Don't accept an empty thousands_sep string, either */
3549         /* similar code exists in formatting.c */
3550         if (*extlconv->thousands_sep)
3551                 thousands_sep = pg_strdup(extlconv->thousands_sep);
3552         /* Make sure thousands separator doesn't match decimal point symbol. */
3553         else if (strcmp(decimal_point, ",") != 0)
3554                 thousands_sep = ",";
3555         else
3556                 thousands_sep = ".";
3557 }
3558
3559 /* get selected or default line style */
3560 const printTextFormat *
3561 get_line_style(const printTableOpt *opt)
3562 {
3563         /*
3564          * Note: this function mainly exists to preserve the convention that a
3565          * printTableOpt struct can be initialized to zeroes to get default
3566          * behavior.
3567          */
3568         if (opt->line_style != NULL)
3569                 return opt->line_style;
3570         else
3571                 return &pg_asciiformat;
3572 }
3573
3574 void
3575 refresh_utf8format(const printTableOpt *opt)
3576 {
3577         printTextFormat *popt = &pg_utf8format;
3578
3579         const unicodeStyleBorderFormat *border;
3580         const unicodeStyleRowFormat *header;
3581         const unicodeStyleColumnFormat *column;
3582
3583         popt->name = "unicode";
3584
3585         border = &unicode_style.border_style[opt->unicode_border_linestyle];
3586         header = &unicode_style.row_style[opt->unicode_header_linestyle];
3587         column = &unicode_style.column_style[opt->unicode_column_linestyle];
3588
3589         popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal;
3590         popt->lrule[PRINT_RULE_TOP].leftvrule = border->down_and_right;
3591         popt->lrule[PRINT_RULE_TOP].midvrule = column->down_and_horizontal[opt->unicode_border_linestyle];
3592         popt->lrule[PRINT_RULE_TOP].rightvrule = border->down_and_left;
3593
3594         popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal;
3595         popt->lrule[PRINT_RULE_MIDDLE].leftvrule = header->vertical_and_right[opt->unicode_border_linestyle];
3596         popt->lrule[PRINT_RULE_MIDDLE].midvrule = column->vertical_and_horizontal[opt->unicode_header_linestyle];
3597         popt->lrule[PRINT_RULE_MIDDLE].rightvrule = header->vertical_and_left[opt->unicode_border_linestyle];
3598
3599         popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal;
3600         popt->lrule[PRINT_RULE_BOTTOM].leftvrule = border->up_and_right;
3601         popt->lrule[PRINT_RULE_BOTTOM].midvrule = column->up_and_horizontal[opt->unicode_border_linestyle];
3602         popt->lrule[PRINT_RULE_BOTTOM].rightvrule = border->left_and_right;
3603
3604         /* N/A */
3605         popt->lrule[PRINT_RULE_DATA].hrule = "";
3606         popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical;
3607         popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical;
3608         popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical;
3609
3610         popt->midvrule_nl = column->vertical;
3611         popt->midvrule_wrap = column->vertical;
3612         popt->midvrule_blank = column->vertical;
3613
3614         /* Same for all unicode today */
3615         popt->header_nl_left = unicode_style.header_nl_left;
3616         popt->header_nl_right = unicode_style.header_nl_right;
3617         popt->nl_left = unicode_style.nl_left;
3618         popt->nl_right = unicode_style.nl_right;
3619         popt->wrap_left = unicode_style.wrap_left;
3620         popt->wrap_right = unicode_style.wrap_right;
3621         popt->wrap_right_border = unicode_style.wrap_right_border;
3622
3623         return;
3624 }
3625
3626 /*
3627  * Compute the byte distance to the end of the string or *target_width
3628  * display character positions, whichever comes first.  Update *target_width
3629  * to be the number of display character positions actually filled.
3630  */
3631 static int
3632 strlen_max_width(unsigned char *str, int *target_width, int encoding)
3633 {
3634         unsigned char *start = str;
3635         unsigned char *end = str + strlen((char *) str);
3636         int                     curr_width = 0;
3637
3638         while (str < end)
3639         {
3640                 int                     char_width = PQdsplen((char *) str, encoding);
3641
3642                 /*
3643                  * If the display width of the new character causes the string to
3644                  * exceed its target width, skip it and return.  However, if this is
3645                  * the first character of the string (curr_width == 0), we have to
3646                  * accept it.
3647                  */
3648                 if (*target_width < curr_width + char_width && curr_width != 0)
3649                         break;
3650
3651                 curr_width += char_width;
3652
3653                 str += PQmblen((char *) str, encoding);
3654         }
3655
3656         *target_width = curr_width;
3657
3658         return str - start;
3659 }