Bruce Momjian wrote:
> The attached patch causes psql to use the pager if newlines or
> 'format=wrapped' has caused a single row to span more than one line and
> the output is then too long for the screen.  It also uses the pager if
> psql thinks the data will wrap off the edge of the screen.  
> 
> The display width as defined by \pset columns, $COLUMNS, or the ioctl
> (as previously discussed) We don't have similar settings for the number
> of display rows.  I assume that is OK. 
> 
> I believe this makes the pager more reliable, and in fact I have removed
> the psql manual mention that pager computations are somewhat imperfect.

Update patch applied.

-- 
  Bruce Momjian  <[EMAIL PROTECTED]>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.204
diff -c -c -r1.204 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml	14 May 2008 04:07:01 -0000	1.204
--- doc/src/sgml/ref/psql-ref.sgml	16 May 2008 16:49:19 -0000
***************
*** 1555,1561 ****
            <term><literal>columns</literal></term>
            <listitem>
            <para>
!           Controls the target width for the <literal>wrapped</> format.
            Zero (the default) causes the <literal>wrapped</> format to
            affect only screen output.
            </para>
--- 1555,1562 ----
            <term><literal>columns</literal></term>
            <listitem>
            <para>
!           Controls the target width for the <literal>wrapped</> format,
!           and width for determining if wide output requires the pager.
            Zero (the default) causes the <literal>wrapped</> format to
            affect only screen output.
            </para>
***************
*** 1717,1726 ****
            When the pager is <literal>off</>, the pager is not used. When the pager
            is <literal>on</>, the pager is used only when appropriate, i.e. the
            output is to a terminal and will not fit on the screen.
!           (<application>psql</> does not do a perfect job of estimating
!           when to use the pager.) <literal>\pset pager</> turns the
!           pager on and off. Pager can also be set to <literal>always</>,
!           which causes the pager to be always used.
            </para>
            </listitem>
            </varlistentry>
--- 1718,1726 ----
            When the pager is <literal>off</>, the pager is not used. When the pager
            is <literal>on</>, the pager is used only when appropriate, i.e. the
            output is to a terminal and will not fit on the screen.
!           <literal>\pset pager</> turns the pager on and off. Pager can
!           also be set to <literal>always</>, which causes the pager to be
!           always used.
            </para>
            </listitem>
            </varlistentry>
***************
*** 2734,2741 ****
  
      <listitem>
       <para>
!       Used for the <literal>wrapped</> output format if 
!       <literal>\pset columns</> is zero.
       </para>
      </listitem>
     </varlistentry>
--- 2734,2742 ----
  
      <listitem>
       <para>
!       If <literal>\pset columns</> is zero, controls the
!       width for the <literal>wrapped</> format and width for determining
!       if wide output requires the pager.
       </para>
      </listitem>
     </varlistentry>
Index: src/bin/psql/print.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/print.c,v
retrieving revision 1.101
diff -c -c -r1.101 print.c
*** src/bin/psql/print.c	13 May 2008 00:14:11 -0000	1.101
--- src/bin/psql/print.c	16 May 2008 16:49:20 -0000
***************
*** 45,50 ****
--- 45,52 ----
  
  /* Local functions */
  static int strlen_max_width(unsigned char *str, int *target_width, int encoding);
+ static void IsPagerNeeded(const printTableContent *cont, const int extra_lines,
+ 						  FILE **fout, bool *is_pager);
  
  
  static void *
***************
*** 394,400 ****
   *	Print pretty boxes around cells.
   */
  static void
! print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout)
  {
  	bool		opt_tuples_only = cont->opt->tuples_only;
  	bool		opt_numeric_locale = cont->opt->numericLocale;
--- 396,402 ----
   *	Print pretty boxes around cells.
   */
  static void
! print_aligned_text(const printTableContent *cont, FILE *fout)
  {
  	bool		opt_tuples_only = cont->opt->tuples_only;
  	bool		opt_numeric_locale = cont->opt->numericLocale;
***************
*** 416,421 ****
--- 418,425 ----
  	unsigned char **format_buf;
  	unsigned int width_total;
  	unsigned int total_header_width;
+ 	unsigned int extra_row_output_lines = 0;
+ 	unsigned int extra_output_lines = 0;
  
  	const char * const *ptr;
  
***************
*** 424,429 ****
--- 428,434 ----
  	bool	   *header_done;	/* Have all header lines been output? */
  	int		   *bytes_output;	/* Bytes output for column value */
  	int			output_columns = 0;	/* Width of interactive console */
+ 	bool		is_pager = false;
  
  	if (cancel_pressed)
  		return;
***************
*** 476,484 ****
--- 481,494 ----
  			max_nl_lines[i] = nl_lines;
  		if (bytes_required > max_bytes[i])
  			max_bytes[i] = bytes_required;
+ 		if (nl_lines > extra_row_output_lines)
+ 			extra_row_output_lines = nl_lines;
  
  		width_header[i] = width;
  	}
+ 	/* Add height of tallest header column */
+ 	extra_output_lines += extra_row_output_lines;
+ 	extra_row_output_lines = 0;
  
  	/* scan all cells, find maximum width, compute cell_count */
  	for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++)
***************
*** 487,493 ****
  					nl_lines,
  					bytes_required;
  
- 		/* Get width, ignore nl_lines */
  		pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
  				   &width, &nl_lines, &bytes_required);
  		if (opt_numeric_locale && cont->aligns[i % col_count] == 'r')
--- 497,502 ----
***************
*** 552,579 ****
  	for (i = 0; i < col_count; i++)
  		width_wrap[i] = max_width[i];
  
! 	if (cont->opt->format == PRINT_WRAPPED)
  	{
! 		/*
! 		 * Choose target output width: \pset columns, or $COLUMNS, or ioctl
! 		 */
! 		if (cont->opt->columns > 0)
! 			output_columns = cont->opt->columns;
! 		else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
! 		{
! 			if (cont->opt->env_columns > 0)
! 				output_columns = cont->opt->env_columns;
  #ifdef TIOCGWINSZ
! 			else
! 			{
! 				struct winsize screen_size;
! 	
! 				if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
! 					output_columns = screen_size.ws_col;
! 			}
! #endif
  		}
  
  		/*
  		 * Optional optimized word wrap. Shrink columns with a high max/avg
  		 * ratio.  Slighly bias against wider columns. (Increases chance a
--- 561,588 ----
  	for (i = 0; i < col_count; i++)
  		width_wrap[i] = max_width[i];
  
! 	/*
! 	 * Choose target output width: \pset columns, or $COLUMNS, or ioctl
! 	 */
! 	if (cont->opt->columns > 0)
! 		output_columns = cont->opt->columns;
! 	else if ((fout == stdout && isatty(fileno(stdout))) || is_pager)
  	{
! 		if (cont->opt->env_columns > 0)
! 			output_columns = cont->opt->env_columns;
  #ifdef TIOCGWINSZ
! 		else
! 		{
! 			struct winsize screen_size;
! 
! 			if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1)
! 				output_columns = screen_size.ws_col;
  		}
+ #endif
+ 	}
  
+ 	if (cont->opt->format == PRINT_WRAPPED)
+ 	{
  		/*
  		 * Optional optimized word wrap. Shrink columns with a high max/avg
  		 * ratio.  Slighly bias against wider columns. (Increases chance a
***************
*** 623,628 ****
--- 632,680 ----
  		}
  	}
  
+ 	/* If we wrapped beyond the display width, use the pager */
+ 	if (!is_pager && output_columns > 0 &&
+ 		(output_columns < total_header_width || output_columns < width_total))
+ 	{
+ 		fout = PageOutput(INT_MAX, cont->opt->pager);	/* force pager */
+ 		is_pager = true;
+ 	}
+ 	
+ 	/* Check if newlines or our wrapping now need the pager */
+ 	if (!is_pager)
+ 	{
+ 		/* scan all cells, find maximum width, compute cell_count */
+ 		for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++)
+ 		{
+ 			int			width,
+ 						nl_lines,
+ 						bytes_required;
+ 	
+ 			pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding,
+ 					   &width, &nl_lines, &bytes_required);
+ 			if (opt_numeric_locale && cont->align[i % col_count] == 'r')
+ 				width += additional_numeric_locale_len(*ptr);
+ 	
+ 			/*
+ 			 *	A row can have both wrapping and newlines that cause
+ 			 *	it to display across multiple lines.  We check
+ 			 *	for both cases below.
+ 			 */
+ 			if (width > 0 && width_wrap[i] &&
+ 				(width-1) / width_wrap[i] + nl_lines > extra_row_output_lines)
+ 				extra_row_output_lines = (width-1) / width_wrap[i] + nl_lines;
+ 
+ 			/* If last column, add tallest column height */
+ 			if (i % col_count == col_count - 1)
+ 			{
+ 				/* Add height of tallest row */
+ 				extra_output_lines += extra_row_output_lines;
+ 				extra_row_output_lines = 0;
+ 			}
+ 		}
+ 		IsPagerNeeded(cont, extra_output_lines, &fout, &is_pager);
+ 	}
+ 	
  	/* time to output */
  	if (cont->opt->start_table)
  	{
***************
*** 882,887 ****
--- 934,942 ----
  	for (i = 0; i < col_count; i++)
  		free(format_buf[i]);
  	free(format_buf);
+ 
+ 	if (is_pager)
+ 		ClosePager(fout);
  }
  
  
***************
*** 2115,2135 ****
  }
  
  /*
!  * Use this to print just any table in the supported formats.
   */
  void
! printTable(const printTableContent *cont, FILE *fout, FILE *flog)
  {
! 	FILE	   *output;
! 	bool		is_pager = false;
! 	
! 	if (cancel_pressed)
! 		return;
! 
! 	if (cont->opt->format == PRINT_NOTHING)
! 		return;
! 
! 	if (fout == stdout)
  	{
  		int			lines;
  
--- 2170,2184 ----
  }
  
  /*
!  * IsPagerNeeded
!  *
!  * Setup pager if required
   */
  void
! IsPagerNeeded(const printTableContent *cont, const int extra_lines, FILE **fout,
! 			  bool *is_pager)
  {
! 	if (*fout == stdout)
  	{
  		int			lines;
  
***************
*** 2150,2207 ****
  				lines++;
  		}
  
! 		output = PageOutput(lines, cont->opt->pager);
! 		is_pager = (output != fout);
  	}
  	else
! 		output = fout;
  
  	/* print the stuff */
  
  	if (flog)
! 		print_aligned_text(cont, is_pager, flog);
  
  	switch (cont->opt->format)
  	{
  		case PRINT_UNALIGNED:
  			if (cont->opt->expanded)
! 				print_unaligned_vertical(cont, output);
  			else
! 				print_unaligned_text(cont, output);
  			break;
  		case PRINT_ALIGNED:
  		case PRINT_WRAPPED:
  			if (cont->opt->expanded)
! 				print_aligned_vertical(cont, output);
  			else
! 				print_aligned_text(cont, is_pager, output);
  			break;
  		case PRINT_HTML:
  			if (cont->opt->expanded)
! 				print_html_vertical(cont, output);
  			else
! 				print_html_text(cont, output);
  			break;
  		case PRINT_LATEX:
  			if (cont->opt->expanded)
! 				print_latex_vertical(cont, output);
  			else
! 				print_latex_text(cont, output);
  			break;
  		case PRINT_TROFF_MS:
  			if (cont->opt->expanded)
! 				print_troff_ms_vertical(cont, output);
  			else
! 				print_troff_ms_text(cont, output);
  			break;
  		default:
! 			fprintf(stderr, _("invalid output format (internal error): %d"),
  					cont->opt->format);
  			exit(EXIT_FAILURE);
  	}
  
  	if (is_pager)
! 		ClosePager(output);
  }
  
  /*
--- 2199,2277 ----
  				lines++;
  		}
  
! 		*fout = PageOutput(lines + extra_lines, cont->opt->pager);
! 		*is_pager = (*fout != stdout);
  	}
  	else
! 		*is_pager = false;
! }
! 
! /*
!  * Use this to print just any table in the supported formats.
!  */
! void
! printTable(const printTableContent *cont, FILE *fout, FILE *flog)
! {
! 	bool		is_pager = false;
! 	
! 	if (cancel_pressed)
! 		return;
! 
! 	if (cont->opt->format == PRINT_NOTHING)
! 		return;
! 
! 	/* print_aligned_text() handles the pager itself */
! 	if ((cont->opt->format != PRINT_ALIGNED &&
! 		 cont->opt->format != PRINT_WRAPPED) ||
! 		 cont->opt->expanded)
! 		IsPagerNeeded(cont, 0, &fout, &is_pager);
  
  	/* print the stuff */
  
  	if (flog)
! 		print_aligned_text(cont, flog);
  
  	switch (cont->opt->format)
  	{
  		case PRINT_UNALIGNED:
  			if (cont->opt->expanded)
! 				print_unaligned_vertical(cont, fout);
  			else
! 				print_unaligned_text(cont, fout);
  			break;
  		case PRINT_ALIGNED:
  		case PRINT_WRAPPED:
  			if (cont->opt->expanded)
! 				print_aligned_vertical(cont, fout);
  			else
! 				print_aligned_text(cont, fout);
  			break;
  		case PRINT_HTML:
  			if (cont->opt->expanded)
! 				print_html_vertical(cont, fout);
  			else
! 				print_html_text(cont, fout);
  			break;
  		case PRINT_LATEX:
  			if (cont->opt->expanded)
! 				print_latex_vertical(cont, fout);
  			else
! 				print_latex_text(cont, fout);
  			break;
  		case PRINT_TROFF_MS:
  			if (cont->opt->expanded)
! 				print_troff_ms_vertical(cont, fout);
  			else
! 				print_troff_ms_text(cont, fout);
  			break;
  		default:
! 			fprintf(stderr, _("invalid fout format (internal error): %d"),
  					cont->opt->format);
  			exit(EXIT_FAILURE);
  	}
  
  	if (is_pager)
! 		ClosePager(fout);
  }
  
  /*
-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches

Reply via email to