]> code.citadel.org Git - citadel.git/blobdiff - citadel/textclient/screen.c
Detect screen dimensions _before_ attaching to the server.
[citadel.git] / citadel / textclient / screen.c
index 8229c63d3bfb5a06f2998e26048e5618a910533b..c79d693fd8e1599fba5e534fd5b816a83a96640e 100644 (file)
@@ -1,14 +1,33 @@
 /*
  * 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] = "     ";
+
+/* the default paginator prompt will be replaced by the server's prompt when we learn it */
+char *moreprompt = " -- more -- ";
 
-extern int screenheight;
-extern int screenwidth;
+int screenheight = 24;
+int screenwidth = 80;
 int lines_printed = 0;
 int cols_printed = 0;
 
 extern int rc_ansi_color;
 extern int rc_prompt_control;
-extern void check_screen_dims(void);
-
 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
  */
@@ -99,29 +144,25 @@ int scr_getc(int delay)
  * Issue the paginator prompt (more / hit any key to continue)
  */
 void hit_any_key(void) {
-       int b;
+       int a, b;
 
        color(COLOR_PUSH);
        color(DIM_RED);
-       /* scr_printf("%s\r", ipc->ServInfo.moreprompt); */
-       scr_printf("<<more>>\r");       // FIXME use the prompt given by the server
+       scr_printf("%s\r", moreprompt);
        color(COLOR_POP);
-       stty_ctdl(0);
        b=inkey();
-       /*
-       for (a=0; !IsEmptyStr(&ipc->ServInfo.moreprompt[a]); ++a)
+       for (a=0; a<screenwidth; ++a) {
                scr_putc(' ');
-       */
-       scr_printf("        ");
-       scr_putc(13);
-       stty_ctdl(1);
-
-       if ( (rc_prompt_control == 1)
-          || ((rc_prompt_control == 3) && (userflags & US_PROMPTCTL)) ) {
-               if (b == 'q' || b == 'Q' || b == 's' || b == 'S')
+       }
+       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')
+               }
+               if (b == 'n' || b == 'N') {
                        b = NEXT_KEY;
+               }
        }
 
        if (b==NEXT_KEY) sigcaught = SIGINT;
@@ -162,12 +203,13 @@ int scr_putc(int c)
                }
        }
 
-       //      if we want to do a top status line, this is a reasonable way to do it
-       //      printf("\033[s\033[0;70H");
-       //      printf("\033[K   %d/%d  %d/%d", cols_printed, screenwidth, lines_printed, screenheight);
-       //      printf("\033[u");
+       /* 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) ) ;
 
-       if ((screenheight > 0) && (lines_printed > (screenheight-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;
@@ -177,9 +219,16 @@ int scr_putc(int c)
        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);
 }
 
@@ -196,8 +245,38 @@ RETSIGTYPE scr_winch(int signum)
        /* 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();
+       }
+}
+