"Fossies" - the Fresh Open Source Software Archive

Member "screen-4.7.0/resize.c" (1 Oct 2019, 26086 Bytes) of package /linux/misc/screen-4.7.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "resize.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.6.2_vs_4.7.0.

    1 /* Copyright (c) 2008, 2009
    2  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
    3  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
    4  *      Micah Cowan (micah@cowan.name)
    5  *      Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
    6  * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
    7  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
    8  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
    9  * Copyright (c) 1987 Oliver Laumann
   10  *
   11  * This program is free software; you can redistribute it and/or modify
   12  * it under the terms of the GNU General Public License as published by
   13  * the Free Software Foundation; either version 3, or (at your option)
   14  * any later version.
   15  *
   16  * This program is distributed in the hope that it will be useful,
   17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19  * GNU General Public License for more details.
   20  *
   21  * You should have received a copy of the GNU General Public License
   22  * along with this program (see the file COPYING); if not, see
   23  * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
   24  * 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
   25  *
   26  ****************************************************************
   27  */
   28 
   29 #include <sys/types.h>
   30 #include <signal.h>
   31 #ifndef sun
   32 #include <sys/ioctl.h>
   33 #endif
   34 
   35 #ifdef ISC
   36 # include <sys/tty.h>
   37 # include <sys/sioctl.h>
   38 # include <sys/pty.h>
   39 #endif
   40 
   41 #include "config.h"
   42 #include "screen.h"
   43 #include "extern.h"
   44 
   45 /* maximum window width */
   46 #define MAXWIDTH 1000
   47 
   48 static void CheckMaxSize __P((int));
   49 static void FreeMline  __P((struct mline *));
   50 static int  AllocMline __P((struct mline *ml, int));
   51 static void MakeBlankLine __P((unsigned char *, int));
   52 static void kaablamm __P((void));
   53 static int  BcopyMline __P((struct mline *, int, struct mline *, int, int, int));
   54 static void SwapAltScreen __P((struct win *));
   55 
   56 extern struct layer *flayer;
   57 extern struct display *display, *displays;
   58 extern unsigned char *blank, *null;
   59 extern struct mline mline_blank, mline_null, mline_old;
   60 extern struct win *windows;
   61 extern const int Z0width, Z1width;
   62 extern int captionalways;
   63 
   64 #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ)
   65 struct winsize glwz;
   66 #endif
   67 
   68 static struct mline mline_zero = {
   69  (unsigned char *)0,
   70  (unsigned char *)0
   71 #ifdef FONT
   72  ,(unsigned char *)0
   73 #endif
   74 #ifdef COLOR
   75  ,(unsigned char *)0
   76 # ifdef COLORS256
   77  ,(unsigned char *)0
   78 # endif
   79 #endif
   80 };
   81 
   82 /*
   83  * ChangeFlag:   0: try to modify no window
   84  *               1: modify fore (and try to modify no other) + redisplay
   85  *               2: modify all windows
   86  *
   87  * Note: Activate() is only called if change_flag == 1
   88  *       i.e. on a WINCH event
   89  */
   90 
   91 void
   92 CheckScreenSize(change_flag)
   93 int change_flag;
   94 {
   95   int wi, he;
   96 
   97   if (display == 0)
   98     {
   99       debug("CheckScreenSize: No display -> no check.\n");
  100       return;
  101     }
  102 #ifdef TIOCGWINSZ
  103   if (ioctl(D_userfd, TIOCGWINSZ, (char *)&glwz) != 0)
  104     {
  105       debug2("CheckScreenSize: ioctl(%d, TIOCGWINSZ) errno %d\n", D_userfd, errno);
  106       wi = D_CO;
  107       he = D_LI;
  108     }
  109   else
  110     {
  111       wi = glwz.ws_col;
  112       he = glwz.ws_row;
  113       if (wi == 0)
  114         wi = D_CO;
  115       if (he == 0)
  116         he = D_LI;
  117     }
  118 #else
  119   wi = D_CO;
  120   he = D_LI;
  121 #endif
  122   
  123   debug2("CheckScreenSize: screen is (%d,%d)\n", wi, he);
  124 
  125 #if 0 /* XXX: Fixme */
  126   if (change_flag == 2)
  127     {
  128       debug("Trying to adapt all windows (-A)\n");
  129       for (p = windows; p; p = p->w_next)
  130     if (p->w_display == 0 || p->w_display == display)
  131           ChangeWindowSize(p, wi, he, p->w_histheight);
  132     }
  133 #endif
  134   if (D_width == wi && D_height == he)
  135     {
  136       debug("CheckScreenSize: No change -> return.\n");
  137       return;
  138     }
  139 #ifdef BLANKER_PRG
  140   KillBlanker();
  141 #endif
  142   ResetIdle();
  143   ChangeScreenSize(wi, he, change_flag);
  144 /* XXX Redisplay logic */
  145 #if 0
  146   if (change_flag == 1)
  147     Redisplay(D_fore ? D_fore->w_norefresh : 0);
  148 #endif
  149 }
  150 
  151 void
  152 ChangeScreenSize(wi, he, change_fore)
  153 int wi, he;
  154 int change_fore;
  155 {
  156   struct win *p;
  157   struct canvas *cv;
  158   int wwi;
  159 
  160   debug2("ChangeScreenSize from (%d,%d) ", D_width, D_height);
  161   debug3("to (%d,%d) (change_fore: %d)\n",wi, he, change_fore);
  162 
  163   cv = &D_canvas;
  164   cv->c_xe = wi - 1;
  165   cv->c_ys = (D_has_hstatus == HSTATUS_FIRSTLINE);
  166   cv->c_ye = he - 1 - ((cv->c_slperp && cv->c_slperp->c_slnext) || captionalways) - (D_has_hstatus == HSTATUS_LASTLINE);
  167   cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1;
  168   if (cv->c_slperp)
  169     {
  170       ResizeCanvas(cv);
  171       RecreateCanvasChain();
  172       RethinkDisplayViewports();
  173     }
  174   if (D_forecv == 0)
  175     D_forecv = D_cvlist;
  176   if (D_forecv)
  177     D_fore = Layer2Window(D_forecv->c_layer);
  178 
  179   D_width = wi;
  180   D_height = he;
  181 
  182   CheckMaxSize(wi);
  183   if (D_CWS)
  184     {
  185       D_defwidth = D_CO;
  186       D_defheight = D_LI;
  187     }
  188   else
  189     {
  190       if (D_CZ0 && (wi == Z0width || wi == Z1width) &&
  191           (D_CO == Z0width || D_CO == Z1width))
  192         D_defwidth = D_CO;
  193       else
  194         D_defwidth = wi;
  195       D_defheight = he;
  196     }
  197   debug2("Default size: (%d,%d)\n", D_defwidth, D_defheight);
  198   if (change_fore)
  199     ResizeLayersToCanvases();
  200   if (change_fore == 2 && D_CWS == NULL && displays->d_next == 0)
  201     {
  202       /* adapt all windows  -  to be removed ? */
  203       for (p = windows; p; p = p->w_next)
  204         {
  205           debug1("Trying to change window %d.\n", p->w_number);
  206           wwi = wi;
  207 #if 0
  208           if (D_CZ0 && p->w_width != wi && (wi == Z0width || wi == Z1width))
  209         {
  210           if (p->w_width > (Z0width + Z1width) / 2)
  211         wwi = Z0width;
  212           else
  213         wwi = Z1width;
  214         }
  215 #endif
  216       if (p->w_savelayer && p->w_savelayer->l_cvlist == 0)
  217         ResizeLayer(p->w_savelayer, wwi, he, 0);
  218 #if 0
  219           ChangeWindowSize(p, wwi, he, p->w_histheight);
  220 #endif
  221         }
  222     }
  223 }
  224 
  225 void
  226 ResizeLayersToCanvases()
  227 {
  228   struct canvas *cv;
  229   struct layer *l;
  230   int lx, ly;
  231 
  232   debug("ResizeLayersToCanvases\n");
  233   D_kaablamm = 0;
  234   for (cv = D_cvlist; cv; cv = cv->c_next)
  235     {
  236       l = cv->c_layer;
  237       if (l == 0)
  238     continue;
  239       debug("Doing canvas: ");
  240       if (l->l_width  == cv->c_xe - cv->c_xs + 1 &&
  241           l->l_height == cv->c_ye - cv->c_ys + 1)
  242         {
  243           debug("already fitting.\n");
  244           continue;
  245         }
  246       if (!MayResizeLayer(l))
  247         {
  248           debug("may not resize.\n");
  249         }
  250       else
  251     {
  252       debug("doing resize.\n");
  253       ResizeLayer(l, cv->c_xe - cv->c_xs + 1, cv->c_ye - cv->c_ys + 1, display);
  254     }
  255 
  256       /* normalize window, see screen.c */
  257       lx = cv->c_layer->l_x;
  258       ly = cv->c_layer->l_y;
  259       if (ly + cv->c_yoff < cv->c_ys)
  260     {
  261           cv->c_yoff = cv->c_ys - ly;
  262           RethinkViewportOffsets(cv);
  263     }
  264       else if (ly + cv->c_yoff > cv->c_ye)
  265     {
  266       cv->c_yoff = cv->c_ye - ly;
  267           RethinkViewportOffsets(cv);
  268     }
  269       if (lx + cv->c_xoff < cv->c_xs)
  270         {
  271       int n = cv->c_xs - (lx + cv->c_xoff);
  272       if (n < (cv->c_xe - cv->c_xs + 1) / 2)
  273         n = (cv->c_xe - cv->c_xs + 1) / 2;
  274       if (cv->c_xoff + n > cv->c_xs)
  275         n = cv->c_xs - cv->c_xoff;
  276       cv->c_xoff += n;
  277       RethinkViewportOffsets(cv);
  278         }
  279       else if (lx + cv->c_xoff > cv->c_xe)
  280     {
  281       int n = lx + cv->c_xoff - cv->c_xe;
  282       if (n < (cv->c_xe - cv->c_xs + 1) / 2)
  283         n = (cv->c_xe - cv->c_xs + 1) / 2;
  284       if (cv->c_xoff - n + cv->c_layer->l_width - 1 < cv->c_xe)
  285         n = cv->c_xoff + cv->c_layer->l_width - 1 - cv->c_xe;
  286       cv->c_xoff -= n;
  287       RethinkViewportOffsets(cv);
  288     }
  289     }
  290   Redisplay(0);
  291   if (D_kaablamm)
  292     {
  293       kaablamm();
  294       D_kaablamm = 0;
  295     }
  296 }
  297 
  298 int
  299 MayResizeLayer(l)
  300 struct layer *l;
  301 {
  302   int cvs = 0;
  303   debug("MayResizeLayer:\n");
  304   for (; l; l = l->l_next)
  305     {
  306       if (l->l_cvlist)
  307         if (++cvs > 1 || l->l_cvlist->c_lnext)
  308       {
  309         debug1("may not - cvs %d\n", cvs);
  310         return 0;
  311       }
  312     }
  313   debug("may resize\n");
  314   return 1;
  315 }
  316 
  317 /*
  318  *  Easy implementation: rely on the fact that the only layers
  319  *  supporting resize are Win and Blank. So just kill all overlays.
  320  *
  321  *  This is a lot harder if done the right way...
  322  */
  323 
  324 static void
  325 kaablamm()
  326 {
  327   Msg(0, "Aborted because of window size change.");
  328 }
  329 
  330 /* Kills non-resizable layers. */
  331 #define RESIZE_OR_KILL_LAYERS(l, wi, he) do \
  332   { \
  333     struct layer *_last = NULL; \
  334     flayer = (l);   \
  335     while (flayer->l_next)  \
  336       { \
  337     if (LayResize(wi, he) == 0) \
  338       { \
  339         _last = flayer; \
  340         flayer = flayer->l_next;    \
  341       } \
  342     else    \
  343       { \
  344         struct canvas *_cv; \
  345         for (_cv = flayer->l_cvlist; _cv; _cv = _cv->c_lnext)   \
  346           _cv->c_display->d_kaablamm = 1;   \
  347         ExitOverlayPage();  \
  348         if (_last)  \
  349           _last->l_next = flayer;   \
  350       } \
  351       } \
  352     /* We assume that the bottom-most layer, i.e. when flayer->l_next == 0, \
  353      * is always resizable. Currently, WinLf and BlankLf can be the bottom-most layers. \
  354      */ \
  355     LayResize(wi, he);  \
  356   } while (0)
  357 
  358 void
  359 ResizeLayer(l, wi, he, norefdisp)
  360 struct layer *l;
  361 int wi, he;
  362 struct display *norefdisp;
  363 {
  364   struct win *p;
  365   struct canvas *cv;
  366   struct layer *oldflayer = flayer;
  367   struct display *d, *olddisplay = display;
  368 
  369   if (l->l_width == wi && l->l_height == he)
  370     return;
  371   p = Layer2Window(l);
  372 
  373   /* If 'flayer' and 'l' are for the same window, then we will not
  374    * restore 'flayer'. */
  375   if (oldflayer && (l == oldflayer || Layer2Window(oldflayer) == p))
  376     oldflayer = NULL;
  377 
  378   flayer = l;
  379 
  380   if (p)
  381     {
  382       /* It's a window layer. Kill the overlays on it in all displays. */
  383       for (d = displays; d; d = d->d_next)
  384     for (cv = d->d_cvlist; cv; cv = cv->c_next)
  385       {
  386         if (p == Layer2Window(cv->c_layer))
  387           {
  388         /* Canvas 'cv' on display 'd' shows this window. Remove any non-resizable
  389          * layers over it. */
  390         RESIZE_OR_KILL_LAYERS(cv->c_layer, wi, he);
  391           }
  392       }
  393     }
  394   else
  395     {
  396       /* It's a Blank layer. Just kill the non-resizable overlays over it. */
  397       RESIZE_OR_KILL_LAYERS(flayer, wi, he);
  398     }
  399 
  400   for (display = displays; display; display = display->d_next)
  401     {
  402       if (display == norefdisp)
  403     continue;
  404       for (cv = D_cvlist; cv; cv = cv->c_next)
  405     if (Layer2Window(cv->c_layer) == p)
  406       {
  407             CV_CALL(cv, LayRedisplayLine(-1, -1, -1, 0));
  408             RefreshArea(cv->c_xs, cv->c_ys, cv->c_xe, cv->c_ye, 0);
  409       }
  410       if (D_kaablamm)
  411     {
  412       kaablamm();
  413       D_kaablamm = 0;
  414     }
  415     }
  416 
  417   /* If we started resizing a non-flayer layer, then restore the flayer.
  418    * Otherwise, flayer should already be updated to the topmost foreground layer. */
  419   if (oldflayer)
  420     flayer = oldflayer;
  421   display = olddisplay;
  422 }
  423 
  424 static void
  425 FreeMline(ml)
  426 struct mline *ml;
  427 {
  428   if (ml->image)
  429     free(ml->image);
  430   if (ml->attr && ml->attr != null)
  431     free(ml->attr);
  432 #ifdef FONT
  433   if (ml->font && ml->font != null)
  434     free(ml->font);
  435   if (ml->fontx && ml->fontx != null)
  436     free(ml->fontx);
  437 #endif
  438 #ifdef COLOR
  439   if (ml->color && ml->color != null)
  440     free(ml->color);
  441 # ifdef COLORS256
  442   if (ml->colorx && ml->colorx != null)
  443     free(ml->colorx);
  444 # endif
  445 #endif
  446   *ml = mline_zero;
  447 }
  448 
  449 static int
  450 AllocMline(ml, w)
  451 struct mline *ml;
  452 int w;
  453 {
  454   ml->image = malloc(w);
  455   ml->attr  = null;
  456 #ifdef FONT
  457   ml->font  = null;
  458   ml->fontx = null;
  459 #endif
  460 #ifdef COLOR
  461   ml->color = null;
  462 # ifdef COLORS256
  463   ml->colorx = null;
  464 # endif
  465 #endif
  466   if (ml->image == 0)
  467     return -1;
  468   return 0;
  469 }
  470 
  471 
  472 static int
  473 BcopyMline(mlf, xf, mlt, xt, l, w)
  474 struct mline *mlf, *mlt;
  475 int xf, xt, l, w;
  476 {
  477   int r = 0;
  478 
  479   bcopy((char *)mlf->image + xf, (char *)mlt->image + xt, l);
  480   if (mlf->attr != null && mlt->attr == null)
  481     {
  482       if ((mlt->attr = (unsigned char *)calloc(w, 1)) == 0)
  483     mlt->attr = null, r = -1;
  484     }
  485   if (mlt->attr != null)
  486     bcopy((char *)mlf->attr + xf, (char *)mlt->attr + xt, l);
  487 #ifdef FONT
  488   if (mlf->font != null && mlt->font == null)
  489     {
  490       if ((mlt->font = (unsigned char *)calloc(w, 1)) == 0)
  491     mlt->font = null, r = -1;
  492     }
  493   if (mlt->font != null)
  494     bcopy((char *)mlf->font + xf, (char *)mlt->font + xt, l);
  495   if (mlf->fontx != null && mlt->fontx == null)
  496     {
  497       if ((mlt->fontx = (unsigned char *)calloc(w, 1)) == 0)
  498     mlt->fontx = null, r = -1;
  499     }
  500   if (mlt->fontx != null)
  501     bcopy((char *)mlf->fontx + xf, (char *)mlt->fontx + xt, l);
  502 #endif
  503 #ifdef COLOR
  504   if (mlf->color != null && mlt->color == null)
  505     {
  506       if ((mlt->color = (unsigned char *)calloc(w, 1)) == 0)
  507     mlt->color = null, r = -1;
  508     }
  509   if (mlt->color != null)
  510     bcopy((char *)mlf->color + xf, (char *)mlt->color + xt, l);
  511 # ifdef COLORS256
  512   if (mlf->colorx != null && mlt->colorx == null)
  513     {
  514       if ((mlt->colorx = (unsigned char *)calloc(w, 1)) == 0)
  515     mlt->colorx = null, r = -1;
  516     }
  517   if (mlt->colorx != null)
  518     bcopy((char *)mlf->colorx + xf, (char *)mlt->colorx + xt, l);
  519 # endif
  520 #endif
  521   return r;
  522 }
  523 
  524 
  525 static int maxwidth;
  526 
  527 static void
  528 CheckMaxSize(wi)
  529 int wi;
  530 {
  531   unsigned char *oldnull = null;
  532   unsigned char *oldblank = blank;
  533   struct win *p;
  534   int i;
  535   struct mline *ml;
  536 
  537   if (wi > MAXWIDTH)
  538       wi = MAXWIDTH;
  539   if (wi <= maxwidth)
  540     return;
  541   maxwidth = wi + 1;
  542   debug1("New maxwidth: %d\n", maxwidth);
  543   blank = (unsigned char *)xrealloc((char *)blank, maxwidth);
  544   null = (unsigned char *)xrealloc((char *)null, maxwidth);
  545   mline_old.image = (unsigned char *)xrealloc((char *)mline_old.image, maxwidth);
  546   mline_old.attr = (unsigned char *)xrealloc((char *)mline_old.attr, maxwidth);
  547 #ifdef FONT
  548   mline_old.font = (unsigned char *)xrealloc((char *)mline_old.font, maxwidth);
  549   mline_old.fontx = (unsigned char *)xrealloc((char *)mline_old.fontx, maxwidth);
  550 #endif
  551 #ifdef COLOR
  552   mline_old.color = (unsigned char *)xrealloc((char *)mline_old.color, maxwidth);
  553 # ifdef COLORS256
  554   mline_old.colorx = (unsigned char *)xrealloc((char *)mline_old.colorx, maxwidth);
  555 # endif
  556 #endif
  557   if (!(blank && null && mline_old.image && mline_old.attr IFFONT(&& mline_old.font) IFFONTX(&& mline_old.fontx) IFCOLOR(&& mline_old.color) IFCOLORX(&& mline_old.colorx)))
  558     Panic(0, "%s", strnomem);
  559 
  560   MakeBlankLine(blank, maxwidth);
  561   bzero((char *)null, maxwidth);
  562 
  563   mline_blank.image = blank;
  564   mline_blank.attr  = null;
  565   mline_null.image = null;
  566   mline_null.attr  = null;
  567 #ifdef FONT
  568   mline_blank.font  = null;
  569   mline_null.font   = null;
  570   mline_blank.fontx = null;
  571   mline_null.fontx  = null;
  572 #endif
  573 #ifdef COLOR
  574   mline_blank.color = null;
  575   mline_null.color = null;
  576 # ifdef COLORS256
  577   mline_blank.colorx = null;
  578   mline_null.colorx = null;
  579 # endif
  580 #endif
  581 
  582 #define RESET_AFC(x, bl) do { if (x == old##bl) x = bl; } while (0)
  583 
  584 #define RESET_LINES(lines, count) \
  585   do { \
  586     ml = lines; \
  587     for (i = 0; i < count; i++, ml++) \
  588       { \
  589     RESET_AFC(ml->image, blank); \
  590     RESET_AFC(ml->attr, null); \
  591     IFFONT(RESET_AFC(ml->font, null)); \
  592     IFFONT(RESET_AFC(ml->fontx, null)); \
  593     IFCOLOR(RESET_AFC(ml->color, null)); \
  594     IFCOLORX(RESET_AFC(ml->colorx, null)); \
  595       } \
  596   } while (0)
  597 
  598   /* We have to run through all windows to substitute
  599    * the null and blank references.
  600    */
  601   for (p = windows; p; p = p->w_next)
  602     {
  603       RESET_LINES(p->w_mlines, p->w_height);
  604 
  605 #ifdef COPY_PASTE
  606       RESET_LINES(p->w_hlines, p->w_histheight);
  607       RESET_LINES(p->w_alt.hlines, p->w_alt.histheight);
  608 #endif
  609 
  610       RESET_LINES(p->w_alt.mlines, p->w_alt.height);
  611     }
  612 }
  613 
  614 
  615 char *
  616 xrealloc(mem, len)
  617 char *mem;
  618 int len;
  619 {
  620   register char *nmem;
  621 
  622   if (mem == 0)
  623     return malloc(len);
  624   if ((nmem = realloc(mem, len)))
  625     return nmem;
  626   free(mem);
  627   return (char *)0;
  628 }
  629 
  630 static void
  631 MakeBlankLine(p, n)
  632 register unsigned char *p;
  633 register int n;
  634 {
  635   while (n--)
  636     *p++ = ' ';
  637 }
  638 
  639 
  640 
  641 
  642 #ifdef COPY_PASTE
  643 
  644 #define OLDWIN(y) ((y < p->w_histheight) \
  645         ? &p->w_hlines[(p->w_histidx + y) % p->w_histheight] \
  646         : &p->w_mlines[y - p->w_histheight])
  647 
  648 #define NEWWIN(y) ((y < hi) ? &nhlines[y] : &nmlines[y - hi])
  649     
  650 #else
  651 
  652 #define OLDWIN(y) (&p->w_mlines[y])
  653 #define NEWWIN(y) (&nmlines[y])
  654 
  655 #endif
  656 
  657 
  658 int
  659 ChangeWindowSize(p, wi, he, hi)
  660 struct win *p;
  661 int wi, he, hi;
  662 {
  663   struct mline *mlf = 0, *mlt = 0, *ml, *nmlines, *nhlines;
  664   int fy, ty, l, lx, lf, lt, yy, oty, addone;
  665   int ncx, ncy, naka, t;
  666   int y, shift;
  667 
  668   if (wi <= 0 || he <= 0)
  669     wi = he = hi = 0;
  670 
  671   if (p->w_type == W_TYPE_GROUP)
  672     return 0;
  673 
  674   if (wi > MAXWIDTH)
  675     {
  676       Msg(0, "Window width too large. Truncated to %d.", MAXWIDTH);
  677       wi = MAXWIDTH;
  678     }
  679 
  680   if (he > MAXWIDTH)
  681     {
  682       Msg(0, "Window height too large. Truncated to %d.", MAXWIDTH);
  683       he = MAXWIDTH;
  684     }
  685 
  686   if (p->w_width == wi && p->w_height == he && p->w_histheight == hi)
  687     {
  688       debug("ChangeWindowSize: No change.\n");
  689       return 0;
  690     }
  691 
  692   CheckMaxSize(wi);
  693 
  694   /* XXX */
  695 #if 0
  696   /* just in case ... */
  697   if (wi && (p->w_width != wi || p->w_height != he) && p->w_lay != &p->w_winlay)
  698     {
  699       debug("ChangeWindowSize: No resize because of overlay?\n");
  700       return -1;
  701     }
  702 #endif
  703 
  704   debug("ChangeWindowSize");
  705   debug3(" from (%d,%d)+%d", p->w_width, p->w_height, p->w_histheight);
  706   debug3(" to(%d,%d)+%d\n", wi, he, hi);
  707 
  708   fy = p->w_histheight + p->w_height - 1;
  709   ty = hi + he - 1;
  710 
  711   nmlines = nhlines = 0;
  712   ncx = 0;
  713   ncy = 0;
  714   naka = 0;
  715 
  716   if (wi)
  717     {
  718       if (wi != p->w_width || he != p->w_height)
  719     {
  720       if ((nmlines = (struct mline *)calloc(he, sizeof(struct mline))) == 0)
  721         {
  722           KillWindow(p);
  723           Msg(0, "%s", strnomem);
  724           return -1;
  725         }
  726     }
  727       else
  728     {
  729       debug1("image stays the same: %d lines\n", he);
  730       nmlines = p->w_mlines;
  731       fy -= he;
  732       ty -= he;
  733       ncx = p->w_x;
  734       ncy = p->w_y;
  735       naka = p->w_autoaka;
  736     }
  737     }
  738 #ifdef COPY_PASTE
  739   if (hi)
  740     {
  741       if ((nhlines = (struct mline *)calloc(hi, sizeof(struct mline))) == 0)
  742     {
  743       Msg(0, "No memory for history buffer - turned off");
  744       hi = 0;
  745       ty = he - 1;
  746     }
  747     }
  748 #endif
  749 
  750   /* special case: cursor is at magic margin position */
  751   addone = 0;
  752   if (p->w_width && p->w_x == p->w_width)
  753     {
  754       debug2("Special addone case: %d %d\n", p->w_x, p->w_y);
  755       addone = 1;
  756       p->w_x--;
  757     }
  758 
  759   /* handle the cursor and autoaka lines now if the widths are equal */
  760   if (p->w_width == wi)
  761     {
  762       ncx = p->w_x + addone;
  763       ncy = p->w_y + he - p->w_height;
  764       /* never lose sight of the line with the cursor on it */
  765       shift = -ncy;
  766       for (yy = p->w_y + p->w_histheight - 1; yy >= 0 && ncy + shift < he; yy--)
  767     {
  768       ml = OLDWIN(yy);
  769       if (!ml->image)
  770         break;
  771       if (ml->image[p->w_width] == ' ')
  772         break;
  773       shift++;
  774     }
  775       if (shift < 0)
  776     shift = 0;
  777       else
  778     debug1("resize: cursor out of bounds, shifting %d\n", shift);
  779       ncy += shift;
  780       if (p->w_autoaka > 0)
  781     {
  782       naka = p->w_autoaka + he - p->w_height + shift;
  783       if (naka < 1 || naka > he)
  784         naka = 0;
  785     }
  786       while (shift-- > 0)
  787     {
  788       ml = OLDWIN(fy);
  789       FreeMline(ml);
  790       fy--;
  791     }
  792     }
  793   debug2("fy %d ty %d\n", fy, ty);
  794   if (fy >= 0)
  795     mlf = OLDWIN(fy);
  796   if (ty >= 0)
  797     mlt = NEWWIN(ty);
  798 
  799   while (fy >= 0 && ty >= 0)
  800     {
  801       if (p->w_width == wi)
  802     {
  803       /* here is a simple shortcut: just copy over */
  804       *mlt = *mlf;
  805           *mlf = mline_zero;
  806       if (--fy >= 0)
  807         mlf = OLDWIN(fy);
  808       if (--ty >= 0)
  809         mlt = NEWWIN(ty);
  810       continue;
  811     }
  812 
  813       /* calculate lenght */
  814       for (l = p->w_width - 1; l > 0; l--)
  815     if (mlf->image[l] != ' ' || mlf->attr[l])
  816       break;
  817       if (fy == p->w_y + p->w_histheight && l < p->w_x)
  818     l = p->w_x; /* cursor is non blank */
  819       l++;
  820       lf = l;
  821 
  822       /* add wrapped lines to length */
  823       for (yy = fy - 1; yy >= 0; yy--)
  824     {
  825       ml = OLDWIN(yy);
  826       if (ml->image[p->w_width] == ' ')
  827         break;
  828       l += p->w_width;
  829     }
  830 
  831       /* rewrap lines */
  832       lt = (l - 1) % wi + 1;    /* lf is set above */
  833       oty = ty;
  834       while (l > 0 && fy >= 0 && ty >= 0)
  835     {
  836       lx = lt > lf ? lf : lt;
  837       if (mlt->image == 0)
  838         {
  839           if (AllocMline(mlt, wi + 1))
  840         goto nomem;
  841               MakeBlankLine(mlt->image + lt, wi - lt);
  842           mlt->image[wi] = ((oty == ty) ? ' ' : 0);
  843         }
  844       if (BcopyMline(mlf, lf - lx, mlt, lt - lx, lx, wi + 1))
  845         goto nomem;
  846 
  847       /* did we copy the cursor ? */
  848       if (fy == p->w_y + p->w_histheight && lf - lx <= p->w_x && lf > p->w_x)
  849         {
  850           ncx = p->w_x + lt - lf + addone;
  851           ncy = ty - hi;
  852           shift = wi ? -ncy + (l - lx) / wi : 0;
  853           if (ty + shift > hi + he - 1)
  854         shift = hi + he - 1 - ty;
  855           if (shift > 0)
  856         {
  857               debug3("resize: cursor out of bounds, shifting %d [%d/%d]\n", shift, lt - lx, wi);
  858           for (y = hi + he - 1; y >= ty; y--)
  859             {
  860               mlt = NEWWIN(y);
  861               FreeMline(mlt);
  862               if (y - shift < ty)
  863             continue;
  864               ml  = NEWWIN(y - shift);
  865               *mlt = *ml;
  866               *ml = mline_zero;
  867             }
  868           ncy += shift;
  869           ty += shift;
  870           mlt = NEWWIN(ty);
  871           if (naka > 0)
  872             naka = naka + shift > he ? 0 : naka + shift;
  873         }
  874           ASSERT(ncy >= 0);
  875         }
  876       /* did we copy autoaka line ? */
  877       if (p->w_autoaka > 0 && fy == p->w_autoaka - 1 + p->w_histheight && lf - lx <= 0)
  878         naka = ty - hi >= 0 ? 1 + ty - hi : 0;
  879 
  880       lf -= lx;
  881       lt -= lx;
  882       l  -= lx;
  883       if (lf == 0)
  884         {
  885           FreeMline(mlf);
  886           lf = p->w_width;
  887           if (--fy >= 0)
  888             mlf = OLDWIN(fy);
  889         }
  890       if (lt == 0)
  891         {
  892           lt = wi;
  893           if (--ty >= 0)
  894             mlt = NEWWIN(ty);
  895         }
  896     }
  897       ASSERT(l != 0 || fy == yy);
  898     }
  899   while (fy >= 0)
  900     {
  901       FreeMline(mlf);
  902       if (--fy >= 0)
  903     mlf = OLDWIN(fy);
  904     }
  905   while (ty >= 0)
  906     {
  907       if (AllocMline(mlt, wi + 1))
  908     goto nomem;
  909       MakeBlankLine(mlt->image, wi + 1);
  910       if (--ty >= 0)
  911     mlt = NEWWIN(ty);
  912     }
  913 
  914 #ifdef DEBUG
  915   if (nmlines != p->w_mlines)
  916     for (fy = 0; fy < p->w_height + p->w_histheight; fy++)
  917       {
  918     ml = OLDWIN(fy);
  919     ASSERT(ml->image == 0);
  920       }
  921 #endif
  922 
  923   if (p->w_mlines && p->w_mlines != nmlines)
  924     free((char *)p->w_mlines);
  925   p->w_mlines = nmlines;
  926 #ifdef COPY_PASTE
  927   if (p->w_hlines && p->w_hlines != nhlines)
  928     free((char *)p->w_hlines);
  929   p->w_hlines = nhlines;
  930 #endif
  931   nmlines = nhlines = 0;
  932 
  933   /* change tabs */
  934   if (p->w_width != wi)
  935     {
  936       if (wi)
  937     {
  938       t = p->w_tabs ? p->w_width : 0;
  939       p->w_tabs = xrealloc(p->w_tabs, wi + 1);
  940       if (p->w_tabs == 0)
  941             goto nomem;
  942       for (; t < wi; t++)
  943         p->w_tabs[t] = t && !(t & 7) ? 1 : 0; 
  944       p->w_tabs[wi] = 0; 
  945     }
  946       else
  947     {
  948       if (p->w_tabs)
  949         free(p->w_tabs);
  950       p->w_tabs = 0;
  951     }
  952     }
  953 
  954   /* Change w_saved.y - this is only an estimate... */
  955   p->w_saved.y += ncy - p->w_y;
  956 
  957   p->w_x = ncx;
  958   p->w_y = ncy;
  959   if (p->w_autoaka > 0)
  960     p->w_autoaka = naka;
  961 
  962   /* do sanity checks */
  963   if (p->w_x > wi)
  964     p->w_x = wi;
  965   if (p->w_y >= he)
  966     p->w_y = he - 1;
  967   if (p->w_saved.x > wi)
  968     p->w_saved.x = wi;
  969   if (p->w_saved.y >= he)
  970     p->w_saved.y = he - 1;
  971   if (p->w_saved.y < 0)
  972     p->w_saved.y = 0;
  973   if (p->w_alt.cursor.x > wi)
  974     p->w_alt.cursor.x = wi;
  975   if (p->w_alt.cursor.y >= he)
  976     p->w_alt.cursor.y = he - 1;
  977   if (p->w_alt.cursor.y < 0)
  978     p->w_alt.cursor.y = 0;
  979 
  980   /* reset scrolling region */
  981   p->w_top = 0;
  982   p->w_bot = he - 1;
  983 
  984   /* signal new size to window */
  985 #ifdef TIOCSWINSZ
  986   if (wi && (p->w_width != wi || p->w_height != he)
  987       && p->w_width != 0 && p->w_height != 0 && p->w_ptyfd >= 0 && p->w_pid)
  988     {
  989       glwz.ws_col = wi;
  990       glwz.ws_row = he;
  991       debug("Setting pty winsize.\n");
  992       if (ioctl(p->w_ptyfd, TIOCSWINSZ, (char *)&glwz))
  993     debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->w_ptyfd);
  994     }
  995 #endif /* TIOCSWINSZ */
  996 
  997   /* store new size */
  998   p->w_width = wi;
  999   p->w_height = he;
 1000   if(p->w_scrollback_height > hi)
 1001     p->w_scrollback_height = hi;
 1002 #ifdef COPY_PASTE
 1003   p->w_histidx = 0;
 1004   p->w_histheight = hi;
 1005 #endif
 1006 
 1007 #ifdef BUILTIN_TELNET
 1008   if (p->w_type == W_TYPE_TELNET)
 1009     TelWindowSize(p);
 1010 #endif
 1011 
 1012 #ifdef DEBUG
 1013   /* Test if everything was ok */
 1014   for (fy = 0; fy < p->w_height + p->w_histheight; fy++)
 1015     {
 1016       ml = OLDWIN(fy);
 1017       ASSERT(ml->image);
 1018 # ifdef UTF8
 1019       if (p->w_encoding == UTF8)
 1020     {
 1021       for (l = 0; l < p->w_width; l++)
 1022         ASSERT(ml->image[l] >= ' ' || ml->font[l] || ml->fontx);
 1023     }
 1024       else
 1025 #endif
 1026         for (l = 0; l < p->w_width; l++)
 1027           ASSERT(ml->image[l] >= ' ');
 1028     }
 1029 #endif
 1030   return 0;
 1031 
 1032 nomem:
 1033   if (nmlines || nhlines)
 1034     {
 1035       for (ty = he + hi - 1; ty >= 0; ty--)
 1036         {
 1037           mlt = NEWWIN(ty);
 1038           FreeMline(mlt);
 1039         }
 1040       if (nmlines && p->w_mlines != nmlines)
 1041         free((char *)nmlines);
 1042 #ifdef COPY_PASTE
 1043       if (nhlines && p->w_hlines != nhlines)
 1044         free((char *)nhlines);
 1045 #endif
 1046     }
 1047   KillWindow(p);
 1048   Msg(0, "%s", strnomem);
 1049   return -1;
 1050 }
 1051 
 1052 void
 1053 FreeAltScreen(p)
 1054 struct win *p;
 1055 {
 1056   int i;
 1057 
 1058   if (p->w_alt.mlines)
 1059     {
 1060       for (i = 0; i < p->w_alt.height; i++)
 1061         FreeMline(p->w_alt.mlines + i);
 1062       free(p->w_alt.mlines);
 1063     }
 1064   p->w_alt.mlines = 0;
 1065   p->w_alt.width = 0;
 1066   p->w_alt.height = 0;
 1067 #ifdef COPY_PASTE
 1068   if (p->w_alt.hlines)
 1069     {
 1070       for (i = 0; i < p->w_alt.histheight; i++)
 1071         FreeMline(p->w_alt.hlines + i);
 1072       free(p->w_alt.hlines);
 1073     }
 1074   p->w_alt.hlines = 0;
 1075   p->w_alt.histidx = 0;
 1076   p->w_alt.histheight = 0;
 1077 #endif
 1078 }
 1079 
 1080 static void
 1081 SwapAltScreen(p)
 1082 struct win *p;
 1083 {
 1084   struct mline *ml;
 1085   int t;
 1086 
 1087 #define SWAP(item, t) do { (t) = p->w_alt. item; p->w_alt. item = p->w_##item; p->w_##item = (t); } while (0)
 1088 
 1089   SWAP(mlines, ml);
 1090   SWAP(width, t);
 1091   SWAP(height, t);
 1092 
 1093 #ifdef COPY_PASTE
 1094   SWAP(histheight, t);
 1095   SWAP(hlines, ml);
 1096   SWAP(histidx, t);
 1097 #endif
 1098 #undef SWAP
 1099 }
 1100 
 1101 void
 1102 EnterAltScreen(p)
 1103 struct win *p;
 1104 {
 1105   if (!p->w_alt.on)
 1106     {
 1107       /* If not already using the alternate screen buffer, then create
 1108      a new one and swap it with the 'real' screen buffer. */
 1109       FreeAltScreen(p);
 1110       SwapAltScreen(p);
 1111     }
 1112   else
 1113     {
 1114       /* Already using the alternate buffer. Just clear the screen. To do so, it
 1115      is only necessary to reset the height(s) without resetting the width. */
 1116       p->w_height = 0;
 1117       p->w_histheight = 0;
 1118     }
 1119   ChangeWindowSize(p, p->w_alt.width, p->w_alt.height, p->w_alt.histheight);
 1120   p->w_alt.on = 1;
 1121 }
 1122 
 1123 void
 1124 LeaveAltScreen(p)
 1125 struct win *p;
 1126 {
 1127   if (!p->w_alt.on)
 1128     return;
 1129   SwapAltScreen(p);
 1130   ChangeWindowSize(p, p->w_alt.width, p->w_alt.height, p->w_alt.histheight);
 1131   FreeAltScreen(p);
 1132   p->w_alt.on = 0;
 1133 }