fit terminal window size as it changes. Reviewed by John Darrington.
* automake.mk (src_ui_terminal_libui_a_SOURCES): Add new files.
* terminal.c: New file.
* terminal.h: New file.
* main.c (main): No need to set up SIGWINCH handler any longer.
But we do need to call terminal_init.
(set_fallback_viewport): Move to terminal.c.
[HAVE_LIBNCURSES] (get_termcap_viewport): Ditto.
[!HAVE_LIBNCURSES] (get_termcap_viewport): Ditto.
* read-line.c (readln_read): After the first line of a command,
call terminal_check_size to allow it to re-detect the terminal
size.
* ascii.c: Implement ability to resize output device parameters to
fit terminal window size as it changes.
(struct ascii_driver_ext): New members `auto_width',
`auto_length'.
(ascii_open_driver): Initialize new members, call
update_page_size.
(update_page_size): New function to update device size.
(handle_option): Support new "auto" setting for length, width.
(ascii_open_page): Call update_page_size.
* devices (tty-ascii): Set length and width to "auto", so that
they reflect the current size of the terminal window as it
changes.
+2007-09-25 Ben Pfaff <blp@gnu.org>
+
+ * devices (tty-ascii): Set length and width to "auto", so that
+ they reflect the current size of the terminal window as it
+ changes.
+
2007-09-22 Ben Pfaff <blp@gnu.org>
Bug #21128. Reviewed by John Darrington.
# Generic ASCII devices
tty-ascii:ascii:screen:squeeze=on headers=off top-margin=0 bottom-margin=0 \
- paginate=off length=${viewlength} width=${viewwidth} \
- output-file=${tty-output-file}
+ paginate=off length=auto width=auto output-file=${tty-output-file}
list-ascii:ascii:listing:length=66 width=79 output-file=${list-output-file}
raw-ascii:ascii:listing:width=9999 length=9999 output-file=${list-output-file} \
emphasis=none headers=off paginate=off squeeze=on \
@item length=@var{line-count}
-Physical length of a page, in lines. Headers and margins are subtracted
-from this value. Default: @code{66}.
+Physical length of a page. Headers and margins are subtracted from
+this value. You may specify the number of lines as a number, or for
+screen output you may specify @code{auto} to track the height of the
+terminal as it changes. Default: @code{66}.
@item width=@var{character-count}
-Physical width of a page, in characters. Margins are subtracted from
-this value. Default: @code{130}.
+Physical width of a page. Margins are subtracted from this value.
+You may specify the width as a number of characters, or for screen
+output you may specify @code{auto} to track the width of the terminal
+as it changes. Default: @code{79}.
@item top-margin=@var{top-margin-lines}
+2007-09-25 Ben Pfaff <blp@gnu.org>
+
+ Patch #6210. Reviewed by John Darrington.
+
+ * ascii.c: Implement ability to resize output device parameters to
+ fit terminal window size as it changes.
+ (struct ascii_driver_ext): New members `auto_width',
+ `auto_length'.
+ (ascii_open_driver): Initialize new members, call
+ update_page_size.
+ (update_page_size): New function to update device size.
+ (handle_option): Support new "auto" setting for length, width.
+ (ascii_open_page): Call update_page_size.
+
2007-09-22 Ben Pfaff <blp@gnu.org>
Bug #21128. Reviewed by John Darrington.
#include <stdlib.h>
#include <data/file-name.h>
+#include <data/settings.h>
#include <libpspp/alloc.h>
#include <libpspp/assertion.h>
#include <libpspp/compiler.h>
headers=on|off Put headers at top of page?
emphasis=bold|underline|none Style to use for emphasis.
- length=66
- width=130
+ length=66|auto
+ width=79|auto
squeeze=off|on Squeeze multiple newlines into exactly one.
top-margin=2
const char *chart_type; /* Type of charts to output; NULL for none. */
const char *chart_file_name; /* Name of files used for charts. */
+ bool auto_width; /* Use viewwidth as page width? */
+ bool auto_length; /* Use viewlength as page width? */
int page_length; /* Page length before subtracting margins. */
int top_margin; /* Top margin in lines. */
int bottom_margin; /* Bottom margin in lines. */
static void ascii_flush (struct outp_driver *);
static int get_default_box_char (size_t idx);
+static bool update_page_size (struct outp_driver *, bool issue_error);
static bool handle_option (struct outp_driver *this, const char *key,
const struct string *val);
x->tab_width = 8;
x->chart_file_name = pool_strdup (x->pool, "pspp-#.png");
x->chart_type = pool_strdup (x->pool, "png");
+ x->auto_width = false;
+ x->auto_length = false;
x->page_length = 66;
x->top_margin = 2;
x->bottom_margin = 2;
if (!outp_parse_options (options, handle_option, this))
goto error;
- this->length = x->page_length - x->top_margin - x->bottom_margin - 1;
- if (x->headers)
- this->length -= 3;
-
- if (this->width < 59 || this->length < 15)
- {
- error (0, 0,
- _("ascii: page excluding margins and headers "
- "must be at least 59 characters wide by 15 lines long, but as "
- "configured is only %d characters by %d lines"),
- this->width, this->length);
- return false;
- }
+ if (!update_page_size (this, true))
+ goto error;
for (i = 0; i < LNS_COUNT; i++)
if (x->box[i] == NULL)
}
}
+/* Re-calculates the page width and length based on settings,
+ margins, and, if "auto" is set, the size of the user's
+ terminal window or GUI output window. */
+static bool
+update_page_size (struct outp_driver *this, bool issue_error)
+{
+ struct ascii_driver_ext *x = this->ext;
+ int margins = x->top_margin + x->bottom_margin + 1 + (x->headers ? 3 : 0);
+
+ if (x->auto_width)
+ this->width = get_viewwidth ();
+ if (x->auto_length)
+ x->page_length = get_viewlength ();
+
+ this->length = x->page_length - margins;
+
+ if (this->width < 59 || this->length < 15)
+ {
+ if (issue_error)
+ error (0, 0,
+ _("ascii: page excluding margins and headers "
+ "must be at least 59 characters wide by 15 lines long, but "
+ "as configured is only %d characters by %d lines"),
+ this->width, this->length);
+ if (this->width < 59)
+ this->width = 59;
+ if (this->length < 15)
+ {
+ this->length = 15;
+ x->page_length = this->length + margins;
+ }
+ return false;
+ }
+
+ return true;
+}
+
static bool
ascii_close_driver (struct outp_driver *this)
{
boolean_arg,
emphasis_arg,
nonneg_int_arg,
- pos_int_arg,
+ page_size_arg,
string_arg
};
{"emphasis", emphasis_arg, 0},
- {"length", pos_int_arg, 0},
- {"width", pos_int_arg, 1},
+ {"length", page_size_arg, 0},
+ {"width", page_size_arg, 1},
{"top-margin", nonneg_int_arg, 0},
{"bottom-margin", nonneg_int_arg, 1},
case -1:
error (0, 0, _("ascii: unknown parameter `%s'"), key);
break;
- case pos_int_arg:
+ case page_size_arg:
{
char *tail;
int arg;
- errno = 0;
- arg = strtol (value, &tail, 0);
- if (arg < 1 || errno == ERANGE || *tail)
- {
- error (0, 0, _("ascii: positive integer required as `%s' value"),
- key);
- break;
- }
- switch (subcat)
- {
- case 0:
- x->page_length = arg;
- break;
- case 1:
- this->width = arg;
- break;
- default:
- NOT_REACHED ();
- }
+ if (ss_equals_case (ds_ss (val), ss_cstr ("auto")))
+ {
+ if (!(this->device & OUTP_DEV_SCREEN))
+ {
+ /* We only let `screen' devices have `auto'
+ length or width because output to such devices
+ is flushed before each new command. Resizing
+ a device in the middle of output seems like a
+ bad idea. */
+ error (0, 0, _("ascii: only screen devices may have `auto' "
+ "length or width"));
+ }
+ else if (subcat == 0)
+ x->auto_length = true;
+ else
+ x->auto_width = true;
+ }
+ else
+ {
+ errno = 0;
+ arg = strtol (value, &tail, 0);
+ if (arg < 1 || errno == ERANGE || *tail)
+ {
+ error (0, 0, _("ascii: positive integer required as "
+ "`%s' value"),
+ key);
+ break;
+ }
+ switch (subcat)
+ {
+ case 0:
+ x->page_length = arg;
+ break;
+ case 1:
+ this->width = arg;
+ break;
+ default:
+ NOT_REACHED ();
+ }
+ }
}
break;
case emphasis_arg:
struct ascii_driver_ext *x = this->ext;
int i;
+ update_page_size (this, false);
+
if (x->file == NULL)
{
x->file = fn_open (x->file_name, x->append ? "a" : "w");
+2007-09-25 Ben Pfaff <blp@gnu.org>
+
+ Patch #6210: implement ability to resize output device parameters
+ to fit terminal window size as it changes. Reviewed by John
+ Darrington.
+
+ * automake.mk (src_ui_terminal_libui_a_SOURCES): Add new files.
+
+ * terminal.c: New file.
+
+ * terminal.h: New file.
+
+ * main.c (main): No need to set up SIGWINCH handler any longer.
+ But we do need to call terminal_init.
+ (set_fallback_viewport): Move to terminal.c.
+ [HAVE_LIBNCURSES] (get_termcap_viewport): Ditto.
+ [!HAVE_LIBNCURSES] (get_termcap_viewport): Ditto.
+
+ * read-line.c (readln_read): After the first line of a command,
+ call terminal_check_size to allow it to re-detect the terminal
+ size.
+
2007-09-24 Ben Pfaff <blp@gnu.org>
Patch #6210. Reviewed by John Darrington.
src/ui/terminal/read-line.h \
src/ui/terminal/main.c \
src/ui/terminal/msg-ui.c \
- src/ui/terminal/msg-ui.h
+ src/ui/terminal/msg-ui.h \
+ src/ui/terminal/terminal.c \
+ src/ui/terminal/terminal.h
src_ui_terminal_libui_a_CFLAGS = -DINSTALLDIR=\"$(bindir)\"
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <config.h>
+#include <locale.h>
#include <signal.h>
#include <stdio.h>
-
-#include <ui/debugger.h>
-#include "command-line.h"
-#include "msg-ui.h"
-#include "progname.h"
-#include "read-line.h"
+#include <stdlib.h>
+#if HAVE_FPU_CONTROL_H
+#include <fpu_control.h>
+#endif
+#if HAVE_FENV_H
+#include <fenv.h>
+#endif
+#if HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
#include <data/dictionary.h>
#include <data/file-handle-def.h>
#include <libpspp/version.h>
#include <math/random.h>
#include <output/output.h>
+#include <ui/debugger.h>
+#include <ui/terminal/command-line.h>
+#include <ui/terminal/msg-ui.h>
+#include <ui/terminal/read-line.h>
+#include <ui/terminal/terminal.h>
-#if HAVE_FPU_CONTROL_H
-#include <fpu_control.h>
-#endif
-
-#if HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-#if HAVE_FENV_H
-#include <fenv.h>
-#endif
-
-#if HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
+#include "progname.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
-#include <stdlib.h>
static void i18n_init (void);
static void fpu_init (void);
static struct lexer *the_lexer;
static struct source_stream *the_source_stream ;
-static int view_length = -1;
-static int view_width = -1;
-
-static void get_termcap_viewport (int);
-
-
/* Program entry point. */
int
main (int argc, char **argv)
{
+ int *view_width_p, *view_length_p;
+
+ set_program_name (argv[0]);
+
signal (SIGABRT, bug_handler);
signal (SIGSEGV, bug_handler);
signal (SIGFPE, bug_handler);
signal (SIGINT, interrupt_handler);
- signal (SIGWINCH, get_termcap_viewport);
-
- set_program_name (argv[0]);
i18n_init ();
fpu_init ();
);
prompt_init ();
readln_initialize ();
- get_termcap_viewport (0);
- settings_init (&view_width, &view_length);
+ terminal_init (&view_width_p, &view_length_p);
+ settings_init (view_width_p, view_length_p);
random_init ();
the_dataset = create_dataset ();
}
exit (success ? EXIT_SUCCESS : EXIT_FAILURE);
}
-
-\f
-#include "error.h"
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-
-/* If view_width or view_length has not yet been set to a
- reasonable value, takes a guess. */
-static void
-set_fallback_viewport (void)
-{
- if (view_width <= 0)
- {
- if (getenv ("COLUMNS") != NULL)
- view_width = atoi (getenv ("COLUMNS"));
- if (view_width <= 0)
- view_width = 79;
- }
-
- if (view_length <= 0)
- {
- if (getenv ("LINES") != NULL)
- view_length = atoi (getenv ("LINES"));
- if (view_length <= 0)
- view_length = 24;
- }
-}
-
-/* Code that interfaces to ncurses. This must be at the very end
- of this file because curses.h redefines "bool" on some systems
- (e.g. OpenBSD), causing declaration mismatches with functions
- that have parameters or return values of type "bool". */
-#if HAVE_LIBNCURSES
-#include <curses.h>
-#include <term.h>
-
-static void
-get_termcap_viewport (int sig UNUSED)
-{
- char term_buffer [16384];
-
- if (getenv ("TERM") != NULL)
- {
- if (tgetent (term_buffer, getenv ("TERM")) > 0)
- {
- if (tgetnum ("li") > 0)
- view_length = tgetnum ("li");
- if (tgetnum ("co") > 1)
- view_width = tgetnum ("co") - 1;
- }
- else
- error (0, 0, _("could not access definition for terminal `%s'"),
- getenv ("TERM"));
- }
-
- set_fallback_viewport ();
-}
-
-#else /* !HAVE_LIBNCURSES */
-
-static void
-get_termcap_viewport (int sig UNUSED)
-{
- set_fallback_viewport ();
-}
-
-#endif /* !HAVE_LIBNCURSES */
-
-
#include <language/prompt.h>
#include <output/journal.h>
#include <output/manager.h>
+#include <ui/terminal/terminal.h>
#include "xalloc.h"
#if HAVE_READLINE
char *string;
#endif
+ bool eof;
assert (initialised);
: dont_complete);
string = readline (prompt);
if (string == NULL)
- return false;
+ eof = true;
else
{
if (string[0])
add_history (string);
ds_assign_cstr (line, string);
free (string);
- return true;
+ eof = false;
}
#else
fputs (prompt, stdout);
if (ds_read_line (line, stdin))
{
ds_chomp (line, '\n');
- return true;
+ eof = false;
}
else
- return false;
+ eof = true;
#endif
-}
+ /* Check whether the size of the window has changed, so that
+ the output drivers can adjust their settings as needed. We
+ only do this for the first line of a command, as it's
+ possible that the output drivers are actually in use
+ afterward, and we don't want to confuse them in the middle
+ of output. */
+ if (style == PROMPT_FIRST)
+ terminal_check_size ();
+
+ return !eof;
+}
static void
readln_close (struct getl_interface *i)
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <ui/terminal/terminal.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <libpspp/compiler.h>
+
+#include "error.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+static int view_width = -1;
+static int view_length = -1;
+
+/* Initializes the terminal interface by determining the size of
+ the user's terminal. Stores a pointer to the size variables
+ in *VIEW_WIDTH_P and *VIEW_LENGTH_P. */
+void
+terminal_init (int **view_width_p, int **view_length_p)
+{
+ *view_width_p = &view_width;
+ *view_length_p = &view_length;
+ terminal_check_size ();
+}
+
+/* Code that interfaces to ncurses. This must be at the very end
+ of this file because curses.h redefines "bool" on some systems
+ (e.g. OpenBSD), causing declaration mismatches with functions
+ that have parameters or return values of type "bool". */
+#if HAVE_LIBNCURSES
+#include <curses.h>
+#include <term.h>
+#endif
+
+/* Determines the size of the terminal, if possible, or at least
+ takes an educated guess. */
+void
+terminal_check_size (void)
+{
+#if HAVE_LIBNCURSES
+ if (getenv ("TERM") != NULL)
+ {
+ char term_buffer [16384];
+
+ if (tgetent (term_buffer, getenv ("TERM")) > 0)
+ {
+ if (tgetnum ("li") > 0)
+ view_length = tgetnum ("li");
+ if (tgetnum ("co") > 1)
+ view_width = tgetnum ("co") - 1;
+ }
+ else
+ error (0, 0, _("could not access definition for terminal `%s'"),
+ getenv ("TERM"));
+ }
+#endif
+
+ if (view_width <= 0)
+ {
+ if (getenv ("COLUMNS") != NULL)
+ view_width = atoi (getenv ("COLUMNS"));
+ if (view_width <= 0)
+ view_width = 79;
+ }
+
+ if (view_length <= 0)
+ {
+ if (getenv ("LINES") != NULL)
+ view_length = atoi (getenv ("LINES"));
+ if (view_length <= 0)
+ view_length = 24;
+ }
+}
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef UI_TERMINAL_TERMINAL_H
+#define UI_TERMINAL_TERMINAL_H 1
+
+void terminal_init (int **view_width_p, int **view_length_p);
+void terminal_check_size (void);
+
+#endif /* ui/terminal/terminal.h */