Don't signal WINCH on EnterAltScreen (#23803).
[screen-lua.git] / src / resize.c
blob31ffb74c6d54f37b9aca3bdd896fd0806636a541
1 /* Copyright (c) 1993-2002
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
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.
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.
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.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 ****************************************************************
24 #include <sys/types.h>
25 #include <signal.h>
26 #ifndef sun
27 #include <sys/ioctl.h>
28 #endif
30 #ifdef ISC
31 # include <sys/tty.h>
32 # include <sys/sioctl.h>
33 # include <sys/pty.h>
34 #endif
36 #include "config.h"
37 #include "screen.h"
38 #include "extern.h"
40 static void CheckMaxSize __P((int));
41 static void FreeMline __P((struct mline *));
42 static int AllocMline __P((struct mline *ml, int));
43 static void MakeBlankLine __P((unsigned char *, int));
44 static void kaablamm __P((void));
45 static int BcopyMline __P((struct mline *, int, struct mline *, int, int, int));
46 static void SwapAltScreen __P((struct win *));
48 extern struct layer *flayer;
49 extern struct display *display, *displays;
50 extern unsigned char *blank, *null;
51 extern struct mline mline_blank, mline_null, mline_old;
52 extern struct win *windows;
53 extern int Z0width, Z1width;
54 extern int captionalways;
56 #if defined(TIOCGWINSZ) || defined(TIOCSWINSZ)
57 struct winsize glwz;
58 #endif
60 static struct mline mline_zero = {
61 (unsigned char *)0,
62 (unsigned char *)0
63 #ifdef FONT
64 ,(unsigned char *)0
65 #endif
66 #ifdef COLOR
67 ,(unsigned char *)0
68 # ifdef COLORS256
69 ,(unsigned char *)0
70 # endif
71 #endif
75 * ChangeFlag: 0: try to modify no window
76 * 1: modify fore (and try to modify no other) + redisplay
77 * 2: modify all windows
79 * Note: Activate() is only called if change_flag == 1
80 * i.e. on a WINCH event
83 void
84 CheckScreenSize(change_flag)
85 int change_flag;
87 int wi, he;
89 if (display == 0)
91 debug("CheckScreenSize: No display -> no check.\n");
92 return;
94 #ifdef TIOCGWINSZ
95 if (ioctl(D_userfd, TIOCGWINSZ, (char *)&glwz) != 0)
97 debug2("CheckScreenSize: ioctl(%d, TIOCGWINSZ) errno %d\n", D_userfd, errno);
98 wi = D_CO;
99 he = D_LI;
101 else
103 wi = glwz.ws_col;
104 he = glwz.ws_row;
105 if (wi == 0)
106 wi = D_CO;
107 if (he == 0)
108 he = D_LI;
110 #else
111 wi = D_CO;
112 he = D_LI;
113 #endif
115 debug2("CheckScreenSize: screen is (%d,%d)\n", wi, he);
117 #if 0 /* XXX: Fixme */
118 if (change_flag == 2)
120 debug("Trying to adapt all windows (-A)\n");
121 for (p = windows; p; p = p->w_next)
122 if (p->w_display == 0 || p->w_display == display)
123 ChangeWindowSize(p, wi, he, p->w_histheight);
125 #endif
126 if (D_width == wi && D_height == he)
128 debug("CheckScreenSize: No change -> return.\n");
129 return;
131 #ifdef BLANKER_PRG
132 KillBlanker();
133 #endif
134 ResetIdle();
135 ChangeScreenSize(wi, he, change_flag);
136 /* XXX Redisplay logic */
137 #if 0
138 if (change_flag == 1)
139 Redisplay(D_fore ? D_fore->w_norefresh : 0);
140 #endif
143 void
144 ChangeScreenSize(wi, he, change_fore)
145 int wi, he;
146 int change_fore;
148 struct win *p;
149 struct canvas *cv, **cvpp;
150 int wwi;
151 int y, h, hn, xe, ye;
153 debug2("ChangeScreenSize from (%d,%d) ", D_width, D_height);
154 debug3("to (%d,%d) (change_fore: %d)\n",wi, he, change_fore);
156 cv = &D_canvas;
157 cv->c_xe = wi - 1;
158 cv->c_ye = he - 1 - ((cv->c_slperp && cv->c_slperp->c_slnext) || captionalways) - (D_has_hstatus == HSTATUS_LASTLINE);
159 if (cv->c_slperp)
161 ResizeCanvas(cv);
162 RecreateCanvasChain();
163 RethinkDisplayViewports();
165 if (D_forecv == 0)
166 D_forecv = D_cvlist;
167 if (D_forecv)
168 D_fore = Layer2Window(D_forecv->c_layer);
170 D_width = wi;
171 D_height = he;
173 CheckMaxSize(wi);
174 if (D_CWS)
176 D_defwidth = D_CO;
177 D_defheight = D_LI;
179 else
181 if (D_CZ0 && (wi == Z0width || wi == Z1width) &&
182 (D_CO == Z0width || D_CO == Z1width))
183 D_defwidth = D_CO;
184 else
185 D_defwidth = wi;
186 D_defheight = he;
188 debug2("Default size: (%d,%d)\n", D_defwidth, D_defheight);
189 if (change_fore)
190 ResizeLayersToCanvases();
191 if (change_fore == 2 && D_CWS == NULL && displays->d_next == 0)
193 /* adapt all windows - to be removed ? */
194 for (p = windows; p; p = p->w_next)
196 debug1("Trying to change window %d.\n", p->w_number);
197 wwi = wi;
198 #if 0
199 if (D_CZ0 && p->w_width != wi && (wi == Z0width || wi == Z1width))
201 if (p->w_width > (Z0width + Z1width) / 2)
202 wwi = Z0width;
203 else
204 wwi = Z1width;
206 #endif
207 if (p->w_savelayer && p->w_savelayer->l_cvlist == 0)
208 ResizeLayer(p->w_savelayer, wwi, he, 0);
209 #if 0
210 ChangeWindowSize(p, wwi, he, p->w_histheight);
211 #endif
216 void
217 ResizeLayersToCanvases()
219 struct canvas *cv;
220 struct layer *l;
221 int lx, ly;
223 debug("ResizeLayersToCanvases\n");
224 D_kaablamm = 0;
225 for (cv = D_cvlist; cv; cv = cv->c_next)
227 l = cv->c_layer;
228 if (l == 0)
229 continue;
230 debug("Doing canvas: ");
231 if (l->l_width == cv->c_xe - cv->c_xs + 1 &&
232 l->l_height == cv->c_ye - cv->c_ys + 1)
234 debug("already fitting.\n");
235 continue;
237 if (!MayResizeLayer(l))
239 debug("may not resize.\n");
241 else
243 debug("doing resize.\n");
244 ResizeLayer(l, cv->c_xe - cv->c_xs + 1, cv->c_ye - cv->c_ys + 1, display);
247 /* normalize window, see screen.c */
248 lx = cv->c_layer->l_x;
249 ly = cv->c_layer->l_y;
250 if (ly + cv->c_yoff < cv->c_ys)
252 cv->c_yoff = cv->c_ys - ly;
253 RethinkViewportOffsets(cv);
255 else if (ly + cv->c_yoff > cv->c_ye)
257 cv->c_yoff = cv->c_ye - ly;
258 RethinkViewportOffsets(cv);
260 if (lx + cv->c_xoff < cv->c_xs)
262 int n = cv->c_xs - (lx + cv->c_xoff);
263 if (n < (cv->c_xe - cv->c_xs + 1) / 2)
264 n = (cv->c_xe - cv->c_xs + 1) / 2;
265 if (cv->c_xoff + n > cv->c_xs)
266 n = cv->c_xs - cv->c_xoff;
267 cv->c_xoff += n;
268 RethinkViewportOffsets(cv);
270 else if (lx + cv->c_xoff > cv->c_xe)
272 int n = lx + cv->c_xoff - cv->c_xe;
273 if (n < (cv->c_xe - cv->c_xs + 1) / 2)
274 n = (cv->c_xe - cv->c_xs + 1) / 2;
275 if (cv->c_xoff - n + cv->c_layer->l_width - 1 < cv->c_xe)
276 n = cv->c_xoff + cv->c_layer->l_width - 1 - cv->c_xe;
277 cv->c_xoff -= n;
278 RethinkViewportOffsets(cv);
281 Redisplay(0);
282 if (D_kaablamm)
284 kaablamm();
285 D_kaablamm = 0;
290 MayResizeLayer(l)
291 struct layer *l;
293 int cvs = 0;
294 debug("MayResizeLayer:\n");
295 for (; l; l = l->l_next)
297 if (l->l_cvlist)
298 if (++cvs > 1 || l->l_cvlist->c_lnext)
300 debug1("may not - cvs %d\n", cvs);
301 return 0;
304 debug("may resize\n");
305 return 1;
309 * Easy implementation: rely on the fact that the only layers
310 * supporting resize are Win and Blank. So just kill all overlays.
312 * This is a lot harder if done the right way...
315 static void
316 kaablamm()
318 Msg(0, "Aborted because of window size change.");
321 void
322 ResizeLayer(l, wi, he, norefdisp)
323 struct layer *l;
324 int wi, he;
325 struct display *norefdisp;
327 struct win *p;
328 struct canvas *cv;
329 struct layer *oldflayer = flayer;
330 struct display *d, *olddisplay = display;
332 if (l->l_width == wi && l->l_height == he)
333 return;
334 p = Layer2Window(l);
336 if (oldflayer && (l == oldflayer || Layer2Window(oldflayer) == p))
337 while (oldflayer->l_next)
338 oldflayer = oldflayer->l_next;
340 if (p)
342 for (d = displays; d; d = d->d_next)
343 for (cv = d->d_cvlist; cv; cv = cv->c_next)
345 if (p == Layer2Window(cv->c_layer))
347 flayer = cv->c_layer;
348 if (flayer->l_next)
349 d->d_kaablamm = 1;
350 while (flayer->l_next)
351 ExitOverlayPage();
354 l = p->w_savelayer;
356 flayer = l;
357 if (p == 0 && flayer->l_next && flayer->l_next->l_next == 0 && LayResize(wi, he) == 0)
359 flayer = flayer->l_next;
360 LayResize(wi, he);
361 flayer = l;
363 else
365 if (flayer->l_next)
366 for (cv = flayer->l_cvlist; cv; cv = cv->c_lnext)
367 cv->c_display->d_kaablamm = 1;
368 while (flayer->l_next)
369 ExitOverlayPage();
371 if (p)
372 flayer = &p->w_layer;
373 LayResize(wi, he);
374 /* now everybody is on flayer, redisplay */
375 l = flayer;
376 for (display = displays; display; display = display->d_next)
378 if (display == norefdisp)
379 continue;
380 for (cv = D_cvlist; cv; cv = cv->c_next)
381 if (cv->c_layer == l)
383 CV_CALL(cv, LayRedisplayLine(-1, -1, -1, 0));
384 RefreshArea(cv->c_xs, cv->c_ys, cv->c_xe, cv->c_ye, 0);
386 if (D_kaablamm)
388 kaablamm();
389 D_kaablamm = 0;
392 flayer = oldflayer;
393 display = olddisplay;
397 static void
398 FreeMline(ml)
399 struct mline *ml;
401 if (ml->image)
402 free(ml->image);
403 if (ml->attr && ml->attr != null)
404 free(ml->attr);
405 #ifdef FONT
406 if (ml->font && ml->font != null)
407 free(ml->font);
408 #endif
409 #ifdef COLOR
410 if (ml->color && ml->color != null)
411 free(ml->color);
412 # ifdef COLORS256
413 if (ml->colorx && ml->colorx != null)
414 free(ml->colorx);
415 # endif
416 #endif
417 *ml = mline_zero;
420 static int
421 AllocMline(ml, w)
422 struct mline *ml;
423 int w;
425 ml->image = malloc(w);
426 ml->attr = null;
427 #ifdef FONT
428 ml->font = null;
429 #endif
430 #ifdef COLOR
431 ml->color = null;
432 # ifdef COLORS256
433 ml->colorx = null;
434 # endif
435 #endif
436 if (ml->image == 0)
437 return -1;
438 return 0;
442 static int
443 BcopyMline(mlf, xf, mlt, xt, l, w)
444 struct mline *mlf, *mlt;
445 int xf, xt, l, w;
447 int r = 0;
449 bcopy((char *)mlf->image + xf, (char *)mlt->image + xt, l);
450 if (mlf->attr != null && mlt->attr == null)
452 if ((mlt->attr = (unsigned char *)malloc(w)) == 0)
453 mlt->attr = null, r = -1;
454 bzero((char *)mlt->attr, w);
456 if (mlt->attr != null)
457 bcopy((char *)mlf->attr + xf, (char *)mlt->attr + xt, l);
458 #ifdef FONT
459 if (mlf->font != null && mlt->font == null)
461 if ((mlt->font = (unsigned char *)malloc(w)) == 0)
462 mlt->font = null, r = -1;
463 bzero((char *)mlt->font, w);
465 if (mlt->font != null)
466 bcopy((char *)mlf->font + xf, (char *)mlt->font + xt, l);
467 #endif
468 #ifdef COLOR
469 if (mlf->color != null && mlt->color == null)
471 if ((mlt->color = (unsigned char *)malloc(w)) == 0)
472 mlt->color = null, r = -1;
473 bzero((char *)mlt->color, w);
475 if (mlt->color != null)
476 bcopy((char *)mlf->color + xf, (char *)mlt->color + xt, l);
477 # ifdef COLORS256
478 if (mlf->colorx != null && mlt->colorx == null)
480 if ((mlt->colorx = (unsigned char *)malloc(w)) == 0)
481 mlt->colorx = null, r = -1;
482 bzero((char *)mlt->colorx, w);
484 if (mlt->colorx != null)
485 bcopy((char *)mlf->colorx + xf, (char *)mlt->colorx + xt, l);
486 # endif
487 #endif
488 return r;
492 static int maxwidth;
494 static void
495 CheckMaxSize(wi)
496 int wi;
498 unsigned char *oldnull = null;
499 struct win *p;
500 int i;
501 struct mline *ml;
503 wi = ((wi + 1) + 255) & ~255;
504 if (wi <= maxwidth)
505 return;
506 maxwidth = wi;
507 debug1("New maxwidth: %d\n", maxwidth);
508 blank = (unsigned char *)xrealloc((char *)blank, maxwidth);
509 null = (unsigned char *)xrealloc((char *)null, maxwidth);
510 mline_old.image = (unsigned char *)xrealloc((char *)mline_old.image, maxwidth);
511 mline_old.attr = (unsigned char *)xrealloc((char *)mline_old.attr, maxwidth);
512 #ifdef FONT
513 mline_old.font = (unsigned char *)xrealloc((char *)mline_old.font, maxwidth);
514 #endif
515 #ifdef COLOR
516 mline_old.color = (unsigned char *)xrealloc((char *)mline_old.color, maxwidth);
517 # ifdef COLORS256
518 mline_old.colorx = (unsigned char *)xrealloc((char *)mline_old.color, maxwidth);
519 # endif
520 #endif
521 if (!(blank && null && mline_old.image && mline_old.attr IFFONT(&& mline_old.font) IFCOLOR(&& mline_old.color) IFCOLORX(&& mline_old.colorx)))
522 Panic(0, strnomem);
524 MakeBlankLine(blank, maxwidth);
525 bzero((char *)null, maxwidth);
527 mline_blank.image = blank;
528 mline_blank.attr = null;
529 mline_null.image = null;
530 mline_null.attr = null;
531 #ifdef FONT
532 mline_blank.font = null;
533 mline_null.font = null;
534 #endif
535 #ifdef COLOR
536 mline_blank.color = null;
537 mline_null.color = null;
538 # ifdef COLORS256
539 mline_blank.colorx = null;
540 mline_null.colorx = null;
541 # endif
542 #endif
544 /* We have to run through all windows to substitute
545 * the null references.
547 for (p = windows; p; p = p->w_next)
549 ml = p->w_mlines;
550 for (i = 0; i < p->w_height; i++, ml++)
552 if (ml->attr == oldnull)
553 ml->attr = null;
554 #ifdef FONT
555 if (ml->font == oldnull)
556 ml->font = null;
557 #endif
558 #ifdef COLOR
559 if (ml->color == oldnull)
560 ml->color= null;
561 #ifdef COLORS256
562 if (ml->colorx == oldnull)
563 ml->colorx = null;
564 #endif
565 #endif
567 #ifdef COPY_PASTE
568 ml = p->w_hlines;
569 for (i = 0; i < p->w_histheight; i++, ml++)
571 if (ml->attr == oldnull)
572 ml->attr = null;
573 # ifdef FONT
574 if (ml->font == oldnull)
575 ml->font = null;
576 # endif
577 # ifdef COLOR
578 if (ml->color == oldnull)
579 ml->color= null;
580 # ifdef COLORS256
581 if (ml->colorx == oldnull)
582 ml->colorx = null;
583 # endif
584 # endif
586 #endif
591 char *
592 xrealloc(mem, len)
593 char *mem;
594 int len;
596 register char *nmem;
598 if (mem == 0)
599 return malloc(len);
600 if ((nmem = realloc(mem, len)))
601 return nmem;
602 free(mem);
603 return (char *)0;
606 static void
607 MakeBlankLine(p, n)
608 register unsigned char *p;
609 register int n;
611 while (n--)
612 *p++ = ' ';
618 #ifdef COPY_PASTE
620 #define OLDWIN(y) ((y < p->w_histheight) \
621 ? &p->w_hlines[(p->w_histidx + y) % p->w_histheight] \
622 : &p->w_mlines[y - p->w_histheight])
624 #define NEWWIN(y) ((y < hi) ? &nhlines[y] : &nmlines[y - hi])
626 #else
628 #define OLDWIN(y) (&p->w_mlines[y])
629 #define NEWWIN(y) (&nmlines[y])
631 #endif
635 ChangeWindowSize(p, wi, he, hi)
636 struct win *p;
637 int wi, he, hi;
639 struct mline *mlf = 0, *mlt = 0, *ml, *nmlines, *nhlines;
640 int fy, ty, l, lx, lf, lt, yy, oty, addone;
641 int ncx, ncy, naka, t;
642 int y, shift;
644 if (wi == 0)
645 he = hi = 0;
647 if (p->w_type == W_TYPE_GROUP)
648 return 0;
649 if (p->w_width == wi && p->w_height == he && p->w_histheight == hi)
651 debug("ChangeWindowSize: No change.\n");
652 return 0;
655 CheckMaxSize(wi);
657 /* XXX */
658 #if 0
659 /* just in case ... */
660 if (wi && (p->w_width != wi || p->w_height != he) && p->w_lay != &p->w_winlay)
662 debug("ChangeWindowSize: No resize because of overlay?\n");
663 return -1;
665 #endif
667 debug("ChangeWindowSize");
668 debug3(" from (%d,%d)+%d", p->w_width, p->w_height, p->w_histheight);
669 debug3(" to(%d,%d)+%d\n", wi, he, hi);
671 fy = p->w_histheight + p->w_height - 1;
672 ty = hi + he - 1;
674 nmlines = nhlines = 0;
675 ncx = 0;
676 ncy = 0;
677 naka = 0;
679 if (wi)
681 if (wi != p->w_width || he != p->w_height)
683 if ((nmlines = (struct mline *)calloc(he, sizeof(struct mline))) == 0)
685 KillWindow(p);
686 Msg(0, strnomem);
687 return -1;
690 else
692 debug1("image stays the same: %d lines\n", he);
693 nmlines = p->w_mlines;
694 fy -= he;
695 ty -= he;
696 ncx = p->w_x;
697 ncy = p->w_y;
698 naka = p->w_autoaka;
701 #ifdef COPY_PASTE
702 if (hi)
704 if ((nhlines = (struct mline *)calloc(hi, sizeof(struct mline))) == 0)
706 Msg(0, "No memory for history buffer - turned off");
707 hi = 0;
708 ty = he - 1;
711 #endif
713 /* special case: cursor is at magic margin position */
714 addone = 0;
715 if (p->w_width && p->w_x == p->w_width)
717 debug2("Special addone case: %d %d\n", p->w_x, p->w_y);
718 addone = 1;
719 p->w_x--;
722 /* handle the cursor and autoaka lines now if the widths are equal */
723 if (p->w_width == wi)
725 ncx = p->w_x + addone;
726 ncy = p->w_y + he - p->w_height;
727 /* never lose sight of the line with the cursor on it */
728 shift = -ncy;
729 for (yy = p->w_y + p->w_histheight - 1; yy >= 0 && ncy + shift < he; yy--)
731 ml = OLDWIN(yy);
732 if (ml->image[p->w_width] == ' ')
733 break;
734 shift++;
736 if (shift < 0)
737 shift = 0;
738 else
739 debug1("resize: cursor out of bounds, shifting %d\n", shift);
740 ncy += shift;
741 if (p->w_autoaka > 0)
743 naka = p->w_autoaka + he - p->w_height + shift;
744 if (naka < 1 || naka > he)
745 naka = 0;
747 while (shift-- > 0)
749 ml = OLDWIN(fy);
750 FreeMline(ml);
751 fy--;
754 debug2("fy %d ty %d\n", fy, ty);
755 if (fy >= 0)
756 mlf = OLDWIN(fy);
757 if (ty >= 0)
758 mlt = NEWWIN(ty);
760 while (fy >= 0 && ty >= 0)
762 if (p->w_width == wi)
764 /* here is a simple shortcut: just copy over */
765 *mlt = *mlf;
766 *mlf = mline_zero;
767 if (--fy >= 0)
768 mlf = OLDWIN(fy);
769 if (--ty >= 0)
770 mlt = NEWWIN(ty);
771 continue;
774 /* calculate lenght */
775 for (l = p->w_width - 1; l > 0; l--)
776 if (mlf->image[l] != ' ' || mlf->attr[l])
777 break;
778 if (fy == p->w_y + p->w_histheight && l < p->w_x)
779 l = p->w_x; /* cursor is non blank */
780 l++;
781 lf = l;
783 /* add wrapped lines to length */
784 for (yy = fy - 1; yy >= 0; yy--)
786 ml = OLDWIN(yy);
787 if (ml->image[p->w_width] == ' ')
788 break;
789 l += p->w_width;
792 /* rewrap lines */
793 lt = (l - 1) % wi + 1; /* lf is set above */
794 oty = ty;
795 while (l > 0 && fy >= 0 && ty >= 0)
797 lx = lt > lf ? lf : lt;
798 if (mlt->image == 0)
800 if (AllocMline(mlt, wi + 1))
801 goto nomem;
802 MakeBlankLine(mlt->image + lt, wi - lt);
803 mlt->image[wi] = ((oty == ty) ? ' ' : 0);
805 if (BcopyMline(mlf, lf - lx, mlt, lt - lx, lx, wi + 1))
806 goto nomem;
808 /* did we copy the cursor ? */
809 if (fy == p->w_y + p->w_histheight && lf - lx <= p->w_x && lf > p->w_x)
811 ncx = p->w_x + lt - lf + addone;
812 ncy = ty - hi;
813 shift = wi ? -ncy + (l - lx) / wi : 0;
814 if (ty + shift > hi + he - 1)
815 shift = hi + he - 1 - ty;
816 if (shift > 0)
818 debug3("resize: cursor out of bounds, shifting %d [%d/%d]\n", shift, lt - lx, wi);
819 for (y = hi + he - 1; y >= ty; y--)
821 mlt = NEWWIN(y);
822 FreeMline(mlt);
823 if (y - shift < ty)
824 continue;
825 ml = NEWWIN(y - shift);
826 *mlt = *ml;
827 *ml = mline_zero;
829 ncy += shift;
830 ty += shift;
831 mlt = NEWWIN(ty);
832 if (naka > 0)
833 naka = naka + shift > he ? 0 : naka + shift;
835 ASSERT(ncy >= 0);
837 /* did we copy autoaka line ? */
838 if (p->w_autoaka > 0 && fy == p->w_autoaka - 1 + p->w_histheight && lf - lx <= 0)
839 naka = ty - hi >= 0 ? 1 + ty - hi : 0;
841 lf -= lx;
842 lt -= lx;
843 l -= lx;
844 if (lf == 0)
846 FreeMline(mlf);
847 lf = p->w_width;
848 if (--fy >= 0)
849 mlf = OLDWIN(fy);
851 if (lt == 0)
853 lt = wi;
854 if (--ty >= 0)
855 mlt = NEWWIN(ty);
858 ASSERT(l != 0 || fy == yy);
860 while (fy >= 0)
862 FreeMline(mlf);
863 if (--fy >= 0)
864 mlf = OLDWIN(fy);
866 while (ty >= 0)
868 if (AllocMline(mlt, wi + 1))
869 goto nomem;
870 MakeBlankLine(mlt->image, wi + 1);
871 if (--ty >= 0)
872 mlt = NEWWIN(ty);
875 #ifdef DEBUG
876 if (nmlines != p->w_mlines)
877 for (fy = 0; fy < p->w_height + p->w_histheight; fy++)
879 ml = OLDWIN(fy);
880 ASSERT(ml->image == 0);
882 #endif
884 if (p->w_mlines && p->w_mlines != nmlines)
885 free((char *)p->w_mlines);
886 p->w_mlines = nmlines;
887 #ifdef COPY_PASTE
888 if (p->w_hlines && p->w_hlines != nhlines)
889 free((char *)p->w_hlines);
890 p->w_hlines = nhlines;
891 #endif
892 nmlines = nhlines = 0;
894 /* change tabs */
895 if (p->w_width != wi)
897 if (wi)
899 t = p->w_tabs ? p->w_width : 0;
900 p->w_tabs = xrealloc(p->w_tabs, wi + 1);
901 if (p->w_tabs == 0)
903 nomem:
904 if (nmlines)
906 for (ty = he + hi - 1; ty >= 0; ty--)
908 mlt = NEWWIN(ty);
909 FreeMline(mlt);
911 if (nmlines && p->w_mlines != nmlines)
912 free((char *)nmlines);
913 #ifdef COPY_PASTE
914 if (nhlines && p->w_hlines != nhlines)
915 free((char *)nhlines);
916 #endif
918 KillWindow(p);
919 Msg(0, strnomem);
920 return -1;
922 for (; t < wi; t++)
923 p->w_tabs[t] = t && !(t & 7) ? 1 : 0;
924 p->w_tabs[wi] = 0;
926 else
928 if (p->w_tabs)
929 free(p->w_tabs);
930 p->w_tabs = 0;
934 /* Change w_Saved_y - this is only an estimate... */
935 p->w_Saved_y += ncy - p->w_y;
937 p->w_x = ncx;
938 p->w_y = ncy;
939 if (p->w_autoaka > 0)
940 p->w_autoaka = naka;
942 /* do sanity checks */
943 if (p->w_x > wi)
944 p->w_x = wi;
945 if (p->w_y >= he)
946 p->w_y = he - 1;
947 if (p->w_Saved_x > wi)
948 p->w_Saved_x = wi;
949 if (p->w_Saved_y < 0)
950 p->w_Saved_y = 0;
951 if (p->w_Saved_y >= he)
952 p->w_Saved_y = he - 1;
954 /* reset scrolling region */
955 p->w_top = 0;
956 p->w_bot = he - 1;
958 /* signal new size to window */
959 #ifdef TIOCSWINSZ
960 if (wi && (p->w_width != wi || p->w_height != he)
961 && p->w_width != 0 && p->w_height != 0 && p->w_ptyfd >= 0 && p->w_pid)
963 glwz.ws_col = wi;
964 glwz.ws_row = he;
965 debug("Setting pty winsize.\n");
966 if (ioctl(p->w_ptyfd, TIOCSWINSZ, (char *)&glwz))
967 debug2("SetPtySize: errno %d (fd:%d)\n", errno, p->w_ptyfd);
969 #endif /* TIOCSWINSZ */
971 /* store new size */
972 p->w_width = wi;
973 p->w_height = he;
974 #ifdef COPY_PASTE
975 p->w_histidx = 0;
976 p->w_histheight = hi;
977 #endif
979 #ifdef BUILTIN_TELNET
980 if (p->w_type == W_TYPE_TELNET)
981 TelWindowSize(p);
982 #endif
984 #ifdef DEBUG
985 /* Test if everything was ok */
986 for (fy = 0; fy < p->w_height + p->w_histheight; fy++)
988 ml = OLDWIN(fy);
989 ASSERT(ml->image);
990 # ifdef UTF8
991 if (p->w_encoding == UTF8)
993 for (l = 0; l < p->w_width; l++)
994 ASSERT(ml->image[l] >= ' ' || ml->font[l]);
996 else
997 #endif
998 for (l = 0; l < p->w_width; l++)
999 ASSERT(ml->image[l] >= ' ');
1001 #endif
1002 return 0;
1005 void
1006 FreeAltScreen(p)
1007 struct win *p;
1009 int i;
1011 if (p->w_alt_mlines)
1013 for (i = 0; i < p->w_alt_height; i++)
1014 FreeMline(p->w_alt_mlines + i);
1015 free(p->w_alt_mlines);
1017 p->w_alt_mlines = 0;
1018 p->w_alt_width = 0;
1019 p->w_alt_height = 0;
1020 p->w_alt_x = 0;
1021 p->w_alt_y = 0;
1022 #ifdef COPY_PASTE
1023 if (p->w_alt_hlines)
1025 for (i = 0; i < p->w_alt_histheight; i++)
1026 FreeMline(p->w_alt_hlines + i);
1027 free(p->w_alt_hlines);
1029 p->w_alt_hlines = 0;
1030 p->w_alt_histidx = 0;
1031 #endif
1032 p->w_alt_histheight = 0;
1035 static void
1036 SwapAltScreen(p)
1037 struct win *p;
1039 struct mline *ml;
1040 int t;
1042 ml = p->w_alt_mlines; p->w_alt_mlines = p->w_mlines; p->w_mlines = ml;
1043 t = p->w_alt_width; p->w_alt_width = p->w_width; p->w_width = t;
1044 t = p->w_alt_height; p->w_alt_height = p->w_height; p->w_height = t;
1045 t = p->w_alt_histheight; p->w_alt_histheight = p->w_histheight; p->w_histheight = t;
1046 t = p->w_alt_x; p->w_alt_x = p->w_x; p->w_x = t;
1047 t = p->w_alt_y; p->w_alt_y = p->w_y; p->w_y = t;
1048 #ifdef COPY_PASTE
1049 ml = p->w_alt_hlines; p->w_alt_hlines = p->w_hlines; p->w_hlines = ml;
1050 t = p->w_alt_histidx; p->w_alt_histidx = p->w_histidx; p->w_histidx = t;
1051 #endif
1054 void
1055 EnterAltScreen(p)
1056 struct win *p;
1058 int ox = p->w_x, oy = p->w_y;
1059 FreeAltScreen(p);
1060 SwapAltScreen(p);
1061 ChangeWindowSize(p, p->w_alt_width, p->w_alt_height, p->w_alt_histheight);
1062 p->w_x = ox;
1063 p->w_y = oy;
1066 void
1067 LeaveAltScreen(p)
1068 struct win *p;
1070 if (!p->w_alt_mlines)
1071 return;
1072 SwapAltScreen(p);
1073 ChangeWindowSize(p, p->w_alt_width, p->w_alt_height, p->w_alt_histheight);
1074 FreeAltScreen(p);