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 <fcntl.h> 26#ifndef sun /* we want to know about TIOCPKT. */ 27# include <sys/ioctl.h> 28#endif 29 30#include "config.h" 31#include "screen.h" 32#include "braille.h" 33#include "extern.h" 34#include "logfile.h" 35 36extern struct display *display, *displays; 37extern struct win *fore; /* for 83 escape */ 38extern struct layer *flayer; /* for 83 escape */ 39 40extern struct NewWindow nwin_default; /* for ResetWindow() */ 41extern int nversion; /* numerical version of screen */ 42extern int log_flush, logtstamp_on, logtstamp_after; 43extern char *logtstamp_string; 44extern char *captionstring; 45extern char *hstatusstring; 46extern char *wliststr; 47#ifdef COPY_PASTE 48extern int compacthist; 49#endif 50#ifdef MULTIUSER 51extern struct acluser *EffectiveAclUser; 52#endif 53 54int Z0width, Z1width; /* widths for Z0/Z1 switching */ 55 56/* globals set in WriteString */ 57static struct win *curr; /* window we are working on */ 58static int rows, cols; /* window size of the curr window */ 59 60int visual_bell = 0; 61int use_hardstatus = 1; /* display status line in hs */ 62char *printcmd = 0; 63int use_altscreen = 0; /* enable alternate screen support? */ 64 65unsigned char *blank; /* line filled with spaces */ 66unsigned char *null; /* line filled with '\0' */ 67 68struct mline mline_old; 69struct mline mline_blank; 70struct mline mline_null; 71 72struct mchar mchar_null; 73struct mchar mchar_blank = {' ' /* , 0, 0, ... */}; 74struct mchar mchar_so = {' ', A_SO /* , 0, 0, ... */}; 75 76/* keep string_t and string_t_string in sync! */ 77static char *string_t_string[] = 78{ 79 "NONE", 80 "DCS", /* Device control string */ 81 "OSC", /* Operating system command */ 82 "APC", /* Application program command */ 83 /* - used for status change */ 84 "PM", /* Privacy message */ 85 "AKA", /* title for current screen */ 86 "GM", /* Global message to every display */ 87 "STATUS" /* User hardstatus line */ 88}; 89 90/* keep state_t and state_t_string in sync! */ 91static char *state_t_string[] = 92{ 93 "LIT", /* Literal input */ 94 "ESC", /* Start of escape sequence */ 95 "ASTR", /* Start of control string */ 96 "STRESC", /* ESC seen in control string */ 97 "CSI", /* Reading arguments in "CSI Pn ;...*/ 98 "PRIN", /* Printer mode */ 99 "PRINESC", /* ESC seen in printer mode */ 100 "PRINCSI", /* CSI seen in printer mode */ 101 "PRIN4" /* CSI 4 seen in printer mode */ 102}; 103 104static int Special __P((int)); 105static void DoESC __P((int, int)); 106static void DoCSI __P((int, int)); 107static void StringStart __P((enum string_t)); 108static void StringChar __P((int)); 109static int StringEnd __P((void)); 110static void PrintStart __P((void)); 111static void PrintChar __P((int)); 112static void PrintFlush __P((void)); 113#ifdef FONT 114static void DesignateCharset __P((int, int)); 115static void MapCharset __P((int)); 116static void MapCharsetR __P((int)); 117#endif 118static void SaveCursor __P((void)); 119static void RestoreCursor __P((void)); 120static void BackSpace __P((void)); 121static void Return __P((void)); 122static void LineFeed __P((int)); 123static void ReverseLineFeed __P((void)); 124static void InsertChar __P((int)); 125static void DeleteChar __P((int)); 126static void DeleteLine __P((int)); 127static void InsertLine __P((int)); 128static void Scroll __P((char *, int, int, char *)); 129static void ForwardTab __P((void)); 130static void BackwardTab __P((void)); 131static void ClearScreen __P((void)); 132static void ClearFromBOS __P((void)); 133static void ClearToEOS __P((void)); 134static void ClearLineRegion __P((int, int)); 135static void CursorRight __P((int)); 136static void CursorUp __P((int)); 137static void CursorDown __P((int)); 138static void CursorLeft __P((int)); 139static void ASetMode __P((int)); 140static void SelectRendition __P((void)); 141static void RestorePosRendition __P((void)); 142static void FillWithEs __P((void)); 143static void FindAKA __P((void)); 144static void Report __P((char *, int, int)); 145static void ScrollRegion __P((int)); 146#ifdef COPY_PASTE 147static void WAddLineToHist __P((struct win *, struct mline *)); 148#endif 149static void WLogString __P((struct win *, char *, int)); 150static void WReverseVideo __P((struct win *, int)); 151static int WindowChangedCheck __P((char *, int, int *)); 152static void MFixLine __P((struct win *, int, struct mchar *)); 153static void MScrollH __P((struct win *, int, int, int, int, int)); 154static void MScrollV __P((struct win *, int, int, int, int)); 155static void MClearArea __P((struct win *, int, int, int, int, int)); 156static void MInsChar __P((struct win *, struct mchar *, int, int)); 157static void MPutChar __P((struct win *, struct mchar *, int, int)); 158static void MPutStr __P((struct win *, char *, int, struct mchar *, int, int)); 159static void MWrapChar __P((struct win *, struct mchar *, int, int, int, int)); 160#ifdef COLOR 161static void MBceLine __P((struct win *, int, int, int, int)); 162#endif 163 164#ifdef COLOR 165# define CURR_BCE (curr->w_bce ? rend_getbg(&curr->w_rend) : 0) 166#else 167# define CURR_BCE 0 168#endif 169 170void 171ResetAnsiState(p) 172struct win *p; 173{ 174 p->w_state = LIT; 175 p->w_StringType = NONE; 176} 177 178void 179ResetWindow(p) 180register struct win *p; 181{ 182 register int i; 183 184 p->w_wrap = nwin_default.wrap; 185 p->w_origin = 0; 186 p->w_insert = 0; 187 p->w_revvid = 0; 188 p->w_mouse = 0; 189 p->w_curinv = 0; 190 p->w_curvvis = 0; 191 p->w_autolf = 0; 192 p->w_keypad = 0; 193 p->w_cursorkeys = 0; 194 p->w_top = 0; 195 p->w_bot = p->w_height - 1; 196 p->w_saved = 0; 197 p->w_x = p->w_y = 0; 198 p->w_state = LIT; 199 p->w_StringType = NONE; 200 bzero(p->w_tabs, p->w_width); 201 for (i = 8; i < p->w_width; i += 8) 202 p->w_tabs[i] = 1; 203 p->w_rend = mchar_null; 204#ifdef FONT 205 ResetCharsets(p); 206#endif 207#ifdef COLOR 208 p->w_bce = nwin_default.bce; 209#endif 210} 211 212/* adds max 22 bytes */ 213int 214GetAnsiStatus(w, buf) 215struct win *w; 216char *buf; 217{ 218 char *p = buf; 219 220 if (w->w_state == LIT) 221 return 0; 222 223 strcpy(p, state_t_string[w->w_state]); 224 p += strlen(p); 225 if (w->w_intermediate) 226 { 227 *p++ = '-'; 228 if (w->w_intermediate > 0xff) 229 p += AddXChar(p, w->w_intermediate >> 8); 230 p += AddXChar(p, w->w_intermediate & 0xff); 231 *p = 0; 232 } 233 if (w->w_state == ASTR || w->w_state == STRESC) 234 sprintf(p, "-%s", string_t_string[w->w_StringType]); 235 p += strlen(p); 236 return p - buf; 237} 238 239 240#ifdef FONT 241 242void 243ResetCharsets(p) 244struct win *p; 245{ 246 p->w_gr = nwin_default.gr; 247 p->w_c1 = nwin_default.c1; 248 SetCharsets(p, "BBBB02"); 249 if (nwin_default.charset) 250 SetCharsets(p, nwin_default.charset); 251#ifdef ENCODINGS 252 ResetEncoding(p); 253#endif 254} 255 256void 257SetCharsets(p, s) 258struct win *p; 259char *s; 260{ 261 int i; 262 263 for (i = 0; i < 4 && *s; i++, s++) 264 if (*s != '.') 265 p->w_charsets[i] = ((*s == 'B') ? ASCII : *s); 266 if (*s && *s++ != '.') 267 p->w_Charset = s[-1] - '0'; 268 if (*s && *s != '.') 269 p->w_CharsetR = *s - '0'; 270 p->w_ss = 0; 271 p->w_FontL = p->w_charsets[p->w_Charset]; 272 p->w_FontR = p->w_charsets[p->w_CharsetR]; 273} 274#endif /* FONT */ 275 276/*****************************************************************/ 277 278 279/* 280 * Here comes the vt100 emulator 281 * - writes logfiles, 282 * - sets timestamp and flags activity in window. 283 * - record program output in window scrollback 284 * - translate program output for the display and put it into the obuf. 285 * 286 */ 287void 288WriteString(wp, buf, len) 289struct win *wp; 290register char *buf; 291register int len; 292{ 293 register int c; 294#ifdef FONT 295 register int font; 296#endif 297 struct canvas *cv; 298 299 if (!len) 300 return; 301 if (wp->w_log) 302 WLogString(wp, buf, len); 303 304 /* set global variables (yuck!) */ 305 curr = wp; 306 cols = curr->w_width; 307 rows = curr->w_height; 308 309 if (curr->w_silence) 310 SetTimeout(&curr->w_silenceev, curr->w_silencewait * 1000); 311 312 if (curr->w_monitor == MON_ON) 313 { 314 debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell); 315 curr->w_monitor = MON_FOUND; 316 } 317 318 do 319 { 320 c = (unsigned char)*buf++; 321#ifdef FONT 322# ifdef DW_CHARS 323 if (!curr->w_mbcs) 324# endif 325 curr->w_rend.font = curr->w_FontL; /* Default: GL */ 326#endif 327 328 /* The next part is only for speedup */ 329 if (curr->w_state == LIT && 330#ifdef UTF8 331 curr->w_encoding != UTF8 && 332#endif 333#ifdef DW_CHARS 334 !is_dw_font(curr->w_rend.font) && 335# ifdef ENCODINGS 336 curr->w_rend.font != KANA && !curr->w_mbcs && 337# endif 338#endif 339#ifdef FONT 340 curr->w_rend.font != '<' && 341#endif 342 c >= ' ' && c != 0x7f && 343 ((c & 0x80) == 0 || ((c >= 0xa0 || !curr->w_c1) && !curr->w_gr)) && !curr->w_ss && 344 !curr->w_insert && curr->w_x < cols - 1) 345 { 346 register int currx = curr->w_x; 347 char *imp = buf - 1; 348 349 while (currx < cols - 1) 350 { 351 currx++; 352 if (--len == 0) 353 break; 354 c = (unsigned char)*buf++; 355 if (c < ' ' || c == 0x7f || ((c & 0x80) && ((c < 0xa0 && curr->w_c1) || curr->w_gr))) 356 break; 357 } 358 currx -= curr->w_x; 359 if (currx > 0) 360 { 361 MPutStr(curr, imp, currx, &curr->w_rend, curr->w_x, curr->w_y); 362 LPutStr(&curr->w_layer, imp, currx, &curr->w_rend, curr->w_x, curr->w_y); 363 curr->w_x += currx; 364 } 365 if (len == 0) 366 break; 367 } 368 /* end of speedup code */ 369 370#ifdef UTF8 371 if (curr->w_encoding == UTF8) 372 { 373 c = FromUtf8(c, &curr->w_decodestate); 374 if (c == -1) 375 continue; 376 if (c == -2) 377 { 378 c = UCS_REPL; 379 /* try char again */ 380 buf--; 381 len++; 382 } 383 if (c > 0xff) 384 debug1("read UNICODE %04x\n", c); 385 } 386#endif 387 388 tryagain: 389 switch (curr->w_state) 390 { 391 case PRIN: 392 switch (c) 393 { 394 case '\033': 395 curr->w_state = PRINESC; 396 break; 397 default: 398 PrintChar(c); 399 } 400 break; 401 case PRINESC: 402 switch (c) 403 { 404 case '[': 405 curr->w_state = PRINCSI; 406 break; 407 default: 408 PrintChar('\033'); 409 PrintChar(c); 410 curr->w_state = PRIN; 411 } 412 break; 413 case PRINCSI: 414 switch (c) 415 { 416 case '4': 417 curr->w_state = PRIN4; 418 break; 419 default: 420 PrintChar('\033'); 421 PrintChar('['); 422 PrintChar(c); 423 curr->w_state = PRIN; 424 } 425 break; 426 case PRIN4: 427 switch (c) 428 { 429 case 'i': 430 curr->w_state = LIT; 431 PrintFlush(); 432 if (curr->w_pdisplay && curr->w_pdisplay->d_printfd >= 0) 433 { 434 close(curr->w_pdisplay->d_printfd); 435 curr->w_pdisplay->d_printfd = -1; 436 } 437 curr->w_pdisplay = 0; 438 break; 439 default: 440 PrintChar('\033'); 441 PrintChar('['); 442 PrintChar('4'); 443 PrintChar(c); 444 curr->w_state = PRIN; 445 } 446 break; 447 case ASTR: 448 if (c == 0) 449 break; 450 if (c == '\033') 451 { 452 curr->w_state = STRESC; 453 break; 454 } 455 /* special xterm hack: accept SetStatus sequence. Yucc! */ 456 /* allow ^E for title escapes */ 457 if (!(curr->w_StringType == OSC && c < ' ' && c != '\005')) 458 if (!curr->w_c1 || c != ('\\' ^ 0xc0)) 459 { 460 StringChar(c); 461 break; 462 } 463 c = '\\'; 464 /* FALLTHROUGH */ 465 case STRESC: 466 switch (c) 467 { 468 case '\\': 469 if (StringEnd() == 0 || len <= 1) 470 break; 471 /* check if somewhere a status is displayed */ 472 for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext) 473 { 474 display = cv->c_display; 475 if (D_status == STATUS_ON_WIN) 476 break; 477 } 478 if (cv) 479 { 480 if (len > IOSIZE + 1) 481 len = IOSIZE + 1; 482 curr->w_outlen = len - 1; 483 bcopy(buf, curr->w_outbuf, len - 1); 484 return; /* wait till status is gone */ 485 } 486 break; 487 case '\033': 488 StringChar('\033'); 489 break; 490 default: 491 curr->w_state = ASTR; 492 StringChar('\033'); 493 StringChar(c); 494 break; 495 } 496 break; 497 case ESC: 498 switch (c) 499 { 500 case '[': 501 curr->w_NumArgs = 0; 502 curr->w_intermediate = 0; 503 bzero((char *) curr->w_args, MAXARGS * sizeof(int)); 504 curr->w_state = CSI; 505 break; 506 case ']': 507 StringStart(OSC); 508 break; 509 case '_': 510 StringStart(APC); 511 break; 512 case 'P': 513 StringStart(DCS); 514 break; 515 case '^': 516 StringStart(PM); 517 break; 518 case '!': 519 StringStart(GM); 520 break; 521 case '"': 522 case 'k': 523 StringStart(AKA); 524 break; 525 default: 526 if (Special(c)) 527 { 528 curr->w_state = LIT; 529 break; 530 } 531 debug1("not special. c = %x\n", c); 532 if (c >= ' ' && c <= '/') 533 { 534 if (curr->w_intermediate) 535 { 536#ifdef DW_CHARS 537 if (curr->w_intermediate == '$') 538 c |= '$' << 8; 539 else 540#endif 541 c = -1; 542 } 543 curr->w_intermediate = c; 544 } 545 else if (c >= '0' && c <= '~') 546 { 547 DoESC(c, curr->w_intermediate); 548 curr->w_state = LIT; 549 } 550 else 551 { 552 curr->w_state = LIT; 553 goto tryagain; 554 } 555 } 556 break; 557 case CSI: 558 switch (c) 559 { 560 case '0': case '1': case '2': case '3': case '4': 561 case '5': case '6': case '7': case '8': case '9': 562 if (curr->w_NumArgs < MAXARGS) 563 { 564 if (curr->w_args[curr->w_NumArgs] < 100000000) 565 curr->w_args[curr->w_NumArgs] = 566 10 * curr->w_args[curr->w_NumArgs] + (c - '0'); 567 } 568 break; 569 case ';': 570 case ':': 571 if (curr->w_NumArgs < MAXARGS) 572 curr->w_NumArgs++; 573 break; 574 default: 575 if (Special(c)) 576 break; 577 if (c >= '@' && c <= '~') 578 { 579 if (curr->w_NumArgs < MAXARGS) 580 curr->w_NumArgs++; 581 DoCSI(c, curr->w_intermediate); 582 if (curr->w_state != PRIN) 583 curr->w_state = LIT; 584 } 585 else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?')) 586 curr->w_intermediate = curr->w_intermediate ? -1 : c; 587 else 588 { 589 curr->w_state = LIT; 590 goto tryagain; 591 } 592 } 593 break; 594 case LIT: 595 default: 596#ifdef DW_CHARS 597 if (curr->w_mbcs) 598 if (c <= ' ' || c == 0x7f || (c >= 0x80 && c < 0xa0 && curr->w_c1)) 599 curr->w_mbcs = 0; 600#endif 601 if (c < ' ') 602 { 603 if (c == '\033') 604 { 605 curr->w_intermediate = 0; 606 curr->w_state = ESC; 607 if (curr->w_autoaka < 0) 608 curr->w_autoaka = 0; 609 } 610 else 611 Special(c); 612 break; 613 } 614 if (c >= 0x80 && c < 0xa0 && curr->w_c1) 615#ifdef FONT 616 if ((curr->w_FontR & 0xf0) != 0x20 617# ifdef UTF8 618 || curr->w_encoding == UTF8 619# endif 620 ) 621#endif 622 { 623 switch (c) 624 { 625 case 0xc0 ^ 'D': 626 case 0xc0 ^ 'E': 627 case 0xc0 ^ 'H': 628 case 0xc0 ^ 'M': 629 case 0xc0 ^ 'N': /* SS2 */ 630 case 0xc0 ^ 'O': /* SS3 */ 631 DoESC(c ^ 0xc0, 0); 632 break; 633 case 0xc0 ^ '[': 634 if (curr->w_autoaka < 0) 635 curr->w_autoaka = 0; 636 curr->w_NumArgs = 0; 637 curr->w_intermediate = 0; 638 bzero((char *) curr->w_args, MAXARGS * sizeof(int)); 639 curr->w_state = CSI; 640 break; 641 case 0xc0 ^ 'P': 642 StringStart(DCS); 643 break; 644 default: 645 break; 646 } 647 break; 648 } 649 650#ifdef FONT 651# ifdef DW_CHARS 652 if (!curr->w_mbcs) 653 { 654# endif 655 if (c < 0x80 || curr->w_gr == 0) 656 curr->w_rend.font = curr->w_FontL; 657# ifdef ENCODINGS 658 else if (curr->w_gr == 2 && !curr->w_ss) 659 curr->w_rend.font = curr->w_FontE; 660# endif 661 else 662 curr->w_rend.font = curr->w_FontR; 663# ifdef DW_CHARS 664 } 665# endif 666# ifdef UTF8 667 if (curr->w_encoding == UTF8) 668 { 669 if (curr->w_rend.font == '0') 670 { 671 struct mchar mc, *mcp; 672 673 debug1("SPECIAL %x\n", c); 674 mc.image = c; 675 mc.mbcs = 0; 676 mc.font = '0'; 677 mcp = recode_mchar(&mc, 0, UTF8); 678 debug2("%02x %02x\n", mcp->image, mcp->font); 679 c = mcp->image | mcp->font << 8; 680 } 681 curr->w_rend.font = 0; 682 } 683# ifdef DW_CHARS 684 if (curr->w_encoding == UTF8 && c >= 0x1100 && utf8_isdouble(c)) 685 curr->w_mbcs = 0xff; 686# endif 687 if (curr->w_encoding == UTF8 && c >= 0x0300 && utf8_iscomb(c)) 688 { 689 int ox, oy; 690 struct mchar omc; 691 692 ox = curr->w_x - 1; 693 oy = curr->w_y; 694 if (ox < 0) 695 { 696 ox = curr->w_width - 1; 697 oy--; 698 } 699 if (oy < 0) 700 oy = 0; 701 copy_mline2mchar(&omc, &curr->w_mlines[oy], ox); 702 if (omc.image == 0xff && omc.font == 0xff) 703 { 704 ox--; 705 if (ox >= 0) 706 { 707 copy_mline2mchar(&omc, &curr->w_mlines[oy], ox); 708 omc.mbcs = 0xff; 709 } 710 } 711 if (ox >= 0) 712 { 713 utf8_handle_comb(c, &omc); 714 MFixLine(curr, oy, &omc); 715 copy_mchar2mline(&omc, &curr->w_mlines[oy], ox); 716 LPutChar(&curr->w_layer, &omc, ox, oy); 717 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 718 } 719 break; 720 } 721 font = curr->w_rend.font; 722# endif 723# ifdef DW_CHARS 724# ifdef ENCODINGS 725 if (font == KANA && curr->w_encoding == SJIS && curr->w_mbcs == 0) 726 { 727 /* Lets see if it is the first byte of a kanji */ 728 debug1("%x may be first of SJIS\n", c); 729 if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef)) 730 { 731 debug("YES!\n"); 732 curr->w_mbcs = c; 733 break; 734 } 735 } 736# endif 737 if (font == 031 && c == 0x80 && !curr->w_mbcs) 738 font = curr->w_rend.font = 0; 739 if (is_dw_font(font) && c == ' ') 740 font = curr->w_rend.font = 0; 741 if (is_dw_font(font) || curr->w_mbcs) 742 { 743 int t = c; 744 if (curr->w_mbcs == 0) 745 { 746 curr->w_mbcs = c; 747 break; 748 } 749 if (curr->w_x == cols - 1) 750 { 751 curr->w_x += curr->w_wrap ? 1 : -1; 752 debug1("Patched w_x to %d\n", curr->w_x); 753 } 754# ifdef UTF8 755 if (curr->w_encoding != UTF8) 756# endif 757 { 758 c = curr->w_mbcs; 759# ifdef ENCODINGS 760 if (font == KANA && curr->w_encoding == SJIS) 761 { 762 debug2("SJIS !! %x %x\n", c, t); 763 /* 764 * SJIS -> EUC mapping: 765 * First byte: 766 * 81,82...9f -> 21,23...5d 767 * e0,e1...ef -> 5f,61...7d 768 * Second byte: 769 * 40-7e -> 21-5f 770 * 80-9e -> 60-7e 771 * 9f-fc -> 21-7e (increment first byte!) 772 */ 773 if (0x40 <= t && t <= 0xfc && t != 0x7f) 774 { 775 if (c <= 0x9f) c = (c - 0x81) * 2 + 0x21; 776 else c = (c - 0xc1) * 2 + 0x21; 777 if (t <= 0x7e) t -= 0x1f; 778 else if (t <= 0x9e) t -= 0x20; 779 else t -= 0x7e, c++; 780 curr->w_rend.font = KANJI; 781 } 782 else 783 { 784 /* Incomplete shift-jis - skip first byte */ 785 c = t; 786 t = 0; 787 } 788 debug2("SJIS after %x %x\n", c, t); 789 } 790# endif 791 if (t && curr->w_gr && font != 030 && font != 031) 792 { 793 t &= 0x7f; 794 if (t < ' ') 795 goto tryagain; 796 } 797 if (t == '\177') 798 break; 799 curr->w_mbcs = t; 800 } 801 } 802# endif /* DW_CHARS */ 803 if (font == '<' && c >= ' ') 804 { 805 font = curr->w_rend.font = 0; 806 c |= 0x80; 807 } 808# ifdef UTF8 809 else if (curr->w_gr && curr->w_encoding != UTF8) 810# else 811 else if (curr->w_gr) 812# endif 813 { 814#ifdef ENCODINGS 815 if (c == 0x80 && font == 0 && curr->w_encoding == GBK) 816 c = 0xa4; 817 else 818 c &= 0x7f; 819 if (c < ' ' && font != 031) 820 goto tryagain; 821#else 822 c &= 0x7f; 823 if (c < ' ') /* this is ugly but kanji support */ 824 goto tryagain; /* prevents nicer programming */ 825#endif 826 } 827#endif /* FONT */ 828 if (c == '\177') 829 break; 830 curr->w_rend.image = c; 831#ifdef UTF8 832 if (curr->w_encoding == UTF8) 833 curr->w_rend.font = c >> 8; 834#endif 835#ifdef DW_CHARS 836 curr->w_rend.mbcs = curr->w_mbcs; 837#endif 838 if (curr->w_x < cols - 1) 839 { 840 if (curr->w_insert) 841 { 842 save_mline(&curr->w_mlines[curr->w_y], cols); 843 MInsChar(curr, &curr->w_rend, curr->w_x, curr->w_y); 844 LInsChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y, &mline_old); 845 curr->w_x++; 846 } 847 else 848 { 849 MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y); 850 LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y); 851 curr->w_x++; 852 } 853 } 854 else if (curr->w_x == cols - 1) 855 { 856 MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y); 857 LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y); 858 if (curr->w_wrap) 859 curr->w_x++; 860 } 861 else 862 { 863 MWrapChar(curr, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert); 864 LWrapChar(&curr->w_layer, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert); 865 if (curr->w_y != curr->w_bot && curr->w_y != curr->w_height - 1) 866 curr->w_y++; 867 curr->w_x = 1; 868 } 869#ifdef FONT 870# ifdef DW_CHARS 871 if (curr->w_mbcs) 872 { 873 curr->w_rend.mbcs = curr->w_mbcs = 0; 874 curr->w_x++; 875 } 876# endif 877 if (curr->w_ss) 878 { 879 curr->w_FontL = curr->w_charsets[curr->w_Charset]; 880 curr->w_FontR = curr->w_charsets[curr->w_CharsetR]; 881 curr->w_rend.font = curr->w_FontL; 882 LSetRendition(&curr->w_layer, &curr->w_rend); 883 curr->w_ss = 0; 884 } 885#endif /* FONT */ 886 break; 887 } 888 } 889 while (--len); 890 if (!printcmd && curr->w_state == PRIN) 891 PrintFlush(); 892} 893 894static void 895WLogString(p, buf, len) 896struct win *p; 897char *buf; 898int len; 899{ 900 if (!p->w_log) 901 return; 902 if (logtstamp_on && p->w_logsilence >= logtstamp_after * 2) 903 { 904 char *t = MakeWinMsg(logtstamp_string, p, '%'); 905 logfwrite(p->w_log, t, strlen(t)); /* long time no write */ 906 } 907 p->w_logsilence = 0; 908 if (logfwrite(p->w_log, buf, len) < 1) 909 { 910 WMsg(p, errno, "Error writing logfile"); 911 logfclose(p->w_log); 912 p->w_log = 0; 913 } 914 if (!log_flush) 915 logfflush(p->w_log); 916} 917 918static int 919Special(c) 920register int c; 921{ 922 switch (c) 923 { 924 case '\b': 925 BackSpace(); 926 return 1; 927 case '\r': 928 Return(); 929 return 1; 930 case '\n': 931 if (curr->w_autoaka) 932 FindAKA(); 933 LineFeed(0); 934 return 1; 935 case '\007': 936 WBell(curr, visual_bell); 937 return 1; 938 case '\t': 939 ForwardTab(); 940 return 1; 941#ifdef FONT 942 case '\017': /* SI */ 943 MapCharset(G0); 944 return 1; 945 case '\016': /* SO */ 946 MapCharset(G1); 947 return 1; 948#endif 949 } 950 return 0; 951} 952 953static void 954DoESC(c, intermediate) 955int c, intermediate; 956{ 957 debug2("DoESC: %x - inter = %x\n", c, intermediate); 958 switch (intermediate) 959 { 960 case 0: 961 switch (c) 962 { 963 case 'E': 964 LineFeed(1); 965 break; 966 case 'D': 967 LineFeed(0); 968 break; 969 case 'M': 970 ReverseLineFeed(); 971 break; 972 case 'H': 973 curr->w_tabs[curr->w_x] = 1; 974 break; 975 case 'Z': /* jph: Identify as VT100 */ 976 Report("\033[?%d;%dc", 1, 2); 977 break; 978 case '7': 979 SaveCursor(); 980 break; 981 case '8': 982 RestoreCursor(); 983 break; 984 case 'c': 985 ClearScreen(); 986 ResetWindow(curr); 987 LKeypadMode(&curr->w_layer, 0); 988 LCursorkeysMode(&curr->w_layer, 0); 989#ifndef TIOCPKT 990 WNewAutoFlow(curr, 1); 991#endif 992 /* XXX 993 SetRendition(&mchar_null); 994 InsertMode(0); 995 ChangeScrollRegion(0, rows - 1); 996 */ 997 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 998 break; 999 case '=': 1000 LKeypadMode(&curr->w_layer, curr->w_keypad = 1); 1001#ifndef TIOCPKT 1002 WNewAutoFlow(curr, 0); 1003#endif /* !TIOCPKT */ 1004 break; 1005 case '>': 1006 LKeypadMode(&curr->w_layer, curr->w_keypad = 0); 1007#ifndef TIOCPKT 1008 WNewAutoFlow(curr, 1); 1009#endif /* !TIOCPKT */ 1010 break; 1011#ifdef FONT 1012 case 'n': /* LS2 */ 1013 MapCharset(G2); 1014 break; 1015 case 'o': /* LS3 */ 1016 MapCharset(G3); 1017 break; 1018 case '~': 1019 MapCharsetR(G1); /* LS1R */ 1020 break; 1021 /* { */ 1022 case '}': 1023 MapCharsetR(G2); /* LS2R */ 1024 break; 1025 case '|': 1026 MapCharsetR(G3); /* LS3R */ 1027 break; 1028 case 'N': /* SS2 */ 1029 if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2] 1030 || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G2]) 1031 curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G2]; 1032 else 1033 curr->w_ss = 0; 1034 break; 1035 case 'O': /* SS3 */ 1036 if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3] 1037 || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G3]) 1038 curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G3]; 1039 else 1040 curr->w_ss = 0; 1041 break; 1042#endif /* FONT */ 1043 case 'g': /* VBELL, private screen sequence */ 1044 WBell(curr, 1); 1045 break; 1046 } 1047 break; 1048 case '#': 1049 switch (c) 1050 { 1051 case '8': 1052 FillWithEs(); 1053 break; 1054 } 1055 break; 1056#ifdef FONT 1057 case '(': 1058 DesignateCharset(c, G0); 1059 break; 1060 case ')': 1061 DesignateCharset(c, G1); 1062 break; 1063 case '*': 1064 DesignateCharset(c, G2); 1065 break; 1066 case '+': 1067 DesignateCharset(c, G3); 1068 break; 1069# ifdef DW_CHARS 1070/* 1071 * ESC $ ( Fn: invoke multi-byte charset, Fn, to G0 1072 * ESC $ Fn: same as above. (old sequence) 1073 * ESC $ ) Fn: invoke multi-byte charset, Fn, to G1 1074 * ESC $ * Fn: invoke multi-byte charset, Fn, to G2 1075 * ESC $ + Fn: invoke multi-byte charset, Fn, to G3 1076 */ 1077 case '$': 1078 case '$'<<8 | '(': 1079 DesignateCharset(c & 037, G0); 1080 break; 1081 case '$'<<8 | ')': 1082 DesignateCharset(c & 037, G1); 1083 break; 1084 case '$'<<8 | '*': 1085 DesignateCharset(c & 037, G2); 1086 break; 1087 case '$'<<8 | '+': 1088 DesignateCharset(c & 037, G3); 1089 break; 1090# endif 1091#endif /* FONT */ 1092 } 1093} 1094 1095static void 1096DoCSI(c, intermediate) 1097int c, intermediate; 1098{ 1099 register int i, a1 = curr->w_args[0], a2 = curr->w_args[1]; 1100 1101 if (curr->w_NumArgs > MAXARGS) 1102 curr->w_NumArgs = MAXARGS; 1103 switch (intermediate) 1104 { 1105 case 0: 1106 switch (c) 1107 { 1108 case 'H': 1109 case 'f': 1110 if (a1 < 1) 1111 a1 = 1; 1112 if (curr->w_origin) 1113 a1 += curr->w_top; 1114 if (a1 > rows) 1115 a1 = rows; 1116 if (a2 < 1) 1117 a2 = 1; 1118 if (a2 > cols) 1119 a2 = cols; 1120 LGotoPos(&curr->w_layer, --a2, --a1); 1121 curr->w_x = a2; 1122 curr->w_y = a1; 1123 if (curr->w_autoaka) 1124 curr->w_autoaka = a1 + 1; 1125 break; 1126 case 'J': 1127 if (a1 < 0 || a1 > 2) 1128 a1 = 0; 1129 switch (a1) 1130 { 1131 case 0: 1132 ClearToEOS(); 1133 break; 1134 case 1: 1135 ClearFromBOS(); 1136 break; 1137 case 2: 1138 ClearScreen(); 1139 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1140 break; 1141 } 1142 break; 1143 case 'K': 1144 if (a1 < 0 || a1 > 2) 1145 a1 %= 3; 1146 switch (a1) 1147 { 1148 case 0: 1149 ClearLineRegion(curr->w_x, cols - 1); 1150 break; 1151 case 1: 1152 ClearLineRegion(0, curr->w_x); 1153 break; 1154 case 2: 1155 ClearLineRegion(0, cols - 1); 1156 break; 1157 } 1158 break; 1159 case 'X': 1160 a1 = curr->w_x + (a1 ? a1 - 1 : 0); 1161 ClearLineRegion(curr->w_x, a1 < cols ? a1 : cols - 1); 1162 break; 1163 case 'A': 1164 CursorUp(a1 ? a1 : 1); 1165 break; 1166 case 'B': 1167 CursorDown(a1 ? a1 : 1); 1168 break; 1169 case 'C': 1170 CursorRight(a1 ? a1 : 1); 1171 break; 1172 case 'D': 1173 CursorLeft(a1 ? a1 : 1); 1174 break; 1175 case 'E': 1176 curr->w_x = 0; 1177 CursorDown(a1 ? a1 : 1); /* positions cursor */ 1178 break; 1179 case 'F': 1180 curr->w_x = 0; 1181 CursorUp(a1 ? a1 : 1); /* positions cursor */ 1182 break; 1183 case 'G': 1184 case '`': /* HPA */ 1185 curr->w_x = a1 ? a1 - 1 : 0; 1186 if (curr->w_x >= cols) 1187 curr->w_x = cols - 1; 1188 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1189 break; 1190 case 'd': /* VPA */ 1191 curr->w_y = a1 ? a1 - 1 : 0; 1192 if (curr->w_y >= rows) 1193 curr->w_y = rows - 1; 1194 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1195 break; 1196 case 'm': 1197 SelectRendition(); 1198 break; 1199 case 'g': 1200 if (a1 == 0) 1201 curr->w_tabs[curr->w_x] = 0; 1202 else if (a1 == 3) 1203 bzero(curr->w_tabs, cols); 1204 break; 1205 case 'r': 1206 if (!a1) 1207 a1 = 1; 1208 if (!a2) 1209 a2 = rows; 1210 if (a1 < 1 || a2 > rows || a1 >= a2) 1211 break; 1212 curr->w_top = a1 - 1; 1213 curr->w_bot = a2 - 1; 1214 /* ChangeScrollRegion(curr->w_top, curr->w_bot); */ 1215 if (curr->w_origin) 1216 { 1217 curr->w_y = curr->w_top; 1218 curr->w_x = 0; 1219 } 1220 else 1221 curr->w_y = curr->w_x = 0; 1222 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1223 break; 1224 case 's': 1225 SaveCursor(); 1226 break; 1227 case 't': 1228 if (a1 != 8) 1229 break; 1230 a1 = curr->w_args[2]; 1231 if (a1 < 1) 1232 a1 = curr->w_width; 1233 if (a2 < 1) 1234 a2 = curr->w_height; 1235 if (a1 > 10000 || a2 > 10000) 1236 break; 1237 WChangeSize(curr, a1, a2); 1238 cols = curr->w_width; 1239 rows = curr->w_height; 1240 break; 1241 case 'u': 1242 RestoreCursor(); 1243 break; 1244 case 'I': 1245 if (!a1) 1246 a1 = 1; 1247 while (a1--) 1248 ForwardTab(); 1249 break; 1250 case 'Z': 1251 if (!a1) 1252 a1 = 1; 1253 while (a1--) 1254 BackwardTab(); 1255 break; 1256 case 'L': 1257 InsertLine(a1 ? a1 : 1); 1258 break; 1259 case 'M': 1260 DeleteLine(a1 ? a1 : 1); 1261 break; 1262 case 'P': 1263 DeleteChar(a1 ? a1 : 1); 1264 break; 1265 case '@': 1266 InsertChar(a1 ? a1 : 1); 1267 break; 1268 case 'h': 1269 ASetMode(1); 1270 break; 1271 case 'l': 1272 ASetMode(0); 1273 break; 1274 case 'i': /* MC Media Control */ 1275 if (a1 == 5) 1276 PrintStart(); 1277 break; 1278 case 'n': 1279 if (a1 == 5) /* Report terminal status */ 1280 Report("\033[0n", 0, 0); 1281 else if (a1 == 6) /* Report cursor position */ 1282 Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1); 1283 break; 1284 case 'c': /* Identify as VT100 */ 1285 if (a1 == 0) 1286 Report("\033[?%d;%dc", 1, 2); 1287 break; 1288 case 'x': /* decreqtparm */ 1289 if (a1 == 0 || a1 == 1) 1290 Report("\033[%d;1;1;112;112;1;0x", a1 + 2, 0); 1291 break; 1292 case 'p': /* obscure code from a 97801 term */ 1293 if (a1 == 6 || a1 == 7) 1294 { 1295 curr->w_curinv = 7 - a1; 1296 LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); 1297 } 1298 break; 1299 case 'S': /* code from a 97801 term / DEC vt400 */ 1300 ScrollRegion(a1 ? a1 : 1); 1301 break; 1302 case 'T': /* code from a 97801 term / DEC vt400 */ 1303 case '^': /* SD as per ISO 6429 */ 1304 ScrollRegion(a1 ? -a1 : -1); 1305 break; 1306 } 1307 break; 1308 case '?': 1309 for (a2 = 0; a2 < curr->w_NumArgs; a2++) 1310 { 1311 a1 = curr->w_args[a2]; 1312 debug2("\\E[?%d%c\n",a1,c); 1313 if (c != 'h' && c != 'l') 1314 break; 1315 i = (c == 'h'); 1316 switch (a1) 1317 { 1318 case 1: /* CKM: cursor key mode */ 1319 LCursorkeysMode(&curr->w_layer, curr->w_cursorkeys = i); 1320#ifndef TIOCPKT 1321 WNewAutoFlow(curr, !i); 1322#endif /* !TIOCPKT */ 1323 break; 1324 case 2: /* ANM: ansi/vt52 mode */ 1325 if (i) 1326 { 1327#ifdef FONT 1328# ifdef ENCODINGS 1329 if (curr->w_encoding) 1330 break; 1331# endif 1332 curr->w_charsets[0] = curr->w_charsets[1] = 1333 curr->w_charsets[2] = curr->w_charsets[2] = 1334 curr->w_FontL = curr->w_FontR = ASCII; 1335 curr->w_Charset = 0; 1336 curr->w_CharsetR = 2; 1337 curr->w_ss = 0; 1338#endif 1339 } 1340 break; 1341 case 3: /* COLM: column mode */ 1342 i = (i ? Z0width : Z1width); 1343 WChangeSize(curr, i, curr->w_height); 1344 cols = curr->w_width; 1345 rows = curr->w_height; 1346 break; 1347 /* case 4: SCLM: scrolling mode */ 1348 case 5: /* SCNM: screen mode */ 1349 if (i != curr->w_revvid) 1350 WReverseVideo(curr, i); 1351 curr->w_revvid = i; 1352 break; 1353 case 6: /* OM: origin mode */ 1354 if ((curr->w_origin = i) != 0) 1355 { 1356 curr->w_y = curr->w_top; 1357 curr->w_x = 0; 1358 } 1359 else 1360 curr->w_y = curr->w_x = 0; 1361 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1362 break; 1363 case 7: /* AWM: auto wrap mode */ 1364 curr->w_wrap = i; 1365 break; 1366 /* case 8: ARM: auto repeat mode */ 1367 /* case 9: INLM: interlace mode */ 1368 case 9: /* X10 mouse tracking */ 1369 curr->w_mouse = i ? 9 : 0; 1370 LMouseMode(&curr->w_layer, curr->w_mouse); 1371 break; 1372 /* case 10: EDM: edit mode */ 1373 /* case 11: LTM: line transmit mode */ 1374 /* case 13: SCFDM: space compression / field delimiting */ 1375 /* case 14: TEM: transmit execution mode */ 1376 /* case 16: EKEM: edit key execution mode */ 1377 /* case 18: PFF: Printer term form feed */ 1378 /* case 19: PEX: Printer extend screen / scroll. reg */ 1379 case 25: /* TCEM: text cursor enable mode */ 1380 curr->w_curinv = !i; 1381 LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); 1382 break; 1383 /* case 34: RLM: Right to left mode */ 1384 /* case 35: HEBM: hebrew keyboard map */ 1385 /* case 36: HEM: hebrew encoding */ 1386 /* case 38: TeK Mode */ 1387 /* case 40: 132 col enable */ 1388 /* case 42: NRCM: 7bit NRC character mode */ 1389 /* case 44: margin bell enable */ 1390 case 47: /* xterm-like alternate screen */ 1391 case 1047: /* xterm-like alternate screen */ 1392 case 1049: /* xterm-like alternate screen */ 1393 if (use_altscreen) 1394 { 1395 if (i) 1396 EnterAltScreen(curr); 1397 else 1398 LeaveAltScreen(curr); 1399 if (a1 == 47 && !i) 1400 curr->w_saved = 0; 1401 LRefreshAll(&curr->w_layer, 0); 1402 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1403 } 1404 break; 1405 /* case 66: NKM: Numeric keypad appl mode */ 1406 /* case 68: KBUM: Keyboard usage mode (data process) */ 1407 case 1000: /* VT200 mouse tracking */ 1408 case 1001: /* VT200 highlight mouse */ 1409 case 1002: /* button event mouse*/ 1410 case 1003: /* any event mouse*/ 1411 curr->w_mouse = i ? a1 : 0; 1412 LMouseMode(&curr->w_layer, curr->w_mouse); 1413 break; 1414 } 1415 } 1416 break; 1417 case '>': 1418 switch (c) 1419 { 1420 case 'c': /* secondary DA */ 1421 if (a1 == 0) 1422 Report("\033[>%d;%d;0c", 83, nversion); /* 83 == 'S' */ 1423 break; 1424 } 1425 break; 1426 } 1427} 1428 1429 1430static void 1431StringStart(type) 1432enum string_t type; 1433{ 1434 curr->w_StringType = type; 1435 curr->w_stringp = curr->w_string; 1436 curr->w_state = ASTR; 1437} 1438 1439static void 1440StringChar(c) 1441int c; 1442{ 1443 if (curr->w_stringp >= curr->w_string + MAXSTR - 1) 1444 curr->w_state = LIT; 1445 else 1446 *(curr->w_stringp)++ = c; 1447} 1448 1449/* 1450 * Do string processing. Returns -1 if output should be suspended 1451 * until status is gone. 1452 */ 1453static int 1454StringEnd() 1455{ 1456 struct canvas *cv; 1457 char *p; 1458 int typ; 1459 1460 curr->w_state = LIT; 1461 *curr->w_stringp = '\0'; 1462 switch (curr->w_StringType) 1463 { 1464 case OSC: /* special xterm compatibility hack */ 1465 if (curr->w_string[0] == ';' || (p = index(curr->w_string, ';')) == 0) 1466 break; 1467 typ = atoi(curr->w_string); 1468 p++; 1469#ifdef MULTIUSER 1470 if (typ == 83) /* 83 = 'S' */ 1471 { 1472 /* special execute commands sequence */ 1473 char *args[MAXARGS]; 1474 int argl[MAXARGS]; 1475 struct acluser *windowuser; 1476 1477 windowuser = *FindUserPtr(":window:"); 1478 if (windowuser && Parse(p, sizeof(curr->w_string) - (p - curr->w_string), args, argl)) 1479 { 1480 for (display = displays; display; display = display->d_next) 1481 if (D_forecv->c_layer->l_bottom == &curr->w_layer) 1482 break; /* found it */ 1483 if (display == 0 && curr->w_layer.l_cvlist) 1484 display = curr->w_layer.l_cvlist->c_display; 1485 if (display == 0) 1486 display = displays; 1487 EffectiveAclUser = windowuser; 1488 fore = curr; 1489 flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer; 1490 DoCommand(args, argl); 1491 EffectiveAclUser = 0; 1492 fore = 0; 1493 flayer = 0; 1494 } 1495 break; 1496 } 1497#endif 1498#ifdef RXVT_OSC 1499 if (typ == 0 || typ == 1 || typ == 20 || typ == 39 || typ == 49) 1500 { 1501 int typ2; 1502 typ2 = typ / 10; 1503 if (--typ2 < 0) 1504 typ2 = 0; 1505 if (strcmp(curr->w_xtermosc[typ2], p)) 1506 { 1507 strncpy(curr->w_xtermosc[typ2], p, sizeof(curr->w_xtermosc[typ2]) - 1); 1508 curr->w_xtermosc[typ2][sizeof(curr->w_xtermosc[typ2]) - 1] = 0; 1509 1510 for (display = displays; display; display = display->d_next) 1511 { 1512 if (!D_CXT) 1513 continue; 1514 if (D_forecv->c_layer->l_bottom == &curr->w_layer) 1515 SetXtermOSC(typ2, curr->w_xtermosc[typ2]); 1516 if ((typ2 == 2 || typ2 == 3) && D_xtermosc[typ2]) 1517 Redisplay(0); 1518 } 1519 } 1520 } 1521 if (typ != 0 && typ != 2) 1522 break; 1523#else 1524 if (typ < 0 || typ > 2) 1525 break; 1526#endif 1527 1528 curr->w_stringp -= p - curr->w_string; 1529 if (curr->w_stringp > curr->w_string) 1530 bcopy(p, curr->w_string, curr->w_stringp - curr->w_string); 1531 *curr->w_stringp = '\0'; 1532 /* FALLTHROUGH */ 1533 case APC: 1534 if (curr->w_hstatus) 1535 { 1536 if (strcmp(curr->w_hstatus, curr->w_string) == 0) 1537 break; /* not changed */ 1538 free(curr->w_hstatus); 1539 curr->w_hstatus = 0; 1540 } 1541 if (curr->w_string != curr->w_stringp) 1542 curr->w_hstatus = SaveStr(curr->w_string); 1543 WindowChanged(curr, 'h'); 1544 break; 1545 case PM: 1546 case GM: 1547 for (display = displays; display; display = display->d_next) 1548 { 1549 for (cv = D_cvlist; cv; cv = cv->c_next) 1550 if (cv->c_layer->l_bottom == &curr->w_layer) 1551 break; 1552 if (cv || curr->w_StringType == GM) 1553 MakeStatus(curr->w_string); 1554 } 1555 return -1; 1556 case DCS: 1557 LAY_DISPLAYS(&curr->w_layer, AddStr(curr->w_string)); 1558 break; 1559 case AKA: 1560 if (curr->w_title == curr->w_akabuf && !*curr->w_string) 1561 break; 1562 ChangeAKA(curr, curr->w_string, strlen(curr->w_string)); 1563 if (!*curr->w_string) 1564 curr->w_autoaka = curr->w_y + 1; 1565 break; 1566 default: 1567 break; 1568 } 1569 return 0; 1570} 1571 1572static void 1573PrintStart() 1574{ 1575 curr->w_pdisplay = 0; 1576 1577 /* find us a nice display to print on, fore prefered */ 1578 display = curr->w_lastdisp; 1579 if (!(display && curr == D_fore && (printcmd || D_PO))) 1580 for (display = displays; display; display = display->d_next) 1581 if (curr == D_fore && (printcmd || D_PO)) 1582 break; 1583 if (!display) 1584 { 1585 struct canvas *cv; 1586 for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext) 1587 { 1588 display = cv->c_display; 1589 if (printcmd || D_PO) 1590 break; 1591 } 1592 if (!cv) 1593 { 1594 display = displays; 1595 if (!display || display->d_next || !(printcmd || D_PO)) 1596 return; 1597 } 1598 } 1599 curr->w_pdisplay = display; 1600 curr->w_stringp = curr->w_string; 1601 curr->w_state = PRIN; 1602 if (printcmd && curr->w_pdisplay->d_printfd < 0) 1603 curr->w_pdisplay->d_printfd = printpipe(curr, printcmd); 1604} 1605 1606static void 1607PrintChar(c) 1608int c; 1609{ 1610 if (curr->w_stringp >= curr->w_string + MAXSTR - 1) 1611 PrintFlush(); 1612 *(curr->w_stringp)++ = c; 1613} 1614 1615static void 1616PrintFlush() 1617{ 1618 display = curr->w_pdisplay; 1619 if (display && printcmd) 1620 { 1621 char *bp = curr->w_string; 1622 int len = curr->w_stringp - curr->w_string; 1623 int r; 1624 while (len && display->d_printfd >= 0) 1625 { 1626 r = write(display->d_printfd, bp, len); 1627 if (r <= 0) 1628 { 1629 WMsg(curr, errno, "printing aborted"); 1630 close(display->d_printfd); 1631 display->d_printfd = -1; 1632 break; 1633 } 1634 bp += r; 1635 len -= r; 1636 } 1637 } 1638 else if (display && curr->w_stringp > curr->w_string) 1639 { 1640 AddCStr(D_PO); 1641 AddStrn(curr->w_string, curr->w_stringp - curr->w_string); 1642 AddCStr(D_PF); 1643 Flush(); 1644 } 1645 curr->w_stringp = curr->w_string; 1646} 1647 1648 1649void 1650WNewAutoFlow(win, on) 1651struct win *win; 1652int on; 1653{ 1654 debug1("WNewAutoFlow: %d\n", on); 1655 if (win->w_flow & FLOW_AUTOFLAG) 1656 win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on; 1657 else 1658 win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on; 1659 LSetFlow(&win->w_layer, win->w_flow & FLOW_NOW); 1660} 1661 1662 1663#ifdef FONT 1664 1665static void 1666DesignateCharset(c, n) 1667int c, n; 1668{ 1669 curr->w_ss = 0; 1670# ifdef ENCODINGS 1671 if (c == ('@' & 037)) /* map JIS 6226 to 0208 */ 1672 c = KANJI; 1673# endif 1674 if (c == 'B') 1675 c = ASCII; 1676 if (curr->w_charsets[n] != c) 1677 { 1678 curr->w_charsets[n] = c; 1679 if (curr->w_Charset == n) 1680 { 1681 curr->w_FontL = c; 1682 curr->w_rend.font = curr->w_FontL; 1683 LSetRendition(&curr->w_layer, &curr->w_rend); 1684 } 1685 if (curr->w_CharsetR == n) 1686 curr->w_FontR = c; 1687 } 1688} 1689 1690static void 1691MapCharset(n) 1692int n; 1693{ 1694 curr->w_ss = 0; 1695 if (curr->w_Charset != n) 1696 { 1697 curr->w_Charset = n; 1698 curr->w_FontL = curr->w_charsets[n]; 1699 curr->w_rend.font = curr->w_FontL; 1700 LSetRendition(&curr->w_layer, &curr->w_rend); 1701 } 1702} 1703 1704static void 1705MapCharsetR(n) 1706int n; 1707{ 1708 curr->w_ss = 0; 1709 if (curr->w_CharsetR != n) 1710 { 1711 curr->w_CharsetR = n; 1712 curr->w_FontR = curr->w_charsets[n]; 1713 } 1714 curr->w_gr = 1; 1715} 1716 1717#endif /* FONT */ 1718 1719static void 1720SaveCursor() 1721{ 1722 curr->w_saved = 1; 1723 curr->w_Saved_x = curr->w_x; 1724 curr->w_Saved_y = curr->w_y; 1725 curr->w_SavedRend = curr->w_rend; 1726#ifdef FONT 1727 curr->w_SavedCharset = curr->w_Charset; 1728 curr->w_SavedCharsetR = curr->w_CharsetR; 1729 bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets, 1730 4 * sizeof(int)); 1731#endif 1732} 1733 1734static void 1735RestoreCursor() 1736{ 1737 if (!curr->w_saved) 1738 return; 1739 LGotoPos(&curr->w_layer, curr->w_Saved_x, curr->w_Saved_y); 1740 curr->w_x = curr->w_Saved_x; 1741 curr->w_y = curr->w_Saved_y; 1742 curr->w_rend = curr->w_SavedRend; 1743#ifdef FONT 1744 bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets, 1745 4 * sizeof(int)); 1746 curr->w_Charset = curr->w_SavedCharset; 1747 curr->w_CharsetR = curr->w_SavedCharsetR; 1748 curr->w_ss = 0; 1749 curr->w_FontL = curr->w_charsets[curr->w_Charset]; 1750 curr->w_FontR = curr->w_charsets[curr->w_CharsetR]; 1751#endif 1752 LSetRendition(&curr->w_layer, &curr->w_rend); 1753} 1754 1755static void 1756BackSpace() 1757{ 1758 if (curr->w_x > 0) 1759 { 1760 curr->w_x--; 1761 } 1762 else if (curr->w_wrap && curr->w_y > 0) 1763 { 1764 curr->w_x = cols - 1; 1765 curr->w_y--; 1766 } 1767 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1768} 1769 1770static void 1771Return() 1772{ 1773 if (curr->w_x == 0) 1774 return; 1775 curr->w_x = 0; 1776 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1777} 1778 1779static void 1780LineFeed(out_mode) 1781int out_mode; 1782{ 1783 /* out_mode: 0=lf, 1=cr+lf */ 1784 if (out_mode) 1785 curr->w_x = 0; 1786 if (curr->w_y != curr->w_bot) /* Don't scroll */ 1787 { 1788 if (curr->w_y < rows-1) 1789 curr->w_y++; 1790 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1791 return; 1792 } 1793 if (curr->w_autoaka > 1) 1794 curr->w_autoaka--; 1795 MScrollV(curr, 1, curr->w_top, curr->w_bot, CURR_BCE); 1796 LScrollV(&curr->w_layer, 1, curr->w_top, curr->w_bot, CURR_BCE); 1797 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1798} 1799 1800static void 1801ReverseLineFeed() 1802{ 1803 if (curr->w_y == curr->w_top) 1804 { 1805 MScrollV(curr, -1, curr->w_top, curr->w_bot, CURR_BCE); 1806 LScrollV(&curr->w_layer, -1, curr->w_top, curr->w_bot, CURR_BCE); 1807 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1808 } 1809 else if (curr->w_y > 0) 1810 CursorUp(1); 1811} 1812 1813static void 1814InsertChar(n) 1815int n; 1816{ 1817 register int y = curr->w_y, x = curr->w_x; 1818 1819 if (n <= 0) 1820 return; 1821 if (x == cols) 1822 x--; 1823 save_mline(&curr->w_mlines[y], cols); 1824 MScrollH(curr, -n, y, x, curr->w_width - 1, CURR_BCE); 1825 LScrollH(&curr->w_layer, -n, y, x, curr->w_width - 1, CURR_BCE, &mline_old); 1826 LGotoPos(&curr->w_layer, x, y); 1827} 1828 1829static void 1830DeleteChar(n) 1831int n; 1832{ 1833 register int y = curr->w_y, x = curr->w_x; 1834 1835 if (x == cols) 1836 x--; 1837 save_mline(&curr->w_mlines[y], cols); 1838 MScrollH(curr, n, y, x, curr->w_width - 1, CURR_BCE); 1839 LScrollH(&curr->w_layer, n, y, x, curr->w_width - 1, CURR_BCE, &mline_old); 1840 LGotoPos(&curr->w_layer, x, y); 1841} 1842 1843static void 1844DeleteLine(n) 1845int n; 1846{ 1847 if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot) 1848 return; 1849 if (n > curr->w_bot - curr->w_y + 1) 1850 n = curr->w_bot - curr->w_y + 1; 1851 MScrollV(curr, n, curr->w_y, curr->w_bot, CURR_BCE); 1852 LScrollV(&curr->w_layer, n, curr->w_y, curr->w_bot, CURR_BCE); 1853 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1854} 1855 1856static void 1857InsertLine(n) 1858int n; 1859{ 1860 if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot) 1861 return; 1862 if (n > curr->w_bot - curr->w_y + 1) 1863 n = curr->w_bot - curr->w_y + 1; 1864 MScrollV(curr, -n, curr->w_y, curr->w_bot, CURR_BCE); 1865 LScrollV(&curr->w_layer, -n, curr->w_y, curr->w_bot, CURR_BCE); 1866 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1867} 1868 1869static void 1870ScrollRegion(n) 1871int n; 1872{ 1873 MScrollV(curr, n, curr->w_top, curr->w_bot, CURR_BCE); 1874 LScrollV(&curr->w_layer, n, curr->w_top, curr->w_bot, CURR_BCE); 1875 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1876} 1877 1878 1879static void 1880ForwardTab() 1881{ 1882 register int x = curr->w_x; 1883 1884 if (x == cols) 1885 { 1886 LineFeed(1); 1887 x = 0; 1888 } 1889 if (curr->w_tabs[x] && x < cols - 1) 1890 x++; 1891 while (x < cols - 1 && !curr->w_tabs[x]) 1892 x++; 1893 curr->w_x = x; 1894 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1895} 1896 1897static void 1898BackwardTab() 1899{ 1900 register int x = curr->w_x; 1901 1902 if (curr->w_tabs[x] && x > 0) 1903 x--; 1904 while (x > 0 && !curr->w_tabs[x]) 1905 x--; 1906 curr->w_x = x; 1907 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1908} 1909 1910static void 1911ClearScreen() 1912{ 1913 LClearArea(&curr->w_layer, 0, 0, curr->w_width - 1, curr->w_height - 1, CURR_BCE, 1); 1914#ifdef COPY_PASTE 1915 MScrollV(curr, curr->w_height, 0, curr->w_height - 1, CURR_BCE); 1916#else 1917 MClearArea(curr, 0, 0, curr->w_width - 1, curr->w_height - 1, CURR_BCE); 1918#endif 1919} 1920 1921static void 1922ClearFromBOS() 1923{ 1924 register int y = curr->w_y, x = curr->w_x; 1925 1926 LClearArea(&curr->w_layer, 0, 0, x, y, CURR_BCE, 1); 1927 MClearArea(curr, 0, 0, x, y, CURR_BCE); 1928 RestorePosRendition(); 1929} 1930 1931static void 1932ClearToEOS() 1933{ 1934 register int y = curr->w_y, x = curr->w_x; 1935 1936 if (x == 0 && y == 0) 1937 { 1938 ClearScreen(); 1939 RestorePosRendition(); 1940 return; 1941 } 1942 LClearArea(&curr->w_layer, x, y, cols - 1, rows - 1, CURR_BCE, 1); 1943 MClearArea(curr, x, y, cols - 1, rows - 1, CURR_BCE); 1944 RestorePosRendition(); 1945} 1946 1947static void 1948ClearLineRegion(from, to) 1949int from, to; 1950{ 1951 register int y = curr->w_y; 1952 LClearArea(&curr->w_layer, from, y, to, y, CURR_BCE, 1); 1953 MClearArea(curr, from, y, to, y, CURR_BCE); 1954 RestorePosRendition(); 1955} 1956 1957static void 1958CursorRight(n) 1959register int n; 1960{ 1961 register int x = curr->w_x; 1962 1963 if (x == cols) 1964 { 1965 LineFeed(1); 1966 x = 0; 1967 } 1968 if ((curr->w_x += n) >= cols) 1969 curr->w_x = cols - 1; 1970 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1971} 1972 1973static void 1974CursorUp(n) 1975register int n; 1976{ 1977 if (curr->w_y < curr->w_top) /* if above scrolling rgn, */ 1978 { 1979 if ((curr->w_y -= n) < 0) /* ignore its limits */ 1980 curr->w_y = 0; 1981 } 1982 else 1983 if ((curr->w_y -= n) < curr->w_top) 1984 curr->w_y = curr->w_top; 1985 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 1986} 1987 1988static void 1989CursorDown(n) 1990register int n; 1991{ 1992 if (curr->w_y > curr->w_bot) /* if below scrolling rgn, */ 1993 { 1994 if ((curr->w_y += n) > rows - 1) /* ignore its limits */ 1995 curr->w_y = rows - 1; 1996 } 1997 else 1998 if ((curr->w_y += n) > curr->w_bot) 1999 curr->w_y = curr->w_bot; 2000 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 2001} 2002 2003static void 2004CursorLeft(n) 2005register int n; 2006{ 2007 if ((curr->w_x -= n) < 0) 2008 curr->w_x = 0; 2009 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 2010} 2011 2012static void 2013ASetMode(on) 2014int on; 2015{ 2016 register int i; 2017 2018 for (i = 0; i < curr->w_NumArgs; ++i) 2019 { 2020 switch (curr->w_args[i]) 2021 { 2022 /* case 2: KAM: Lock keyboard */ 2023 case 4: /* IRM: Insert mode */ 2024 curr->w_insert = on; 2025 LAY_DISPLAYS(&curr->w_layer, InsertMode(on)); 2026 break; 2027 /* case 12: SRM: Echo mode on */ 2028 case 20: /* LNM: Linefeed mode */ 2029 curr->w_autolf = on; 2030 break; 2031 case 34: 2032 curr->w_curvvis = !on; 2033 LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); 2034 break; 2035 default: 2036 break; 2037 } 2038 } 2039} 2040 2041static char rendlist[] = 2042{ 2043 ~((1 << NATTR) - 1), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0, 2044 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2045 0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV 2046}; 2047 2048static void 2049SelectRendition() 2050{ 2051#ifdef COLOR 2052 register int j, i = 0, a = curr->w_rend.attr, c = curr->w_rend.color; 2053# ifdef COLORS256 2054 int cx = curr->w_rend.colorx; 2055# endif 2056#else 2057 register int j, i = 0, a = curr->w_rend.attr; 2058#endif 2059 2060 do 2061 { 2062 j = curr->w_args[i]; 2063#ifdef COLOR 2064 if ((j == 38 || j == 48) && i + 2 < curr->w_NumArgs && curr->w_args[i + 1] == 5) 2065 { 2066 int jj; 2067 2068 i += 2; 2069 jj = curr->w_args[i]; 2070 if (jj < 0 || jj > 255) 2071 continue; 2072# ifdef COLORS256 2073 if (j == 38) 2074 { 2075 c = (c & 0xf0) | ((jj & 0x0f) ^ 9); 2076 a |= A_BFG; 2077 if (jj >= 8 && jj < 16) 2078 c |= 0x08; 2079 else 2080 a ^= A_BFG; 2081 a = (a & 0xbf) | (jj & 8 ? 0x40 : 0); 2082 cx = (cx & 0xf0) | (jj >> 4 & 0x0f); 2083 } 2084 else 2085 { 2086 c = (c & 0x0f) | ((jj & 0x0f) ^ 9) << 4; 2087 a |= A_BBG; 2088 if (jj >= 8 && jj < 16) 2089 c |= 0x80; 2090 else 2091 a ^= A_BBG; 2092 cx = (cx & 0x0f) | (jj & 0xf0); 2093 } 2094 continue; 2095# else 2096 jj = color256to16(jj) + 30; 2097 if (jj >= 38) 2098 jj += 60 - 8; 2099 j = j == 38 ? jj : jj + 10; 2100# endif 2101 } 2102# ifdef COLORS16 2103 if (j == 0 || (j >= 30 && j <= 39 && j != 38)) 2104 a &= 0xbf; 2105 if (j == 0 || (j >= 40 && j <= 49 && j != 48)) 2106 a &= 0x7f; 2107 if (j >= 90 && j <= 97) 2108 a |= 0x40; 2109 if (j >= 100 && j <= 107) 2110 a |= 0x80; 2111# endif 2112 if (j >= 90 && j <= 97) 2113 j -= 60; 2114 if (j >= 100 && j <= 107) 2115 j -= 60; 2116 if (j >= 30 && j <= 39 && j != 38) 2117 c = (c & 0xf0) | ((j - 30) ^ 9); 2118 else if (j >= 40 && j <= 49 && j != 48) 2119 c = (c & 0x0f) | (((j - 40) ^ 9) << 4); 2120 if (j == 0) 2121 c = 0; 2122# ifdef COLORS256 2123 if (j == 0 || (j >= 30 && j <= 39 && j != 38)) 2124 cx &= 0xf0; 2125 if (j == 0 || (j >= 40 && j <= 49 && j != 48)) 2126 cx &= 0x0f; 2127# endif 2128#endif 2129 if (j < 0 || j >= (int)(sizeof(rendlist)/sizeof(*rendlist))) 2130 continue; 2131 j = rendlist[j]; 2132 if (j & (1 << NATTR)) 2133 a &= j; 2134 else 2135 a |= j; 2136 } 2137 while (++i < curr->w_NumArgs); 2138 curr->w_rend.attr = a; 2139#ifdef COLOR 2140 curr->w_rend.color = c; 2141# ifdef COLORS256 2142 curr->w_rend.colorx = cx; 2143# endif 2144#endif 2145 LSetRendition(&curr->w_layer, &curr->w_rend); 2146} 2147 2148static void 2149FillWithEs() 2150{ 2151 register int i; 2152 register unsigned char *p, *ep; 2153 2154 LClearAll(&curr->w_layer, 1); 2155 curr->w_y = curr->w_x = 0; 2156 for (i = 0; i < rows; ++i) 2157 { 2158 clear_mline(&curr->w_mlines[i], 0, cols + 1); 2159 p = curr->w_mlines[i].image; 2160 ep = p + cols; 2161 while (p < ep) 2162 *p++ = 'E'; 2163 } 2164 LRefreshAll(&curr->w_layer, 1); 2165} 2166 2167 2168/* 2169 * Ugly autoaka hack support: 2170 * ChangeAKA() sets a new aka 2171 * FindAKA() searches for an autoaka match 2172 */ 2173 2174void 2175ChangeAKA(p, s, l) 2176struct win *p; 2177char *s; 2178int l; 2179{ 2180 int i, c; 2181 2182 for (i = 0; l > 0; l--) 2183 { 2184 if (p->w_akachange + i == p->w_akabuf + sizeof(p->w_akabuf) - 1) 2185 break; 2186 c = (unsigned char)*s++; 2187 if (c == 0) 2188 break; 2189 if (c < 32 || c == 127 || (c >= 128 && c < 160 && p->w_c1)) 2190 continue; 2191 p->w_akachange[i++] = c; 2192 } 2193 p->w_akachange[i] = 0; 2194 p->w_title = p->w_akachange; 2195 if (p->w_akachange != p->w_akabuf) 2196 if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':') 2197 p->w_title = p->w_akabuf + strlen(p->w_akabuf) + 1; 2198 WindowChanged(p, 't'); 2199 WindowChanged((struct win *)0, 'w'); 2200 WindowChanged((struct win *)0, 'W'); 2201} 2202 2203static void 2204FindAKA() 2205{ 2206 register unsigned char *cp, *line; 2207 register struct win *wp = curr; 2208 register int len = strlen(wp->w_akabuf); 2209 int y; 2210 2211 y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y; 2212 cols = wp->w_width; 2213 try_line: 2214 cp = line = wp->w_mlines[y].image; 2215 if (wp->w_autoaka > 0 && *wp->w_akabuf != '\0') 2216 { 2217 for (;;) 2218 { 2219 if (cp - line >= cols - len) 2220 { 2221 if (++y == wp->w_autoaka && y < rows) 2222 goto try_line; 2223 return; 2224 } 2225 if (strncmp((char *)cp, wp->w_akabuf, len) == 0) 2226 break; 2227 cp++; 2228 } 2229 cp += len; 2230 } 2231 for (len = cols - (cp - line); len && *cp == ' '; len--, cp++) 2232 ; 2233 if (len) 2234 { 2235 if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^')) 2236 wp->w_autoaka = -1; 2237 else 2238 wp->w_autoaka = 0; 2239 line = cp; 2240 while (len && *cp != ' ') 2241 { 2242 if (*cp++ == '/') 2243 line = cp; 2244 len--; 2245 } 2246 ChangeAKA(wp, (char *)line, cp - line); 2247 } 2248 else 2249 wp->w_autoaka = 0; 2250} 2251 2252static void 2253RestorePosRendition() 2254{ 2255 LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); 2256 LSetRendition(&curr->w_layer, &curr->w_rend); 2257} 2258 2259/* Send a terminal report as if it were typed. */ 2260static void 2261Report(fmt, n1, n2) 2262char *fmt; 2263int n1, n2; 2264{ 2265 register int len; 2266 char rbuf[40]; /* enough room for all replys */ 2267 2268 sprintf(rbuf, fmt, n1, n2); 2269 len = strlen(rbuf); 2270 2271 if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf)) 2272 { 2273 bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len); 2274 curr->w_inlen += len; 2275 } 2276} 2277 2278 2279 2280/* 2281 *====================================================================* 2282 *====================================================================* 2283 */ 2284 2285/********************************************************************** 2286 * 2287 * Memory subsystem. 2288 * 2289 */ 2290 2291static void 2292MFixLine(p, y, mc) 2293struct win *p; 2294int y; 2295struct mchar *mc; 2296{ 2297 struct mline *ml = &p->w_mlines[y]; 2298 if (mc->attr && ml->attr == null) 2299 { 2300 if ((ml->attr = (unsigned char *)malloc(p->w_width + 1)) == 0) 2301 { 2302 ml->attr = null; 2303 mc->attr = p->w_rend.attr = 0; 2304 WMsg(p, 0, "Warning: no space for attr - turned off"); 2305 } 2306 bzero((char *)ml->attr, p->w_width + 1); 2307 } 2308#ifdef FONT 2309 if (mc->font && ml->font == null) 2310 { 2311 if ((ml->font = (unsigned char *)malloc(p->w_width + 1)) == 0) 2312 { 2313 ml->font = null; 2314 p->w_FontL = p->w_charsets[p->w_ss ? p->w_ss : p->w_Charset] = 0; 2315 p->w_FontR = p->w_charsets[p->w_ss ? p->w_ss : p->w_CharsetR] = 0; 2316 mc->font = p->w_rend.font = 0; 2317 WMsg(p, 0, "Warning: no space for font - turned off"); 2318 } 2319 bzero((char *)ml->font, p->w_width + 1); 2320 } 2321#endif 2322#ifdef COLOR 2323 if (mc->color && ml->color == null) 2324 { 2325 if ((ml->color = (unsigned char *)malloc(p->w_width + 1)) == 0) 2326 { 2327 ml->color = null; 2328 mc->color = p->w_rend.color = 0; 2329 WMsg(p, 0, "Warning: no space for color - turned off"); 2330 } 2331 bzero((char *)ml->color, p->w_width + 1); 2332 } 2333# ifdef COLORS256 2334 if (mc->colorx && ml->colorx == null) 2335 { 2336 if ((ml->colorx = (unsigned char *)malloc(p->w_width + 1)) == 0) 2337 { 2338 ml->colorx = null; 2339 mc->colorx = p->w_rend.colorx = 0; 2340 WMsg(p, 0, "Warning: no space for extended colors - turned off"); 2341 } 2342 bzero((char *)ml->colorx, p->w_width + 1); 2343 } 2344# endif 2345#endif 2346} 2347 2348/*****************************************************************/ 2349 2350#ifdef DW_CHARS 2351# define MKillDwRight(p, ml, x) \ 2352 if (dw_right(ml, x, p->w_encoding)) \ 2353 { \ 2354 if (x > 0) \ 2355 copy_mchar2mline(&mchar_blank, ml, x - 1); \ 2356 copy_mchar2mline(&mchar_blank, ml, x); \ 2357 } 2358 2359# define MKillDwLeft(p, ml, x) \ 2360 if (dw_left(ml, x, p->w_encoding)) \ 2361 { \ 2362 copy_mchar2mline(&mchar_blank, ml, x); \ 2363 copy_mchar2mline(&mchar_blank, ml, x + 1); \ 2364 } 2365#else 2366# define MKillDwRight(p, ml, x) ; 2367# define MKillDwLeft(p, ml, x) ; 2368#endif 2369 2370static void 2371MScrollH(p, n, y, xs, xe, bce) 2372struct win *p; 2373int n, y, xs, xe, bce; 2374{ 2375 struct mline *ml; 2376 2377 if (n == 0) 2378 return; 2379 ml = &p->w_mlines[y]; 2380 MKillDwRight(p, ml, xs); 2381 MKillDwLeft(p, ml, xe); 2382 if (n > 0) 2383 { 2384 if (xe - xs + 1 > n) 2385 { 2386 MKillDwRight(p, ml, xs + n); 2387 bcopy_mline(ml, xs + n, xs, xe + 1 - xs - n); 2388 } 2389 else 2390 n = xe - xs + 1; 2391 clear_mline(ml, xe + 1 - n, n); 2392#ifdef COLOR 2393 if (bce) 2394 MBceLine(p, y, xe + 1 - n, n, bce); 2395#endif 2396 } 2397 else 2398 { 2399 n = -n; 2400 if (xe - xs + 1 > n) 2401 { 2402 MKillDwLeft(p, ml, xe - n); 2403 bcopy_mline(ml, xs, xs + n, xe + 1 - xs - n); 2404 } 2405 else 2406 n = xe - xs + 1; 2407 clear_mline(ml, xs, n); 2408#ifdef COLOR 2409 if (bce) 2410 MBceLine(p, y, xs, n, bce); 2411#endif 2412 } 2413} 2414 2415static void 2416MScrollV(p, n, ys, ye, bce) 2417struct win *p; 2418int n, ys, ye, bce; 2419{ 2420 int i, cnt1, cnt2; 2421 struct mline tmp[256]; 2422 struct mline *ml; 2423 2424 if (n == 0) 2425 return; 2426 if (n > 0) 2427 { 2428 if (n > 256) 2429 { 2430 MScrollV(p, n - 256, ys, ye, bce); 2431 n = 256; 2432 } 2433 if (ye - ys + 1 < n) 2434 n = ye - ys + 1; 2435#ifdef COPY_PASTE 2436 if (compacthist) 2437 { 2438 ye = MFindUsedLine(p, ye, ys); 2439 if (ye - ys + 1 < n) 2440 n = ye - ys + 1; 2441 if (n <= 0) 2442 return; 2443 } 2444#endif 2445 /* Clear lines */ 2446 ml = p->w_mlines + ys; 2447 for (i = ys; i < ys + n; i++, ml++) 2448 { 2449#ifdef COPY_PASTE 2450 if (ys == p->w_top) 2451 WAddLineToHist(p, ml); 2452#endif 2453 if (ml->attr != null) 2454 free(ml->attr); 2455 ml->attr = null; 2456#ifdef FONT 2457 if (ml->font != null) 2458 free(ml->font); 2459 ml->font = null; 2460#endif 2461#ifdef COLOR 2462 if (ml->color != null) 2463 free(ml->color); 2464 ml->color = null; 2465# ifdef COLORS256 2466 if (ml->colorx != null) 2467 free(ml->colorx); 2468 ml->colorx = null; 2469# endif 2470#endif 2471 bclear((char *)ml->image, p->w_width + 1); 2472#ifdef COLOR 2473 if (bce) 2474 MBceLine(p, i, 0, p->w_width, bce); 2475#endif 2476 } 2477 /* switch 'em over */ 2478 cnt1 = n * sizeof(struct mline); 2479 cnt2 = (ye - ys + 1 - n) * sizeof(struct mline); 2480 if (cnt1 && cnt2) 2481 Scroll((char *)(p->w_mlines + ys), cnt1, cnt2, (char *)tmp); 2482 } 2483 else 2484 { 2485 if (n < -256) 2486 { 2487 MScrollV(p, n + 256, ys, ye, bce); 2488 n = -256; 2489 } 2490 n = -n; 2491 if (ye - ys + 1 < n) 2492 n = ye - ys + 1; 2493 2494 ml = p->w_mlines + ye; 2495 /* Clear lines */ 2496 for (i = ye; i > ye - n; i--, ml--) 2497 { 2498 if (ml->attr != null) 2499 free(ml->attr); 2500 ml->attr = null; 2501#ifdef FONT 2502 if (ml->font != null) 2503 free(ml->font); 2504 ml->font = null; 2505#endif 2506#ifdef COLOR 2507 if (ml->color != null) 2508 free(ml->color); 2509 ml->color = null; 2510# ifdef COLORS256 2511 if (ml->colorx != null) 2512 free(ml->colorx); 2513 ml->colorx = null; 2514# endif 2515#endif 2516 bclear((char *)ml->image, p->w_width + 1); 2517#ifdef COLOR 2518 if (bce) 2519 MBceLine(p, i, 0, p->w_width, bce); 2520#endif 2521 } 2522 cnt1 = n * sizeof(struct mline); 2523 cnt2 = (ye - ys + 1 - n) * sizeof(struct mline); 2524 if (cnt1 && cnt2) 2525 Scroll((char *)(p->w_mlines + ys), cnt2, cnt1, (char *)tmp); 2526 } 2527} 2528 2529static void 2530Scroll(cp, cnt1, cnt2, tmp) 2531char *cp, *tmp; 2532int cnt1, cnt2; 2533{ 2534 if (!cnt1 || !cnt2) 2535 return; 2536 if (cnt1 <= cnt2) 2537 { 2538 bcopy(cp, tmp, cnt1); 2539 bcopy(cp + cnt1, cp, cnt2); 2540 bcopy(tmp, cp + cnt2, cnt1); 2541 } 2542 else 2543 { 2544 bcopy(cp + cnt1, tmp, cnt2); 2545 bcopy(cp, cp + cnt2, cnt1); 2546 bcopy(tmp, cp, cnt2); 2547 } 2548} 2549 2550static void 2551MClearArea(p, xs, ys, xe, ye, bce) 2552struct win *p; 2553int xs, ys, xe, ye, bce; 2554{ 2555 int n, y; 2556 int xxe; 2557 struct mline *ml; 2558 2559 /* check for magic margin condition */ 2560 if (xs >= p->w_width) 2561 xs = p->w_width - 1; 2562 if (xe >= p->w_width) 2563 xe = p->w_width - 1; 2564 2565 MKillDwRight(p, p->w_mlines + ys, xs); 2566 MKillDwLeft(p, p->w_mlines + ye, xe); 2567 2568 ml = p->w_mlines + ys; 2569 for (y = ys; y <= ye; y++, ml++) 2570 { 2571 xxe = (y == ye) ? xe : p->w_width - 1; 2572 n = xxe - xs + 1; 2573 if (n > 0) 2574 clear_mline(ml, xs, n); 2575#ifdef COLOR 2576 if (n > 0 && bce) 2577 MBceLine(p, y, xs, xs + n - 1, bce); 2578#endif 2579 xs = 0; 2580 } 2581} 2582 2583static void 2584MInsChar(p, c, x, y) 2585struct win *p; 2586struct mchar *c; 2587int x, y; 2588{ 2589 int n; 2590 struct mline *ml; 2591 2592 ASSERT(x >= 0 && x < p->w_width); 2593 MFixLine(p, y, c); 2594 ml = p->w_mlines + y; 2595 n = p->w_width - x - 1; 2596 MKillDwRight(p, ml, x); 2597 if (n > 0) 2598 { 2599 MKillDwRight(p, ml, p->w_width - 1); 2600 bcopy_mline(ml, x, x + 1, n); 2601 } 2602 copy_mchar2mline(c, ml, x); 2603#ifdef DW_CHARS 2604 if (c->mbcs) 2605 { 2606 if (--n > 0) 2607 { 2608 MKillDwRight(p, ml, p->w_width - 1); 2609 bcopy_mline(ml, x + 1, x + 2, n); 2610 } 2611 copy_mchar2mline(c, ml, x + 1); 2612 ml->image[x + 1] = c->mbcs; 2613# ifdef UTF8 2614 if (p->w_encoding != UTF8) 2615 ml->font[x + 1] |= 0x80; 2616 else if (p->w_encoding == UTF8 && c->mbcs) 2617 ml->font[x + 1] = c->mbcs; 2618# else 2619 ml->font[x + 1] |= 0x80; 2620# endif 2621 } 2622#endif 2623} 2624 2625static void 2626MPutChar(p, c, x, y) 2627struct win *p; 2628struct mchar *c; 2629int x, y; 2630{ 2631 struct mline *ml; 2632 2633 MFixLine(p, y, c); 2634 ml = &p->w_mlines[y]; 2635 MKillDwRight(p, ml, x); 2636 MKillDwLeft(p, ml, x); 2637 copy_mchar2mline(c, ml, x); 2638#ifdef DW_CHARS 2639 if (c->mbcs) 2640 { 2641 MKillDwLeft(p, ml, x + 1); 2642 copy_mchar2mline(c, ml, x + 1); 2643 ml->image[x + 1] = c->mbcs; 2644# ifdef UTF8 2645 if (p->w_encoding != UTF8) 2646 ml->font[x + 1] |= 0x80; 2647 else if (p->w_encoding == UTF8 && c->mbcs) 2648 ml->font[x + 1] = c->mbcs; 2649# else 2650 ml->font[x + 1] |= 0x80; 2651# endif 2652 } 2653#endif 2654} 2655 2656 2657static void 2658MWrapChar(p, c, y, top, bot, ins) 2659struct win *p; 2660struct mchar *c; 2661int y, top, bot; 2662int ins; 2663{ 2664 struct mline *ml; 2665 int bce; 2666 2667#ifdef COLOR 2668 bce = rend_getbg(c); 2669#else 2670 bce = 0; 2671#endif 2672 MFixLine(p, y, c); 2673 ml = &p->w_mlines[y]; 2674 copy_mchar2mline(&mchar_null, ml, p->w_width); 2675 if (y == bot) 2676 MScrollV(p, 1, top, bot, bce); 2677 else if (y < p->w_height - 1) 2678 y++; 2679 if (ins) 2680 MInsChar(p, c, 0, y); 2681 else 2682 MPutChar(p, c, 0, y); 2683} 2684 2685static void 2686MPutStr(p, s, n, r, x, y) 2687struct win *p; 2688char *s; 2689int n; 2690struct mchar *r; 2691int x, y; 2692{ 2693 struct mline *ml; 2694 int i; 2695 unsigned char *b; 2696 2697 if (n <= 0) 2698 return; 2699 MFixLine(p, y, r); 2700 ml = &p->w_mlines[y]; 2701 MKillDwRight(p, ml, x); 2702 MKillDwLeft(p, ml, x + n - 1); 2703 bcopy(s, (char *)ml->image + x, n); 2704 b = ml->attr + x; 2705 for (i = n; i-- > 0;) 2706 *b++ = r->attr; 2707#ifdef FONT 2708 b = ml->font + x; 2709 for (i = n; i-- > 0;) 2710 *b++ = r->font; 2711#endif 2712#ifdef COLOR 2713 b = ml->color + x; 2714 for (i = n; i-- > 0;) 2715 *b++ = r->color; 2716# ifdef COLORS256 2717 b = ml->colorx + x; 2718 for (i = n; i-- > 0;) 2719 *b++ = r->colorx; 2720# endif 2721#endif 2722} 2723 2724#ifdef COLOR 2725static void 2726MBceLine(p, y, xs, xe, bce) 2727struct win *p; 2728int y, xs, xe, bce; 2729{ 2730 struct mchar mc; 2731 struct mline *ml; 2732 int x; 2733 2734 mc = mchar_null; 2735 rend_setbg(&mc, bce); 2736 MFixLine(p, y, &mc); 2737 ml = p->w_mlines + y; 2738# ifdef COLORS16 2739 if (mc.attr) 2740 for (x = xs; x <= xe; x++) 2741 ml->attr[x] = mc.attr; 2742# endif 2743 if (mc.color) 2744 for (x = xs; x <= xe; x++) 2745 ml->color[x] = mc.color; 2746# ifdef COLORS256 2747 if (mc.colorx) 2748 for (x = xs; x <= xe; x++) 2749 ml->colorx[x] = mc.colorx; 2750# endif 2751} 2752#endif 2753 2754 2755#ifdef COPY_PASTE 2756static void 2757WAddLineToHist(wp, ml) 2758struct win *wp; 2759struct mline *ml; 2760{ 2761 register unsigned char *q, *o; 2762 struct mline *hml; 2763 2764 if (wp->w_histheight == 0) 2765 return; 2766 hml = &wp->w_hlines[wp->w_histidx]; 2767 q = ml->image; ml->image = hml->image; hml->image = q; 2768 2769 q = ml->attr; o = hml->attr; hml->attr = q; ml->attr = null; 2770 if (o != null) 2771 free(o); 2772 2773#ifdef FONT 2774 q = ml->font; o = hml->font; hml->font = q; ml->font = null; 2775 if (o != null) 2776 free(o); 2777#endif 2778 2779#ifdef COLOR 2780 q = ml->color; o = hml->color; hml->color = q; ml->color = null; 2781 if (o != null) 2782 free(o); 2783# ifdef COLORS256 2784 q = ml->colorx; o = hml->colorx; hml->colorx = q; ml->colorx = null; 2785 if (o != null) 2786 free(o); 2787# endif 2788#endif 2789 2790 if (++wp->w_histidx >= wp->w_histheight) 2791 wp->w_histidx = 0; 2792} 2793#endif 2794 2795int 2796MFindUsedLine(p, ye, ys) 2797struct win *p; 2798int ys, ye; 2799{ 2800 int y; 2801 struct mline *ml = p->w_mlines + ye; 2802 2803 debug2("MFindUsedLine: %d %d\n", ye, ys); 2804 for (y = ye; y >= ys; y--, ml--) 2805 { 2806 if (bcmp((char*)ml->image, blank, p->w_width)) 2807 break; 2808 if (ml->attr != null && bcmp((char*)ml->attr, null, p->w_width)) 2809 break; 2810#ifdef COLOR 2811 if (ml->color != null && bcmp((char*)ml->color, null, p->w_width)) 2812 break; 2813# ifdef COLORS256 2814 if (ml->colorx != null && bcmp((char*)ml->colorx, null, p->w_width)) 2815 break; 2816# endif 2817#endif 2818 } 2819 debug1("MFindUsedLine returning %d\n", y); 2820 return y; 2821} 2822 2823 2824/* 2825 *====================================================================* 2826 *====================================================================* 2827 */ 2828 2829/* 2830 * Tricky: send only one bell even if the window is displayed 2831 * more than once. 2832 */ 2833void 2834WBell(p, visual) 2835struct win *p; 2836int visual; 2837{ 2838 struct canvas *cv; 2839 for (display = displays; display; display = display->d_next) 2840 { 2841 for (cv = D_cvlist; cv; cv = cv->c_next) 2842 if (cv->c_layer->l_bottom == &p->w_layer) 2843 break; 2844 if (cv && !visual) 2845 AddCStr(D_BL); 2846 else if (cv && D_VB) 2847 AddCStr(D_VB); 2848 else 2849 p->w_bell = visual ? BELL_VISUAL : BELL_FOUND; 2850 } 2851} 2852 2853/* 2854 * This should be reverse video. 2855 * Only change video if window is fore. 2856 * Because it is used in some termcaps to emulate 2857 * a visual bell we do this hack here. 2858 * (screen uses \Eg as special vbell sequence) 2859 */ 2860static void 2861WReverseVideo(p, on) 2862struct win *p; 2863int on; 2864{ 2865 struct canvas *cv; 2866 for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext) 2867 { 2868 display = cv->c_display; 2869 if (cv != D_forecv) 2870 continue; 2871 ReverseVideo(on); 2872 if (!on && p->w_revvid && !D_CVR) 2873 { 2874 if (D_VB) 2875 AddCStr(D_VB); 2876 else 2877 p->w_bell = BELL_VISUAL; 2878 } 2879 } 2880} 2881 2882void 2883WMsg(p, err, str) 2884struct win *p; 2885int err; 2886char *str; 2887{ 2888 extern struct layer *flayer; 2889 struct layer *oldflayer = flayer; 2890 flayer = &p->w_layer; 2891 LMsg(err, str); 2892 flayer = oldflayer; 2893} 2894 2895void 2896WChangeSize(p, w, h) 2897struct win *p; 2898int w, h; 2899{ 2900 int wok = 0; 2901 struct canvas *cv; 2902 2903 if (p->w_layer.l_cvlist == 0) 2904 { 2905 /* window not displayed -> works always */ 2906 ChangeWindowSize(p, w, h, p->w_histheight); 2907 return; 2908 } 2909 for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext) 2910 { 2911 display = cv->c_display; 2912 if (p != D_fore) 2913 continue; /* change only fore */ 2914 if (D_CWS) 2915 break; 2916 if (D_CZ0 && (w == Z0width || w == Z1width)) 2917 wok = 1; 2918 } 2919 if (cv == 0 && wok == 0) /* can't change any display */ 2920 return; 2921 if (!D_CWS) 2922 h = p->w_height; 2923 ChangeWindowSize(p, w, h, p->w_histheight); 2924 for (display = displays; display; display = display->d_next) 2925 { 2926 if (p == D_fore) 2927 { 2928 if (D_cvlist && D_cvlist->c_next == 0) 2929 ResizeDisplay(w, h); 2930 else 2931 ResizeDisplay(w, D_height); 2932 ResizeLayersToCanvases(); /* XXX Hmm ? */ 2933 continue; 2934 } 2935 for (cv = D_cvlist; cv; cv = cv->c_next) 2936 if (cv->c_layer->l_bottom == &p->w_layer) 2937 break; 2938 if (cv) 2939 Redisplay(0); 2940 } 2941} 2942 2943static int 2944WindowChangedCheck(s, what, hp) 2945char *s; 2946int what; 2947int *hp; 2948{ 2949 int h = 0; 2950 int l; 2951 while(*s) 2952 { 2953 if (*s++ != (hp ? '%' : '\005')) 2954 continue; 2955 l = 0; 2956 while (*s >= '0' && *s <= '9') 2957 s++; 2958 if (*s == 'L') 2959 { 2960 s++; 2961 l = 0x100; 2962 } 2963 if (*s == 'h') 2964 h = 1; 2965 if (*s == what || ((*s | l) == what) || what == 'd') 2966 break; 2967 if (*s) 2968 s++; 2969 } 2970 if (hp) 2971 *hp = h; 2972 return *s ? 1 : 0; 2973} 2974 2975void 2976WindowChanged(p, what) 2977struct win *p; 2978int what; 2979{ 2980 int inwstr, inhstr, inlstr; 2981 int inwstrh = 0, inhstrh = 0, inlstrh = 0; 2982 int got, ox, oy; 2983 struct display *olddisplay = display; 2984 struct canvas *cv; 2985 2986 inwstr = inhstr = 0; 2987 2988 if (what == 'f') 2989 { 2990 WindowChanged((struct win *)0, 'w'|0x100); 2991 WindowChanged((struct win *)0, 'W'|0x100); 2992 } 2993 2994 if (what) 2995 { 2996 inwstr = WindowChangedCheck(captionstring, what, &inwstrh); 2997 inhstr = WindowChangedCheck(hstatusstring, what, &inhstrh); 2998 inlstr = WindowChangedCheck(wliststr, what, &inlstrh); 2999 } 3000 else 3001 { 3002 inwstr = inhstr = 0; 3003 inlstr = 1; 3004 } 3005 3006 if (p == 0) 3007 { 3008 for (display = displays; display; display = display->d_next) 3009 { 3010 ox = D_x; 3011 oy = D_y; 3012 for (cv = D_cvlist; cv; cv = cv->c_next) 3013 { 3014 if (inlstr || (inlstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0))) 3015 WListUpdatecv(cv, (struct win *)0); 3016 p = Layer2Window(cv->c_layer); 3017 if (inwstr || (inwstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0))) 3018 if (cv->c_ye + 1 < D_height) 3019 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); 3020 } 3021 p = D_fore; 3022 if (inhstr || (inhstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0))) 3023 RefreshHStatus(); 3024 if (ox != -1 && ox != -1) 3025 GotoPos(ox, oy); 3026 } 3027 display = olddisplay; 3028 return; 3029 } 3030 3031 if (p->w_hstatus && *p->w_hstatus && (inwstrh || inhstrh || inlstrh) && WindowChangedCheck(p->w_hstatus, what, (int *)0)) 3032 { 3033 inwstr |= inwstrh; 3034 inhstr |= inhstrh; 3035 inlstr |= inlstrh; 3036 } 3037 if (!inwstr && !inhstr && !inlstr) 3038 return; 3039 for (display = displays; display; display = display->d_next) 3040 { 3041 got = 0; 3042 ox = D_x; 3043 oy = D_y; 3044 for (cv = D_cvlist; cv; cv = cv->c_next) 3045 { 3046 if (inlstr) 3047 WListUpdatecv(cv, p); 3048 if (Layer2Window(cv->c_layer) != p) 3049 continue; 3050 got = 1; 3051 if (inwstr && cv->c_ye + 1 < D_height) 3052 RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); 3053 } 3054 if (got && inhstr && p == D_fore) 3055 RefreshHStatus(); 3056 if (ox != -1 && ox != -1) 3057 GotoPos(ox, oy); 3058 } 3059 display = olddisplay; 3060} 3061 3062