summaryrefslogtreecommitdiff
path: root/src/resize.c
diff options
context:
space:
mode:
authorjnweiger <jnweiger>2005-12-16 17:36:59 +0000
committerjnweiger <jnweiger>2005-12-16 17:36:59 +0000
commit21ceaf16bd7417cb58998db5a47869c0e11f6c62 (patch)
treef170f27e2754dbcf427f9c4ba816bf31ce31bc8b /src/resize.c
parenta5c2d002715930526cf968553c73a317ac4086fd (diff)
downloadscreen-21ceaf16bd7417cb58998db5a47869c0e11f6c62.tar.gz
historic version screen-3.5.2 Aug 19 1993
Diffstat (limited to 'src/resize.c')
-rw-r--r--src/resize.c621
1 files changed, 621 insertions, 0 deletions
diff --git a/src/resize.c b/src/resize.c
new file mode 100644
index 0000000..a65a3b1
--- /dev/null
+++ b/src/resize.c
@@ -0,0 +1,621 @@
+/* Copyright (c) 1993
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * 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 2, 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 (see the file COPYING); if not, write to the
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************
+ */
+
+#include "rcs.h"
+RCS_ID("$Id$ FAU")
+
+#include <sys/types.h>
+#include <signal.h>
+#ifndef sun
+#include <sys/ioctl.h>
+#endif
+
+#ifdef ISC
+# include <sys/tty.h>
+# include <sys/sioctl.h>
+# include <sys/pty.h>
+#endif
+
+#include "config.h"
+#include "screen.h"
+#include "extern.h"
+
+static void CheckMaxSize __P((int));
+static int ResizeScreenArray __P((struct win *, char ***, int, int, int));
+static void FreeArray __P((char ***, int));
+#ifdef COPY_PASTE
+static int ResizeHistArray __P((struct win *, char ***, int, int, int));
+static void FreeScrollback __P((struct win *));
+#endif
+
+extern int maxwidth;
+extern struct display *display, *displays;
+extern char *blank, *null, *OldImage, *OldAttr;
+extern char *OldFont;
+extern struct win *windows;
+extern int Z0width, Z1width;
+
+#ifdef NETHACK
+extern int nethackflag;
+#endif
+
+#if defined(TIOCGWINSZ) || defined(TIOCSWINSZ)
+ struct winsize glwz;
+#endif
+
+/*
+ * ChangeFlag: 0: try to modify no window
+ * 1: modify fore (and try to modify no d_other) + redisplay
+ * 2: modify all windows
+ *
+ * Note: Activate() is only called if change_flag == 1
+ * i.e. on a WINCH event
+ */
+
+void
+CheckScreenSize(change_flag)
+int change_flag;
+{
+ int wi, he;
+ struct win *p;
+ struct layer *oldlay;
+
+ if (display == 0)
+ {
+ debug("CheckScreenSize: No display -> no check.\n");
+ return;
+ }
+ oldlay = d_lay;
+#ifdef TIOCGWINSZ
+ if (ioctl(d_userfd, TIOCGWINSZ, (char *)&glwz) != 0)
+ {
+ debug2("CheckScreenSize: ioctl(%d, TIOCGWINSZ) errno %d\n", d_userfd, errno);
+ wi = CO;
+ he = LI;
+ }
+ else
+ {
+ wi = glwz.ws_col;
+ he = glwz.ws_row;
+ if (wi == 0)
+ wi = CO;
+ if (he == 0)
+ he = LI;
+ }
+#else
+ wi = CO;
+ he = LI;
+#endif
+
+ debug2("CheckScreenSize: screen is (%d,%d)\n", wi, he);
+
+ if (change_flag == 2)
+ {
+ debug("Trying to adapt all windows (-A)\n");
+ for (p = windows; p; p = p->w_next)
+ if (p->w_display == 0 || p->w_display == display)
+ ChangeWindowSize(p, wi, he);
+ }
+ if (d_width == wi && d_height == he)
+ {
+ debug("CheckScreenSize: No change -> return.\n");
+ return;
+ }
+ ChangeScreenSize(wi, he, change_flag);
+ if (change_flag == 1)
+ Activate(d_fore ? d_fore->w_norefresh : 0);
+ if (d_lay != oldlay)
+ {
+#ifdef NETHACK
+ if (nethackflag)
+ Msg(0, "KAABLAMM!!! You triggered a land mine!");
+ else
+#endif
+ Msg(0, "Aborted because of window size change.");
+ }
+}
+
+void
+ChangeScreenSize(wi, he, change_fore)
+int wi, he;
+int change_fore;
+{
+ struct win *p;
+ int wwi;
+
+ if (d_width == wi && d_height == he)
+ {
+ debug("ChangeScreenSize: no change\n");
+ return;
+ }
+ debug2("ChangeScreenSize from (%d,%d) ", d_width, d_height);
+ debug3("to (%d,%d) (change_fore: %d)\n",wi, he, change_fore);
+ d_width = wi;
+ d_height = he;
+
+ CheckMaxSize(wi);
+ if (CWS)
+ {
+ d_defwidth = CO;
+ d_defheight = LI;
+ }
+ else
+ {
+ if (CZ0 && (wi == Z0width || wi == Z1width) &&
+ (CO == Z0width || CO == Z1width))
+ d_defwidth = CO;
+ else
+ d_defwidth = wi;
+ d_defheight = he;
+ }
+ debug2("Default size: (%d,%d)\n", d_defwidth, d_defheight);
+ if (change_fore)
+ DoResize(wi, he);
+ if (CWS == NULL && displays->_d_next == 0)
+ {
+ /* adapt all windows - to be removed ? */
+ for (p = windows; p; p = p->w_next)
+ {
+ debug1("Trying to change window %d.\n", p->w_number);
+ wwi = wi;
+ if (CZ0 && (wi == Z0width || wi == Z1width))
+ {
+ if (p->w_width > (Z0width + Z1width) / 2)
+ wwi = Z0width;
+ else
+ wwi = Z1width;
+ }
+ ChangeWindowSize(p, wwi, he);
+ }
+ }
+}
+
+void
+DoResize(wi, he)
+int wi, he;
+{
+ struct layer *oldlay;
+ int q = 0;
+
+ for(;;)
+ {
+ oldlay = d_lay;
+ for (; d_lay; d_lay = d_lay->l_next)
+ {
+ d_layfn = d_lay->l_layfn;
+ if ((q = Resize(wi, he)))
+ break;
+ }
+ d_lay = oldlay;
+ d_layfn = d_lay->l_layfn;
+ if (q == 0)
+ break;
+ ExitOverlayPage();
+ }
+}
+
+#ifdef COPY_PASTE
+
+int
+ChangeScrollback(p, histheight, histwidth)
+struct win *p;
+int histheight, histwidth;
+{
+ if (histheight > MAXHISTHEIGHT)
+ histheight = MAXHISTHEIGHT;
+ debug2("ChangeScrollback(..., %d, %d)\n", histheight, histwidth);
+ debug2(" was %d, %d\n", p->w_histheight, p->w_width);
+
+ if (histheight == 0)
+ {
+ FreeScrollback(p);
+ return 0;
+ }
+
+ if (ResizeHistArray(p, &p->w_ihist, histwidth, histheight, 1)
+ || ResizeHistArray(p, &p->w_ahist, histwidth, histheight, 0)
+ || ResizeHistArray(p, &p->w_fhist, histwidth, histheight, 0))
+ {
+ debug(" failed, removing all histbuf\n");
+ FreeScrollback(p);
+ Msg(0, strnomem);
+ return -1;
+ }
+ if (p->w_histheight != histheight)
+ p->w_histidx = 0;
+ p->w_histheight = histheight;
+
+ return 0;
+}
+
+static void
+FreeScrollback(p)
+struct win *p;
+{
+ FreeArray(&p->w_ihist, p->w_histheight);
+ FreeArray(&p->w_ahist, p->w_histheight);
+ FreeArray(&p->w_fhist, p->w_histheight);
+ p->w_histheight = 0;
+}
+
+static int
+ResizeHistArray(p, arr, wi, hi, fillblank)
+struct win *p;
+char ***arr;
+int wi, hi, fillblank;
+{
+ char **narr, **np, **onp, **onpe;
+ int t, x, first;
+
+ if (p->w_width == wi && p->w_histheight == hi)
+ return(0);
+ if (p->w_histheight != hi)
+ {
+ if ((narr = (char **)calloc(sizeof(char *), hi)) == NULL)
+ {
+ FreeArray(arr, p->w_histheight);
+ return(-1);
+ }
+ np = narr;
+ onp = (*arr) + p->w_histidx;
+ onpe = (*arr) + p->w_histheight;
+ first = p->w_histheight - hi;
+ if (first < 0)
+ np -= first;
+ for(t = 0; t < p->w_histheight; t++)
+ {
+ ASSERT(*onp);
+ if (t - first >= 0 && t - first < hi)
+ *np++ = *onp;
+ else if (*onp != null)
+ free(*onp);
+ if (++onp == onpe)
+ onp = *arr;
+ }
+ if (*arr)
+ free(*arr);
+ }
+ else
+ narr = *arr;
+
+ for (t=0, np=narr; t < hi; t++, np++)
+ {
+ if ((!fillblank && *np == 0) || *np == null)
+ {
+ *np = null;
+ continue;
+ }
+ x = p->w_width;
+ if (*np == 0)
+ {
+ *np = (char *)malloc(wi + 1);
+ x = 0;
+ }
+ else if (p->w_width != wi)
+ {
+ *np = (char *)xrealloc(*np, wi + 1);
+ }
+ if (*np == 0)
+ {
+ FreeArray(&narr, hi);
+ return -1;
+ }
+ if (x > wi)
+ x = wi;
+ if (fillblank)
+ bclear(*np + x, wi + 1 - x);
+ else
+ bzero(*np + x, wi + 1 - x);
+ }
+ *arr = narr;
+ return 0;
+}
+#endif /* COPY_PASTE */
+
+
+static int
+ResizeScreenArray(p, arr, wi, hi, fillblank)
+struct win *p;
+char ***arr;
+int wi, hi, fillblank;
+{
+ int minr;
+ char **cp;
+
+ if (p->w_width == wi && p->w_height == hi)
+ return(0);
+
+ if (hi > p->w_height)
+ minr = p->w_height;
+ else
+ minr = hi;
+
+ if (p->w_height > hi)
+ {
+ for (cp = *arr; cp < *arr + (p->w_height - hi); cp++)
+ if (*cp != null)
+ free(*cp);
+ bcopy((char *)(*arr + (p->w_height - hi)), (char *)(*arr),
+ hi * sizeof(char *));
+ }
+ if (*arr && p->w_width != wi)
+ for (cp = *arr; cp < *arr + minr; cp++)
+ {
+ int x = p->w_width;
+
+ if (*cp == null)
+ continue;
+ if ((*cp = (char *)xrealloc(*cp, (unsigned) wi + 1)) == 0)
+ {
+ FreeArray(arr, p->w_height);
+ return(-1);
+ }
+ if (x > wi)
+ x = wi;
+ if (fillblank)
+ bclear(*cp + x, wi + 1 - x);
+ else
+ bzero(*cp + x, wi + 1 - x);
+ }
+ if (*arr)
+ *arr = (char **) xrealloc((char *) *arr, (unsigned) hi * sizeof(char *));
+ else
+ *arr = (char **) malloc((unsigned) hi * sizeof(char *));
+ if (*arr == NULL)
+ return -1;
+ for (cp = *arr + p->w_height; cp < *arr + hi; cp++)
+ {
+ if (!fillblank)
+ {
+ *cp = null;
+ continue;
+ }
+ if ((*cp = malloc((unsigned) wi + 1)) == 0)
+ {
+ while (--cp >= *arr)
+ free(*cp);
+ free(*arr);
+ *arr = NULL;
+ return -1;
+ }
+ bclear(*cp, wi + 1);
+ }
+ return 0;
+}
+
+static void
+FreeArray(arr, hi)
+char ***arr;
+int hi;
+{
+ register char **p;
+ register int t;
+
+ if (*arr == 0)
+ return;
+ for (t = hi, p = *arr; t--; p++)
+ if (*p && *p != null)
+ free(*p);
+ free(*arr);
+ *arr = 0;
+}
+
+
+static void
+CheckMaxSize(wi)
+int wi;
+{
+ char *oldnull = null;
+ struct win *p;
+ int i;
+
+ wi = ((wi + 1) + 255) & ~255;
+ if (wi <= maxwidth)
+ return;
+ maxwidth = wi;
+ debug1("New maxwidth: %d\n", maxwidth);
+ if (blank == 0)
+ blank = malloc((unsigned) maxwidth);
+ else
+ blank = xrealloc(blank, (unsigned) maxwidth);
+ if (null == 0)
+ null = malloc((unsigned) maxwidth);
+ else
+ null = xrealloc(null, (unsigned) maxwidth);
+ if (OldImage == 0)
+ OldImage = malloc((unsigned) maxwidth);
+ else
+ OldImage = xrealloc(OldImage, (unsigned) maxwidth);
+ if (OldAttr == 0)
+ OldAttr = malloc((unsigned) maxwidth);
+ else
+ OldAttr = xrealloc(OldAttr, (unsigned) maxwidth);
+ if (OldFont == 0)
+ OldFont = malloc((unsigned) maxwidth);
+ else
+ OldFont = xrealloc(OldFont, (unsigned) maxwidth);
+ if (!(blank && null && OldImage && OldAttr && OldFont))
+ {
+ Panic(0, "Out of memory -> Game over!!");
+ /*NOTREACHED*/
+ }
+ MakeBlankLine(blank, maxwidth);
+ bzero(null, maxwidth);
+
+ /* We have to run through all windows to substitute
+ * the null references.
+ */
+ for (p = windows; p; p = p->w_next)
+ {
+ for (i = 0; i < p->w_height; i++)
+ {
+ if (p->w_attr[i] == oldnull)
+ p->w_attr[i] = null;
+ if (p->w_font[i] == oldnull)
+ p->w_font[i] = null;
+ }
+#ifdef COPY_PASTE
+ for (i = 0; i < p->w_histheight; i++)
+ {
+ if (p->w_ahist[i] == oldnull)
+ p->w_ahist[i] = null;
+ if (p->w_fhist[i] == oldnull)
+ p->w_fhist[i] = null;
+ }
+#endif
+ }
+}
+
+
+int
+ChangeWindowSize(p, wi, he)
+struct win *p;
+int wi, he;
+{
+ int t, scr;
+
+ CheckMaxSize(wi);
+
+ if (wi == p->w_width && he == p->w_height)
+ {
+ debug("ChangeWindowSize: No change.\n");
+ return 0;
+ }
+
+ debug2("ChangeWindowSize from (%d,%d) to ", p->w_width, p->w_height);
+ debug2("(%d,%d)\n", wi, he);
+ if (p->w_lay != &p->w_winlay)
+ {
+ debug("ChangeWindowSize: No resize because of overlay.\n");
+ return -1;
+ }
+ if (wi == 0 && he == 0)
+ {
+ FreeArray(&p->w_image, p->w_height);
+ FreeArray(&p->w_attr, p->w_height);
+ FreeArray(&p->w_font, p->w_height);
+ if (p->w_tabs)
+ free(p->w_tabs);
+ p->w_tabs = NULL;
+ p->w_width = 0;
+ p->w_height = 0;
+#ifdef COPY_PASTE
+ FreeScrollback(p);
+#endif
+ return 0;
+ }
+
+ /* when window gets smaller, scr is the no. of lines we scroll up */
+ scr = p->w_height - he;
+ if (scr < 0)
+ scr = 0;
+#ifdef COPY_PASTE
+ for (t = 0; t < scr; t++)
+ AddLineToHist(p, p->w_image+t, p->w_attr+t, p->w_font+t);
+#endif
+ if (ResizeScreenArray(p, &p->w_image, wi, he, 1)
+ || ResizeScreenArray(p, &p->w_attr, wi, he, 0)
+ || ResizeScreenArray(p, &p->w_font, wi, he, 0))
+ {
+nomem: KillWindow(p);
+ Msg(0, "Out of memory -> Window destroyed !!");
+ return -1;
+ }
+ /* this won't change the d_height of the scrollback history buffer, but
+ * it will check the d_width of the lines.
+ */
+#ifdef COPY_PASTE
+ ChangeScrollback(p, p->w_histheight, wi);
+#endif
+
+ if (p->w_tabs == 0)
+ {
+ /* tabs get d_width+1 because 0 <= x <= wi */
+ if ((p->w_tabs = malloc((unsigned) wi + 1)) == 0)
+ goto nomem;
+ t = 8;
+ }
+ else
+ {
+ if ((p->w_tabs = xrealloc(p->w_tabs, (unsigned) wi + 1)) == 0)
+ goto nomem;
+ t = p->w_width;
+ }
+ for (t = (t + 7) & 8; t < wi; t += 8)
+ p->w_tabs[t] = 1;
+ p->w_height = he;
+ p->w_width = wi;
+ if (p->w_x >= wi)
+ p->w_x = wi - 1;
+ if ((p->w_y -= scr) < 0)
+ p->w_y = 0;
+ if (p->w_Saved_x >= wi)
+ p->w_Saved_x = wi - 1;
+ if ((p->w_Saved_y -= scr) < 0)
+ p->w_Saved_y = 0;
+ if (p->w_autoaka > 0)
+ if ((p->w_autoaka -= scr) < 1)
+ p->w_autoaka = 1;
+ p->w_top = 0;
+ p->w_bot = he - 1;
+#ifdef TIOCSWINSZ
+ if (p->w_ptyfd >= 0 && p->w_pid)
+ {
+ glwz.ws_col = wi;
+ glwz.ws_row = he;
+ debug("Setting pty winsize.\n");
+ if (ioctl(p->w_ptyfd, TIOCSWINSZ, (char *)&glwz))
+ debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->w_ptyfd);
+# if defined(STUPIDTIOCSWINSZ) && defined(SIGWINCH)
+# ifdef POSIX
+ pgrp = tcgetpgrp(p->w_ptyfd);
+# else /* POSIX */
+ if (ioctl(p->w_ptyfd, TIOCGPGRP, (char *)&pgrp))
+ pgrp = 0;
+# endif /* POSIX */
+ if (pgrp)
+ {
+ debug1("Sending SIGWINCH to pgrp %d.\n", pgrp);
+ if (killpg(pgrp, SIGWINCH))
+ debug1("killpg: errno %d\n", errno);
+ }
+ else
+ debug1("Could not get pgrp: errno %d\n", errno);
+# endif /* STUPIDTIOCSWINSZ */
+ }
+#endif /* TIOCSWINSZ */
+ return 0;
+}
+
+
+char *
+xrealloc(mem, len)
+char *mem;
+int len;
+{
+ register char *nmem;
+
+ if ((nmem = realloc(mem, len)))
+ return(nmem);
+ free(mem);
+ return((char *)0);
+}