home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / screen-3.5.1 / part02 / resize.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-08  |  13.4 KB  |  623 lines

  1. /* Copyright (c) 1993
  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 2, 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.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: resize.c,v 1.3 1993/08/04 00:42:51 mlschroe Exp $ FAU")
  25.  
  26. #include <stdio.h>
  27. #include <sys/types.h>
  28. #include <signal.h>
  29. #ifndef sun
  30. #include <sys/ioctl.h>
  31. #endif
  32.  
  33. #ifdef ISC
  34. # include <sys/tty.h>
  35. # include <sys/sioctl.h>
  36. # include <sys/pty.h>
  37. #endif
  38.  
  39. #include "config.h"
  40. #include "screen.h"
  41. #include "extern.h"
  42.  
  43. static void CheckMaxSize __P((int));
  44. static int ResizeScreenArray __P((struct win *, char ***, int, int, int));
  45. static void FreeArray __P((char ***, int));
  46. #ifdef COPY_PASTE
  47. static int ResizeHistArray __P((struct win *, char ***, int, int, int));
  48. static void FreeScrollback __P((struct win *));
  49. #endif
  50.  
  51. extern int maxwidth;
  52. extern struct display *display, *displays;
  53. extern char *blank, *null, *OldImage, *OldAttr;
  54. extern char *OldFont;
  55. extern struct win *windows;
  56. extern int Z0width, Z1width;
  57.  
  58. #ifdef NETHACK
  59. extern int nethackflag;
  60. #endif
  61.  
  62. #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ)
  63.   struct winsize glwz;
  64. #endif
  65.  
  66. /*
  67.  * ChangeFlag:   0: try to modify no window
  68.  *               1: modify fore (and try to modify no d_other) + redisplay
  69.  *               2: modify all windows
  70.  *
  71.  * Note: Activate() is only called if change_flag == 1
  72.  *       i.e. on a WINCH event
  73.  */
  74.  
  75. void
  76. CheckScreenSize(change_flag)
  77. int change_flag;
  78. {
  79.   int wi, he;
  80.   struct win *p;
  81.   struct layer *oldlay;
  82.  
  83.   if (display == 0)
  84.     {
  85.       debug("CheckScreenSize: No display -> no check.\n");
  86.       return;
  87.     }
  88.   oldlay = d_lay;
  89. #ifdef TIOCGWINSZ
  90.   if (ioctl(d_userfd, TIOCGWINSZ, (char *)&glwz) != 0)
  91.     {
  92.       debug2("CheckScreenSize: ioctl(%d, TIOCGWINSZ) errno %d\n", d_userfd, errno);
  93.       wi = CO;
  94.       he = LI;
  95.     }
  96.   else
  97.     {
  98.       wi = glwz.ws_col;
  99.       he = glwz.ws_row;
  100.       if (wi == 0)
  101.         wi = CO;
  102.       if (he == 0)
  103.         he = LI;
  104.     }
  105. #else
  106.   wi = CO;
  107.   he = LI;
  108. #endif
  109.   
  110.   debug2("CheckScreenSize: screen is (%d,%d)\n", wi, he);
  111.  
  112.   if (change_flag == 2)
  113.     {
  114.       debug("Trying to adapt all windows (-A)\n");
  115.       for (p = windows; p; p = p->w_next)
  116.     if (p->w_display == 0 || p->w_display == display)
  117.           ChangeWindowSize(p, wi, he);
  118.     }
  119.   if (d_width == wi && d_height == he)
  120.     {
  121.       debug("CheckScreenSize: No change -> return.\n");
  122.       return;
  123.     }
  124.   ChangeScreenSize(wi, he, change_flag);
  125.   if (change_flag == 1)
  126.     Activate(d_fore ? d_fore->w_norefresh : 0);
  127.   if (d_lay != oldlay)
  128.     {
  129. #ifdef NETHACK
  130.       if (nethackflag)
  131.     Msg(0, "KAABLAMM!!!  You triggered a land mine!");
  132.       else
  133. #endif
  134.       Msg(0, "Aborted because of window size change.");
  135.     }
  136. }
  137.  
  138. void
  139. ChangeScreenSize(wi, he, change_fore)
  140. int wi, he;
  141. int change_fore;
  142. {
  143.   struct win *p;
  144.   int wwi;
  145.  
  146.   if (d_width == wi && d_height == he)
  147.     {
  148.       debug("ChangeScreenSize: no change\n");
  149.       return;
  150.     }
  151.   debug2("ChangeScreenSize from (%d,%d) ", d_width, d_height);
  152.   debug3("to (%d,%d) (change_fore: %d)\n",wi, he, change_fore);
  153.   d_width = wi;
  154.   d_height = he;
  155.  
  156.   CheckMaxSize(wi);
  157.   if (CWS)
  158.     {
  159.       d_defwidth = CO;
  160.       d_defheight = LI;
  161.     }
  162.   else
  163.     {
  164.       if (CZ0 && (wi == Z0width || wi == Z1width) &&
  165.           (CO == Z0width || CO == Z1width))
  166.         d_defwidth = CO;
  167.       else
  168.         d_defwidth = wi;
  169.       d_defheight = he;
  170.     }
  171.   debug2("Default size: (%d,%d)\n", d_defwidth, d_defheight);
  172.   if (change_fore)
  173.     DoResize(wi, he);
  174.   if (CWS == NULL && displays->_d_next == 0)
  175.     {
  176.       /* adapt all windows  -  to be removed ? */
  177.       for (p = windows; p; p = p->w_next)
  178.         {
  179.           debug1("Trying to change window %d.\n", p->w_number);
  180.           wwi = wi;
  181.           if (CZ0 && (wi == Z0width || wi == Z1width))
  182.         {
  183.           if (p->w_width > (Z0width + Z1width) / 2)
  184.         wwi = Z0width;
  185.           else
  186.         wwi = Z1width;
  187.         }
  188.           ChangeWindowSize(p, wwi, he);
  189.         }
  190.     }
  191. }
  192.  
  193. void
  194. DoResize(wi, he)
  195. int wi, he;
  196. {
  197.   struct layer *oldlay;
  198.   int q = 0;
  199.  
  200.   for(;;)
  201.     {
  202.       oldlay = d_lay;
  203.       for (; d_lay; d_lay = d_lay->l_next)
  204.     {
  205.       d_layfn = d_lay->l_layfn;
  206.       if ((q = Resize(wi, he)))
  207.         break;
  208.     }
  209.       d_lay = oldlay;
  210.       d_layfn = d_lay->l_layfn;
  211.       if (q == 0)
  212.     break;
  213.       ExitOverlayPage();
  214.     }
  215. }
  216.  
  217. #ifdef COPY_PASTE
  218.  
  219. int
  220. ChangeScrollback(p, histheight, histwidth)
  221. struct win *p;
  222. int histheight, histwidth;
  223. {
  224.   if (histheight > MAXHISTHEIGHT)
  225.     histheight = MAXHISTHEIGHT;
  226.   debug2("ChangeScrollback(..., %d, %d)\n", histheight, histwidth);
  227.   debug2("  was %d, %d\n", p->w_histheight, p->w_width);
  228.  
  229.   if (histheight == 0)
  230.     {
  231.       FreeScrollback(p);
  232.       return 0;
  233.     }
  234.  
  235.   if (ResizeHistArray(p, &p->w_ihist, histwidth, histheight, 1)
  236.       || ResizeHistArray(p, &p->w_ahist, histwidth, histheight, 0)
  237.       || ResizeHistArray(p, &p->w_fhist, histwidth, histheight, 0))
  238.     {
  239.       debug("   failed, removing all histbuf\n");
  240.       FreeScrollback(p);
  241.       Msg(0, strnomem);
  242.       return -1;
  243.     }
  244.   if (p->w_histheight != histheight)
  245.     p->w_histidx = 0;
  246.   p->w_histheight = histheight;
  247.  
  248.   return 0;
  249. }
  250.  
  251. static void
  252. FreeScrollback(p)
  253. struct win *p;
  254. {
  255.   FreeArray(&p->w_ihist, p->w_histheight);
  256.   FreeArray(&p->w_ahist, p->w_histheight);
  257.   FreeArray(&p->w_fhist, p->w_histheight);
  258.   p->w_histheight = 0;
  259. }
  260.  
  261. static int
  262. ResizeHistArray(p, arr, wi, hi, fillblank)
  263. struct win *p;
  264. char ***arr;
  265. int wi, hi, fillblank;
  266. {
  267.   char **narr, **np, **onp, **onpe;
  268.   int t, x, first;
  269.  
  270.   if (p->w_width == wi && p->w_histheight == hi)
  271.     return(0);
  272.   if (p->w_histheight != hi)
  273.     {
  274.       if ((narr = (char **)calloc(sizeof(char *), hi)) == NULL)
  275.     {
  276.       FreeArray(arr, p->w_histheight);
  277.       return(-1);
  278.     }
  279.       np = narr;
  280.       onp = (*arr) + p->w_histidx;
  281.       onpe = (*arr) + p->w_histheight;
  282.       first = p->w_histheight - hi;
  283.       if (first < 0)
  284.      np -= first;
  285.       for(t = 0; t < p->w_histheight; t++)
  286.     {
  287.       ASSERT(*onp);
  288.           if (t - first >= 0 && t - first < hi)
  289.         *np++ = *onp;
  290.       else if (*onp != null)
  291.         free(*onp);
  292.       if (++onp == onpe)
  293.         onp = *arr;
  294.     }
  295.       if (*arr)
  296.     free(*arr);
  297.     }
  298.   else
  299.     narr = *arr;
  300.  
  301.   for (t=0, np=narr; t < hi; t++, np++)
  302.     {
  303.       if ((!fillblank && *np == 0) || *np == null)
  304.     {
  305.       *np = null;
  306.       continue;
  307.     }
  308.       x = p->w_width;
  309.       if (*np == 0)
  310.     {
  311.       *np = (char *)malloc(wi + 1);
  312.           x = 0;
  313.     }
  314.       else if (p->w_width != wi)
  315.     {
  316.       *np = (char *)xrealloc(*np, wi + 1);
  317.     }
  318.       if (*np == 0)
  319.     {
  320.       FreeArray(&narr, hi);
  321.       return -1;
  322.     }
  323.       if (x > wi)
  324.     x = wi;
  325.       if (fillblank)
  326.     bclear(*np + x, wi + 1 - x);
  327.       else
  328.     bzero(*np + x, wi + 1 - x);
  329.     }
  330.   *arr = narr;
  331.   return 0;
  332. }
  333. #endif /* COPY_PASTE */
  334.       
  335.  
  336. static int
  337. ResizeScreenArray(p, arr, wi, hi, fillblank)
  338. struct win *p;
  339. char ***arr;
  340. int wi, hi, fillblank;
  341. {
  342.   int minr;
  343.   char **cp;
  344.  
  345.   if (p->w_width == wi && p->w_height == hi)
  346.     return(0);
  347.  
  348.   if (hi > p->w_height)
  349.     minr = p->w_height;
  350.   else
  351.     minr = hi;
  352.  
  353.   if (p->w_height > hi)
  354.     {
  355.       for (cp = *arr; cp < *arr + (p->w_height - hi); cp++)
  356.         if (*cp != null)
  357.       free(*cp);
  358.       bcopy((char *)(*arr + (p->w_height - hi)), (char *)(*arr),
  359.         hi * sizeof(char *));
  360.     }
  361.   if (*arr && p->w_width != wi)
  362.     for (cp = *arr; cp < *arr + minr; cp++)
  363.       {
  364.     int x = p->w_width;
  365.  
  366.     if (*cp == null)
  367.       continue;
  368.     if ((*cp = (char *)xrealloc(*cp, (unsigned) wi + 1)) == 0)
  369.       {
  370.         FreeArray(arr, p->w_height);
  371.         return(-1);
  372.       }
  373.     if (x > wi)
  374.       x = wi;
  375.     if (fillblank)
  376.       bclear(*cp + x, wi + 1 - x);
  377.     else
  378.       bzero(*cp + x, wi + 1 - x);
  379.       }
  380.   if (*arr)
  381.     *arr = (char **) xrealloc((char *) *arr, (unsigned) hi * sizeof(char *));
  382.   else
  383.     *arr = (char **) malloc((unsigned) hi * sizeof(char *));
  384.   if (*arr == NULL)
  385.     return -1;
  386.   for (cp = *arr + p->w_height; cp < *arr + hi; cp++)
  387.     {
  388.       if (!fillblank)
  389.     {
  390.       *cp = null;
  391.       continue;
  392.     }
  393.       if ((*cp = malloc((unsigned) wi + 1)) == 0)
  394.     {
  395.       while (--cp >= *arr)
  396.         free(*cp);
  397.       free(*arr);
  398.       *arr = NULL;
  399.           return -1;
  400.     }
  401.       bclear(*cp, wi + 1);
  402.     }
  403.   return 0;
  404. }
  405.  
  406. static void
  407. FreeArray(arr, hi)
  408. char ***arr;
  409. int hi;
  410. {
  411.   register char **p;
  412.   register int t;
  413.  
  414.   if (*arr == 0)
  415.     return;
  416.   for (t = hi, p = *arr; t--; p++)
  417.     if (*p && *p != null)
  418.       free(*p);
  419.   free(*arr);
  420.   *arr = 0;
  421. }
  422.  
  423.  
  424. static void
  425. CheckMaxSize(wi)
  426. int wi;
  427. {
  428.   char *oldnull = null;
  429.   struct win *p;
  430.   int i;
  431.  
  432.   wi = ((wi + 1) + 255) & ~255;
  433.   if (wi <= maxwidth)
  434.     return;
  435.   maxwidth = wi;
  436.   debug1("New maxwidth: %d\n", maxwidth);
  437.   if (blank == 0)
  438.     blank = malloc((unsigned) maxwidth);
  439.   else
  440.     blank = xrealloc(blank, (unsigned) maxwidth);
  441.   if (null == 0)
  442.     null = malloc((unsigned) maxwidth);
  443.   else
  444.     null = xrealloc(null, (unsigned) maxwidth);
  445.   if (OldImage == 0)
  446.     OldImage = malloc((unsigned) maxwidth);
  447.   else
  448.     OldImage = xrealloc(OldImage, (unsigned) maxwidth);
  449.   if (OldAttr == 0)
  450.     OldAttr = malloc((unsigned) maxwidth);
  451.   else
  452.     OldAttr = xrealloc(OldAttr, (unsigned) maxwidth);
  453.   if (OldFont == 0)
  454.     OldFont = malloc((unsigned) maxwidth);
  455.   else
  456.     OldFont = xrealloc(OldFont, (unsigned) maxwidth);
  457.   if (!(blank && null && OldImage && OldAttr && OldFont))
  458.     {
  459.       Panic(0, "Out of memory -> Game over!!");
  460.       /*NOTREACHED*/
  461.     }
  462.   MakeBlankLine(blank, maxwidth);
  463.   bzero(null, maxwidth);
  464.  
  465.   /* We have to run through all windows to substitute
  466.    * the null references.
  467.    */
  468.   for (p = windows; p; p = p->w_next)
  469.     {
  470.       for (i = 0; i < p->w_height; i++)
  471.     {
  472.       if (p->w_attr[i] == oldnull)
  473.         p->w_attr[i] = null;
  474.       if (p->w_font[i] == oldnull)
  475.         p->w_font[i] = null;
  476.     }
  477. #ifdef COPY_PASTE
  478.       for (i = 0; i < p->w_histheight; i++)
  479.     {
  480.       if (p->w_ahist[i] == oldnull)
  481.         p->w_ahist[i] = null;
  482.       if (p->w_fhist[i] == oldnull)
  483.         p->w_fhist[i] = null;
  484.     }
  485. #endif
  486.     }
  487. }
  488.  
  489.  
  490. int
  491. ChangeWindowSize(p, wi, he)
  492. struct win *p;
  493. int wi, he;
  494. {
  495.   int t, scr;
  496.   
  497.   CheckMaxSize(wi);
  498.   
  499.   if (wi == p->w_width && he == p->w_height)
  500.     {
  501.       debug("ChangeWindowSize: No change.\n");
  502.       return 0;
  503.     }
  504.  
  505.   debug2("ChangeWindowSize from (%d,%d) to ", p->w_width, p->w_height);
  506.   debug2("(%d,%d)\n", wi, he);
  507.   if (p->w_lay != &p->w_winlay)
  508.     {
  509.       debug("ChangeWindowSize: No resize because of overlay.\n");
  510.       return -1;
  511.     }
  512.   if (wi == 0 && he == 0)
  513.     {
  514.       FreeArray(&p->w_image, p->w_height);
  515.       FreeArray(&p->w_attr, p->w_height);
  516.       FreeArray(&p->w_font, p->w_height);
  517.       if (p->w_tabs)
  518.     free(p->w_tabs);
  519.       p->w_tabs = NULL;
  520.       p->w_width = 0;
  521.       p->w_height = 0;
  522. #ifdef COPY_PASTE
  523.       FreeScrollback(p);
  524. #endif
  525.       return 0;
  526.     }
  527.  
  528.   /* when window gets smaller, scr is the no. of lines we scroll up */
  529.   scr = p->w_height - he;
  530.   if (scr < 0)
  531.     scr = 0;
  532. #ifdef COPY_PASTE
  533.   for (t = 0; t < scr; t++)
  534.     AddLineToHist(p, p->w_image+t, p->w_attr+t, p->w_font+t); 
  535. #endif
  536.   if (ResizeScreenArray(p, &p->w_image, wi, he, 1)
  537.       || ResizeScreenArray(p, &p->w_attr, wi, he, 0)
  538.       || ResizeScreenArray(p, &p->w_font, wi, he, 0))
  539.     {
  540. nomem:      KillWindow(p);
  541.       Msg(0, "Out of memory -> Window destroyed !!");
  542.       return -1;
  543.     }
  544.   /* this won't change the d_height of the scrollback history buffer, but
  545.    * it will check the d_width of the lines.
  546.    */
  547. #ifdef COPY_PASTE
  548.   ChangeScrollback(p, p->w_histheight, wi);
  549. #endif
  550.  
  551.   if (p->w_tabs == 0)
  552.     {
  553.       /* tabs get d_width+1 because 0 <= x <= wi */
  554.       if ((p->w_tabs = malloc((unsigned) wi + 1)) == 0)
  555.         goto nomem;
  556.       t = 8;
  557.     }
  558.   else
  559.     {
  560.       if ((p->w_tabs = xrealloc(p->w_tabs, (unsigned) wi + 1)) == 0)
  561.         goto nomem;
  562.       t = p->w_width;
  563.     }
  564.   for (t = (t + 7) & 8; t < wi; t += 8)
  565.     p->w_tabs[t] = 1; 
  566.   p->w_height = he;
  567.   p->w_width = wi;
  568.   if (p->w_x >= wi)
  569.     p->w_x = wi - 1;
  570.   if ((p->w_y -= scr) < 0)
  571.     p->w_y = 0;
  572.   if (p->w_Saved_x >= wi)
  573.     p->w_Saved_x = wi - 1;
  574.   if ((p->w_Saved_y -= scr) < 0)
  575.     p->w_Saved_y = 0;
  576.   if (p->w_autoaka > 0) 
  577.     if ((p->w_autoaka -= scr) < 1)
  578.       p->w_autoaka = 1;
  579.   p->w_top = 0;
  580.   p->w_bot = he - 1;
  581. #ifdef TIOCSWINSZ
  582.   if (p->w_ptyfd && p->w_pid)
  583.     {
  584.       glwz.ws_col = wi;
  585.       glwz.ws_row = he;
  586.       debug("Setting pty winsize.\n");
  587.       if (ioctl(p->w_ptyfd, TIOCSWINSZ, (char *)&glwz))
  588.     debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->w_ptyfd);
  589. # if defined(STUPIDTIOCSWINSZ) && defined(SIGWINCH)
  590. #  ifdef POSIX
  591.       pgrp = tcgetpgrp(p->w_ptyfd);
  592. #  else /* POSIX */
  593.       if (ioctl(p->w_ptyfd, TIOCGPGRP, (char *)&pgrp))
  594.     pgrp = 0;
  595. #  endif /* POSIX */
  596.       if (pgrp)
  597.     {
  598.       debug1("Sending SIGWINCH to pgrp %d.\n", pgrp);
  599.       if (killpg(pgrp, SIGWINCH))
  600.         debug1("killpg: errno %d\n", errno);
  601.     }
  602.       else
  603.     debug1("Could not get pgrp: errno %d\n", errno);
  604. # endif /* STUPIDTIOCSWINSZ */
  605.     }
  606. #endif /* TIOCSWINSZ */
  607.   return 0;
  608. }
  609.  
  610.  
  611. char *
  612. xrealloc(mem, len)
  613. char *mem;
  614. int len;
  615. {
  616.   register char *nmem;
  617.  
  618.   if ((nmem = realloc(mem, len)))
  619.     return(nmem);
  620.   free(mem);
  621.   return((char *)0);
  622. }
  623.