home *** CD-ROM | disk | FTP | other *** search
- /* 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: resize.c,v 1.3 1993/08/04 00:42:51 mlschroe Exp $ FAU")
-
- #include <stdio.h>
- #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 && 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);
- }
-