3
3
*
4
4
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
5
5
*
6
- * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.98 2008/05/08 17:04:26 momjian Exp $
6
+ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.99 2008/05/10 03:31:58 tgl Exp $
7
7
*/
8
8
#include "postgres_fe.h"
9
9
28
28
29
29
#include "mbprint.h"
30
30
31
- static int strlen_max_width (unsigned char * str , int * target_width , int encoding );
32
-
33
31
/*
34
32
* We define the cancel_pressed flag in this file, rather than common.c where
35
33
* it naturally belongs, because this file is also used by non-psql programs
@@ -45,6 +43,9 @@ static char *decimal_point;
45
43
static char * grouping ;
46
44
static char * thousands_sep ;
47
45
46
+ /* Local functions */
47
+ static int strlen_max_width (unsigned char * str , int * target_width , int encoding );
48
+
48
49
49
50
static void *
50
51
pg_local_malloc (size_t size )
@@ -400,7 +401,7 @@ _print_horizontal_line(const unsigned int col_count, const unsigned int *widths,
400
401
401
402
402
403
/*
403
- * Prety pretty boxes around cells.
404
+ * Print pretty boxes around cells.
404
405
*/
405
406
static void
406
407
print_aligned_text (const char * title , const char * const * headers ,
@@ -411,7 +412,7 @@ print_aligned_text(const char *title, const char *const * headers,
411
412
bool opt_tuples_only = opt -> tuples_only ;
412
413
bool opt_numeric_locale = opt -> numericLocale ;
413
414
int encoding = opt -> encoding ;
414
- unsigned short int opt_border = opt -> border ;
415
+ unsigned short opt_border = opt -> border ;
415
416
416
417
unsigned int col_count = 0 , cell_count = 0 ;
417
418
@@ -483,7 +484,8 @@ print_aligned_text(const char *title, const char *const * headers,
483
484
nl_lines ,
484
485
bytes_required ;
485
486
486
- pg_wcssize ((unsigned char * ) headers [i ], strlen (headers [i ]), encoding , & width , & nl_lines , & bytes_required );
487
+ pg_wcssize ((unsigned char * ) headers [i ], strlen (headers [i ]), encoding ,
488
+ & width , & nl_lines , & bytes_required );
487
489
if (width > max_width [i ])
488
490
max_width [i ] = width ;
489
491
if (nl_lines > max_nl_lines [i ])
@@ -502,7 +504,8 @@ print_aligned_text(const char *title, const char *const * headers,
502
504
bytes_required ;
503
505
504
506
/* Get width, ignore nl_lines */
505
- pg_wcssize ((unsigned char * ) * ptr , strlen (* ptr ), encoding , & width , & nl_lines , & bytes_required );
507
+ pg_wcssize ((unsigned char * ) * ptr , strlen (* ptr ), encoding ,
508
+ & width , & nl_lines , & bytes_required );
506
509
if (opt_numeric_locale && opt_align [i % col_count ] == 'r' )
507
510
{
508
511
width += additional_numeric_locale_len (* ptr );
@@ -567,12 +570,14 @@ print_aligned_text(const char *title, const char *const * headers,
567
570
568
571
if (opt -> format == PRINT_WRAPPED )
569
572
{
570
- /* Get terminal width */
573
+ /*
574
+ * Choose target output width: \pset columns, or $COLUMNS, or ioctl
575
+ */
571
576
if (opt -> columns > 0 )
572
577
output_columns = opt -> columns ;
573
578
else if ((fout == stdout && isatty (fileno (stdout ))) || is_pager )
574
579
{
575
- if (opt -> env_columns )
580
+ if (opt -> env_columns > 0 )
576
581
output_columns = opt -> env_columns ;
577
582
#ifdef TIOCGWINSZ
578
583
else
@@ -586,11 +591,11 @@ print_aligned_text(const char *title, const char *const * headers,
586
591
}
587
592
588
593
/*
589
- * Optional optimized word wrap. Shrink columns with a high max/avg ratio.
590
- * Slighly bias against wider columns. (Increases chance a narrow column
591
- * will fit in its cell.)
592
- * If available columns is positive...
593
- * and greater than the width of the unshrinkable column headers
594
+ * Optional optimized word wrap. Shrink columns with a high max/avg
595
+ * ratio. Slighly bias against wider columns. (Increases chance a
596
+ * narrow column will fit in its cell.) If available columns is
597
+ * positive... and greater than the width of the unshrinkable column
598
+ * headers
594
599
*/
595
600
if (output_columns > 0 && output_columns >= total_header_width )
596
601
{
@@ -610,10 +615,11 @@ print_aligned_text(const char *title, const char *const * headers,
610
615
{
611
616
if (width_average [i ] && width_wrap [i ] > width_header [i ])
612
617
{
613
- /* Penalize wide columns by +1% of their width (0.01) */
614
- double ratio = (double )width_wrap [i ] / width_average [i ] +
615
- max_width [i ] * 0.01 ;
618
+ /* Penalize wide columns by 1% of their width */
619
+ double ratio ;
616
620
621
+ ratio = (double ) width_wrap [i ] / width_average [i ] +
622
+ max_width [i ] * 0.01 ;
617
623
if (ratio > max_ratio )
618
624
{
619
625
max_ratio = ratio ;
@@ -641,7 +647,8 @@ print_aligned_text(const char *title, const char *const * headers,
641
647
{
642
648
int width , height ;
643
649
644
- pg_wcssize ((unsigned char * ) title , strlen (title ), encoding , & width , & height , NULL );
650
+ pg_wcssize ((unsigned char * ) title , strlen (title ), encoding ,
651
+ & width , & height , NULL );
645
652
if (width >= width_total )
646
653
fprintf (fout , "%s\n" , title ); /* Aligned */
647
654
else
@@ -723,21 +730,22 @@ print_aligned_text(const char *title, const char *const * headers,
723
730
break ;
724
731
725
732
/*
726
- * Format each cell. Format again, it is a numeric formatting locale
733
+ * Format each cell. Format again, if it's a numeric formatting locale
727
734
* (e.g. 123,456 vs. 123456)
728
735
*/
729
736
for (j = 0 ; j < col_count ; j ++ )
730
737
{
731
- pg_wcsformat ((unsigned char * ) ptr [j ], strlen (ptr [j ]), encoding , col_lineptrs [j ], max_nl_lines [j ]);
738
+ pg_wcsformat ((unsigned char * ) ptr [j ], strlen (ptr [j ]), encoding ,
739
+ col_lineptrs [j ], max_nl_lines [j ]);
732
740
curr_nl_line [j ] = 0 ;
733
741
734
742
if (opt_numeric_locale && opt_align [j % col_count ] == 'r' )
735
743
{
736
744
char * my_cell ;
737
745
738
746
my_cell = format_numeric_locale ((char * ) col_lineptrs [j ]-> ptr );
739
- strcpy (( char * ) col_lineptrs [ j ] -> ptr , my_cell ); /* Buffer IS large
740
- * enough... now */
747
+ /* Buffer IS large enough... now */
748
+ strcpy (( char * ) col_lineptrs [ j ] -> ptr , my_cell );
741
749
free (my_cell );
742
750
}
743
751
}
@@ -764,16 +772,22 @@ print_aligned_text(const char *title, const char *const * headers,
764
772
{
765
773
/* We have a valid array element, so index it */
766
774
struct lineptr * this_line = & col_lineptrs [j ][curr_nl_line [j ]];
767
- int bytes_to_output , chars_to_output = width_wrap [j ];
775
+ int bytes_to_output ;
776
+ int chars_to_output = width_wrap [j ];
777
+ bool finalspaces = (opt_border == 2 || j < col_count - 1 );
768
778
769
- /* Past newline lines so pad for other columns */
770
779
if (!this_line -> ptr )
771
- fprintf (fout , "%*s" , width_wrap [j ], "" );
780
+ {
781
+ /* Past newline lines so just pad for other columns */
782
+ if (finalspaces )
783
+ fprintf (fout , "%*s" , chars_to_output , "" );
784
+ }
772
785
else
773
786
{
774
- /* Get strlen() of the width_wrap character */
775
- bytes_to_output = strlen_max_width (this_line -> ptr +
776
- bytes_output [j ], & chars_to_output , encoding );
787
+ /* Get strlen() of the characters up to width_wrap */
788
+ bytes_to_output =
789
+ strlen_max_width (this_line -> ptr + bytes_output [j ],
790
+ & chars_to_output , encoding );
777
791
778
792
/*
779
793
* If we exceeded width_wrap, it means the display width
@@ -796,13 +810,14 @@ print_aligned_text(const char *title, const char *const * headers,
796
810
/* spaces second */
797
811
fprintf (fout , "%.*s" , bytes_to_output ,
798
812
this_line -> ptr + bytes_output [j ]);
799
- fprintf (fout , "%*s" , width_wrap [j ] - chars_to_output , "" );
813
+ if (finalspaces )
814
+ fprintf (fout , "%*s" , width_wrap [j ] - chars_to_output , "" );
800
815
}
801
816
802
817
bytes_output [j ] += bytes_to_output ;
803
818
804
819
/* Do we have more text to wrap? */
805
- if (* (this_line -> ptr + bytes_output [j ]) != 0 )
820
+ if (* (this_line -> ptr + bytes_output [j ]) != '\0' )
806
821
more_lines = true;
807
822
else
808
823
{
@@ -814,8 +829,8 @@ print_aligned_text(const char *title, const char *const * headers,
814
829
}
815
830
}
816
831
817
- /* print a divider, middle columns only */
818
- if (( j + 1 ) % col_count )
832
+ /* print a divider, if not the last column */
833
+ if (j < col_count - 1 )
819
834
{
820
835
if (opt_border == 0 )
821
836
fputc (' ' , fout );
@@ -832,10 +847,9 @@ print_aligned_text(const char *title, const char *const * headers,
832
847
/* Ordinary line */
833
848
fputs (" | " , fout );
834
849
}
835
-
836
850
}
837
851
838
- /* end of row border */
852
+ /* end-of- row border */
839
853
if (opt_border == 2 )
840
854
fputs (" |" , fout );
841
855
fputc ('\n' , fout );
@@ -887,7 +901,7 @@ print_aligned_vertical(const char *title, const char *const * headers,
887
901
{
888
902
bool opt_tuples_only = opt -> tuples_only ;
889
903
bool opt_numeric_locale = opt -> numericLocale ;
890
- unsigned short int opt_border = opt -> border ;
904
+ unsigned short opt_border = opt -> border ;
891
905
int encoding = opt -> encoding ;
892
906
unsigned int col_count = 0 ;
893
907
unsigned long record = opt -> prior_records + 1 ;
@@ -927,7 +941,8 @@ print_aligned_vertical(const char *title, const char *const * headers,
927
941
height ,
928
942
fs ;
929
943
930
- pg_wcssize ((unsigned char * ) headers [i ], strlen (headers [i ]), encoding , & width , & height , & fs );
944
+ pg_wcssize ((unsigned char * ) headers [i ], strlen (headers [i ]), encoding ,
945
+ & width , & height , & fs );
931
946
if (width > hwidth )
932
947
hwidth = width ;
933
948
if (height > hheight )
@@ -953,7 +968,8 @@ print_aligned_vertical(const char *title, const char *const * headers,
953
968
else
954
969
numeric_locale_len = 0 ;
955
970
956
- pg_wcssize ((unsigned char * ) * ptr , strlen (* ptr ), encoding , & width , & height , & fs );
971
+ pg_wcssize ((unsigned char * ) * ptr , strlen (* ptr ), encoding ,
972
+ & width , & height , & fs );
957
973
width += numeric_locale_len ;
958
974
if (width > dwidth )
959
975
dwidth = width ;
@@ -1041,9 +1057,11 @@ print_aligned_vertical(const char *title, const char *const * headers,
1041
1057
1042
1058
/* Format the header */
1043
1059
pg_wcsformat ((unsigned char * ) headers [i % col_count ],
1044
- strlen (headers [i % col_count ]), encoding , hlineptr , hheight );
1060
+ strlen (headers [i % col_count ]),
1061
+ encoding , hlineptr , hheight );
1045
1062
/* Format the data */
1046
- pg_wcsformat ((unsigned char * ) * ptr , strlen (* ptr ), encoding , dlineptr , dheight );
1063
+ pg_wcsformat ((unsigned char * ) * ptr , strlen (* ptr ), encoding ,
1064
+ dlineptr , dheight );
1047
1065
1048
1066
line_count = 0 ;
1049
1067
dcomplete = hcomplete = 0 ;
@@ -1182,7 +1200,7 @@ print_html_text(const char *title, const char *const * headers,
1182
1200
{
1183
1201
bool opt_tuples_only = opt -> tuples_only ;
1184
1202
bool opt_numeric_locale = opt -> numericLocale ;
1185
- unsigned short int opt_border = opt -> border ;
1203
+ unsigned short opt_border = opt -> border ;
1186
1204
const char * opt_table_attr = opt -> tableAttr ;
1187
1205
unsigned int col_count = 0 ;
1188
1206
unsigned int i ;
@@ -1283,7 +1301,7 @@ print_html_vertical(const char *title, const char *const * headers,
1283
1301
{
1284
1302
bool opt_tuples_only = opt -> tuples_only ;
1285
1303
bool opt_numeric_locale = opt -> numericLocale ;
1286
- unsigned short int opt_border = opt -> border ;
1304
+ unsigned short opt_border = opt -> border ;
1287
1305
const char * opt_table_attr = opt -> tableAttr ;
1288
1306
unsigned int col_count = 0 ;
1289
1307
unsigned long record = opt -> prior_records + 1 ;
@@ -1421,7 +1439,7 @@ print_latex_text(const char *title, const char *const * headers,
1421
1439
{
1422
1440
bool opt_tuples_only = opt -> tuples_only ;
1423
1441
bool opt_numeric_locale = opt -> numericLocale ;
1424
- unsigned short int opt_border = opt -> border ;
1442
+ unsigned short opt_border = opt -> border ;
1425
1443
unsigned int col_count = 0 ;
1426
1444
unsigned int i ;
1427
1445
const char * const * ptr ;
@@ -1534,7 +1552,7 @@ print_latex_vertical(const char *title, const char *const * headers,
1534
1552
{
1535
1553
bool opt_tuples_only = opt -> tuples_only ;
1536
1554
bool opt_numeric_locale = opt -> numericLocale ;
1537
- unsigned short int opt_border = opt -> border ;
1555
+ unsigned short opt_border = opt -> border ;
1538
1556
unsigned int col_count = 0 ;
1539
1557
unsigned long record = opt -> prior_records + 1 ;
1540
1558
unsigned int i ;
@@ -1661,7 +1679,7 @@ print_troff_ms_text(const char *title, const char *const * headers,
1661
1679
{
1662
1680
bool opt_tuples_only = opt -> tuples_only ;
1663
1681
bool opt_numeric_locale = opt -> numericLocale ;
1664
- unsigned short int opt_border = opt -> border ;
1682
+ unsigned short opt_border = opt -> border ;
1665
1683
unsigned int col_count = 0 ;
1666
1684
unsigned int i ;
1667
1685
const char * const * ptr ;
@@ -1764,7 +1782,7 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
1764
1782
{
1765
1783
bool opt_tuples_only = opt -> tuples_only ;
1766
1784
bool opt_numeric_locale = opt -> numericLocale ;
1767
- unsigned short int opt_border = opt -> border ;
1785
+ unsigned short opt_border = opt -> border ;
1768
1786
unsigned int col_count = 0 ;
1769
1787
unsigned long record = opt -> prior_records + 1 ;
1770
1788
unsigned int i ;
@@ -1970,7 +1988,7 @@ printTable(const char *title,
1970
1988
static const char * default_footer [] = {NULL };
1971
1989
FILE * output ;
1972
1990
bool is_pager = false;
1973
-
1991
+
1974
1992
if (cancel_pressed )
1975
1993
return ;
1976
1994
@@ -2216,36 +2234,36 @@ setDecimalLocale(void)
2216
2234
}
2217
2235
2218
2236
/*
2219
- * Returns the byte length to the end of the specified character
2220
- * and number of display characters processed (useful if the string
2221
- * is shorter then dpylen) .
2237
+ * Compute the byte distance to the end of the string or *target_width
2238
+ * display character positions, whichever comes first. Update *target_width
2239
+ * to be the number of display character positions actually filled .
2222
2240
*/
2223
2241
static int
2224
2242
strlen_max_width (unsigned char * str , int * target_width , int encoding )
2225
2243
{
2226
2244
unsigned char * start = str ;
2245
+ unsigned char * end = str + strlen ((char * ) str );
2227
2246
int curr_width = 0 ;
2228
2247
2229
- while (* str && curr_width < * target_width )
2248
+ while (str < end )
2230
2249
{
2231
2250
int char_width = PQdsplen ((char * ) str , encoding );
2232
2251
2233
2252
/*
2234
2253
* If the display width of the new character causes
2235
2254
* the string to exceed its target width, skip it
2236
2255
* and return. However, if this is the first character
2237
- * of the string (*width == 0), we have to accept it.
2256
+ * of the string (curr_width == 0), we have to accept it.
2238
2257
*/
2239
- if (* target_width - curr_width < char_width && curr_width != 0 )
2258
+ if (* target_width < curr_width + char_width && curr_width != 0 )
2240
2259
break ;
2241
-
2242
- str += PQmblen ((char * )str , encoding );
2243
2260
2244
2261
curr_width += char_width ;
2262
+
2263
+ str += PQmblen ((char * ) str , encoding );
2245
2264
}
2246
2265
2247
2266
* target_width = curr_width ;
2248
2267
2249
- /* last byte */
2250
2268
return str - start ;
2251
2269
}
0 commit comments