/*
* Screen output handling
+ *
+ * Copyright (c) 1987-2011 by the citadel.org team
+ *
+ * This program is open source 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdarg.h>
+#include <ctype.h>
#include <sys/types.h>
+#include <sys/ioctl.h>
#include "sysdep.h"
#ifndef HAVE_SNPRINTF
#include "snprintf.h"
#include "commands.h"
#include "screen.h"
-char arg_screen;
+int enable_status_line = 0; /* FIXME the status line works, but not on Mac. Make this configurable. */
+char status_line[1024] = " ";
-extern int screenheight;
-extern int screenwidth;
-extern int rc_ansi_color;
-extern void check_screen_dims(void);
+/* the default paginator prompt will be replaced by the server's prompt when we learn it */
+char *moreprompt = " -- more -- ";
+
+int screenheight = 24;
+int screenwidth = 80;
+int lines_printed = 0;
+int cols_printed = 0;
+extern int rc_ansi_color;
+extern int rc_prompt_control;
void do_keepalive(void);
+/*
+ * Attempt to discover the screen dimensions.
+ * WARNING: This is sometimes called from a signal handler.
+ */
+void check_screen_dims(void)
+{
+#ifdef TIOCGWINSZ
+ struct {
+ unsigned short height; /* rows */
+ unsigned short width; /* columns */
+ unsigned short xpixels;
+ unsigned short ypixels; /* pixels */
+ } xwinsz;
+
+ if (ioctl(0, TIOCGWINSZ, &xwinsz) == 0) {
+ if (xwinsz.height)
+ screenheight = (int) xwinsz.height;
+ if (xwinsz.width)
+ screenwidth = (int) xwinsz.width;
+ }
+#endif
+}
+
/*
* Initialize the screen
}
-/*
- * Kill the screen completely (used at exit). It is safe to call this
- * function more than once.
- */
-void screen_delete(void)
-{
- screen_reset();
-}
-
-
/*
* Beep.
-/*
- * Set screen/IO parameters, e.g. at start of program or return from external
- * program run.
- */
-int screen_set(void)
-{
- return 0;
-}
-
-
-/*
- * Reset screen/IO parameters, e.g. at exit or fork of external program.
- */
-int screen_reset(void)
-{
- return 0;
-}
-
/*
* scr_printf() outputs to the terminal
buf = '\0';
if (!read (0, &buf, 1))
logoff(NULL, 3);
+
+ lines_printed = 0;
return buf;
}
+/*
+ * Issue the paginator prompt (more / hit any key to continue)
+ */
+void hit_any_key(void) {
+ int a, b;
+
+ color(COLOR_PUSH);
+ color(DIM_RED);
+ scr_printf("%s\r", moreprompt);
+ color(COLOR_POP);
+ b=inkey();
+ for (a=0; a<screenwidth; ++a) {
+ scr_putc(' ');
+ }
+ scr_printf("\r");
+
+ if ( (rc_prompt_control == 1) || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL)) ) {
+ if (b == 'q' || b == 'Q' || b == 's' || b == 'S') {
+ b = STOP_KEY;
+ }
+ if (b == 'n' || b == 'N') {
+ b = NEXT_KEY;
+ }
+ }
+
+ if (b==NEXT_KEY) sigcaught = SIGINT;
+ if (b==STOP_KEY) sigcaught = SIGQUIT;
+}
+
+
/*
* Output one character to the terminal
*/
int scr_putc(int c)
{
+ /* handle tabs normally */
+ if (c == '\t') {
+ do {
+ scr_putc(' ');
+ } while ((cols_printed % 8) != 0);
+ return(c);
+ }
+
+ /* Output the character... */
if (putc(c, stdout) == EOF) {
logoff(NULL, 3);
}
+
+ if (c == '\n') {
+ ++lines_printed;
+ cols_printed = 0;
+ }
+ else if (c == '\r') {
+ cols_printed = 0;
+ }
+ else if (isprint(c)) {
+ ++cols_printed;
+ if ((screenwidth > 0) && (cols_printed > screenwidth)) {
+ ++lines_printed;
+ cols_printed = 0;
+ }
+ }
+
+ /* How many lines output before stopping for the paginator?
+ * Depends on whether we are displaying a status line.
+ */
+ int height_offset = ( ((enable_color) && (screenwidth > 0) && (enable_status_line)) ? (3) : (2) ) ;
+
+ /* Ok, go check it. Stop and display the paginator prompt if necessary. */
+ if ((screenheight > 0) && (lines_printed > (screenheight-height_offset))) {
+ lines_printed = 0;
+ hit_any_key();
+ lines_printed = 0;
+ cols_printed = 0;
+ }
+
return c;
}
-
void scr_flush(void)
{
+ if ((enable_color) && (screenwidth > 0) && (enable_status_line)) {
+ if (strlen(status_line) < screenwidth) {
+ memset(&status_line[strlen(status_line)], 32, screenwidth - strlen(status_line));
+ }
+ printf("\033[s\033[1;1H\033[K\033[7m");
+ fwrite(status_line, screenwidth, 1, stdout);
+ printf("\033[27m\033[u");
+ }
fflush(stdout);
}
static volatile int caught_sigwinch = 0;
-/*
- * this is not supposed to be called from a signal handler.
- */
-int scr_set_windowsize(CtdlIPC* ipc)
-{
- return 0;
-}
/*
* scr_winch() handles window size changes from SIGWINCH
/* if we receive this signal, we must be running
* in a terminal that supports resizing.
*/
- have_xterm = 1;
caught_sigwinch = 1;
check_screen_dims();
signal(SIGWINCH, scr_winch);
}
+
+
+
+/*
+ * Display a 3270-style "wait" indicator at the bottom of the screen
+ */
+void scr_wait_indicator(int state) {
+ int sp = (screenwidth - 2);
+
+ if (!enable_status_line) return;
+
+ if (screenwidth > 0) {
+ switch (state) {
+ default:
+ case 0: /* Idle */
+ status_line[sp] = ' ';
+ break;
+ case 1: /* Waiting */
+ status_line[sp] = 'X';
+ break;
+ case 2: /* Receiving */
+ status_line[sp] = '<';
+ break;
+ case 3: /* Sending */
+ status_line[sp] = '>';
+ break;
+ }
+ scr_flush();
+ }
+}
+