diff options
author | jnweiger <jnweiger> | 2005-12-16 17:36:59 +0000 |
---|---|---|
committer | jnweiger <jnweiger> | 2005-12-16 17:36:59 +0000 |
commit | 21ceaf16bd7417cb58998db5a47869c0e11f6c62 (patch) | |
tree | f170f27e2754dbcf427f9c4ba816bf31ce31bc8b /src/resize.c | |
parent | a5c2d002715930526cf968553c73a317ac4086fd (diff) | |
download | screen-21ceaf16bd7417cb58998db5a47869c0e11f6c62.tar.gz |
historic version screen-3.5.2 Aug 19 1993
Diffstat (limited to 'src/resize.c')
-rw-r--r-- | src/resize.c | 621 |
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); +} |