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 (unsignedchar * 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 (unsignedchar * 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 shortint opt_border = opt -> border ;
415
+ unsigned short opt_border = opt -> border ;
415
416
416
417
unsignedint 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 ((unsignedchar * )headers [i ],strlen (headers [i ]),encoding ,& width ,& nl_lines ,& bytes_required );
487
+ pg_wcssize ((unsignedchar * )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 ((unsignedchar * )* ptr ,strlen (* ptr ),encoding ,& width ,& nl_lines ,& bytes_required );
507
+ pg_wcssize ((unsignedchar * )* 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 ((unsignedchar * )title ,strlen (title ),encoding ,& width ,& height ,NULL );
650
+ pg_wcssize ((unsignedchar * )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 ((unsignedchar * )ptr [j ],strlen (ptr [j ]),encoding ,col_lineptrs [j ],max_nl_lines [j ]);
738
+ pg_wcsformat ((unsignedchar * )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 shortint opt_border = opt -> border ;
904
+ unsigned short opt_border = opt -> border ;
891
905
int encoding = opt -> encoding ;
892
906
unsignedint 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 ((unsignedchar * )headers [i ],strlen (headers [i ]),encoding ,& width ,& height ,& fs );
944
+ pg_wcssize ((unsignedchar * )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 ((unsignedchar * )* ptr ,strlen (* ptr ),encoding ,& width ,& height ,& fs );
971
+ pg_wcssize ((unsignedchar * )* 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 ((unsignedchar * )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 ((unsignedchar * )* ptr ,strlen (* ptr ),encoding ,dlineptr ,dheight );
1063
+ pg_wcsformat ((unsignedchar * )* 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 shortint opt_border = opt -> border ;
1203
+ unsigned short opt_border = opt -> border ;
1186
1204
const char * opt_table_attr = opt -> tableAttr ;
1187
1205
unsignedint col_count = 0 ;
1188
1206
unsignedint 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 shortint opt_border = opt -> border ;
1304
+ unsigned short opt_border = opt -> border ;
1287
1305
const char * opt_table_attr = opt -> tableAttr ;
1288
1306
unsignedint 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 shortint opt_border = opt -> border ;
1442
+ unsigned short opt_border = opt -> border ;
1425
1443
unsignedint col_count = 0 ;
1426
1444
unsignedint 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 shortint opt_border = opt -> border ;
1555
+ unsigned short opt_border = opt -> border ;
1538
1556
unsignedint col_count = 0 ;
1539
1557
unsigned long record = opt -> prior_records + 1 ;
1540
1558
unsignedint 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 shortint opt_border = opt -> border ;
1682
+ unsigned short opt_border = opt -> border ;
1665
1683
unsignedint col_count = 0 ;
1666
1684
unsignedint 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 shortint opt_border = opt -> border ;
1785
+ unsigned short opt_border = opt -> border ;
1768
1786
unsignedint col_count = 0 ;
1769
1787
unsigned long record = opt -> prior_records + 1 ;
1770
1788
unsignedint 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 bytelength to the end of thespecified character
2220
- * and number of display characters processed (useful if the string
2221
- *is shorter then dpylen) .
2237
+ * Compute the bytedistance to the end of thestring 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 (unsignedchar * str ,int * target_width ,int encoding )
2225
2243
{
2226
2244
unsignedchar * start = str ;
2245
+ unsignedchar * 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
}