This is window.c in view mode; [Download] [Up]
/* Copyright (c) 1991 * 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 1, 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. * * Noteworthy contributors to screen's design and implementation: * Wayne Davison (davison@borland.com) * Patrick Wolfe (pat@kai.com, kailand!pat) * Bart Schaefer (schaefer@cse.ogi.edu) * Nathan Glasser (nathan@brokaw.lcs.mit.edu) * Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu) * Howard Chu (hyc@hanauma.jpl.nasa.gov) * Tim MacKenzie (tym@dibbler.cs.monash.edu.au) * Markku Jarvinen (mta@{cc,cs,ee}.tut.fi) * Marc Boucher (marc@CAM.ORG) * **************************************************************** */ #ifndef lint static char rcs_id[] = "$Id: window.c,v 1.2 92/02/03 02:28:20 jnweiger Exp $ FAU"; #endif #include <stdio.h> #include <sys/types.h> #include <signal.h> #ifndef sun #include <sys/ioctl.h> #endif #ifdef BSDI # include <string.h> #endif /* BSDI */ #ifdef ISC # include <sys/tty.h> # include <sys/sioctl.h> # include <sys/pty.h> #endif #ifdef MIPS extern int errno; #endif #include "config.h" #include "screen.h" #include "extern.h" static void FreeScrollback __P((struct win *)); static int ResizeHistArray __P((struct win *, char ***, int, int, int)); static int ResizeScreenArray __P((struct win *, char ***, int, int, int)); static void FreeArray __P((char ***, int)); extern TermcapCOLS, TermcapROWS; extern int maxwidth; extern int default_width, default_height, screenwidth, screenheight; extern char *blank, *null, *OldImage, *OldAttr; extern char *OldFont, *LastMsg; extern struct win *wtab[], *fore; extern int WinList, ForeNum; extern char *Z0, *Z1, *WS; extern int Z0width, Z1width; extern int Detached; #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ) struct winsize glwz; #endif /* * ChangeFlag: 0: try to modify no window * 1: modify fore (and try to modify no other) * 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 width, height, n; struct win *p; if (Detached) { debug("CheckScreenSize: Detached -> No check.\n"); return; } #ifdef TIOCGWINSZ if (ioctl(0, TIOCGWINSZ, &glwz) != 0) { debug1("CheckScreenSize: ioctl(0, TIOCGWINSZ) errno %d\n", errno); width = TermcapCOLS; height = TermcapROWS; } else { width = glwz.ws_col; height = glwz.ws_row; if (width == 0) width = TermcapCOLS; if (height == 0) height = TermcapROWS; } #else width = TermcapCOLS; height = TermcapROWS; #endif debug2("CheckScreenSize: screen is (%d,%d)\n", width, height); if (change_flag == 2) { for (n = WinList; n != -1; n = p->WinLink) { p = wtab[n]; ChangeWindowSize(p, width, height); } } if (screenwidth == width && screenheight == height) { debug("CheckScreenSize: No change -> return.\n"); return; } ChangeScreenSize(width, height, change_flag); if (change_flag == 1 && WinList != -1) /* was HasWindow */ Activate(fore->norefresh); } void ChangeScreenSize(width, height, change_fore) int width, height; int change_fore; { struct win *p; int n, wwi; if (screenwidth == width && screenheight == height) { debug("ChangeScreenSize: no change\n"); return; } debug3("ChangeScreenSize to (%d,%d) (change_fore: %d)\n",width, height, change_fore); screenwidth = width; screenheight = height; if (WS) { default_width = TermcapCOLS; default_height = TermcapROWS; } else { if (Z0 && (width == Z0width || width == Z1width) && (TermcapCOLS == Z0width || TermcapCOLS == Z1width)) default_width = TermcapCOLS; else default_width = width; default_height = height; } debug2("Default size: (%d,%d)\n",default_width, default_height); if (change_fore) { if (WinList != -1 && change_fore) /* was HasWindow */ { debug("Trying to change fore.\n"); ChangeWindowSize(fore, width, height); } } if (WS == NULL) { /* We have to adapt all windows */ for (n = WinList; n != -1; n = p->WinLink) { p = wtab[n]; debug1("Trying to change window %d.\n",n); wwi = width; if (Z0 && (width==Z0width || width==Z1width)) { if (p->width > (Z0width + Z1width) / 2) wwi = Z0width; else wwi = Z1width; } ChangeWindowSize(p, wwi, height); } } } 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->histheight, p->width); if (histheight == 0) { FreeScrollback(p); return 0; } if (ResizeHistArray(p, &p->ihist, histwidth, histheight, 1) || ResizeHistArray(p, &p->ahist, histwidth, histheight, 0) || ResizeHistArray(p, &p->fhist, histwidth, histheight, 0)) { debug(" failed, removing all histbuf\n"); FreeScrollback(p); Msg_nomem; return (-1); } if (p->histheight != histheight) p->histidx = 0; p->histheight = histheight; return(0); } static void FreeScrollback(p) struct win *p; { FreeArray(&p->ihist, p->histheight); FreeArray(&p->ahist, p->histheight); FreeArray(&p->fhist, p->histheight); p->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->width == wi && p->histheight == hi) return(0); if (p->histheight != hi) { if ((narr = (char **)calloc(sizeof(char *), hi)) == NULL) { FreeArray(arr, p->histheight); return(-1); } np = narr; onp = (*arr) + p->histidx; onpe = (*arr) + p->histheight; first = p->histheight - hi; if (first<0) np-=first; for(t=0; t<p->histheight; t++) { if (t-first >=0 && t-first < hi) *np++ = *onp; else Free(*onp); if (++onp == onpe) onp = *arr; } if (*arr) Free(*arr); } else narr = *arr; for (t=0, np=narr; t<hi; t++, np++) { x = p->width; if (*np == 0) { *np = (char *)malloc(wi); x = 0; } else if (p->width != wi) { *np = (char *)xrealloc(*np, wi); } if (*np == 0) { FreeArray(&narr, hi); return(-1); } if (x<wi) { if (fillblank) bclear(*np+x, wi-x); else bzero(*np+x, wi-x); } } *arr = narr; return(0); } static int ResizeScreenArray(p, arr, wi, hi, fillblank) struct win *p; char ***arr; int wi, hi, fillblank; { int minr; char **cp; if (p->width == wi && p->height == hi) return(0); if (hi > p->height) minr = p->height; else minr = hi; if (p->height > hi) { for (cp = *arr; cp < *arr + (p->height - hi); cp++) Free(*cp); bcopy((char *)(*arr + (p->height - hi)), (char *)(*arr), hi * sizeof(char *)); } if (*arr && p->width != wi) for (cp = *arr; cp < *arr + minr; cp++) { if ((*cp = (char *)xrealloc(*cp, (unsigned) wi)) == 0) { FreeArray(arr, p->height); return(-1); } if (wi > p->width) { if (fillblank) bclear(*cp + p->width, wi - p->width); else bzero(*cp + p->width, wi - p->width); } } if (*arr) *arr = (char **) xrealloc((char *) *arr, (unsigned) hi * sizeof(char *)); else *arr = (char **) malloc((unsigned) hi * sizeof(char *)); if (*arr == 0) return(-1); for (cp = *arr + p->height; cp < *arr + hi; cp++) { if ((*cp = malloc((unsigned) wi)) == 0) { while (--cp >= *arr) Free(*cp); Free(*arr); return(-1); } if (fillblank) bclear(*cp, wi); else bzero(*cp, wi); } 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) Free(*p); Free(*arr); } int ChangeWindowSize(p, width, height) struct win *p; int width, height; { int t, scr; if (width > maxwidth) { maxwidth = width; 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 (LastMsg == 0) { LastMsg = malloc((unsigned) maxwidth + 1); *LastMsg = 0; } else LastMsg = xrealloc(LastMsg, (unsigned) maxwidth + 1); LastMsg[maxwidth]=0; if (!(blank && null && OldImage && OldAttr && OldFont && LastMsg)) { nomem: for (t = WinList; t != -1 && wtab[t] != p; t = p->WinLink) ; if (t >= 0) KillWindow(t); Msg(0, "Out of memory -> Window destroyed !!"); return(-1); } MakeBlankLine(blank, maxwidth); bzero(null, maxwidth); } if (width == p->width && height == p->height) { debug("ChangeWindowSize: No change.\n"); return(0); } debug2("ChangeWindowSize from (%d,%d) to ", p->width, p->height); debug2("(%d,%d)\n", width, height); if (width == 0 && height == 0) { FreeArray(&p->image, p->height); FreeArray(&p->attr, p->height); FreeArray(&p->font, p->height); if (p->tabs) Free(p->tabs); p->width = 0; p->height = 0; FreeScrollback(p); return(0); } /* when window gets smaller, scr is the no. of lines we scroll up */ scr = p->height - height; if (scr < 0) scr = 0; for (t = 0; t < scr; t++) AddLineToHist(p, p->image+t, p->attr+t, p->font+t); if (ResizeScreenArray(p, &p->image, width, height, 1) || ResizeScreenArray(p, &p->attr, width, height, 0) || ResizeScreenArray(p, &p->font, width, height, 0)) { goto nomem; } /* this won't change the height of the scrollback history buffer, but * it will check the width of the lines. */ ChangeScrollback(p, p->histheight, width); if (p->tabs == 0) { /* tabs get width+1 because 0 <= x <= width */ if ((p->tabs = malloc((unsigned) width + 1)) == 0) goto nomem; t = 8; } else { if ((p->tabs = xrealloc(p->tabs, (unsigned) width + 1)) == 0) goto nomem; t = p->width; } for (t = (t + 7) & 8; t < width; t += 8) p->tabs[t] = 1; p->height = height; p->width = width; if (p->x >= width) p->x = width - 1; if ((p->y -= scr) < 0) p->y = 0; if (p->Saved_x >= width) p->Saved_x = width - 1; if ((p->Saved_y -= scr) < 0) p->Saved_y = 0; if (p->autoaka > 0) if ((p->autoaka -= scr) < 1) p->autoaka = 1; p->top = 0; p->bot = height - 1; #ifdef TIOCSWINSZ if (p->ptyfd && p->wpid) { glwz.ws_col = width; glwz.ws_row = height; debug("Setting pty winsize.\n"); if (ioctl(p->ptyfd, TIOCSWINSZ, &glwz)) debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->ptyfd); # if defined(STUPIDTIOCSWINSZ) && defined(SIGWINCH) # ifdef POSIX pgrp = tcgetpgrp(p->ptyfd); # else if (ioctl(p->ptyfd, TIOCGPGRP, &pgrp)) pgrp = 0; # endif 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 return(0); } void ResizeScreen(wi) struct win *wi; { int width, height; if (wi) { width = wi->width; height = wi->height; } else { width = default_width; height = default_height; } if (screenwidth == width && screenheight == height) { debug("ResizeScreen: No change\n"); return; } debug2("ResizeScreen: to (%d,%d).\n", width, height); if (WS) { debug("ResizeScreen: using WS\n"); WSresize(width, height); ChangeScreenSize(width, height, 0); } else if (Z0 && (width == Z0width || width == Z1width)) { debug("ResizeScreen: using Z0/Z1\n"); PutStr(width == Z0width ? Z0 : Z1); ChangeScreenSize(width, screenheight, 0); } if (screenwidth != width || screenheight != height) { debug2("BUG: Cannot resize from (%d,%d)",screenwidth, screenheight); debug2(" to (%d,%d) !!\n", width, height); if (wi) ChangeWindowSize(wi, screenwidth, screenheight); } } char * xrealloc(mem, len) char *mem; int len; { register char *nmem; if (nmem = realloc(mem, len)) return(nmem); free(mem); return((char *)0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.