Project

General

Profile

ansi.c

Marius Gligor, 03/17/2014 11:11 AM

Download (71.8 KB)

 
1
/* Copyright (c) 2008, 2009
2
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4
 *      Micah Cowan (micah@cowan.name)
5
 *      Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6
 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7
 *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8
 *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9
 * Copyright (c) 1987 Oliver Laumann
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 3, or (at your option)
14
 * any later version.
15
 *  
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program (see the file COPYING); if not, see
23
 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24
 * 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
25
 *
26
 ****************************************************************
27
 */
28

    
29
#include <sys/types.h>
30
#include <fcntl.h>
31
#ifndef sun        /* we want to know about TIOCPKT. */
32
# include <sys/ioctl.h>
33
#endif
34

    
35
#include "config.h"
36
#include "screen.h"
37
#include "braille.h"
38
#include "extern.h"
39
#include "logfile.h"
40

    
41
extern struct display *display, *displays;
42
extern struct win *fore;        /* for 83 escape */
43
extern struct layer *flayer;        /* for 83 escape */
44

    
45
extern struct NewWindow nwin_default;        /* for ResetWindow() */
46
extern int  nversion;                /* numerical version of screen */
47
extern int  log_flush, logtstamp_on, logtstamp_after;
48
extern char *logtstamp_string;
49
extern char *captionstring;
50
extern char *hstatusstring;
51
extern char *wliststr;
52
#ifdef COPY_PASTE
53
extern int compacthist;
54
#endif
55
#ifdef MULTIUSER
56
extern struct acluser *EffectiveAclUser;
57
#endif
58

    
59
int Z0width, Z1width;                /* widths for Z0/Z1 switching */
60

    
61
/* globals set in WriteString */
62
static struct win *curr;        /* window we are working on */
63
static int rows, cols;                /* window size of the curr window */
64

    
65
int visual_bell = 0;
66
int use_hardstatus = 1;                /* display status line in hs */
67
char *printcmd = 0;
68
int use_altscreen = 0;                /* enable alternate screen support? */
69

    
70
unsigned char *blank;                /* line filled with spaces */
71
unsigned char *null;                /* line filled with '\0' */
72

    
73
struct mline mline_old;
74
struct mline mline_blank;
75
struct mline mline_null;
76

    
77
struct mchar mchar_null;
78
struct mchar mchar_blank = {' ' /* , 0, 0, ... */};
79
struct mchar mchar_so    = {' ', A_SO /* , 0, 0, ... */};
80

    
81
int renditions[NUM_RENDS] = {65529 /* =ub */, 65531 /* =b */, 65533 /* =u */ };
82

    
83
/* keep string_t and string_t_string in sync! */
84
static char *string_t_string[] =
85
{
86
  "NONE",
87
  "DCS",                        /* Device control string */
88
  "OSC",                        /* Operating system command */
89
  "APC",                        /* Application program command */
90
                                /*  - used for status change */
91
  "PM",                                /* Privacy message */
92
  "AKA",                        /* title for current screen */
93
  "GM",                                /* Global message to every display */
94
  "STATUS"                        /* User hardstatus line */
95
};
96

    
97
/* keep state_t and state_t_string in sync! */
98
static char *state_t_string[] =
99
{
100
  "LIT",                        /* Literal input */
101
  "ESC",                        /* Start of escape sequence */
102
  "ASTR",                        /* Start of control string */
103
  "STRESC",                        /* ESC seen in control string */
104
  "CSI",                        /* Reading arguments in "CSI Pn ;...*/
105
  "PRIN",                        /* Printer mode */
106
  "PRINESC",                        /* ESC seen in printer mode */
107
  "PRINCSI",                        /* CSI seen in printer mode */
108
  "PRIN4"                        /* CSI 4 seen in printer mode */
109
};
110

    
111
static int  Special __P((int));
112
static void DoESC __P((int, int));
113
static void DoCSI __P((int, int));
114
static void StringStart __P((enum string_t));
115
static void StringChar __P((int));
116
static int  StringEnd __P((void));
117
static void PrintStart __P((void));
118
static void PrintChar __P((int));
119
static void PrintFlush __P((void));
120
#ifdef FONT
121
static void DesignateCharset __P((int, int));
122
static void MapCharset __P((int));
123
static void MapCharsetR __P((int));
124
#endif
125
static void SaveCursor __P((struct cursor *));
126
static void RestoreCursor __P((struct cursor *));
127
static void BackSpace __P((void));
128
static void Return __P((void));
129
static void LineFeed __P((int));
130
static void ReverseLineFeed __P((void));
131
static void InsertChar __P((int));
132
static void DeleteChar __P((int));
133
static void DeleteLine __P((int));
134
static void InsertLine __P((int));
135
static void Scroll __P((char *, int, int, char *));
136
static void ForwardTab __P((void));
137
static void BackwardTab __P((void));
138
static void ClearScreen __P((void));
139
static void ClearFromBOS __P((void));
140
static void ClearToEOS __P((void));
141
static void ClearLineRegion __P((int, int));
142
static void CursorRight __P((int));
143
static void CursorUp __P((int));
144
static void CursorDown __P((int));
145
static void CursorLeft __P((int));
146
static void ASetMode __P((int));
147
static void SelectRendition __P((void));
148
static void RestorePosRendition __P((void));
149
static void FillWithEs __P((void));
150
static void FindAKA __P((void));
151
static void Report __P((char *, int, int));
152
static void ScrollRegion __P((int));
153
#ifdef COPY_PASTE
154
static void WAddLineToHist __P((struct win *, struct mline *));
155
#endif
156
static void WLogString __P((struct win *, char *, int));
157
static void WReverseVideo __P((struct win *, int));
158
static int  WindowChangedCheck __P((char *, int, int *));
159
static void MFixLine __P((struct win *, int, struct mchar *));
160
static void MScrollH __P((struct win *, int, int, int, int, int));
161
static void MScrollV __P((struct win *, int, int, int, int));
162
static void MClearArea __P((struct win *, int, int, int, int, int));
163
static void MInsChar __P((struct win *, struct mchar *, int, int));
164
static void MPutChar __P((struct win *, struct mchar *, int, int));
165
static void MPutStr __P((struct win *, char *, int, struct mchar *, int, int));
166
static void MWrapChar __P((struct win *, struct mchar *, int, int, int, int));
167
#ifdef COLOR
168
static void MBceLine __P((struct win *, int, int, int, int));
169
#endif
170

    
171
#ifdef COLOR
172
# define CURR_BCE (curr->w_bce ? rend_getbg(&curr->w_rend) : 0)
173
#else
174
# define CURR_BCE 0
175
#endif
176

    
177
void
178
ResetAnsiState(p)
179
struct win *p;
180
{
181
  p->w_state = LIT;
182
  p->w_StringType = NONE;
183
}
184

    
185
void
186
ResetWindow(p)
187
register struct win *p;
188
{
189
  register int i;
190

    
191
  p->w_wrap = nwin_default.wrap;
192
  p->w_origin = 0;
193
  p->w_insert = 0;
194
  p->w_revvid = 0;
195
  p->w_mouse = 0;
196
  p->w_curinv = 0;
197
  p->w_curvvis = 0;
198
  p->w_autolf = 0;
199
  p->w_keypad = 0;
200
  p->w_cursorkeys = 0;
201
  p->w_top = 0;
202
  p->w_bot = p->w_height - 1;
203
  p->w_saved.on = 0;
204
  p->w_x = p->w_y = 0;
205
  p->w_state = LIT;
206
  p->w_StringType = NONE;
207
  bzero(p->w_tabs, p->w_width);
208
  for (i = 8; i < p->w_width; i += 8)
209
    p->w_tabs[i] = 1;
210
  p->w_rend = mchar_null;
211
#ifdef FONT
212
  ResetCharsets(p);
213
#endif
214
#ifdef COLOR
215
  p->w_bce = nwin_default.bce;
216
#endif
217
}
218

    
219
/* adds max 22 bytes */
220
int
221
GetAnsiStatus(w, buf)
222
struct win *w;
223
char *buf;
224
{
225
  char *p = buf;
226

    
227
  if (w->w_state == LIT)
228
    return 0;
229

    
230
  strcpy(p, state_t_string[w->w_state]);
231
  p += strlen(p);
232
  if (w->w_intermediate)
233
    {
234
      *p++ = '-';
235
      if (w->w_intermediate > 0xff)
236
        p += AddXChar(p, w->w_intermediate >> 8);
237
      p += AddXChar(p, w->w_intermediate & 0xff);
238
      *p = 0;
239
    }
240
  if (w->w_state == ASTR || w->w_state == STRESC)
241
    sprintf(p, "-%s", string_t_string[w->w_StringType]);
242
  p += strlen(p);
243
  return p - buf;
244
}
245

    
246

    
247
#ifdef FONT
248

    
249
void
250
ResetCharsets(p)
251
struct win *p;
252
{
253
  p->w_gr = nwin_default.gr;
254
  p->w_c1 = nwin_default.c1;
255
  SetCharsets(p, "BBBB02");
256
  if (nwin_default.charset)
257
    SetCharsets(p, nwin_default.charset);
258
#ifdef ENCODINGS
259
  ResetEncoding(p);
260
#endif
261
}
262

    
263
void
264
SetCharsets(p, s)
265
struct win *p;
266
char *s;
267
{
268
  int i;
269

    
270
  for (i = 0; i < 4 && *s; i++, s++)
271
    if (*s != '.')
272
      p->w_charsets[i] = ((*s == 'B') ? ASCII : *s);
273
  if (*s && *s++ != '.')
274
    p->w_Charset = s[-1] - '0';
275
  if (*s && *s != '.')
276
    p->w_CharsetR = *s - '0';
277
  p->w_ss = 0;
278
  p->w_FontL = p->w_charsets[p->w_Charset];
279
  p->w_FontR = p->w_charsets[p->w_CharsetR];
280
}
281
#endif        /* FONT */
282

    
283
/*****************************************************************/
284

    
285

    
286
/*
287
 *  Here comes the vt100 emulator
288
 *  - writes logfiles,
289
 *  - sets timestamp and flags activity in window.
290
 *  - record program output in window scrollback
291
 *  - translate program output for the display and put it into the obuf.
292
 *
293
 */
294
void
295
WriteString(wp, buf, len)
296
struct win *wp;
297
register char *buf;
298
register int len;
299
{
300
  register int c;
301
#ifdef FONT
302
  register int font;
303
#endif
304
  struct canvas *cv;
305

    
306
  if (!len)
307
    return;
308
  if (wp->w_log)
309
    WLogString(wp, buf, len);
310

    
311
  /* set global variables (yuck!) */
312
  curr = wp;
313
  cols = curr->w_width;
314
  rows = curr->w_height;
315

    
316
  if (curr->w_silence)
317
    SetTimeout(&curr->w_silenceev, curr->w_silencewait * 1000);
318

    
319
  if (curr->w_monitor == MON_ON)
320
    {
321
      debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell);
322
      curr->w_monitor = MON_FOUND;
323
    }
324

    
325
  if (cols > 0 && rows > 0)
326
    {
327
      do
328
        {
329
          c = (unsigned char)*buf++;
330
#ifdef FONT
331
# ifdef DW_CHARS
332
          if (!curr->w_mbcs)
333
# endif
334
            curr->w_rend.font = curr->w_FontL;        /* Default: GL */
335
#endif
336

    
337
          /* The next part is only for speedup */
338
          if (curr->w_state == LIT &&
339
#ifdef UTF8
340
              curr->w_encoding != UTF8 &&
341
#endif
342
#ifdef DW_CHARS
343
              !is_dw_font(curr->w_rend.font) &&
344
# ifdef ENCODINGS
345
              curr->w_rend.font != KANA && !curr->w_mbcs &&
346
# endif
347
#endif
348
#ifdef FONT
349
              curr->w_rend.font != '<' &&
350
#endif
351
              c >= ' ' && c != 0x7f &&
352
              ((c & 0x80) == 0 || ((c >= 0xa0 || !curr->w_c1) && !curr->w_gr)) && !curr->w_ss &&
353
              !curr->w_insert && curr->w_x < cols - 1)
354
            {
355
              register int currx = curr->w_x;
356
              char *imp = buf - 1;
357

    
358
              while (currx < cols - 1)
359
                {
360
                  currx++;
361
                  if (--len == 0)
362
                    break;
363
                  c = (unsigned char)*buf++;
364
                  if (c < ' ' || c == 0x7f || ((c & 0x80) && ((c < 0xa0 && curr->w_c1) || curr->w_gr)))
365
                    break;
366
                }
367
              currx -= curr->w_x;
368
              if (currx > 0)
369
                {
370
                  MPutStr(curr, imp, currx, &curr->w_rend, curr->w_x, curr->w_y);
371
                  LPutStr(&curr->w_layer, imp, currx, &curr->w_rend, curr->w_x, curr->w_y);
372
                  curr->w_x += currx;
373
                }
374
              if (len == 0)
375
                break;
376
            }
377
          /* end of speedup code */
378

    
379
#ifdef UTF8
380
          if (curr->w_encoding == UTF8)
381
            {
382
              c = FromUtf8(c, &curr->w_decodestate);
383
              if (c == -1)
384
                continue;
385
              if (c == -2)
386
                {
387
                  c = UCS_REPL;
388
                  /* try char again */
389
                  buf--;
390
                  len++;
391
                }
392
              if (c > 0xff)
393
                debug1("read UNICODE %04x\n", c);
394
            }
395
#endif
396

    
397
        tryagain:
398
          switch (curr->w_state)
399
            {
400
            case PRIN:
401
              switch (c)
402
                {
403
                case '\033':
404
                  curr->w_state = PRINESC;
405
                  break;
406
                default:
407
                  PrintChar(c);
408
                }
409
              break;
410
            case PRINESC:
411
              switch (c)
412
                {
413
                case '[':
414
                  curr->w_state = PRINCSI;
415
                  break;
416
                default:
417
                  PrintChar('\033');
418
                  PrintChar(c);
419
                  curr->w_state = PRIN;
420
                }
421
              break;
422
            case PRINCSI:
423
              switch (c)
424
                {
425
                case '4':
426
                  curr->w_state = PRIN4;
427
                  break;
428
                default:
429
                  PrintChar('\033');
430
                  PrintChar('[');
431
                  PrintChar(c);
432
                  curr->w_state = PRIN;
433
                }
434
              break;
435
            case PRIN4:
436
              switch (c)
437
                {
438
                case 'i':
439
                  curr->w_state = LIT;
440
                  PrintFlush();
441
                  if (curr->w_pdisplay && curr->w_pdisplay->d_printfd >= 0)
442
                    {
443
                      close(curr->w_pdisplay->d_printfd);
444
                      curr->w_pdisplay->d_printfd = -1;
445
                    }
446
                  curr->w_pdisplay = 0;
447
                  break;
448
                default:
449
                  PrintChar('\033');
450
                  PrintChar('[');
451
                  PrintChar('4');
452
                  PrintChar(c);
453
                  curr->w_state = PRIN;
454
                }
455
              break;
456
            case ASTR:
457
              if (c == 0)
458
                break;
459
              if (c == '\033')
460
                {
461
                  curr->w_state = STRESC;
462
                  break;
463
                }
464
              /* special xterm hack: accept SetStatus sequence. Yucc! */
465
              /* allow ^E for title escapes */
466
              if (!(curr->w_StringType == OSC && c < ' ' && c != '\005'))
467
                if (!curr->w_c1 || c != ('\\' ^ 0xc0))
468
                  {
469
                    StringChar(c);
470
                    break;
471
                  }
472
              c = '\\';
473
              /* FALLTHROUGH */
474
            case STRESC:
475
              switch (c)
476
                {
477
                case '\\':
478
                  if (StringEnd() == 0 || len <= 1)
479
                    break;
480
                  /* check if somewhere a status is displayed */
481
                  for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext)
482
                    {
483
                      display = cv->c_display;
484
                      if (D_status == STATUS_ON_WIN)
485
                        break;
486
                    }
487
                  if (cv)
488
                    {
489
                      if (len > IOSIZE + 1)
490
                        len = IOSIZE + 1;
491
                      curr->w_outlen = len - 1;
492
                      bcopy(buf, curr->w_outbuf, len - 1);
493
                      return;        /* wait till status is gone */
494
                    }
495
                  break;
496
                case '\033':
497
                  StringChar('\033');
498
                  break;
499
                default:
500
                  curr->w_state = ASTR;
501
                  StringChar('\033');
502
                  StringChar(c);
503
                  break;
504
                }
505
              break;
506
            case ESC:
507
              switch (c)
508
                {
509
                case '[':
510
                  curr->w_NumArgs = 0;
511
                  curr->w_intermediate = 0;
512
                  bzero((char *) curr->w_args, MAXARGS * sizeof(int));
513
                  curr->w_state = CSI;
514
                  break;
515
                case ']':
516
                  StringStart(OSC);
517
                  break;
518
                case '_':
519
                  StringStart(APC);
520
                  break;
521
                case 'P':
522
                  StringStart(DCS);
523
                  break;
524
                case '^':
525
                  StringStart(PM);
526
                  break;
527
                case '!':
528
                  StringStart(GM);
529
                  break;
530
                case '"':
531
                case 'k':
532
                  StringStart(AKA);
533
                  break;
534
                default:
535
                  if (Special(c))
536
                    {
537
                      curr->w_state = LIT;
538
                      break;
539
                    }
540
                  debug1("not special. c = %x\n", c);
541
                  if (c >= ' ' && c <= '/')
542
                    {
543
                      if (curr->w_intermediate)
544
                        {
545
#ifdef DW_CHARS
546
                          if (curr->w_intermediate == '$')
547
                            c |= '$' << 8;
548
                          else
549
#endif
550
                          c = -1;
551
                        }
552
                      curr->w_intermediate = c;
553
                    }
554
                  else if (c >= '0' && c <= '~')
555
                    {
556
                      DoESC(c, curr->w_intermediate);
557
                      curr->w_state = LIT;
558
                    }
559
                  else
560
                    {
561
                      curr->w_state = LIT;
562
                      goto tryagain;
563
                    }
564
                }
565
              break;
566
            case CSI:
567
              switch (c)
568
                {
569
                case '0': case '1': case '2': case '3': case '4':
570
                case '5': case '6': case '7': case '8': case '9':
571
                  if (curr->w_NumArgs < MAXARGS)
572
                    {
573
                      if (curr->w_args[curr->w_NumArgs] < 100000000)
574
                        curr->w_args[curr->w_NumArgs] =
575
                          10 * curr->w_args[curr->w_NumArgs] + (c - '0');
576
                    }
577
                  break;
578
                case ';':
579
                case ':':
580
                  if (curr->w_NumArgs < MAXARGS)
581
                    curr->w_NumArgs++;
582
                  break;
583
                default:
584
                  if (Special(c))
585
                    break;
586
                  if (c >= '@' && c <= '~')
587
                    {
588
                      if (curr->w_NumArgs < MAXARGS)
589
                        curr->w_NumArgs++;
590
                      DoCSI(c, curr->w_intermediate);
591
                      if (curr->w_state != PRIN)
592
                        curr->w_state = LIT;
593
                    }
594
                  else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
595
                    curr->w_intermediate = curr->w_intermediate ? -1 : c;
596
                  else
597
                    {
598
                      curr->w_state = LIT;
599
                      goto tryagain;
600
                    }
601
                }
602
              break;
603
            case LIT:
604
            default:
605
#ifdef DW_CHARS
606
              if (curr->w_mbcs)
607
                if (c <= ' ' || c == 0x7f || (c >= 0x80 && c < 0xa0 && curr->w_c1))
608
                  curr->w_mbcs = 0;
609
#endif
610
              if (c < ' ')
611
                {
612
                  if (c == '\033')
613
                    {
614
                      curr->w_intermediate = 0;
615
                      curr->w_state = ESC;
616
                      if (curr->w_autoaka < 0)
617
                        curr->w_autoaka = 0;
618
                    }
619
                  else
620
                    Special(c);
621
                  break;
622
                }
623
              if (c >= 0x80 && c < 0xa0 && curr->w_c1)
624
#ifdef FONT
625
                if ((curr->w_FontR & 0xf0) != 0x20
626
# ifdef UTF8
627
                       || curr->w_encoding == UTF8
628
# endif
629
                   )
630
#endif
631
                {
632
                  switch (c)
633
                    {
634
                    case 0xc0 ^ 'D':
635
                    case 0xc0 ^ 'E':
636
                    case 0xc0 ^ 'H':
637
                    case 0xc0 ^ 'M':
638
                    case 0xc0 ^ 'N':                /* SS2 */
639
                    case 0xc0 ^ 'O':                /* SS3 */
640
                      DoESC(c ^ 0xc0, 0);
641
                      break;
642
                    case 0xc0 ^ '[':
643
                      if (curr->w_autoaka < 0)
644
                        curr->w_autoaka = 0;
645
                      curr->w_NumArgs = 0;
646
                      curr->w_intermediate = 0;
647
                      bzero((char *) curr->w_args, MAXARGS * sizeof(int));
648
                      curr->w_state = CSI;
649
                      break;
650
                    case 0xc0 ^ 'P':
651
                      StringStart(DCS);
652
                      break;
653
                    default:
654
                      break;
655
                    }
656
                  break;
657
                }
658

    
659
#ifdef FONT
660
# ifdef DW_CHARS
661
              if (!curr->w_mbcs)
662
                {
663
# endif
664
                  if (c < 0x80 || curr->w_gr == 0)
665
                    curr->w_rend.font = curr->w_FontL;
666
# ifdef ENCODINGS
667
                  else if (curr->w_gr == 2 && !curr->w_ss)
668
                    curr->w_rend.font = curr->w_FontE;
669
# endif
670
                  else
671
                    curr->w_rend.font = curr->w_FontR;
672
# ifdef DW_CHARS
673
                }
674
# endif
675
# ifdef UTF8
676
              if (curr->w_encoding == UTF8)
677
                {
678
                  if (curr->w_rend.font == '0')
679
                    {
680
                      struct mchar mc, *mcp;
681

    
682
                      debug1("SPECIAL %x\n", c);
683
                      mc.image = c;
684
                      mc.mbcs = 0;
685
                      mc.font = '0';
686
                      mc.fontx = 0;
687
                      mcp = recode_mchar(&mc, 0, UTF8);
688
                      debug2("%02x %02x\n", mcp->image, mcp->font);
689
                      c = mcp->image | mcp->font << 8;
690
                    }
691
                  curr->w_rend.font = 0;
692
                }
693
#  ifdef DW_CHARS
694
              if (curr->w_encoding == UTF8 && utf8_isdouble(c))
695
                curr->w_mbcs = 0xff;
696
#  endif
697
              if (curr->w_encoding == UTF8 && c >= 0x0300 && utf8_iscomb(c))
698
                {
699
                  int ox, oy;
700
                  struct mchar omc;
701

    
702
                  ox = curr->w_x - 1;
703
                  oy = curr->w_y;
704
                  if (ox < 0)
705
                    {
706
                      ox = curr->w_width - 1;
707
                      oy--;
708
                    }
709
                  if (oy < 0)
710
                    oy = 0;
711
                  copy_mline2mchar(&omc, &curr->w_mlines[oy], ox);
712
                  if (omc.image == 0xff && omc.font == 0xff && omc.fontx == 0)
713
                    {
714
                      ox--;
715
                      if (ox >= 0)
716
                        {
717
                          copy_mline2mchar(&omc, &curr->w_mlines[oy], ox);
718
                          omc.mbcs = 0xff;
719
                        }
720
                    }
721
                  if (ox >= 0)
722
                    {
723
                      utf8_handle_comb(c, &omc);
724
                      MFixLine(curr, oy, &omc);
725
                      copy_mchar2mline(&omc, &curr->w_mlines[oy], ox);
726
                      LPutChar(&curr->w_layer, &omc, ox, oy);
727
                      LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
728
                    }
729
                  break;
730
                }
731
              font = curr->w_rend.font;
732
# endif
733
# ifdef DW_CHARS
734
#  ifdef ENCODINGS
735
              if (font == KANA && curr->w_encoding == SJIS && curr->w_mbcs == 0)
736
                {
737
                  /* Lets see if it is the first byte of a kanji */
738
                  debug1("%x may be first of SJIS\n", c);
739
                  if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef))
740
                    {
741
                      debug("YES!\n");
742
                      curr->w_mbcs = c;
743
                      break;
744
                    }
745
                }
746
#  endif
747
              if (font == 031 && c == 0x80 && !curr->w_mbcs)
748
                font = curr->w_rend.font = 0;
749
              if (is_dw_font(font) && c == ' ')
750
                font = curr->w_rend.font = 0;
751
              if (is_dw_font(font) || curr->w_mbcs)
752
                {
753
                  int t = c;
754
                  if (curr->w_mbcs == 0)
755
                    {
756
                      curr->w_mbcs = c;
757
                      break;
758
                    }
759
                  if (curr->w_x == cols - 1)
760
                    {
761
                      curr->w_x += curr->w_wrap ? 1 : -1;
762
                      debug1("Patched w_x to %d\n", curr->w_x);
763
                    }
764
#  ifdef UTF8
765
                  if (curr->w_encoding != UTF8)
766
#  endif
767
                    {
768
                      c = curr->w_mbcs;
769
#  ifdef ENCODINGS
770
                      if (font == KANA && curr->w_encoding == SJIS)
771
                        {
772
                          debug2("SJIS !! %x %x\n", c, t);
773
                          /*
774
                           * SJIS -> EUC mapping:
775
                           *   First byte:
776
                           *     81,82...9f -> 21,23...5d
777
                           *     e0,e1...ef -> 5f,61...7d
778
                           *   Second byte:
779
                           *     40-7e -> 21-5f
780
                           *     80-9e -> 60-7e
781
                           *     9f-fc -> 21-7e (increment first byte!)
782
                           */
783
                          if (0x40 <= t && t <= 0xfc && t != 0x7f)
784
                            {
785
                              if (c <= 0x9f) c = (c - 0x81) * 2 + 0x21;
786
                              else c = (c - 0xc1) * 2 + 0x21;
787
                              if (t <= 0x7e) t -= 0x1f;
788
                              else if (t <= 0x9e) t -= 0x20;
789
                              else t -= 0x7e, c++;
790
                              curr->w_rend.font = KANJI;
791
                            }
792
                          else
793
                            {
794
                              /* Incomplete shift-jis - skip first byte */
795
                              c = t;
796
                              t = 0;
797
                            }
798
                          debug2("SJIS after %x %x\n", c, t);
799
                        }
800
#  endif
801
                      if (t && curr->w_gr && font != 030 && font != 031)
802
                        {
803
                          t &= 0x7f;
804
                          if (t < ' ')
805
                            goto tryagain;
806
                        }
807
                      if (t == '\177')
808
                        break;
809
                      curr->w_mbcs = t;
810
                    }
811
                }
812
# endif        /* DW_CHARS */
813
              if (font == '<' && c >= ' ')
814
                {
815
                  font = curr->w_rend.font = 0;
816
                  c |= 0x80;
817
                }
818
# ifdef UTF8
819
              else if (curr->w_gr && curr->w_encoding != UTF8)
820
# else
821
              else if (curr->w_gr)
822
# endif
823
                {
824
#ifdef ENCODINGS
825
                  if (c == 0x80 && font == 0 && curr->w_encoding == GBK)
826
                    c = 0xa4;
827
                  else
828
                    c &= 0x7f;
829
                  if (c < ' ' && font != 031)
830
                    goto tryagain;
831
#else
832
                  c &= 0x7f;
833
                  if (c < ' ')        /* this is ugly but kanji support */
834
                    goto tryagain;        /* prevents nicer programming */
835
#endif
836
                }
837
#endif /* FONT */
838
              if (c == '\177')
839
                break;
840
              curr->w_rend.image = c;
841
#ifdef UTF8
842
              if (curr->w_encoding == UTF8)
843
                {
844
                  curr->w_rend.font = c >> 8;
845
                  curr->w_rend.fontx = c >> 16;
846
                }
847
#endif
848
#ifdef DW_CHARS
849
              curr->w_rend.mbcs = curr->w_mbcs;
850
#endif
851
              if (curr->w_x < cols - 1)
852
                {
853
                  if (curr->w_insert)
854
                    {
855
                      save_mline(&curr->w_mlines[curr->w_y], cols);
856
                      MInsChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
857
                      LInsChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y, &mline_old);
858
                      curr->w_x++;
859
                    }
860
                  else
861
                    {
862
                      MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
863
                      LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y);
864
                      curr->w_x++;
865
                    }
866
                }
867
              else if (curr->w_x == cols - 1)
868
                {
869
                  MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y);
870
                  LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y);
871
                  if (curr->w_wrap)
872
                    curr->w_x++;
873
                }
874
              else
875
                {
876
                  MWrapChar(curr, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert);
877
                  LWrapChar(&curr->w_layer, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert);
878
                  if (curr->w_y != curr->w_bot && curr->w_y != curr->w_height - 1)
879
                    curr->w_y++;
880
                  curr->w_x = 1;
881
                }
882
#ifdef FONT
883
# ifdef DW_CHARS
884
              if (curr->w_mbcs)
885
                {
886
                  curr->w_rend.mbcs = curr->w_mbcs = 0;
887
                  curr->w_x++;
888
                }
889
# endif
890
              if (curr->w_ss)
891
                {
892
                  curr->w_FontL = curr->w_charsets[curr->w_Charset];
893
                  curr->w_FontR = curr->w_charsets[curr->w_CharsetR];
894
                  curr->w_rend.font = curr->w_FontL;
895
                  LSetRendition(&curr->w_layer, &curr->w_rend);
896
                  curr->w_ss = 0;
897
                }
898
#endif /* FONT */
899
              break;
900
            }
901
        }
902
      while (--len);
903
    }
904
  if (!printcmd && curr->w_state == PRIN)
905
    PrintFlush();
906
}
907

    
908
static void
909
WLogString(p, buf, len)
910
struct win *p;
911
char *buf;
912
int len;
913
{
914
  if (!p->w_log)
915
    return;
916
  if (logtstamp_on && p->w_logsilence >= logtstamp_after * 2)
917
    {
918
      char *t = MakeWinMsg(logtstamp_string, p, '%');
919
      logfwrite(p->w_log, t, strlen(t));        /* long time no write */
920
    }
921
  p->w_logsilence = 0;
922
  if (logfwrite(p->w_log, buf, len) < 1)
923
    {
924
      WMsg(p, errno, "Error writing logfile");
925
      logfclose(p->w_log);
926
      p->w_log = 0;
927
    }
928
  if (!log_flush)
929
    logfflush(p->w_log);
930
}
931

    
932
static int
933
Special(c)
934
register int c;
935
{
936
  switch (c)
937
    {
938
    case '\b':
939
      BackSpace();
940
      return 1;
941
    case '\r':
942
      Return();
943
      return 1;
944
    case '\n':
945
      if (curr->w_autoaka)
946
        FindAKA();
947
    case '\013':        /* Vertical tab is the same as Line Feed */
948
      LineFeed(0);
949
      return 1;
950
    case '\007':
951
      WBell(curr, visual_bell);
952
      return 1;
953
    case '\t':
954
      ForwardTab();
955
      return 1;
956
#ifdef FONT
957
    case '\017':                /* SI */
958
      MapCharset(G0);
959
      return 1;
960
    case '\016':                /* SO */
961
      MapCharset(G1);
962
      return 1;
963
#endif
964
    }
965
  return 0;
966
}
967

    
968
static void
969
DoESC(c, intermediate)
970
int c, intermediate;
971
{
972
  debug2("DoESC: %x - inter = %x\n", c, intermediate);
973
  switch (intermediate)
974
    {
975
    case 0:
976
      switch (c)
977
        {
978
        case 'E':
979
          LineFeed(1);
980
          break;
981
        case 'D':
982
          LineFeed(0);
983
          break;
984
        case 'M':
985
          ReverseLineFeed();
986
          break;
987
        case 'H':
988
          curr->w_tabs[curr->w_x] = 1;
989
          break;
990
        case 'Z':                /* jph: Identify as VT100 */
991
          Report("\033[?%d;%dc", 1, 2);
992
          break;
993
        case '7':
994
          SaveCursor(&curr->w_saved);
995
          break;
996
        case '8':
997
          RestoreCursor(&curr->w_saved);
998
          break;
999
        case 'c':
1000
          ClearScreen();
1001
          ResetWindow(curr);
1002
          LKeypadMode(&curr->w_layer, 0);
1003
          LCursorkeysMode(&curr->w_layer, 0);
1004
#ifndef TIOCPKT
1005
          WNewAutoFlow(curr, 1);
1006
#endif
1007
          /* XXX
1008
          SetRendition(&mchar_null);
1009
          InsertMode(0);
1010
          ChangeScrollRegion(0, rows - 1);
1011
          */
1012
          LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1013
          break;
1014
        case '=':
1015
          LKeypadMode(&curr->w_layer, curr->w_keypad = 1);
1016
#ifndef TIOCPKT
1017
          WNewAutoFlow(curr, 0);
1018
#endif /* !TIOCPKT */
1019
          break;
1020
        case '>':
1021
          LKeypadMode(&curr->w_layer, curr->w_keypad = 0);
1022
#ifndef TIOCPKT
1023
          WNewAutoFlow(curr, 1);
1024
#endif /* !TIOCPKT */
1025
          break;
1026
#ifdef FONT
1027
        case 'n':                /* LS2 */
1028
          MapCharset(G2);
1029
          break;
1030
        case 'o':                /* LS3 */
1031
          MapCharset(G3);
1032
          break;
1033
        case '~':
1034
          MapCharsetR(G1);        /* LS1R */
1035
          break;
1036
        /* { */
1037
        case '}':
1038
          MapCharsetR(G2);        /* LS2R */
1039
          break;
1040
        case '|':
1041
          MapCharsetR(G3);        /* LS3R */
1042
          break;
1043
        case 'N':                /* SS2 */
1044
          if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2]
1045
              || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G2])
1046
            curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G2];
1047
          else
1048
            curr->w_ss = 0;
1049
          break;
1050
        case 'O':                /* SS3 */
1051
          if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3]
1052
              || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G3])
1053
            curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G3];
1054
          else
1055
            curr->w_ss = 0;
1056
          break;
1057
#endif /* FONT */
1058
        case 'g':                /* VBELL, private screen sequence */
1059
          WBell(curr, 1);
1060
          break;
1061
        }
1062
      break;
1063
    case '#':
1064
      switch (c)
1065
        {
1066
        case '8':
1067
          FillWithEs();
1068
          break;
1069
        }
1070
      break;
1071
#ifdef FONT
1072
    case '(':
1073
      DesignateCharset(c, G0);
1074
      break;
1075
    case ')':
1076
      DesignateCharset(c, G1);
1077
      break;
1078
    case '*':
1079
      DesignateCharset(c, G2);
1080
      break;
1081
    case '+':
1082
      DesignateCharset(c, G3);
1083
      break;
1084
# ifdef DW_CHARS
1085
/*
1086
 * ESC $ ( Fn: invoke multi-byte charset, Fn, to G0
1087
 * ESC $ Fn: same as above.  (old sequence)
1088
 * ESC $ ) Fn: invoke multi-byte charset, Fn, to G1
1089
 * ESC $ * Fn: invoke multi-byte charset, Fn, to G2
1090
 * ESC $ + Fn: invoke multi-byte charset, Fn, to G3
1091
 */
1092
    case '$':
1093
    case '$'<<8 | '(':
1094
      DesignateCharset(c & 037, G0);
1095
      break;
1096
    case '$'<<8 | ')':
1097
      DesignateCharset(c & 037, G1);
1098
      break;
1099
    case '$'<<8 | '*':
1100
      DesignateCharset(c & 037, G2);
1101
      break;
1102
    case '$'<<8 | '+':
1103
      DesignateCharset(c & 037, G3);
1104
      break;
1105
# endif
1106
#endif /* FONT */
1107
    }
1108
}
1109

    
1110
static void
1111
DoCSI(c, intermediate)
1112
int c, intermediate;
1113
{
1114
  register int i, a1 = curr->w_args[0], a2 = curr->w_args[1];
1115

    
1116
  if (curr->w_NumArgs > MAXARGS)
1117
    curr->w_NumArgs = MAXARGS;
1118
  switch (intermediate)
1119
    {
1120
    case 0:
1121
      switch (c)
1122
        {
1123
        case 'H':
1124
        case 'f':
1125
          if (a1 < 1)
1126
            a1 = 1;
1127
          if (curr->w_origin)
1128
            a1 += curr->w_top;
1129
          if (a1 > rows)
1130
            a1 = rows;
1131
          if (a2 < 1)
1132
            a2 = 1;
1133
          if (a2 > cols)
1134
            a2 = cols;
1135
          LGotoPos(&curr->w_layer, --a2, --a1);
1136
          curr->w_x = a2;
1137
          curr->w_y = a1;
1138
          if (curr->w_autoaka)
1139
            curr->w_autoaka = a1 + 1;
1140
          break;
1141
        case 'J':
1142
          if (a1 < 0 || a1 > 2)
1143
            a1 = 0;
1144
          switch (a1)
1145
            {
1146
            case 0:
1147
              ClearToEOS();
1148
              break;
1149
            case 1:
1150
              ClearFromBOS();
1151
              break;
1152
            case 2:
1153
              ClearScreen();
1154
              LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1155
              break;
1156
            }
1157
          break;
1158
        case 'K':
1159
          if (a1 < 0 || a1 > 2)
1160
            a1 %= 3;
1161
          switch (a1)
1162
            {
1163
            case 0:
1164
              ClearLineRegion(curr->w_x, cols - 1);
1165
              break;
1166
            case 1:
1167
              ClearLineRegion(0, curr->w_x);
1168
              break;
1169
            case 2:
1170
              ClearLineRegion(0, cols - 1);
1171
              break;
1172
            }
1173
          break;
1174
        case 'X':
1175
          a1 = curr->w_x + (a1 ? a1 - 1 : 0);
1176
          ClearLineRegion(curr->w_x, a1 < cols ? a1 : cols - 1);
1177
          break;
1178
        case 'A':
1179
          CursorUp(a1 ? a1 : 1);
1180
          break;
1181
        case 'B':
1182
          CursorDown(a1 ? a1 : 1);
1183
          break;
1184
        case 'C':
1185
          CursorRight(a1 ? a1 : 1);
1186
          break;
1187
        case 'D':
1188
          CursorLeft(a1 ? a1 : 1);
1189
          break;
1190
        case 'E':
1191
          curr->w_x = 0;
1192
          CursorDown(a1 ? a1 : 1);        /* positions cursor */
1193
          break;
1194
        case 'F':
1195
          curr->w_x = 0;
1196
          CursorUp(a1 ? a1 : 1);        /* positions cursor */
1197
          break;
1198
        case 'G':
1199
        case '`':                        /* HPA */
1200
          curr->w_x = a1 ? a1 - 1 : 0;
1201
          if (curr->w_x >= cols)
1202
            curr->w_x = cols - 1;
1203
          LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1204
          break;
1205
        case 'd':                        /* VPA */
1206
          curr->w_y = a1 ? a1 - 1 : 0;
1207
          if (curr->w_y >= rows)
1208
            curr->w_y = rows - 1;
1209
          LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1210
          break;
1211
        case 'm':
1212
          SelectRendition();
1213
          break;
1214
        case 'g':
1215
          if (a1 == 0)
1216
            curr->w_tabs[curr->w_x] = 0;
1217
          else if (a1 == 3)
1218
            bzero(curr->w_tabs, cols);
1219
          break;
1220
        case 'r':
1221
          if (!a1)
1222
            a1 = 1;
1223
          if (!a2)
1224
            a2 = rows;
1225
          if (a1 < 1 || a2 > rows || a1 >= a2)
1226
            break;
1227
          curr->w_top = a1 - 1;
1228
          curr->w_bot = a2 - 1;
1229
          /* ChangeScrollRegion(curr->w_top, curr->w_bot); */
1230
          if (curr->w_origin)
1231
            {
1232
              curr->w_y = curr->w_top;
1233
              curr->w_x = 0;
1234
            }
1235
          else
1236
            curr->w_y = curr->w_x = 0;
1237
          LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1238
          break;
1239
        case 's':
1240
          SaveCursor(&curr->w_saved);
1241
          break;
1242
        case 't':
1243
          switch(a1)
1244
            {
1245
            case 11:
1246
              if (curr->w_layer.l_cvlist)
1247
                Report("\033[1t", 0, 0);
1248
              else
1249
                Report("\033[2t", 0, 0);
1250
              break;
1251
            case 7:
1252
              LRefreshAll(&curr->w_layer, 0);
1253
              break;
1254
            case 21:
1255
              a1 = strlen(curr->w_title);
1256
              if ((unsigned)(curr->w_inlen + 5 + a1) <= sizeof(curr->w_inbuf))
1257
                {
1258
                  bcopy("\033]l", curr->w_inbuf + curr->w_inlen, 3);
1259
                  bcopy(curr->w_title, curr->w_inbuf + curr->w_inlen + 3, a1);
1260
                  bcopy("\033\\", curr->w_inbuf + curr->w_inlen + 3 + a1, 2);
1261
                  curr->w_inlen += 5 + a1;
1262
                }
1263
              break;
1264
            case 8:
1265
              a1 = curr->w_args[2];
1266
              if (a1 < 1)
1267
                a1 = curr->w_width;
1268
              if (a2 < 1)
1269
                a2 = curr->w_height;
1270
              if (a1 > 10000 || a2 > 10000)
1271
                break;
1272
              WChangeSize(curr, a1, a2);
1273
              cols = curr->w_width;
1274
              rows = curr->w_height;
1275
              break;
1276
            default:
1277
              break;
1278
            }
1279
          break;
1280
        case 'u':
1281
          RestoreCursor(&curr->w_saved);
1282
          break;
1283
        case 'I':
1284
          if (!a1)
1285
            a1 = 1;
1286
          while (a1--)
1287
            ForwardTab();
1288
          break;
1289
        case 'Z':
1290
          if (!a1)
1291
            a1 = 1;
1292
          while (a1--)
1293
            BackwardTab();
1294
          break;
1295
        case 'L':
1296
          InsertLine(a1 ? a1 : 1);
1297
          break;
1298
        case 'M':
1299
          DeleteLine(a1 ? a1 : 1);
1300
          break;
1301
        case 'P':
1302
          DeleteChar(a1 ? a1 : 1);
1303
          break;
1304
        case '@':
1305
          InsertChar(a1 ? a1 : 1);
1306
          break;
1307
        case 'h':
1308
          ASetMode(1);
1309
          break;
1310
        case 'l':
1311
          ASetMode(0);
1312
          break;
1313
        case 'i':                /* MC Media Control */
1314
          if (a1 == 5)
1315
            PrintStart();
1316
          break;
1317
        case 'n':
1318
          if (a1 == 5)                /* Report terminal status */
1319
            Report("\033[0n", 0, 0);
1320
          else if (a1 == 6)                /* Report cursor position */
1321
            Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1);
1322
          break;
1323
        case 'c':                /* Identify as VT100 */
1324
          if (a1 == 0)
1325
            Report("\033[?%d;%dc", 1, 2);
1326
          break;
1327
        case 'x':                /* decreqtparm */
1328
          if (a1 == 0 || a1 == 1)
1329
            Report("\033[%d;1;1;112;112;1;0x", a1 + 2, 0);
1330
          break;
1331
        case 'p':                /* obscure code from a 97801 term */
1332
          if (a1 == 6 || a1 == 7)
1333
            {
1334
              curr->w_curinv = 7 - a1;
1335
              LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
1336
            }
1337
          break;
1338
        case 'S':                /* code from a 97801 term / DEC vt400 */
1339
          ScrollRegion(a1 ? a1 : 1);
1340
          break;
1341
        case 'T':                /* code from a 97801 term / DEC vt400 */
1342
        case '^':                /* SD as per ISO 6429 */
1343
          ScrollRegion(a1 ? -a1 : -1);
1344
          break;
1345
        }
1346
      break;
1347
    case '?':
1348
      for (a2 = 0; a2 < curr->w_NumArgs; a2++)
1349
        {
1350
          a1 = curr->w_args[a2];
1351
          debug2("\\E[?%d%c\n",a1,c);
1352
          if (c != 'h' && c != 'l')
1353
            break;
1354
          i = (c == 'h');
1355
          switch (a1)
1356
            {
1357
            case 1:        /* CKM:  cursor key mode */
1358
              LCursorkeysMode(&curr->w_layer, curr->w_cursorkeys = i);
1359
#ifndef TIOCPKT
1360
              WNewAutoFlow(curr, !i);
1361
#endif /* !TIOCPKT */
1362
              break;
1363
            case 2:        /* ANM:  ansi/vt52 mode */
1364
              if (i)
1365
                {
1366
#ifdef FONT
1367
# ifdef ENCODINGS
1368
                  if (curr->w_encoding)
1369
                    break;
1370
# endif
1371
                  curr->w_charsets[0] = curr->w_charsets[1] =
1372
                    curr->w_charsets[2] = curr->w_charsets[3] =
1373
                    curr->w_FontL = curr->w_FontR = ASCII;
1374
                  curr->w_Charset = 0;
1375
                  curr->w_CharsetR = 2;
1376
                  curr->w_ss = 0;
1377
#endif
1378
                }
1379
              break;
1380
            case 3:        /* COLM: column mode */
1381
              i = (i ? Z0width : Z1width);
1382
              ClearScreen();
1383
              curr->w_x = 0;
1384
              curr->w_y = 0;
1385
              WChangeSize(curr, i, curr->w_height);
1386
              cols = curr->w_width;
1387
              rows = curr->w_height;
1388
              break;
1389
         /* case 4:           SCLM: scrolling mode */
1390
            case 5:        /* SCNM: screen mode */
1391
              if (i != curr->w_revvid)
1392
                WReverseVideo(curr, i);
1393
              curr->w_revvid = i;
1394
              break;
1395
            case 6:        /* OM:   origin mode */
1396
              if ((curr->w_origin = i) != 0)
1397
                {
1398
                  curr->w_y = curr->w_top;
1399
                  curr->w_x = 0;
1400
                }
1401
              else
1402
                curr->w_y = curr->w_x = 0;
1403
              LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1404
              break;
1405
            case 7:        /* AWM:  auto wrap mode */
1406
              curr->w_wrap = i;
1407
              break;
1408
         /* case 8:           ARM:  auto repeat mode */
1409
         /* case 9:           INLM: interlace mode */
1410
            case 9:        /* X10 mouse tracking */
1411
              curr->w_mouse = i ? 9 : 0;
1412
              LMouseMode(&curr->w_layer, curr->w_mouse);
1413
              break;
1414
         /* case 10:           EDM:  edit mode */
1415
         /* case 11:           LTM:  line transmit mode */
1416
         /* case 13:           SCFDM: space compression / field delimiting */
1417
         /* case 14:           TEM:  transmit execution mode */
1418
         /* case 16:           EKEM: edit key execution mode */
1419
         /* case 18:           PFF:  Printer term form feed */
1420
         /* case 19:           PEX:  Printer extend screen / scroll. reg */
1421
            case 25:        /* TCEM: text cursor enable mode */
1422
              curr->w_curinv = !i;
1423
              LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
1424
              break;
1425
         /* case 34:           RLM:  Right to left mode */
1426
         /* case 35:           HEBM: hebrew keyboard map */
1427
         /* case 36:           HEM:  hebrew encoding */
1428
         /* case 38:                 TeK Mode */
1429
         /* case 40:                 132 col enable */
1430
         /* case 42:           NRCM: 7bit NRC character mode */
1431
         /* case 44:                 margin bell enable */
1432
            case 47:    /*       xterm-like alternate screen */
1433
            case 1047:  /*       xterm-like alternate screen */
1434
            case 1049:  /*       xterm-like alternate screen */
1435
              if (use_altscreen)
1436
                {
1437
                  if (i)
1438
                    {
1439
                      if (!curr->w_alt.on)
1440
                        SaveCursor(&curr->w_alt.cursor);
1441
                      EnterAltScreen(curr);
1442
                    }
1443
                  else
1444
                    {
1445
                      LeaveAltScreen(curr);
1446
                      RestoreCursor(&curr->w_alt.cursor);
1447
                    }
1448
                  if (a1 == 47 && !i)
1449
                    curr->w_saved.on = 0;
1450
                  LRefreshAll(&curr->w_layer, 0);
1451
                  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1452
                }
1453
              break;
1454
            case 1048:
1455
              if (i)
1456
                SaveCursor(&curr->w_saved);
1457
              else
1458
                RestoreCursor(&curr->w_saved);
1459
              break;
1460
         /* case 66:           NKM:  Numeric keypad appl mode */
1461
         /* case 68:           KBUM: Keyboard usage mode (data process) */
1462
            case 1000:        /* VT200 mouse tracking */
1463
            case 1001:        /* VT200 highlight mouse */
1464
            case 1002:        /* button event mouse*/
1465
            case 1003:        /* any event mouse*/
1466
              curr->w_mouse = i ? a1 : 0;
1467
              LMouseMode(&curr->w_layer, curr->w_mouse);
1468
              break;
1469
            }
1470
        }
1471
      break;
1472
    case '>':
1473
      switch (c)
1474
        {
1475
        case 'c':        /* secondary DA */
1476
          if (a1 == 0)
1477
            Report("\033[>%d;%d;0c", 83, nversion);        /* 83 == 'S' */
1478
          break;
1479
        }
1480
      break;
1481
    }
1482
}
1483

    
1484

    
1485
static void
1486
StringStart(type)
1487
enum string_t type;
1488
{
1489
  curr->w_StringType = type;
1490
  curr->w_stringp = curr->w_string;
1491
  curr->w_state = ASTR;
1492
}
1493

    
1494
static void
1495
StringChar(c)
1496
int c;
1497
{
1498
  if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
1499
    curr->w_state = LIT;
1500
  else
1501
    *(curr->w_stringp)++ = c;
1502
}
1503

    
1504
/*
1505
 * Do string processing. Returns -1 if output should be suspended
1506
 * until status is gone.
1507
 */
1508
static int
1509
StringEnd()
1510
{
1511
  struct canvas *cv;
1512
  char *p;
1513
  int typ;
1514

    
1515
  curr->w_state = LIT;
1516
  *curr->w_stringp = '\0';
1517
  switch (curr->w_StringType)
1518
    {
1519
    case OSC:        /* special xterm compatibility hack */
1520
      if (curr->w_string[0] == ';' || (p = index(curr->w_string, ';')) == 0)
1521
        break;
1522
      typ = atoi(curr->w_string);
1523
      p++;
1524
#ifdef MULTIUSER
1525
      if (typ == 83)        /* 83 = 'S' */
1526
        {
1527
          /* special execute commands sequence */
1528
          char *args[MAXARGS];
1529
          int argl[MAXARGS];
1530
          struct acluser *windowuser;
1531

    
1532
          windowuser = *FindUserPtr(":window:");
1533
          if (windowuser && Parse(p, sizeof(curr->w_string) - (p - curr->w_string), args, argl))
1534
            {
1535
              for (display = displays; display; display = display->d_next)
1536
                if (D_forecv->c_layer->l_bottom == &curr->w_layer)
1537
                  break;        /* found it */
1538
              if (display == 0 && curr->w_layer.l_cvlist)
1539
                display = curr->w_layer.l_cvlist->c_display;
1540
              if (display == 0)
1541
                display = displays;
1542
              EffectiveAclUser = windowuser;
1543
              fore = curr;
1544
              flayer = fore->w_savelayer ? fore->w_savelayer : &fore->w_layer;
1545
              DoCommand(args, argl);
1546
              EffectiveAclUser = 0;
1547
              fore = 0;
1548
              flayer = 0;
1549
            }
1550
          break;
1551
        }
1552
#endif
1553
#ifdef RXVT_OSC
1554
      if (typ == 0 || typ == 1 || typ == 2 || typ == 20 || typ == 39 || typ == 49)
1555
        {
1556
          int typ2;
1557
          typ2 = typ / 10;
1558
          if (--typ2 < 0)
1559
            typ2 = 0;
1560
          if (strcmp(curr->w_xtermosc[typ2], p))
1561
            {
1562
              strncpy(curr->w_xtermosc[typ2], p, sizeof(curr->w_xtermosc[typ2]) - 1);
1563
              curr->w_xtermosc[typ2][sizeof(curr->w_xtermosc[typ2]) - 1] = 0;
1564

    
1565
              for (display = displays; display; display = display->d_next)
1566
                {
1567
                  if (!D_CXT)
1568
                    continue;
1569
                  if (D_forecv->c_layer->l_bottom == &curr->w_layer)
1570
                    SetXtermOSC(typ2, curr->w_xtermosc[typ2]);
1571
                  if ((typ2 == 2 || typ2 == 3) && D_xtermosc[typ2])
1572
                    Redisplay(0);
1573
                }
1574
            }
1575
        }
1576
      if (typ != 0 && typ != 2)
1577
        break;
1578
#else
1579
      if (typ < 0 || typ > 2)
1580
        break;
1581
#endif
1582
      
1583
      curr->w_stringp -= p - curr->w_string;
1584
      if (curr->w_stringp > curr->w_string)
1585
        bcopy(p, curr->w_string, curr->w_stringp - curr->w_string);
1586
      *curr->w_stringp = '\0';
1587
      /* FALLTHROUGH */
1588
    case APC:
1589
      if (curr->w_hstatus)
1590
        {
1591
          if (strcmp(curr->w_hstatus, curr->w_string) == 0)
1592
            break;        /* not changed */
1593
          free(curr->w_hstatus);
1594
          curr->w_hstatus = 0;
1595
        }
1596
      if (curr->w_string != curr->w_stringp)
1597
        curr->w_hstatus = SaveStr(curr->w_string);
1598
      WindowChanged(curr, 'h');
1599
      break;
1600
    case PM:
1601
    case GM:
1602
      for (display = displays; display; display = display->d_next)
1603
        {
1604
          for (cv = D_cvlist; cv; cv = cv->c_next)
1605
            if (cv->c_layer->l_bottom == &curr->w_layer)
1606
              break;
1607
          if (cv || curr->w_StringType == GM)
1608
            MakeStatus(curr->w_string);
1609
        }
1610
      return -1;
1611
    case DCS:
1612
      LAY_DISPLAYS(&curr->w_layer, AddStr(curr->w_string));
1613
      break;
1614
    case AKA:
1615
      if (curr->w_title == curr->w_akabuf && !*curr->w_string)
1616
        break;
1617
      ChangeAKA(curr, curr->w_string, strlen(curr->w_string));
1618
      if (!*curr->w_string)
1619
        curr->w_autoaka = curr->w_y + 1;
1620
      break;
1621
    default:
1622
      break;
1623
    }
1624
  return 0;
1625
}
1626

    
1627
static void
1628
PrintStart()
1629
{
1630
  curr->w_pdisplay = 0;
1631

    
1632
  /* find us a nice display to print on, fore prefered */
1633
  display = curr->w_lastdisp;
1634
  if (!(display && curr == D_fore && (printcmd || D_PO)))
1635
    for (display = displays; display; display = display->d_next)
1636
      if (curr == D_fore && (printcmd || D_PO))
1637
        break;
1638
  if (!display)
1639
    {
1640
      struct canvas *cv;
1641
      for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext)
1642
        {
1643
          display = cv->c_display;
1644
          if (printcmd || D_PO)
1645
            break;
1646
        }
1647
      if (!cv)
1648
        {
1649
          display = displays;
1650
          if (!display || display->d_next || !(printcmd || D_PO))
1651
            return;
1652
        }
1653
    }
1654
  curr->w_pdisplay = display;
1655
  curr->w_stringp = curr->w_string;
1656
  curr->w_state = PRIN;
1657
  if (printcmd && curr->w_pdisplay->d_printfd < 0)
1658
    curr->w_pdisplay->d_printfd = printpipe(curr, printcmd);
1659
}
1660

    
1661
static void
1662
PrintChar(c)
1663
int c;
1664
{
1665
  if (curr->w_stringp >= curr->w_string + MAXSTR - 1)
1666
    PrintFlush();
1667
  *(curr->w_stringp)++ = c;
1668
}
1669

    
1670
static void
1671
PrintFlush()
1672
{
1673
  display = curr->w_pdisplay;
1674
  if (display && printcmd)
1675
    {
1676
      char *bp = curr->w_string;
1677
      int len = curr->w_stringp - curr->w_string;
1678
      int r;
1679
      while (len && display->d_printfd >= 0)
1680
        {
1681
          r = write(display->d_printfd, bp, len);
1682
          if (r <= 0)
1683
            {
1684
              WMsg(curr, errno, "printing aborted");
1685
              close(display->d_printfd);
1686
              display->d_printfd = -1;
1687
              break;
1688
            }
1689
          bp += r;
1690
          len -= r;
1691
        }
1692
    }
1693
  else if (display && curr->w_stringp > curr->w_string)
1694
    {
1695
      AddCStr(D_PO);
1696
      AddStrn(curr->w_string, curr->w_stringp - curr->w_string);
1697
      AddCStr(D_PF);
1698
      Flush(3);
1699
    }
1700
  curr->w_stringp = curr->w_string;
1701
}
1702

    
1703

    
1704
void
1705
WNewAutoFlow(win, on)
1706
struct win *win;
1707
int on;
1708
{
1709
  debug1("WNewAutoFlow: %d\n", on);
1710
  if (win->w_flow & FLOW_AUTOFLAG)
1711
    win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on;
1712
  else
1713
    win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on;
1714
  LSetFlow(&win->w_layer, win->w_flow & FLOW_NOW);
1715
}
1716

    
1717

    
1718
#ifdef FONT
1719

    
1720
static void
1721
DesignateCharset(c, n)
1722
int c, n;
1723
{
1724
  curr->w_ss = 0;
1725
# ifdef ENCODINGS
1726
  if (c == ('@' & 037))                /* map JIS 6226 to 0208 */
1727
    c = KANJI;
1728
# endif
1729
  if (c == 'B')
1730
    c = ASCII;
1731
  if (curr->w_charsets[n] != c)
1732
    {
1733
      curr->w_charsets[n] = c;
1734
      if (curr->w_Charset == n)
1735
        {
1736
          curr->w_FontL = c;
1737
          curr->w_rend.font = curr->w_FontL;
1738
          LSetRendition(&curr->w_layer, &curr->w_rend);
1739
        }
1740
      if (curr->w_CharsetR == n)
1741
        curr->w_FontR = c;
1742
    }
1743
}
1744

    
1745
static void
1746
MapCharset(n)
1747
int n;
1748
{
1749
  curr->w_ss = 0;
1750
  if (curr->w_Charset != n)
1751
    {
1752
      curr->w_Charset = n;
1753
      curr->w_FontL = curr->w_charsets[n];
1754
      curr->w_rend.font = curr->w_FontL;
1755
      LSetRendition(&curr->w_layer, &curr->w_rend);
1756
    }
1757
}
1758

    
1759
static void
1760
MapCharsetR(n)
1761
int n;
1762
{
1763
  curr->w_ss = 0;
1764
  if (curr->w_CharsetR != n)
1765
    {
1766
      curr->w_CharsetR = n;
1767
      curr->w_FontR = curr->w_charsets[n];
1768
    }
1769
  curr->w_gr = 1;
1770
}
1771

    
1772
#endif /* FONT */
1773

    
1774
static void
1775
SaveCursor(cursor)
1776
struct cursor *cursor;
1777
{
1778
  cursor->on = 1;
1779
  cursor->x = curr->w_x;
1780
  cursor->y = curr->w_y;
1781
  cursor->Rend = curr->w_rend;
1782
#ifdef FONT
1783
  cursor->Charset = curr->w_Charset;
1784
  cursor->CharsetR = curr->w_CharsetR;
1785
  bcopy((char *) curr->w_charsets, (char *) cursor->Charsets,
1786
        4 * sizeof(int));
1787
#endif
1788
}
1789

    
1790
static void
1791
RestoreCursor(cursor)
1792
struct cursor *cursor;
1793
{
1794
  if (!cursor->on)
1795
    return;
1796
  LGotoPos(&curr->w_layer, cursor->x, cursor->y);
1797
  curr->w_x = cursor->x;
1798
  curr->w_y = cursor->y;
1799
  curr->w_rend = cursor->Rend;
1800
#ifdef FONT
1801
  bcopy((char *) cursor->Charsets, (char *) curr->w_charsets,
1802
        4 * sizeof(int));
1803
  curr->w_Charset = cursor->Charset;
1804
  curr->w_CharsetR = cursor->CharsetR;
1805
  curr->w_ss = 0;
1806
  curr->w_FontL = curr->w_charsets[curr->w_Charset];
1807
  curr->w_FontR = curr->w_charsets[curr->w_CharsetR];
1808
#endif
1809
  LSetRendition(&curr->w_layer, &curr->w_rend);
1810
}
1811

    
1812
static void
1813
BackSpace()
1814
{
1815
  if (curr->w_x > 0)
1816
    {
1817
      curr->w_x--;
1818
    }
1819
  else if (curr->w_wrap && curr->w_y > 0)
1820
    {
1821
      curr->w_x = cols - 1;
1822
      curr->w_y--;
1823
    }
1824
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1825
}
1826

    
1827
static void
1828
Return()
1829
{
1830
  if (curr->w_x == 0)
1831
    return;
1832
  curr->w_x = 0;
1833
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1834
}
1835

    
1836
static void
1837
LineFeed(out_mode)
1838
int out_mode;
1839
{
1840
  /* out_mode: 0=lf, 1=cr+lf */
1841
  if (out_mode)
1842
    curr->w_x = 0;
1843
  if (curr->w_y != curr->w_bot)                /* Don't scroll */
1844
    {
1845
      if (curr->w_y < rows-1)
1846
        curr->w_y++;
1847
      LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1848
      return;
1849
    }
1850
  if (curr->w_autoaka > 1)
1851
    curr->w_autoaka--;
1852
  MScrollV(curr, 1, curr->w_top, curr->w_bot, CURR_BCE);
1853
  LScrollV(&curr->w_layer, 1, curr->w_top, curr->w_bot, CURR_BCE);
1854
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1855
}
1856

    
1857
static void
1858
ReverseLineFeed()
1859
{
1860
  if (curr->w_y == curr->w_top)
1861
    {
1862
      MScrollV(curr, -1, curr->w_top, curr->w_bot, CURR_BCE);
1863
      LScrollV(&curr->w_layer, -1, curr->w_top, curr->w_bot, CURR_BCE);
1864
      LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1865
    }
1866
  else if (curr->w_y > 0)
1867
    CursorUp(1);
1868
}
1869

    
1870
static void
1871
InsertChar(n)
1872
int n;
1873
{
1874
  register int y = curr->w_y, x = curr->w_x;
1875

    
1876
  if (n <= 0)
1877
    return;
1878
  if (x == cols)
1879
    x--;
1880
  save_mline(&curr->w_mlines[y], cols);
1881
  MScrollH(curr, -n, y, x, curr->w_width - 1, CURR_BCE);
1882
  LScrollH(&curr->w_layer, -n, y, x, curr->w_width - 1, CURR_BCE, &mline_old);
1883
  LGotoPos(&curr->w_layer, x, y);
1884
}
1885

    
1886
static void
1887
DeleteChar(n)
1888
int n;
1889
{
1890
  register int y = curr->w_y, x = curr->w_x;
1891

    
1892
  if (x == cols)
1893
    x--;
1894
  save_mline(&curr->w_mlines[y], cols);
1895
  MScrollH(curr, n, y, x, curr->w_width - 1, CURR_BCE);
1896
  LScrollH(&curr->w_layer, n, y, x, curr->w_width - 1, CURR_BCE, &mline_old);
1897
  LGotoPos(&curr->w_layer, x, y);
1898
}
1899

    
1900
static void
1901
DeleteLine(n)
1902
int n;
1903
{
1904
  if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
1905
    return;
1906
  if (n > curr->w_bot - curr->w_y + 1)
1907
    n = curr->w_bot - curr->w_y + 1;
1908
  MScrollV(curr, n, curr->w_y, curr->w_bot, CURR_BCE);
1909
  LScrollV(&curr->w_layer, n, curr->w_y, curr->w_bot, CURR_BCE);
1910
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1911
}
1912

    
1913
static void
1914
InsertLine(n)
1915
int n;
1916
{
1917
  if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot)
1918
    return;
1919
  if (n > curr->w_bot - curr->w_y + 1)
1920
    n = curr->w_bot - curr->w_y + 1;
1921
  MScrollV(curr, -n, curr->w_y, curr->w_bot, CURR_BCE);
1922
  LScrollV(&curr->w_layer, -n, curr->w_y, curr->w_bot, CURR_BCE);
1923
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1924
}
1925

    
1926
static void
1927
ScrollRegion(n)
1928
int n;
1929
{
1930
  MScrollV(curr, n, curr->w_top, curr->w_bot, CURR_BCE);
1931
  LScrollV(&curr->w_layer, n, curr->w_top, curr->w_bot, CURR_BCE);
1932
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1933
}
1934

    
1935

    
1936
static void
1937
ForwardTab()
1938
{
1939
  register int x = curr->w_x;
1940

    
1941
  if (x == cols)
1942
    {
1943
      LineFeed(1);
1944
      x = 0;
1945
    }
1946
  if (curr->w_tabs[x] && x < cols - 1)
1947
    x++;
1948
  while (x < cols - 1 && !curr->w_tabs[x])
1949
    x++;
1950
  curr->w_x = x;
1951
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1952
}
1953

    
1954
static void
1955
BackwardTab()
1956
{
1957
  register int x = curr->w_x;
1958

    
1959
  if (curr->w_tabs[x] && x > 0)
1960
    x--;
1961
  while (x > 0 && !curr->w_tabs[x])
1962
    x--;
1963
  curr->w_x = x;
1964
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
1965
}
1966

    
1967
static void
1968
ClearScreen()
1969
{
1970
  LClearArea(&curr->w_layer, 0, 0, curr->w_width - 1, curr->w_height - 1, CURR_BCE, 1);
1971
#ifdef COPY_PASTE
1972
  MScrollV(curr, curr->w_height, 0, curr->w_height - 1, CURR_BCE);
1973
#else
1974
  MClearArea(curr, 0, 0, curr->w_width - 1, curr->w_height - 1, CURR_BCE);
1975
#endif
1976
}
1977

    
1978
static void
1979
ClearFromBOS()
1980
{
1981
  register int y = curr->w_y, x = curr->w_x;
1982

    
1983
  LClearArea(&curr->w_layer, 0, 0, x, y, CURR_BCE, 1);
1984
  MClearArea(curr, 0, 0, x, y, CURR_BCE);
1985
  RestorePosRendition();
1986
}
1987

    
1988
static void
1989
ClearToEOS()
1990
{
1991
  register int y = curr->w_y, x = curr->w_x;
1992

    
1993
  if (x == 0 && y == 0)
1994
    {
1995
      ClearScreen();
1996
      RestorePosRendition();
1997
      return;
1998
    }
1999
  LClearArea(&curr->w_layer, x, y, cols - 1, rows - 1, CURR_BCE, 1);
2000
  MClearArea(curr, x, y, cols - 1, rows - 1, CURR_BCE);
2001
  RestorePosRendition();
2002
}
2003

    
2004
static void
2005
ClearLineRegion(from, to)
2006
int from, to;
2007
{
2008
  register int y = curr->w_y;
2009
  LClearArea(&curr->w_layer, from, y, to, y, CURR_BCE, 1);
2010
  MClearArea(curr, from, y, to, y, CURR_BCE);
2011
  RestorePosRendition();
2012
}
2013

    
2014
static void
2015
CursorRight(n)
2016
register int n;
2017
{
2018
  register int x = curr->w_x;
2019

    
2020
  if (x == cols)
2021
    {
2022
      LineFeed(1);
2023
      x = 0;
2024
    }
2025
  if ((curr->w_x += n) >= cols)
2026
    curr->w_x = cols - 1;
2027
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2028
}
2029

    
2030
static void
2031
CursorUp(n)
2032
register int n;
2033
{
2034
  if (curr->w_y < curr->w_top)                /* if above scrolling rgn, */
2035
    {
2036
      if ((curr->w_y -= n) < 0)                /* ignore its limits      */
2037
         curr->w_y = 0;
2038
    }
2039
  else
2040
    if ((curr->w_y -= n) < curr->w_top)
2041
      curr->w_y = curr->w_top;
2042
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2043
}
2044

    
2045
static void
2046
CursorDown(n)
2047
register int n;
2048
{
2049
  if (curr->w_y > curr->w_bot)                /* if below scrolling rgn, */
2050
    {
2051
      if ((curr->w_y += n) > rows - 1)        /* ignore its limits      */
2052
        curr->w_y = rows - 1;
2053
    }
2054
  else
2055
    if ((curr->w_y += n) > curr->w_bot)
2056
      curr->w_y = curr->w_bot;
2057
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2058
}
2059

    
2060
static void
2061
CursorLeft(n)
2062
register int n;
2063
{
2064
  if ((curr->w_x -= n) < 0)
2065
    curr->w_x = 0;
2066
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2067
}
2068

    
2069
static void
2070
ASetMode(on)
2071
int on;
2072
{
2073
  register int i;
2074

    
2075
  for (i = 0; i < curr->w_NumArgs; ++i)
2076
    {
2077
      switch (curr->w_args[i])
2078
        {
2079
     /* case 2:                   KAM: Lock keyboard */
2080
        case 4:                /* IRM: Insert mode */
2081
          curr->w_insert = on;
2082
          LAY_DISPLAYS(&curr->w_layer, InsertMode(on));
2083
          break;
2084
     /* case 12:           SRM: Echo mode on */
2085
        case 20:        /* LNM: Linefeed mode */
2086
          curr->w_autolf = on;
2087
          break;
2088
        case 34:
2089
          curr->w_curvvis = !on;
2090
          LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis);
2091
          break;
2092
        default:
2093
          break;
2094
        }
2095
    }
2096
}
2097

    
2098
static char rendlist[] =
2099
{
2100
  ~((1 << NATTR) - 1), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0,
2101
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2102
  0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV
2103
};
2104

    
2105
static void
2106
SelectRendition()
2107
{
2108
#ifdef COLOR
2109
  register int j, i = 0, a = curr->w_rend.attr, c = curr->w_rend.color;
2110
# ifdef COLORS256
2111
  int cx = curr->w_rend.colorx;
2112
# endif
2113
#else
2114
  register int j, i = 0, a = curr->w_rend.attr;
2115
#endif
2116

    
2117
  do
2118
    {
2119
      j = curr->w_args[i];
2120
#ifdef COLOR
2121
      if ((j == 38 || j == 48) && i + 2 < curr->w_NumArgs && curr->w_args[i + 1] == 5)
2122
        {
2123
          int jj;
2124

    
2125
          i += 2;
2126
          jj = curr->w_args[i];
2127
          if (jj < 0 || jj > 255)
2128
            continue;
2129
# ifdef COLORS256
2130
          if (j == 38)
2131
            {
2132
              c = (c & 0xf0) | ((jj & 0x0f) ^ 9);
2133
              a |= A_BFG;
2134
              if (jj >= 8 && jj < 16)
2135
                c |= 0x08;
2136
              else
2137
                a ^= A_BFG;
2138
              a = (a & 0xbf) | (jj & 8 ? 0x40 : 0);
2139
              cx = (cx & 0xf0) | (jj >> 4 & 0x0f);
2140
            }
2141
          else
2142
            {
2143
              c = (c & 0x0f) | ((jj & 0x0f) ^ 9) << 4;
2144
              a |= A_BBG;
2145
              if (jj >= 8 && jj < 16)
2146
                c |= 0x80;
2147
              else
2148
                a ^= A_BBG;
2149
              cx = (cx & 0x0f) | (jj & 0xf0);
2150
            }
2151
          continue;
2152
# else
2153
          jj = color256to16(jj) + 30;
2154
          if (jj >= 38)
2155
            jj += 60 - 8;
2156
          j = j == 38 ? jj : jj + 10;
2157
# endif
2158
        }
2159
# ifdef COLORS16
2160
      if (j == 0 || (j >= 30 && j <= 39 && j != 38))
2161
        a &= 0xbf;
2162
      if (j == 0 || (j >= 40 && j <= 49 && j != 48))
2163
        a &= 0x7f;
2164
      if (j >= 90 && j <= 97)
2165
        a |= 0x40;
2166
      if (j >= 100 && j <= 107)
2167
        a |= 0x80;
2168
# endif
2169
      if (j >= 90 && j <= 97)
2170
        j -= 60;
2171
      if (j >= 100 && j <= 107)
2172
        j -= 60;
2173
      if (j >= 30 && j <= 39 && j != 38)
2174
        c = (c & 0xf0) | ((j - 30) ^ 9);
2175
      else if (j >= 40 && j <= 49 && j != 48)
2176
        c = (c & 0x0f) | (((j - 40) ^ 9) << 4);
2177
      if (j == 0)
2178
        c = 0;
2179
# ifdef COLORS256
2180
      if (j == 0 || (j >= 30 && j <= 39 && j != 38))
2181
        cx &= 0xf0;
2182
      if (j == 0 || (j >= 40 && j <= 49 && j != 48))
2183
        cx &= 0x0f;
2184
# endif
2185
#endif
2186
      if (j < 0 || j >= (int)(sizeof(rendlist)/sizeof(*rendlist)))
2187
        continue;
2188
      j = rendlist[j];
2189
      if (j & (1 << NATTR))
2190
        a &= j;
2191
      else
2192
        a |= j;
2193
    }
2194
  while (++i < curr->w_NumArgs);
2195
  curr->w_rend.attr = a;
2196
#ifdef COLOR
2197
  curr->w_rend.color = c;
2198
# ifdef COLORS256
2199
  curr->w_rend.colorx = cx;
2200
# endif
2201
#endif
2202
  LSetRendition(&curr->w_layer, &curr->w_rend);
2203
}
2204

    
2205
static void
2206
FillWithEs()
2207
{
2208
  register int i;
2209
  register unsigned char *p, *ep;
2210

    
2211
  LClearAll(&curr->w_layer, 1);
2212
  curr->w_y = curr->w_x = 0;
2213
  for (i = 0; i < rows; ++i)
2214
    {
2215
      clear_mline(&curr->w_mlines[i], 0, cols + 1);
2216
      p = curr->w_mlines[i].image;
2217
      ep = p + cols;
2218
      while (p < ep)
2219
        *p++ = 'E';
2220
    }
2221
  LRefreshAll(&curr->w_layer, 1);
2222
}
2223

    
2224

    
2225
/*
2226
 *  Ugly autoaka hack support:
2227
 *    ChangeAKA() sets a new aka
2228
 *    FindAKA() searches for an autoaka match
2229
 */
2230

    
2231
void
2232
ChangeAKA(p, s, l)
2233
struct win *p;
2234
char *s;
2235
int l;
2236
{
2237
  int i, c;
2238

    
2239
  for (i = 0; l > 0; l--)
2240
    {
2241
      if (p->w_akachange + i == p->w_akabuf + sizeof(p->w_akabuf) - 1)
2242
        break;
2243
      c = (unsigned char)*s++;
2244
      if (c == 0)
2245
        break;
2246
      if (c < 32 || c == 127 || (c >= 128 && c < 160 && p->w_c1))
2247
        continue;
2248
      p->w_akachange[i++] = c;
2249
    }
2250
  p->w_akachange[i] = 0;
2251
  p->w_title = p->w_akachange;
2252
  if (p->w_akachange != p->w_akabuf)
2253
    if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':')
2254
      p->w_title = p->w_akabuf + strlen(p->w_akabuf) + 1;
2255
  WindowChanged(p, 't');
2256
  WindowChanged((struct win *)0, 'w');
2257
  WindowChanged((struct win *)0, 'W');
2258
}
2259

    
2260
static void
2261
FindAKA()
2262
{
2263
  register unsigned char *cp, *line;
2264
  register struct win *wp = curr;
2265
  register int len = strlen(wp->w_akabuf);
2266
  int y;
2267

    
2268
  y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y;
2269
  cols = wp->w_width;
2270
 try_line:
2271
  cp = line = wp->w_mlines[y].image;
2272
  if (wp->w_autoaka > 0 &&  *wp->w_akabuf != '\0')
2273
    {
2274
      for (;;)
2275
        {
2276
          if (cp - line >= cols - len)
2277
            {
2278
              if (++y == wp->w_autoaka && y < rows)
2279
                goto try_line;
2280
              return;
2281
            }
2282
          if (strncmp((char *)cp, wp->w_akabuf, len) == 0)
2283
            break;
2284
          cp++;
2285
        }
2286
      cp += len;
2287
    }
2288
  for (len = cols - (cp - line); len && *cp == ' '; len--, cp++)
2289
    ;
2290
  if (len)
2291
    {
2292
      if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^'))
2293
        wp->w_autoaka = -1;
2294
      else
2295
        wp->w_autoaka = 0;
2296
      line = cp;
2297
      while (len && *cp != ' ')
2298
        {
2299
          if (*cp++ == '/')
2300
            line = cp;
2301
          len--;
2302
        }
2303
      ChangeAKA(wp, (char *)line, cp - line);
2304
    }
2305
  else
2306
    wp->w_autoaka = 0;
2307
}
2308

    
2309
static void
2310
RestorePosRendition()
2311
{
2312
  LGotoPos(&curr->w_layer, curr->w_x, curr->w_y);
2313
  LSetRendition(&curr->w_layer, &curr->w_rend);
2314
}
2315

    
2316
/* Send a terminal report as if it were typed. */ 
2317
static void
2318
Report(fmt, n1, n2)
2319
char *fmt;
2320
int n1, n2;
2321
{
2322
  register int len;
2323
  char rbuf[40];        /* enough room for all replys */
2324

    
2325
  sprintf(rbuf, fmt, n1, n2);
2326
  len = strlen(rbuf);
2327

    
2328
#ifdef PSEUDOS
2329
  if (W_UWP(curr))
2330
    {
2331
      if ((unsigned)(curr->w_pwin->p_inlen + len) <= sizeof(curr->w_pwin->p_inbuf))
2332
        {
2333
          bcopy(rbuf, curr->w_pwin->p_inbuf + curr->w_pwin->p_inlen, len);
2334
          curr->w_pwin->p_inlen += len;
2335
        }
2336
    }
2337
  else
2338
#endif
2339
    {
2340
      if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf))
2341
        {
2342
          bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len);
2343
          curr->w_inlen += len;
2344
        }
2345
    }
2346
}
2347

    
2348

    
2349

    
2350
/*
2351
 *====================================================================*
2352
 *====================================================================*
2353
 */
2354

    
2355
/**********************************************************************
2356
 *
2357
 * Memory subsystem.
2358
 *
2359
 */
2360

    
2361
static void
2362
MFixLine(p, y, mc)
2363
struct win *p;
2364
int y;
2365
struct mchar *mc;
2366
{
2367
  struct mline *ml = &p->w_mlines[y];
2368
  if (mc->attr && ml->attr == null)
2369
    {
2370
      if ((ml->attr = (unsigned char *)calloc(p->w_width + 1, 1)) == 0)
2371
        {
2372
          ml->attr = null;
2373
          mc->attr = p->w_rend.attr = 0;
2374
          WMsg(p, 0, "Warning: no space for attr - turned off");
2375
        }
2376
    }
2377
#ifdef FONT
2378
  if (mc->font && ml->font == null)
2379
    {
2380
      if ((ml->font = (unsigned char *)calloc(p->w_width + 1, 1)) == 0)
2381
        {
2382
          ml->font = null;
2383
          p->w_FontL = p->w_charsets[p->w_ss ? p->w_ss : p->w_Charset] = 0;
2384
          p->w_FontR = p->w_charsets[p->w_ss ? p->w_ss : p->w_CharsetR] = 0;
2385
          mc->font = mc->fontx = p->w_rend.font  = 0;
2386
          WMsg(p, 0, "Warning: no space for font - turned off");
2387
        }
2388
    }
2389
  if (mc->fontx && ml->fontx == null)
2390
    {
2391
      if ((ml->fontx = (unsigned char *)calloc(p->w_width + 1, 1)) == 0)
2392
        {
2393
          ml->fontx = null;
2394
          mc->fontx = 0;
2395
        }
2396
    }
2397
#endif
2398
#ifdef COLOR
2399
  if (mc->color && ml->color == null)
2400
    {
2401
      if ((ml->color = (unsigned char *)calloc(p->w_width + 1, 1)) == 0)
2402
        {
2403
          ml->color = null;
2404
          mc->color = p->w_rend.color = 0;
2405
          WMsg(p, 0, "Warning: no space for color - turned off");
2406
        }
2407
    }
2408
# ifdef COLORS256
2409
  if (mc->colorx && ml->colorx == null)
2410
    {
2411
      if ((ml->colorx = (unsigned char *)calloc(p->w_width + 1, 1)) == 0)
2412
        {
2413
          ml->colorx = null;
2414
          mc->colorx = p->w_rend.colorx = 0;
2415
          WMsg(p, 0, "Warning: no space for extended colors - turned off");
2416
        }
2417
    }
2418
# endif
2419
#endif
2420
}
2421

    
2422
/*****************************************************************/
2423

    
2424
#ifdef DW_CHARS
2425
# define MKillDwRight(p, ml, x)                                        \
2426
  if (dw_right(ml, x, p->w_encoding))                                \
2427
    {                                                                \
2428
      if (x > 0)                                                \
2429
        copy_mchar2mline(&mchar_blank, ml, x - 1);                \
2430
      copy_mchar2mline(&mchar_blank, ml, x);                        \
2431
    }
2432

    
2433
# define MKillDwLeft(p, ml, x)                                        \
2434
  if (dw_left(ml, x, p->w_encoding))                                \
2435
    {                                                                \
2436
      copy_mchar2mline(&mchar_blank, ml, x);                        \
2437
      copy_mchar2mline(&mchar_blank, ml, x + 1);                \
2438
    }
2439
#else
2440
# define MKillDwRight(p, ml, x) ;
2441
# define MKillDwLeft(p, ml, x) ;
2442
#endif
2443

    
2444
static void
2445
MScrollH(p, n, y, xs, xe, bce)
2446
struct win *p;
2447
int n, y, xs, xe, bce;
2448
{
2449
  struct mline *ml;
2450

    
2451
  if (n == 0)
2452
    return;
2453
  ml = &p->w_mlines[y];
2454
  MKillDwRight(p, ml, xs);
2455
  MKillDwLeft(p, ml, xe);
2456
  if (n > 0)
2457
    {
2458
      if (xe - xs + 1 > n)
2459
        {
2460
          MKillDwRight(p, ml, xs + n);
2461
          bcopy_mline(ml, xs + n, xs, xe + 1 - xs - n);
2462
        }
2463
      else
2464
        n = xe - xs + 1;
2465
      clear_mline(ml, xe + 1 - n, n);
2466
#ifdef COLOR
2467
      if (bce)
2468
        MBceLine(p, y, xe + 1 - n, n, bce);
2469
#endif
2470
    }
2471
  else
2472
    {
2473
      n = -n;
2474
      if (xe - xs + 1 > n)
2475
        {
2476
          MKillDwLeft(p, ml, xe - n);
2477
          bcopy_mline(ml, xs, xs + n, xe + 1 - xs - n);
2478
        }
2479
      else
2480
        n = xe - xs + 1;
2481
      clear_mline(ml, xs, n);
2482
#ifdef COLOR
2483
      if (bce)
2484
        MBceLine(p, y, xs, n, bce);
2485
#endif
2486
    }
2487
}
2488

    
2489
static void
2490
MScrollV(p, n, ys, ye, bce)
2491
struct win *p;
2492
int n, ys, ye, bce;
2493
{
2494
  int i, cnt1, cnt2;
2495
  struct mline tmp[256];
2496
  struct mline *ml;
2497

    
2498
  if (n == 0)
2499
    return;
2500
  if (n > 0)
2501
    {
2502
      if (n > 256)
2503
        {
2504
          MScrollV(p, n - 256, ys, ye, bce);
2505
          n = 256;
2506
        }
2507
      if (ye - ys + 1 < n)
2508
        n = ye - ys + 1;
2509
#ifdef COPY_PASTE
2510
      if (compacthist)
2511
        {
2512
          ye = MFindUsedLine(p, ye, ys);
2513
          if (ye - ys + 1 < n)
2514
            n = ye - ys + 1;
2515
          if (n <= 0)
2516
            return;
2517
        }
2518
#endif
2519
      /* Clear lines */
2520
      ml = p->w_mlines + ys;
2521
      for (i = ys; i < ys + n; i++, ml++)
2522
        {
2523
#ifdef COPY_PASTE
2524
          if (ys == p->w_top)
2525
            WAddLineToHist(p, ml);
2526
#endif
2527
          if (ml->attr != null)
2528
            free(ml->attr);
2529
          ml->attr = null;
2530
#ifdef FONT
2531
          if (ml->font != null)
2532
            free(ml->font);
2533
          ml->font = null;
2534
          if (ml->fontx != null)
2535
            free(ml->fontx);
2536
          ml->fontx = null;
2537
#endif
2538
#ifdef COLOR
2539
          if (ml->color != null)
2540
            free(ml->color);
2541
          ml->color = null;
2542
# ifdef COLORS256
2543
          if (ml->colorx != null)
2544
            free(ml->colorx);
2545
          ml->colorx = null;
2546
# endif
2547
#endif
2548
          bclear((char *)ml->image, p->w_width + 1);
2549
#ifdef COLOR
2550
          if (bce)
2551
            MBceLine(p, i, 0, p->w_width, bce);
2552
#endif
2553
        }
2554
      /* switch 'em over */
2555
      cnt1 = n * sizeof(struct mline);
2556
      cnt2 = (ye - ys + 1 - n) * sizeof(struct mline);
2557
      if (cnt1 && cnt2)
2558
        Scroll((char *)(p->w_mlines + ys), cnt1, cnt2, (char *)tmp);
2559
    }
2560
  else
2561
    {
2562
      if (n < -256)
2563
        {
2564
          MScrollV(p, n + 256, ys, ye, bce);
2565
          n = -256;
2566
        }
2567
      n = -n;
2568
      if (ye - ys + 1 < n)
2569
        n = ye - ys + 1;
2570

    
2571
      ml = p->w_mlines + ye;
2572
      /* Clear lines */
2573
      for (i = ye; i > ye - n; i--, ml--)
2574
        {
2575
          if (ml->attr != null)
2576
            free(ml->attr);
2577
          ml->attr = null;
2578
#ifdef FONT
2579
          if (ml->font != null)
2580
            free(ml->font);
2581
          ml->font = null;
2582
          if (ml->fontx != null)
2583
            free(ml->fontx);
2584
          ml->fontx = null;
2585
#endif
2586
#ifdef COLOR
2587
          if (ml->color != null)
2588
            free(ml->color);
2589
          ml->color = null;
2590
# ifdef COLORS256
2591
          if (ml->colorx != null)
2592
            free(ml->colorx);
2593
          ml->colorx = null;
2594
# endif
2595
#endif
2596
          bclear((char *)ml->image, p->w_width + 1);
2597
#ifdef COLOR
2598
          if (bce)
2599
            MBceLine(p, i, 0, p->w_width, bce);
2600
#endif
2601
        }
2602
      cnt1 = n * sizeof(struct mline);
2603
      cnt2 = (ye - ys + 1 - n) * sizeof(struct mline);
2604
      if (cnt1 && cnt2)
2605
        Scroll((char *)(p->w_mlines + ys), cnt2, cnt1, (char *)tmp);
2606
    }
2607
}
2608

    
2609
static void
2610
Scroll(cp, cnt1, cnt2, tmp)
2611
char *cp, *tmp;
2612
int cnt1, cnt2;
2613
{
2614
  if (!cnt1 || !cnt2)
2615
    return;
2616
  if (cnt1 <= cnt2)
2617
    {
2618
      bcopy(cp, tmp, cnt1);
2619
      bcopy(cp + cnt1, cp, cnt2);
2620
      bcopy(tmp, cp + cnt2, cnt1);
2621
    }
2622
  else
2623
    {
2624
      bcopy(cp + cnt1, tmp, cnt2);
2625
      bcopy(cp, cp + cnt2, cnt1);
2626
      bcopy(tmp, cp, cnt2);
2627
    }
2628
}
2629

    
2630
static void
2631
MClearArea(p, xs, ys, xe, ye, bce)
2632
struct win *p;
2633
int xs, ys, xe, ye, bce;
2634
{
2635
  int n, y;
2636
  int xxe;
2637
  struct mline *ml;
2638

    
2639
  /* Check for zero-height window */
2640
  if (ys < 0 || ye < ys)
2641
    return;
2642

    
2643
  /* check for magic margin condition */
2644
  if (xs >= p->w_width)
2645
    xs = p->w_width - 1;
2646
  if (xe >= p->w_width)
2647
    xe = p->w_width - 1;
2648

    
2649
  MKillDwRight(p, p->w_mlines + ys, xs);
2650
  MKillDwLeft(p, p->w_mlines + ye, xe);
2651

    
2652
  ml = p->w_mlines + ys;
2653
  for (y = ys; y <= ye; y++, ml++)
2654
    {
2655
      xxe = (y == ye) ? xe : p->w_width - 1;
2656
      n = xxe - xs + 1;
2657
      if (n > 0)
2658
        clear_mline(ml, xs, n);
2659
#ifdef COLOR
2660
      if (n > 0 && bce)
2661
        MBceLine(p, y, xs, xs + n - 1, bce);
2662
#endif
2663
      xs = 0;
2664
    }
2665
}
2666

    
2667
static void
2668
MInsChar(p, c, x, y)
2669
struct win *p;
2670
struct mchar *c;
2671
int x, y;
2672
{
2673
  int n;
2674
  struct mline *ml;
2675

    
2676
  ASSERT(x >= 0 && x < p->w_width);
2677
  MFixLine(p, y, c);
2678
  ml = p->w_mlines + y;
2679
  n = p->w_width - x - 1;
2680
  MKillDwRight(p, ml, x);
2681
  if (n > 0)
2682
    {
2683
      MKillDwRight(p, ml, p->w_width - 1);
2684
      bcopy_mline(ml, x, x + 1, n);
2685
    }
2686
  copy_mchar2mline(c, ml, x);
2687
#ifdef DW_CHARS
2688
  if (c->mbcs)
2689
    {
2690
      if (--n > 0)
2691
        {
2692
          MKillDwRight(p, ml, p->w_width - 1);
2693
          bcopy_mline(ml, x + 1, x + 2, n);
2694
        }
2695
      copy_mchar2mline(c, ml, x + 1);
2696
      ml->image[x + 1] = c->mbcs;
2697
# ifdef UTF8
2698
      if (p->w_encoding != UTF8)
2699
        ml->font[x + 1] |= 0x80;
2700
      else if (p->w_encoding == UTF8 && c->mbcs)
2701
        {
2702
          ml->font[x + 1] = c->mbcs;
2703
          ml->fontx[x + 1] = 0;
2704
        }
2705
# else
2706
      ml->font[x + 1] |= 0x80;
2707
# endif
2708
    }
2709
#endif
2710
}
2711

    
2712
static void
2713
MPutChar(p, c, x, y)
2714
struct win *p;
2715
struct mchar *c;
2716
int x, y;
2717
{
2718
  struct mline *ml;
2719

    
2720
  MFixLine(p, y, c);
2721
  ml = &p->w_mlines[y];
2722
  MKillDwRight(p, ml, x);
2723
  MKillDwLeft(p, ml, x);
2724
  copy_mchar2mline(c, ml, x);
2725
#ifdef DW_CHARS
2726
  if (c->mbcs)
2727
    {
2728
      MKillDwLeft(p, ml, x + 1);
2729
      copy_mchar2mline(c, ml, x + 1);
2730
      ml->image[x + 1] = c->mbcs;
2731
# ifdef UTF8
2732
      if (p->w_encoding != UTF8)
2733
        ml->font[x + 1] |= 0x80;
2734
      else if (p->w_encoding == UTF8 && c->mbcs)
2735
        {
2736
          ml->font[x + 1] = c->mbcs;
2737
          ml->fontx[x + 1] = 0;
2738
        }
2739
# else
2740
      ml->font[x + 1] |= 0x80;
2741
# endif
2742
    }
2743
#endif
2744
}
2745

    
2746

    
2747
static void
2748
MWrapChar(p, c, y, top, bot, ins)
2749
struct win *p;
2750
struct mchar *c;
2751
int y, top, bot;
2752
int ins;
2753
{
2754
  struct mline *ml;
2755
  int bce;
2756

    
2757
#ifdef COLOR
2758
  bce = rend_getbg(c);
2759
#else
2760
  bce = 0;
2761
#endif
2762
  MFixLine(p, y, c);
2763
  ml = &p->w_mlines[y];
2764
  copy_mchar2mline(&mchar_null, ml, p->w_width);
2765
  if (y == bot)
2766
    MScrollV(p, 1, top, bot, bce);
2767
  else if (y < p->w_height - 1)
2768
    y++;
2769
  if (ins)
2770
    MInsChar(p, c, 0, y);
2771
  else
2772
    MPutChar(p, c, 0, y);
2773
}
2774

    
2775
static void
2776
MPutStr(p, s, n, r, x, y)
2777
struct win *p;
2778
char *s;
2779
int n;
2780
struct mchar *r;
2781
int x, y;
2782
{
2783
  struct mline *ml;
2784
  int i;
2785
  unsigned char *b;
2786

    
2787
  if (n <= 0)
2788
    return;
2789
  MFixLine(p, y, r);
2790
  ml = &p->w_mlines[y];
2791
  MKillDwRight(p, ml, x);
2792
  MKillDwLeft(p, ml, x + n - 1);
2793
  bcopy(s, (char *)ml->image + x, n);
2794
  if (ml->attr != null)
2795
    {
2796
      b = ml->attr + x;
2797
      for (i = n; i-- > 0;)
2798
        *b++ = r->attr;
2799
    }
2800
#ifdef FONT
2801
  if (ml->font != null)
2802
    {
2803
      b = ml->font + x;
2804
      for (i = n; i-- > 0;)
2805
        *b++ = r->font;
2806
    }
2807
  if (ml->fontx != null)
2808
    {
2809
      b = ml->fontx + x;
2810
      for (i = n; i-- > 0;)
2811
        *b++ = r->fontx;
2812
    }
2813
#endif
2814
#ifdef COLOR
2815
  if (ml->color != null)
2816
    {
2817
      b = ml->color + x;
2818
      for (i = n; i-- > 0;)
2819
        *b++ = r->color;
2820
    }
2821
# ifdef COLORS256
2822
  if (ml->colorx != null)
2823
    {
2824
      b = ml->colorx + x;
2825
      for (i = n; i-- > 0;)
2826
        *b++ = r->colorx;
2827
    }
2828
# endif
2829
#endif
2830
}
2831

    
2832
#ifdef COLOR
2833
static void
2834
MBceLine(p, y, xs, xe, bce)
2835
struct win *p;
2836
int y, xs, xe, bce;
2837
{
2838
  struct mchar mc;
2839
  struct mline *ml;
2840
  int x;
2841

    
2842
  mc = mchar_null;
2843
  rend_setbg(&mc, bce);
2844
  MFixLine(p, y, &mc);
2845
  ml = p->w_mlines + y;
2846
# ifdef COLORS16
2847
  if (mc.attr)
2848
    for (x = xs; x <= xe; x++)
2849
      ml->attr[x] = mc.attr;
2850
# endif
2851
  if (mc.color)
2852
    for (x = xs; x <= xe; x++)
2853
      ml->color[x] = mc.color;
2854
# ifdef COLORS256
2855
  if (mc.colorx)
2856
    for (x = xs; x <= xe; x++)
2857
      ml->colorx[x] = mc.colorx;
2858
# endif
2859
}
2860
#endif
2861

    
2862

    
2863
#ifdef COPY_PASTE
2864
static void
2865
WAddLineToHist(wp, ml)
2866
struct win *wp;
2867
struct mline *ml;
2868
{
2869
  register unsigned char *q, *o;
2870
  struct mline *hml;
2871

    
2872
  if (wp->w_histheight == 0)
2873
    return;
2874
  hml = &wp->w_hlines[wp->w_histidx];
2875
  q = ml->image; ml->image = hml->image; hml->image = q;
2876

    
2877
  q = ml->attr; o = hml->attr; hml->attr = q; ml->attr = null;
2878
  if (o != null)
2879
    free(o);
2880
 
2881
#ifdef FONT
2882
  q = ml->font; o = hml->font; hml->font = q; ml->font = null;
2883
  if (o != null)
2884
    free(o);
2885
  q = ml->fontx; o = hml->fontx; hml->fontx = q; ml->fontx = null;
2886
  if (o != null)
2887
    free(o);
2888
#endif
2889

    
2890
#ifdef COLOR
2891
  q = ml->color; o = hml->color; hml->color = q; ml->color = null;
2892
  if (o != null)
2893
    free(o);
2894
# ifdef COLORS256
2895
  q = ml->colorx; o = hml->colorx; hml->colorx = q; ml->colorx = null;
2896
  if (o != null)
2897
    free(o);
2898
# endif
2899
#endif
2900

    
2901
  if (++wp->w_histidx >= wp->w_histheight)
2902
    wp->w_histidx = 0;
2903
}
2904
#endif
2905

    
2906
int
2907
MFindUsedLine(p, ye, ys)
2908
struct win *p;
2909
int ys, ye;
2910
{
2911
  int y;
2912
  struct mline *ml = p->w_mlines + ye;
2913

    
2914
  debug2("MFindUsedLine: %d %d\n", ye, ys);
2915
  for (y = ye; y >= ys; y--, ml--)
2916
    {
2917
      if (bcmp((char*)ml->image, blank, p->w_width))
2918
        break;
2919
      if (ml->attr != null && bcmp((char*)ml->attr, null, p->w_width))
2920
        break;
2921
#ifdef COLOR
2922
      if (ml->color != null && bcmp((char*)ml->color, null, p->w_width))
2923
        break;
2924
# ifdef COLORS256
2925
      if (ml->colorx != null && bcmp((char*)ml->colorx, null, p->w_width))
2926
        break;
2927
# endif
2928
#endif
2929
#ifdef UTF8
2930
      if (p->w_encoding == UTF8)
2931
        {
2932
          if (ml->font != null && bcmp((char*)ml->font, null, p->w_width))
2933
            break;
2934
          if (ml->fontx != null && bcmp((char*)ml->fontx, null, p->w_width))
2935
            break;
2936
        }
2937
#endif
2938
    }
2939
  debug1("MFindUsedLine returning  %d\n", y);
2940
  return y;
2941
}
2942

    
2943

    
2944
/*
2945
 *====================================================================*
2946
 *====================================================================*
2947
 */
2948

    
2949
/*
2950
 * Tricky: send only one bell even if the window is displayed
2951
 * more than once.
2952
 */
2953
void
2954
WBell(p, visual)
2955
struct win *p;
2956
int visual;
2957
{
2958
  struct canvas *cv;
2959
  if (displays == NULL)
2960
    p->w_bell = BELL_DONE;
2961
  for (display = displays; display; display = display->d_next)
2962
    {
2963
      for (cv = D_cvlist; cv; cv = cv->c_next)
2964
        if (cv->c_layer->l_bottom == &p->w_layer)
2965
          break;
2966
      if (cv && !visual)
2967
        AddCStr(D_BL);
2968
      else if (cv && D_VB)
2969
        AddCStr(D_VB);
2970
      else
2971
        p->w_bell = visual ? BELL_VISUAL : BELL_FOUND;
2972
    }
2973
}
2974

    
2975
/*
2976
 * This should be reverse video.
2977
 * Only change video if window is fore.
2978
 * Because it is used in some termcaps to emulate
2979
 * a visual bell we do this hack here.
2980
 * (screen uses \Eg as special vbell sequence)
2981
 */
2982
static void
2983
WReverseVideo(p, on)
2984
struct win *p;
2985
int on;
2986
{
2987
  struct canvas *cv;
2988
  for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext)
2989
    {
2990
      display = cv->c_display;
2991
      if (cv != D_forecv)
2992
        continue;
2993
      ReverseVideo(on);
2994
      if (!on && p->w_revvid && !D_CVR)
2995
        {
2996
          if (D_VB)
2997
            AddCStr(D_VB);
2998
          else
2999
            p->w_bell = BELL_VISUAL;
3000
        }
3001
    }
3002
}
3003

    
3004
void
3005
WMsg(p, err, str)
3006
struct win *p;
3007
int err;
3008
char *str;
3009
{
3010
  extern struct layer *flayer;
3011
  struct layer *oldflayer = flayer;
3012
  flayer = &p->w_layer;
3013
  LMsg(err, "%s", str);
3014
  flayer = oldflayer;
3015
}
3016

    
3017
void
3018
WChangeSize(p, w, h)
3019
struct win *p;
3020
int w, h;
3021
{
3022
  int wok = 0;
3023
  struct canvas *cv;
3024

    
3025
  if (p->w_layer.l_cvlist == 0)
3026
    {
3027
      /* window not displayed -> works always */
3028
      ChangeWindowSize(p, w, h, p->w_histheight);
3029
      return;
3030
    }
3031
  for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext)
3032
    {
3033
      display = cv->c_display;
3034
      if (p != D_fore)
3035
        continue;                /* change only fore */
3036
      if (D_CWS)
3037
        break;
3038
      if (D_CZ0 && (w == Z0width || w == Z1width))
3039
        wok = 1;
3040
    }
3041
  if (cv == 0 && wok == 0)        /* can't change any display */
3042
    return;
3043
  if (!D_CWS)
3044
    h = p->w_height;
3045
  ChangeWindowSize(p, w, h, p->w_histheight);
3046
  for (display = displays; display; display = display->d_next)
3047
    {
3048
      if (p == D_fore)
3049
        {
3050
          if (D_cvlist && D_cvlist->c_next == 0)
3051
            ResizeDisplay(w, h);
3052
          else
3053
            ResizeDisplay(w, D_height);
3054
          ResizeLayersToCanvases();        /* XXX Hmm ? */
3055
          continue;
3056
        }
3057
      for (cv = D_cvlist; cv; cv = cv->c_next)
3058
        if (cv->c_layer->l_bottom == &p->w_layer)
3059
          break;
3060
      if (cv)
3061
        Redisplay(0);
3062
    }
3063
}
3064

    
3065
static int
3066
WindowChangedCheck(s, what, hp)
3067
char *s;
3068
int what;
3069
int *hp;
3070
{
3071
  int h = 0;
3072
  int l;
3073
  while(*s)
3074
    {
3075
      if (*s++ != (hp ? '%' : '\005'))
3076
        continue;
3077
      l = 0;
3078
      s += (*s == '+');
3079
      s += (*s == '-');
3080
      while (*s >= '0' && *s <= '9')
3081
        s++;
3082
      if (*s == 'L')
3083
        {
3084
          s++;
3085
          l = 0x100;
3086
        }
3087
      if (*s == 'h')
3088
        h = 1;
3089
      if (*s == what || ((*s | l) == what) || what == 'd')
3090
        break;
3091
      if (*s)
3092
        s++;
3093
    }
3094
  if (hp)
3095
    *hp = h;
3096
  return *s ? 1 : 0;
3097
}
3098

    
3099
void
3100
WindowChanged(p, what)
3101
struct win *p;
3102
int what;
3103
{
3104
  int inwstr, inhstr, inlstr;
3105
  int inwstrh = 0, inhstrh = 0, inlstrh = 0;
3106
  int got, ox, oy;
3107
  struct display *olddisplay = display;
3108
  struct canvas *cv;
3109

    
3110
  inwstr = inhstr = 0;
3111

    
3112
  if (what == 'f')
3113
    {
3114
      WindowChanged((struct win *)0, 'w'|0x100);
3115
      WindowChanged((struct win *)0, 'W'|0x100);
3116
    }
3117

    
3118
  if (what)
3119
    {
3120
      inwstr = WindowChangedCheck(captionstring, what, &inwstrh);
3121
      inhstr = WindowChangedCheck(hstatusstring, what, &inhstrh);
3122
      inlstr = WindowChangedCheck(wliststr, what, &inlstrh);
3123
    }
3124
  else
3125
    {
3126
      inwstr = inhstr = 0;
3127
      inlstr = 1;
3128
    }
3129

    
3130
  if (p == 0)
3131
    {
3132
      for (display = displays; display; display = display->d_next)
3133
        {
3134
          ox = D_x;
3135
          oy = D_y;
3136
          for (cv = D_cvlist; cv; cv = cv->c_next)
3137
            {
3138
              if (inlstr || (inlstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3139
                WListUpdatecv(cv, (struct win *)0);
3140
              p = Layer2Window(cv->c_layer);
3141
              if (inwstr || (inwstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3142
                if (cv->c_ye + 1 < D_height)
3143
                  RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
3144
            }
3145
          p = D_fore;
3146
          if (inhstr || (inhstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0)))
3147
            RefreshHStatus();
3148
          if (ox != -1 && oy != -1)
3149
            GotoPos(ox, oy);
3150
        }
3151
      display = olddisplay;
3152
      return;
3153
    }
3154

    
3155
  if (p->w_hstatus && *p->w_hstatus && (inwstrh || inhstrh || inlstrh) && WindowChangedCheck(p->w_hstatus, what, (int *)0))
3156
    {
3157
      inwstr |= inwstrh;
3158
      inhstr |= inhstrh;
3159
      inlstr |= inlstrh;
3160
    }
3161
  if (!inwstr && !inhstr && !inlstr)
3162
    return;
3163
  for (display = displays; display; display = display->d_next)
3164
    {
3165
      got = 0;
3166
      ox = D_x;
3167
      oy = D_y;
3168
      for (cv = D_cvlist; cv; cv = cv->c_next)
3169
        {
3170
          if (inlstr)
3171
            WListUpdatecv(cv, p);
3172
          if (Layer2Window(cv->c_layer) != p)
3173
            continue;
3174
          got = 1;
3175
          if (inwstr && cv->c_ye + 1 < D_height)
3176
            RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0);
3177
        }
3178
      if (got && inhstr && p == D_fore)
3179
        RefreshHStatus();
3180
      if (ox != -1 && oy != -1)
3181
        GotoPos(ox, oy);
3182
    }
3183
  display = olddisplay;
3184
}
3185