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#include <fcntl.h> 27#ifndef sun 28# include <sys/ioctl.h> 29#endif 30 31#include "config.h" 32#include "screen.h" 33#include "extern.h" 34#include "braille.h" 35 36static int CountChars __P((int)); 37static int DoAddChar __P((int)); 38static int BlankResize __P((int, int)); 39static int CallRewrite __P((int, int, int, int)); 40static void FreeCanvas __P((struct canvas *)); 41static void disp_readev_fn __P((struct event *, char *)); 42static void disp_writeev_fn __P((struct event *, char *)); 43#ifdef linux 44static void disp_writeev_eagain __P((struct event *, char *)); 45#endif 46static void disp_status_fn __P((struct event *, char *)); 47static void disp_hstatus_fn __P((struct event *, char *)); 48static void disp_blocked_fn __P((struct event *, char *)); 49static void cv_winid_fn __P((struct event *, char *)); 50#ifdef MAPKEYS 51static void disp_map_fn __P((struct event *, char *)); 52#endif 53static void disp_idle_fn __P((struct event *, char *)); 54#ifdef BLANKER_PRG 55static void disp_blanker_fn __P((struct event *, char *)); 56#endif 57static void WriteLP __P((int, int)); 58static void INSERTCHAR __P((int)); 59static void RAW_PUTCHAR __P((int)); 60#ifdef COLOR 61static void SetBackColor __P((int)); 62#endif 63 64 65extern struct layer *flayer; 66extern struct win *windows, *fore; 67extern struct LayFuncs WinLf; 68 69extern int use_hardstatus; 70extern int MsgWait, MsgMinWait; 71extern int Z0width, Z1width; 72extern unsigned char *blank, *null; 73extern struct mline mline_blank, mline_null, mline_old; 74extern struct mchar mchar_null, mchar_blank, mchar_so; 75extern struct NewWindow nwin_default; 76extern struct action idleaction; 77 78/* XXX shouldn't be here */ 79extern char *hstatusstring; 80extern char *captionstring; 81 82extern int pastefont; 83extern int idletimo; 84 85#ifdef BLANKER_PRG 86extern int pty_preopen; 87#if defined(TIOCSWINSZ) || defined(TIOCGWINSZ) 88extern struct winsize glwz; 89#endif 90extern char **NewEnv; 91extern int real_uid, real_gid; 92#endif 93 94/* 95 * tputs needs this to calculate the padding 96 */ 97#ifndef NEED_OSPEED 98extern 99#endif /* NEED_OSPEED */ 100short ospeed; 101 102 103struct display *display, *displays; 104#ifdef COLOR 105int attr2color[8][4]; 106int nattr2color; 107#endif 108 109#ifndef MULTI 110struct display TheDisplay; 111#endif 112 113/* 114 * The default values 115 */ 116int defobuflimit = OBUF_MAX; 117int defnonblock = -1; 118#ifdef AUTO_NUKE 119int defautonuke = 0; 120#endif 121int captionalways; 122int hardstatusemu = HSTATUS_IGNORE; 123 124/* 125 * Default layer management 126 */ 127 128void 129DefProcess(bufp, lenp) 130char **bufp; 131int *lenp; 132{ 133 *bufp += *lenp; 134 *lenp = 0; 135} 136 137void 138DefRedisplayLine(y, xs, xe, isblank) 139int y, xs, xe, isblank; 140{ 141 if (isblank == 0 && y >= 0) 142 DefClearLine(y, xs, xe, 0); 143} 144 145void 146DefClearLine(y, xs, xe, bce) 147int y, xs, xe, bce; 148{ 149 LClearLine(flayer, y, xs, xe, bce, (struct mline *)0); 150} 151 152/*ARGSUSED*/ 153int 154DefRewrite(y, xs, xe, rend, doit) 155int y, xs, xe, doit; 156struct mchar *rend; 157{ 158 return EXPENSIVE; 159} 160 161/*ARGSUSED*/ 162int 163DefResize(wi, he) 164int wi, he; 165{ 166 return -1; 167} 168 169void 170DefRestore() 171{ 172 LAY_DISPLAYS(flayer, InsertMode(0)); 173 /* ChangeScrollRegion(0, D_height - 1); */ 174 LKeypadMode(flayer, 0); 175 LCursorkeysMode(flayer, 0); 176 LCursorVisibility(flayer, 0); 177 LMouseMode(flayer, 0); 178 LSetRendition(flayer, &mchar_null); 179 LSetFlow(flayer, nwin_default.flowflag & FLOW_NOW); 180} 181 182/* 183 * Blank layer management 184 */ 185 186struct LayFuncs BlankLf = 187{ 188 DefProcess, 189 0, 190 DefRedisplayLine, 191 DefClearLine, 192 DefRewrite, 193 BlankResize, 194 DefRestore 195}; 196 197/*ARGSUSED*/ 198static int 199BlankResize(wi, he) 200int wi, he; 201{ 202 flayer->l_width = wi; 203 flayer->l_height = he; 204 return 0; 205} 206 207 208/* 209 * Generate new display, start with a blank layer. 210 * The termcap arrays are not initialised here. 211 * The new display is placed in the displays list. 212 */ 213 214struct display * 215MakeDisplay(uname, utty, term, fd, pid, Mode) 216char *uname, *utty, *term; 217int fd, pid; 218struct mode *Mode; 219{ 220 struct acluser **u; 221 struct baud_values *b; 222 223 if (!*(u = FindUserPtr(uname)) && UserAdd(uname, (char *)0, u)) 224 return 0; /* could not find or add user */ 225 226#ifdef MULTI 227 if ((display = (struct display *)calloc(1, sizeof(*display))) == 0) 228 return 0; 229#else 230 if (displays) 231 return 0; 232 bzero((char *)&TheDisplay, sizeof(TheDisplay)); 233 display = &TheDisplay; 234#endif 235 display->d_next = displays; 236 displays = display; 237 D_flow = 1; 238 D_nonblock = defnonblock; 239 D_userfd = fd; 240 D_readev.fd = D_writeev.fd = fd; 241 D_readev.type = EV_READ; 242 D_writeev.type = EV_WRITE; 243 D_readev.data = D_writeev.data = (char *)display; 244 D_readev.handler = disp_readev_fn; 245 D_writeev.handler = disp_writeev_fn; 246 evenq(&D_readev); 247 D_writeev.condpos = &D_obuflen; 248 D_writeev.condneg = &D_obuffree; 249 evenq(&D_writeev); 250 D_statusev.type = EV_TIMEOUT; 251 D_statusev.data = (char *)display; 252 D_statusev.handler = disp_status_fn; 253 D_hstatusev.type = EV_TIMEOUT; 254 D_hstatusev.data = (char *)display; 255 D_hstatusev.handler = disp_hstatus_fn; 256 D_blockedev.type = EV_TIMEOUT; 257 D_blockedev.data = (char *)display; 258 D_blockedev.handler = disp_blocked_fn; 259 D_blockedev.condpos = &D_obuffree; 260 D_blockedev.condneg = &D_obuflenmax; 261 D_hstatusev.handler = disp_hstatus_fn; 262#ifdef MAPKEYS 263 D_mapev.type = EV_TIMEOUT; 264 D_mapev.data = (char *)display; 265 D_mapev.handler = disp_map_fn; 266#endif 267 D_idleev.type = EV_TIMEOUT; 268 D_idleev.data = (char *)display; 269 D_idleev.handler = disp_idle_fn; 270#ifdef BLANKER_PRG 271 D_blankerev.type = EV_READ; 272 D_blankerev.data = (char *)display; 273 D_blankerev.handler = disp_blanker_fn; 274 D_blankerev.fd = -1; 275#endif 276 D_OldMode = *Mode; 277 D_status_obuffree = -1; 278 Resize_obuf(); /* Allocate memory for buffer */ 279 D_obufmax = defobuflimit; 280 D_obuflenmax = D_obuflen - D_obufmax; 281#ifdef AUTO_NUKE 282 D_auto_nuke = defautonuke; 283#endif 284 D_obufp = D_obuf; 285 D_printfd = -1; 286 D_userpid = pid; 287 288#ifdef POSIX 289 if ((b = lookup_baud((int)cfgetospeed(&D_OldMode.tio)))) 290 D_dospeed = b->idx; 291#else 292# ifdef TERMIO 293 if ((b = lookup_baud(D_OldMode.tio.c_cflag & CBAUD))) 294 D_dospeed = b->idx; 295# else 296 D_dospeed = (short)D_OldMode.m_ttyb.sg_ospeed; 297# endif 298#endif 299 debug1("New displays ospeed = %d\n", D_dospeed); 300 301 strncpy(D_usertty, utty, sizeof(D_usertty) - 1); 302 D_usertty[sizeof(D_usertty) - 1] = 0; 303 strncpy(D_termname, term, sizeof(D_termname) - 1); 304 D_termname[sizeof(D_termname) - 1] = 0; 305 D_user = *u; 306 D_processinput = ProcessInput; 307 return display; 308} 309 310 311void 312FreeDisplay() 313{ 314 struct win *p; 315 struct canvas *cv, *cvp; 316#ifdef MULTI 317 struct display *d, **dp; 318#endif 319 320#ifdef FONT 321 FreeTransTable(); 322#endif 323#ifdef BLANKER_PRG 324 KillBlanker(); 325#endif 326 if (D_userfd >= 0) 327 { 328 Flush(); 329 if (!display) 330 return; 331 SetTTY(D_userfd, &D_OldMode); 332 fcntl(D_userfd, F_SETFL, 0); 333 } 334 freetty(); 335 if (D_tentry) 336 free(D_tentry); 337 D_tentry = 0; 338 if (D_processinputdata) 339 free(D_processinputdata); 340 D_processinputdata = 0; 341 D_tcinited = 0; 342 evdeq(&D_hstatusev); 343 evdeq(&D_statusev); 344 evdeq(&D_readev); 345 evdeq(&D_writeev); 346 evdeq(&D_blockedev); 347#ifdef MAPKEYS 348 evdeq(&D_mapev); 349 if (D_kmaps) 350 { 351 free(D_kmaps); 352 D_kmaps = 0; 353 D_aseqs = 0; 354 D_nseqs = 0; 355 D_seqp = 0; 356 D_seql = 0; 357 D_seqh = 0; 358 } 359#endif 360 evdeq(&D_idleev); 361#ifdef BLANKER_PRG 362 evdeq(&D_blankerev); 363#endif 364#ifdef HAVE_BRAILLE 365 if (bd.bd_dpy == display) 366 { 367 bd.bd_start_braille = 0; 368 StartBraille(); 369 } 370#endif 371 372#ifdef MULTI 373 for (dp = &displays; (d = *dp) ; dp = &d->d_next) 374 if (d == display) 375 break; 376 ASSERT(d); 377 if (D_status_lastmsg) 378 free(D_status_lastmsg); 379 if (D_obuf) 380 free(D_obuf); 381 *dp = display->d_next; 382 cv = display->d_cvlist; 383#else /* MULTI */ 384 ASSERT(display == displays); 385 ASSERT(display == &TheDisplay); 386 cv = display->d_cvlist; 387 display->d_cvlist = 0; 388 displays = 0; 389#endif /* MULTI */ 390 391 for (p = windows; p; p = p->w_next) 392 { 393 if (p->w_pdisplay == display) 394 p->w_pdisplay = 0; 395 if (p->w_lastdisp == display) 396 p->w_lastdisp = 0; 397 if (p->w_readev.condneg == &D_status || p->w_readev.condneg == &D_obuflenmax) 398 p->w_readev.condpos = p->w_readev.condneg = 0; 399 } 400 for (; cv; cv = cvp) 401 { 402 cvp = cv->c_next; 403 FreeCanvas(cv); 404 } 405#ifdef ZMODEM 406 for (p = windows; p; p = p->w_next) 407 if (p->w_zdisplay == display) 408 zmodem_abort(p, 0); 409#endif 410#ifdef MULTI 411 free((char *)display); 412#endif 413 display = 0; 414} 415 416int 417MakeDefaultCanvas() 418{ 419 struct canvas *cv; 420 421 ASSERT(display); 422 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0) 423 return -1; 424 cv->c_xs = 0; 425 cv->c_xe = D_width - 1; 426 cv->c_ys = 0; 427 cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways; 428 cv->c_xoff = 0; 429 cv->c_yoff = 0; 430 cv->c_next = 0; 431 cv->c_display = display; 432 cv->c_vplist = 0; 433 cv->c_captev.type = EV_TIMEOUT; 434 cv->c_captev.data = (char *)cv; 435 cv->c_captev.handler = cv_winid_fn; 436 437 cv->c_blank.l_cvlist = cv; 438 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1; 439 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; 440 cv->c_blank.l_x = cv->c_blank.l_y = 0; 441 cv->c_blank.l_layfn = &BlankLf; 442 cv->c_blank.l_data = 0; 443 cv->c_blank.l_next = 0; 444 cv->c_blank.l_bottom = &cv->c_blank; 445 cv->c_blank.l_blocking = 0; 446 cv->c_layer = &cv->c_blank; 447 cv->c_lnext = 0; 448 449 D_cvlist = cv; 450 RethinkDisplayViewports(); 451 D_forecv = cv; /* default input focus */ 452 return 0; 453} 454 455static void 456FreeCanvas(cv) 457struct canvas *cv; 458{ 459 struct viewport *vp, *nvp; 460 struct win *p; 461 462 p = Layer2Window(cv->c_layer); 463 SetCanvasWindow(cv, 0); 464 if (p) 465 WindowChanged(p, 'u'); 466 if (flayer == cv->c_layer) 467 flayer = 0; 468 for (vp = cv->c_vplist; vp; vp = nvp) 469 { 470 vp->v_canvas = 0; 471 nvp = vp->v_next; 472 vp->v_next = 0; 473 free(vp); 474 } 475 evdeq(&cv->c_captev); 476 free(cv); 477} 478 479int 480AddCanvas() 481{ 482 int hh, h, i, j; 483 struct canvas *cv, **cvpp; 484 485 for (cv = D_cvlist, j = 0; cv; cv = cv->c_next) 486 j++; 487 j++; /* new canvas */ 488 h = D_height - (D_has_hstatus == HSTATUS_LASTLINE); 489 if (h / j <= 1) 490 return -1; 491 492 for (cv = D_cvlist; cv; cv = cv->c_next) 493 if (cv == D_forecv) 494 break; 495 ASSERT(cv); 496 cvpp = &cv->c_next; 497 498 if ((cv = (struct canvas *)calloc(1, sizeof *cv)) == 0) 499 return -1; 500 501 cv->c_xs = 0; 502 cv->c_xe = D_width - 1; 503 cv->c_ys = 0; 504 cv->c_ye = D_height - 1; 505 cv->c_xoff = 0; 506 cv->c_yoff = 0; 507 cv->c_display = display; 508 cv->c_vplist = 0; 509 cv->c_captev.type = EV_TIMEOUT; 510 cv->c_captev.data = (char *)cv; 511 cv->c_captev.handler = cv_winid_fn; 512 513 cv->c_blank.l_cvlist = cv; 514 cv->c_blank.l_width = cv->c_xe - cv->c_xs + 1; 515 cv->c_blank.l_height = cv->c_ye - cv->c_ys + 1; 516 cv->c_blank.l_x = cv->c_blank.l_y = 0; 517 cv->c_blank.l_layfn = &BlankLf; 518 cv->c_blank.l_data = 0; 519 cv->c_blank.l_next = 0; 520 cv->c_blank.l_bottom = &cv->c_blank; 521 cv->c_blank.l_blocking = 0; 522 cv->c_layer = &cv->c_blank; 523 cv->c_lnext = 0; 524 525 cv->c_next = *cvpp; 526 *cvpp = cv; 527 528 i = 0; 529 for (cv = D_cvlist; cv; cv = cv->c_next) 530 { 531 hh = h / j-- - 1; 532 cv->c_ys = i; 533 cv->c_ye = i + hh - 1; 534 cv->c_yoff = i; 535 i += hh + 1; 536 h -= hh + 1; 537 } 538 539 RethinkDisplayViewports(); 540 ResizeLayersToCanvases(); 541 return 0; 542} 543 544void 545RemCanvas() 546{ 547 int hh, h, i, j; 548 struct canvas *cv, **cvpp; 549 int did = 0; 550 551 h = D_height - (D_has_hstatus == HSTATUS_LASTLINE); 552 for (cv = D_cvlist, j = 0; cv; cv = cv->c_next) 553 j++; 554 if (j == 1) 555 return; 556 i = 0; 557 j--; 558 for (cvpp = &D_cvlist; (cv = *cvpp); cvpp = &cv->c_next) 559 { 560 if (cv == D_forecv && !did) 561 { 562 *cvpp = cv->c_next; 563 FreeCanvas(cv); 564 cv = *cvpp; 565 D_forecv = cv ? cv : D_cvlist; 566 D_fore = Layer2Window(D_forecv->c_layer); 567 flayer = D_forecv->c_layer; 568 if (cv == 0) 569 break; 570 did = 1; 571 } 572 hh = h / j-- - 1; 573 if (!captionalways && i == 0 && j == 0) 574 hh++; 575 cv->c_ys = i; 576 cv->c_ye = i + hh - 1; 577 cv->c_yoff = i; 578 i += hh + 1; 579 h -= hh + 1; 580 } 581 RethinkDisplayViewports(); 582 ResizeLayersToCanvases(); 583} 584 585void 586OneCanvas() 587{ 588 struct canvas *mycv = D_forecv; 589 struct canvas *cv, **cvpp; 590 591 for (cvpp = &D_cvlist; (cv = *cvpp);) 592 { 593 if (cv == mycv) 594 { 595 cv->c_ys = 0; 596 cv->c_ye = D_height - 1 - (D_has_hstatus == HSTATUS_LASTLINE) - captionalways; 597 cv->c_yoff = 0; 598 cvpp = &cv->c_next; 599 } 600 else 601 { 602 *cvpp = cv->c_next; 603 FreeCanvas(cv); 604 } 605 } 606 RethinkDisplayViewports(); 607 ResizeLayersToCanvases(); 608} 609 610int 611RethinkDisplayViewports() 612{ 613 struct canvas *cv; 614 struct viewport *vp, *vpn; 615 616 /* free old viewports */ 617 for (cv = display->d_cvlist; cv; cv = cv->c_next) 618 { 619 for (vp = cv->c_vplist; vp; vp = vpn) 620 { 621 vp->v_canvas = 0; 622 vpn = vp->v_next; 623 bzero((char *)vp, sizeof(*vp)); 624 free(vp); 625 } 626 cv->c_vplist = 0; 627 } 628 display->d_vpxmin = -1; 629 display->d_vpxmax = -1; 630 631 for (cv = display->d_cvlist; cv; cv = cv->c_next) 632 { 633 if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) 634 return -1; 635#ifdef HOLE 636 vp->v_canvas = cv; 637 vp->v_xs = cv->c_xs; 638 vp->v_ys = (cv->c_ys + cv->c_ye) / 2; 639 vp->v_xe = cv->c_xe; 640 vp->v_ye = cv->c_ye; 641 vp->v_xoff = cv->c_xoff; 642 vp->v_yoff = cv->c_yoff; 643 vp->v_next = cv->c_vplist; 644 cv->c_vplist = vp; 645 646 if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) 647 return -1; 648 vp->v_canvas = cv; 649 vp->v_xs = (cv->c_xs + cv->c_xe) / 2; 650 vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4; 651 vp->v_xe = cv->c_xe; 652 vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1; 653 vp->v_xoff = cv->c_xoff; 654 vp->v_yoff = cv->c_yoff; 655 vp->v_next = cv->c_vplist; 656 cv->c_vplist = vp; 657 658 if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) 659 return -1; 660 vp->v_canvas = cv; 661 vp->v_xs = cv->c_xs; 662 vp->v_ys = (3 * cv->c_ys + cv->c_ye) / 4; 663 vp->v_xe = (3 * cv->c_xs + cv->c_xe) / 4 - 1; 664 vp->v_ye = (cv->c_ys + cv->c_ye) / 2 - 1; 665 vp->v_xoff = cv->c_xoff; 666 vp->v_yoff = cv->c_yoff; 667 vp->v_next = cv->c_vplist; 668 cv->c_vplist = vp; 669 670 if ((vp = (struct viewport *)malloc(sizeof *vp)) == 0) 671 return -1; 672 vp->v_canvas = cv; 673 vp->v_xs = cv->c_xs; 674 vp->v_ys = cv->c_ys; 675 vp->v_xe = cv->c_xe; 676 vp->v_ye = (3 * cv->c_ys + cv->c_ye) / 4 - 1; 677 vp->v_xoff = cv->c_xoff; 678 vp->v_yoff = cv->c_yoff; 679 vp->v_next = cv->c_vplist; 680 cv->c_vplist = vp; 681#else 682 vp->v_canvas = cv; 683 vp->v_xs = cv->c_xs; 684 vp->v_ys = cv->c_ys; 685 vp->v_xe = cv->c_xe; 686 vp->v_ye = cv->c_ye; 687 vp->v_xoff = cv->c_xoff; 688 vp->v_yoff = cv->c_yoff; 689 vp->v_next = cv->c_vplist; 690 cv->c_vplist = vp; 691#endif 692 693 if (cv->c_xs < display->d_vpxmin || display->d_vpxmin == -1) 694 display->d_vpxmin = cv->c_xs; 695 if (cv->c_xe > display->d_vpxmax || display->d_vpxmax == -1) 696 display->d_vpxmax = cv->c_xe; 697 } 698 return 0; 699} 700 701void 702RethinkViewportOffsets(cv) 703struct canvas *cv; 704{ 705 struct viewport *vp; 706 707 for (vp = cv->c_vplist; vp; vp = vp->v_next) 708 { 709 vp->v_xoff = cv->c_xoff; 710 vp->v_yoff = cv->c_yoff; 711 } 712} 713 714/* 715 * if the adaptflag is on, we keep the size of this display, else 716 * we may try to restore our old window sizes. 717 */ 718void 719InitTerm(adapt) 720int adapt; 721{ 722 ASSERT(display); 723 ASSERT(D_tcinited); 724 D_top = D_bot = -1; 725 AddCStr(D_TI); 726 AddCStr(D_IS); 727 /* Check for toggle */ 728 if (D_IM && strcmp(D_IM, D_EI)) 729 AddCStr(D_EI); 730 D_insert = 0; 731#ifdef MAPKEYS 732 AddCStr(D_KS); 733 AddCStr(D_CCS); 734#else 735 /* Check for toggle */ 736 if (D_KS && strcmp(D_KS, D_KE)) 737 AddCStr(D_KE); 738 if (D_CCS && strcmp(D_CCS, D_CCE)) 739 AddCStr(D_CCE); 740#endif 741 D_keypad = 0; 742 D_cursorkeys = 0; 743 AddCStr(D_ME); 744 AddCStr(D_EA); 745 AddCStr(D_CE0); 746 D_rend = mchar_null; 747 D_atyp = 0; 748 if (adapt == 0) 749 ResizeDisplay(D_defwidth, D_defheight); 750 ChangeScrollRegion(0, D_height - 1); 751 D_x = D_y = 0; 752 Flush(); 753 ClearAll(); 754 debug1("we %swant to adapt all our windows to the display\n", 755 (adapt) ? "" : "don't "); 756 /* In case the size was changed by a init sequence */ 757 CheckScreenSize((adapt) ? 2 : 0); 758} 759 760void 761FinitTerm() 762{ 763 ASSERT(display); 764#ifdef BLANKER_PRG 765 KillBlanker(); 766#endif 767 if (D_tcinited) 768 { 769 ResizeDisplay(D_defwidth, D_defheight); 770 InsertMode(0); 771 ChangeScrollRegion(0, D_height - 1); 772 KeypadMode(0); 773 CursorkeysMode(0); 774 CursorVisibility(0); 775 MouseMode(0); 776 SetRendition(&mchar_null); 777 SetFlow(FLOW_NOW); 778#ifdef MAPKEYS 779 AddCStr(D_KE); 780 AddCStr(D_CCE); 781#endif 782 if (D_hstatus) 783 ShowHStatus((char *)0); 784#ifdef RXVT_OSC 785 ClearAllXtermOSC(); 786#endif 787 D_x = D_y = -1; 788 GotoPos(0, D_height - 1); 789 AddChar('\r'); 790 AddChar('\n'); 791 AddCStr(D_TE); 792 } 793 Flush(); 794} 795 796 797static void 798INSERTCHAR(c) 799int c; 800{ 801 ASSERT(display); 802 if (!D_insert && D_x < D_width - 1) 803 { 804 if (D_IC || D_CIC) 805 { 806 if (D_IC) 807 AddCStr(D_IC); 808 else 809 AddCStr2(D_CIC, 1); 810 RAW_PUTCHAR(c); 811 return; 812 } 813 InsertMode(1); 814 if (!D_insert) 815 { 816 RefreshLine(D_y, D_x, D_width-1, 0); 817 return; 818 } 819 } 820 RAW_PUTCHAR(c); 821} 822 823void 824PUTCHAR(c) 825int c; 826{ 827 ASSERT(display); 828 if (D_insert && D_x < D_width - 1) 829 InsertMode(0); 830 RAW_PUTCHAR(c); 831} 832 833void 834PUTCHARLP(c) 835int c; 836{ 837 if (D_x < D_width - 1) 838 { 839 if (D_insert) 840 InsertMode(0); 841 RAW_PUTCHAR(c); 842 return; 843 } 844 if (D_CLP || D_y != D_bot) 845 { 846 int y = D_y; 847 RAW_PUTCHAR(c); 848 if (D_AM && !D_CLP) 849 GotoPos(D_width - 1, y); 850 return; 851 } 852 debug("PUTCHARLP: lp_missing!\n"); 853 D_lp_missing = 1; 854 D_rend.image = c; 855 D_lpchar = D_rend; 856#ifdef DW_CHARS 857 /* XXX -> PutChar ? */ 858 if (D_mbcs) 859 { 860 D_lpchar.mbcs = c; 861 D_lpchar.image = D_mbcs; 862 D_mbcs = 0; 863 D_x--; 864 } 865#endif 866} 867 868/* 869 * RAW_PUTCHAR() is for all text that will be displayed. 870 * NOTE: charset Nr. 0 has a conversion table, but c1, c2, ... don't. 871 */ 872 873STATIC void 874RAW_PUTCHAR(c) 875int c; 876{ 877 ASSERT(display); 878 879#ifdef FONT 880# ifdef UTF8 881 if (D_encoding == UTF8) 882 { 883 c = (c & 255) | (unsigned char)D_rend.font << 8; 884# ifdef DW_CHARS 885 if (D_mbcs) 886 { 887 c = D_mbcs; 888 if (D_x == D_width) 889 D_x += D_AM ? 1 : -1; 890 D_mbcs = 0; 891 } 892 else if (utf8_isdouble(c)) 893 { 894 D_mbcs = c; 895 D_x++; 896 return; 897 } 898# endif 899 if (c < 32) 900 { 901 AddCStr2(D_CS0, '0'); 902 AddChar(c + 0x5f); 903 AddCStr(D_CE0); 904 goto addedutf8; 905 } 906 AddUtf8(c); 907 goto addedutf8; 908 } 909# endif 910# ifdef DW_CHARS 911 if (is_dw_font(D_rend.font)) 912 { 913 int t = c; 914 if (D_mbcs == 0) 915 { 916 D_mbcs = c; 917 D_x++; 918 return; 919 } 920 D_x--; 921 if (D_x == D_width - 1) 922 D_x += D_AM ? 1 : -1; 923 c = D_mbcs; 924 D_mbcs = t; 925 } 926# endif 927# if defined(ENCODINGS) && defined(DW_CHARS) 928 if (D_encoding) 929 c = PrepareEncodedChar(c); 930# endif 931# ifdef DW_CHARS 932 kanjiloop: 933# endif 934 if (D_xtable && D_xtable[(int)(unsigned char)D_rend.font] && D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c]) 935 AddStr(D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c]); 936 else 937 AddChar(D_rend.font != '0' ? c : D_c0_tab[(int)(unsigned char)c]); 938#else /* FONT */ 939 AddChar(c); 940#endif /* FONT */ 941 942#ifdef UTF8 943addedutf8: 944#endif 945 if (++D_x >= D_width) 946 { 947 if (D_AM == 0) 948 D_x = D_width - 1; 949 else if (!D_CLP || D_x > D_width) 950 { 951 D_x -= D_width; 952 if (D_y < D_height-1 && D_y != D_bot) 953 D_y++; 954 } 955 } 956#ifdef DW_CHARS 957 if (D_mbcs) 958 { 959 c = D_mbcs; 960 D_mbcs = 0; 961 goto kanjiloop; 962 } 963#endif 964} 965 966static int 967DoAddChar(c) 968int c; 969{ 970 /* this is for ESC-sequences only (AddChar is a macro) */ 971 AddChar(c); 972 return c; 973} 974 975void 976AddCStr(s) 977char *s; 978{ 979 if (display && s && *s) 980 { 981 ospeed = D_dospeed; 982 tputs(s, 1, DoAddChar); 983 } 984} 985 986void 987AddCStr2(s, c) 988char *s; 989int c; 990{ 991 if (display && s && *s) 992 { 993 ospeed = D_dospeed; 994 tputs(tgoto(s, 0, c), 1, DoAddChar); 995 } 996} 997 998 999/* Insert mode is a toggle on some terminals, so we need this hack: 1000 */ 1001void 1002InsertMode(on) 1003int on; 1004{ 1005 if (display && on != D_insert && D_IM) 1006 { 1007 D_insert = on; 1008 if (on) 1009 AddCStr(D_IM); 1010 else 1011 AddCStr(D_EI); 1012 } 1013} 1014 1015/* ...and maybe keypad application mode is a toggle, too: 1016 */ 1017void 1018KeypadMode(on) 1019int on; 1020{ 1021#ifdef MAPKEYS 1022 if (display) 1023 D_keypad = on; 1024#else 1025 if (display && D_keypad != on && D_KS) 1026 { 1027 D_keypad = on; 1028 if (on) 1029 AddCStr(D_KS); 1030 else 1031 AddCStr(D_KE); 1032 } 1033#endif 1034} 1035 1036void 1037CursorkeysMode(on) 1038int on; 1039{ 1040#ifdef MAPKEYS 1041 if (display) 1042 D_cursorkeys = on; 1043#else 1044 if (display && D_cursorkeys != on && D_CCS) 1045 { 1046 D_cursorkeys = on; 1047 if (on) 1048 AddCStr(D_CCS); 1049 else 1050 AddCStr(D_CCE); 1051 } 1052#endif 1053} 1054 1055void 1056ReverseVideo(on) 1057int on; 1058{ 1059 if (display && D_revvid != on && D_CVR) 1060 { 1061 D_revvid = on; 1062 if (D_revvid) 1063 AddCStr(D_CVR); 1064 else 1065 AddCStr(D_CVN); 1066 } 1067} 1068 1069void 1070CursorVisibility(v) 1071int v; 1072{ 1073 if (display && D_curvis != v) 1074 { 1075 if (D_curvis) 1076 AddCStr(D_VE); /* do this always, just to be safe */ 1077 D_curvis = 0; 1078 if (v == -1 && D_VI) 1079 AddCStr(D_VI); 1080 else if (v == 1 && D_VS) 1081 AddCStr(D_VS); 1082 else 1083 return; 1084 D_curvis = v; 1085 } 1086} 1087 1088void 1089MouseMode(mode) 1090int mode; 1091{ 1092 if (display && D_mouse != mode) 1093 { 1094 char mousebuf[20]; 1095 if (!D_CXT) 1096 return; 1097 if (D_mouse) 1098 { 1099 sprintf(mousebuf, "\033[?%dl", D_mouse); 1100 AddStr(mousebuf); 1101 } 1102 if (mode) 1103 { 1104 sprintf(mousebuf, "\033[?%dh", mode); 1105 AddStr(mousebuf); 1106 } 1107 D_mouse = mode; 1108 } 1109} 1110 1111static int StrCost; 1112 1113/* ARGSUSED */ 1114static int 1115CountChars(c) 1116int c; 1117{ 1118 StrCost++; 1119 return c; 1120} 1121 1122int 1123CalcCost(s) 1124register char *s; 1125{ 1126 ASSERT(display); 1127 if (s) 1128 { 1129 StrCost = 0; 1130 ospeed = D_dospeed; 1131 tputs(s, 1, CountChars); 1132 return StrCost; 1133 } 1134 else 1135 return EXPENSIVE; 1136} 1137 1138static int 1139CallRewrite(y, xs, xe, doit) 1140int y, xs, xe, doit; 1141{ 1142 struct canvas *cv, *cvlist, *cvlnext; 1143 struct viewport *vp; 1144 struct layer *oldflayer; 1145 int cost; 1146 1147 debug3("CallRewrite %d %d %d\n", y, xs, xe); 1148 ASSERT(display); 1149 ASSERT(xe >= xs); 1150 1151 vp = 0; 1152 for (cv = D_cvlist; cv; cv = cv->c_next) 1153 { 1154 if (y < cv->c_ys || y > cv->c_ye || xe < cv->c_xs || xs > cv->c_xe) 1155 continue; 1156 for (vp = cv->c_vplist; vp; vp = vp->v_next) 1157 if (y >= vp->v_ys && y <= vp->v_ye && xe >= vp->v_xs && xs <= vp->v_xe) 1158 break; 1159 if (vp) 1160 break; 1161 } 1162 if (doit) 1163 { 1164 oldflayer = flayer; 1165 flayer = cv->c_layer; 1166 cvlist = flayer->l_cvlist; 1167 cvlnext = cv->c_lnext; 1168 flayer->l_cvlist = cv; 1169 cv->c_lnext = 0; 1170 LayRewrite(y - vp->v_yoff, xs - vp->v_xoff, xe - vp->v_xoff, &D_rend, 1); 1171 flayer->l_cvlist = cvlist; 1172 cv->c_lnext = cvlnext; 1173 flayer = oldflayer; 1174 return 0; 1175 } 1176 if (cv == 0 || cv->c_layer == 0) 1177 return EXPENSIVE; /* not found or nothing on it */ 1178 if (xs < vp->v_xs || xe > vp->v_xe) 1179 return EXPENSIVE; /* crosses viewport boundaries */ 1180 if (y - vp->v_yoff < 0 || y - vp->v_yoff >= cv->c_layer->l_height) 1181 return EXPENSIVE; /* line not on layer */ 1182 if (xs - vp->v_xoff < 0 || xe - vp->v_xoff >= cv->c_layer->l_width) 1183 return EXPENSIVE; /* line not on layer */ 1184#ifdef UTF8 1185 if (D_encoding == UTF8) 1186 D_rend.font = 0; 1187#endif 1188 oldflayer = flayer; 1189 flayer = cv->c_layer; 1190 debug3("Calling Rewrite %d %d %d\n", y - vp->v_yoff, xs - vp->v_xoff, xe - vp->v_xoff); 1191 cost = LayRewrite(y - vp->v_yoff, xs - vp->v_xoff, xe - vp->v_xoff, &D_rend, 0); 1192 flayer = oldflayer; 1193 if (D_insert) 1194 cost += D_EIcost + D_IMcost; 1195 return cost; 1196} 1197 1198 1199void 1200GotoPos(x2, y2) 1201int x2, y2; 1202{ 1203 register int dy, dx, x1, y1; 1204 register int costx, costy; 1205 register int m; 1206 register char *s; 1207 int CMcost; 1208 enum move_t xm = M_NONE, ym = M_NONE; 1209 1210 if (!display) 1211 return; 1212 1213 x1 = D_x; 1214 y1 = D_y; 1215 1216 if (x1 == D_width) 1217 { 1218 if (D_CLP && D_AM) 1219 x1 = -1; /* don't know how the terminal treats this */ 1220 else 1221 x1--; 1222 } 1223 if (x2 == D_width) 1224 x2--; 1225 dx = x2 - x1; 1226 dy = y2 - y1; 1227 if (dy == 0 && dx == 0) 1228 return; 1229 debug2("GotoPos (%d,%d)", x1, y1); 1230 debug2(" -> (%d,%d)\n", x2, y2); 1231 if (!D_MS) /* Safe to move ? */ 1232 SetRendition(&mchar_null); 1233 if (y1 < 0 /* don't know the y position */ 1234 || (y2 > D_bot && y1 <= D_bot) /* have to cross border */ 1235 || (y2 < D_top && y1 >= D_top)) /* of scrollregion ? */ 1236 { 1237 DoCM: 1238 if (D_HO && !x2 && !y2) 1239 AddCStr(D_HO); 1240 else 1241 AddCStr(tgoto(D_CM, x2, y2)); 1242 D_x = x2; 1243 D_y = y2; 1244 return; 1245 } 1246 1247 /* some scrollregion implementations don't allow movements 1248 * away from the region. sigh. 1249 */ 1250 if ((y1 > D_bot && y2 > y1) || (y1 < D_top && y2 < y1)) 1251 goto DoCM; 1252 1253 /* Calculate CMcost */ 1254 if (D_HO && !x2 && !y2) 1255 s = D_HO; 1256 else 1257 s = tgoto(D_CM, x2, y2); 1258 CMcost = CalcCost(s); 1259 1260 /* Calculate the cost to move the cursor to the right x position */ 1261 costx = EXPENSIVE; 1262 if (x1 >= 0) /* relativ x positioning only if we know where we are */ 1263 { 1264 if (dx > 0) 1265 { 1266 if (D_CRI && (dx > 1 || !D_ND)) 1267 { 1268 costx = CalcCost(tgoto(D_CRI, 0, dx)); 1269 xm = M_CRI; 1270 } 1271 if ((m = D_NDcost * dx) < costx) 1272 { 1273 costx = m; 1274 xm = M_RI; 1275 } 1276 /* Speedup: dx <= LayRewrite() */ 1277 if (dx < costx && (m = CallRewrite(y1, x1, x2 - 1, 0)) < costx) 1278 { 1279 costx = m; 1280 xm = M_RW; 1281 } 1282 } 1283 else if (dx < 0) 1284 { 1285 if (D_CLE && (dx < -1 || !D_BC)) 1286 { 1287 costx = CalcCost(tgoto(D_CLE, 0, -dx)); 1288 xm = M_CLE; 1289 } 1290 if ((m = -dx * D_LEcost) < costx) 1291 { 1292 costx = m; 1293 xm = M_LE; 1294 } 1295 } 1296 else 1297 costx = 0; 1298 } 1299 /* Speedup: LayRewrite() >= x2 */ 1300 if (x2 + D_CRcost < costx && (m = (x2 ? CallRewrite(y1, 0, x2 - 1, 0) : 0) + D_CRcost) < costx) 1301 { 1302 costx = m; 1303 xm = M_CR; 1304 } 1305 1306 /* Check if it is already cheaper to do CM */ 1307 if (costx >= CMcost) 1308 goto DoCM; 1309 1310 /* Calculate the cost to move the cursor to the right y position */ 1311 costy = EXPENSIVE; 1312 if (dy > 0) 1313 { 1314 if (D_CDO && dy > 1) /* DO & NL are always != 0 */ 1315 { 1316 costy = CalcCost(tgoto(D_CDO, 0, dy)); 1317 ym = M_CDO; 1318 } 1319 if ((m = dy * ((x2 == 0) ? D_NLcost : D_DOcost)) < costy) 1320 { 1321 costy = m; 1322 ym = M_DO; 1323 } 1324 } 1325 else if (dy < 0) 1326 { 1327 if (D_CUP && (dy < -1 || !D_UP)) 1328 { 1329 costy = CalcCost(tgoto(D_CUP, 0, -dy)); 1330 ym = M_CUP; 1331 } 1332 if ((m = -dy * D_UPcost) < costy) 1333 { 1334 costy = m; 1335 ym = M_UP; 1336 } 1337 } 1338 else 1339 costy = 0; 1340 1341 /* Finally check if it is cheaper to do CM */ 1342 if (costx + costy >= CMcost) 1343 goto DoCM; 1344 1345 switch (xm) 1346 { 1347 case M_LE: 1348 while (dx++ < 0) 1349 AddCStr(D_BC); 1350 break; 1351 case M_CLE: 1352 AddCStr2(D_CLE, -dx); 1353 break; 1354 case M_RI: 1355 while (dx-- > 0) 1356 AddCStr(D_ND); 1357 break; 1358 case M_CRI: 1359 AddCStr2(D_CRI, dx); 1360 break; 1361 case M_CR: 1362 AddCStr(D_CR); 1363 D_x = 0; 1364 x1 = 0; 1365 /* FALLTHROUGH */ 1366 case M_RW: 1367 if (x1 < x2) 1368 (void) CallRewrite(y1, x1, x2 - 1, 1); 1369 break; 1370 default: 1371 break; 1372 } 1373 1374 switch (ym) 1375 { 1376 case M_UP: 1377 while (dy++ < 0) 1378 AddCStr(D_UP); 1379 break; 1380 case M_CUP: 1381 AddCStr2(D_CUP, -dy); 1382 break; 1383 case M_DO: 1384 s = (x2 == 0) ? D_NL : D_DO; 1385 while (dy-- > 0) 1386 AddCStr(s); 1387 break; 1388 case M_CDO: 1389 AddCStr2(D_CDO, dy); 1390 break; 1391 default: 1392 break; 1393 } 1394 D_x = x2; 1395 D_y = y2; 1396} 1397 1398void 1399ClearAll() 1400{ 1401 ASSERT(display); 1402 ClearArea(0, 0, 0, D_width - 1, D_width - 1, D_height - 1, 0, 0); 1403} 1404 1405void 1406ClearArea(x1, y1, xs, xe, x2, y2, bce, uselayfn) 1407int x1, y1, xs, xe, x2, y2, bce, uselayfn; 1408{ 1409 int y, xxe; 1410 struct canvas *cv; 1411 struct viewport *vp; 1412 1413 debug2("Clear %d,%d", x1, y1); 1414 debug2(" %d-%d", xs, xe); 1415 debug2(" %d,%d", x2, y2); 1416 debug2(" uselayfn=%d bce=%d\n", uselayfn, bce); 1417 ASSERT(display); 1418 if (x1 == D_width) 1419 x1--; 1420 if (x2 == D_width) 1421 x2--; 1422 if (xs == -1) 1423 xs = x1; 1424 if (xe == -1) 1425 xe = x2; 1426 if (D_UT) /* Safe to erase ? */ 1427 SetRendition(&mchar_null); 1428#ifdef COLOR 1429 if (D_BE) 1430 SetBackColor(bce); 1431#endif 1432 if (D_lp_missing && y1 <= D_bot && xe >= D_width - 1) 1433 { 1434 if (y2 > D_bot || (y2 == D_bot && x2 >= D_width - 1)) 1435 D_lp_missing = 0; 1436 } 1437 if (x2 == D_width - 1 && (xs == 0 || y1 == y2) && xe == D_width - 1 && y2 == D_height - 1 && (!bce || D_BE)) 1438 { 1439#ifdef AUTO_NUKE 1440 if (x1 == 0 && y1 == 0 && D_auto_nuke) 1441 NukePending(); 1442#endif 1443 if (x1 == 0 && y1 == 0 && D_CL) 1444 { 1445 AddCStr(D_CL); 1446 D_y = D_x = 0; 1447 return; 1448 } 1449 /* 1450 * Workaround a hp700/22 terminal bug. Do not use CD where CE 1451 * is also appropriate. 1452 */ 1453 if (D_CD && (y1 < y2 || !D_CE)) 1454 { 1455 GotoPos(x1, y1); 1456 AddCStr(D_CD); 1457 return; 1458 } 1459 } 1460 if (x1 == 0 && xs == 0 && (xe == D_width - 1 || y1 == y2) && y1 == 0 && D_CCD && (!bce || D_BE)) 1461 { 1462 GotoPos(x1, y1); 1463 AddCStr(D_CCD); 1464 return; 1465 } 1466 xxe = xe; 1467 for (y = y1; y <= y2; y++, x1 = xs) 1468 { 1469 if (y == y2) 1470 xxe = x2; 1471 if (x1 == 0 && D_CB && (xxe != D_width - 1 || (D_x == xxe && D_y == y)) && (!bce || D_BE)) 1472 { 1473 GotoPos(xxe, y); 1474 AddCStr(D_CB); 1475 continue; 1476 } 1477 if (xxe == D_width - 1 && D_CE && (!bce || D_BE)) 1478 { 1479 GotoPos(x1, y); 1480 AddCStr(D_CE); 1481 continue; 1482 } 1483 if (uselayfn) 1484 { 1485 vp = 0; 1486 for (cv = D_cvlist; cv; cv = cv->c_next) 1487 { 1488 if (y < cv->c_ys || y > cv->c_ye || xxe < cv->c_xs || x1 > cv->c_xe) 1489 continue; 1490 for (vp = cv->c_vplist; vp; vp = vp->v_next) 1491 if (y >= vp->v_ys && y <= vp->v_ye && xxe >= vp->v_xs && x1 <= vp->v_xe) 1492 break; 1493 if (vp) 1494 break; 1495 } 1496 if (cv && cv->c_layer && x1 >= vp->v_xs && xxe <= vp->v_xe && 1497 y - vp->v_yoff >= 0 && y - vp->v_yoff < cv->c_layer->l_height && 1498 xxe - vp->v_xoff >= 0 && x1 - vp->v_xoff < cv->c_layer->l_width) 1499 { 1500 struct layer *oldflayer = flayer; 1501 struct canvas *cvlist, *cvlnext; 1502 flayer = cv->c_layer; 1503 cvlist = flayer->l_cvlist; 1504 cvlnext = cv->c_lnext; 1505 flayer->l_cvlist = cv; 1506 cv->c_lnext = 0; 1507 LayClearLine(y - vp->v_yoff, x1 - vp->v_xoff, xxe - vp->v_xoff, bce); 1508 flayer->l_cvlist = cvlist; 1509 cv->c_lnext = cvlnext; 1510 flayer = oldflayer; 1511 continue; 1512 } 1513 } 1514 ClearLine((struct mline *)0, y, x1, xxe, bce); 1515 } 1516} 1517 1518 1519/* 1520 * if cur_only > 0, we only redisplay current line, as a full refresh is 1521 * too expensive over a low baud line. 1522 */ 1523void 1524Redisplay(cur_only) 1525int cur_only; 1526{ 1527 ASSERT(display); 1528 1529 /* XXX do em all? */ 1530 InsertMode(0); 1531 ChangeScrollRegion(0, D_height - 1); 1532 KeypadMode(0); 1533 CursorkeysMode(0); 1534 CursorVisibility(0); 1535 MouseMode(0); 1536 SetRendition(&mchar_null); 1537 SetFlow(FLOW_NOW); 1538 1539 ClearAll(); 1540#ifdef RXVT_OSC 1541 RefreshXtermOSC(); 1542#endif 1543 if (cur_only > 0 && D_fore) 1544 RefreshArea(0, D_fore->w_y, D_width - 1, D_fore->w_y, 1); 1545 else 1546 RefreshAll(1); 1547 RefreshHStatus(); 1548 CV_CALL(D_forecv, LayRestore();LaySetCursor()); 1549} 1550 1551void 1552RedisplayDisplays(cur_only) 1553int cur_only; 1554{ 1555 struct display *olddisplay = display; 1556 for (display = displays; display; display = display->d_next) 1557 Redisplay(cur_only); 1558 display = olddisplay; 1559} 1560 1561 1562/* XXX: use oml! */ 1563void 1564ScrollH(y, xs, xe, n, bce, oml) 1565int y, xs, xe, n, bce; 1566struct mline *oml; 1567{ 1568 int i; 1569 1570 if (n == 0) 1571 return; 1572 if (xe != D_width - 1) 1573 { 1574 RefreshLine(y, xs, xe, 0); 1575 /* UpdateLine(oml, y, xs, xe); */ 1576 return; 1577 } 1578 GotoPos(xs, y); 1579 if (D_UT) 1580 SetRendition(&mchar_null); 1581#ifdef COLOR 1582 if (D_BE) 1583 SetBackColor(bce); 1584#endif 1585 if (n > 0) 1586 { 1587 if (n >= xe - xs + 1) 1588 n = xe - xs + 1; 1589 if (D_CDC && !(n == 1 && D_DC)) 1590 AddCStr2(D_CDC, n); 1591 else if (D_DC) 1592 { 1593 for (i = n; i--; ) 1594 AddCStr(D_DC); 1595 } 1596 else 1597 { 1598 RefreshLine(y, xs, xe, 0); 1599 /* UpdateLine(oml, y, xs, xe); */ 1600 return; 1601 } 1602 } 1603 else 1604 { 1605 if (-n >= xe - xs + 1) 1606 n = -(xe - xs + 1); 1607 if (!D_insert) 1608 { 1609 if (D_CIC && !(n == -1 && D_IC)) 1610 AddCStr2(D_CIC, -n); 1611 else if (D_IC) 1612 { 1613 for (i = -n; i--; ) 1614 AddCStr(D_IC); 1615 } 1616 else if (D_IM) 1617 { 1618 InsertMode(1); 1619 SetRendition(&mchar_null); 1620#ifdef COLOR 1621 SetBackColor(bce); 1622#endif 1623 for (i = -n; i--; ) 1624 INSERTCHAR(' '); 1625 bce = 0; /* all done */ 1626 } 1627 else 1628 { 1629 /* UpdateLine(oml, y, xs, xe); */ 1630 RefreshLine(y, xs, xe, 0); 1631 return; 1632 } 1633 } 1634 else 1635 { 1636 SetRendition(&mchar_null); 1637#ifdef COLOR 1638 SetBackColor(bce); 1639#endif 1640 for (i = -n; i--; ) 1641 INSERTCHAR(' '); 1642 bce = 0; /* all done */ 1643 } 1644 } 1645 if (bce && !D_BE) 1646 { 1647 if (n > 0) 1648 ClearLine((struct mline *)0, y, xe - n + 1, xe, bce); 1649 else 1650 ClearLine((struct mline *)0, y, xs, xs - n - 1, bce); 1651 } 1652 if (D_lp_missing && y == D_bot) 1653 { 1654 if (n > 0) 1655 WriteLP(D_width - 1 - n, y); 1656 D_lp_missing = 0; 1657 } 1658} 1659 1660void 1661ScrollV(xs, ys, xe, ye, n, bce) 1662int xs, ys, xe, ye, n, bce; 1663{ 1664 int i; 1665 int up; 1666 int oldtop, oldbot; 1667 int alok, dlok, aldlfaster; 1668 int missy = 0; 1669 1670 ASSERT(display); 1671 if (n == 0) 1672 return; 1673 if (n >= ye - ys + 1 || -n >= ye - ys + 1) 1674 { 1675 ClearArea(xs, ys, xs, xe, xe, ye, bce, 0); 1676 return; 1677 } 1678 if (xs > D_vpxmin || xe < D_vpxmax) 1679 { 1680 RefreshArea(xs, ys, xe, ye, 0); 1681 return; 1682 } 1683 1684 if (D_lp_missing) 1685 { 1686 if (D_bot > ye || D_bot < ys) 1687 missy = D_bot; 1688 else 1689 { 1690 missy = D_bot - n; 1691 if (missy > ye || missy < ys) 1692 D_lp_missing = 0; 1693 } 1694 } 1695 1696 up = 1; 1697 if (n < 0) 1698 { 1699 up = 0; 1700 n = -n; 1701 } 1702 if (n >= ye - ys + 1) 1703 n = ye - ys + 1; 1704 1705 oldtop = D_top; 1706 oldbot = D_bot; 1707 if (ys < D_top || D_bot != ye) 1708 ChangeScrollRegion(ys, ye); 1709 alok = (D_AL || D_CAL || (ys >= D_top && ye == D_bot && up)); 1710 dlok = (D_DL || D_CDL || (ys >= D_top && ye == D_bot && !up)); 1711 if (D_top != ys && !(alok && dlok)) 1712 ChangeScrollRegion(ys, ye); 1713 1714 if (D_lp_missing && 1715 (oldbot != D_bot || 1716 (oldbot == D_bot && up && D_top == ys && D_bot == ye))) 1717 { 1718 WriteLP(D_width - 1, oldbot); 1719 if (oldbot == D_bot) /* have scrolled */ 1720 { 1721 if (--n == 0) 1722 { 1723/* XXX 1724 ChangeScrollRegion(oldtop, oldbot); 1725*/ 1726 if (bce && !D_BE) 1727 ClearLine((struct mline *)0, ye, xs, xe, bce); 1728 return; 1729 } 1730 } 1731 } 1732 1733 if (D_UT) 1734 SetRendition(&mchar_null); 1735#ifdef COLOR 1736 if (D_BE) 1737 SetBackColor(bce); 1738#endif 1739 1740 aldlfaster = (n > 1 && ys >= D_top && ye == D_bot && ((up && D_CDL) || (!up && D_CAL))); 1741 1742 if ((up || D_SR) && D_top == ys && D_bot == ye && !aldlfaster) 1743 { 1744 if (up) 1745 { 1746 GotoPos(0, ye); 1747 for(i = n; i-- > 0; ) 1748 AddCStr(D_NL); /* was SF, I think NL is faster */ 1749 } 1750 else 1751 { 1752 GotoPos(0, ys); 1753 for(i = n; i-- > 0; ) 1754 AddCStr(D_SR); 1755 } 1756 } 1757 else if (alok && dlok) 1758 { 1759 if (up || ye != D_bot) 1760 { 1761 GotoPos(0, up ? ys : ye+1-n); 1762 if (D_CDL && !(n == 1 && D_DL)) 1763 AddCStr2(D_CDL, n); 1764 else 1765 for(i = n; i--; ) 1766 AddCStr(D_DL); 1767 } 1768 if (!up || ye != D_bot) 1769 { 1770 GotoPos(0, up ? ye+1-n : ys); 1771 if (D_CAL && !(n == 1 && D_AL)) 1772 AddCStr2(D_CAL, n); 1773 else 1774 for(i = n; i--; ) 1775 AddCStr(D_AL); 1776 } 1777 } 1778 else 1779 { 1780 RefreshArea(xs, ys, xe, ye, 0); 1781 return; 1782 } 1783 if (bce && !D_BE) 1784 { 1785 if (up) 1786 ClearArea(xs, ye - n + 1, xs, xe, xe, ye, bce, 0); 1787 else 1788 ClearArea(xs, ys, xs, xe, xe, ys + n - 1, bce, 0); 1789 } 1790 if (D_lp_missing && missy != D_bot) 1791 WriteLP(D_width - 1, missy); 1792/* XXX 1793 ChangeScrollRegion(oldtop, oldbot); 1794 if (D_lp_missing && missy != D_bot) 1795 WriteLP(D_width - 1, missy); 1796*/ 1797} 1798 1799void 1800SetAttr(new) 1801register int new; 1802{ 1803 register int i, j, old, typ; 1804 1805 if (!display || (old = D_rend.attr) == new) 1806 return; 1807#ifdef COLORS16 1808 D_col16change = (old ^ new) & (A_BFG | A_BBG); 1809 new ^= D_col16change; 1810 if (old == new) 1811 return; 1812#endif 1813#if defined(TERMINFO) && defined(USE_SGR) 1814 if (D_SA) 1815 { 1816 char *tparm(); 1817 SetFont(ASCII); 1818 ospeed = D_dospeed; 1819 tputs(tparm(D_SA, new & A_SO, new & A_US, new & A_RV, new & A_BL, 1820 new & A_DI, new & A_BD, 0 , 0 , 1821 0), 1, DoAddChar); 1822 D_rend.attr = new; 1823 D_atyp = 0; 1824# ifdef COLOR 1825 if (D_hascolor) 1826 rend_setdefault(&D_rend); 1827# endif 1828 return; 1829 } 1830#endif 1831 D_rend.attr = new; 1832 typ = D_atyp; 1833 if ((new & old) != old) 1834 { 1835 if ((typ & ATYP_U)) 1836 AddCStr(D_UE); 1837 if ((typ & ATYP_S)) 1838 AddCStr(D_SE); 1839 if ((typ & ATYP_M)) 1840 { 1841 AddCStr(D_ME); 1842#ifdef COLOR 1843 /* ansi attrib handling: \E[m resets color, too */ 1844 if (D_hascolor) 1845 rend_setdefault(&D_rend); 1846#endif 1847#ifdef FONT 1848 if (!D_CG0) 1849 { 1850 /* D_ME may also reset the alternate charset */ 1851 D_rend.font = 0; 1852# ifdef ENCODINGS 1853 D_realfont = 0; 1854# endif 1855 } 1856#endif 1857 } 1858 old = 0; 1859 typ = 0; 1860 } 1861 old ^= new; 1862 for (i = 0, j = 1; old && i < NATTR; i++, j <<= 1) 1863 { 1864 if ((old & j) == 0) 1865 continue; 1866 old ^= j; 1867 if (D_attrtab[i]) 1868 { 1869 AddCStr(D_attrtab[i]); 1870 typ |= D_attrtyp[i]; 1871 } 1872 } 1873 D_atyp = typ; 1874} 1875 1876#ifdef FONT 1877void 1878SetFont(new) 1879int new; 1880{ 1881 int old = D_rend.font; 1882 if (!display || old == new) 1883 return; 1884 D_rend.font = new; 1885#ifdef ENCODINGS 1886 if (D_encoding && CanEncodeFont(D_encoding, new)) 1887 return; 1888 if (new == D_realfont) 1889 return; 1890 D_realfont = new; 1891#endif 1892 if (D_xtable && D_xtable[(int)(unsigned char)new] && 1893 D_xtable[(int)(unsigned char)new][256]) 1894 { 1895 AddCStr(D_xtable[(int)(unsigned char)new][256]); 1896 return; 1897 } 1898 1899 if (!D_CG0 && new != '0') 1900 { 1901 new = ASCII; 1902 if (old == new) 1903 return; 1904 } 1905 1906 if (new == ASCII) 1907 AddCStr(D_CE0); 1908#ifdef DW_CHARS 1909 else if (new < ' ') 1910 { 1911 AddStr("\033$"); 1912 if (new > 2) 1913 AddChar('('); 1914 AddChar(new + '@'); 1915 } 1916#endif 1917 else 1918 AddCStr2(D_CS0, new); 1919} 1920#endif 1921 1922#ifdef COLOR 1923 1924int 1925color256to16(jj) 1926int jj; 1927{ 1928 int min, max; 1929 int r, g, b; 1930 1931 if (jj >= 232) 1932 { 1933 jj = (jj - 232) / 6; 1934 jj = (jj & 1) << 3 | (jj & 2 ? 7 : 0); 1935 } 1936 else if (jj >= 16) 1937 { 1938 jj -= 16; 1939 r = jj / 36; 1940 g = (jj / 6) % 6; 1941 b = jj % 6; 1942 min = r < g ? (r < b ? r : b) : (g < b ? g : b); 1943 max = r > g ? (r > b ? r : b) : (g > b ? g : b); 1944 if (min == max) 1945 jj = ((max + 1) & 2) << 2 | ((max + 1) & 4 ? 7 : 0); 1946 else 1947 jj = (b - min) / (max - min) << 2 | (g - min) / (max - min) << 1 | (r - 1948min) / (max - min) | (max > 3 ? 8 : 0); 1949 } 1950 return jj; 1951} 1952 1953#ifdef COLORS256 1954int 1955color256to88(jj) 1956int jj; 1957{ 1958 int r, g, b; 1959 1960 if (jj >= 232) 1961 return (jj - 232) / 3 + 80; 1962 if (jj >= 16) 1963 { 1964 jj -= 16; 1965 r = jj / 36; 1966 g = (jj / 6) % 6; 1967 b = jj % 6; 1968 return ((r + 1) / 2) * 16 + ((g + 1) / 2) * 4 + ((b + 1) / 2) + 16; 1969 } 1970 return jj; 1971} 1972#endif 1973 1974void 1975SetColor(f, b) 1976int f, b; 1977{ 1978 int of, ob; 1979 static unsigned char sftrans[8] = {0,4,2,6,1,5,3,7}; 1980 1981 if (!display) 1982 return; 1983 1984 of = rend_getfg(&D_rend); 1985 ob = rend_getbg(&D_rend); 1986 1987#ifdef COLORS16 1988 /* intense default not invented yet */ 1989 if (f == 0x100) 1990 f = 0; 1991 if (b == 0x100) 1992 b = 0; 1993#endif 1994 debug2("SetColor %d %d", coli2e(of), coli2e(ob)); 1995 debug2(" -> %d %d\n", coli2e(f), coli2e(b)); 1996 debug2("(%d %d", of, ob); 1997 debug2(" -> %d %d)\n", f, b); 1998 1999 if (!D_CAX && D_hascolor && ((f == 0 && f != of) || (b == 0 && b != ob))) 2000 { 2001 if (D_OP) 2002 AddCStr(D_OP); 2003 else 2004 { 2005 int oattr; 2006 oattr = D_rend.attr; 2007 AddCStr(D_ME ? D_ME : "\033[m"); 2008#ifdef FONT 2009 if (D_ME && !D_CG0) 2010 { 2011 /* D_ME may also reset the alternate charset */ 2012 D_rend.font = 0; 2013# ifdef ENCODINGS 2014 D_realfont = 0; 2015# endif 2016 } 2017#endif 2018 D_atyp = 0; 2019 D_rend.attr = 0; 2020 SetAttr(oattr); 2021 } 2022 of = ob = 0; 2023 } 2024 rend_setfg(&D_rend, f); 2025 rend_setbg(&D_rend, b); 2026#ifdef COLORS16 2027 D_col16change = 0; 2028#endif 2029 if (!D_hascolor) 2030 return; 2031 f = f ? coli2e(f) : -1; 2032 b = b ? coli2e(b) : -1; 2033 of = of ? coli2e(of) : -1; 2034 ob = ob ? coli2e(ob) : -1; 2035#ifdef COLORS256 2036 if (f != of && f > 15 && D_CCO != 256) 2037 f = D_CCO == 88 && D_CAF ? color256to88(f) : color256to16(f); 2038 if (f != of && f > 15 && D_CAF) 2039 { 2040 AddCStr2(D_CAF, f); 2041 of = f; 2042 } 2043 if (b != ob && b > 15 && D_CCO != 256) 2044 b = D_CCO == 88 && D_CAB ? color256to88(b) : color256to16(b); 2045 if (b != ob && b > 15 && D_CAB) 2046 { 2047 AddCStr2(D_CAB, b); 2048 ob = b; 2049 } 2050#endif 2051 if (f != of && f != (of | 8)) 2052 { 2053 if (f == -1) 2054 AddCStr("\033[39m"); /* works because AX is set */ 2055 else if (D_CAF) 2056 AddCStr2(D_CAF, f & 7); 2057 else if (D_CSF) 2058 AddCStr2(D_CSF, sftrans[f & 7]); 2059 } 2060 if (b != ob && b != (ob | 8)) 2061 { 2062 if (b == -1) 2063 AddCStr("\033[49m"); /* works because AX is set */ 2064 else if (D_CAB) 2065 AddCStr2(D_CAB, b & 7); 2066 else if (D_CSB) 2067 AddCStr2(D_CSB, sftrans[b & 7]); 2068 } 2069#ifdef COLORS16 2070 if (f != of && D_CXT && (f & 8) != 0 && f != -1) 2071 { 2072# ifdef TERMINFO 2073 AddCStr2("\033[9%p1%dm", f & 7); 2074# else 2075 AddCStr2("\033[9%dm", f & 7); 2076# endif 2077 } 2078 if (b != ob && D_CXT && (b & 8) != 0 && b != -1) 2079 { 2080# ifdef TERMINFO 2081 AddCStr2("\033[10%p1%dm", b & 7); 2082# else 2083 AddCStr2("\033[10%dm", b & 7); 2084# endif 2085 } 2086#endif 2087} 2088 2089static void 2090SetBackColor(new) 2091int new; 2092{ 2093 if (!display) 2094 return; 2095 SetColor(rend_getfg(&D_rend), new); 2096} 2097#endif /* COLOR */ 2098 2099void 2100SetRendition(mc) 2101struct mchar *mc; 2102{ 2103 if (!display) 2104 return; 2105 if (nattr2color && D_hascolor && (mc->attr & nattr2color) != 0) 2106 { 2107 static struct mchar mmc; 2108 int i; 2109 mmc = *mc; 2110 for (i = 0; i < 8; i++) 2111 if (attr2color[i] && (mc->attr & (1 << i)) != 0) 2112 { 2113 if (mc->color == 0 && attr2color[i][3]) 2114 ApplyAttrColor(attr2color[i][3], &mmc); 2115 else if ((mc->color & 0x0f) == 0 && attr2color[i][2]) 2116 ApplyAttrColor(attr2color[i][2], &mmc); 2117 else if ((mc->color & 0xf0) == 0 && attr2color[i][1]) 2118 ApplyAttrColor(attr2color[i][1], &mmc); 2119 else 2120 ApplyAttrColor(attr2color[i][0], &mmc); 2121 } 2122 mc = &mmc; 2123 debug2("SetRendition: mapped to %02x %02x\n", (unsigned char)mc->attr, 0x99 - (unsigned char)mc->color); 2124 } 2125 if (D_hascolor && D_CC8 && (mc->attr & (A_BFG|A_BBG))) 2126 { 2127 int a = mc->attr; 2128 if ((mc->attr & A_BFG) && D_MD) 2129 a |= A_BD; 2130 if ((mc->attr & A_BBG) && D_MB) 2131 a |= A_BL; 2132 if (D_rend.attr != a) 2133 SetAttr(a); 2134 } 2135 else if (D_rend.attr != mc->attr) 2136 SetAttr(mc->attr); 2137#ifdef COLOR 2138 if (D_rend.color != mc->color 2139# ifdef COLORS256 2140 || D_rend.colorx != mc->colorx 2141# endif 2142# ifdef COLORS16 2143 || D_col16change 2144# endif 2145 ) 2146 SetColor(rend_getfg(mc), rend_getbg(mc)); 2147#endif 2148#ifdef FONT 2149 if (D_rend.font != mc->font) 2150 SetFont(mc->font); 2151#endif 2152} 2153 2154void 2155SetRenditionMline(ml, x) 2156struct mline *ml; 2157int x; 2158{ 2159 if (!display) 2160 return; 2161 if (nattr2color && D_hascolor && (ml->attr[x] & nattr2color) != 0) 2162 { 2163 struct mchar mc; 2164 copy_mline2mchar(&mc, ml, x); 2165 SetRendition(&mc); 2166 return; 2167 } 2168 if (D_hascolor && D_CC8 && (ml->attr[x] & (A_BFG|A_BBG))) 2169 { 2170 int a = ml->attr[x]; 2171 if ((ml->attr[x] & A_BFG) && D_MD) 2172 a |= A_BD; 2173 if ((ml->attr[x] & A_BBG) && D_MB) 2174 a |= A_BL; 2175 if (D_rend.attr != a) 2176 SetAttr(a); 2177 } 2178 else if (D_rend.attr != ml->attr[x]) 2179 SetAttr(ml->attr[x]); 2180#ifdef COLOR 2181 if (D_rend.color != ml->color[x] 2182# ifdef COLORS256 2183 || D_rend.colorx != ml->colorx[x] 2184# endif 2185# ifdef COLORS16 2186 || D_col16change 2187# endif 2188 ) 2189 { 2190 struct mchar mc; 2191 copy_mline2mchar(&mc, ml, x); 2192 SetColor(rend_getfg(&mc), rend_getbg(&mc)); 2193 } 2194#endif 2195#ifdef FONT 2196 if (D_rend.font != ml->font[x]) 2197 SetFont(ml->font[x]); 2198#endif 2199} 2200 2201void 2202MakeStatus(msg) 2203char *msg; 2204{ 2205 register char *s, *t; 2206 register int max; 2207 2208 if (!display) 2209 return; 2210 2211 if (D_blocked) 2212 return; 2213 if (!D_tcinited) 2214 { 2215 debug("tc not inited, just writing msg\n"); 2216 if (D_processinputdata) 2217 return; /* XXX: better */ 2218 AddStr(msg); 2219 AddStr("\r\n"); 2220 Flush(); 2221 return; 2222 } 2223 if (!use_hardstatus || !D_HS) 2224 { 2225 max = D_width; 2226 if (D_CLP == 0) 2227 max--; 2228 } 2229 else 2230 max = D_WS > 0 ? D_WS : (D_width - !D_CLP); 2231 if (D_status) 2232 { 2233 /* same message? */ 2234 if (strcmp(msg, D_status_lastmsg) == 0) 2235 { 2236 debug("same message - increase timeout"); 2237 SetTimeout(&D_statusev, MsgWait); 2238 return; 2239 } 2240 if (!D_status_bell) 2241 { 2242 struct timeval now; 2243 int ti; 2244 gettimeofday(&now, NULL); 2245 ti = (now.tv_sec - D_status_time.tv_sec) * 1000 + (now.tv_usec - D_status_time.tv_usec) / 1000; 2246 if (ti < MsgMinWait) 2247 DisplaySleep1000(MsgMinWait - ti, 0); 2248 } 2249 RemoveStatus(); 2250 } 2251 for (s = t = msg; *s && t - msg < max; ++s) 2252 if (*s == BELL) 2253 AddCStr(D_BL); 2254 else if ((unsigned char)*s >= ' ' && *s != 0177) 2255 *t++ = *s; 2256 *t = '\0'; 2257 if (t == msg) 2258 return; 2259 if (t - msg >= D_status_buflen) 2260 { 2261 char *buf; 2262 if (D_status_lastmsg) 2263 buf = realloc(D_status_lastmsg, t - msg + 1); 2264 else 2265 buf = malloc(t - msg + 1); 2266 if (buf) 2267 { 2268 D_status_lastmsg = buf; 2269 D_status_buflen = t - msg + 1; 2270 } 2271 } 2272 if (t - msg < D_status_buflen) 2273 strcpy(D_status_lastmsg, msg); 2274 D_status_len = t - msg; 2275 D_status_lastx = D_x; 2276 D_status_lasty = D_y; 2277 if (!use_hardstatus || D_has_hstatus == HSTATUS_IGNORE || D_has_hstatus == HSTATUS_MESSAGE) 2278 { 2279 D_status = STATUS_ON_WIN; 2280 debug1("using STATLINE %d\n", STATLINE); 2281 GotoPos(0, STATLINE); 2282 SetRendition(&mchar_so); 2283 InsertMode(0); 2284 AddStr(msg); 2285 if (D_status_len < max) 2286 { 2287 /* Wayne Davison: add extra space for readability */ 2288 D_status_len++; 2289 SetRendition(&mchar_null); 2290 AddChar(' '); 2291 if (D_status_len < max) 2292 { 2293 D_status_len++; 2294 AddChar(' '); 2295 AddChar('\b'); 2296 } 2297 AddChar('\b'); 2298 } 2299 D_x = -1; 2300 } 2301 else 2302 { 2303 D_status = STATUS_ON_HS; 2304 ShowHStatus(msg); 2305 } 2306 Flush(); 2307 if (!display) 2308 return; 2309 if (D_status == STATUS_ON_WIN) 2310 { 2311 struct display *olddisplay = display; 2312 struct layer *oldflayer = flayer; 2313 2314 ASSERT(D_obuffree == D_obuflen); 2315 /* this is copied over from RemoveStatus() */ 2316 D_status = 0; 2317 GotoPos(0, STATLINE); 2318 RefreshLine(STATLINE, 0, D_status_len - 1, 0); 2319 GotoPos(D_status_lastx, D_status_lasty); 2320 flayer = D_forecv ? D_forecv->c_layer : 0; 2321 if (flayer) 2322 LaySetCursor(); 2323 display = olddisplay; 2324 flayer = oldflayer; 2325 D_status_obuflen = D_obuflen; 2326 D_status_obuffree = D_obuffree; 2327 D_obuffree = D_obuflen = 0; 2328 D_status = STATUS_ON_WIN; 2329 } 2330 gettimeofday(&D_status_time, NULL); 2331 SetTimeout(&D_statusev, MsgWait); 2332 evenq(&D_statusev); 2333#ifdef HAVE_BRAILLE 2334 RefreshBraille(); /* let user see multiple Msg()s */ 2335#endif 2336} 2337 2338void 2339RemoveStatus() 2340{ 2341 struct display *olddisplay; 2342 struct layer *oldflayer; 2343 int where; 2344 2345 if (!display) 2346 return; 2347 if (!(where = D_status)) 2348 return; 2349 2350 debug("RemoveStatus\n"); 2351 if (D_status_obuffree >= 0) 2352 { 2353 D_obuflen = D_status_obuflen; 2354 D_obuffree = D_status_obuffree; 2355 D_status_obuffree = -1; 2356 D_status = 0; 2357 D_status_bell = 0; 2358 evdeq(&D_statusev); 2359 return; 2360 } 2361 D_status = 0; 2362 D_status_bell = 0; 2363 evdeq(&D_statusev); 2364 olddisplay = display; 2365 oldflayer = flayer; 2366 if (where == STATUS_ON_WIN) 2367 { 2368 GotoPos(0, STATLINE); 2369 RefreshLine(STATLINE, 0, D_status_len - 1, 0); 2370 GotoPos(D_status_lastx, D_status_lasty); 2371 } 2372 else 2373 RefreshHStatus(); 2374 flayer = D_forecv ? D_forecv->c_layer : 0; 2375 if (flayer) 2376 LaySetCursor(); 2377 display = olddisplay; 2378 flayer = oldflayer; 2379} 2380 2381/* refresh the display's hstatus line */ 2382void 2383ShowHStatus(str) 2384char *str; 2385{ 2386 int l, i, ox, oy, max; 2387 2388 if (D_status == STATUS_ON_WIN && D_has_hstatus == HSTATUS_LASTLINE && STATLINE == D_height-1) 2389 return; /* sorry, in use */ 2390 if (D_blocked) 2391 return; 2392 2393 if (D_HS && D_has_hstatus == HSTATUS_HS) 2394 { 2395 if (!D_hstatus && (str == 0 || *str == 0)) 2396 return; 2397 debug("ShowHStatus: using HS\n"); 2398 SetRendition(&mchar_null); 2399 InsertMode(0); 2400 if (D_hstatus) 2401 AddCStr(D_DS); 2402 D_hstatus = 0; 2403 if (str == 0 || *str == 0) 2404 return; 2405 AddCStr2(D_TS, 0); 2406 max = D_WS > 0 ? D_WS : (D_width - !D_CLP); 2407 if ((int)strlen(str) > max) 2408 AddStrn(str, max); 2409 else 2410 AddStr(str); 2411 AddCStr(D_FS); 2412 D_hstatus = 1; 2413 } 2414 else if (D_has_hstatus == HSTATUS_LASTLINE) 2415 { 2416 debug("ShowHStatus: using last line\n"); 2417 ox = D_x; 2418 oy = D_y; 2419 str = str ? str : ""; 2420 l = strlen(str); 2421 if (l > D_width) 2422 l = D_width; 2423 GotoPos(0, D_height - 1); 2424 SetRendition(captionalways || D_cvlist == 0 || D_cvlist->c_next ? &mchar_null: &mchar_so); 2425 if (!PutWinMsg(str, 0, l)) 2426 for (i = 0; i < l; i++) 2427 PUTCHARLP(str[i]); 2428 if (!captionalways && D_cvlist && !D_cvlist->c_next) 2429 while (l++ < D_width) 2430 PUTCHARLP(' '); 2431 if (l < D_width) 2432 ClearArea(l, D_height - 1, l, D_width - 1, D_width - 1, D_height - 1, 0, 0); 2433 if (ox != -1 && oy != -1) 2434 GotoPos(ox, oy); 2435 D_hstatus = *str ? 1 : 0; 2436 SetRendition(&mchar_null); 2437 } 2438 else if (str && *str && D_has_hstatus == HSTATUS_MESSAGE) 2439 { 2440 debug("ShowHStatus: using message\n"); 2441 Msg(0, "%s", str); 2442 } 2443} 2444 2445 2446/* 2447 * Refreshes the harstatus of the fore window. Shouldn't be here... 2448 */ 2449void 2450RefreshHStatus() 2451{ 2452 char *buf; 2453 2454 evdeq(&D_hstatusev); 2455 if (D_status == STATUS_ON_HS) 2456 return; 2457 buf = MakeWinMsgEv(hstatusstring, D_fore, '%', (D_HS && D_has_hstatus == HSTATUS_HS && D_WS > 0) ? D_WS : D_width - !D_CLP, &D_hstatusev, 0); 2458 if (buf && *buf) 2459 { 2460 ShowHStatus(buf); 2461 if (D_has_hstatus != HSTATUS_IGNORE && D_hstatusev.timeout.tv_sec) 2462 evenq(&D_hstatusev); 2463 } 2464 else 2465 ShowHStatus((char *)0); 2466} 2467 2468/*********************************************************************/ 2469/* 2470 * Here come the routines that refresh an arbitrary part of the screen. 2471 */ 2472 2473void 2474RefreshAll(isblank) 2475int isblank; 2476{ 2477 struct canvas *cv; 2478 2479 ASSERT(display); 2480 debug("Signalling full refresh!\n"); 2481 for (cv = D_cvlist; cv; cv = cv->c_next) 2482 { 2483 CV_CALL(cv, LayRedisplayLine(-1, -1, -1, isblank)); 2484 display = cv->c_display; /* just in case! */ 2485 } 2486 RefreshArea(0, 0, D_width - 1, D_height - 1, isblank); 2487} 2488 2489void 2490RefreshArea(xs, ys, xe, ye, isblank) 2491int xs, ys, xe, ye, isblank; 2492{ 2493 int y; 2494 ASSERT(display); 2495 debug2("Refresh Area: %d,%d", xs, ys); 2496 debug3(" - %d,%d (isblank=%d)\n", xe, ye, isblank); 2497 if (!isblank && xs == 0 && xe == D_width - 1 && ye == D_height - 1 && (ys == 0 || D_CD)) 2498 { 2499 ClearArea(xs, ys, xs, xe, xe, ye, 0, 0); 2500 isblank = 1; 2501 } 2502 for (y = ys; y <= ye; y++) 2503 RefreshLine(y, xs, xe, isblank); 2504} 2505 2506void 2507RefreshLine(y, from, to, isblank) 2508int y, from, to, isblank; 2509{ 2510 struct viewport *vp, *lvp; 2511 struct canvas *cv, *lcv, *cvlist, *cvlnext; 2512 struct layer *oldflayer; 2513 int xx, yy; 2514 char *buf; 2515 struct win *p; 2516 2517 ASSERT(display); 2518 2519 debug2("RefreshLine %d %d", y, from); 2520 debug2(" %d %d\n", to, isblank); 2521 2522 if (D_status == STATUS_ON_WIN && y == STATLINE) 2523 return; /* can't refresh status */ 2524 2525 if (isblank == 0 && D_CE && to == D_width - 1 && from < to) 2526 { 2527 GotoPos(from, y); 2528 if (D_UT || D_BE) 2529 SetRendition(&mchar_null); 2530 AddCStr(D_CE); 2531 isblank = 1; 2532 } 2533 while (from <= to) 2534 { 2535 lcv = 0; 2536 lvp = 0; 2537 for (cv = display->d_cvlist; cv; cv = cv->c_next) 2538 { 2539 if (y < cv->c_ys || y > cv->c_ye || to < cv->c_xs || from > cv->c_xe) 2540 continue; 2541 debug2("- canvas hit: %d %d", cv->c_xs, cv->c_ys); 2542 debug2(" %d %d\n", cv->c_xe, cv->c_ye); 2543 for (vp = cv->c_vplist; vp; vp = vp->v_next) 2544 { 2545 debug2(" - vp: %d %d", vp->v_xs, vp->v_ys); 2546 debug2(" %d %d\n", vp->v_xe, vp->v_ye); 2547 /* find leftmost overlapping vp */ 2548 if (y >= vp->v_ys && y <= vp->v_ye && from <= vp->v_xe && to >= vp->v_xs && (lvp == 0 || lvp->v_xs > vp->v_xs)) 2549 { 2550 lcv = cv; 2551 lvp = vp; 2552 } 2553 } 2554 } 2555 if (lvp == 0) 2556 break; 2557 if (from < lvp->v_xs) 2558 { 2559 if (!isblank) 2560 DisplayLine(&mline_null, &mline_blank, y, from, lvp->v_xs - 1); 2561 from = lvp->v_xs; 2562 } 2563 2564 /* call LayRedisplayLine on canvas lcv viewport lvp */ 2565 yy = y - lvp->v_yoff; 2566 xx = to < lvp->v_xe ? to : lvp->v_xe; 2567 2568 if (lcv->c_layer && yy == lcv->c_layer->l_height) 2569 { 2570 GotoPos(from, y); 2571 SetRendition(&mchar_blank); 2572 while (from <= lvp->v_xe && from - lvp->v_xoff < lcv->c_layer->l_width) 2573 { 2574 PUTCHARLP('-'); 2575 from++; 2576 } 2577 if (from >= lvp->v_xe + 1) 2578 continue; 2579 } 2580 if (lcv->c_layer == 0 || yy >= lcv->c_layer->l_height || from - lvp->v_xoff >= lcv->c_layer->l_width) 2581 { 2582 if (!isblank) 2583 DisplayLine(&mline_null, &mline_blank, y, from, lvp->v_xe); 2584 from = lvp->v_xe + 1; 2585 continue; 2586 } 2587 2588 if (xx - lvp->v_xoff >= lcv->c_layer->l_width) 2589 xx = lcv->c_layer->l_width + lvp->v_xoff - 1; 2590 oldflayer = flayer; 2591 flayer = lcv->c_layer; 2592 cvlist = flayer->l_cvlist; 2593 cvlnext = lcv->c_lnext; 2594 flayer->l_cvlist = lcv; 2595 lcv->c_lnext = 0; 2596 LayRedisplayLine(yy, from - lvp->v_xoff, xx - lvp->v_xoff, isblank); 2597 flayer->l_cvlist = cvlist; 2598 lcv->c_lnext = cvlnext; 2599 flayer = oldflayer; 2600 2601 from = xx + 1; 2602 } 2603 if (from > to) 2604 return; /* all done */ 2605 2606 if (y == D_height - 1 && D_has_hstatus == HSTATUS_LASTLINE) 2607 { 2608 RefreshHStatus(); 2609 return; 2610 } 2611 2612 for (cv = display->d_cvlist; cv; cv = cv->c_next) 2613 if (y == cv->c_ye + 1) 2614 break; 2615 if (cv == 0) 2616 { 2617 if (!isblank) 2618 DisplayLine(&mline_null, &mline_blank, y, from, to); 2619 return; 2620 } 2621 2622 p = Layer2Window(cv->c_layer); 2623 buf = MakeWinMsgEv(captionstring, p, '%', D_width - !D_CLP, &cv->c_captev, 0); 2624 if (cv->c_captev.timeout.tv_sec) 2625 evenq(&cv->c_captev); 2626 xx = strlen(buf); 2627 GotoPos(from, y); 2628 SetRendition(&mchar_so); 2629 if (PutWinMsg(buf, from, to + 1)) 2630 from = xx > to + 1 ? to + 1 : xx; 2631 else 2632 { 2633 while (from <= to && from < xx) 2634 { 2635 PUTCHARLP(buf[from]); 2636 from++; 2637 } 2638 } 2639 while (from++ <= to) 2640 PUTCHARLP(' '); 2641} 2642 2643/*********************************************************************/ 2644 2645/* clear lp_missing by writing the char on the screen. The 2646 * position must be safe. 2647 */ 2648static void 2649WriteLP(x2, y2) 2650int x2, y2; 2651{ 2652 struct mchar oldrend; 2653 2654 ASSERT(display); 2655 ASSERT(D_lp_missing); 2656 oldrend = D_rend; 2657 debug2("WriteLP(%d,%d)\n", x2, y2); 2658#ifdef DW_CHARS 2659 if (D_lpchar.mbcs) 2660 { 2661 if (x2 > 0) 2662 x2--; 2663 else 2664 D_lpchar = mchar_blank; 2665 } 2666#endif 2667 /* Can't use PutChar */ 2668 GotoPos(x2, y2); 2669 SetRendition(&D_lpchar); 2670 PUTCHAR(D_lpchar.image); 2671#ifdef DW_CHARS 2672 if (D_lpchar.mbcs) 2673 PUTCHAR(D_lpchar.mbcs); 2674#endif 2675 D_lp_missing = 0; 2676 SetRendition(&oldrend); 2677} 2678 2679void 2680ClearLine(oml, y, from, to, bce) 2681struct mline *oml; 2682int from, to, y, bce; 2683{ 2684 int x; 2685#ifdef COLOR 2686 struct mchar bcechar; 2687#endif 2688 2689 debug3("ClearLine %d,%d-%d\n", y, from, to); 2690 if (D_UT) /* Safe to erase ? */ 2691 SetRendition(&mchar_null); 2692#ifdef COLOR 2693 if (D_BE) 2694 SetBackColor(bce); 2695#endif 2696 if (from == 0 && D_CB && (to != D_width - 1 || (D_x == to && D_y == y)) && (!bce || D_BE)) 2697 { 2698 GotoPos(to, y); 2699 AddCStr(D_CB); 2700 return; 2701 } 2702 if (to == D_width - 1 && D_CE && (!bce || D_BE)) 2703 { 2704 GotoPos(from, y); 2705 AddCStr(D_CE); 2706 return; 2707 } 2708 if (oml == 0) 2709 oml = &mline_null; 2710#ifdef COLOR 2711 if (!bce) 2712 { 2713 DisplayLine(oml, &mline_blank, y, from, to); 2714 return; 2715 } 2716 bcechar = mchar_blank; 2717 rend_setbg(&bcechar, bce); 2718 for (x = from; x <= to; x++) 2719 copy_mchar2mline(&bcechar, &mline_old, x); 2720 DisplayLine(oml, &mline_old, y, from, to); 2721#else 2722 DisplayLine(oml, &mline_blank, y, from, to); 2723#endif 2724} 2725 2726void 2727DisplayLine(oml, ml, y, from, to) 2728struct mline *oml, *ml; 2729int from, to, y; 2730{ 2731 register int x; 2732 int last2flag = 0, delete_lp = 0; 2733 2734 ASSERT(display); 2735 ASSERT(y >= 0 && y < D_height); 2736 ASSERT(from >= 0 && from < D_width); 2737 ASSERT(to >= 0 && to < D_width); 2738 if (!D_CLP && y == D_bot && to == D_width - 1) 2739 { 2740 if (D_lp_missing || !cmp_mline(oml, ml, to)) 2741 { 2742#ifdef DW_CHARS 2743 if ((D_IC || D_IM) && from < to && !dw_left(ml, to, D_encoding)) 2744#else 2745 if ((D_IC || D_IM) && from < to) 2746#endif 2747 { 2748 last2flag = 1; 2749 D_lp_missing = 0; 2750 to--; 2751 } 2752 else 2753 { 2754 delete_lp = !cmp_mchar_mline(&mchar_blank, oml, to) && (D_CE || D_DC || D_CDC); 2755 D_lp_missing = !cmp_mchar_mline(&mchar_blank, ml, to); 2756 copy_mline2mchar(&D_lpchar, ml, to); 2757 } 2758 } 2759 to--; 2760 } 2761#ifdef DW_CHARS 2762 if (D_mbcs) 2763 { 2764 /* finish dw-char (can happen after a wrap) */ 2765 debug("DisplayLine finishing kanji\n"); 2766 SetRenditionMline(ml, from); 2767 PUTCHAR(ml->image[from]); 2768 from++; 2769 } 2770#endif 2771 for (x = from; x <= to; x++) 2772 { 2773#if 0 /* no longer needed */ 2774 if (x || D_x != D_width || D_y != y - 1) 2775#endif 2776 { 2777 if (x < to || x != D_width - 1 || ml->image[x + 1]) 2778 if (cmp_mline(oml, ml, x)) 2779 continue; 2780 GotoPos(x, y); 2781 } 2782#ifdef DW_CHARS 2783 if (dw_right(ml, x, D_encoding)) 2784 { 2785 x--; 2786 debug1("DisplayLine on right side of dw char- x now %d\n", x); 2787 GotoPos(x, y); 2788 } 2789 if (x == to && dw_left(ml, x, D_encoding)) 2790 break; /* don't start new kanji */ 2791#endif 2792 SetRenditionMline(ml, x); 2793 PUTCHAR(ml->image[x]); 2794#ifdef DW_CHARS 2795 if (dw_left(ml, x, D_encoding)) 2796 PUTCHAR(ml->image[++x]); 2797#endif 2798 } 2799#if 0 /* not needed any longer */ 2800 /* compare != 0 because ' ' can happen when clipping occures */ 2801 if (to == D_width - 1 && y < D_height - 1 && D_x == D_width && ml->image[to + 1]) 2802 GotoPos(0, y + 1); 2803#endif 2804 if (last2flag) 2805 { 2806 GotoPos(x, y); 2807 SetRenditionMline(ml, x + 1); 2808 PUTCHAR(ml->image[x + 1]); 2809 GotoPos(x, y); 2810 SetRenditionMline(ml, x); 2811 INSERTCHAR(ml->image[x]); 2812 } 2813 else if (delete_lp) 2814 { 2815 if (D_UT) 2816 SetRendition(&mchar_null); 2817 if (D_DC) 2818 AddCStr(D_DC); 2819 else if (D_CDC) 2820 AddCStr2(D_CDC, 1); 2821 else if (D_CE) 2822 AddCStr(D_CE); 2823 } 2824} 2825 2826void 2827PutChar(c, x, y) 2828struct mchar *c; 2829int x, y; 2830{ 2831 GotoPos(x, y); 2832 SetRendition(c); 2833 PUTCHARLP(c->image); 2834#ifdef DW_CHARS 2835 if (c->mbcs) 2836 { 2837# ifdef UTF8 2838 if (D_encoding == UTF8) 2839 D_rend.font = 0; 2840# endif 2841 PUTCHARLP(c->mbcs); 2842 } 2843#endif 2844} 2845 2846void 2847InsChar(c, x, xe, y, oml) 2848struct mchar *c; 2849int x, xe, y; 2850struct mline *oml; 2851{ 2852 GotoPos(x, y); 2853 if (y == D_bot && !D_CLP) 2854 { 2855 if (x == D_width - 1) 2856 { 2857 D_lp_missing = 1; 2858 D_lpchar = *c; 2859 return; 2860 } 2861 if (xe == D_width - 1) 2862 D_lp_missing = 0; 2863 } 2864 if (x == xe) 2865 { 2866 SetRendition(c); 2867 PUTCHARLP(c->image); 2868 return; 2869 } 2870 if (!(D_IC || D_CIC || D_IM) || xe != D_width - 1) 2871 { 2872 RefreshLine(y, x, xe, 0); 2873 GotoPos(x + 1, y); 2874 /* UpdateLine(oml, y, x, xe); */ 2875 return; 2876 } 2877 InsertMode(1); 2878 if (!D_insert) 2879 { 2880#ifdef DW_CHARS 2881 if (c->mbcs && D_IC) 2882 AddCStr(D_IC); 2883 if (D_IC) 2884 AddCStr(D_IC); 2885 else 2886 AddCStr2(D_CIC, c->mbcs ? 2 : 1); 2887#else 2888 if (D_IC) 2889 AddCStr(D_IC); 2890 else 2891 AddCStr2(D_CIC, 1); 2892#endif 2893 } 2894 SetRendition(c); 2895 RAW_PUTCHAR(c->image); 2896#ifdef DW_CHARS 2897 if (c->mbcs) 2898 { 2899# ifdef UTF8 2900 if (D_encoding == UTF8) 2901 D_rend.font = 0; 2902# endif 2903 if (D_x == D_width - 1) 2904 PUTCHARLP(c->mbcs); 2905 else 2906 RAW_PUTCHAR(c->mbcs); 2907 } 2908#endif 2909} 2910 2911void 2912WrapChar(c, x, y, xs, ys, xe, ye, ins) 2913struct mchar *c; 2914int x, y; 2915int xs, ys, xe, ye; 2916int ins; 2917{ 2918 int bce; 2919 2920#ifdef COLOR 2921 bce = rend_getbg(c); 2922#else 2923 bce = 0; 2924#endif 2925 debug("WrapChar:"); 2926 debug2(" x %d y %d", x, y); 2927 debug2(" Dx %d Dy %d", D_x, D_y); 2928 debug2(" xs %d ys %d", xs, ys); 2929 debug3(" xe %d ye %d ins %d\n", xe, ye, ins); 2930 if (xs != 0 || x != D_width || !D_AM) 2931 { 2932 if (y == ye) 2933 ScrollV(xs, ys, xe, ye, 1, bce); 2934 else if (y < D_height - 1) 2935 y++; 2936 if (ins) 2937 InsChar(c, xs, xe, y, 0); 2938 else 2939 PutChar(c, xs, y); 2940 return; 2941 } 2942 if (y == ye) /* we have to scroll */ 2943 { 2944 debug("- scrolling\n"); 2945 ChangeScrollRegion(ys, ye); 2946 if (D_bot != y || D_x != D_width || (!bce && !D_BE)) 2947 { 2948 debug("- have to call ScrollV\n"); 2949 ScrollV(xs, ys, xe, ye, 1, bce); 2950 y--; 2951 } 2952 } 2953 else if (y == D_bot) /* remove unusable region? */ 2954 ChangeScrollRegion(0, D_height - 1); 2955 if (D_x != D_width || D_y != y) 2956 { 2957 if (D_CLP && y >= 0) /* don't even try if !LP */ 2958 RefreshLine(y, D_width - 1, D_width - 1, 0); 2959 debug2("- refresh last char -> x,y now %d,%d\n", D_x, D_y); 2960 if (D_x != D_width || D_y != y) /* sorry, no bonus */ 2961 { 2962 if (y == ye) 2963 ScrollV(xs, ys, xe, ye, 1, bce); 2964 GotoPos(xs, y == ye || y == D_height - 1 ? y : y + 1); 2965 } 2966 } 2967 debug("- writeing new char"); 2968 if (y != ye && y < D_height - 1) 2969 y++; 2970 if (ins != D_insert) 2971 InsertMode(ins); 2972 if (ins && !D_insert) 2973 { 2974 InsChar(c, 0, xe, y, 0); 2975 debug2(" -> done with insert (%d,%d)\n", D_x, D_y); 2976 return; 2977 } 2978 D_y = y; 2979 D_x = 0; 2980 SetRendition(c); 2981 RAW_PUTCHAR(c->image); 2982#ifdef DW_CHARS 2983 if (c->mbcs) 2984 { 2985# ifdef UTF8 2986 if (D_encoding == UTF8) 2987 D_rend.font = 0; 2988# endif 2989 RAW_PUTCHAR(c->mbcs); 2990 } 2991#endif 2992 debug2(" -> done (%d,%d)\n", D_x, D_y); 2993} 2994 2995int 2996ResizeDisplay(wi, he) 2997int wi, he; 2998{ 2999 ASSERT(display); 3000 debug2("ResizeDisplay: to (%d,%d).\n", wi, he); 3001 if (D_width == wi && D_height == he) 3002 { 3003 debug("ResizeDisplay: No change\n"); 3004 return 0; 3005 } 3006 if (D_width != wi && (D_height == he || !D_CWS) && D_CZ0 && (wi == Z0width || wi == Z1width)) 3007 { 3008 debug("ResizeDisplay: using Z0/Z1\n"); 3009 AddCStr(wi == Z0width ? D_CZ0 : D_CZ1); 3010 ChangeScreenSize(wi, D_height, 0); 3011 return (he == D_height) ? 0 : -1; 3012 } 3013 if (D_CWS) 3014 { 3015 debug("ResizeDisplay: using WS\n"); 3016 AddCStr(tgoto(D_CWS, wi, he)); 3017 ChangeScreenSize(wi, he, 0); 3018 return 0; 3019 } 3020 return -1; 3021} 3022 3023void 3024ChangeScrollRegion(newtop, newbot) 3025int newtop, newbot; 3026{ 3027 if (display == 0) 3028 return; 3029 if (newtop == newbot) 3030 return; /* xterm etc can't do it */ 3031 if (newtop == -1) 3032 newtop = 0; 3033 if (newbot == -1) 3034 newbot = D_height - 1; 3035 if (D_CS == 0) 3036 { 3037 D_top = 0; 3038 D_bot = D_height - 1; 3039 return; 3040 } 3041 if (D_top == newtop && D_bot == newbot) 3042 return; 3043 debug2("ChangeScrollRegion: (%d - %d)\n", newtop, newbot); 3044 AddCStr(tgoto(D_CS, newbot, newtop)); 3045 D_top = newtop; 3046 D_bot = newbot; 3047 D_y = D_x = -1; /* Just in case... */ 3048} 3049 3050#ifdef RXVT_OSC 3051void 3052SetXtermOSC(i, s) 3053int i; 3054char *s; 3055{ 3056 static char oscs[] = "1;\000\00020;\00039;\00049;\000"; 3057 3058 ASSERT(display); 3059 if (!D_CXT) 3060 return; 3061 if (!s) 3062 s = ""; 3063 if (!D_xtermosc[i] && !*s) 3064 return; 3065 if (i == 0 && !*s) 3066 s = "screen"; /* always set icon name */ 3067 if (i == 1 && !*s) 3068 s = ""; /* no background */ 3069 if (i == 2 && !*s) 3070 s = "black"; /* black text */ 3071 if (i == 3 && !*s) 3072 s = "white"; /* on white background */ 3073 D_xtermosc[i] = 1; 3074 AddStr("\033]"); 3075 AddStr(oscs + i * 4); 3076 AddStr(s); 3077 AddChar(7); 3078} 3079 3080void 3081ClearAllXtermOSC() 3082{ 3083 int i; 3084 for (i = 3; i >= 0; i--) 3085 SetXtermOSC(i, 0); 3086} 3087#endif 3088 3089/* 3090 * Output buffering routines 3091 */ 3092 3093void 3094AddStr(str) 3095char *str; 3096{ 3097 register char c; 3098 3099 ASSERT(display); 3100 3101#ifdef UTF8 3102 if (D_encoding == UTF8) 3103 { 3104 while ((c = *str++)) 3105 AddUtf8((unsigned char)c); 3106 return; 3107 } 3108#endif 3109 while ((c = *str++)) 3110 AddChar(c); 3111} 3112 3113void 3114AddStrn(str, n) 3115char *str; 3116int n; 3117{ 3118 register char c; 3119 3120 ASSERT(display); 3121#ifdef UTF8 3122 if (D_encoding == UTF8) 3123 { 3124 while ((c = *str++) && n-- > 0) 3125 AddUtf8((unsigned char)c); 3126 } 3127 else 3128#endif 3129 while ((c = *str++) && n-- > 0) 3130 AddChar(c); 3131 while (n-- > 0) 3132 AddChar(' '); 3133} 3134 3135void 3136Flush() 3137{ 3138 register int l; 3139 register char *p; 3140 3141 ASSERT(display); 3142 l = D_obufp - D_obuf; 3143 debug1("Flush(): %d\n", l); 3144 if (l == 0) 3145 return; 3146 ASSERT(l + D_obuffree == D_obuflen); 3147 if (D_userfd < 0) 3148 { 3149 D_obuffree += l; 3150 D_obufp = D_obuf; 3151 return; 3152 } 3153 p = D_obuf; 3154 if (fcntl(D_userfd, F_SETFL, 0)) 3155 debug1("Warning: BLOCK fcntl failed: %d\n", errno); 3156 while (l) 3157 { 3158 register int wr; 3159 wr = write(D_userfd, p, l); 3160 if (wr <= 0) 3161 { 3162 if (errno == EINTR) 3163 continue; 3164 debug1("Writing to display: %d\n", errno); 3165 wr = l; 3166 } 3167 if (!display) 3168 return; 3169 D_obuffree += wr; 3170 p += wr; 3171 l -= wr; 3172 } 3173 D_obuffree += l; 3174 D_obufp = D_obuf; 3175 if (fcntl(D_userfd, F_SETFL, FNBLOCK)) 3176 debug1("Warning: NBLOCK fcntl failed: %d\n", errno); 3177 if (D_blocked == 1) 3178 D_blocked = 0; 3179 D_blocked_fuzz = 0; 3180} 3181 3182void 3183freetty() 3184{ 3185 if (D_userfd >= 0) 3186 close(D_userfd); 3187 debug1("did freetty %d\n", D_userfd); 3188 D_userfd = -1; 3189 D_obufp = 0; 3190 D_obuffree = 0; 3191 if (D_obuf) 3192 free(D_obuf); 3193 D_obuf = 0; 3194 D_obuflen = 0; 3195 D_obuflenmax = -D_obufmax; 3196 D_blocked = 0; 3197 D_blocked_fuzz = 0; 3198} 3199 3200/* 3201 * Asynchronous output routines by 3202 * Tim MacKenzie (tym@dibbler.cs.monash.edu.au) 3203 */ 3204 3205void 3206Resize_obuf() 3207{ 3208 register int ind; 3209 3210 ASSERT(display); 3211 if (D_status_obuffree >= 0) 3212 { 3213 ASSERT(D_obuffree == -1); 3214 if (!D_status_bell) 3215 { 3216 struct timeval now; 3217 int ti; 3218 gettimeofday(&now, NULL); 3219 ti = (now.tv_sec - D_status_time.tv_sec) * 1000 + (now.tv_usec - D_status_time.tv_usec) / 1000; 3220 if (ti < MsgMinWait) 3221 DisplaySleep1000(MsgMinWait - ti, 0); 3222 } 3223 RemoveStatus(); 3224 if (--D_obuffree > 0) /* redo AddChar decrement */ 3225 return; 3226 } 3227 if (D_obuflen && D_obuf) 3228 { 3229 ind = D_obufp - D_obuf; 3230 D_obuflen += GRAIN; 3231 D_obuffree += GRAIN; 3232 D_obuf = realloc(D_obuf, D_obuflen); 3233 } 3234 else 3235 { 3236 ind = 0; 3237 D_obuflen = GRAIN; 3238 D_obuffree = GRAIN; 3239 D_obuf = malloc(D_obuflen); 3240 } 3241 if (!D_obuf) 3242 Panic(0, "Out of memory"); 3243 D_obufp = D_obuf + ind; 3244 D_obuflenmax = D_obuflen - D_obufmax; 3245 debug1("ResizeObuf: resized to %d\n", D_obuflen); 3246} 3247 3248void 3249DisplaySleep1000(n, eat) 3250int n; 3251int eat; 3252{ 3253 char buf; 3254 fd_set r; 3255 struct timeval t; 3256 3257 if (n <= 0) 3258 return; 3259 if (!display) 3260 { 3261 debug("DisplaySleep has no display sigh\n"); 3262 sleep1000(n); 3263 return; 3264 } 3265 t.tv_usec = (n % 1000) * 1000; 3266 t.tv_sec = n / 1000; 3267 FD_ZERO(&r); 3268 FD_SET(D_userfd, &r); 3269 if (select(FD_SETSIZE, &r, (fd_set *)0, (fd_set *)0, &t) > 0) 3270 { 3271 debug("display activity stopped sleep\n"); 3272 if (eat) 3273 read(D_userfd, &buf, 1); 3274 } 3275 debug2("DisplaySleep(%d) ending, eat was %d\n", n, eat); 3276} 3277 3278#ifdef AUTO_NUKE 3279void 3280NukePending() 3281{/* Nuke pending output in current display, clear screen */ 3282 register int len; 3283 int oldtop = D_top, oldbot = D_bot; 3284 struct mchar oldrend; 3285 int oldkeypad = D_keypad, oldcursorkeys = D_cursorkeys; 3286 int oldcurvis = D_curvis; 3287 int oldmouse = D_mouse; 3288 3289 oldrend = D_rend; 3290 len = D_obufp - D_obuf; 3291 debug1("NukePending: nuking %d chars\n", len); 3292 3293 /* Throw away any output that we can... */ 3294# ifdef POSIX 3295 tcflush(D_userfd, TCOFLUSH); 3296# else 3297# ifdef TCFLSH 3298 (void) ioctl(D_userfd, TCFLSH, (char *) 1); 3299# endif 3300# endif 3301 3302 D_obufp = D_obuf; 3303 D_obuffree += len; 3304 D_top = D_bot = -1; 3305 AddCStr(D_TI); 3306 AddCStr(D_IS); 3307 /* Turn off all attributes. (Tim MacKenzie) */ 3308 if (D_ME) 3309 AddCStr(D_ME); 3310 else 3311 { 3312#ifdef COLOR 3313 if (D_hascolor) 3314 AddStr("\033[m"); /* why is D_ME not set? */ 3315#endif 3316 AddCStr(D_SE); 3317 AddCStr(D_UE); 3318 } 3319 /* Check for toggle */ 3320 if (D_IM && strcmp(D_IM, D_EI)) 3321 AddCStr(D_EI); 3322 D_insert = 0; 3323 /* Check for toggle */ 3324#ifdef MAPKEYS 3325 if (D_KS && strcmp(D_KS, D_KE)) 3326 AddCStr(D_KS); 3327 if (D_CCS && strcmp(D_CCS, D_CCE)) 3328 AddCStr(D_CCS); 3329#else 3330 if (D_KS && strcmp(D_KS, D_KE)) 3331 AddCStr(D_KE); 3332 D_keypad = 0; 3333 if (D_CCS && strcmp(D_CCS, D_CCE)) 3334 AddCStr(D_CCE); 3335 D_cursorkeys = 0; 3336#endif 3337 AddCStr(D_CE0); 3338 D_rend = mchar_null; 3339 D_atyp = 0; 3340 AddCStr(D_DS); 3341 D_hstatus = 0; 3342 AddCStr(D_VE); 3343 D_curvis = 0; 3344 ChangeScrollRegion(oldtop, oldbot); 3345 SetRendition(&oldrend); 3346 KeypadMode(oldkeypad); 3347 CursorkeysMode(oldcursorkeys); 3348 CursorVisibility(oldcurvis); 3349 MouseMode(oldmouse); 3350 if (D_CWS) 3351 { 3352 debug("ResizeDisplay: using WS\n"); 3353 AddCStr(tgoto(D_CWS, D_width, D_height)); 3354 } 3355 else if (D_CZ0 && (D_width == Z0width || D_width == Z1width)) 3356 { 3357 debug("ResizeDisplay: using Z0/Z1\n"); 3358 AddCStr(D_width == Z0width ? D_CZ0 : D_CZ1); 3359 } 3360} 3361#endif /* AUTO_NUKE */ 3362 3363#ifdef linux 3364/* linux' select can't handle flow control, so wait 100ms if 3365 * we get EAGAIN 3366 */ 3367static void 3368disp_writeev_eagain(ev, data) 3369struct event *ev; 3370char *data; 3371{ 3372 display = (struct display *)data; 3373 evdeq(&D_writeev); 3374 D_writeev.type = EV_WRITE; 3375 D_writeev.handler = disp_writeev_fn; 3376 evenq(&D_writeev); 3377} 3378#endif 3379 3380static void 3381disp_writeev_fn(ev, data) 3382struct event *ev; 3383char *data; 3384{ 3385 int len, size = OUTPUT_BLOCK_SIZE; 3386 3387 display = (struct display *)data; 3388 len = D_obufp - D_obuf; 3389 if (len < size) 3390 size = len; 3391 ASSERT(len >= 0); 3392 size = write(D_userfd, D_obuf, size); 3393 if (size >= 0) 3394 { 3395 len -= size; 3396 if (len) 3397 { 3398 bcopy(D_obuf + size, D_obuf, len); 3399 debug2("ASYNC: wrote %d - remaining %d\n", size, len); 3400 } 3401 D_obufp -= size; 3402 D_obuffree += size; 3403 if (D_blocked_fuzz) 3404 { 3405 D_blocked_fuzz -= size; 3406 if (D_blocked_fuzz < 0) 3407 D_blocked_fuzz = 0; 3408 } 3409 if (D_blockedev.queued) 3410 { 3411 if (D_obufp - D_obuf > D_obufmax / 2) 3412 { 3413 debug2("%s: resetting timeout to %g secs\n", D_usertty, D_nonblock/1000.); 3414 SetTimeout(&D_blockedev, D_nonblock); 3415 } 3416 else 3417 { 3418 debug1("%s: deleting blocked timeout\n", D_usertty); 3419 evdeq(&D_blockedev); 3420 } 3421 } 3422 if (D_blocked == 1 && D_obuf == D_obufp) 3423 { 3424 /* empty again, restart output */ 3425 debug1("%s: buffer empty, unblocking\n", D_usertty); 3426 D_blocked = 0; 3427 Activate(D_fore ? D_fore->w_norefresh : 0); 3428 D_blocked_fuzz = D_obufp - D_obuf; 3429 } 3430 } 3431 else 3432 { 3433#ifdef linux 3434 /* linux flow control is badly broken */ 3435 if (errno == EAGAIN) 3436 { 3437 evdeq(&D_writeev); 3438 D_writeev.type = EV_TIMEOUT; 3439 D_writeev.handler = disp_writeev_eagain; 3440 SetTimeout(&D_writeev, 100); 3441 evenq(&D_writeev); 3442 } 3443#endif 3444 if (errno != EINTR && errno != EAGAIN) 3445#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) 3446 if (errno != EWOULDBLOCK) 3447#endif 3448 Msg(errno, "Error writing output to display"); 3449 } 3450} 3451 3452static void 3453disp_readev_fn(ev, data) 3454struct event *ev; 3455char *data; 3456{ 3457 int size; 3458 char buf[IOSIZE]; 3459 struct canvas *cv; 3460 3461 display = (struct display *)data; 3462 3463 /* Hmmmm... a bit ugly... */ 3464 if (D_forecv) 3465 for (cv = D_forecv->c_layer->l_cvlist; cv; cv = cv->c_lnext) 3466 { 3467 display = cv->c_display; 3468 if (D_status == STATUS_ON_WIN) 3469 RemoveStatus(); 3470 } 3471 3472 display = (struct display *)data; 3473 if (D_fore == 0) 3474 size = IOSIZE; 3475 else 3476 { 3477#ifdef PSEUDOS 3478 if (W_UWP(D_fore)) 3479 size = sizeof(D_fore->w_pwin->p_inbuf) - D_fore->w_pwin->p_inlen; 3480 else 3481#endif 3482 size = sizeof(D_fore->w_inbuf) - D_fore->w_inlen; 3483 } 3484 3485 if (size > IOSIZE) 3486 size = IOSIZE; 3487 if (size <= 0) 3488 size = 1; /* Always allow one char for command keys */ 3489 3490 size = read(D_userfd, buf, size); 3491 if (size < 0) 3492 { 3493 if (errno == EINTR || errno == EAGAIN) 3494 return; 3495#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) 3496 if (errno == EWOULDBLOCK) 3497 return; 3498#endif 3499 debug1("Read error: %d - hangup!\n", errno); 3500 Hangup(); 3501 sleep(1); 3502 return; 3503 } 3504 else if (size == 0) 3505 { 3506 debug("Found EOF - hangup!\n"); 3507 Hangup(); 3508 sleep(1); 3509 return; 3510 } 3511 if (D_blocked == 4) 3512 { 3513 D_blocked = 0; 3514#ifdef BLANKER_PRG 3515 KillBlanker(); 3516#endif 3517 Activate(D_fore ? D_fore->w_norefresh : 0); 3518 ResetIdle(); 3519 return; 3520 } 3521#ifdef ZMODEM 3522 if (D_blocked > 1) /* 2, 3 */ 3523 { 3524 char *bufp; 3525 struct win *p; 3526 3527 flayer = 0; 3528 for (p = windows; p ; p = p->w_next) 3529 if (p->w_zdisplay == display) 3530 { 3531 flayer = &p->w_layer; 3532 bufp = buf; 3533 while (size > 0) 3534 LayProcess(&bufp, &size); 3535 return; 3536 } 3537 debug("zmodem window gone, deblocking display"); 3538 zmodem_abort(0, display); 3539 } 3540#endif 3541 if (idletimo > 0) 3542 ResetIdle(); 3543 if (D_fore) 3544 D_fore->w_lastdisp = display; 3545 if (D_mouse && D_forecv) 3546 { 3547 unsigned char *bp = (unsigned char *)buf; 3548 int x, y, i = size; 3549 3550 /* XXX this assumes that the string is read in as a whole... */ 3551 for (i = size; i > 0; i--, bp++) 3552 { 3553 if (i > 5 && bp[0] == 033 && bp[1] == '[' && bp[2] == 'M') 3554 { 3555 bp++; 3556 i--; 3557 } 3558 else if (i < 5 || bp[0] != 0233 || bp[1] != 'M') 3559 continue; 3560 x = bp[3] - 33; 3561 y = bp[4] - 33; 3562 if (x >= D_forecv->c_xs && x <= D_forecv->c_xe && y >= D_forecv->c_ys && y <= D_forecv->c_ye) 3563 { 3564 x -= D_forecv->c_xoff; 3565 y -= D_forecv->c_yoff; 3566 if (x >= 0 && x < D_forecv->c_layer->l_width && y >= 0 && y < D_forecv->c_layer->l_height) 3567 { 3568 bp[3] = x + 33; 3569 bp[4] = y + 33; 3570 i -= 4; 3571 bp += 4; 3572 continue; 3573 } 3574 } 3575 if (bp[0] == '[') 3576 { 3577 bcopy((char *)bp + 1, (char *)bp, i); 3578 bp--; 3579 size--; 3580 } 3581 if (i > 5) 3582 bcopy((char *)bp + 5, (char *)bp, i - 5); 3583 bp--; 3584 i -= 4; 3585 size -= 5; 3586 } 3587 } 3588#ifdef ENCODINGS 3589 if (D_encoding != (D_forecv ? D_forecv->c_layer->l_encoding : 0)) 3590 { 3591 int i, j, c, enc; 3592 char buf2[IOSIZE * 2 + 10]; 3593 enc = D_forecv ? D_forecv->c_layer->l_encoding : 0; 3594 for (i = j = 0; i < size; i++) 3595 { 3596 c = ((unsigned char *)buf)[i]; 3597 c = DecodeChar(c, D_encoding, &D_decodestate); 3598 if (c == -2) 3599 i--; /* try char again */ 3600 if (c < 0) 3601 continue; 3602 if (pastefont) 3603 { 3604 int font = 0; 3605 j += EncodeChar(buf2 + j, c, enc, &font); 3606 j += EncodeChar(buf2 + j, -1, enc, &font); 3607 } 3608 else 3609 j += EncodeChar(buf2 + j, c, enc, 0); 3610 if (j > (int)sizeof(buf2) - 10) /* just in case... */ 3611 break; 3612 } 3613 (*D_processinput)(buf2, j); 3614 return; 3615 } 3616#endif 3617 (*D_processinput)(buf, size); 3618} 3619 3620static void 3621disp_status_fn(ev, data) 3622struct event *ev; 3623char *data; 3624{ 3625 display = (struct display *)data; 3626 debug1("disp_status_fn for display %x\n", (int)display); 3627 if (D_status) 3628 RemoveStatus(); 3629} 3630 3631static void 3632disp_hstatus_fn(ev, data) 3633struct event *ev; 3634char *data; 3635{ 3636 display = (struct display *)data; 3637 if (D_status == STATUS_ON_HS) 3638 { 3639 SetTimeout(ev, 1); 3640 evenq(ev); 3641 return; 3642 } 3643 RefreshHStatus(); 3644} 3645 3646static void 3647disp_blocked_fn(ev, data) 3648struct event *ev; 3649char *data; 3650{ 3651 struct win *p; 3652 3653 display = (struct display *)data; 3654 debug1("blocked timeout %s\n", D_usertty); 3655 if (D_obufp - D_obuf > D_obufmax + D_blocked_fuzz) 3656 { 3657 debug("stopping output to display\n"); 3658 D_blocked = 1; 3659 /* re-enable all windows */ 3660 for (p = windows; p; p = p->w_next) 3661 if (p->w_readev.condneg == &D_obuflenmax) 3662 { 3663 debug1("freeing window #%d\n", p->w_number); 3664 p->w_readev.condpos = p->w_readev.condneg = 0; 3665 } 3666 } 3667} 3668 3669static void 3670cv_winid_fn(ev, data) 3671struct event *ev; 3672char *data; 3673{ 3674 int ox, oy; 3675 struct canvas *cv = (struct canvas *)data; 3676 3677 display = cv->c_display; 3678 if (D_status == STATUS_ON_WIN) 3679 { 3680 SetTimeout(ev, 1); 3681 evenq(ev); 3682 return; 3683 } 3684 ox = D_x; 3685 oy = D_y; 3686 if (cv->c_ye + 1 < D_height) 3687 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); 3688 if (ox != -1 && oy != -1) 3689 GotoPos(ox, oy); 3690} 3691 3692#ifdef MAPKEYS 3693static void 3694disp_map_fn(ev, data) 3695struct event *ev; 3696char *data; 3697{ 3698 char *p; 3699 int l, i; 3700 unsigned char *q; 3701 display = (struct display *)data; 3702 debug("Flushing map sequence\n"); 3703 if (!(l = D_seql)) 3704 return; 3705 p = (char *)D_seqp - l; 3706 D_seqp = D_kmaps + 3; 3707 D_seql = 0; 3708 if ((q = D_seqh) != 0) 3709 { 3710 D_seqh = 0; 3711 i = q[0] << 8 | q[1]; 3712 i &= ~KMAP_NOTIMEOUT; 3713 debug1("Mapping former hit #%d - ", i); 3714 debug2("%d(%s) - ", q[2], q + 3); 3715 if (StuffKey(i)) 3716 ProcessInput2((char *)q + 3, q[2]); 3717 if (display == 0) 3718 return; 3719 l -= q[2]; 3720 p += q[2]; 3721 } 3722 else 3723 D_dontmap = 1; 3724 ProcessInput(p, l); 3725} 3726#endif 3727 3728static void 3729disp_idle_fn(ev, data) 3730struct event *ev; 3731char *data; 3732{ 3733 struct display *olddisplay; 3734 display = (struct display *)data; 3735 debug("idle timeout\n"); 3736 if (idletimo <= 0 || idleaction.nr == RC_ILLEGAL) 3737 return; 3738 olddisplay = display; 3739 flayer = D_forecv->c_layer; 3740 fore = D_fore; 3741 DoAction(&idleaction, -1); 3742 if (idleaction.nr == RC_BLANKER) 3743 return; 3744 for (display = displays; display; display = display->d_next) 3745 if (olddisplay == display) 3746 break; 3747 if (display) 3748 ResetIdle(); 3749} 3750 3751void 3752ResetIdle() 3753{ 3754 if (idletimo > 0) 3755 { 3756 SetTimeout(&D_idleev, idletimo); 3757 if (!D_idleev.queued) 3758 evenq(&D_idleev); 3759 } 3760 else 3761 evdeq(&D_idleev); 3762} 3763 3764 3765#ifdef BLANKER_PRG 3766 3767static void 3768disp_blanker_fn(ev, data) 3769struct event *ev; 3770char *data; 3771{ 3772 char buf[IOSIZE], *b; 3773 int size; 3774 3775 display = (struct display *)data; 3776 size = read(D_blankerev.fd, buf, IOSIZE); 3777 if (size <= 0) 3778 { 3779 evdeq(&D_blankerev); 3780 close(D_blankerev.fd); 3781 D_blankerev.fd = -1; 3782 return; 3783 } 3784 for (b = buf; size; size--) 3785 AddChar(*b++); 3786} 3787 3788void 3789KillBlanker() 3790{ 3791 int oldtop = D_top, oldbot = D_bot; 3792 struct mchar oldrend; 3793 3794 if (D_blankerev.fd == -1) 3795 return; 3796 if (D_blocked == 4) 3797 D_blocked = 0; 3798 evdeq(&D_blankerev); 3799 close(D_blankerev.fd); 3800 D_blankerev.fd = -1; 3801 Kill(D_blankerpid, SIGHUP); 3802 D_top = D_bot = -1; 3803 oldrend = D_rend; 3804 if (D_ME) 3805 { 3806 AddCStr(D_ME); 3807 AddCStr(D_ME); 3808 } 3809 else 3810 { 3811#ifdef COLOR 3812 if (D_hascolor) 3813 AddStr("\033[m\033[m"); /* why is D_ME not set? */ 3814#endif 3815 AddCStr(D_SE); 3816 AddCStr(D_UE); 3817 } 3818 AddCStr(D_VE); 3819 AddCStr(D_CE0); 3820 D_rend = mchar_null; 3821 D_atyp = 0; 3822 D_curvis = 0; 3823 D_x = D_y = -1; 3824 ChangeScrollRegion(oldtop, oldbot); 3825 SetRendition(&oldrend); 3826 ClearAll(); 3827} 3828 3829void 3830RunBlanker(cmdv) 3831char **cmdv; 3832{ 3833 char *m; 3834 int pid; 3835 int slave = -1; 3836 char termname[30]; 3837#ifndef TIOCSWINSZ 3838 char libuf[20], cobuf[20]; 3839#endif 3840 char **np; 3841 3842 strcpy(termname, "TERM="); 3843 strncpy(termname + 5, D_termname, sizeof(termname) - 6); 3844 termname[sizeof(termname) - 1] = 0; 3845 KillBlanker(); 3846 D_blankerpid = -1; 3847 if ((D_blankerev.fd = OpenPTY(&m)) == -1) 3848 { 3849 Msg(0, "OpenPty failed"); 3850 return; 3851 } 3852#ifdef O_NOCTTY 3853 if (pty_preopen) 3854 { 3855 if ((slave = open(m, O_RDWR|O_NOCTTY)) == -1) 3856 { 3857 Msg(errno, "%s", m); 3858 close(D_blankerev.fd); 3859 D_blankerev.fd = -1; 3860 return; 3861 } 3862 } 3863#endif 3864 switch (pid = (int)fork()) 3865 { 3866 case -1: 3867 Msg(errno, "fork"); 3868 close(D_blankerev.fd); 3869 D_blankerev.fd = -1; 3870 return; 3871 case 0: 3872 displays = 0; 3873#ifdef DEBUG 3874 if (dfp && dfp != stderr) 3875 fclose(dfp); 3876#endif 3877 if (setgid(real_gid) || setuid(real_uid)) 3878 Panic(errno, "setuid/setgid"); 3879 brktty(D_userfd); 3880 freetty(); 3881 close(0); 3882 close(1); 3883 close(2); 3884 closeallfiles(slave); 3885 if (open(m, O_RDWR)) 3886 Panic(errno, "Cannot open %s", m); 3887 dup(0); 3888 dup(0); 3889 if (slave != -1) 3890 close(slave); 3891 InitPTY(0); 3892 fgtty(0); 3893 SetTTY(0, &D_OldMode); 3894 np = NewEnv + 3; 3895 *np++ = NewEnv[0]; 3896 *np++ = termname; 3897#ifdef TIOCSWINSZ 3898 glwz.ws_col = D_width; 3899 glwz.ws_row = D_height; 3900 (void)ioctl(0, TIOCSWINSZ, (char *)&glwz); 3901#else 3902 sprintf(libuf, "LINES=%d", D_height); 3903 sprintf(libuf, "COLUMNS=%d", D_width); 3904 *np++ = libuf; 3905 *np++ = cobuf; 3906#endif 3907#ifdef SIGPIPE 3908 signal(SIGPIPE, SIG_DFL); 3909#endif 3910 display = 0; 3911 execvpe(*cmdv, cmdv, NewEnv + 3); 3912 Panic(errno, *cmdv); 3913 default: 3914 break; 3915 } 3916 D_blankerpid = pid; 3917 evenq(&D_blankerev); 3918 D_blocked = 4; 3919 ClearAll(); 3920} 3921 3922#endif 3923