home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume25 / screen3 / part03 / window.c < prev   
C/C++ Source or Header  |  1991-12-18  |  14KB  |  593 lines

  1. /* Copyright (c) 1991
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 1, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  * Noteworthy contributors to screen's design and implementation:
  21.  *    Wayne Davison (davison@borland.com)
  22.  *    Patrick Wolfe (pat@kai.com, kailand!pat)
  23.  *    Bart Schaefer (schaefer@cse.ogi.edu)
  24.  *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  25.  *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  26.  *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  27.  *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  28.  *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  29.  *    Marc Boucher (marc@CAM.ORG)
  30.  *
  31.  ****************************************************************
  32.  */
  33.  
  34. #ifndef lint
  35.   static char rcs_id[] = "$Id: window.c,v 1.22 91/10/08 15:11:00 mlschroe Exp $ FAU";
  36. #endif
  37.  
  38. #include <stdio.h>
  39. #include <sys/types.h>
  40. #include <signal.h>
  41. #ifndef sun
  42. #include <sys/ioctl.h>
  43. #endif
  44.  
  45. #ifdef MIPS
  46. extern int errno;
  47. #endif
  48.  
  49. #include "config.h"
  50. #include "screen.h"
  51. #include "extern.h"
  52.  
  53. static void FreeScrollback __P((struct win *));
  54.  
  55. static int ResizeHistArray __P((struct win *, char ***, int, int, int));
  56. static int ResizeScreenArray __P((struct win *, char ***, int, int, int));
  57. static void FreeArray __P((char ***, int));
  58.  
  59. extern TermcapCOLS, TermcapROWS;
  60. extern int maxwidth;
  61. extern int default_width, default_height, screenwidth, screenheight;
  62. extern char *blank, *null, *OldImage, *OldAttr;
  63. extern char *OldFont, *LastMsg;
  64. extern struct win *wtab[], *fore;
  65. extern int WinList, ForeNum;
  66. extern char *Z0, *Z1, *WS;
  67. extern int Z0width, Z1width;
  68.  
  69. extern int Detached;
  70.  
  71. #ifdef TIOCSWINSZ
  72.   struct winsize glwz;
  73. #endif
  74.  
  75. /*
  76.  * ChangeFlag:   0: try to modify no window
  77.  *               1: modify fore (and try to modify no other)
  78.  *               2: modify all windows
  79.  *
  80.  * Note: Activate() is only called if change_flag == 1
  81.  *       i.e. on a WINCH event
  82.  */
  83.  
  84. void
  85. CheckScreenSize(change_flag)
  86. int change_flag;
  87. {
  88.   int width, height, n;
  89.   struct win *p;
  90.  
  91.   if (Detached)
  92.     {
  93.       debug("CheckScreenSize: Detached -> No check.\n");
  94.       return;
  95.     }
  96. #ifdef TIOCSWINSZ
  97.   if (ioctl(0, TIOCGWINSZ, &glwz) != 0)
  98.     {
  99.       debug1("CheckScreenSize: ioctl(0, TIOCGWINSZ) errno %d\n", errno);
  100.       width = TermcapCOLS;
  101.       height = TermcapROWS;
  102.     }
  103.   else
  104.     {
  105.       width = glwz.ws_col;
  106.       height = glwz.ws_row;
  107.       if (width == 0)
  108.         width = TermcapCOLS;
  109.       if (height == 0)
  110.         height = TermcapROWS;
  111.     }
  112. #else
  113.   width = TermcapCOLS;
  114.   height = TermcapROWS;
  115. #endif
  116.   
  117.   debug2("CheckScreenSize: screen is (%d,%d)\n", width, height);
  118.  
  119.   if (change_flag == 2)
  120.     {
  121.       for (n = WinList; n != -1; n = p->WinLink)
  122.         {
  123.           p = wtab[n];
  124.           ChangeWindowSize(p, width, height);
  125.     }
  126.     }
  127.   if (screenwidth == width && screenheight == height)
  128.     {
  129.       debug("CheckScreenSize: No change -> return.\n");
  130.       return;
  131.     }
  132.   ChangeScreenSize(width, height, change_flag);
  133.   if (change_flag == 1 && WinList != -1)    /* was HasWindow */
  134.     Activate ();
  135. }
  136.  
  137. void
  138. ChangeScreenSize(width, height, change_fore)
  139. int width, height;
  140. int change_fore;
  141. {
  142.   struct win *p;
  143.   int n, wwi;
  144.  
  145.   if (screenwidth == width && screenheight == height)
  146.     {
  147.       debug("ChangeScreenSize: no change\n");
  148.       return;
  149.     }
  150.   debug3("ChangeScreenSize to (%d,%d) (change_fore: %d)\n",width, height, change_fore);
  151.   screenwidth = width;
  152.   screenheight = height;
  153.  
  154.   if (WS)
  155.     {
  156.       default_width = TermcapCOLS;
  157.       default_height = TermcapROWS;
  158.     }
  159.   else
  160.     {
  161.       if (Z0 && (width == Z0width || width == Z1width) &&
  162.           (TermcapCOLS == Z0width || TermcapCOLS == Z1width))
  163.         default_width = TermcapCOLS;
  164.       else
  165.         default_width = width;
  166.       default_height = height;
  167.     }
  168.   debug2("Default size: (%d,%d)\n",default_width, default_height);
  169.   if (change_fore)
  170.     {
  171.       if (WinList != -1 && change_fore) /* was HasWindow */
  172.         {
  173.           debug("Trying to change fore.\n");
  174.           ChangeWindowSize(fore, width, height);
  175.         }
  176.     }
  177.   if (WS == NULL)
  178.     {
  179.       /* We have to adapt all windows */
  180.       for (n = WinList; n != -1; n = p->WinLink)
  181.         {
  182.           p = wtab[n];
  183.           debug1("Trying to change window %d.\n",n);
  184.           wwi = width;
  185.           if (Z0 && (width==Z0width || width==Z1width))
  186.         {
  187.           if (p->width > (Z0width + Z1width) / 2)
  188.         wwi = Z0width;
  189.           else
  190.         wwi = Z1width;
  191.         }
  192.           ChangeWindowSize(p, wwi, height);
  193.         }
  194.     }
  195. }
  196.  
  197. int
  198. ChangeScrollback(p, histheight, histwidth)
  199. struct win *p;
  200. int histheight, histwidth;
  201. {
  202.   if (histheight > MAXHISTHEIGHT)
  203.     histheight = MAXHISTHEIGHT;
  204.   debug2("ChangeScrollback(..., %d, %d)\n", histheight, histwidth);
  205.   debug2("  was %d, %d\n", p->histheight, p->width);
  206.  
  207.   if (histheight == 0)
  208.     {
  209.       FreeScrollback(p);
  210.       return 0;
  211.     }
  212.  
  213.   if (ResizeHistArray(p, &p->ihist, histwidth, histheight, 1)
  214.       || ResizeHistArray(p, &p->ahist, histwidth, histheight, 0)
  215.       || ResizeHistArray(p, &p->fhist, histwidth, histheight, 0))
  216.     {
  217.       debug("   failed, removing all histbuf\n");
  218.       FreeScrollback(p);
  219.       Msg_nomem;
  220.       return (-1);
  221.     }
  222.   if (p->histheight != histheight)
  223.     p->histidx = 0;
  224.   p->histheight = histheight;
  225.  
  226.   return(0);
  227. }
  228.  
  229. static void FreeScrollback(p)
  230. struct win *p;
  231. {
  232.   FreeArray(&p->ihist, p->histheight);
  233.   FreeArray(&p->ahist, p->histheight);
  234.   FreeArray(&p->fhist, p->histheight);
  235.   p->histheight = 0;
  236. }
  237.  
  238. static int
  239. ResizeHistArray(p, arr, wi, hi, fillblank)
  240. struct win *p;
  241. char ***arr;
  242. int wi, hi, fillblank;
  243. {
  244.   char **narr, **np, **onp, **onpe;
  245.   int t, x, first;
  246.  
  247.   if (p->width == wi && p->histheight == hi)
  248.     return(0);
  249.   if (p->histheight != hi)
  250.     {
  251.       if ((narr = (char **)calloc(sizeof(char *), hi)) == NULL)
  252.     {
  253.       FreeArray(arr, p->histheight);
  254.       return(-1);
  255.     }
  256.       np = narr;
  257.       onp = (*arr) + p->histidx;
  258.       onpe = (*arr) + p->histheight;
  259.       first = p->histheight - hi;
  260.       if (first<0)
  261.      np-=first;
  262.       for(t=0; t<p->histheight; t++)
  263.     {
  264.           if (t-first >=0 && t-first < hi)
  265.         *np++ = *onp;
  266.       else
  267.         Free(*onp);
  268.       if (++onp == onpe)
  269.         onp = *arr;
  270.     }
  271.       if (*arr)
  272.     Free(*arr);
  273.     }
  274.   else
  275.     narr = *arr;
  276.  
  277.   for (t=0, np=narr; t<hi; t++, np++)
  278.     {
  279.       x = p->width;
  280.       if (*np == 0)
  281.     {
  282.       *np = (char *)malloc(wi);
  283.           x = 0;
  284.     }
  285.       else if (p->width != wi)
  286.     {
  287.       *np = (char *)xrealloc(*np, wi);
  288.     }
  289.       if (*np == 0)
  290.     {
  291.       FreeArray(&narr, hi);
  292.       return(-1);
  293.     }
  294.       if (x<wi)
  295.     {
  296.       if (fillblank)
  297.         bclear(*np+x, wi-x);
  298.       else
  299.         bzero(*np+x, wi-x);
  300.     }
  301.     }
  302.   *arr = narr;
  303.   return(0);
  304. }
  305.       
  306.  
  307. static int
  308. ResizeScreenArray(p, arr, wi, hi, fillblank)
  309. struct win *p;
  310. char ***arr;
  311. int wi, hi, fillblank;
  312. {
  313.   int minr;
  314.   char **cp;
  315.  
  316.   if (p->width == wi && p->height == hi)
  317.     return(0);
  318.  
  319.   if (hi > p->height)
  320.     minr = p->height;
  321.   else
  322.     minr = hi;
  323.  
  324.   if (p->height > hi)
  325.     {
  326.       for (cp = *arr; cp < *arr + (p->height - hi); cp++)
  327.     Free(*cp);
  328.       bcopy((char *)(*arr + (p->height - hi)), (char *)(*arr),
  329.         hi * sizeof(char *));
  330.     }
  331.   if (*arr && p->width != wi)
  332.     for (cp = *arr; cp < *arr + minr; cp++)
  333.       {
  334.     if ((*cp = (char *)xrealloc(*cp, (unsigned) wi)) == 0)
  335.       {
  336.         FreeArray(arr, p->height);
  337.         return(-1);
  338.       }
  339.     if (wi > p->width)
  340.       {
  341.         if (fillblank)
  342.           bclear(*cp + p->width, wi - p->width);
  343.         else
  344.           bzero(*cp + p->width, wi - p->width);
  345.       }
  346.       }
  347.   if (*arr)
  348.     *arr = (char **) xrealloc((char *) *arr, (unsigned) hi * sizeof(char *));
  349.   else
  350.     *arr = (char **) malloc((unsigned) hi * sizeof(char *));
  351.   if (*arr == 0)
  352.     return(-1);
  353.   for (cp = *arr + p->height; cp < *arr + hi; cp++)
  354.     {
  355.       if ((*cp = malloc((unsigned) wi)) == 0)
  356.     {
  357.       while (--cp >= *arr)
  358.         Free(*cp);
  359.       Free(*arr);
  360.           return(-1);
  361.     }
  362.       if (fillblank)
  363.     bclear(*cp, wi);
  364.       else
  365.     bzero(*cp, wi);
  366.     }
  367.   return(0);
  368. }
  369.  
  370. static void
  371. FreeArray(arr, hi)
  372. char ***arr;
  373. int hi;
  374. {
  375.   register char **p;
  376.   register int t;
  377.  
  378.   if (*arr == 0)
  379.     return;
  380.   for (t = hi, p = *arr; t--; p++)
  381.     if (*p)
  382.       Free(*p);
  383.   Free(*arr);
  384. }
  385.  
  386.  
  387. int
  388. ChangeWindowSize(p, width, height)
  389. struct win *p;
  390. int width, height;
  391. {
  392.   int t, scr;
  393.   
  394.   if (width > maxwidth)
  395.     {
  396.       maxwidth = width;
  397.       debug1("New maxwidth: %d\n", maxwidth);
  398.       if (blank == 0)
  399.         blank = malloc((unsigned) maxwidth);
  400.       else
  401.         blank = xrealloc(blank, (unsigned) maxwidth);
  402.       if (null == 0)
  403.         null = malloc((unsigned) maxwidth);
  404.       else
  405.         null = xrealloc(null, (unsigned) maxwidth);
  406.       if (OldImage == 0)
  407.         OldImage = malloc((unsigned) maxwidth);
  408.       else
  409.         OldImage = xrealloc(OldImage, (unsigned) maxwidth);
  410.       if (OldAttr == 0)
  411.         OldAttr = malloc((unsigned) maxwidth);
  412.       else
  413.         OldAttr = xrealloc(OldAttr, (unsigned) maxwidth);
  414.       if (OldFont == 0)
  415.         OldFont = malloc((unsigned) maxwidth);
  416.       else
  417.         OldFont = xrealloc(OldFont, (unsigned) maxwidth);
  418.       if (LastMsg == 0)
  419.         {
  420.           LastMsg = malloc((unsigned) maxwidth + 1);
  421.           *LastMsg = 0;
  422.         }
  423.       else
  424.         LastMsg = xrealloc(LastMsg, (unsigned) maxwidth + 1);
  425.       LastMsg[maxwidth]=0;
  426.       if (!(blank && null && OldImage && OldAttr && OldFont && LastMsg))
  427.     {
  428. nomem:      for (t = WinList; t != -1 && wtab[t] != p; t = p->WinLink) 
  429.         ;
  430.       if (t >= 0)
  431.         KillWindow(t);
  432.       Msg(0, "Out of memory -> Window destroyed !!");
  433.       return(-1);
  434.     }
  435.       MakeBlankLine(blank, maxwidth);
  436.       bzero(null, maxwidth);
  437.     }
  438.   
  439.   if (width == p->width && height == p->height)
  440.     {
  441.       debug("ChangeWindowSize: No change.\n");
  442.       return(0);
  443.     }
  444.  
  445.   debug2("ChangeWindowSize from (%d,%d) to ", p->width, p->height);
  446.   debug2("(%d,%d)\n", width, height);
  447.  
  448.   if (width == 0 && height == 0)
  449.     {
  450.       FreeArray(&p->image, p->height);
  451.       FreeArray(&p->attr, p->height);
  452.       FreeArray(&p->font, p->height);
  453.       if (p->tabs)
  454.     Free(p->tabs);
  455.       p->width = 0;
  456.       p->height = 0;
  457.       FreeScrollback(p);
  458.       return(0);
  459.     }
  460.  
  461.   /* when window gets smaller, scr is the no. of lines we scroll up */
  462.   scr = p->height - height;
  463.   if (scr < 0)
  464.     scr = 0;
  465.   for (t = 0; t < scr; t++)
  466.     AddLineToHist(p, p->image+t, p->attr+t, p->font+t); 
  467.   if (ResizeScreenArray(p, &p->image, width, height, 1)
  468.       || ResizeScreenArray(p, &p->attr, width, height, 0)
  469.       || ResizeScreenArray(p, &p->font, width, height, 0))
  470.     {
  471.       goto nomem;
  472.     }
  473.   /* this won't change the height of the scrollback history buffer, but
  474.    * it will check the width of the lines.
  475.    */
  476.   ChangeScrollback(p, p->histheight, width);
  477.  
  478.   if (p->tabs == 0)
  479.     {
  480.       /* tabs get width+1 because 0 <= x <= width */
  481.       if ((p->tabs = malloc((unsigned) width + 1)) == 0)
  482.         goto nomem;
  483.       t = 8;
  484.     }
  485.   else
  486.     {
  487.       if ((p->tabs = xrealloc(p->tabs, (unsigned) width + 1)) == 0)
  488.         goto nomem;
  489.       t = p->width;
  490.     }
  491.   for (t = (t + 7) & 8; t < width; t += 8)
  492.     p->tabs[t] = 1; 
  493.   p->height = height;
  494.   p->width = width;
  495.   if (p->x >= width)
  496.     p->x = width - 1;
  497.   if ((p->y -= scr) < 0)
  498.     p->y = 0;
  499.   if (p->Saved_x >= width)
  500.     p->Saved_x = width - 1;
  501.   if ((p->Saved_y -= scr) < 0)
  502.     p->Saved_y = 0;
  503.   if (p->autoaka > 0) 
  504.     if ((p->autoaka -= scr) < 1)
  505.       p->autoaka = 1;
  506.   p->top = 0;
  507.   p->bot = height - 1;
  508. #ifdef TIOCSWINSZ
  509.   if (p->ptyfd && p->wpid)
  510.     {
  511.       glwz.ws_col = width;
  512.       glwz.ws_row = height;
  513.       debug("Setting pty winsize.\n");
  514.       if (ioctl(p->ptyfd, TIOCSWINSZ, &glwz))
  515.     debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->ptyfd);
  516. # if defined(STUPIDTIOCSWINSZ) && defined(SIGWINCH)
  517. #  ifdef POSIX
  518.       pgrp = tcgetpgrp(p->ptyfd);
  519. #  else
  520.       if (ioctl(p->ptyfd, TIOCGPGRP, &pgrp))
  521.     pgrp = 0;
  522. #  endif
  523.       if (pgrp)
  524.     {
  525.       debug1("Sending SIGWINCH to pgrp %d.\n", pgrp);
  526.       if (killpg(pgrp, SIGWINCH))
  527.         debug1("killpg: errno %d\n", errno);
  528.     }
  529.       else
  530.     debug1("Could not get pgrp: errno %d\n", errno);
  531. # endif /* STUPIDTIOCSWINSZ */
  532.     }
  533. #endif
  534.   return(0);
  535. }
  536.  
  537.  
  538. void
  539. ResizeScreen(wi)
  540. struct win *wi;
  541. {
  542.   int width, height;
  543.  
  544.   if (wi)
  545.     {
  546.       width = wi->width;
  547.       height = wi->height;
  548.     }
  549.   else
  550.     {
  551.       width = default_width;
  552.       height = default_height;
  553.     }
  554.   if (screenwidth == width && screenheight == height)
  555.     {
  556.       debug("ResizeScreen: No change\n");
  557.       return;
  558.     }
  559.   debug2("ResizeScreen: to (%d,%d).\n", width, height);
  560.   if (WS)
  561.     {
  562.       debug("ResizeScreen: using WS\n");
  563.       WSresize(width, height);
  564.       ChangeScreenSize(width, height, 0);
  565.     }
  566.   else if (Z0 && (width == Z0width || width == Z1width))
  567.     {
  568.       debug("ResizeScreen: using Z0/Z1\n");
  569.       PutStr(width == Z0width ? Z0 : Z1);
  570.       ChangeScreenSize(width, screenheight, 0);
  571.     }
  572.   if (screenwidth != width || screenheight != height)
  573.     {
  574.       debug2("BUG: Cannot resize from (%d,%d)",screenwidth, screenheight);
  575.       debug2(" to (%d,%d) !!\n", width, height);
  576.       if (wi)
  577.     ChangeWindowSize(wi, screenwidth, screenheight);
  578.     }
  579. }
  580.  
  581. char *
  582. xrealloc(mem, len)
  583. char *mem;
  584. int len;
  585. {
  586.   register char *nmem;
  587.  
  588.   if (nmem = realloc(mem, len))
  589.     return(nmem);
  590.   free(mem);
  591.   return((char *)0);
  592. }
  593.