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