~dannf/ubuntu/saucy/screen/lp1213278-from-debian

« back to all changes in this revision

Viewing changes to ansi.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathaniel McCallum
  • Date: 2004-09-03 15:15:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040903151533-px02yqlrchs4fv2t
Tags: upstream-4.0.2
ImportĀ upstreamĀ versionĀ 4.0.2

Show diffs side-by-side

added added

removed removed

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