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

« back to all changes in this revision

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