rip out SHELL_ESCAPE define
[unix-history] / usr / src / usr.bin / window / win.c
index 61b431d..5de1f85 100644 (file)
@@ -1,8 +1,26 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)win.c       3.4 84/03/29";
-#endif
+static char sccsid[] = "@(#)win.c      3.20 (Berkeley) %G%";
+#endif /* not lint */
 
 #include "defs.h"
 
 #include "defs.h"
+#include "char.h"
 
 /*
  * Higher level routines for dealing with windows.
 
 /*
  * Higher level routines for dealing with windows.
@@ -11,12 +29,12 @@ static      char *sccsid = "@(#)win.c       3.4 84/03/29";
  * User windows are the ones with a pty and shell.  Information windows
  * are for displaying error messages, and other information.
  *
  * User windows are the ones with a pty and shell.  Information windows
  * are for displaying error messages, and other information.
  *
- * The windows are stacked in overlapping order and divided into
- * three groups: foreground, normal, and background.  Information
- * windows are always foreground.  User windows can be anywhere.
- * Addwin() adds a window to one of the three groups.
+ * The windows are doubly linked in overlapping order and divided into
+ * two groups: foreground and normal.  Information
+ * windows are always foreground.  User windows can be either.
+ * Addwin() adds a window to the list at the top of one of the two groups.
  * Deletewin() deletes a window.  Front() moves a window to the front
  * Deletewin() deletes a window.  Front() moves a window to the front
- * of its group.  Wwadd() and wwdelete() should never be called
+ * of its group.  Wwopen(), wwadd(), and wwdelete() should never be called
  * directly.
  */
 
  * directly.
  */
 
@@ -24,8 +42,10 @@ static       char *sccsid = "@(#)win.c       3.4 84/03/29";
  * Open a user window.
  */
 struct ww *
  * Open a user window.
  */
 struct ww *
-openwin(id, row, col, nrow, ncol, nline, label)
+openwin(id, row, col, nrow, ncol, nline, label, haspty, hasframe, shf, sh)
 char *label;
 char *label;
+char haspty, hasframe;
+char *shf, **sh;
 {
        register struct ww *w;
 
 {
        register struct ww *w;
 
@@ -36,26 +56,31 @@ char *label;
                error("Illegal window position.");
                return 0;
        }
                error("Illegal window position.");
                return 0;
        }
-       if ((w = wwopen(WWO_PTY, nrow, ncol, row, col, nline)) == 0) {
-               error("%s.", wwerror());
+       w = wwopen(haspty ? WWO_PTY : WWO_SOCKET, nrow, ncol, row, col, nline);
+       if (w == 0) {
+               error("Can't open window: %s.", wwerror());
                return 0;
        }
        w->ww_id = id;
        window[id] = w;
                return 0;
        }
        w->ww_id = id;
        window[id] = w;
-       w->ww_hasframe = 1;
-       w->ww_altpos.r = 1;
-       w->ww_altpos.c = 0;
+       w->ww_hasframe = hasframe;
+       w->ww_alt = w->ww_w;
        if (label != 0 && setlabel(w, label) < 0)
                error("No memory for label.");
        wwcursor(w, 1);
        if (label != 0 && setlabel(w, label) < 0)
                error("No memory for label.");
        wwcursor(w, 1);
-       addwin(w, 1);
-       selwin = w;
-       reframe();
+       /*
+        * We have to do this little maneuver to make sure
+        * addwin() puts w at the top, so we don't waste an
+        * insert and delete operation.
+        */
+       setselwin((struct ww *)0);
+       addwin(w, 0);
+       setselwin(w);
        wwupdate();
        wwflush();
        wwupdate();
        wwflush();
-       if (wwspawn(w, shell, shellname, (char *)0) < 0) {
-               c_close(w);
-               error("%s: %s.", shell, wwerror());
+       if (wwspawn(w, shf, sh) < 0) {
+               error("Can't execute %s: %s.", shf, wwerror());
+               closewin(w);
                return 0;
        }
        return w;
                return 0;
        }
        return w;
@@ -74,23 +99,51 @@ findid()
        return i;
 }
 
        return i;
 }
 
+struct ww *
+findselwin()
+{
+       register struct ww *w, *s = 0;
+       register i;
+
+       for (i = 0; i < NWINDOW; i++)
+               if ((w = window[i]) != 0 && w != selwin &&
+                   (s == 0 ||
+                    !isfg(w) && (w->ww_order < s->ww_order || isfg(s))))
+                       s = w;
+       return s;
+}
+
 /*
 /*
- * Close a user window.
- * May leave selwin == 0.
+ * Close a user window.  Close all if w == 0.
  */
 closewin(w)
 register struct ww *w;
 {
  */
 closewin(w)
 register struct ww *w;
 {
-       if (w == selwin)
-               selwin = 0;
-       if (w == lastselwin)
-               lastselwin = 0;
-       if (w->ww_id >= 0 && w->ww_id < NWINDOW)
-               window[w->ww_id] = 0;
-       if (w->ww_label)
-               str_free(w->ww_label);
-       deletewin(w);
-       wwclose(w);
+       char didit = 0;
+       register i;
+
+       if (w != 0) {
+               closewin1(w);
+               didit++;
+       } else
+               for (i = 0; i < NWINDOW; i++) {
+                       if ((w = window[i]) == 0)
+                               continue;
+                       closewin1(w);
+                       didit++;
+               }
+       if (didit) {
+               if (selwin == 0)
+                       if (lastselwin != 0) {
+                               setselwin(lastselwin);
+                               lastselwin = 0;
+                       } else if (w = findselwin())
+                               setselwin(w);
+               if (lastselwin == 0 && selwin)
+                       if (w = findselwin())
+                               lastselwin = w;
+               reframe();
+       }
 }
 
 /*
 }
 
 /*
@@ -107,10 +160,12 @@ char *label;
        w->ww_mapnl = 1;
        w->ww_hasframe = 1;
        w->ww_nointr = 1;
        w->ww_mapnl = 1;
        w->ww_hasframe = 1;
        w->ww_nointr = 1;
+       w->ww_noupdate = 1;
+       w->ww_unctrl = 1;
        w->ww_id = -1;
        w->ww_center = 1;
        (void) setlabel(w, label);
        w->ww_id = -1;
        w->ww_center = 1;
        (void) setlabel(w, label);
-       addwin(w, 0);
+       addwin(w, 1);
        reframe();
        wwupdate();
        return w;
        reframe();
        wwupdate();
        return w;
@@ -122,25 +177,28 @@ char *label;
 closeiwin(w)
 struct ww *w;
 {
 closeiwin(w)
 struct ww *w;
 {
-       closewin(w);
+       closewin1(w);
        reframe();
 }
 
        reframe();
 }
 
-/*
- * Set the current window.
- */
-setselwin(w)
-struct ww *w;
+closewin1(w)
+register struct ww *w;
 {
 {
-       if (selwin == w)
-               return;
-       lastselwin = selwin;
-       front(selwin = w, 1);
+       if (w == selwin)
+               selwin = 0;
+       if (w == lastselwin)
+               lastselwin = 0;
+       if (w->ww_id >= 0 && w->ww_id < NWINDOW)
+               window[w->ww_id] = 0;
+       if (w->ww_label)
+               str_free(w->ww_label);
+       deletewin(w);
+       wwclose(w);
 }
 
 /*
  * Move the window to the top of its group.
 }
 
 /*
  * Move the window to the top of its group.
- * Don't do it, if already fully visible.
+ * Don't do it if already fully visible.
  * Wwvisible() doesn't work for tinted windows.
  * But anything to make it faster.
  * Always reframe() if doreframe is true.
  * Wwvisible() doesn't work for tinted windows.
  * But anything to make it faster.
  * Always reframe() if doreframe is true.
@@ -149,52 +207,30 @@ front(w, doreframe)
 register struct ww *w;
 char doreframe;
 {
 register struct ww *w;
 char doreframe;
 {
-       if (isfg(w)) {
-               if (w->ww_back != framewin && !wwvisible(w)) {
-                       deletewin(w);
-                       addwin(w, 0);
-                       doreframe = 1;
-               }
-       } else if (isbg(w)) {
-               if (w != bgwin && !wwvisible(w)) {
-                       deletewin(w);
-                       addwin(w, 3);
-                       doreframe = 1;
-               }
-       } else {
-               if (w->ww_back != fgwin && !wwvisible(w)) {
-                       deletewin(w);
-                       addwin(w, 1);
-                       doreframe = 1;
-               }
+       if (w->ww_back != (isfg(w) ? framewin : fgwin) && !wwvisible(w)) {
+               deletewin(w);
+               addwin(w, isfg(w));
+               doreframe = 1;
        }
        if (doreframe)
                reframe();
 }
 
 /*
        }
        if (doreframe)
                reframe();
 }
 
 /*
- * Add a window at one of four places.
+ * Add a window at the top of normal windows or foreground windows.
+ * For normal windows, we put it behind the current window.
  */
  */
-addwin(w, where)
+addwin(w, fg)
 register struct ww *w;
 register struct ww *w;
+char fg;
 {
 {
-       switch (where) {
-       case 0:         /* top of foreground windows */
+       if (fg) {
                wwadd(w, framewin);
                if (fgwin == framewin)
                        fgwin = w;
                wwadd(w, framewin);
                if (fgwin == framewin)
                        fgwin = w;
-               break;
-       case 1:         /* top of normal windows */
-               wwadd(w, fgwin);
-               break;
-       case 2:         /* bottom of normal windows */
-               wwadd(w, bgwin->ww_back);
-               break;
-       case 3:         /* top of background windows */
-               wwadd(w, bgwin->ww_back);
-               bgwin = w;
-               break;
-       }
+       } else
+               wwadd(w, selwin != 0 && selwin != w && !isfg(selwin)
+                               ? selwin : fgwin);
 }
 
 /*
 }
 
 /*
@@ -203,13 +239,8 @@ register struct ww *w;
 deletewin(w)
 register struct ww *w;
 {
 deletewin(w)
 register struct ww *w;
 {
-       if (isfg(w)) {
-               if (fgwin == w)
-                       fgwin = w->ww_back;
-       } else if (isbg(w)) {
-               if (bgwin == w)
-                       bgwin = w->ww_forw;
-       }
+       if (fgwin == w)
+               fgwin = w->ww_back;
        wwdelete(w);
 }
 
        wwdelete(w);
 }
 
@@ -251,6 +282,36 @@ register struct ww *w;
        }
 }
 
        }
 }
 
+stopwin(w)
+       register struct ww *w;
+{
+       w->ww_stopped = 1;
+       if (w->ww_pty >= 0 && w->ww_ispty)
+               (void) ioctl(w->ww_pty, TIOCSTOP, (char *)0);
+}
+
+startwin(w)
+       register struct ww *w;
+{
+       w->ww_stopped = 0;
+       if (w->ww_pty >= 0 && w->ww_ispty)
+               (void) ioctl(w->ww_pty, TIOCSTART, (char *)0);
+}
+
+sizewin(w, nrow, ncol)
+register struct ww *w;
+{
+       struct ww *back = w->ww_back;
+
+       w->ww_alt.nr = w->ww_w.nr;
+       w->ww_alt.nc = w->ww_w.nc;
+       wwdelete(w);
+       if (wwsize(w, nrow, ncol) < 0)
+               error("Can't resize window: %s.", wwerror());
+       wwadd(w, back);
+       reframe();
+}
+
 waitnl(w)
 struct ww *w;
 {
 waitnl(w)
 struct ww *w;
 {
@@ -262,23 +323,30 @@ register struct ww *w;
 char always;
 {
        int c;
 char always;
 {
        int c;
+       char uc = w->ww_unctrl;
 
        if (!always && w->ww_cur.r < w->ww_w.b - 2)
                return 0;
        c = waitnl1(w, "[Type escape to abort, any other key to continue]");
 
        if (!always && w->ww_cur.r < w->ww_w.b - 2)
                return 0;
        c = waitnl1(w, "[Type escape to abort, any other key to continue]");
+       w->ww_unctrl = 0;
        wwputs("\033E", w);
        wwputs("\033E", w);
-       return c == CTRL([) ? 2 : 1;
+       w->ww_unctrl = uc;
+       return c == ctrl('[') ? 2 : 1;
 }
 
 waitnl1(w, prompt)
 register struct ww *w;
 char *prompt;
 {
 }
 
 waitnl1(w, prompt)
 register struct ww *w;
 char *prompt;
 {
+       char uc = w->ww_unctrl;
+
+       w->ww_unctrl = 0;
        front(w, 0);
        front(w, 0);
-       wwprintf(w, "\033Y%c%c\033p%s\033q ",
+       wwprintf(w, "\033Y%c%c\033sA%s\033rA ",
                w->ww_w.nr - 1 + ' ', ' ', prompt);     /* print on last line */
        wwcurtowin(w);
        while (wwpeekc() < 0)
                wwiomux();
                w->ww_w.nr - 1 + ' ', ' ', prompt);     /* print on last line */
        wwcurtowin(w);
        while (wwpeekc() < 0)
                wwiomux();
+       w->ww_unctrl = uc;
        return wwgetc();
 }
        return wwgetc();
 }